diff --git a/.gitignore b/.gitignore
index d01aefe..36cb465 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,6 @@
build
-ChibiOS_*
**/.*
gui/stmdspgui
**/*.o
**/*.so
perf*
-
diff --git a/ChibiOS_20.3.2/license.txt b/ChibiOS_20.3.2/license.txt
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/ChibiOS_20.3.2/license.txt
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/ChibiOS_20.3.2/os/common/abstractions/cmsis_os/cmsis_os.c b/ChibiOS_20.3.2/os/common/abstractions/cmsis_os/cmsis_os.c
new file mode 100644
index 0000000..af1c85f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/cmsis_os/cmsis_os.c
@@ -0,0 +1,557 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+/*
+ Concepts and parts of this file have been contributed by Andre R.
+ */
+
+/**
+ * @file cmsis_os.c
+ * @brief CMSIS RTOS module code.
+ *
+ * @addtogroup CMSIS_OS
+ * @{
+ */
+
+#include "cmsis_os.h"
+#include
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+int32_t cmsis_os_started;
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+static memory_pool_t sempool;
+static semaphore_t semaphores[CMSIS_CFG_NUM_SEMAPHORES];
+
+static memory_pool_t timpool;
+static struct os_timer_cb timers[CMSIS_CFG_NUM_TIMERS];
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Virtual timers common callback.
+ */
+static void timer_cb(void const *arg) {
+
+ osTimerId timer_id = (osTimerId)arg;
+ timer_id->ptimer(timer_id->argument);
+ if (timer_id->type == osTimerPeriodic) {
+ chSysLockFromISR();
+ chVTDoSetI(&timer_id->vt, TIME_MS2I(timer_id->millisec),
+ (vtfunc_t)timer_cb, timer_id);
+ chSysUnlockFromISR();
+ }
+}
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Kernel initialization.
+ */
+osStatus osKernelInitialize(void) {
+
+ cmsis_os_started = 0;
+
+ chSysInit();
+ chThdSetPriority(HIGHPRIO);
+
+ chPoolObjectInit(&sempool, sizeof(semaphore_t), chCoreAllocAlignedI);
+ chPoolLoadArray(&sempool, semaphores, CMSIS_CFG_NUM_SEMAPHORES);
+
+ chPoolObjectInit(&timpool, sizeof(struct os_timer_cb), chCoreAllocAlignedI);
+ chPoolLoadArray(&timpool, timers, CMSIS_CFG_NUM_TIMERS);
+
+ return osOK;
+}
+
+/**
+ * @brief Kernel start.
+ */
+osStatus osKernelStart(void) {
+
+ cmsis_os_started = 1;
+
+ chThdSetPriority(NORMALPRIO);
+
+ return osOK;
+}
+
+/**
+ * @brief Creates a thread.
+ */
+osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *argument) {
+ size_t size;
+
+ size = thread_def->stacksize == 0 ? CMSIS_CFG_DEFAULT_STACK :
+ thread_def->stacksize;
+ return (osThreadId)chThdCreateFromHeap(0,
+ THD_WORKING_AREA_SIZE(size),
+ thread_def->name,
+ NORMALPRIO+thread_def->tpriority,
+ (tfunc_t)thread_def->pthread,
+ argument);
+}
+
+/**
+ * @brief Thread termination.
+ * @note The thread is not really terminated but asked to terminate which
+ * is not compliant.
+ */
+osStatus osThreadTerminate(osThreadId thread_id) {
+
+ if (thread_id == osThreadGetId()) {
+ /* Note, no memory will be recovered unless a cleaner thread is
+ implemented using the registry.*/
+ chThdExit(0);
+ }
+ chThdTerminate(thread_id);
+ chThdWait((thread_t *)thread_id);
+
+ return osOK;
+}
+
+/**
+ * @brief Change thread priority.
+ * @note This can interfere with the priority inheritance mechanism.
+ */
+osStatus osThreadSetPriority(osThreadId thread_id, osPriority newprio) {
+ thread_t * tp = (thread_t *)thread_id;
+
+ chSysLock();
+
+ /* Changing priority.*/
+#if CH_CFG_USE_MUTEXES
+ if ((tp->prio == tp->realprio) || ((tprio_t)newprio > tp->prio))
+ tp->prio = (tprio_t)newprio;
+ tp->realprio = (tprio_t)newprio;
+#else
+ tp->prio = (tprio_t)newprio;
+#endif
+
+ /* The following states need priority queues reordering.*/
+ switch (tp->state) {
+#if CH_CFG_USE_MUTEXES | \
+ CH_CFG_USE_CONDVARS | \
+ (CH_CFG_USE_SEMAPHORES && CH_CFG_USE_SEMAPHORES_PRIORITY) | \
+ (CH_CFG_USE_MESSAGES && CH_CFG_USE_MESSAGES_PRIORITY)
+#if CH_CFG_USE_MUTEXES
+ case CH_STATE_WTMTX:
+#endif
+#if CH_CFG_USE_CONDVARS
+ case CH_STATE_WTCOND:
+#endif
+#if CH_CFG_USE_SEMAPHORES && CH_CFG_USE_SEMAPHORES_PRIORITY
+ case CH_STATE_WTSEM:
+#endif
+#if CH_CFG_USE_MESSAGES && CH_CFG_USE_MESSAGES_PRIORITY
+ case CH_STATE_SNDMSGQ:
+#endif
+ /* Re-enqueues tp with its new priority on the queue.*/
+ queue_prio_insert(queue_dequeue(tp),
+ (threads_queue_t *)tp->u.wtobjp);
+ break;
+#endif
+ case CH_STATE_READY:
+#if CH_DBG_ENABLE_ASSERTS
+ /* Prevents an assertion in chSchReadyI().*/
+ tp->state = CH_STATE_CURRENT;
+#endif
+ /* Re-enqueues tp with its new priority on the ready list.*/
+ chSchReadyI(queue_dequeue(tp));
+ break;
+ }
+
+ /* Rescheduling.*/
+ chSchRescheduleS();
+
+ chSysUnlock();
+
+ return osOK;
+}
+
+/**
+ * @brief Create a timer.
+ */
+osTimerId osTimerCreate(const osTimerDef_t *timer_def,
+ os_timer_type type,
+ void *argument) {
+
+ osTimerId timer = chPoolAlloc(&timpool);
+ chVTObjectInit(&timer->vt);
+ timer->ptimer = timer_def->ptimer;
+ timer->type = type;
+ timer->argument = argument;
+ return timer;
+}
+
+/**
+ * @brief Start a timer.
+ */
+osStatus osTimerStart(osTimerId timer_id, uint32_t millisec) {
+
+ if ((millisec == 0) || (millisec == osWaitForever))
+ return osErrorValue;
+
+ timer_id->millisec = millisec;
+ chVTSet(&timer_id->vt, TIME_MS2I(millisec), (vtfunc_t)timer_cb, timer_id);
+
+ return osOK;
+}
+
+/**
+ * @brief Stop a timer.
+ */
+osStatus osTimerStop(osTimerId timer_id) {
+
+ chVTReset(&timer_id->vt);
+
+ return osOK;
+}
+
+/**
+ * @brief Delete a timer.
+ */
+osStatus osTimerDelete(osTimerId timer_id) {
+
+ chVTReset(&timer_id->vt);
+ chPoolFree(&timpool, (void *)timer_id);
+
+ return osOK;
+}
+
+/**
+ * @brief Send signals.
+ */
+int32_t osSignalSet(osThreadId thread_id, int32_t signals) {
+ int32_t oldsignals;
+
+ syssts_t sts = chSysGetStatusAndLockX();
+ oldsignals = (int32_t)thread_id->epending;
+ chEvtSignalI((thread_t *)thread_id, (eventmask_t)signals);
+ chSysRestoreStatusX(sts);
+
+ return oldsignals;
+}
+
+/**
+ * @brief Clear signals.
+ */
+int32_t osSignalClear(osThreadId thread_id, int32_t signals) {
+ eventmask_t m;
+
+ chSysLock();
+
+ m = thread_id->epending & (eventmask_t)signals;
+ thread_id->epending &= ~(eventmask_t)signals;
+
+ chSysUnlock();
+
+ return (int32_t)m;
+}
+
+/**
+ * @brief Wait for signals.
+ */
+osEvent osSignalWait(int32_t signals, uint32_t millisec) {
+ osEvent event;
+ sysinterval_t timeout = (millisec == osWaitForever ?
+ TIME_INFINITE : (millisec == 0 ? TIME_IMMEDIATE :
+ TIME_MS2I(millisec)));
+
+ if (signals == 0)
+ event.value.signals = (uint32_t)chEvtWaitAnyTimeout(ALL_EVENTS, timeout);
+ else
+ event.value.signals = (uint32_t)chEvtWaitAllTimeout((eventmask_t)signals,
+ timeout);
+
+ /* Type of event.*/
+ if (event.value.signals == 0)
+ event.status = osEventTimeout;
+ else
+ event.status = osEventSignal;
+
+ return event;
+}
+
+/**
+ * @brief Create a semaphore.
+ * @note @p semaphore_def is not used.
+ * @note Can involve memory allocation.
+ */
+osSemaphoreId osSemaphoreCreate(const osSemaphoreDef_t *semaphore_def,
+ int32_t count) {
+
+ (void)semaphore_def;
+
+ semaphore_t *sem = chPoolAlloc(&sempool);
+ chSemObjectInit(sem, (cnt_t)count);
+ return sem;
+}
+
+/**
+ * @brief Wait on a semaphore.
+ */
+int32_t osSemaphoreWait(osSemaphoreId semaphore_id, uint32_t millisec) {
+ sysinterval_t timeout = (millisec == osWaitForever ?
+ TIME_INFINITE : (millisec == 0 ? TIME_IMMEDIATE :
+ TIME_MS2I(millisec)));
+
+ msg_t msg = chSemWaitTimeout((semaphore_t *)semaphore_id, timeout);
+ switch (msg) {
+ case MSG_OK:
+ return osOK;
+ case MSG_TIMEOUT:
+ return osErrorTimeoutResource;
+ }
+ return osErrorResource;
+}
+
+/**
+ * @brief Release a semaphore.
+ */
+osStatus osSemaphoreRelease(osSemaphoreId semaphore_id) {
+
+ syssts_t sts = chSysGetStatusAndLockX();
+ chSemSignalI((semaphore_t *)semaphore_id);
+ chSysRestoreStatusX(sts);
+
+ return osOK;
+}
+
+/**
+ * @brief Deletes a semaphore.
+ * @note After deletion there could be references in the system to a
+ * non-existent semaphore.
+ */
+osStatus osSemaphoreDelete(osSemaphoreId semaphore_id) {
+
+ chSemReset((semaphore_t *)semaphore_id, 0);
+ chPoolFree(&sempool, (void *)semaphore_id);
+
+ return osOK;
+}
+
+/**
+ * @brief Create a mutex.
+ * @note @p mutex_def is not used.
+ * @note Can involve memory allocation.
+ */
+osMutexId osMutexCreate(const osMutexDef_t *mutex_def) {
+
+ (void)mutex_def;
+
+ binary_semaphore_t *mtx = chPoolAlloc(&sempool);
+ chBSemObjectInit(mtx, false);
+ return mtx;
+}
+
+/**
+ * @brief Wait on a mutex.
+ */
+osStatus osMutexWait(osMutexId mutex_id, uint32_t millisec) {
+ sysinterval_t timeout = (millisec == osWaitForever ?
+ TIME_INFINITE : (millisec == 0 ? TIME_IMMEDIATE :
+ TIME_MS2I(millisec)));
+
+ msg_t msg = chBSemWaitTimeout((binary_semaphore_t *)mutex_id, timeout);
+ switch (msg) {
+ case MSG_OK:
+ return osOK;
+ case MSG_TIMEOUT:
+ return osErrorTimeoutResource;
+ }
+ return osErrorResource;
+}
+
+/**
+ * @brief Release a mutex.
+ */
+osStatus osMutexRelease(osMutexId mutex_id) {
+
+ syssts_t sts = chSysGetStatusAndLockX();
+ chBSemSignalI((binary_semaphore_t *)mutex_id);
+ chSysRestoreStatusX(sts);
+
+ return osOK;
+}
+
+/**
+ * @brief Deletes a mutex.
+ * @note After deletion there could be references in the system to a
+ * non-existent semaphore.
+ */
+osStatus osMutexDelete(osMutexId mutex_id) {
+
+ chSemReset((semaphore_t *)mutex_id, 0);
+ chPoolFree(&sempool, (void *)mutex_id);
+
+ return osOK;
+}
+
+/**
+ * @brief Create a memory pool.
+ * @note The pool is not really created because it is allocated statically,
+ * this function just re-initializes it.
+ */
+osPoolId osPoolCreate(const osPoolDef_t *pool_def) {
+
+ chPoolObjectInit(pool_def->pool, (size_t)pool_def->item_sz, NULL);
+ chPoolLoadArray(pool_def->pool, pool_def->items, (size_t)pool_def->pool_sz);
+
+ return (osPoolId)pool_def->pool;
+}
+
+/**
+ * @brief Allocate an object.
+ */
+void *osPoolAlloc(osPoolId pool_id) {
+ void *object;
+
+ syssts_t sts = chSysGetStatusAndLockX();
+ object = chPoolAllocI((memory_pool_t *)pool_id);
+ chSysRestoreStatusX(sts);
+
+ return object;
+}
+
+/**
+ * @brief Allocate an object clearing it.
+ */
+void *osPoolCAlloc(osPoolId pool_id) {
+ void *object;
+
+ object = chPoolAllocI((memory_pool_t *)pool_id);
+ memset(object, 0, pool_id->object_size);
+ return object;
+}
+
+/**
+ * @brief Free an object.
+ */
+osStatus osPoolFree(osPoolId pool_id, void *block) {
+
+ syssts_t sts = chSysGetStatusAndLockX();
+ chPoolFreeI((memory_pool_t *)pool_id, block);
+ chSysRestoreStatusX(sts);
+
+ return osOK;
+}
+
+/**
+ * @brief Create a message queue.
+ * @note The queue is not really created because it is allocated statically,
+ * this function just re-initializes it.
+ */
+osMessageQId osMessageCreate(const osMessageQDef_t *queue_def,
+ osThreadId thread_id) {
+
+ /* Ignoring this parameter for now.*/
+ (void)thread_id;
+
+ if (queue_def->item_sz > sizeof (msg_t))
+ return NULL;
+
+ chMBObjectInit(queue_def->mailbox,
+ queue_def->items,
+ (size_t)queue_def->queue_sz);
+
+ return (osMessageQId) queue_def->mailbox;
+}
+
+/**
+ * @brief Put a message in the queue.
+ */
+osStatus osMessagePut(osMessageQId queue_id,
+ uint32_t info,
+ uint32_t millisec) {
+ msg_t msg;
+ sysinterval_t timeout = (millisec == osWaitForever ?
+ TIME_INFINITE : (millisec == 0 ? TIME_IMMEDIATE :
+ TIME_MS2I(millisec)));
+
+ if (port_is_isr_context()) {
+
+ /* Waiting makes no sense in ISRs so any value except "immediate"
+ makes no sense.*/
+ if (millisec != 0)
+ return osErrorValue;
+
+ chSysLockFromISR();
+ msg = chMBPostI((mailbox_t *)queue_id, (msg_t)info);
+ chSysUnlockFromISR();
+ }
+ else
+ msg = chMBPostTimeout((mailbox_t *)queue_id, (msg_t)info, timeout);
+
+ return msg == MSG_OK ? osOK : osEventTimeout;
+}
+
+/**
+ * @brief Get a message from the queue.
+ */
+osEvent osMessageGet(osMessageQId queue_id,
+ uint32_t millisec) {
+ msg_t msg;
+ osEvent event;
+ sysinterval_t timeout = (millisec == osWaitForever ?
+ TIME_INFINITE : (millisec == 0 ? TIME_IMMEDIATE :
+ TIME_MS2I(millisec)));
+
+ event.def.message_id = queue_id;
+
+ if (port_is_isr_context()) {
+
+ /* Waiting makes no sense in ISRs so any value except "immediate"
+ makes no sense.*/
+ if (millisec != 0) {
+ event.status = osErrorValue;
+ return event;
+ }
+
+ chSysLockFromISR();
+ msg = chMBFetchI((mailbox_t *)queue_id, (msg_t*)&event.value.v);
+ chSysUnlockFromISR();
+ }
+ else {
+ msg = chMBFetchTimeout((mailbox_t *)queue_id, (msg_t*)&event.value.v, timeout);
+ }
+
+ /* Returned event type.*/
+ event.status = msg == MSG_OK ? osEventMessage : osEventTimeout;
+ return event;
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/abstractions/cmsis_os/cmsis_os.h b/ChibiOS_20.3.2/os/common/abstractions/cmsis_os/cmsis_os.h
new file mode 100644
index 0000000..1b41318
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/cmsis_os/cmsis_os.h
@@ -0,0 +1,522 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+/*
+ Concepts and parts of this file have been contributed by Andre R.
+ */
+
+/**
+ * @file cmsis_os.h
+ * @brief CMSIS RTOS module macros and structures.
+ *
+ * @addtogroup CMSIS_OS
+ * @{
+ */
+
+#ifndef CMSIS_OS_H
+#define CMSIS_OS_H
+
+#include "ch.h"
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @brief API version.
+ */
+#define osCMSIS 0x10002
+
+/**
+ * @brief Kernel version.
+ */
+#define osKernelSystemId "KERNEL V1.00"
+
+/**
+ * @brief ChibiOS/RT version encoded for CMSIS.
+ */
+#define osCMSIS_KERNEL ((CH_KERNEL_MAJOR << 16) | \
+ (CH_KERNEL_MINOR << 8) | \
+ (CH_KERNEL_PATCH))
+
+/**
+ * @name CMSIS Capabilities
+ * @{
+ */
+#define osFeature_MainThread 1
+#define osFeature_Pool 1
+#define osFeature_MailQ 0
+#define osFeature_MessageQ 1
+#define osFeature_Signals 24
+#define osFeature_Semaphore ((1U << 31) - 1U)
+#define osFeature_Wait 0
+#define osFeature_SysTick 1
+/**< @} */
+
+/**
+ * @brief Wait forever specification for timeouts.
+ */
+#define osWaitForever ((uint32_t)-1)
+
+/**
+ * @brief System tick frequency.
+ */
+#define osKernelSysTickFrequency CH_CFG_ST_FREQUENCY
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of pre-allocated static semaphores/mutexes.
+ */
+#if !defined(CMSIS_CFG_DEFAULT_STACK)
+#define CMSIS_CFG_DEFAULT_STACK 256
+#endif
+
+/**
+ * @brief Number of pre-allocated static semaphores/mutexes.
+ */
+#if !defined(CMSIS_CFG_NUM_SEMAPHORES)
+#define CMSIS_CFG_NUM_SEMAPHORES 4
+#endif
+
+/**
+ * @brief Number of pre-allocated static timers.
+ */
+#if !defined(CMSIS_CFG_NUM_TIMERS)
+#define CMSIS_CFG_NUM_TIMERS 4
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !CH_CFG_USE_MEMPOOLS
+#error "CMSIS RTOS requires CH_CFG_USE_MEMPOOLS"
+#endif
+
+#if !CH_CFG_USE_EVENTS
+#error "CMSIS RTOS requires CH_CFG_USE_EVENTS"
+#endif
+
+#if !CH_CFG_USE_EVENTS_TIMEOUT
+#error "CMSIS RTOS requires CH_CFG_USE_EVENTS_TIMEOUT"
+#endif
+
+#if !CH_CFG_USE_SEMAPHORES
+#error "CMSIS RTOS requires CH_CFG_USE_SEMAPHORES"
+#endif
+
+#if !CH_CFG_USE_DYNAMIC
+#error "CMSIS RTOS requires CH_CFG_USE_DYNAMIC"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of priority levels.
+ */
+typedef enum {
+ osPriorityIdle = -3,
+ osPriorityLow = -2,
+ osPriorityBelowNormal = -1,
+ osPriorityNormal = 0,
+ osPriorityAboveNormal = +1,
+ osPriorityHigh = +2,
+ osPriorityRealtime = +3,
+ osPriorityError = 0x84
+} osPriority;
+
+/**
+ * @brief Type of error codes.
+ */
+typedef enum {
+ osOK = 0,
+ osEventSignal = 0x08,
+ osEventMessage = 0x10,
+ osEventMail = 0x20,
+ osEventTimeout = 0x40,
+ osErrorParameter = 0x80,
+ osErrorResource = 0x81,
+ osErrorTimeoutResource = 0xC1,
+ osErrorISR = 0x82,
+ osErrorISRRecursive = 0x83,
+ osErrorPriority = 0x84,
+ osErrorNoMemory = 0x85,
+ osErrorValue = 0x86,
+ osErrorOS = 0xFF,
+ os_status_reserved = 0x7FFFFFFF
+} osStatus;
+
+/**
+ * @brief Type of a timer mode.
+ */
+typedef enum {
+ osTimerOnce = 0,
+ osTimerPeriodic = 1
+} os_timer_type;
+
+/**
+ * @brief Type of thread functions.
+ */
+typedef void (*os_pthread) (void const *argument);
+
+/**
+ * @brief Type of timer callback.
+ */
+typedef void (*os_ptimer) (void const *argument);
+
+/**
+ * @brief Type of pointer to thread control block.
+ */
+typedef thread_t *osThreadId;
+
+/**
+ * @brief Type of pointer to timer control block.
+ */
+typedef struct os_timer_cb {
+ virtual_timer_t vt;
+ os_timer_type type;
+ os_ptimer ptimer;
+ void *argument;
+ uint32_t millisec;
+} *osTimerId;
+
+/**
+ * @brief Type of pointer to mutex control block.
+ */
+typedef binary_semaphore_t *osMutexId;
+
+/**
+ * @brief Type of pointer to semaphore control block.
+ */
+typedef semaphore_t *osSemaphoreId;
+
+/**
+ * @brief Type of pointer to memory pool control block.
+ */
+typedef memory_pool_t *osPoolId;
+
+/**
+ * @brief Type of pointer to message queue control block.
+ */
+typedef struct mailbox *osMessageQId;
+
+/**
+ * @brief Type of an event.
+ */
+typedef struct {
+ osStatus status;
+ union {
+ uint32_t v;
+ void *p;
+ int32_t signals;
+ } value;
+ union {
+/* osMailQId mail_id;*/
+ osMessageQId message_id;
+ } def;
+} osEvent;
+
+/**
+ * @brief Type of a thread definition block.
+ */
+typedef struct os_thread_def {
+ os_pthread pthread;
+ osPriority tpriority;
+ uint32_t stacksize;
+ const char *name;
+} osThreadDef_t;
+
+/**
+ * @brief Type of a timer definition block.
+ */
+typedef struct os_timer_def {
+ os_ptimer ptimer;
+} osTimerDef_t;
+
+/**
+ * @brief Type of a mutex definition block.
+ */
+typedef struct os_mutex_def {
+ uint32_t dummy;
+} osMutexDef_t;
+
+/**
+ * @brief Type of a semaphore definition block.
+ */
+typedef struct os_semaphore_def {
+ uint32_t dummy;
+} osSemaphoreDef_t;
+
+/**
+ * @brief Type of a memory pool definition block.
+ */
+typedef struct os_pool_def {
+ uint32_t pool_sz;
+ uint32_t item_sz;
+ memory_pool_t *pool;
+ void *items;
+} osPoolDef_t;
+
+/**
+ * @brief Type of a message queue definition block.
+ */
+typedef struct os_messageQ_def {
+ uint32_t queue_sz;
+ uint32_t item_sz;
+ mailbox_t *mailbox;
+ void *items;
+} osMessageQDef_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Convert a microseconds value to a RTOS kernel system timer value.
+ */
+#define osKernelSysTickMicroSec(microsec) (((uint64_t)microsec * \
+ (osKernelSysTickFrequency)) / \
+ 1000000)
+
+/**
+ * @brief Create a Thread definition.
+ */
+#if defined(osObjectsExternal)
+#define osThreadDef(thd, priority, stacksz, name) \
+ extern const osThreadDef_t os_thread_def_##thd
+#else
+#define osThreadDef(thd, priority, stacksz, name) \
+const osThreadDef_t os_thread_def_##thd = { \
+ (thd), \
+ (priority), \
+ (stacksz), \
+ (name) \
+}
+#endif
+
+/**
+ * @brief Access a Thread definition.
+ */
+#define osThread(name) &os_thread_def_##name
+
+/**
+ * @brief Define a Timer object.
+ */
+#if defined(osObjectsExternal)
+#define osTimerDef(name, function) \
+ extern const osTimerDef_t os_timer_def_##name
+#else
+#define osTimerDef(name, function) \
+const osTimerDef_t os_timer_def_##name = { \
+ (function) \
+}
+#endif
+
+/**
+ * @brief Access a Timer definition.
+ */
+#define osTimer(name) &os_timer_def_##name
+
+/**
+ * @brief Define a Mutex.
+ */
+#if defined(osObjectsExternal)
+#define osMutexDef(name) extern const osMutexDef_t os_mutex_def_##name
+#else
+#define osMutexDef(name) const osMutexDef_t os_mutex_def_##name = {0}
+#endif
+
+/**
+ * @brief Access a Mutex definition.
+ */
+#define osMutex(name) &os_mutex_def_##name
+
+/**
+ * @brief Define a Semaphore.
+ */
+#if defined(osObjectsExternal)
+#define osSemaphoreDef(name) \
+ extern const osSemaphoreDef_t os_semaphore_def_##name
+#else // define the object
+#define osSemaphoreDef(name) \
+ const osSemaphoreDef_t os_semaphore_def_##name = {0}
+#endif
+
+/**
+ * @brief Access a Semaphore definition.
+ */
+#define osSemaphore(name) &os_semaphore_def_##name
+
+/**
+ * @brief Define a Memory Pool.
+ */
+#if defined(osObjectsExternal)
+#define osPoolDef(name, no, type) \
+ extern const osPoolDef_t os_pool_def_##name
+#else
+#define osPoolDef(name, no, type) \
+static const type os_pool_buf_##name[no]; \
+static memory_pool_t os_pool_obj_##name; \
+const osPoolDef_t os_pool_def_##name = { \
+ (no), \
+ sizeof (type), \
+ (void *)&os_pool_obj_##name, \
+ (void *)&os_pool_buf_##name[0] \
+}
+#endif
+
+/**
+ * @brief Access a Memory Pool definition.
+ */
+#define osPool(name) &os_pool_def_##name
+
+/**
+ * @brief Define a Message Queue.
+ */
+#if defined(osObjectsExternal)
+#define osMessageQDef(name, queue_sz, type) \
+ extern const osMessageQDef_t os_messageQ_def_##name
+#else
+#define osMessageQDef(name, queue_sz, type) \
+static const msg_t os_messageQ_buf_##name[queue_sz]; \
+static mailbox_t os_messageQ_obj_##name; \
+const osMessageQDef_t os_messageQ_def_##name = { \
+ (queue_sz), \
+ sizeof (type), \
+ (void *)&os_messageQ_obj_##name, \
+ (void *)&os_messageQ_buf_##name[0] \
+}
+#endif
+
+/**
+ * @brief Access a Message Queue definition.
+ */
+#define osMessageQ(name) &os_messageQ_def_##name
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+extern int32_t cmsis_os_started;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ osStatus osKernelInitialize(void);
+ osStatus osKernelStart(void);
+ osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *argument);
+ osStatus osThreadTerminate(osThreadId thread_id);
+ osStatus osThreadSetPriority(osThreadId thread_id, osPriority newprio);
+ /*osEvent osWait(uint32_t millisec);*/
+ osTimerId osTimerCreate(const osTimerDef_t *timer_def,
+ os_timer_type type,
+ void *argument);
+ osStatus osTimerStart(osTimerId timer_id, uint32_t millisec);
+ osStatus osTimerStop(osTimerId timer_id);
+ osStatus osTimerDelete(osTimerId timer_id);
+ int32_t osSignalSet(osThreadId thread_id, int32_t signals);
+ int32_t osSignalClear(osThreadId thread_id, int32_t signals);
+ osEvent osSignalWait(int32_t signals, uint32_t millisec);
+ osSemaphoreId osSemaphoreCreate(const osSemaphoreDef_t *semaphore_def,
+ int32_t count);
+ int32_t osSemaphoreWait(osSemaphoreId semaphore_id, uint32_t millisec);
+ osStatus osSemaphoreRelease(osSemaphoreId semaphore_id);
+ osStatus osSemaphoreDelete(osSemaphoreId semaphore_id);
+ osMutexId osMutexCreate(const osMutexDef_t *mutex_def);
+ osStatus osMutexWait(osMutexId mutex_id, uint32_t millisec);
+ osStatus osMutexRelease(osMutexId mutex_id);
+ osStatus osMutexDelete(osMutexId mutex_id);
+ osPoolId osPoolCreate(const osPoolDef_t *pool_def);
+ void *osPoolAlloc(osPoolId pool_id);
+ void *osPoolCAlloc(osPoolId pool_id);
+ osStatus osPoolFree(osPoolId pool_id, void *block);
+ osMessageQId osMessageCreate(const osMessageQDef_t *queue_def,
+ osThreadId thread_id);
+ osStatus osMessagePut(osMessageQId queue_id,
+ uint32_t info,
+ uint32_t millisec);
+ osEvent osMessageGet(osMessageQId queue_id,
+ uint32_t millisec);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief To be or not to be.
+ */
+static inline int32_t osKernelRunning(void) {
+
+ return cmsis_os_started;
+}
+
+/**
+ * @brief System ticks since start.
+ */
+static inline uint32_t osKernelSysTick(void) {
+
+ return (uint32_t)chVTGetSystemTimeX();
+}
+
+/**
+ * @brief Returns the current thread.
+ */
+static inline osThreadId osThreadGetId(void) {
+
+ return (osThreadId)chThdGetSelfX();
+}
+
+/**
+ * @brief Thread time slice yield.
+ */
+static inline osStatus osThreadYield(void) {
+
+ chThdYield();
+
+ return osOK;
+}
+
+/**
+ * @brief Returns priority of a thread.
+ */
+static inline osPriority osThreadGetPriority(osThreadId thread_id) {
+
+ return (osPriority)(NORMALPRIO - thread_id->prio);
+}
+
+/**
+ * @brief Thread delay in milliseconds.
+ */
+static inline osStatus osDelay(uint32_t millisec) {
+
+ chThdSleepMilliseconds(millisec);
+
+ return osOK;
+}
+
+#endif /* CMSIS_OS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/abstractions/cmsis_os/cmsis_os.mk b/ChibiOS_20.3.2/os/common/abstractions/cmsis_os/cmsis_os.mk
new file mode 100644
index 0000000..530a479
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/cmsis_os/cmsis_os.mk
@@ -0,0 +1,8 @@
+# List of the ChibiOS/RT CMSIS RTOS wrapper.
+CMSISRTOSSRC = ${CHIBIOS}/os/common/abstractions/cmsis_os/cmsis_os.c
+
+CMSISRTOSINC = ${CHIBIOS}/os/common/abstractions/cmsis_os
+
+# Shared variables
+ALLCSRC += $(CMSISRTOSSRC)
+ALLINC += $(CMSISRTOSINC)
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/cfe_osal.mk b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/cfe_osal.mk
new file mode 100644
index 0000000..cc129c2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/cfe_osal.mk
@@ -0,0 +1,8 @@
+# NASA CFE OSAL files.
+CFEOSALSRC = $(CHIBIOS)/os/common/abstractions/nasa_cfe/osal/src/osapi.c
+
+CFEOSALINC = $(CHIBIOS)/os/common/abstractions/nasa_cfe/osal/include
+
+# Shared variables
+ALLCSRC += $(CFEOSALSRC)
+ALLINC += $(CFEOSALINC)
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/common_types.h b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/common_types.h
new file mode 100644
index 0000000..100a9c7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/common_types.h
@@ -0,0 +1,267 @@
+/*---------------------------------------------------------------------------
+**
+** Filename:
+** $Id: common_types.h 1.9 2014/01/14 16:28:32GMT-05:00 acudmore Exp $
+**
+** Copyright (c) 2004-2006, United States government as represented by the
+** administrator of the National Aeronautics Space Administration.
+** All rights reserved. This software was created at NASAs Goddard
+** Space Flight Center pursuant to government contracts.
+**
+** This is governed by the NASA Open Source Agreement and may be used,
+** distributed and modified only pursuant to the terms of that agreement.
+**
+** Purpose:
+** Unit specification for common types.
+**
+** Design Notes:
+** Assumes make file has defined processor family
+**
+** References:
+** Flight Software Branch C Coding Standard Version 1.0a
+**
+**
+** Notes:
+**
+**
+** $Date: 2014/01/14 16:28:32GMT-05:00 $
+** $Revision: 1.9 $
+** $Log: common_types.h $
+** Revision 1.9 2014/01/14 16:28:32GMT-05:00 acudmore
+** Fixed typo in macro for x86-64
+** Revision 1.8 2013/08/09 13:58:04GMT-05:00 acudmore
+** Added int64 type, added support for ARM arch, added 64 bit x86 arch, added arch check for GCC arch macros, added check for proper data type sizes
+** Revision 1.7 2013/07/25 10:01:29GMT-05:00 acudmore
+** Added C++ support
+** Revision 1.6 2012/04/11 09:19:03GMT-05:00 acudmore
+** added OS_USED attribute
+** Revision 1.5 2010/02/18 16:43:29EST acudmore
+** Added SPARC processor section
+** Removed special characters from comments that cause problems with some tools.
+** Revision 1.4 2010/02/18 16:41:39EST acudmore
+** Added a block of defines for GCC specific pragmas and extensions.
+** Removed RTEMS boolean related ifdefs
+** moved OS_PACK into the GCC specific block
+** Revision 1.3 2010/02/01 12:31:17EST acudmore
+** Added uint64 type
+** Revision 1.2 2009/07/07 16:30:05EDT acudmore
+** Removed conditinal comp. around boolean for m68k.
+** This will need to be done for all RTEMS targets
+** Revision 1.1 2009/06/02 10:04:58EDT acudmore
+** Initial revision
+** Member added to project c:/MKSDATA/MKS-REPOSITORY/MKS-OSAL-REPOSITORY/src/os/inc/project.pj
+** Revision 1.1 2008/04/20 22:35:58EDT ruperera
+** Initial revision
+** Member added to project c:/MKSDATA/MKS-REPOSITORY/MKS-OSAL-REPOSITORY/src/inc/project.pj
+** Revision 1.1 2007/10/16 16:14:49EDT apcudmore
+** Initial revision
+** Member added to project d:/mksdata/MKS-OSAL-REPOSITORY/src/inc/project.pj
+** Revision 1.2 2006/06/08 14:28:32EDT David Kobe (dlkobe)
+** Added NASA Open Source Legal Statement
+** Revision 1.1 2005/06/09 09:57:51GMT-05:00 rperera
+** Initial revision
+** Member added to project d:/mksdata/MKS-CFE-REPOSITORY/cfe-core/inc/project.pj
+** Revision 1.6 2005/03/24 19:20:52 rmcgraw
+** Wrapped the boolean defintion for all three processors with #ifndef _USING_RTEMS_INCLUDES_
+**
+** Revision 1.5 2005/03/10 16:59:08 acudmore
+** removed boolean prefix to TRUE and FALSE defintion to avoid vxWorks conflict.
+**
+** Revision 1.4 2005/03/07 20:23:34 acudmore
+** removed duplicate boolean definition
+**
+** Revision 1.3 2005/03/07 20:05:17 acudmore
+** updated with __PPC__ macro that gnu compiler uses
+**
+** Revision 1.2 2005/03/04 16:02:44 acudmore
+** added coldfire architecture
+**
+** Revision 1.1 2005/03/04 15:58:45 acudmore
+** Added common_types.h
+**
+**
+**
+**-------------------------------------------------------------------------*/
+
+#ifndef _common_types_
+#define _common_types_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*
+** Includes
+*/
+
+/*
+** Macro Definitions
+*/
+
+/*
+** Condition = TRUE is ok, Condition = FALSE is error
+*/
+#define CompileTimeAssert(Condition, Message) typedef char Message[(Condition) ? 1 : -1]
+
+
+/*
+** Define compiler specific macros
+** The __extension__ compiler pragma is required
+** for the uint64 type using GCC with the ANSI C90 standard.
+** Other macros can go in here as needed, for example alignment
+** pragmas.
+*/
+#if defined (__GNUC__)
+ #define _EXTENSION_ __extension__
+ #define OS_PACK __attribute__ ((packed))
+ #define OS_ALIGN(n) __attribute__((aligned(n)))
+ #define OS_USED __attribute__((used))
+#else
+ #define _EXTENSION_
+ #define OS_PACK
+ #define OS_ALIGN(n)
+ #define OS_USED
+#endif
+
+#if defined(_ix86_) || defined (__i386__)
+/* ----------------------- Intel x86 processor family -------------------------*/
+ /* Little endian */
+ #undef _STRUCT_HIGH_BIT_FIRST_
+ #define _STRUCT_LOW_BIT_FIRST_
+
+ typedef unsigned char boolean;
+ typedef signed char int8;
+ typedef short int int16;
+ typedef long int int32;
+ _EXTENSION_ typedef long long int int64;
+ typedef unsigned char uint8;
+ typedef unsigned short int uint16;
+ typedef unsigned long int uint32;
+ _EXTENSION_ typedef unsigned long long int uint64;
+
+ typedef unsigned long int cpuaddr;
+
+#elif defined (_ix64_) || defined (__x86_64__)
+/* ----------------------- Intel/AMD x64 processor family -------------------------*/
+ /* Little endian */
+ #undef _STRUCT_HIGH_BIT_FIRST_
+ #define _STRUCT_LOW_BIT_FIRST_
+
+ typedef unsigned char boolean;
+ typedef signed char int8;
+ typedef short int int16;
+ typedef int int32;
+ typedef long int int64;
+ typedef unsigned char uint8;
+ typedef unsigned short int uint16;
+ typedef unsigned int uint32;
+ typedef unsigned long int uint64;
+
+ typedef unsigned long int cpuaddr;
+
+#elif defined(__PPC__) || defined (__ppc__)
+ /* ----------------------- Motorola Power PC family ---------------------------*/
+ /* The PPC can be programmed to be big or little endian, we assume native */
+ /* Big endian */
+ #define _STRUCT_HIGH_BIT_FIRST_
+ #undef _STRUCT_LOW_BIT_FIRST_
+
+ typedef unsigned char boolean;
+ typedef signed char int8;
+ typedef short int int16;
+ typedef long int int32;
+ _EXTENSION_ typedef long long int int64;
+ typedef unsigned char uint8;
+ typedef unsigned short int uint16;
+ typedef unsigned long int uint32;
+ _EXTENSION_ typedef unsigned long long int uint64;
+
+ typedef unsigned long int cpuaddr;
+
+#elif defined(_m68k_) || defined(__m68k__)
+ /* ----------------------- Motorola m68k/Coldfire family ---------------------------*/
+ /* Big endian */
+ #define _STRUCT_HIGH_BIT_FIRST_
+ #undef _STRUCT_LOW_BIT_FIRST_
+
+ typedef unsigned char boolean;
+ typedef signed char int8;
+ typedef short int int16;
+ typedef long int int32;
+ _EXTENSION_ typedef long long int int64;
+ typedef unsigned char uint8;
+ typedef unsigned short int uint16;
+ typedef unsigned long int uint32;
+ _EXTENSION_ typedef unsigned long long int uint64;
+
+ typedef unsigned long int cpuaddr;
+
+#elif defined (__ARM__) || defined(__arm__)
+/* ----------------------- ARM processor family -------------------------*/
+ /* Little endian */
+ #undef _STRUCT_HIGH_BIT_FIRST_
+ #define _STRUCT_LOW_BIT_FIRST_
+
+ typedef unsigned char boolean;
+ typedef signed char int8;
+ typedef short int int16;
+ typedef long int int32;
+ _EXTENSION_ typedef long long int int64;
+ typedef unsigned char uint8;
+ typedef unsigned short int uint16;
+ typedef unsigned long int uint32;
+ _EXTENSION_ typedef unsigned long long int uint64;
+
+ typedef unsigned long int cpuaddr;
+
+#elif defined(__SPARC__) || defined (_sparc_)
+ /* ----------------------- SPARC/LEON family ---------------------------*/
+ /* SPARC Big endian */
+ #define _STRUCT_HIGH_BIT_FIRST_
+ #undef _STRUCT_LOW_BIT_FIRST_
+
+ typedef unsigned char boolean;
+ typedef signed char int8;
+ typedef short int int16;
+ typedef long int int32;
+ _EXTENSION_ typedef long long int int64;
+ typedef unsigned char uint8;
+ typedef unsigned short int uint16;
+ typedef unsigned long int uint32;
+ _EXTENSION_ typedef unsigned long long int uint64;
+
+ typedef unsigned long int cpuaddr;
+
+#else /* not any of the above */
+ #error undefined processor
+#endif /* processor types */
+
+#ifndef NULL /* pointer to nothing */
+ #define NULL ((void *) 0)
+#endif
+
+#ifndef TRUE /* Boolean true */
+ #define TRUE (1)
+#endif
+
+#ifndef FALSE /* Boolean false */
+ #define FALSE (0)
+#endif
+
+/*
+** Check Sizes
+*/
+CompileTimeAssert(sizeof(uint8)==1, TypeUint8WrongSize);
+CompileTimeAssert(sizeof(uint16)==2, TypeUint16WrongSize);
+CompileTimeAssert(sizeof(uint32)==4, TypeUint32WrongSize);
+CompileTimeAssert(sizeof(uint64)==8, TypeUint64WrongSize);
+CompileTimeAssert(sizeof(int8)==1, Typeint8WrongSize);
+CompileTimeAssert(sizeof(int16)==2, Typeint16WrongSize);
+CompileTimeAssert(sizeof(int32)==4, Typeint32WrongSize);
+CompileTimeAssert(sizeof(int64)==8, Typeint64WrongSize);
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _common_types_ */
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-os-core.h b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-os-core.h
new file mode 100644
index 0000000..8c9b13a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-os-core.h
@@ -0,0 +1,274 @@
+/*
+** File: osapi-os-core.h
+**
+** Copyright (c) 2004-2006, United States government as represented by the
+** administrator of the National Aeronautics Space Administration.
+** All rights reserved. This software was created at NASAs Goddard
+** Space Flight Center pursuant to government contracts.
+**
+** This is governed by the NASA Open Source Agreement and may be used,
+** distributed and modified only pursuant to the terms of that agreement.
+**
+** Author: Ezra Yeheksli -Code 582/Raytheon
+**
+** Purpose: Contains functions prototype definitions and variables declarations
+** for the OS Abstraction Layer, Core OS module
+**
+** $Revision: 1.8 $
+**
+** $Date: 2013/07/25 10:02:00GMT-05:00 $
+**
+** $Log: osapi-os-core.h $
+** Revision 1.8 2013/07/25 10:02:00GMT-05:00 acudmore
+** removed circular include "osapi.h"
+** Revision 1.7 2012/04/11 09:30:48GMT-05:00 acudmore
+** Added OS_printf_enable and OS_printf_disable
+** Revision 1.6 2010/11/12 12:00:17EST acudmore
+** replaced copyright character with (c) and added open source notice where needed.
+** Revision 1.5 2010/11/10 15:33:14EST acudmore
+** Updated IntAttachHandler prototype
+** Revision 1.4 2010/03/08 12:06:28EST acudmore
+** added function pointer type to get rid of warnings
+** Revision 1.3 2010/02/01 12:37:15EST acudmore
+** added return code to OS API init
+** Revision 1.2 2009/08/04 10:49:09EDT acudmore
+**
+*/
+
+#ifndef _osapi_core_
+#define _osapi_core_
+
+#include /* for va_list */
+
+/*difines constants for OS_BinSemCreate for state of semaphore */
+#define OS_SEM_FULL 1
+#define OS_SEM_EMPTY 0
+
+/* #define for enabling floating point operations on a task*/
+#define OS_FP_ENABLED 1
+
+/* tables for the properties of objects */
+
+/*tasks */
+typedef struct
+{
+ char name [OS_MAX_API_NAME];
+ uint32 creator;
+ uint32 stack_size;
+ uint32 priority;
+ uint32 OStask_id;
+}OS_task_prop_t;
+
+/* queues */
+typedef struct
+{
+ char name [OS_MAX_API_NAME];
+ uint32 creator;
+}OS_queue_prop_t;
+
+/* Binary Semaphores */
+typedef struct
+{
+ char name [OS_MAX_API_NAME];
+ uint32 creator;
+ int32 value;
+}OS_bin_sem_prop_t;
+
+/* Counting Semaphores */
+typedef struct
+{
+ char name [OS_MAX_API_NAME];
+ uint32 creator;
+ int32 value;
+}OS_count_sem_prop_t;
+
+/* Mutexes */
+typedef struct
+{
+ char name [OS_MAX_API_NAME];
+ uint32 creator;
+}OS_mut_sem_prop_t;
+
+
+/* struct for OS_GetLocalTime() */
+
+typedef struct
+{
+ uint32 seconds;
+ uint32 microsecs;
+}OS_time_t;
+
+/* heap info */
+typedef struct
+{
+ uint32 free_bytes;
+ uint32 free_blocks;
+ uint32 largest_free_block;
+}OS_heap_prop_t;
+
+
+/* This typedef is for the OS_GetErrorName function, to ensure
+ * everyone is making an array of the same length */
+
+typedef char os_err_name_t[35];
+
+/*
+** These typedefs are for the task entry point
+*/
+typedef void osal_task;
+typedef osal_task ((*osal_task_entry)(void));
+
+/*
+** Exported Functions
+*/
+
+/*
+** Initialization of API
+*/
+int32 OS_API_Init (void);
+
+
+/*
+** Task API
+*/
+
+int32 OS_TaskCreate (uint32 *task_id, const char *task_name,
+ osal_task_entry function_pointer,
+ const uint32 *stack_pointer,
+ uint32 stack_size,
+ uint32 priority, uint32 flags);
+
+int32 OS_TaskDelete (uint32 task_id);
+void OS_TaskExit (void);
+int32 OS_TaskInstallDeleteHandler(void *function_pointer);
+int32 OS_TaskDelay (uint32 millisecond);
+int32 OS_TaskSetPriority (uint32 task_id, uint32 new_priority);
+int32 OS_TaskRegister (void);
+uint32 OS_TaskGetId (void);
+int32 OS_TaskGetIdByName (uint32 *task_id, const char *task_name);
+int32 OS_TaskGetInfo (uint32 task_id, OS_task_prop_t *task_prop);
+
+/*
+** Message Queue API
+*/
+
+/*
+** Queue Create now has the Queue ID returned to the caller.
+*/
+int32 OS_QueueCreate (uint32 *queue_id, const char *queue_name,
+ uint32 queue_depth, uint32 data_size, uint32 flags);
+int32 OS_QueueDelete (uint32 queue_id);
+int32 OS_QueueGet (uint32 queue_id, void *data, uint32 size,
+ uint32 *size_copied, int32 timeout);
+int32 OS_QueuePut (uint32 queue_id, void *data, uint32 size,
+ uint32 flags);
+int32 OS_QueueGetIdByName (uint32 *queue_id, const char *queue_name);
+int32 OS_QueueGetInfo (uint32 queue_id, OS_queue_prop_t *queue_prop);
+
+/*
+** Semaphore API
+*/
+
+int32 OS_BinSemCreate (uint32 *sem_id, const char *sem_name,
+ uint32 sem_initial_value, uint32 options);
+int32 OS_BinSemFlush (uint32 sem_id);
+int32 OS_BinSemGive (uint32 sem_id);
+int32 OS_BinSemTake (uint32 sem_id);
+int32 OS_BinSemTimedWait (uint32 sem_id, uint32 msecs);
+int32 OS_BinSemDelete (uint32 sem_id);
+int32 OS_BinSemGetIdByName (uint32 *sem_id, const char *sem_name);
+int32 OS_BinSemGetInfo (uint32 sem_id, OS_bin_sem_prop_t *bin_prop);
+
+int32 OS_CountSemCreate (uint32 *sem_id, const char *sem_name,
+ uint32 sem_initial_value, uint32 options);
+int32 OS_CountSemGive (uint32 sem_id);
+int32 OS_CountSemTake (uint32 sem_id);
+int32 OS_CountSemTimedWait (uint32 sem_id, uint32 msecs);
+int32 OS_CountSemDelete (uint32 sem_id);
+int32 OS_CountSemGetIdByName (uint32 *sem_id, const char *sem_name);
+int32 OS_CountSemGetInfo (uint32 sem_id, OS_count_sem_prop_t *count_prop);
+
+/*
+** Mutex API
+*/
+
+int32 OS_MutSemCreate (uint32 *sem_id, const char *sem_name, uint32 options);
+int32 OS_MutSemGive (uint32 sem_id);
+int32 OS_MutSemTake (uint32 sem_id);
+int32 OS_MutSemDelete (uint32 sem_id);
+int32 OS_MutSemGetIdByName (uint32 *sem_id, const char *sem_name);
+int32 OS_MutSemGetInfo (uint32 sem_id, OS_mut_sem_prop_t *mut_prop);
+
+/*
+** OS Time/Tick related API
+*/
+
+int32 OS_Milli2Ticks (uint32 milli_seconds);
+int32 OS_Tick2Micros (void);
+int32 OS_GetLocalTime (OS_time_t *time_struct);
+int32 OS_SetLocalTime (OS_time_t *time_struct);
+
+/*
+** Exception API
+*/
+
+int32 OS_ExcAttachHandler (uint32 ExceptionNumber,
+ void (*ExceptionHandler)(uint32, uint32 *,uint32),
+ int32 parameter);
+int32 OS_ExcEnable (int32 ExceptionNumber);
+int32 OS_ExcDisable (int32 ExceptionNumber);
+
+/*
+** Floating Point Unit API
+*/
+
+int32 OS_FPUExcAttachHandler (uint32 ExceptionNumber, void * ExceptionHandler ,
+ int32 parameter);
+int32 OS_FPUExcEnable (int32 ExceptionNumber);
+int32 OS_FPUExcDisable (int32 ExceptionNumber);
+int32 OS_FPUExcSetMask (uint32 mask);
+int32 OS_FPUExcGetMask (uint32 *mask);
+
+/*
+** Interrupt API
+*/
+int32 OS_IntAttachHandler (uint32 InterruptNumber, osal_task_entry InterruptHandler, int32 parameter);
+int32 OS_IntUnlock (int32 IntLevel);
+int32 OS_IntLock (void);
+
+int32 OS_IntEnable (int32 Level);
+int32 OS_IntDisable (int32 Level);
+
+int32 OS_IntSetMask (uint32 mask);
+int32 OS_IntGetMask (uint32 *mask);
+int32 OS_IntAck (int32 InterruptNumber);
+
+/*
+** Shared memory API
+*/
+int32 OS_ShMemInit (void);
+int32 OS_ShMemCreate (uint32 *Id, uint32 NBytes, char* SegName);
+int32 OS_ShMemSemTake (uint32 Id);
+int32 OS_ShMemSemGive (uint32 Id);
+int32 OS_ShMemAttach (uint32 * Address, uint32 Id);
+int32 OS_ShMemGetIdByName (uint32 *ShMemId, const char *SegName );
+
+/*
+** Heap API
+*/
+int32 OS_HeapGetInfo (OS_heap_prop_t *heap_prop);
+
+/*
+** API for useful debugging function
+*/
+int32 OS_GetErrorName (int32 error_num, os_err_name_t* err_name);
+
+
+/*
+** Abstraction for printf statements
+*/
+void OS_printf( const char *string, ...);
+void OS_printf_disable(void);
+void OS_printf_enable(void);
+
+#endif
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-os-custom.h b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-os-custom.h
new file mode 100644
index 0000000..c05c1ac
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-os-custom.h
@@ -0,0 +1,68 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file osapi-os-custom.h
+ * @brief Custom OSAPI extensions header.
+ *
+ * @addtogroup osapi-custom
+ * @{
+ */
+
+#ifndef OSAPI_CUSTOM_H
+#define OSAPI_CUSTOM_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void OS_set_printf(int (*printf)(const char *fmt, ...));
+ boolean OS_TaskDeleteCheck(void);
+ int32 OS_TaskWait(uint32 task_id);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* OSAPI_CUSTOM_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-os-filesys.h b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-os-filesys.h
new file mode 100644
index 0000000..c468003
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-os-filesys.h
@@ -0,0 +1,419 @@
+/*
+** File: osapi-os-filesys.h
+**
+** Copyright (c) 2004-2006, United States government as represented by the
+** administrator of the National Aeronautics Space Administration.
+** All rights reserved. This software was created at NASAs Goddard
+** Space Flight Center pursuant to government contracts.
+**
+** This is governed by the NASA Open Source Agreement and may be used,
+** distributed and modified only pursuant to the terms of that agreement.
+**
+** Author: Alan Cudmore Code 582
+**
+** Purpose: Contains functions prototype definitions and variables declarations
+** for the OS Abstraction Layer, File System module
+**
+** $Revision: 1.11 $
+**
+** $Date: 2013/12/16 12:57:41GMT-05:00 $
+**
+** $Log: osapi-os-filesys.h $
+** Revision 1.11 2013/12/16 12:57:41GMT-05:00 acudmore
+** Added macros for Volume name length and physical device name length
+** Revision 1.10 2013/07/29 12:05:48GMT-05:00 acudmore
+** Added define for device and volume name length
+** Revision 1.9 2013/07/25 14:31:21GMT-05:00 acudmore
+** Added prototype and datatype for OS_GetFsInfo
+** Revision 1.8 2011/12/05 12:04:21GMT-05:00 acudmore
+** Added OS_rewinddir API
+** Revision 1.7 2011/04/05 16:01:12EDT acudmore
+** Added OS_CloseFileByName and OS_CloseAllFiles
+** Revision 1.6 2010/11/15 11:04:38EST acudmore
+** Added OS_FileOpenCheck function.
+** Revision 1.5 2010/11/12 12:00:18EST acudmore
+** replaced copyright character with (c) and added open source notice where needed.
+** Revision 1.4 2010/02/01 12:28:57EST acudmore
+** Added OS_fsBytesFree API
+** Revision 1.3 2010/01/25 14:44:26EST acudmore
+** renamed "new" variable to avoid C++ reserved name conflict.
+** Revision 1.2 2009/07/14 15:16:05EDT acudmore
+** Added OS_TranslatePath to the API
+** Revision 1.1 2008/04/20 22:36:01EDT ruperera
+** Initial revision
+** Member added to project c:/MKSDATA/MKS-REPOSITORY/MKS-OSAL-REPOSITORY/src/os/inc/project.pj
+** Revision 1.1 2007/10/16 16:14:52EDT apcudmore
+** Initial revision
+** Member added to project d:/mksdata/MKS-OSAL-REPOSITORY/src/os/inc/project.pj
+** Revision 1.1 2007/08/24 13:43:24EDT apcudmore
+** Initial revision
+** Member added to project d:/mksdata/MKS-CFE-PROJECT/fsw/cfe-core/os/inc/project.pj
+** Revision 1.17 2007/06/07 09:59:14EDT njyanchik
+** I replaced the second OS_cp definition with OS_mv
+** Revision 1.16 2007/06/05 16:25:33EDT apcudmore
+** Increased Number of volume table entries from 10 to 14.
+** Added 2 extra EEPROM disk mappings to RAD750 Volume table + 2 spares
+** Added 4 spares to every other volume table.
+** Revision 1.15 2007/05/25 09:17:56EDT njyanchik
+** I added the rmfs call to the OSAL and updated the unit test stubs to match
+** Revision 1.14 2007/03/21 10:15:29EST njyanchik
+** I mistakenly put the wrong length in for the path in the OS_FDTableEntry structure, and I added
+** some code that will set and out of range file descriptors .IsValid flag to false in OS_FDGetInfo
+** Revision 1.13 2007/03/06 11:52:46EST njyanchik
+** This change goes with the previous CP, I forgot to include it
+** Revision 1.12 2007/02/28 14:57:45EST njyanchik
+** The updates for supporting copying and moving files are now supported
+** Revision 1.11 2007/02/27 15:22:11EST njyanchik
+** This CP has the initial import of the new file descripor table mechanism
+** Revision 1.10 2006/12/20 10:27:09EST njyanchik
+** This change package incorporates all the changes necessary for the addition
+** of a new API to get the real physical drive undernieth a mount point
+** Revision 1.9 2006/11/14 14:44:28GMT-05:00 njyanchik
+** Checks were added to the OS fs calls that look at the return of a function that
+** changes the name of paths from abstracted to local path names.
+** Revision 1.8 2006/10/30 16:12:19GMT-05:00 apcudmore
+** Updated Compact flash and RAM device names for vxWorks 6.2 changes.
+** Revision 1.7 2006/10/25 11:31:18EDT njyanchik
+** This CP incorporates changes to every bsp_voltab.c file. I increased the number
+** entries in the volume table to 10. I also changed the #define in the os_filesys.h
+** file for the number of entries to match.
+**
+** This update also includes adding the prototype for OS_initfs in os_filesys.h
+** Revision 1.6 2006/09/26 09:03:46GMT-05:00 njyanchik
+** Contains the initial import of the ES Shell commands interface
+** Revision 1.5 2006/07/25 15:37:52EDT njyanchik
+** It turns out the both the FS app and the OSAL were incorrect where file descriptors are
+** concerned. the file descriptors should be int32 across the board.
+** Revision 1.4 2006/01/20 11:56:18EST njyanchik
+** Fixed header file information to match api document
+** Revision 1.26 2005/07/12 17:13:56 nyanchik
+** Moved the Volume table to a bsp table in the arch directories.
+**
+** Revision 1.2 2005/07/11 16:26:57EDT apcudmore
+** OSAPI 2.0 integration
+** Revision 1.25 2005/07/06 16:11:17 nyanchik
+** *** empty log message ***
+**
+** Revision 1.24 2005/07/05 18:34:55 nyanchik
+** fixed issues found in code walkthrogh. Also removed the OS_Info* functions that are going in the BSP
+**
+** Revision 1.23 2005/06/17 19:46:34 nyanchik
+** added new file system style to linux and rtems.
+**
+** Revision 1.22 2005/06/15 16:43:48 nyanchik
+** added extra parenthesis for the .h file # defines
+**
+** Revision 1.21 2005/06/06 14:17:42 nyanchik
+** added headers to osapi-os-core.h and osapi-os-filesys.h
+**
+** Revision 1.20 2005/06/02 18:04:24 nyanchik
+** *** empty log message ***
+**
+** Revision 1.1 2005/03/15 18:26:32 nyanchik
+** *** empty log message ***
+**
+**
+** Date Written:
+**
+**
+*/
+
+#ifndef _osapi_filesys_
+#define _osapi_filesys_
+#include
+#include
+#include
+#include
+
+#define OS_READ_ONLY 0
+#define OS_WRITE_ONLY 1
+#define OS_READ_WRITE 2
+
+#define OS_SEEK_SET 0
+#define OS_SEEK_CUR 1
+#define OS_SEEK_END 2
+
+#define OS_CHK_ONLY 0
+#define OS_REPAIR 1
+
+#define FS_BASED 0
+#define RAM_DISK 1
+#define EEPROM_DISK 2
+#define ATA_DISK 3
+
+
+/*
+** Number of entries in the internal volume table
+*/
+#define NUM_TABLE_ENTRIES 14
+
+/*
+** Length of a Device and Volume name
+*/
+#define OS_FS_DEV_NAME_LEN 32
+#define OS_FS_PHYS_NAME_LEN 64
+#define OS_FS_VOL_NAME_LEN 32
+
+
+/*
+** Defines for File System Calls
+*/
+#define OS_FS_SUCCESS 0
+#define OS_FS_ERROR (-1)
+#define OS_FS_ERR_INVALID_POINTER (-2)
+#define OS_FS_ERR_PATH_TOO_LONG (-3)
+#define OS_FS_ERR_NAME_TOO_LONG (-4)
+#define OS_FS_UNIMPLEMENTED (-5)
+#define OS_FS_ERR_DRIVE_NOT_CREATED (-6)
+#define OS_FS_ERR_DEVICE_NOT_FREE (-7)
+#define OS_FS_ERR_PATH_INVALID (-8)
+#define OS_FS_ERR_NO_FREE_FDS (-9)
+#define OS_FS_ERR_INVALID_FD (-10)
+
+/* This typedef is for the OS_FS_GetErrorName function, to ensure
+ * everyone is making an array of the same length */
+
+typedef char os_fs_err_name_t[35];
+
+
+/*
+** Internal structure of the OS volume table for
+** mounted file systems and path translation
+*/
+typedef struct
+{
+ char DeviceName [OS_FS_DEV_NAME_LEN];
+ char PhysDevName [OS_FS_PHYS_NAME_LEN];
+ uint32 VolumeType;
+ uint8 VolatileFlag;
+ uint8 FreeFlag;
+ uint8 IsMounted;
+ char VolumeName [OS_FS_VOL_NAME_LEN];
+ char MountPoint [OS_MAX_PATH_LEN];
+ uint32 BlockSize;
+
+}OS_VolumeInfo_t;
+
+typedef struct
+{
+ int32 OSfd; /* The underlying OS's file descriptor */
+ char Path[OS_MAX_PATH_LEN]; /* The path of the file opened */
+ uint32 User; /* The task id of the task who opened the file*/
+ uint8 IsValid; /* Whether or not this entry is valid */
+}OS_FDTableEntry;
+
+typedef struct
+{
+ uint32 MaxFds; /* Total number of file descriptors */
+ uint32 FreeFds; /* Total number that are free */
+ uint32 MaxVolumes; /* Maximum number of volumes */
+ uint32 FreeVolumes; /* Total number of volumes free */
+} os_fsinfo_t;
+
+/* modified to posix calls, since all of the
+ * applicable OSes use the posix calls */
+
+typedef struct stat os_fstat_t;
+typedef DIR* os_dirp_t;
+typedef struct dirent os_dirent_t;
+/* still don't know what this should be*/
+typedef unsigned long int os_fshealth_t;
+
+/*
+ * Exported Functions
+*/
+
+
+/******************************************************************************
+** Standard File system API
+******************************************************************************/
+/*
+ * Initializes the File System functions
+*/
+
+int32 OS_FS_Init(void);
+
+/*
+ * Creates a file specified by path
+*/
+int32 OS_creat (const char *path, int32 access);
+
+/*
+ * Opend a file for reading/writing. Returns file descriptor
+*/
+int32 OS_open (const char *path, int32 access, uint32 mode);
+
+/*
+ * Closes an open file.
+*/
+int32 OS_close (int32 filedes);
+
+/*
+ * Reads nbytes bytes from file into buffer
+*/
+int32 OS_read (int32 filedes, void *buffer, uint32 nbytes);
+
+/*
+ * Write nybytes bytes of buffer into the file
+*/
+int32 OS_write (int32 filedes, void *buffer, uint32 nbytes);
+
+/*
+ * Changes the permissions of a file
+*/
+int32 OS_chmod (const char *path, uint32 access);
+
+/*
+ * Returns file status information in filestats
+*/
+int32 OS_stat (const char *path, os_fstat_t *filestats);
+
+/*
+ * Seeks to the specified position of an open file
+*/
+int32 OS_lseek (int32 filedes, int32 offset, uint32 whence);
+
+/*
+ * Removes a file from the file system
+*/
+int32 OS_remove (const char *path);
+
+/*
+ * Renames a file in the file system
+*/
+int32 OS_rename (const char *old_filename, const char *new_filename);
+
+/*
+ * copies a single file from src to dest
+*/
+int32 OS_cp (const char *src, const char *dest);
+
+/*
+ * moves a single file from src to dest
+*/
+int32 OS_mv (const char *src, const char *dest);
+
+/*
+ * Copies the info of an open file to the structure
+*/
+int32 OS_FDGetInfo (int32 filedes, OS_FDTableEntry *fd_prop);
+
+/*
+** Check to see if a file is open
+*/
+int32 OS_FileOpenCheck(char *Filename);
+
+/*
+** Close all open files
+*/
+int32 OS_CloseAllFiles(void);
+
+/*
+** Close a file by filename
+*/
+int32 OS_CloseFileByName(char *Filename);
+
+
+/******************************************************************************
+** Directory API
+******************************************************************************/
+
+/*
+ * Makes a new directory
+*/
+int32 OS_mkdir (const char *path, uint32 access);
+
+/*
+ * Opens a directory for searching
+*/
+os_dirp_t OS_opendir (const char *path);
+
+/*
+ * Closes an open directory
+*/
+int32 OS_closedir(os_dirp_t directory);
+
+/*
+ * Rewinds an open directory
+*/
+void OS_rewinddir(os_dirp_t directory);
+
+/*
+ * Reads the next object in the directory
+*/
+os_dirent_t * OS_readdir (os_dirp_t directory);
+
+/*
+ * Removes an empty directory from the file system.
+*/
+int32 OS_rmdir (const char *path);
+
+/******************************************************************************
+** System Level API
+******************************************************************************/
+/*
+ * Makes a file system
+*/
+int32 OS_mkfs (char *address,char *devname, char *volname,
+ uint32 blocksize, uint32 numblocks);
+/*
+ * Mounts a file system
+*/
+int32 OS_mount (const char *devname, char *mountpoint);
+
+/*
+ * Initializes an existing file system
+*/
+int32 OS_initfs (char *address,char *devname, char *volname,
+ uint32 blocksize, uint32 numblocks);
+
+/*
+ * removes a file system
+*/
+int32 OS_rmfs (char *devname);
+
+/*
+ * Unmounts a mounted file system
+*/
+int32 OS_unmount (const char *mountpoint);
+
+/*
+ * Returns the number of free blocks in a file system
+*/
+int32 OS_fsBlocksFree (const char *name);
+
+/*
+** Returns the number of free bytes in a file system
+** Note the 64 bit data type to support filesystems that
+** are greater than 4 Gigabytes
+*/
+int32 OS_fsBytesFree (const char *name, uint64 *bytes_free);
+
+/*
+ * Checks the health of a file system and repairs it if neccesary
+*/
+os_fshealth_t OS_chkfs (const char *name, boolean repair);
+
+/*
+ * Returns in the parameter the physical drive underneith the mount point
+*/
+int32 OS_FS_GetPhysDriveName (char * PhysDriveName, char * MountPoint);
+
+/*
+** Translates a OSAL Virtual file system path to a host Local path
+*/
+int32 OS_TranslatePath ( const char *VirtualPath, char *LocalPath);
+
+/*
+** Returns information about the file system in an os_fsinfo_t
+*/
+int32 OS_GetFsInfo(os_fsinfo_t *filesys_info);
+
+/******************************************************************************
+** Shell API
+******************************************************************************/
+
+/* executes the shell command passed into is and writes the output of that
+ * command to the file specified by the given OSAPI file descriptor */
+int32 OS_ShellOutputToFile(char* Cmd, int32 OS_fd);
+#endif
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-os-loader.h b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-os-loader.h
new file mode 100644
index 0000000..4f0b21b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-os-loader.h
@@ -0,0 +1,91 @@
+/*
+** File: osapi-os-loader.h
+**
+** Copyright (c) 2004-2006, United States government as represented by the
+** administrator of the National Aeronautics Space Administration.
+** All rights reserved. This software was created at NASAs Goddard
+** Space Flight Center pursuant to government contracts.
+**
+** This is governed by the NASA Open Source Agreement and may be used,
+** distributed and modified only pursuant to the terms of that agreement.
+**
+** Author: Alan Cudmore - Code 582
+**
+** Purpose: Contains functions prototype definitions and variables declarations
+** for the OS Abstraction Layer, Object file loader API
+**
+** $Revision: 1.5 $
+**
+** $Date: 2013/07/25 10:02:08GMT-05:00 $
+**
+** $Log: osapi-os-loader.h $
+** Revision 1.5 2013/07/25 10:02:08GMT-05:00 acudmore
+** removed circular include "osapi.h"
+** Revision 1.4 2010/11/12 12:00:18GMT-05:00 acudmore
+** replaced copyright character with (c) and added open source notice where needed.
+** Revision 1.3 2010/02/01 12:38:06EST acudmore
+** added return code to OS_ModuleTableInit
+** Revision 1.2 2008/06/20 15:13:43EDT apcudmore
+** Checked in new Module loader/symbol table functionality
+** Revision 1.1 2008/04/20 22:36:02EDT ruperera
+** Initial revision
+** Member added to project c:/MKSDATA/MKS-REPOSITORY/MKS-OSAL-REPOSITORY/src/os/inc/project.pj
+** Revision 1.1 2008/02/07 11:08:24EST apcudmore
+** Initial revision
+** Member added to project d:/mksdata/MKS-OSAL-REPOSITORY/src/os/inc/project.pj
+**
+**
+*/
+
+#ifndef _osapi_loader_
+#define _osapi_loader_
+
+/*
+** Defines
+*/
+
+
+/*
+** Typedefs
+*/
+
+typedef struct
+{
+ uint32 valid;
+ uint32 code_address;
+ uint32 code_size;
+ uint32 data_address;
+ uint32 data_size;
+ uint32 bss_address;
+ uint32 bss_size;
+ uint32 flags;
+} OS_module_address_t;
+
+typedef struct
+{
+ int free;
+ uint32 entry_point;
+ uint32 host_module_id;
+ char filename[OS_MAX_PATH_LEN];
+ char name[OS_MAX_API_NAME];
+ OS_module_address_t addr;
+
+} OS_module_record_t;
+
+/*
+** Loader API
+*/
+int32 OS_ModuleTableInit ( void );
+
+int32 OS_SymbolLookup (uint32 *symbol_address, char *symbol_name );
+
+int32 OS_SymbolTableDump ( char *filename, uint32 size_limit );
+
+int32 OS_ModuleLoad ( uint32 *module_id, char *module_name, char *filename );
+
+int32 OS_ModuleUnload ( uint32 module_id );
+
+int32 OS_ModuleInfo ( uint32 module_id, OS_module_record_t *module_info );
+
+
+#endif
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-os-net.h b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-os-net.h
new file mode 100644
index 0000000..b8cc67d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-os-net.h
@@ -0,0 +1,61 @@
+/*
+** File: osapi-os-net.h
+**
+** Copyright (c) 2004-2006, United States government as represented by the
+** administrator of the National Aeronautics Space Administration.
+** All rights reserved. This software was created at NASAs Goddard
+** Space Flight Center pursuant to government contracts.
+**
+** This is governed by the NASA Open Source Agreement and may be used,
+** distributed and modified only pursuant to the terms of that agreement.
+**
+** Author: Alan Cudmore Code 582
+**
+** Purpose: Contains functions prototype definitions and variables declarations
+** for the OS Abstraction Layer, Network Module
+**
+** $Revision: 1.2 $
+**
+** $Date: 2010/11/12 12:00:19GMT-05:00 $
+**
+** $Log: osapi-os-net.h $
+** Revision 1.2 2010/11/12 12:00:19GMT-05:00 acudmore
+** replaced copyright character with (c) and added open source notice where needed.
+** Revision 1.1 2008/04/20 22:36:02EDT ruperera
+** Initial revision
+** Member added to project c:/MKSDATA/MKS-REPOSITORY/MKS-OSAL-REPOSITORY/src/os/inc/project.pj
+** Revision 1.1 2007/10/16 16:14:52EDT apcudmore
+** Initial revision
+** Member added to project d:/mksdata/MKS-OSAL-REPOSITORY/src/os/inc/project.pj
+** Revision 1.1 2007/08/24 13:43:25EDT apcudmore
+** Initial revision
+** Member added to project d:/mksdata/MKS-CFE-PROJECT/fsw/cfe-core/os/inc/project.pj
+** Revision 1.3 2006/01/20 11:56:18EST njyanchik
+** Fixed header file information to match api document
+** Revision 1.4 2005/06/07 16:49:31 nyanchik
+** changed returns code for osapi.c to all int32 from uint32
+**
+** Revision 1.3 2005/03/22 19:04:54 acudmore
+** fixed uint type
+**
+** Revision 1.2 2005/03/22 18:59:33 acudmore
+** updated prototype
+**
+** Revision 1.1 2005/03/22 18:58:51 acudmore
+** added osapi network interface
+**
+** Revision 1.1 2005/03/15 18:26:32 nyanchik
+** *** empty log message ***
+**
+**
+** Date Written:
+**
+**
+*/
+#ifndef _osapi_network_
+#define _osapi_network_
+
+int32 OS_NetworkGetID (void);
+int32 OS_NetworkGetHostName (char *host_name, uint32 name_len);
+
+#endif
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-os-timer.h b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-os-timer.h
new file mode 100644
index 0000000..8082c62
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-os-timer.h
@@ -0,0 +1,68 @@
+/*
+** File: osapi-os-timer.h
+**
+** Copyright (c) 2004-2006, United States government as represented by the
+** administrator of the National Aeronautics Space Administration.
+** All rights reserved. This software was created at NASAs Goddard
+** Space Flight Center pursuant to government contracts.
+**
+** This is governed by the NASA Open Source Agreement and may be used,
+** distributed and modified only pursuant to the terms of that agreement.
+**
+** Author: Alan Cudmore - Code 582
+**
+** Purpose: Contains functions prototype definitions and variable declarations
+** for the OS Abstraction Layer, Timer API
+**
+** $Revision: 1.5 $
+**
+** $Date: 2013/07/25 10:02:20GMT-05:00 $
+**
+** $Log: osapi-os-timer.h $
+** Revision 1.5 2013/07/25 10:02:20GMT-05:00 acudmore
+** removed circular include "osapi.h"
+** Revision 1.4 2010/11/12 12:00:19GMT-05:00 acudmore
+** replaced copyright character with (c) and added open source notice where needed.
+** Revision 1.3 2010/02/01 12:38:34EST acudmore
+** Added return code to OS_TimerAPIInit
+** Revision 1.2 2008/08/26 13:52:52EDT apcudmore
+** removed linux specific define
+** Revision 1.1 2008/08/20 16:12:07EDT apcudmore
+** Initial revision
+** Member added to project c:/MKSDATA/MKS-REPOSITORY/MKS-OSAL-REPOSITORY/src/os/inc/project.pj
+**
+**
+*/
+
+#ifndef _osapi_timer_
+#define _osapi_timer_
+
+/*
+** Typedefs
+*/
+typedef void (*OS_TimerCallback_t)(uint32 timer_id);
+
+typedef struct
+{
+ char name[OS_MAX_API_NAME];
+ uint32 creator;
+ uint32 start_time;
+ uint32 interval_time;
+ uint32 accuracy;
+
+} OS_timer_prop_t;
+
+
+/*
+** Timer API
+*/
+int32 OS_TimerAPIInit (void);
+
+int32 OS_TimerCreate (uint32 *timer_id, const char *timer_name, uint32 *clock_accuracy, OS_TimerCallback_t callback_ptr);
+int32 OS_TimerSet (uint32 timer_id, uint32 start_msec, uint32 interval_msec);
+int32 OS_TimerDelete (uint32 timer_id);
+
+int32 OS_TimerGetIdByName (uint32 *timer_id, const char *timer_name);
+int32 OS_TimerGetInfo (uint32 timer_id, OS_timer_prop_t *timer_prop);
+
+#endif
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-version.h b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-version.h
new file mode 100644
index 0000000..331e96c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi-version.h
@@ -0,0 +1,48 @@
+/************************************************************************
+** File:
+** $Id: osapi-version.h 1.11 2014/05/02 13:53:14GMT-05:00 acudmore Exp $
+**
+** Copyright (c) 2004-2006, United States government as represented by the
+** administrator of the National Aeronautics Space Administration.
+** All rights reserved. This software was created at NASAs Goddard
+** Space Flight Center pursuant to government contracts.
+**
+** This is governed by the NASA Open Source Agreement and may be used,
+** distributed and modified only pursuant to the terms of that agreement.
+**
+** Purpose:
+** The OSAL version numbers
+**
+** Notes:
+**
+** $Log: osapi-version.h $
+** Revision 1.11 2014/05/02 13:53:14GMT-05:00 acudmore
+** Updated version to 4.1.1
+** Revision 1.10 2014/01/23 16:33:31GMT-05:00 acudmore
+** Update for 4.1 release
+** Revision 1.9 2013/01/16 14:35:18GMT-05:00 acudmore
+** updated version label
+** Revision 1.8 2012/04/16 14:57:04GMT-05:00 acudmore
+** Updated version label to 3.5.0.0
+** Revision 1.7 2012/01/17 16:04:29EST acudmore
+** Updated version to 3.4.1
+** Revision 1.6 2011/12/05 15:45:16EST acudmore
+** Updated version label to 3.4.0
+** Initial revision
+** Member added to project c:/MKSDATA/MKS-REPOSITORY/MKS-OSAL-REPOSITORY/src/os/inc/project.pj
+**
+*************************************************************************/
+#ifndef _osapi_version_h_
+#define _osapi_version_h_
+
+#define OS_MAJOR_VERSION (4)
+#define OS_MINOR_VERSION (1)
+#define OS_REVISION (1)
+#define OS_MISSION_REV (0)
+
+
+#endif /* _osapi_version_h_ */
+
+/************************/
+/* End of File Comment */
+/************************/
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi.h b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi.h
new file mode 100644
index 0000000..72a7c34
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/include/osapi.h
@@ -0,0 +1,143 @@
+/*
+** File: osapi.h
+**
+** Copyright (c) 2004-2006, United States government as represented by the
+** administrator of the National Aeronautics Space Administration.
+** All rights reserved. This software was created at NASAs Goddard
+** Space Flight Center pursuant to government contracts.
+**
+** This is governed by the NASA Open Source Agreement and may be used,
+** distributed and modified only pursuant to the terms of that agreement.
+**
+** Author: Alan Cudmore - Code 582
+**
+** Purpose: Contains functions prototype definitions and variables declarations
+** for the OS Abstraction Layer, Core OS module
+**
+** $Revision: 1.10 $
+**
+** $Date: 2013/07/25 10:01:32GMT-05:00 $
+**
+** $Log: osapi.h $
+** Revision 1.10 2013/07/25 10:01:32GMT-05:00 acudmore
+** Added C++ support
+** Revision 1.9 2010/11/12 12:00:17GMT-05:00 acudmore
+** replaced copyright character with (c) and added open source notice where needed.
+** Revision 1.8 2010/03/08 15:57:20EST acudmore
+** include new OSAL version header file
+** Revision 1.7 2009/08/10 14:01:10EDT acudmore
+** Reset OSAL version for trunk
+** Revision 1.6 2009/08/10 13:55:49EDT acudmore
+** Updated OSAL version defines to 3.0
+** Revision 1.5 2009/06/10 14:15:55EDT acudmore
+** Removed HAL include files. HAL code was removed from OSAL.
+** Revision 1.4 2008/08/20 16:12:51EDT apcudmore
+** Updated timer error codes
+** Revision 1.3 2008/08/20 15:46:27EDT apcudmore
+** Add support for timer API
+** Revision 1.2 2008/06/20 15:13:43EDT apcudmore
+** Checked in new Module loader/symbol table functionality
+** Revision 1.1 2008/04/20 22:36:02EDT ruperera
+** Initial revision
+** Member added to project c:/MKSDATA/MKS-REPOSITORY/MKS-OSAL-REPOSITORY/src/os/inc/project.pj
+** Revision 1.6 2008/02/14 11:29:10EST apcudmore
+** Updated version define ( 2.11 )
+** Revision 1.5 2008/02/07 11:31:58EST apcudmore
+** Fixed merge problem
+** Revision 1.4 2008/02/07 11:07:29EST apcudmore
+** Added dynamic loader / Symbol lookup API
+** -- API only, next release will have functionality
+** Revision 1.2 2008/01/29 14:30:49EST njyanchik
+** I added code to all the ports that allow the values of both binary and counting semaphores to be
+** gotten through the OS_*SemGetInfo API.
+** Revision 1.1 2007/10/16 16:14:52EDT apcudmore
+** Initial revision
+** Member added to project d:/mksdata/MKS-OSAL-REPOSITORY/src/os/inc/project.pj
+** Revision 1.2 2007/09/28 15:46:49EDT rjmcgraw
+** Updated version numbers to 5.0
+** Revision 1.1 2007/08/24 13:43:25EDT apcudmore
+** Initial revision
+** Member added to project d:/mksdata/MKS-CFE-PROJECT/fsw/cfe-core/os/inc/project.pj
+** Revision 1.9.1.1 2007/05/21 08:58:51EDT njyanchik
+** The trunk version number has been updated to version 0.0
+** Revision 1.9 2006/06/12 10:20:07EDT rjmcgraw
+** Updated OS_MINOR_VERSION from 3 to 4
+** Revision 1.8 2006/02/03 09:30:45EST njyanchik
+** Changed version number to 2.3
+** Revision 1.7 2006/01/20 11:56:16EST njyanchik
+** Fixed header file information to match api document
+** Revision 1.15 2005/11/09 13:35:49 nyanchik
+** Revisions for 2.2 include:
+** a new scheduler mapper for Linux and OS X
+** addition of OS_printf function
+** fixed issues that would cause warnings at compile time
+**
+**
+*/
+
+#ifndef _osapi_
+#define _osapi_
+
+#include "common_types.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define OS_SUCCESS (0)
+#define OS_ERROR (-1)
+#define OS_INVALID_POINTER (-2)
+#define OS_ERROR_ADDRESS_MISALIGNED (-3)
+#define OS_ERROR_TIMEOUT (-4)
+#define OS_INVALID_INT_NUM (-5)
+#define OS_SEM_FAILURE (-6)
+#define OS_SEM_TIMEOUT (-7)
+#define OS_QUEUE_EMPTY (-8)
+#define OS_QUEUE_FULL (-9)
+#define OS_QUEUE_TIMEOUT (-10)
+#define OS_QUEUE_INVALID_SIZE (-11)
+#define OS_QUEUE_ID_ERROR (-12)
+#define OS_ERR_NAME_TOO_LONG (-13)
+#define OS_ERR_NO_FREE_IDS (-14)
+#define OS_ERR_NAME_TAKEN (-15)
+#define OS_ERR_INVALID_ID (-16)
+#define OS_ERR_NAME_NOT_FOUND (-17)
+#define OS_ERR_SEM_NOT_FULL (-18)
+#define OS_ERR_INVALID_PRIORITY (-19)
+#define OS_INVALID_SEM_VALUE (-20)
+#define OS_ERR_FILE (-27)
+#define OS_ERR_NOT_IMPLEMENTED (-28)
+#define OS_TIMER_ERR_INVALID_ARGS (-29)
+#define OS_TIMER_ERR_TIMER_ID (-30)
+#define OS_TIMER_ERR_UNAVAILABLE (-31)
+#define OS_TIMER_ERR_INTERNAL (-32)
+
+/*
+** Defines for Queue Timeout parameters
+*/
+#define OS_PEND (0)
+#define OS_CHECK (-1)
+
+#include "osapi-version.h"
+
+/*
+** Include the configuration file
+*/
+#include "osconfig.h"
+
+/*
+** Include the OS API modules
+*/
+#include "osapi-os-core.h"
+//#include "osapi-os-filesys.h"
+//#include "osapi-os-net.h"
+//#include "osapi-os-loader.h"
+#include "osapi-os-timer.h"
+#include "osapi-os-custom.h"
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
+
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/src/osapi.c b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/src/osapi.c
new file mode 100644
index 0000000..c3c5110
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/osal/src/osapi.c
@@ -0,0 +1,2280 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file osapi.c
+ * @brief OS API module code.
+ *
+ * @addtogroup nasa_osapi
+ * @{
+ */
+
+#include
+#include
+
+#include "ch.h"
+
+#include "common_types.h"
+#include "osapi.h"
+
+#if CH_CFG_ST_FREQUENCY > 1000000
+#error "CH_CFG_ST_FREQUENCY limit is 1000000"
+#endif
+
+#if (CH_CFG_ST_FREQUENCY % 1000) != 0
+#error "CH_CFG_ST_FREQUENCY is not a multiple of 1000"
+#endif
+
+#if CH_CFG_USE_REGISTRY == FALSE
+#error "NASA OSAL requires CH_CFG_USE_REGISTRY"
+#endif
+
+#if CH_CFG_USE_EVENTS == FALSE
+#error "NASA OSAL requires CH_CFG_USE_EVENTS"
+#endif
+
+#if CH_CFG_USE_MUTEXES == FALSE
+#error "NASA OSAL requires CH_CFG_USE_MUTEXES"
+#endif
+
+#if CH_CFG_USE_SEMAPHORES == FALSE
+#error "NASA OSAL requires CH_CFG_USE_SEMAPHORES"
+#endif
+
+#if CH_CFG_USE_MEMCORE == FALSE
+#error "NASA OSAL requires CH_CFG_USE_MEMCORE"
+#endif
+
+#if CH_CFG_USE_MEMPOOLS == FALSE
+#error "NASA OSAL requires CH_CFG_USE_MEMPOOLS"
+#endif
+
+#if CH_CFG_USE_HEAP == FALSE
+#error "NASA OSAL requires CH_CFG_USE_HEAP"
+#endif
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+#define MIN_PRIORITY 1
+#define MAX_PRIORITY 255
+
+#define MIN_MESSAGE_SIZE 4
+#define MAX_MESSAGE_SIZE 16384
+
+#define MIN_QUEUE_DEPTH 1
+#define MAX_QUEUE_DEPTH 16384
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/**
+ * @brief Generic function pointer type.
+ */
+typedef void (*funcptr_t)(void);
+
+/**
+ * @brief Type of OSAL timer.
+ */
+typedef struct {
+ uint32 is_free;
+ char name[OS_MAX_API_NAME];
+ OS_TimerCallback_t callback_ptr;
+ uint32 start_time;
+ uint32 interval_time;
+ virtual_timer_t vt;
+} osal_timer_t;
+
+/**
+ * @brief Type of an OSAL queue.
+ */
+typedef struct {
+ uint32 is_free;
+ char name[OS_MAX_API_NAME];
+ semaphore_t free_msgs;
+ memory_pool_t messages;
+ mailbox_t mb;
+ msg_t *mb_buffer;
+ void *q_buffer;
+ uint32 depth;
+ uint32 size;
+} osal_queue_t;
+
+/**
+ * @brief Type of an osal message with minimum size.
+ */
+typedef struct {
+ size_t size;
+ char buf[4];
+} osal_message_t;
+
+/**
+ * @brief Type of OSAL main structure.
+ */
+typedef struct {
+ bool printf_enabled;
+ int (*printf)(const char *fmt, ...);
+ virtual_timer_t vt;
+ OS_time_t localtime;
+ memory_pool_t timers_pool;
+ memory_pool_t queues_pool;
+ memory_pool_t binary_semaphores_pool;
+ memory_pool_t count_semaphores_pool;
+ memory_pool_t mutexes_pool;
+ osal_timer_t timers[OS_MAX_TIMERS];
+ osal_queue_t queues[OS_MAX_QUEUES];
+ binary_semaphore_t binary_semaphores[OS_MAX_BIN_SEMAPHORES];
+ semaphore_t count_semaphores[OS_MAX_COUNT_SEMAPHORES];
+ mutex_t mutexes[OS_MAX_MUTEXES];
+} osal_t;
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+static osal_t osal;
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief System time callback.
+ */
+static void systime_update(void *p) {
+ sysinterval_t delay = (sysinterval_t)p;
+
+ chSysLockFromISR();
+ osal.localtime.microsecs += 1000;
+ if (osal.localtime.microsecs >= 1000000) {
+ osal.localtime.microsecs = 0;
+ osal.localtime.seconds++;
+ }
+ chVTDoSetI(&osal.vt, delay, systime_update, p);
+ chSysUnlockFromISR();
+}
+
+/**
+ * @brief Virtual timers callback.
+ */
+static void timer_handler(void *p) {
+ osal_timer_t *otp = (osal_timer_t *)p;
+
+ /* Real callback.*/
+ otp->callback_ptr((uint32)p);
+
+ /* Timer restart if an interval is defined.*/
+ if (otp->interval_time != 0) {
+ chSysLockFromISR();
+ chVTSetI(&otp->vt, TIME_US2I(otp->interval_time), timer_handler, p);
+ chSysUnlockFromISR();
+ }
+}
+
+/**
+ * @brief Finds a queue by name.
+ */
+uint32 queue_find(const char *queue_name) {
+ osal_queue_t *oqp;
+
+ /* Searching the queue in the table.*/
+ for (oqp = &osal.queues[0]; oqp < &osal.queues[OS_MAX_QUEUES]; oqp++) {
+ /* Entering a reentrant critical zone.*/
+ syssts_t sts = chSysGetStatusAndLockX();
+
+ if (!oqp->is_free &&
+ (strncmp(oqp->name, queue_name, OS_MAX_API_NAME - 1) == 0)) {
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+ return (uint32)oqp;
+ }
+
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+ }
+
+ return 0;
+}
+
+/**
+ * @brief Finds a timer by name.
+ */
+uint32 timer_find(const char *timer_name) {
+ osal_timer_t *otp;
+
+ /* Searching the queue in the table.*/
+ for (otp = &osal.timers[0]; otp < &osal.timers[OS_MAX_TIMERS]; otp++) {
+ /* Entering a reentrant critical zone.*/
+ syssts_t sts = chSysGetStatusAndLockX();
+
+ if (!otp->is_free &&
+ (strncmp(otp->name, timer_name, OS_MAX_API_NAME - 1) == 0)) {
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+ return (uint32)otp;
+ }
+
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+ }
+
+ return 0;
+}
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/*-- Initialization API -----------------------------------------------------*/
+
+/**
+ * @brief OS initialization.
+ * @details This function returns initializes the internal data structures
+ * of the OS Abstraction Layer. It must be called in the application
+ * startup code before calling any other OS routines.
+ *
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_API_Init(void) {
+
+ chSysInit();
+
+ /* OS_printf() initially disabled.*/
+ osal.printf_enabled = false;
+ osal.printf = NULL;
+
+ /* System time handling.*/
+ osal.localtime.microsecs = 0;
+ osal.localtime.seconds = 0;
+ chVTObjectInit(&osal.vt);
+ chVTSet(&osal.vt, TIME_MS2I(1), systime_update, (void *)TIME_MS2I(1));
+
+ /* Timers pool initialization.*/
+ chPoolObjectInit(&osal.timers_pool,
+ sizeof (osal_timer_t),
+ NULL);
+ chPoolLoadArray(&osal.timers_pool,
+ &osal.timers[0],
+ OS_MAX_TIMERS);
+
+ /* Queues pool initialization.*/
+ chPoolObjectInit(&osal.queues_pool,
+ sizeof (osal_queue_t),
+ NULL);
+ chPoolLoadArray(&osal.queues_pool,
+ &osal.queues[0],
+ OS_MAX_QUEUES);
+
+ /* Binary Semaphores pool initialization.*/
+ chPoolObjectInit(&osal.binary_semaphores_pool,
+ sizeof (binary_semaphore_t),
+ NULL);
+ chPoolLoadArray(&osal.binary_semaphores_pool,
+ &osal.binary_semaphores[0],
+ OS_MAX_BIN_SEMAPHORES);
+
+ /* Counter Semaphores pool initialization.*/
+ chPoolObjectInit(&osal.count_semaphores_pool,
+ sizeof (semaphore_t),
+ NULL);
+ chPoolLoadArray(&osal.count_semaphores_pool,
+ &osal.count_semaphores[0],
+ OS_MAX_COUNT_SEMAPHORES);
+
+ /* Mutexes pool initialization.*/
+ chPoolObjectInit(&osal.mutexes_pool,
+ sizeof (mutex_t),
+ NULL);
+ chPoolLoadArray(&osal.mutexes_pool,
+ &osal.mutexes[0],
+ OS_MAX_MUTEXES);
+
+ return OS_SUCCESS;
+}
+
+/*-- Various API -----------------------------------------------------------*/
+
+/**
+ * @brief OS printf-like function.
+ * @note It is initially disabled.
+ *
+ * @param[in] string formatter string
+ *
+ * @api
+ */
+void OS_printf(const char *string, ...) {
+ va_list ap;
+
+ if (osal.printf_enabled && (osal.printf != NULL)) {
+ va_start(ap, string);
+ (void) osal.printf(string);
+ va_end(ap);
+ }
+}
+
+/**
+ * @brief Disables @p OS_printf().
+ *
+ * @api
+ */
+void OS_printf_disable(void) {
+
+ osal.printf_enabled = false;
+}
+
+/**
+ * @brief Enables @p OS_printf().
+ *
+ * @api
+ */
+void OS_printf_enable(void) {
+
+ osal.printf_enabled = true;
+}
+
+/**
+ * @brief Sets the system printf function.
+ * @note By default the printf function is not defined.
+ * @note This is a ChibiOS/RT extension.
+ *
+ * @param[in] printf pointer to a @p printf() like function
+ *
+ * @api
+ */
+void OS_set_printf(int (*printf)(const char *fmt, ...)) {
+
+ osal.printf = printf;
+}
+
+/**
+ * @brief System tick period in microseconds.
+ *
+ * @return The system tick period.
+ */
+int32 OS_Tick2Micros(void) {
+
+ return 1000000 / CH_CFG_ST_FREQUENCY;
+}
+
+/**
+ * @brief Returns the local time.
+ *
+ * @param[out] time_struct the system time
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_GetLocalTime(OS_time_t *time_struct) {
+
+ if (time_struct == NULL) {
+ return OS_INVALID_POINTER;
+ }
+
+ chSysLock();
+ *time_struct = osal.localtime;
+ chSysUnlock();
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Changes the local time.
+ *
+ * @param[in] time_struct the system time
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_SetLocalTime(OS_time_t *time_struct) {
+
+ if (time_struct == NULL) {
+ return OS_INVALID_POINTER;
+ }
+
+ chSysLock();
+ osal.localtime = *time_struct;
+ chSysUnlock();
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Conversion from milliseconds to ticks.
+ *
+ * @param[in] milli_seconds the time in milliseconds
+ * @return The system ticks.
+ *
+ * @api
+ */
+int32 OS_Milli2Ticks(uint32 milli_seconds) {
+
+ return (int32)TIME_MS2I(milli_seconds);
+}
+
+/*-- timers API -------------------------------------------------------------*/
+
+/**
+ * @brief Timer creation.
+ *
+ * @param[out] timer_id pointer to a timer id variable
+ * @param[in] timer_name the timer name
+ * @param[out] clock_accuracy timer accuracy in microseconds
+ * @param[in] callback_ptr timer callback
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_TimerCreate(uint32 *timer_id, const char *timer_name,
+ uint32 *clock_accuracy, OS_TimerCallback_t callback_ptr) {
+ osal_timer_t *otp;
+
+ /* NULL pointer checks.*/
+ if ((timer_id == NULL) || (timer_name == NULL) ||
+ (clock_accuracy == NULL)) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* NULL callback check.*/
+ if (callback_ptr == NULL) {
+ *timer_id = 0;
+ return OS_TIMER_ERR_INVALID_ARGS;
+ }
+
+ /* Checking timer name length.*/
+ if (strlen(timer_name) >= OS_MAX_API_NAME) {
+ *timer_id = 0;
+ return OS_ERR_NAME_TOO_LONG;
+ }
+
+ /* Checking if the name is already taken.*/
+ if (timer_find(timer_name) > 0) {
+ *timer_id = 0;
+ return OS_ERR_NAME_TAKEN;
+ }
+
+ /* Getting object.*/
+ otp = chPoolAlloc(&osal.timers_pool);
+ if (otp == NULL) {
+ *timer_id = 0;
+ return OS_ERR_NO_FREE_IDS;
+ }
+
+ strncpy(otp->name, timer_name, OS_MAX_API_NAME - 1);
+ chVTObjectInit(&otp->vt);
+ otp->start_time = 0;
+ otp->interval_time = 0;
+ otp->callback_ptr = callback_ptr;
+ otp->is_free = 0; /* Note, last.*/
+
+ *timer_id = (uint32)otp;
+ *clock_accuracy = (uint32)(1000000 / CH_CFG_ST_FREQUENCY);
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Timer deletion.
+ *
+ * @param[in] timer_id timer id variable
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_TimerDelete(uint32 timer_id) {
+ osal_timer_t *otp = (osal_timer_t *)timer_id;
+
+ /* Range check.*/
+ if ((otp < &osal.timers[0]) ||
+ (otp >= &osal.timers[OS_MAX_TIMERS]) ||
+ (otp->is_free)) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ chSysLock();
+
+ /* Marking as no more free, will be overwritten by the pool pointer.*/
+ otp->is_free = 1;
+
+ /* Resetting the timer.*/
+ chVTResetI(&otp->vt);
+ otp->start_time = 0;
+ otp->interval_time = 0;
+
+ /* Flagging it as unused and returning it to the pool.*/
+ chPoolFreeI(&osal.timers_pool, (void *)otp);
+
+ chSysUnlock();
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Timer deletion.
+ * @note This function can be safely called from timer callbacks or ISRs.
+ *
+ * @param[in] timer_id timer id variable
+ * @param[in] start_time start time in microseconds or zero
+ * @param[in] interval_time interval time in microseconds or zero
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_TimerSet(uint32 timer_id, uint32 start_time, uint32 interval_time) {
+ syssts_t sts;
+ osal_timer_t *otp = (osal_timer_t *)timer_id;
+
+ /* Range check.*/
+ if ((otp < &osal.timers[0]) ||
+ (otp >= &osal.timers[OS_MAX_TIMERS]) ||
+ (otp->is_free)) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ /* Entering a reentrant critical zone.*/
+ sts = chSysGetStatusAndLockX();
+
+ if (start_time == 0) {
+ chVTResetI(&otp->vt);
+ }
+ else {
+ otp->start_time = start_time;
+ otp->interval_time = interval_time;
+ chVTSetI(&otp->vt, TIME_US2I(start_time), timer_handler, (void *)timer_id);
+ }
+
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Retrieves a timer id by name.
+ *
+ * @param[out] timer_id pointer to a timer id variable
+ * @param[in] sem_name the timer name
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_TimerGetIdByName(uint32 *timer_id, const char *timer_name) {
+
+ /* NULL pointer checks.*/
+ if ((timer_id == NULL) || (timer_name == NULL)) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Checking name length.*/
+ if (strlen(timer_name) >= OS_MAX_API_NAME) {
+ return OS_ERR_NAME_TOO_LONG;
+ }
+
+ /* Searching the queue.*/
+ *timer_id = timer_find(timer_name);
+ if (*timer_id > 0) {
+ return OS_SUCCESS;
+ }
+
+ return OS_ERR_NAME_NOT_FOUND;
+}
+
+/**
+ * @brief Returns timer information.
+ * @note This function can be safely called from timer callbacks or ISRs.
+ *
+ * @param[in] timer_id timer id variable
+ * @param[in] timer_prop timer properties
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_TimerGetInfo(uint32 timer_id, OS_timer_prop_t *timer_prop) {
+ syssts_t sts;
+ osal_timer_t *otp = (osal_timer_t *)timer_id;
+
+ /* NULL pointer checks.*/
+ if (timer_prop == NULL) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Range check.*/
+ if ((otp < &osal.timers[0]) ||
+ (otp >= &osal.timers[OS_MAX_TIMERS]) ||
+ (otp->is_free)) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ /* Entering a reentrant critical zone.*/
+ sts = chSysGetStatusAndLockX();
+
+ /* If the timer is not in use then error.*/
+ if (otp->is_free) {
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+ return OS_ERR_INVALID_ID;
+ }
+
+ strncpy(timer_prop->name, otp->name, OS_MAX_API_NAME - 1);
+ timer_prop->creator = (uint32)0;
+ timer_prop->start_time = otp->start_time;
+ timer_prop->interval_time = otp->interval_time;
+ timer_prop->accuracy = (uint32)(1000000 / CH_CFG_ST_FREQUENCY);
+
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+
+ return OS_SUCCESS;
+}
+
+/*-- Queues API -------------------------------------------------------------*/
+
+/**
+ * @brief Queue creation.
+ *
+ * @param[out] queue_id pointer to a queue id variable
+ * @param[in] queue_name the queue name
+ * @param[in] queue_depth desired queue depth
+ * @param[in] data_size maximum message size
+ * @param[in] flags queue option flags
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_QueueCreate(uint32 *queue_id, const char *queue_name,
+ uint32 queue_depth, uint32 data_size, uint32 flags) {
+ osal_queue_t *oqp;
+ size_t msgsize;
+
+ (void)flags;
+
+ /* NULL pointer checks.*/
+ if ((queue_id == NULL) || (queue_name == NULL)) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Checking queue name length.*/
+ if (strlen(queue_name) >= OS_MAX_API_NAME) {
+ *queue_id = 0;
+ return OS_ERR_NAME_TOO_LONG;
+ }
+
+ /* Checking if the name is already taken.*/
+ if (queue_find(queue_name) > 0) {
+ *queue_id = 0;
+ return OS_ERR_NAME_TAKEN;
+ }
+
+ /* Checks on queue limits. There is no dedicated error code.*/
+ if ((data_size < MIN_MESSAGE_SIZE) || (data_size > MAX_MESSAGE_SIZE) ||
+ (queue_depth < MIN_QUEUE_DEPTH) || (queue_depth > MAX_QUEUE_DEPTH)) {
+ *queue_id = 0;
+ return OS_ERROR;
+ }
+
+ /* Getting object.*/
+ oqp = chPoolAlloc(&osal.queues_pool);
+ if (oqp == NULL) {
+ *queue_id = 0;
+ return OS_ERR_NO_FREE_IDS;
+ }
+
+ /* Attempting messages buffer allocation.*/
+ msgsize = MEM_ALIGN_NEXT(data_size + sizeof (size_t), PORT_NATURAL_ALIGN);
+ oqp->mb_buffer = chHeapAllocAligned(NULL,
+ msgsize * (size_t)queue_depth,
+ PORT_NATURAL_ALIGN);
+ if (oqp->mb_buffer == NULL) {
+ *queue_id = 0;
+ return OS_ERROR;
+ }
+
+ /* Attempting queue buffer allocation.*/
+ oqp->q_buffer = chHeapAllocAligned(NULL,
+ sizeof (msg_t) * (size_t)queue_depth,
+ PORT_NATURAL_ALIGN);
+ if (oqp->q_buffer == NULL) {
+ *queue_id = 0;
+ chHeapFree(oqp->mb_buffer);
+ return OS_ERROR;
+ }
+
+ /* Initializing object static parts.*/
+ strncpy(oqp->name, queue_name, OS_MAX_API_NAME - 1);
+ chMBObjectInit(&oqp->mb, oqp->q_buffer, (size_t)queue_depth);
+ chSemObjectInit(&oqp->free_msgs, (cnt_t)queue_depth);
+ chPoolObjectInit(&oqp->messages, msgsize, NULL);
+ chPoolLoadArray(&oqp->messages, oqp->mb_buffer, (size_t)queue_depth);
+ oqp->depth = queue_depth;
+ oqp->size = data_size;
+ oqp->is_free = 0; /* Note, last.*/
+ *queue_id = (uint32)oqp;
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Queue deletion.
+ *
+ * @param[in] queue_id queue id variable
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_QueueDelete(uint32 queue_id) {
+ osal_queue_t *oqp = (osal_queue_t *)queue_id;
+ void *q_buffer, *mb_buffer;
+
+ /* Range check.*/
+ if ((oqp < &osal.queues[0]) ||
+ (oqp >= &osal.queues[OS_MAX_QUEUES]) ||
+ (oqp->is_free)) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ /* Critical zone.*/
+ chSysLock();
+
+ /* Marking as no more free, will be overwritten by the pool pointer.*/
+ oqp->is_free = 1;
+
+ /* Pointers to areas to be freed.*/
+ q_buffer = oqp->q_buffer;
+ mb_buffer = oqp->mb_buffer;
+
+ /* Resetting the queue.*/
+ chMBResetI(&oqp->mb);
+ chSemResetI(&oqp->free_msgs, 0);
+
+ /* Flagging it as unused and returning it to the pool.*/
+ chPoolFreeI(&osal.queues_pool, (void *)oqp);
+
+ chSchRescheduleS();
+
+ /* Leaving critical zone.*/
+ chSysUnlock();
+
+ /* Freeing buffers, outside critical zone, slow heap operation.*/
+ chHeapFree(q_buffer);
+ chHeapFree(mb_buffer);
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Retrieves a message from the queue.
+ *
+ * @param[in] queue_id queue id variable
+ * @param[out] data message buffer pointer
+ * @param[in] size size of the buffer
+ * @param[out] size_copied size of the received message
+ * @param[in] timeout timeout in ticks, the special values @p OS_PEND
+ * and @p OS_CHECK can be specified
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_QueueGet(uint32 queue_id, void *data, uint32 size,
+ uint32 *size_copied, int32 timeout) {
+ osal_queue_t *oqp = (osal_queue_t *)queue_id;
+ msg_t msg, msgsts;
+ void *body;
+
+ /* NULL pointer checks.*/
+ if ((data == NULL) || (size_copied == NULL)) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Range check.*/
+ if ((oqp < &osal.queues[0]) ||
+ (oqp >= &osal.queues[OS_MAX_QUEUES]) ||
+ (oqp->is_free)) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ /* Check on minimum size.*/
+ if (size < oqp->size) {
+ return OS_QUEUE_INVALID_SIZE;
+ }
+
+ /* Special time handling.*/
+ if (timeout == OS_PEND) {
+ msgsts = chMBFetchTimeout(&oqp->mb, &msg, TIME_INFINITE);
+ if (msgsts < MSG_OK) {
+ *size_copied = 0;
+ return OS_ERROR;
+ }
+ }
+ else if (timeout == OS_CHECK) {
+ msgsts = chMBFetchTimeout(&oqp->mb, &msg, TIME_IMMEDIATE);
+ if (msgsts < MSG_OK) {
+ *size_copied = 0;
+ return OS_QUEUE_EMPTY;
+ }
+ }
+ else {
+ msgsts = chMBFetchTimeout(&oqp->mb, &msg, (sysinterval_t)timeout);
+ if (msgsts < MSG_OK) {
+ *size_copied = 0;
+ return OS_QUEUE_TIMEOUT;
+ }
+ }
+
+ /* Message body and size.*/
+ *size_copied = ((osal_message_t *)msg)->size;
+ body = (void *)((osal_message_t *)msg)->buf;
+
+ /* Copying the message body.*/
+ memcpy(data, body, *size_copied);
+
+ /* Freeing the message buffer.*/
+ chPoolFree(&oqp->messages, (void *)msg);
+ chSemSignal(&oqp->free_msgs);
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Puts a message in the queue.
+ *
+ * @param[in] queue_id queue id variable
+ * @param[in] data message buffer pointer
+ * @param[in] size size of the message
+ * @param[in] flags operation flags
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_QueuePut(uint32 queue_id, void *data, uint32 size, uint32 flags) {
+ osal_queue_t *oqp = (osal_queue_t *)queue_id;
+ msg_t msgsts;
+ osal_message_t *omsg;
+
+ (void)flags;
+
+ /* NULL pointer checks.*/
+ if (data == NULL) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Range check.*/
+ if ((oqp < &osal.queues[0]) ||
+ (oqp >= &osal.queues[OS_MAX_QUEUES]) ||
+ (oqp->is_free)) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ /* Check on maximum size.*/
+ if (size > oqp->size) {
+ return OS_QUEUE_INVALID_SIZE;
+ }
+
+ /* Getting a message buffer from the pool.*/
+ msgsts = chSemWait(&oqp->free_msgs);
+ if (msgsts < MSG_OK) {
+ return OS_ERROR;
+ }
+ omsg = chPoolAlloc(&oqp->messages);
+
+ /* Filling message size and data.*/
+ omsg->size = (size_t)size;
+ memcpy(omsg->buf, data, size);
+
+ /* Posting the message.*/
+ msgsts = chMBPostTimeout(&oqp->mb, (msg_t)omsg, TIME_INFINITE);
+ if (msgsts < MSG_OK) {
+ return OS_ERROR;
+ }
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Retrieves a queue id by name.
+ *
+ * @param[out] queue_id pointer to a queue id variable
+ * @param[in] sem_name the queue name
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_QueueGetIdByName(uint32 *queue_id, const char *queue_name) {
+
+ /* NULL pointer checks.*/
+ if ((queue_id == NULL) || (queue_name == NULL)) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Checking name length.*/
+ if (strlen(queue_name) >= OS_MAX_API_NAME) {
+ return OS_ERR_NAME_TOO_LONG;
+ }
+
+ /* Searching the queue.*/
+ *queue_id = queue_find(queue_name);
+ if (*queue_id > 0) {
+ return OS_SUCCESS;
+ }
+
+ return OS_ERR_NAME_NOT_FOUND;
+}
+
+/**
+ * @brief Returns queue information.
+ * @note This function can be safely called from timer callbacks or ISRs.
+ *
+ * @param[in] queue_id queue id variable
+ * @param[in] queue_prop queue properties
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_QueueGetInfo (uint32 queue_id, OS_queue_prop_t *queue_prop) {
+ osal_queue_t *oqp = (osal_queue_t *)queue_id;
+ syssts_t sts;
+
+ /* NULL pointer checks.*/
+ if (queue_prop == NULL) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Range check.*/
+ if ((oqp < &osal.queues[0]) ||
+ (oqp >= &osal.queues[OS_MAX_QUEUES]) ||
+ (oqp->is_free)) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ /* Entering a reentrant critical zone.*/
+ sts = chSysGetStatusAndLockX();
+
+ /* If the queue is not in use then error.*/
+ if (oqp->is_free) {
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+ return OS_ERR_INVALID_ID;
+ }
+
+ strncpy(queue_prop->name, oqp->name, OS_MAX_API_NAME - 1);
+ queue_prop->creator = (uint32)0;
+
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+
+ return OS_SUCCESS;
+
+ return OS_ERR_NOT_IMPLEMENTED;
+}
+
+/*-- Binary Semaphore API ---------------------------------------------------*/
+
+/**
+ * @brief Binary semaphore creation.
+ *
+ * @param[out] sem_id pointer to a binary semaphore id variable
+ * @param[in] sem_name the binary semaphore name
+ * @param[in] sem_initial_value semaphore initial value
+ * @param[in] options semaphore options
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_BinSemCreate(uint32 *sem_id, const char *sem_name,
+ uint32 sem_initial_value, uint32 options) {
+ binary_semaphore_t *bsp;
+
+ (void)options;
+
+ /* NULL pointer checks.*/
+ if ((sem_id == NULL) || (sem_name == NULL)) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Checking semaphore name length.*/
+ if (strlen(sem_name) >= OS_MAX_API_NAME) {
+ return OS_ERR_NAME_TOO_LONG;
+ }
+
+ /* Semaphore counter check, it is binary so only 0 and 1.*/
+ if (sem_initial_value > 1) {
+ return OS_INVALID_INT_NUM;
+ }
+
+ /* Getting object.*/
+ bsp = chPoolAlloc(&osal.binary_semaphores_pool);
+ if (bsp == NULL) {
+ return OS_ERR_NO_FREE_IDS;
+ }
+
+ /* Semaphore is initialized.*/
+ chBSemObjectInit(bsp, sem_initial_value == 0 ? true : false);
+
+ *sem_id = (uint32)bsp;
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Binary semaphore deletion.
+ *
+ * @param[in] sem_id binary semaphore id variable
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_BinSemDelete(uint32 sem_id) {
+ binary_semaphore_t *bsp = (binary_semaphore_t *)sem_id;
+
+ /* Range check.*/
+ if ((bsp < &osal.binary_semaphores[0]) ||
+ (bsp >= &osal.binary_semaphores[OS_MAX_BIN_SEMAPHORES])) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ chSysLock();
+
+ /* Resetting the semaphore, no threads in queue.*/
+ chBSemResetI(bsp, true);
+
+ /* Flagging it as unused and returning it to the pool.*/
+ bsp->sem.queue.prev = NULL;
+ chPoolFreeI(&osal.binary_semaphores_pool, (void *)bsp);
+
+ /* Required because some thread could have been made ready.*/
+ chSchRescheduleS();
+
+ chSysUnlock();
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Binary semaphore flush.
+ * @note The state of the binary semaphore is not changed.
+ * @note This function can be safely called from timer callbacks or ISRs.
+ *
+ * @param[in] sem_id binary semaphore id variable
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_BinSemFlush(uint32 sem_id) {
+ syssts_t sts;
+ binary_semaphore_t *bsp = (binary_semaphore_t *)sem_id;
+
+ /* Range check.*/
+ if ((bsp < &osal.binary_semaphores[0]) ||
+ (bsp >= &osal.binary_semaphores[OS_MAX_BIN_SEMAPHORES])) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ /* Entering a reentrant critical zone.*/
+ sts = chSysGetStatusAndLockX();
+
+ /* If the semaphore is not in use then error.*/
+ if (bsp->sem.queue.prev == NULL) {
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+ return OS_SEM_FAILURE;
+ }
+
+ /* If the semaphore state is "not taken" then it is not touched.*/
+ if (bsp->sem.cnt < 0) {
+ chBSemResetI(bsp, true);
+ }
+
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Binary semaphore give.
+ * @note This function can be safely called from timer callbacks or ISRs.
+ *
+ * @param[in] sem_id binary semaphore id variable
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_BinSemGive(uint32 sem_id) {
+ syssts_t sts;
+ binary_semaphore_t *bsp = (binary_semaphore_t *)sem_id;
+
+ /* Range check.*/
+ if ((bsp < &osal.binary_semaphores[0]) ||
+ (bsp >= &osal.binary_semaphores[OS_MAX_BIN_SEMAPHORES])) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ /* Entering a reentrant critical zone.*/
+ sts = chSysGetStatusAndLockX();
+
+ /* If the semaphore is not in use then error.*/
+ if (bsp->sem.queue.prev == NULL) {
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+ return OS_SEM_FAILURE;
+ }
+
+ chBSemSignalI(bsp);
+
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Binary semaphore take.
+ *
+ * @param[in] sem_id binary semaphore id variable
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_BinSemTake(uint32 sem_id) {
+ binary_semaphore_t *bsp = (binary_semaphore_t *)sem_id;
+
+ /* Range check.*/
+ if ((bsp < &osal.binary_semaphores[0]) ||
+ (bsp >= &osal.binary_semaphores[OS_MAX_BIN_SEMAPHORES])) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ chSysLock();
+
+ /* If the semaphore is not in use then error.*/
+ if (bsp->sem.queue.prev == NULL) {
+ chSysUnlock();
+ return OS_SEM_FAILURE;
+ }
+
+ (void) chBSemWaitS(bsp);
+
+ chSysUnlock();
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Binary semaphore take with timeout.
+ *
+ * @param[in] sem_id binary semaphore id variable
+ * @param[in] msecs timeout in milliseconds
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_BinSemTimedWait(uint32 sem_id, uint32 msecs) {
+ binary_semaphore_t *bsp = (binary_semaphore_t *)sem_id;
+ msg_t msg;
+
+ /* Range check.*/
+ if ((bsp < &osal.binary_semaphores[0]) ||
+ (bsp >= &osal.binary_semaphores[OS_MAX_BIN_SEMAPHORES])) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ /* Timeouts of zero not allowed.*/
+ if (msecs == 0) {
+ return OS_INVALID_INT_NUM;
+ }
+
+ chSysLock();
+
+ /* If the semaphore is not in use then error.*/
+ if (bsp->sem.queue.prev == NULL) {
+ chSysUnlock();
+ return OS_SEM_FAILURE;
+ }
+
+ msg = chBSemWaitTimeoutS(bsp, TIME_MS2I(msecs));
+
+ chSysUnlock();
+
+ return msg == MSG_TIMEOUT ? OS_SEM_TIMEOUT : OS_SUCCESS;
+}
+
+/**
+ * @brief Retrieves a binary semaphore id by name.
+ * @note It is not currently implemented.
+ *
+ * @param[out] sem_id pointer to a binary semaphore id variable
+ * @param[in] sem_name the binary semaphore name
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_BinSemGetIdByName(uint32 *sem_id, const char *sem_name) {
+
+ /* NULL pointer checks.*/
+ if ((sem_id == NULL) || (sem_name == NULL)) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Checking name length.*/
+ if (strlen(sem_name) >= OS_MAX_API_NAME) {
+ return OS_ERR_NAME_TOO_LONG;
+ }
+
+ return OS_ERR_NOT_IMPLEMENTED;
+}
+
+/**
+ * @brief Returns binary semaphore information.
+ * @note This function can be safely called from timer callbacks or ISRs.
+ * @note It is not currently implemented.
+ *
+ * @param[in] sem_id binary semaphore id variable
+ * @param[in] bin_prop binary semaphore properties
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_BinSemGetInfo(uint32 sem_id, OS_bin_sem_prop_t *bin_prop) {
+ syssts_t sts;
+ binary_semaphore_t *bsp = (binary_semaphore_t *)sem_id;
+
+ /* NULL pointer checks.*/
+ if (bin_prop == NULL) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Range check.*/
+ if ((bsp < &osal.binary_semaphores[0]) ||
+ (bsp >= &osal.binary_semaphores[OS_MAX_BIN_SEMAPHORES])) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ /* Entering a reentrant critical zone.*/
+ sts = chSysGetStatusAndLockX();
+
+ /* If the semaphore is not in use then error.*/
+ if (bsp->sem.queue.prev == NULL) {
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+ return OS_ERR_INVALID_ID;
+ }
+
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+
+ return OS_ERR_NOT_IMPLEMENTED;
+}
+
+/*-- Counter Semaphore API --------------------------------------------------*/
+
+/**
+ * @brief Counter semaphore creation.
+ *
+ * @param[out] sem_id pointer to a counter semaphore id variable
+ * @param[in] sem_name the counter semaphore name
+ * @param[in] sem_initial_value semaphore initial value
+ * @param[in] options semaphore options
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_CountSemCreate(uint32 *sem_id, const char *sem_name,
+ uint32 sem_initial_value, uint32 options) {
+ semaphore_t *sp;
+
+ (void)options;
+
+ /* NULL pointer checks.*/
+ if ((sem_id == NULL) || (sem_name == NULL)) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Checking semaphore name length.*/
+ if (strlen(sem_name) >= OS_MAX_API_NAME) {
+ return OS_ERR_NAME_TOO_LONG;
+ }
+
+ /* Semaphore counter check, it must be non-negative.*/
+ if ((int32)sem_initial_value < 0) {
+ return OS_INVALID_INT_NUM;
+ }
+
+ /* Getting object.*/
+ sp = chPoolAlloc(&osal.count_semaphores_pool);
+ if (sp == NULL) {
+ return OS_ERR_NO_FREE_IDS;
+ }
+
+ /* Semaphore is initialized.*/
+ chSemObjectInit(sp, (cnt_t)sem_initial_value);
+
+ *sem_id = (uint32)sp;
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Counter semaphore deletion.
+ *
+ * @param[in] sem_id counter semaphore id variable
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_CountSemDelete(uint32 sem_id) {
+ semaphore_t *sp = (semaphore_t *)sem_id;
+
+ /* Range check.*/
+ if ((sp < &osal.count_semaphores[0]) ||
+ (sp >= &osal.count_semaphores[OS_MAX_COUNT_SEMAPHORES])) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ chSysLock();
+
+ /* Resetting the semaphore, no threads in queue.*/
+ chSemResetI(sp, 0);
+
+ /* Flagging it as unused and returning it to the pool.*/
+ sp->queue.prev = NULL;
+ chPoolFreeI(&osal.count_semaphores_pool, (void *)sp);
+
+ /* Required because some thread could have been made ready.*/
+ chSchRescheduleS();
+
+ chSysUnlock();
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Counter semaphore give.
+ * @note This function can be safely called from timer callbacks or ISRs.
+ *
+ * @param[in] sem_id counter semaphore id variable
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_CountSemGive(uint32 sem_id) {
+ syssts_t sts;
+ semaphore_t *sp = (semaphore_t *)sem_id;
+
+ /* Range check.*/
+ if ((sp < &osal.count_semaphores[0]) ||
+ (sp >= &osal.count_semaphores[OS_MAX_COUNT_SEMAPHORES])) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ /* Entering a reentrant critical zone.*/
+ sts = chSysGetStatusAndLockX();
+
+ /* If the semaphore is not in use then error.*/
+ if (sp->queue.prev == NULL) {
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+ return OS_SEM_FAILURE;
+ }
+
+ chSemSignalI(sp);
+
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Counter semaphore take.
+ *
+ * @param[in] sem_id counter semaphore id variable
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_CountSemTake(uint32 sem_id) {
+ semaphore_t *sp = (semaphore_t *)sem_id;
+
+ /* Range check.*/
+ if ((sp < &osal.count_semaphores[0]) ||
+ (sp >= &osal.count_semaphores[OS_MAX_COUNT_SEMAPHORES])) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ chSysLock();
+
+ /* If the semaphore is not in use then error.*/
+ if (sp->queue.prev == NULL) {
+ chSysUnlock();
+ return OS_SEM_FAILURE;
+ }
+
+ (void) chSemWaitS(sp);
+
+ chSysUnlock();
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Counter semaphore take with timeout.
+ *
+ * @param[in] sem_id counter semaphore id variable
+ * @param[in] msecs timeout in milliseconds
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_CountSemTimedWait(uint32 sem_id, uint32 msecs) {
+ semaphore_t *sp = (semaphore_t *)sem_id;
+ msg_t msg;
+
+ /* Range check.*/
+ if ((sp < &osal.count_semaphores[0]) ||
+ (sp >= &osal.count_semaphores[OS_MAX_COUNT_SEMAPHORES])) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ /* Timeouts of zero not allowed.*/
+ if (msecs == 0) {
+ return OS_INVALID_INT_NUM;
+ }
+
+ chSysLock();
+
+ /* If the semaphore is not in use then error.*/
+ if (sp->queue.prev == NULL) {
+ chSysUnlock();
+ return OS_SEM_FAILURE;
+ }
+
+ msg = chSemWaitTimeoutS(sp, TIME_MS2I(msecs));
+
+ chSysUnlock();
+
+ return msg == MSG_TIMEOUT ? OS_SEM_TIMEOUT : OS_SUCCESS;
+}
+
+/**
+ * @brief Retrieves a counter semaphore id by name.
+ * @note It is not currently implemented.
+ *
+ * @param[out] sem_id pointer to a counter semaphore id variable
+ * @param[in] sem_name the counter semaphore name
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_CountSemGetIdByName(uint32 *sem_id, const char *sem_name) {
+
+ /* NULL pointer checks.*/
+ if ((sem_id == NULL) || (sem_name == NULL)) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Checking name length.*/
+ if (strlen(sem_name) >= OS_MAX_API_NAME) {
+ return OS_ERR_NAME_TOO_LONG;
+ }
+
+ return OS_ERR_NOT_IMPLEMENTED;
+}
+
+/**
+ * @brief Returns counter semaphore information.
+ * @note This function can be safely called from timer callbacks or ISRs.
+ * @note It is not currently implemented.
+ *
+ * @param[in] sem_id counter semaphore id variable
+ * @param[in] sem_prop counter semaphore properties
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_CountSemGetInfo(uint32 sem_id, OS_count_sem_prop_t *sem_prop) {
+ syssts_t sts;
+ semaphore_t *sp = (semaphore_t *)sem_id;
+
+ /* NULL pointer checks.*/
+ if (sem_prop == NULL) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Range check.*/
+ if ((sp < &osal.count_semaphores[0]) ||
+ (sp >= &osal.count_semaphores[OS_MAX_BIN_SEMAPHORES])) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ /* Entering a reentrant critical zone.*/
+ sts = chSysGetStatusAndLockX();
+
+ /* If the semaphore is not in use then error.*/
+ if (sp->queue.prev == NULL) {
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+ return OS_ERR_INVALID_ID;
+ }
+
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+
+ return OS_ERR_NOT_IMPLEMENTED;
+}
+
+/*-- Mutex API --------------------------------------------------------------*/
+
+/**
+ * @brief Mutex creation.
+ *
+ * @param[out] sem_id pointer to a mutex id variable
+ * @param[in] sem_name the mutex name
+ * @param[in] options mutex options
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_MutSemCreate(uint32 *sem_id, const char *sem_name, uint32 options) {
+ mutex_t *mp;
+
+ (void)options;
+
+ /* NULL pointer checks.*/
+ if ((sem_id == NULL) || (sem_name == NULL)) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Checking semaphore name length.*/
+ if (strlen(sem_name) >= OS_MAX_API_NAME) {
+ return OS_ERR_NAME_TOO_LONG;
+ }
+
+ /* Getting object.*/
+ mp = chPoolAlloc(&osal.mutexes_pool);
+ if (mp == NULL) {
+ return OS_ERR_NO_FREE_IDS;
+ }
+
+ /* Semaphore is initialized.*/
+ chMtxObjectInit(mp);
+
+ *sem_id = (uint32)mp;
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Mutex deletion.
+ *
+ * @param[in] sem_id mutex id variable
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_MutSemDelete(uint32 sem_id) {
+ mutex_t *mp = (mutex_t *)sem_id;
+
+ /* Range check.*/
+ if ((mp < &osal.mutexes[0]) ||
+ (mp >= &osal.mutexes[OS_MAX_MUTEXES])) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ chSysLock();
+
+ /* Resetting the mutex, no threads in queue.*/
+ chMtxUnlockAllS();
+
+ /* Flagging it as unused and returning it to the pool.*/
+ mp->queue.prev = NULL;
+ chPoolFreeI(&osal.mutexes_pool, (void *)mp);
+
+ /* Required because some thread could have been made ready.*/
+ chSchRescheduleS();
+
+ chSysUnlock();
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Mutex give.
+ *
+ * @param[in] sem_id mutex id variable
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_MutSemGive(uint32 sem_id) {
+ mutex_t *mp = (mutex_t *)sem_id;
+
+ /* Range check.*/
+ if ((mp < &osal.mutexes[0]) ||
+ (mp >= &osal.mutexes[OS_MAX_COUNT_SEMAPHORES])) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ chSysLock();
+
+ /* If the mutex is not in use then error.*/
+ if (mp->queue.prev == NULL) {
+ chSysUnlock();
+ return OS_SEM_FAILURE;
+ }
+
+ chMtxUnlockS(mp);
+ chSchRescheduleS();
+
+ chSysUnlock();
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Mutex take.
+ *
+ * @param[in] sem_id mutex id variable
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_MutSemTake(uint32 sem_id) {
+ mutex_t *mp = (mutex_t *)sem_id;
+
+ /* Range check.*/
+ if ((mp < &osal.mutexes[0]) ||
+ (mp >= &osal.mutexes[OS_MAX_COUNT_SEMAPHORES])) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ chSysLock();
+
+ /* If the mutex is not in use then error.*/
+ if (mp->queue.prev == NULL) {
+ chSysUnlock();
+ return OS_SEM_FAILURE;
+ }
+
+ chMtxLockS(mp);
+
+ chSysUnlock();
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Retrieves a mutex id by name.
+ * @note It is not currently implemented.
+ *
+ * @param[out] sem_id pointer to a mutex id variable
+ * @param[in] sem_name the mutex name
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_MutSemGetIdByName(uint32 *sem_id, const char *sem_name) {
+
+ /* NULL pointer checks.*/
+ if ((sem_id == NULL) || (sem_name == NULL)) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Checking name length.*/
+ if (strlen(sem_name) >= OS_MAX_API_NAME) {
+ return OS_ERR_NAME_TOO_LONG;
+ }
+
+ return OS_ERR_NOT_IMPLEMENTED;
+}
+
+/**
+ * @brief Returns mutex information.
+ * @note This function can be safely called from timer callbacks or ISRs.
+ * @note It is not currently implemented.
+ *
+ * @param[in] sem_id mutex id variable
+ * @param[in] sem_prop mutex properties
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_MutSemGetInfo(uint32 sem_id, OS_mut_sem_prop_t *sem_prop) {
+ syssts_t sts;
+ mutex_t *mp = (mutex_t *)sem_id;
+
+ /* NULL pointer checks.*/
+ if (sem_prop == NULL) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Range check.*/
+ if ((mp < &osal.mutexes[0]) ||
+ (mp >= &osal.mutexes[OS_MAX_BIN_SEMAPHORES])) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ /* Entering a reentrant critical zone.*/
+ sts = chSysGetStatusAndLockX();
+
+ /* If the mutex is not in use then error.*/
+ if (mp->queue.prev == NULL) {
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+ return OS_ERR_INVALID_ID;
+ }
+
+ /* Leaving the critical zone.*/
+ chSysRestoreStatusX(sts);
+
+ return OS_ERR_NOT_IMPLEMENTED;
+}
+
+/*-- Task Control API -------------------------------------------------------*/
+
+/**
+ * @brief Task creation.
+ * @note The task name is not copied inside the task but kept by reference,
+ * the name is supposed to be persistent, better if defined as a
+ * sting constant.
+ *
+ * @param[out] task_id pointer to a task id variable
+ * @param[in] task_name the task name
+ * @param[in] function_pointer the task function
+ * @param[in] stack_pointer base of stack area
+ * @param[in] stack_size size of stack area
+ * @param[in] priority the task priority
+ * @param[in] flags task attributes
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_TaskCreate(uint32 *task_id,
+ const char *task_name,
+ osal_task_entry function_pointer,
+ const uint32 *stack_pointer,
+ uint32 stack_size,
+ uint32 priority,
+ uint32 flags) {
+ tprio_t rt_prio;
+ thread_t *tp;
+
+ (void)flags;
+
+ /* NULL pointer checks.*/
+ if ((task_id == NULL) || (task_name == NULL) ||
+ (function_pointer == NULL) || (stack_pointer == NULL)) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Checking alignment of stack base and size, it is application
+ responsibility to pass correct values.*/
+ if (!MEM_IS_ALIGNED(stack_pointer, PORT_WORKING_AREA_ALIGN) ||
+ !MEM_IS_ALIGNED(stack_size, sizeof (stkalign_t))) {
+ return OS_ERROR_ADDRESS_MISALIGNED;
+ }
+
+ /* Checking task name length.*/
+ if (strlen(task_name) >= OS_MAX_API_NAME) {
+ return OS_ERR_NAME_TOO_LONG;
+ }
+
+ /* Checking priority range.*/
+ if ((priority < MIN_PRIORITY) || (priority > MAX_PRIORITY)) {
+ return OS_ERR_INVALID_PRIORITY;
+ }
+
+ /* Checking if the specified stack size is below the bare minimum.*/
+ if (stack_size < (uint32)THD_WORKING_AREA_SIZE(0)) {
+ return OS_INVALID_INT_NUM;
+ }
+
+ /* Checking if this working area is already in use by some thread, the
+ error code is not very appropriate but this case seems to not be
+ coveded by the specification.*/
+ tp = chRegFindThreadByWorkingArea((stkalign_t *)stack_pointer);
+ if (tp != NULL) {
+ /* Releasing the thread reference.*/
+ chThdRelease(tp);
+ return OS_ERR_NO_FREE_IDS;
+ }
+
+ /* Checking if the name is already in use.*/
+ if ((tp = chRegFindThreadByName(task_name)) != NULL) {
+ /* Releasing the thread reference.*/
+ chThdRelease(tp);
+ return OS_ERR_NAME_TAKEN;
+ }
+
+ /* Converting priority to RT type.*/
+ rt_prio = (tprio_t)256 - (tprio_t)priority;
+ if (rt_prio == 1) {
+ rt_prio = 2;
+ }
+
+ thread_descriptor_t td = {
+ task_name,
+ (stkalign_t *)stack_pointer,
+ (stkalign_t *)((uint8_t *)stack_pointer + stack_size),
+ rt_prio,
+ (tfunc_t)(void *)function_pointer,
+ NULL
+ };
+
+ /* Creating the task and detaching it, other APIs will have to gain a
+ reference using the registry API.*/
+ tp = chThdCreate(&td);
+ chThdRelease(tp);
+
+ /* Storing the task id.*/
+ *task_id = (uint32)tp;
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Installs a deletion handler.
+ * @note It is implemented as hooks in chconf.h.
+ *
+ * @param[in] function_pointer the handler function
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_TaskInstallDeleteHandler(void *function_pointer) {
+
+ chThdGetSelfX()->osal_delete_handler = function_pointer;
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Check for task termination request.
+ * @note This is a ChibiOS/RT extension, direct task delete is not
+ * allowed in RT.
+ *
+ * @return The termination request flag.
+ * @retval false if termination has not been requested.
+ * @retval true if termination has been requested.
+ *
+ * @api
+ */
+boolean OS_TaskDeleteCheck(void) {
+
+ return (boolean)chThdShouldTerminateX();
+}
+
+/**
+ * @brief Task delete.
+ * @note Limitation, it does not actually kill the thread, it just sets a
+ * flag in the thread that has then to terminate voluntarily. The
+ * flag can be checked using @p chThdShouldTerminateX().
+ *
+ * @param[in] task_id the task id
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_TaskDelete(uint32 task_id) {
+ thread_t *tp = (thread_t *)task_id;
+ funcptr_t fp;
+
+ /* Check for thread validity, getting a reference.*/
+ if (chRegFindThreadByPointer(tp) == NULL) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ /* Asking for thread termination.*/
+ chThdTerminate(tp);
+
+ /* Getting the delete handler while the thread is still referenced.*/
+ fp = (funcptr_t)tp->osal_delete_handler;
+
+ /* Waiting for termination, releasing the reference.*/
+ chThdWait(tp);
+
+ /* Calling the delete handler, if defined.*/
+ if (fp != NULL) {
+ fp();
+ }
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Task exit.
+ *
+ * @api
+ */
+void OS_TaskExit(void) {
+
+ chThdExit(MSG_OK);
+}
+
+/**
+ * @brief Wait for task termination.
+ * @note This is a ChibiOS/RT extension, added for improved testability.
+ *
+ * @param[in] task_id the task id
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_TaskWait(uint32 task_id) {
+ thread_t *tp = (thread_t *)task_id;
+
+ /* Check for thread validity, getting a reference.*/
+ if (chRegFindThreadByPointer(tp) == NULL) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ (void) chThdWait(tp);
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Task delay.
+ *
+ * @param[in] milli_second the period in miliseconds
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_TaskDelay(uint32 milli_second) {
+
+ chThdSleepMilliseconds(milli_second);
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Change task priority.
+ * @note Priority 255 is not available and it is transformed internally in
+ * 254.
+ *
+ * @param[in] task_id the task id
+ * @param[in] new_priority the task new priority
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_TaskSetPriority(uint32 task_id, uint32 new_priority) {
+ tprio_t rt_newprio;
+ thread_t *tp = (thread_t *)task_id;
+
+ /* Checking priority range.*/
+ if ((new_priority < MIN_PRIORITY) || (new_priority > MAX_PRIORITY)) {
+ return OS_ERR_INVALID_PRIORITY;
+ }
+
+ /* Converting priority to RT type.*/
+ rt_newprio = (tprio_t)256 - (tprio_t)new_priority;
+ if (rt_newprio == 1) {
+ rt_newprio = 2;
+ }
+
+ if (chThdGetPriorityX() == rt_newprio) {
+ return OS_SUCCESS;
+ }
+
+ /* Check for thread validity.*/
+ if (chRegFindThreadByPointer(tp) == NULL) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ chSysLock();
+
+ /* Changing priority.*/
+ if ((tp->prio == tp->realprio) || (rt_newprio > tp->prio)) {
+ tp->prio = rt_newprio;
+ }
+ tp->realprio = rt_newprio;
+
+ /* The following states need priority queues reordering.*/
+ switch (tp->state) {
+ case CH_STATE_WTMTX:
+#if CH_CFG_USE_CONDVARS
+ case CH_STATE_WTCOND:
+#endif
+#if CH_CFG_USE_SEMAPHORES_PRIORITY
+ case CH_STATE_WTSEM:
+#endif
+#if CH_CFG_USE_MESSAGES && CH_CFG_USE_MESSAGES_PRIORITY
+ case CH_STATE_SNDMSGQ:
+#endif
+ /* Re-enqueues tp with its new priority on the queue.*/
+ queue_prio_insert(queue_dequeue(tp),
+ (threads_queue_t *)tp->u.wtobjp);
+ break;
+ case CH_STATE_READY:
+#if CH_DBG_ENABLE_ASSERTS
+ /* Prevents an assertion in chSchReadyI().*/
+ tp->state = CH_STATE_CURRENT;
+#endif
+ /* Re-enqueues tp with its new priority on the ready list.*/
+ chSchReadyI(queue_dequeue(tp));
+ break;
+ }
+
+ /* Rescheduling.*/
+ chSchRescheduleS();
+ chSysUnlock();
+
+ /* Releasing the thread reference.*/
+ chThdRelease(tp);
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Task registration.
+ * @note In ChibiOS/RT it does nothing.
+ *
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_TaskRegister(void) {
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Current task id.
+ * @note This function can be safely called from timer callbacks or ISRs.
+ *
+ * @return The current task id.
+ *
+ * @api
+ */
+uint32 OS_TaskGetId(void) {
+
+ return (uint32)chThdGetSelfX();
+}
+
+/**
+ * @brief Retrieves a task id by name.
+ *
+ * @param[out] task_id pointer to a task id variable
+ * @param[in] task_name the task name
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_TaskGetIdByName(uint32 *task_id, const char *task_name) {
+ thread_t *tp;
+
+ /* NULL pointer checks.*/
+ if ((task_id == NULL) || (task_name == NULL)) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Checking task name length.*/
+ if (strlen(task_name) >= OS_MAX_API_NAME) {
+ return OS_ERR_NAME_TOO_LONG;
+ }
+
+ /* Searching in the registry.*/
+ tp = chRegFindThreadByName(task_name);
+ if (tp == NULL) {
+ return OS_ERR_NAME_NOT_FOUND;
+ }
+
+ *task_id = (uint32)tp;
+
+ /* Releasing the thread reference.*/
+ chThdRelease(tp);
+
+ return OS_SUCCESS;
+}
+
+/**
+ * @brief Returns task information.
+ * @note This function can be safely called from timer callbacks or ISRs.
+ * @note Priority 255 is not available and it is transformed internally in
+ * 254.
+ *
+ * @param[in] task_id the task id
+ * @param[in] task_prop task properties
+ * @return An error code.
+ *
+ * @api
+ */
+int32 OS_TaskGetInfo(uint32 task_id, OS_task_prop_t *task_prop) {
+ thread_t *tp = (thread_t *)task_id;
+ size_t wasize = (size_t)tp - (size_t)tp->wabase + sizeof (thread_t);
+
+ /* NULL pointer checks.*/
+ if (task_prop == NULL) {
+ return OS_INVALID_POINTER;
+ }
+
+ /* Check for thread validity.*/
+ if (chRegFindThreadByPointer(tp) == NULL) {
+ return OS_ERR_INVALID_ID;
+ }
+
+ strncpy(task_prop->name, tp->name, OS_MAX_API_NAME - 1);
+ task_prop->creator = (uint32)chSysGetIdleThreadX();
+ task_prop->stack_size = (uint32)MEM_ALIGN_NEXT(wasize, PORT_STACK_ALIGN);
+ task_prop->priority = (uint32)256U - (uint32)tp->realprio;
+ task_prop->OStask_id = task_id;
+
+ /* Releasing the thread reference.*/
+ chThdRelease(tp);
+
+ return OS_SUCCESS;
+}
+
+/*-- System Interrupt API ---------------------------------------------------*/
+
+/* In ChibiOS interrupts are statically linked, the vectors table is in
+ flash.*/
+int32 OS_IntAttachHandler (uint32 InterruptNumber,
+ osal_task_entry InterruptHandler,
+ int32 parameter) {
+ (void)InterruptNumber;
+ (void)parameter;
+
+ /* NULL pointer checks.*/
+ if (InterruptHandler == NULL) {
+ return OS_INVALID_POINTER;
+ }
+
+ return OS_ERR_NOT_IMPLEMENTED;
+}
+
+int32 OS_IntLock(void) {
+
+ return (int32)chSysGetStatusAndLockX();
+}
+
+int32 OS_IntUnlock(int32 IntLevel) {
+
+ chSysRestoreStatusX((syssts_t) IntLevel);
+
+ return OS_SUCCESS;
+}
+
+int32 OS_IntEnable(int32 Level) {
+
+ NVIC_EnableIRQ((IRQn_Type)Level);
+
+ return OS_SUCCESS;
+}
+
+int32 OS_IntDisable(int32 Level) {
+
+ NVIC_DisableIRQ((IRQn_Type)Level);
+
+ return OS_SUCCESS;
+}
+
+int32 OS_IntAck(int32 InterruptNumber) {
+
+ NVIC_ClearPendingIRQ((IRQn_Type)InterruptNumber);
+
+ return OS_SUCCESS;
+}
+
+/*-- System Exception API ---------------------------------------------------*/
+
+/* In ChibiOS exceptions are statically linked, the vectors table is in
+ flash.*/
+int32 OS_ExcAttachHandler(uint32 ExceptionNumber,
+ void (*ExceptionHandler)(uint32, uint32 *,uint32),
+ int32 parameter) {
+
+ (void)ExceptionNumber;
+ (void)parameter;
+
+ /* NULL pointer checks.*/
+ if (ExceptionHandler == NULL) {
+ return OS_INVALID_POINTER;
+ }
+
+ return OS_ERR_NOT_IMPLEMENTED;
+}
+
+/* No exceptions masking.*/
+int32 OS_ExcEnable(int32 ExceptionNumber) {
+
+ (void)ExceptionNumber;
+
+ return OS_ERR_NOT_IMPLEMENTED;
+}
+
+/* No exceptions masking.*/
+int32 OS_ExcDisable(int32 ExceptionNumber) {
+
+ (void)ExceptionNumber;
+
+ return OS_ERR_NOT_IMPLEMENTED;
+}
+
+/*-- Floating Point Unit API ------------------------------------------------*/
+
+/* In ChibiOS exceptions are statically linked, the vectors table is in
+ flash.*/
+int32 OS_FPUExcAttachHandler(uint32 ExceptionNumber,
+ void * ExceptionHandler ,
+ int32 parameter) {
+
+ (void)ExceptionNumber;
+ (void)parameter;
+
+ /* NULL pointer checks.*/
+ if (ExceptionHandler == NULL) {
+ return OS_INVALID_POINTER;
+ }
+
+ return OS_ERR_NOT_IMPLEMENTED;
+}
+
+int32 OS_FPUExcEnable(int32 ExceptionNumber) {
+
+ (void)ExceptionNumber;
+
+ return OS_ERR_NOT_IMPLEMENTED;
+}
+
+int32 OS_FPUExcDisable(int32 ExceptionNumber) {
+
+ (void)ExceptionNumber;
+
+ return OS_ERR_NOT_IMPLEMENTED;
+}
+
+int32 OS_FPUExcSetMask(uint32 mask) {
+
+ (void)mask;
+
+ return OS_ERR_NOT_IMPLEMENTED;
+}
+
+int32 OS_FPUExcGetMask(uint32 *mask) {
+
+ (void)mask;
+
+ return OS_ERR_NOT_IMPLEMENTED;
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/cfe_psp.mk b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/cfe_psp.mk
new file mode 100644
index 0000000..0409c3f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/cfe_psp.mk
@@ -0,0 +1,11 @@
+# NASA CFE PSP files.
+CFEPSPSRC = $(CHIBIOS)/os/common/abstractions/nasa_cfe/psp/src/cfe_psp_support.c \
+ $(CHIBIOS)/os/common/abstractions/nasa_cfe/psp/src/cfe_psp_timer.c \
+ $(CHIBIOS)/os/common/abstractions/nasa_cfe/psp/src/cfe_psp_memory.c \
+ $(CHIBIOS)/os/common/abstractions/nasa_cfe/psp/src/cfe_psp_exception.c
+
+CFEPSPINC = $(CHIBIOS)/os/common/abstractions/nasa_cfe/psp/include
+
+# Shared variables
+ALLCSRC += $(CFEPSPSRC)
+ALLINC += $(CFEPSPINC)
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/include/cfe_psp.h b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/include/cfe_psp.h
new file mode 100644
index 0000000..402064c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/include/cfe_psp.h
@@ -0,0 +1,375 @@
+/*
+** File Name: cfe_psp.h
+**
+** Copyright (c) 2004-2006, United States government as represented by the
+** administrator of the National Aeronautics Space Administration.
+** All rights reserved. This software(cFE) was created at NASA's Goddard
+** Space Flight Center pursuant to government contracts.
+**
+** This software may be used only pursuant to a United States government
+** sponsored project and the United States government may not be charged
+** for use thereof.
+**
+** Author: A. Cudmore
+**
+** Purpose: This file contains the cFE Platform Support Package(PSP)
+** prototypes.
+** The PSP routines serve as the "glue" between the RTOS and
+** the cFE Flight Software. The routines fill gaps that are not
+** really considered part of the OS Abstraction, but are required
+** for the cFE flight software implementation. It is possible that
+** some of these routines could migrate into the OS AL.
+**
+** $Log: cfe_psp.h $
+** Revision 1.3 2009/07/29 12:04:46GMT-05:00 acudmore
+** Added Bank parameter to EEPROM Power up/down and EEPROM write enable/disable functions.
+** Revision 1.2 2009/07/22 17:34:10EDT acudmore
+** Added new watchdog API
+** Revision 1.1 2009/06/10 09:28:44EDT acudmore
+** Initial revision
+** Member added to project c:/MKSDATA/MKS-REPOSITORY/CFE-PSP-REPOSITORY/fsw/inc/project.pj
+**
+*/
+
+#ifndef _cfe_psp_
+#define _cfe_psp_
+
+/*
+** Include Files
+*/
+
+#include "common_types.h"
+#include "osapi.h"
+#include "cfe_psp_config.h"
+#include "psp_version.h"
+
+/*
+** Macro Definitions
+*/
+
+/*
+** Error and return codes
+*/
+#define CFE_PSP_SUCCESS (0)
+#define CFE_PSP_ERROR (-1)
+#define CFE_PSP_INVALID_POINTER (-2)
+#define CFE_PSP_ERROR_ADDRESS_MISALIGNED (-3)
+#define CFE_PSP_ERROR_TIMEOUT (-4)
+#define CFE_PSP_INVALID_INT_NUM (-5)
+#define CFE_PSP_INVALID_MEM_ADDR (-21)
+#define CFE_PSP_INVALID_MEM_TYPE (-22)
+#define CFE_PSP_INVALID_MEM_RANGE (-23)
+#define CFE_PSP_INVALID_MEM_WORDSIZE (-24)
+#define CFE_PSP_INVALID_MEM_SIZE (-25)
+#define CFE_PSP_INVALID_MEM_ATTR (-26)
+#define CFE_PSP_ERROR_NOT_IMPLEMENTED (-27)
+
+
+
+/*
+** Definitions for PSP PANIC types
+*/
+#define CFE_PSP_PANIC_STARTUP 1
+#define CFE_PSP_PANIC_VOLATILE_DISK 2
+#define CFE_PSP_PANIC_MEMORY_ALLOC 3
+#define CFE_PSP_PANIC_NONVOL_DISK 4
+#define CFE_PSP_PANIC_STARTUP_SEM 5
+#define CFE_PSP_PANIC_CORE_APP 6
+#define CFE_PSP_PANIC_GENERAL_FAILURE 7
+
+/*
+** Macros for the file loader
+*/
+#define BUFF_SIZE 256
+#define SIZE_BYTE 1
+#define SIZE_HALF 2
+#define SIZE_WORD 3
+
+/*
+** Define memory types
+*/
+#define CFE_PSP_MEM_RAM 1
+#define CFE_PSP_MEM_EEPROM 2
+#define CFE_PSP_MEM_ANY 3
+#define CFE_PSP_MEM_INVALID 4
+
+/*
+** Define Memory Read/Write Attributes
+*/
+#define CFE_PSP_MEM_ATTR_WRITE 0x01
+#define CFE_PSP_MEM_ATTR_READ 0x02
+#define CFE_PSP_MEM_ATTR_READWRITE 0x03
+
+/*
+** Define the Memory Word Sizes
+*/
+#define CFE_PSP_MEM_SIZE_BYTE 0x01
+#define CFE_PSP_MEM_SIZE_WORD 0x02
+#define CFE_PSP_MEM_SIZE_DWORD 0x04
+
+/*
+** Type Definitions
+*/
+
+/*
+** Memory table type
+*/
+typedef struct
+{
+ uint32 MemoryType;
+ uint32 WordSize;
+ uint32 StartAddr;
+ uint32 Size;
+ uint32 Attributes;
+} CFE_PSP_MemTable_t;
+
+/*
+** Function prototypes
+*/
+
+/*
+** PSP entry point and reset routines
+*/
+extern void CFE_PSP_Main(int ModeId, char *StartupFilePath);
+
+/*
+** CFE_PSP_Main is the entry point that the real time OS calls to start our
+** software. This routine will do any BSP/OS specific setup, then call the
+** entrypoint of the flight software ( i.e. the cFE main entry point ).
+** The flight software (i.e. cFE ) should not call this routine.
+*/
+
+extern void CFE_PSP_GetTime(OS_time_t *LocalTime);
+/* This call gets the local time from the hardware on the Vxworks system
+ * on the mcp750s
+ * on the other os/hardware setup, it will get the time the normal way */
+
+
+extern void CFE_PSP_Restart(uint32 resetType);
+/*
+** CFE_PSP_Restart is the entry point back to the BSP to restart the processor.
+** The flight software calls this routine to restart the processor.
+*/
+
+
+extern uint32 CFE_PSP_GetRestartType(uint32 *restartSubType );
+/*
+** CFE_PSP_GetRestartType returns the last reset type and if a pointer to a valid
+** memory space is passed in, it returns the reset sub-type in that memory.
+** Right now the reset types are application specific. For the cFE they
+** are defined in the cfe_es.h file.
+*/
+
+
+extern void CFE_PSP_FlushCaches(uint32 type, uint32 address, uint32 size);
+/*
+** This is a BSP specific cache flush routine
+*/
+
+extern uint32 CFE_PSP_GetProcessorId ( void );
+/*
+** CFE_PSP_GetProcessorId returns the CPU ID as defined by the specific board
+** and BSP.
+*/
+
+
+extern uint32 CFE_PSP_GetSpacecraftId ( void );
+/*
+** CFE_PSP_GetSpacecraftId retuns the Spacecraft ID (if any )
+*/
+
+
+extern uint32 CFE_PSP_Get_Timer_Tick(void);
+/*
+** CFE_PSP_Get_Timer_Tick returns the underlying OS timer tick value
+** It is used for the performance monitoring software
+*/
+
+extern uint32 CFE_PSP_GetTimerTicksPerSecond(void);
+/*
+** CFE_PSP_GetTimerTicksPerSecond provides the resolution of the least significant
+** 32 bits of the 64 bit time stamp returned by CFE_PSP_Get_Timebase in timer
+** ticks per second. The timer resolution for accuracy should not be any slower
+** than 1000000 ticks per second or 1 us per tick
+*/
+
+extern uint32 CFE_PSP_GetTimerLow32Rollover(void);
+/*
+** CFE_PSP_GetTimerLow32Rollover provides the number that the least significant
+** 32 bits of the 64 bit time stamp returned by CFE_PSP_Get_Timebase rolls over.
+** If the lower 32 bits rolls at 1 second, then the CFE_PSP_TIMER_LOW32_ROLLOVER
+** will be 1000000. if the lower 32 bits rolls at its maximum value (2^32) then
+** CFE_PSP_TIMER_LOW32_ROLLOVER will be 0.
+*/
+
+extern void CFE_PSP_Get_Timebase(uint32 *Tbu, uint32 *Tbl);
+/*
+** CFE_PSP_Get_Timebase
+*/
+
+extern uint32 CFE_PSP_Get_Dec(void);
+/*
+** CFE_PSP_Get_Dec
+*/
+
+
+extern int32 CFE_PSP_InitProcessorReservedMemory(uint32 RestartType );
+/*
+** CFE_PSP_InitProcessorReservedMemory initializes all of the memory in the
+** BSP that is preserved on a processor reset. The memory includes the
+** Critical Data Store, the ES Reset Area, the Volatile Disk Memory, and
+** the User Reserved Memory. In general, the memory areas will be initialized
+** ( cleared ) on a Power On reset, and preserved during a processor reset.
+*/
+
+extern int32 CFE_PSP_GetCDSSize(uint32 *SizeOfCDS);
+/*
+** CFE_PSP_GetCDSSize fetches the size of the OS Critical Data Store area.
+*/
+
+extern int32 CFE_PSP_WriteToCDS(void *PtrToDataToWrite, uint32 CDSOffset, uint32 NumBytes);
+/*
+** CFE_PSP_WriteToCDS writes to the CDS Block.
+*/
+
+extern int32 CFE_PSP_ReadFromCDS(void *PtrToDataToRead, uint32 CDSOffset, uint32 NumBytes);
+/*
+** CFE_PSP_ReadFromCDS reads from the CDS Block
+*/
+
+extern int32 CFE_PSP_GetResetArea (void *PtrToResetArea, uint32 *SizeOfResetArea);
+/*
+** CFE_PSP_GetResetArea returns the location and size of the ES Reset information area.
+** This area is preserved during a processor reset and is used to store the
+** ER Log, System Log and reset related variables
+*/
+
+extern int32 CFE_PSP_GetUserReservedArea(void *PtrToUserArea, uint32 *SizeOfUserArea );
+/*
+** CFE_PSP_GetUserReservedArea returns the location and size of the memory used for the cFE
+** User reserved area.
+*/
+
+extern int32 CFE_PSP_GetVolatileDiskMem(void *PtrToVolDisk, uint32 *SizeOfVolDisk );
+/*
+** CFE_PSP_GetVolatileDiskMem returns the location and size of the memory used for the cFE
+** volatile disk.
+*/
+
+extern int32 CFE_PSP_GetKernelTextSegmentInfo(void *PtrToKernelSegment, uint32 *SizeOfKernelSegment);
+/*
+** CFE_PSP_GetKernelTextSegmentInfo returns the location and size of the kernel memory.
+*/
+
+extern int32 CFE_PSP_GetCFETextSegmentInfo(void *PtrToCFESegment, uint32 *SizeOfCFESegment);
+/*
+** CFE_PSP_GetCFETextSegmentInfo returns the location and size of the kernel memory.
+*/
+
+extern void CFE_PSP_WatchdogInit(void);
+/*
+** CFE_PSP_WatchdogInit configures the watchdog timer.
+*/
+
+extern void CFE_PSP_WatchdogEnable(void);
+/*
+** CFE_PSP_WatchdogEnable enables the watchdog timer.
+*/
+
+extern void CFE_PSP_WatchdogDisable(void);
+/*
+** CFE_PSP_WatchdogDisable disables the watchdog timer.
+*/
+
+extern void CFE_PSP_WatchdogService(void);
+/*
+** CFE_PSP_WatchdogService services the watchdog timer according to the
+** value set in WatchDogSet.
+*/
+
+extern uint32 CFE_PSP_WatchdogGet(void);
+/*
+** CFE_PSP_WatchdogGet gets the watchdog time in milliseconds
+*/
+
+extern void CFE_PSP_WatchdogSet(uint32 WatchdogValue);
+/*
+** CFE_PSP_WatchdogSet sets the watchdog time in milliseconds
+*/
+
+extern void CFE_PSP_Panic(int32 ErrorCode);
+/*
+** CFE_PSP_Panic is called by the cFE Core startup code when it needs to abort the
+** cFE startup. This should not be called by applications.
+*/
+
+extern int32 CFE_PSP_InitSSR(uint32 bus, uint32 device, char *DeviceName );
+/*
+** CFE_PSP_InitSSR will initialize the Solid state recorder memory for a particular platform
+*/
+
+extern int32 CFE_PSP_Decompress( char * srcFileName, char * dstFileName );
+/*
+** CFE_PSP_Decompress will uncompress the source file to the file specified in the
+** destination file name. The Decompress uses the "gzip" algorithm. Files can
+** be compressed using the "gzip" program available on almost all host platforms.
+*/
+
+extern void CFE_PSP_AttachExceptions(void);
+/*
+** CFE_PSP_AttachExceptions will setup the exception environment for the chosen platform
+** On a board, this can be configured to look at a debug flag or switch in order to
+** keep the standard OS exeption handlers, rather than restarting the system
+*/
+
+
+extern void CFE_PSP_SetDefaultExceptionEnvironment(void);
+/*
+**
+** CFE_PSP_SetDefaultExceptionEnvironment defines the CPU and FPU exceptions that are enabled for each cFE Task/App
+**
+** Notes: The exception environment is local to each task Therefore this must be
+** called for each task that that wants to do floating point and catch exceptions
+*/
+
+
+/*
+** I/O Port API
+*/
+int32 CFE_PSP_PortRead8 (uint32 PortAddress, uint8 *ByteValue);
+int32 CFE_PSP_PortWrite8 (uint32 PortAddress, uint8 ByteValue);
+int32 CFE_PSP_PortRead16 (uint32 PortAddress, uint16 *uint16Value);
+int32 CFE_PSP_PortWrite16 (uint32 PortAddress, uint16 uint16Value);
+int32 CFE_PSP_PortRead32 (uint32 PortAddress, uint32 *uint32Value);
+int32 CFE_PSP_PortWrite32 (uint32 PortAddress, uint32 uint32Value);
+
+/*
+** Memory API
+*/
+int32 CFE_PSP_MemRead8 (uint32 MemoryAddress, uint8 *ByteValue);
+int32 CFE_PSP_MemWrite8 (uint32 MemoryAddress, uint8 ByteValue);
+int32 CFE_PSP_MemRead16 (uint32 MemoryAddress, uint16 *uint16Value);
+int32 CFE_PSP_MemWrite16 (uint32 MemoryAddress, uint16 uint16Value);
+int32 CFE_PSP_MemRead32 (uint32 MemoryAddress, uint32 *uint32Value);
+int32 CFE_PSP_MemWrite32 (uint32 MemoryAddress, uint32 uint32Value);
+
+int32 CFE_PSP_MemCpy (void *dest, void *src, uint32 n);
+int32 CFE_PSP_MemSet (void *dest, uint8 value, uint32 n);
+
+int32 CFE_PSP_MemValidateRange (uint32 Address, uint32 Size, uint32 MemoryType);
+uint32 CFE_PSP_MemRanges (void);
+int32 CFE_PSP_MemRangeSet (uint32 RangeNum, uint32 MemoryType, uint32 StartAddr,
+ uint32 Size, uint32 WordSize, uint32 Attributes);
+int32 CFE_PSP_MemRangeGet (uint32 RangeNum, uint32 *MemoryType, uint32 *StartAddr,
+ uint32 *Size, uint32 *WordSize, uint32 *Attributes);
+
+int32 CFE_PSP_EepromWrite8 (uint32 MemoryAddress, uint8 ByteValue);
+int32 CFE_PSP_EepromWrite16 (uint32 MemoryAddress, uint16 uint16Value);
+int32 CFE_PSP_EepromWrite32 (uint32 MemoryAddress, uint32 uint32Value);
+
+int32 CFE_PSP_EepromWriteEnable (uint32 Bank);
+int32 CFE_PSP_EepromWriteDisable(uint32 Bank);
+int32 CFE_PSP_EepromPowerUp (uint32 Bank);
+int32 CFE_PSP_EepromPowerDown (uint32 Bank);
+
+#endif /* _cfe_psp_ */
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/include/cfe_psp_config.h b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/include/cfe_psp_config.h
new file mode 100644
index 0000000..0967e07
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/include/cfe_psp_config.h
@@ -0,0 +1,21 @@
+/*
+** cfe_psp_config.h
+**
+** Copyright (c) 2004-2006, United States government as represented by the
+** administrator of the National Aeronautics Space Administration.
+** All rights reserved. This software(cFE) was created at NASA Goddard
+** Space Flight Center pursuant to government contracts.
+**
+** This software may be used only pursuant to a United States government
+** sponsored project and the United States government may not be charged
+** for use thereof.
+**
+**
+*/
+
+#ifndef _cfe_psp_config_
+#define _cfe_psp_config_
+
+#include "common_types.h"
+
+#endif /* _cfe_psp_config_ */
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/include/psp_version.h b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/include/psp_version.h
new file mode 100644
index 0000000..c5374c4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/include/psp_version.h
@@ -0,0 +1,38 @@
+/*
+** $Id: psp_version.h 1.2.2.3 2014/10/01 15:41:27GMT-05:00 sstrege Exp $
+**
+**
+** Copyright (c) 2004-2006, United States government as represented by the
+** administrator of the National Aeronautics Space Administration.
+** All rights reserved. This software(cFE) was created at NASA's Goddard
+** Space Flight Center pursuant to government contracts.
+**
+** This software may be used only pursuant to a United States government
+** sponsored project and the United States government may not be charged
+** for use thereof.
+**
+**
+**
+** Purpose:
+** Provide version identifiers for the cFE Platform Support Packages (PSP).
+**
+*/
+
+#ifndef _psp_version_
+#define _psp_version_
+
+
+/*
+** Macro Definitions
+*/
+#define CFE_PSP_MAJOR_VERSION 1
+#define CFE_PSP_MINOR_VERSION 2
+#define CFE_PSP_REVISION 0
+#define CFE_PSP_MISSION_REV 0
+
+/* For backwards compatibility */
+#define CFE_PSP_SUBMINOR_VERSION CFE_PSP_REVISION
+
+
+#endif /* _psp_version_ */
+
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/src/cfe_psp_exception.c b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/src/cfe_psp_exception.c
new file mode 100644
index 0000000..47dfe42
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/src/cfe_psp_exception.c
@@ -0,0 +1,60 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file cfe_psp_exception.c
+ * @brief CFE PSP exception module code.
+ *
+ * @addtogroup nasa_cfe_psp_exception
+ * @{
+ */
+
+#include "ch.h"
+
+#include "common_types.h"
+#include "osapi.h"
+#include "cfe_psp.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+void CFE_PSP_SetDefaultExceptionEnvironment(void) {
+
+ /* Does nothing in ChibiOS, exceptions are initialized by the OS.*/
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/src/cfe_psp_memory.c b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/src/cfe_psp_memory.c
new file mode 100644
index 0000000..7036b76
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/src/cfe_psp_memory.c
@@ -0,0 +1,136 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file cfe_psp_memory.c
+ * @brief CFE PSP memory module code.
+ *
+ * @addtogroup nasa_cfe_psp_memory
+ * @{
+ */
+
+#include "ch.h"
+
+#include "common_types.h"
+#include "osapi.h"
+#include "cfe_psp.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+int32 CFE_PSP_GetCDSSize(uint32 *SizeOfCDS) {
+
+ (void)SizeOfCDS;
+
+ return 0;
+}
+
+int32 CFE_PSP_WriteToCDS(void *PtrToDataToWrite,
+ uint32 CDSOffset,
+ uint32 NumBytes) {
+
+ (void)PtrToDataToWrite;
+ (void)CDSOffset;
+ (void)NumBytes;
+
+ return 0;
+}
+
+int32 CFE_PSP_ReadFromCDS(void *PtrToDataToRead,
+ uint32 CDSOffset,
+ uint32 NumBytes) {
+
+ (void)PtrToDataToRead;
+ (void)CDSOffset;
+ (void)NumBytes;
+
+ return 0;
+}
+
+int32 CFE_PSP_GetResetArea(void *PtrToResetArea,
+ uint32 *SizeOfResetArea) {
+
+ (void)PtrToResetArea;
+ (void)SizeOfResetArea;
+
+ return 0;
+}
+
+int32 CFE_PSP_GetUserReservedArea(void *PtrToUserArea,
+ uint32 *SizeOfUserArea) {
+
+ (void)PtrToUserArea;
+ (void)SizeOfUserArea;
+
+ return 0;
+}
+
+int32 CFE_PSP_GetVolatileDiskMem(void *PtrToVolDisk,
+ uint32 *SizeOfVolDisk) {
+
+ (void)PtrToVolDisk;
+ (void)SizeOfVolDisk;
+
+ return 0;
+}
+
+int32 CFE_PSP_InitProcessorReservedMemory(uint32 RestartType) {
+
+ (void)RestartType;
+
+ return 0;
+}
+
+int32 CFE_PSP_GetKernelTextSegmentInfo(void *PtrToKernelSegment,
+ uint32 *SizeOfKernelSegment) {
+
+ (void)PtrToKernelSegment;
+ (void)SizeOfKernelSegment;
+
+ return 0;
+}
+
+int32 CFE_PSP_GetCFETextSegmentInfo(void *PtrToCFESegment,
+ uint32 *SizeOfCFESegment) {
+
+ (void)PtrToCFESegment;
+ (void)SizeOfCFESegment;
+
+ return 0;
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/src/cfe_psp_support.c b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/src/cfe_psp_support.c
new file mode 100644
index 0000000..77df47e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/src/cfe_psp_support.c
@@ -0,0 +1,72 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file cfe_psp_support.c
+ * @brief CFE PSP support module code.
+ *
+ * @addtogroup nasa_cfe_psp_support
+ * @{
+ */
+
+#include "ch.h"
+
+#include "common_types.h"
+#include "osapi.h"
+#include "cfe_psp.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Provides a common interface to the processor reset.
+ * @note Not currently implemented.
+ */
+void CFE_PSP_Restart(uint32 reset_type) {
+
+ (void)reset_type;
+}
+
+/**
+ * @brief Generic panic handler.
+ */
+void CFE_PSP_Panic(int32 ErrorCode) {
+
+ chSysHalt((char *)ErrorCode);
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/src/cfe_psp_timer.c b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/src/cfe_psp_timer.c
new file mode 100644
index 0000000..407dd1b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/abstractions/nasa_cfe/psp/src/cfe_psp_timer.c
@@ -0,0 +1,81 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file cfe_psp_timer.c
+ * @brief CFE PSP timer module code.
+ *
+ * @addtogroup nasa_cfe_psp_timer
+ * @{
+ */
+
+#include "ch.h"
+
+#include "common_types.h"
+#include "osapi.h"
+#include "cfe_psp.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+void CFE_PSP_GetTime(OS_time_t *LocalTime) {
+
+ (void)LocalTime;
+}
+
+uint32 CFE_PSP_GetTimerTicksPerSecond(void) {
+
+ return 0;
+}
+
+uint32 CFE_PSP_GetTimerLow32Rollover(void) {
+
+ return 0;
+}
+
+void CFE_PSP_Get_Timebase(uint32 *Tbu, uint32* Tbl) {
+
+ (void)Tbu;
+ (void)Tbl;
+}
+
+uint32 CFE_PSP_Get_Dec(void) {
+
+ return 0;
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/cmsis_armcc.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/cmsis_armcc.h
new file mode 100644
index 0000000..4d9d064
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/cmsis_armcc.h
@@ -0,0 +1,865 @@
+/**************************************************************************//**
+ * @file cmsis_armcc.h
+ * @brief CMSIS compiler ARMCC (Arm Compiler 5) header file
+ * @version V5.0.4
+ * @date 10. January 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CMSIS_ARMCC_H
+#define __CMSIS_ARMCC_H
+
+
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677)
+ #error "Please use Arm Compiler Toolchain V4.0.677 or later!"
+#endif
+
+/* CMSIS compiler control architecture macros */
+#if ((defined (__TARGET_ARCH_6_M ) && (__TARGET_ARCH_6_M == 1)) || \
+ (defined (__TARGET_ARCH_6S_M ) && (__TARGET_ARCH_6S_M == 1)) )
+ #define __ARM_ARCH_6M__ 1
+#endif
+
+#if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M == 1))
+ #define __ARM_ARCH_7M__ 1
+#endif
+
+#if (defined (__TARGET_ARCH_7E_M) && (__TARGET_ARCH_7E_M == 1))
+ #define __ARM_ARCH_7EM__ 1
+#endif
+
+ /* __ARM_ARCH_8M_BASE__ not applicable */
+ /* __ARM_ARCH_8M_MAIN__ not applicable */
+
+
+/* CMSIS compiler specific defines */
+#ifndef __ASM
+ #define __ASM __asm
+#endif
+#ifndef __INLINE
+ #define __INLINE __inline
+#endif
+#ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static __inline
+#endif
+#ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE static __forceinline
+#endif
+#ifndef __NO_RETURN
+ #define __NO_RETURN __declspec(noreturn)
+#endif
+#ifndef __USED
+ #define __USED __attribute__((used))
+#endif
+#ifndef __WEAK
+ #define __WEAK __attribute__((weak))
+#endif
+#ifndef __PACKED
+ #define __PACKED __attribute__((packed))
+#endif
+#ifndef __PACKED_STRUCT
+ #define __PACKED_STRUCT __packed struct
+#endif
+#ifndef __PACKED_UNION
+ #define __PACKED_UNION __packed union
+#endif
+#ifndef __UNALIGNED_UINT32 /* deprecated */
+ #define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x)))
+#endif
+#ifndef __UNALIGNED_UINT16_WRITE
+ #define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val))
+#endif
+#ifndef __UNALIGNED_UINT16_READ
+ #define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr)))
+#endif
+#ifndef __UNALIGNED_UINT32_WRITE
+ #define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val))
+#endif
+#ifndef __UNALIGNED_UINT32_READ
+ #define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr)))
+#endif
+#ifndef __ALIGNED
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+#endif
+#ifndef __RESTRICT
+ #define __RESTRICT __restrict
+#endif
+
+/* ########################### Core Function Access ########################### */
+/** \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
+ @{
+ */
+
+/**
+ \brief Enable IRQ Interrupts
+ \details Enables IRQ interrupts by clearing the I-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+/* intrinsic void __enable_irq(); */
+
+
+/**
+ \brief Disable IRQ Interrupts
+ \details Disables IRQ interrupts by setting the I-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+/* intrinsic void __disable_irq(); */
+
+/**
+ \brief Get Control Register
+ \details Returns the content of the Control Register.
+ \return Control Register value
+ */
+__STATIC_INLINE uint32_t __get_CONTROL(void)
+{
+ register uint32_t __regControl __ASM("control");
+ return(__regControl);
+}
+
+
+/**
+ \brief Set Control Register
+ \details Writes the given value to the Control Register.
+ \param [in] control Control Register value to set
+ */
+__STATIC_INLINE void __set_CONTROL(uint32_t control)
+{
+ register uint32_t __regControl __ASM("control");
+ __regControl = control;
+}
+
+
+/**
+ \brief Get IPSR Register
+ \details Returns the content of the IPSR Register.
+ \return IPSR Register value
+ */
+__STATIC_INLINE uint32_t __get_IPSR(void)
+{
+ register uint32_t __regIPSR __ASM("ipsr");
+ return(__regIPSR);
+}
+
+
+/**
+ \brief Get APSR Register
+ \details Returns the content of the APSR Register.
+ \return APSR Register value
+ */
+__STATIC_INLINE uint32_t __get_APSR(void)
+{
+ register uint32_t __regAPSR __ASM("apsr");
+ return(__regAPSR);
+}
+
+
+/**
+ \brief Get xPSR Register
+ \details Returns the content of the xPSR Register.
+ \return xPSR Register value
+ */
+__STATIC_INLINE uint32_t __get_xPSR(void)
+{
+ register uint32_t __regXPSR __ASM("xpsr");
+ return(__regXPSR);
+}
+
+
+/**
+ \brief Get Process Stack Pointer
+ \details Returns the current value of the Process Stack Pointer (PSP).
+ \return PSP Register value
+ */
+__STATIC_INLINE uint32_t __get_PSP(void)
+{
+ register uint32_t __regProcessStackPointer __ASM("psp");
+ return(__regProcessStackPointer);
+}
+
+
+/**
+ \brief Set Process Stack Pointer
+ \details Assigns the given value to the Process Stack Pointer (PSP).
+ \param [in] topOfProcStack Process Stack Pointer value to set
+ */
+__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
+{
+ register uint32_t __regProcessStackPointer __ASM("psp");
+ __regProcessStackPointer = topOfProcStack;
+}
+
+
+/**
+ \brief Get Main Stack Pointer
+ \details Returns the current value of the Main Stack Pointer (MSP).
+ \return MSP Register value
+ */
+__STATIC_INLINE uint32_t __get_MSP(void)
+{
+ register uint32_t __regMainStackPointer __ASM("msp");
+ return(__regMainStackPointer);
+}
+
+
+/**
+ \brief Set Main Stack Pointer
+ \details Assigns the given value to the Main Stack Pointer (MSP).
+ \param [in] topOfMainStack Main Stack Pointer value to set
+ */
+__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
+{
+ register uint32_t __regMainStackPointer __ASM("msp");
+ __regMainStackPointer = topOfMainStack;
+}
+
+
+/**
+ \brief Get Priority Mask
+ \details Returns the current state of the priority mask bit from the Priority Mask Register.
+ \return Priority Mask value
+ */
+__STATIC_INLINE uint32_t __get_PRIMASK(void)
+{
+ register uint32_t __regPriMask __ASM("primask");
+ return(__regPriMask);
+}
+
+
+/**
+ \brief Set Priority Mask
+ \details Assigns the given value to the Priority Mask Register.
+ \param [in] priMask Priority Mask
+ */
+__STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
+{
+ register uint32_t __regPriMask __ASM("primask");
+ __regPriMask = (priMask);
+}
+
+
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
+
+/**
+ \brief Enable FIQ
+ \details Enables FIQ interrupts by clearing the F-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+#define __enable_fault_irq __enable_fiq
+
+
+/**
+ \brief Disable FIQ
+ \details Disables FIQ interrupts by setting the F-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+#define __disable_fault_irq __disable_fiq
+
+
+/**
+ \brief Get Base Priority
+ \details Returns the current value of the Base Priority register.
+ \return Base Priority register value
+ */
+__STATIC_INLINE uint32_t __get_BASEPRI(void)
+{
+ register uint32_t __regBasePri __ASM("basepri");
+ return(__regBasePri);
+}
+
+
+/**
+ \brief Set Base Priority
+ \details Assigns the given value to the Base Priority register.
+ \param [in] basePri Base Priority value to set
+ */
+__STATIC_INLINE void __set_BASEPRI(uint32_t basePri)
+{
+ register uint32_t __regBasePri __ASM("basepri");
+ __regBasePri = (basePri & 0xFFU);
+}
+
+
+/**
+ \brief Set Base Priority with condition
+ \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled,
+ or the new value increases the BASEPRI priority level.
+ \param [in] basePri Base Priority value to set
+ */
+__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri)
+{
+ register uint32_t __regBasePriMax __ASM("basepri_max");
+ __regBasePriMax = (basePri & 0xFFU);
+}
+
+
+/**
+ \brief Get Fault Mask
+ \details Returns the current value of the Fault Mask register.
+ \return Fault Mask register value
+ */
+__STATIC_INLINE uint32_t __get_FAULTMASK(void)
+{
+ register uint32_t __regFaultMask __ASM("faultmask");
+ return(__regFaultMask);
+}
+
+
+/**
+ \brief Set Fault Mask
+ \details Assigns the given value to the Fault Mask register.
+ \param [in] faultMask Fault Mask value to set
+ */
+__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
+{
+ register uint32_t __regFaultMask __ASM("faultmask");
+ __regFaultMask = (faultMask & (uint32_t)1U);
+}
+
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
+
+
+/**
+ \brief Get FPSCR
+ \details Returns the current value of the Floating Point Status/Control register.
+ \return Floating Point Status/Control register value
+ */
+__STATIC_INLINE uint32_t __get_FPSCR(void)
+{
+#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
+ register uint32_t __regfpscr __ASM("fpscr");
+ return(__regfpscr);
+#else
+ return(0U);
+#endif
+}
+
+
+/**
+ \brief Set FPSCR
+ \details Assigns the given value to the Floating Point Status/Control register.
+ \param [in] fpscr Floating Point Status/Control value to set
+ */
+__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
+{
+#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
+ register uint32_t __regfpscr __ASM("fpscr");
+ __regfpscr = (fpscr);
+#else
+ (void)fpscr;
+#endif
+}
+
+
+/*@} end of CMSIS_Core_RegAccFunctions */
+
+
+/* ########################## Core Instruction Access ######################### */
+/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
+ Access to dedicated instructions
+ @{
+*/
+
+/**
+ \brief No Operation
+ \details No Operation does nothing. This instruction can be used for code alignment purposes.
+ */
+#define __NOP __nop
+
+
+/**
+ \brief Wait For Interrupt
+ \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
+ */
+#define __WFI __wfi
+
+
+/**
+ \brief Wait For Event
+ \details Wait For Event is a hint instruction that permits the processor to enter
+ a low-power state until one of a number of events occurs.
+ */
+#define __WFE __wfe
+
+
+/**
+ \brief Send Event
+ \details Send Event is a hint instruction. It causes an event to be signaled to the CPU.
+ */
+#define __SEV __sev
+
+
+/**
+ \brief Instruction Synchronization Barrier
+ \details Instruction Synchronization Barrier flushes the pipeline in the processor,
+ so that all instructions following the ISB are fetched from cache or memory,
+ after the instruction has been completed.
+ */
+#define __ISB() do {\
+ __schedule_barrier();\
+ __isb(0xF);\
+ __schedule_barrier();\
+ } while (0U)
+
+/**
+ \brief Data Synchronization Barrier
+ \details Acts as a special kind of Data Memory Barrier.
+ It completes when all explicit memory accesses before this instruction complete.
+ */
+#define __DSB() do {\
+ __schedule_barrier();\
+ __dsb(0xF);\
+ __schedule_barrier();\
+ } while (0U)
+
+/**
+ \brief Data Memory Barrier
+ \details Ensures the apparent order of the explicit memory operations before
+ and after the instruction, without ensuring their completion.
+ */
+#define __DMB() do {\
+ __schedule_barrier();\
+ __dmb(0xF);\
+ __schedule_barrier();\
+ } while (0U)
+
+
+/**
+ \brief Reverse byte order (32 bit)
+ \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __REV __rev
+
+
+/**
+ \brief Reverse byte order (16 bit)
+ \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#ifndef __NO_EMBEDDED_ASM
+__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
+{
+ rev16 r0, r0
+ bx lr
+}
+#endif
+
+
+/**
+ \brief Reverse byte order (16 bit)
+ \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#ifndef __NO_EMBEDDED_ASM
+__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value)
+{
+ revsh r0, r0
+ bx lr
+}
+#endif
+
+
+/**
+ \brief Rotate Right in unsigned value (32 bit)
+ \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
+ \param [in] op1 Value to rotate
+ \param [in] op2 Number of Bits to rotate
+ \return Rotated value
+ */
+#define __ROR __ror
+
+
+/**
+ \brief Breakpoint
+ \details Causes the processor to enter Debug state.
+ Debug tools can use this to investigate system state when the instruction at a particular address is reached.
+ \param [in] value is ignored by the processor.
+ If required, a debugger can use it to store additional information about the breakpoint.
+ */
+#define __BKPT(value) __breakpoint(value)
+
+
+/**
+ \brief Reverse bit order of value
+ \details Reverses the bit order of the given value.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
+ #define __RBIT __rbit
+#else
+__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
+{
+ uint32_t result;
+ uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */
+
+ result = value; /* r will be reversed bits of v; first get LSB of v */
+ for (value >>= 1U; value != 0U; value >>= 1U)
+ {
+ result <<= 1U;
+ result |= value & 1U;
+ s--;
+ }
+ result <<= s; /* shift when v's highest bits are zero */
+ return result;
+}
+#endif
+
+
+/**
+ \brief Count leading zeros
+ \details Counts the number of leading zeros of a data value.
+ \param [in] value Value to count the leading zeros
+ \return number of leading zeros in value
+ */
+#define __CLZ __clz
+
+
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
+
+/**
+ \brief LDR Exclusive (8 bit)
+ \details Executes a exclusive LDR instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
+ #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
+#else
+ #define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop")
+#endif
+
+
+/**
+ \brief LDR Exclusive (16 bit)
+ \details Executes a exclusive LDR instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
+ #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
+#else
+ #define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop")
+#endif
+
+
+/**
+ \brief LDR Exclusive (32 bit)
+ \details Executes a exclusive LDR instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
+ #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
+#else
+ #define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop")
+#endif
+
+
+/**
+ \brief STR Exclusive (8 bit)
+ \details Executes a exclusive STR instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
+ #define __STREXB(value, ptr) __strex(value, ptr)
+#else
+ #define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
+#endif
+
+
+/**
+ \brief STR Exclusive (16 bit)
+ \details Executes a exclusive STR instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
+ #define __STREXH(value, ptr) __strex(value, ptr)
+#else
+ #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
+#endif
+
+
+/**
+ \brief STR Exclusive (32 bit)
+ \details Executes a exclusive STR instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
+ #define __STREXW(value, ptr) __strex(value, ptr)
+#else
+ #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
+#endif
+
+
+/**
+ \brief Remove the exclusive lock
+ \details Removes the exclusive lock which is created by LDREX.
+ */
+#define __CLREX __clrex
+
+
+/**
+ \brief Signed Saturate
+ \details Saturates a signed value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (1..32)
+ \return Saturated value
+ */
+#define __SSAT __ssat
+
+
+/**
+ \brief Unsigned Saturate
+ \details Saturates an unsigned value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (0..31)
+ \return Saturated value
+ */
+#define __USAT __usat
+
+
+/**
+ \brief Rotate Right with Extend (32 bit)
+ \details Moves each bit of a bitstring right by one bit.
+ The carry input is shifted in at the left end of the bitstring.
+ \param [in] value Value to rotate
+ \return Rotated value
+ */
+#ifndef __NO_EMBEDDED_ASM
+__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value)
+{
+ rrx r0, r0
+ bx lr
+}
+#endif
+
+
+/**
+ \brief LDRT Unprivileged (8 bit)
+ \details Executes a Unprivileged LDRT instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr))
+
+
+/**
+ \brief LDRT Unprivileged (16 bit)
+ \details Executes a Unprivileged LDRT instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr))
+
+
+/**
+ \brief LDRT Unprivileged (32 bit)
+ \details Executes a Unprivileged LDRT instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr))
+
+
+/**
+ \brief STRT Unprivileged (8 bit)
+ \details Executes a Unprivileged STRT instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+#define __STRBT(value, ptr) __strt(value, ptr)
+
+
+/**
+ \brief STRT Unprivileged (16 bit)
+ \details Executes a Unprivileged STRT instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+#define __STRHT(value, ptr) __strt(value, ptr)
+
+
+/**
+ \brief STRT Unprivileged (32 bit)
+ \details Executes a Unprivileged STRT instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+#define __STRT(value, ptr) __strt(value, ptr)
+
+#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
+
+/**
+ \brief Signed Saturate
+ \details Saturates a signed value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (1..32)
+ \return Saturated value
+ */
+__attribute__((always_inline)) __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat)
+{
+ if ((sat >= 1U) && (sat <= 32U))
+ {
+ const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
+ const int32_t min = -1 - max ;
+ if (val > max)
+ {
+ return max;
+ }
+ else if (val < min)
+ {
+ return min;
+ }
+ }
+ return val;
+}
+
+/**
+ \brief Unsigned Saturate
+ \details Saturates an unsigned value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (0..31)
+ \return Saturated value
+ */
+__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat)
+{
+ if (sat <= 31U)
+ {
+ const uint32_t max = ((1U << sat) - 1U);
+ if (val > (int32_t)max)
+ {
+ return max;
+ }
+ else if (val < 0)
+ {
+ return 0U;
+ }
+ }
+ return (uint32_t)val;
+}
+
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
+
+/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
+
+
+/* ################### Compiler specific Intrinsics ########################### */
+/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
+ Access to dedicated SIMD instructions
+ @{
+*/
+
+#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
+
+#define __SADD8 __sadd8
+#define __QADD8 __qadd8
+#define __SHADD8 __shadd8
+#define __UADD8 __uadd8
+#define __UQADD8 __uqadd8
+#define __UHADD8 __uhadd8
+#define __SSUB8 __ssub8
+#define __QSUB8 __qsub8
+#define __SHSUB8 __shsub8
+#define __USUB8 __usub8
+#define __UQSUB8 __uqsub8
+#define __UHSUB8 __uhsub8
+#define __SADD16 __sadd16
+#define __QADD16 __qadd16
+#define __SHADD16 __shadd16
+#define __UADD16 __uadd16
+#define __UQADD16 __uqadd16
+#define __UHADD16 __uhadd16
+#define __SSUB16 __ssub16
+#define __QSUB16 __qsub16
+#define __SHSUB16 __shsub16
+#define __USUB16 __usub16
+#define __UQSUB16 __uqsub16
+#define __UHSUB16 __uhsub16
+#define __SASX __sasx
+#define __QASX __qasx
+#define __SHASX __shasx
+#define __UASX __uasx
+#define __UQASX __uqasx
+#define __UHASX __uhasx
+#define __SSAX __ssax
+#define __QSAX __qsax
+#define __SHSAX __shsax
+#define __USAX __usax
+#define __UQSAX __uqsax
+#define __UHSAX __uhsax
+#define __USAD8 __usad8
+#define __USADA8 __usada8
+#define __SSAT16 __ssat16
+#define __USAT16 __usat16
+#define __UXTB16 __uxtb16
+#define __UXTAB16 __uxtab16
+#define __SXTB16 __sxtb16
+#define __SXTAB16 __sxtab16
+#define __SMUAD __smuad
+#define __SMUADX __smuadx
+#define __SMLAD __smlad
+#define __SMLADX __smladx
+#define __SMLALD __smlald
+#define __SMLALDX __smlaldx
+#define __SMUSD __smusd
+#define __SMUSDX __smusdx
+#define __SMLSD __smlsd
+#define __SMLSDX __smlsdx
+#define __SMLSLD __smlsld
+#define __SMLSLDX __smlsldx
+#define __SEL __sel
+#define __QADD __qadd
+#define __QSUB __qsub
+
+#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
+ ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
+
+#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
+ ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
+
+#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \
+ ((int64_t)(ARG3) << 32U) ) >> 32U))
+
+#endif /* ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
+/*@} end of group CMSIS_SIMD_intrinsics */
+
+
+#endif /* __CMSIS_ARMCC_H */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/cmsis_armclang.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/cmsis_armclang.h
new file mode 100644
index 0000000..162a400
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/cmsis_armclang.h
@@ -0,0 +1,1869 @@
+/**************************************************************************//**
+ * @file cmsis_armclang.h
+ * @brief CMSIS compiler armclang (Arm Compiler 6) header file
+ * @version V5.0.4
+ * @date 10. January 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*lint -esym(9058, IRQn)*/ /* disable MISRA 2012 Rule 2.4 for IRQn */
+
+#ifndef __CMSIS_ARMCLANG_H
+#define __CMSIS_ARMCLANG_H
+
+#pragma clang system_header /* treat file as system include file */
+
+#ifndef __ARM_COMPAT_H
+#include /* Compatibility header for Arm Compiler 5 intrinsics */
+#endif
+
+/* CMSIS compiler specific defines */
+#ifndef __ASM
+ #define __ASM __asm
+#endif
+#ifndef __INLINE
+ #define __INLINE __inline
+#endif
+#ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static __inline
+#endif
+#ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline
+#endif
+#ifndef __NO_RETURN
+ #define __NO_RETURN __attribute__((__noreturn__))
+#endif
+#ifndef __USED
+ #define __USED __attribute__((used))
+#endif
+#ifndef __WEAK
+ #define __WEAK __attribute__((weak))
+#endif
+#ifndef __PACKED
+ #define __PACKED __attribute__((packed, aligned(1)))
+#endif
+#ifndef __PACKED_STRUCT
+ #define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
+#endif
+#ifndef __PACKED_UNION
+ #define __PACKED_UNION union __attribute__((packed, aligned(1)))
+#endif
+#ifndef __UNALIGNED_UINT32 /* deprecated */
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT32)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32 */
+ struct __attribute__((packed)) T_UINT32 { uint32_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
+#endif
+#ifndef __UNALIGNED_UINT16_WRITE
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */
+ __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
+#endif
+#ifndef __UNALIGNED_UINT16_READ
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */
+ __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
+#endif
+#ifndef __UNALIGNED_UINT32_WRITE
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */
+ __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
+#endif
+#ifndef __UNALIGNED_UINT32_READ
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT32_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_READ */
+ __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
+#endif
+#ifndef __ALIGNED
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+#endif
+#ifndef __RESTRICT
+ #define __RESTRICT __restrict
+#endif
+
+
+/* ########################### Core Function Access ########################### */
+/** \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
+ @{
+ */
+
+/**
+ \brief Enable IRQ Interrupts
+ \details Enables IRQ interrupts by clearing the I-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+/* intrinsic void __enable_irq(); see arm_compat.h */
+
+
+/**
+ \brief Disable IRQ Interrupts
+ \details Disables IRQ interrupts by setting the I-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+/* intrinsic void __disable_irq(); see arm_compat.h */
+
+
+/**
+ \brief Get Control Register
+ \details Returns the content of the Control Register.
+ \return Control Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_CONTROL(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, control" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Control Register (non-secure)
+ \details Returns the content of the non-secure Control Register when in secure mode.
+ \return non-secure Control Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, control_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Control Register
+ \details Writes the given value to the Control Register.
+ \param [in] control Control Register value to set
+ */
+__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control)
+{
+ __ASM volatile ("MSR control, %0" : : "r" (control) : "memory");
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Control Register (non-secure)
+ \details Writes the given value to the non-secure Control Register when in secure state.
+ \param [in] control Control Register value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control)
+{
+ __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory");
+}
+#endif
+
+
+/**
+ \brief Get IPSR Register
+ \details Returns the content of the IPSR Register.
+ \return IPSR Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_IPSR(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, ipsr" : "=r" (result) );
+ return(result);
+}
+
+
+/**
+ \brief Get APSR Register
+ \details Returns the content of the APSR Register.
+ \return APSR Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_APSR(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, apsr" : "=r" (result) );
+ return(result);
+}
+
+
+/**
+ \brief Get xPSR Register
+ \details Returns the content of the xPSR Register.
+ \return xPSR Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_xPSR(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, xpsr" : "=r" (result) );
+ return(result);
+}
+
+
+/**
+ \brief Get Process Stack Pointer
+ \details Returns the current value of the Process Stack Pointer (PSP).
+ \return PSP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_PSP(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, psp" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Process Stack Pointer (non-secure)
+ \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state.
+ \return PSP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, psp_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Process Stack Pointer
+ \details Assigns the given value to the Process Stack Pointer (PSP).
+ \param [in] topOfProcStack Process Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack)
+{
+ __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : );
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Process Stack Pointer (non-secure)
+ \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state.
+ \param [in] topOfProcStack Process Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack)
+{
+ __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : );
+}
+#endif
+
+
+/**
+ \brief Get Main Stack Pointer
+ \details Returns the current value of the Main Stack Pointer (MSP).
+ \return MSP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_MSP(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, msp" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Main Stack Pointer (non-secure)
+ \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state.
+ \return MSP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, msp_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Main Stack Pointer
+ \details Assigns the given value to the Main Stack Pointer (MSP).
+ \param [in] topOfMainStack Main Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack)
+{
+ __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : );
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Main Stack Pointer (non-secure)
+ \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state.
+ \param [in] topOfMainStack Main Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack)
+{
+ __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : );
+}
+#endif
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Stack Pointer (non-secure)
+ \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state.
+ \return SP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, sp_ns" : "=r" (result) );
+ return(result);
+}
+
+
+/**
+ \brief Set Stack Pointer (non-secure)
+ \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state.
+ \param [in] topOfStack Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack)
+{
+ __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : );
+}
+#endif
+
+
+/**
+ \brief Get Priority Mask
+ \details Returns the current state of the priority mask bit from the Priority Mask Register.
+ \return Priority Mask value
+ */
+__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, primask" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Priority Mask (non-secure)
+ \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state.
+ \return Priority Mask value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, primask_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Priority Mask
+ \details Assigns the given value to the Priority Mask Register.
+ \param [in] priMask Priority Mask
+ */
+__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask)
+{
+ __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Priority Mask (non-secure)
+ \details Assigns the given value to the non-secure Priority Mask Register when in secure state.
+ \param [in] priMask Priority Mask
+ */
+__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask)
+{
+ __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory");
+}
+#endif
+
+
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) )
+/**
+ \brief Enable FIQ
+ \details Enables FIQ interrupts by clearing the F-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+#define __enable_fault_irq __enable_fiq /* see arm_compat.h */
+
+
+/**
+ \brief Disable FIQ
+ \details Disables FIQ interrupts by setting the F-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+#define __disable_fault_irq __disable_fiq /* see arm_compat.h */
+
+
+/**
+ \brief Get Base Priority
+ \details Returns the current value of the Base Priority register.
+ \return Base Priority register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, basepri" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Base Priority (non-secure)
+ \details Returns the current value of the non-secure Base Priority register when in secure state.
+ \return Base Priority register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Base Priority
+ \details Assigns the given value to the Base Priority register.
+ \param [in] basePri Base Priority value to set
+ */
+__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri)
+{
+ __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory");
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Base Priority (non-secure)
+ \details Assigns the given value to the non-secure Base Priority register when in secure state.
+ \param [in] basePri Base Priority value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri)
+{
+ __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory");
+}
+#endif
+
+
+/**
+ \brief Set Base Priority with condition
+ \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled,
+ or the new value increases the BASEPRI priority level.
+ \param [in] basePri Base Priority value to set
+ */
+__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri)
+{
+ __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory");
+}
+
+
+/**
+ \brief Get Fault Mask
+ \details Returns the current value of the Fault Mask register.
+ \return Fault Mask register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, faultmask" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Fault Mask (non-secure)
+ \details Returns the current value of the non-secure Fault Mask register when in secure state.
+ \return Fault Mask register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Fault Mask
+ \details Assigns the given value to the Fault Mask register.
+ \param [in] faultMask Fault Mask value to set
+ */
+__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask)
+{
+ __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory");
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Fault Mask (non-secure)
+ \details Assigns the given value to the non-secure Fault Mask register when in secure state.
+ \param [in] faultMask Fault Mask value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask)
+{
+ __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory");
+}
+#endif
+
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */
+
+
+#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
+
+/**
+ \brief Get Process Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always in non-secure
+ mode.
+
+ \details Returns the current value of the Process Stack Pointer Limit (PSPLIM).
+ \return PSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, psplim" : "=r" (result) );
+ return result;
+#endif
+}
+
+#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Process Stack Pointer Limit (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always in non-secure
+ mode.
+
+ \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state.
+ \return PSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) );
+ return result;
+#endif
+}
+#endif
+
+
+/**
+ \brief Set Process Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored in non-secure
+ mode.
+
+ \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM).
+ \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set
+ */
+__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ (void)ProcStackPtrLimit;
+#else
+ __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit));
+#endif
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Process Stack Pointer (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored in non-secure
+ mode.
+
+ \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state.
+ \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ (void)ProcStackPtrLimit;
+#else
+ __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit));
+#endif
+}
+#endif
+
+
+/**
+ \brief Get Main Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always.
+
+ \details Returns the current value of the Main Stack Pointer Limit (MSPLIM).
+ \return MSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, msplim" : "=r" (result) );
+ return result;
+#endif
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Main Stack Pointer Limit (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always.
+
+ \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state.
+ \return MSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) );
+ return result;
+#endif
+}
+#endif
+
+
+/**
+ \brief Set Main Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored.
+
+ \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM).
+ \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set
+ */
+__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ (void)MainStackPtrLimit;
+#else
+ __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit));
+#endif
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Main Stack Pointer Limit (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored.
+
+ \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state.
+ \param [in] MainStackPtrLimit Main Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ (void)MainStackPtrLimit;
+#else
+ __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit));
+#endif
+}
+#endif
+
+#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */
+
+/**
+ \brief Get FPSCR
+ \details Returns the current value of the Floating Point Status/Control register.
+ \return Floating Point Status/Control register value
+ */
+#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
+#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr
+#else
+#define __get_FPSCR() ((uint32_t)0U)
+#endif
+
+/**
+ \brief Set FPSCR
+ \details Assigns the given value to the Floating Point Status/Control register.
+ \param [in] fpscr Floating Point Status/Control value to set
+ */
+#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
+#define __set_FPSCR __builtin_arm_set_fpscr
+#else
+#define __set_FPSCR(x) ((void)(x))
+#endif
+
+
+/*@} end of CMSIS_Core_RegAccFunctions */
+
+
+/* ########################## Core Instruction Access ######################### */
+/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
+ Access to dedicated instructions
+ @{
+*/
+
+/* Define macros for porting to both thumb1 and thumb2.
+ * For thumb1, use low register (r0-r7), specified by constraint "l"
+ * Otherwise, use general registers, specified by constraint "r" */
+#if defined (__thumb__) && !defined (__thumb2__)
+#define __CMSIS_GCC_OUT_REG(r) "=l" (r)
+#define __CMSIS_GCC_USE_REG(r) "l" (r)
+#else
+#define __CMSIS_GCC_OUT_REG(r) "=r" (r)
+#define __CMSIS_GCC_USE_REG(r) "r" (r)
+#endif
+
+/**
+ \brief No Operation
+ \details No Operation does nothing. This instruction can be used for code alignment purposes.
+ */
+#define __NOP __builtin_arm_nop
+
+/**
+ \brief Wait For Interrupt
+ \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
+ */
+#define __WFI __builtin_arm_wfi
+
+
+/**
+ \brief Wait For Event
+ \details Wait For Event is a hint instruction that permits the processor to enter
+ a low-power state until one of a number of events occurs.
+ */
+#define __WFE __builtin_arm_wfe
+
+
+/**
+ \brief Send Event
+ \details Send Event is a hint instruction. It causes an event to be signaled to the CPU.
+ */
+#define __SEV __builtin_arm_sev
+
+
+/**
+ \brief Instruction Synchronization Barrier
+ \details Instruction Synchronization Barrier flushes the pipeline in the processor,
+ so that all instructions following the ISB are fetched from cache or memory,
+ after the instruction has been completed.
+ */
+#define __ISB() __builtin_arm_isb(0xF);
+
+/**
+ \brief Data Synchronization Barrier
+ \details Acts as a special kind of Data Memory Barrier.
+ It completes when all explicit memory accesses before this instruction complete.
+ */
+#define __DSB() __builtin_arm_dsb(0xF);
+
+
+/**
+ \brief Data Memory Barrier
+ \details Ensures the apparent order of the explicit memory operations before
+ and after the instruction, without ensuring their completion.
+ */
+#define __DMB() __builtin_arm_dmb(0xF);
+
+
+/**
+ \brief Reverse byte order (32 bit)
+ \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __REV(value) __builtin_bswap32(value)
+
+
+/**
+ \brief Reverse byte order (16 bit)
+ \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __REV16(value) __ROR(__REV(value), 16)
+
+
+/**
+ \brief Reverse byte order (16 bit)
+ \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __REVSH(value) (int16_t)__builtin_bswap16(value)
+
+
+/**
+ \brief Rotate Right in unsigned value (32 bit)
+ \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
+ \param [in] op1 Value to rotate
+ \param [in] op2 Number of Bits to rotate
+ \return Rotated value
+ */
+__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
+{
+ op2 %= 32U;
+ if (op2 == 0U)
+ {
+ return op1;
+ }
+ return (op1 >> op2) | (op1 << (32U - op2));
+}
+
+
+/**
+ \brief Breakpoint
+ \details Causes the processor to enter Debug state.
+ Debug tools can use this to investigate system state when the instruction at a particular address is reached.
+ \param [in] value is ignored by the processor.
+ If required, a debugger can use it to store additional information about the breakpoint.
+ */
+#define __BKPT(value) __ASM volatile ("bkpt "#value)
+
+
+/**
+ \brief Reverse bit order of value
+ \details Reverses the bit order of the given value.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __RBIT __builtin_arm_rbit
+
+/**
+ \brief Count leading zeros
+ \details Counts the number of leading zeros of a data value.
+ \param [in] value Value to count the leading zeros
+ \return number of leading zeros in value
+ */
+#define __CLZ (uint8_t)__builtin_clz
+
+
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
+/**
+ \brief LDR Exclusive (8 bit)
+ \details Executes a exclusive LDR instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+#define __LDREXB (uint8_t)__builtin_arm_ldrex
+
+
+/**
+ \brief LDR Exclusive (16 bit)
+ \details Executes a exclusive LDR instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+#define __LDREXH (uint16_t)__builtin_arm_ldrex
+
+
+/**
+ \brief LDR Exclusive (32 bit)
+ \details Executes a exclusive LDR instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+#define __LDREXW (uint32_t)__builtin_arm_ldrex
+
+
+/**
+ \brief STR Exclusive (8 bit)
+ \details Executes a exclusive STR instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STREXB (uint32_t)__builtin_arm_strex
+
+
+/**
+ \brief STR Exclusive (16 bit)
+ \details Executes a exclusive STR instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STREXH (uint32_t)__builtin_arm_strex
+
+
+/**
+ \brief STR Exclusive (32 bit)
+ \details Executes a exclusive STR instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STREXW (uint32_t)__builtin_arm_strex
+
+
+/**
+ \brief Remove the exclusive lock
+ \details Removes the exclusive lock which is created by LDREX.
+ */
+#define __CLREX __builtin_arm_clrex
+
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */
+
+
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) )
+
+/**
+ \brief Signed Saturate
+ \details Saturates a signed value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (1..32)
+ \return Saturated value
+ */
+#define __SSAT __builtin_arm_ssat
+
+
+/**
+ \brief Unsigned Saturate
+ \details Saturates an unsigned value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (0..31)
+ \return Saturated value
+ */
+#define __USAT __builtin_arm_usat
+
+
+/**
+ \brief Rotate Right with Extend (32 bit)
+ \details Moves each bit of a bitstring right by one bit.
+ The carry input is shifted in at the left end of the bitstring.
+ \param [in] value Value to rotate
+ \return Rotated value
+ */
+__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value)
+{
+ uint32_t result;
+
+ __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
+ return(result);
+}
+
+
+/**
+ \brief LDRT Unprivileged (8 bit)
+ \details Executes a Unprivileged LDRT instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint8_t) result); /* Add explicit type cast here */
+}
+
+
+/**
+ \brief LDRT Unprivileged (16 bit)
+ \details Executes a Unprivileged LDRT instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint16_t) result); /* Add explicit type cast here */
+}
+
+
+/**
+ \brief LDRT Unprivileged (32 bit)
+ \details Executes a Unprivileged LDRT instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return(result);
+}
+
+
+/**
+ \brief STRT Unprivileged (8 bit)
+ \details Executes a Unprivileged STRT instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr)
+{
+ __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief STRT Unprivileged (16 bit)
+ \details Executes a Unprivileged STRT instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr)
+{
+ __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief STRT Unprivileged (32 bit)
+ \details Executes a Unprivileged STRT instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr)
+{
+ __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) );
+}
+
+#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */
+
+/**
+ \brief Signed Saturate
+ \details Saturates a signed value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (1..32)
+ \return Saturated value
+ */
+__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat)
+{
+ if ((sat >= 1U) && (sat <= 32U))
+ {
+ const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
+ const int32_t min = -1 - max ;
+ if (val > max)
+ {
+ return max;
+ }
+ else if (val < min)
+ {
+ return min;
+ }
+ }
+ return val;
+}
+
+/**
+ \brief Unsigned Saturate
+ \details Saturates an unsigned value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (0..31)
+ \return Saturated value
+ */
+__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat)
+{
+ if (sat <= 31U)
+ {
+ const uint32_t max = ((1U << sat) - 1U);
+ if (val > (int32_t)max)
+ {
+ return max;
+ }
+ else if (val < 0)
+ {
+ return 0U;
+ }
+ }
+ return (uint32_t)val;
+}
+
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */
+
+
+#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
+/**
+ \brief Load-Acquire (8 bit)
+ \details Executes a LDAB instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint8_t) result);
+}
+
+
+/**
+ \brief Load-Acquire (16 bit)
+ \details Executes a LDAH instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint16_t) result);
+}
+
+
+/**
+ \brief Load-Acquire (32 bit)
+ \details Executes a LDA instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return(result);
+}
+
+
+/**
+ \brief Store-Release (8 bit)
+ \details Executes a STLB instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr)
+{
+ __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief Store-Release (16 bit)
+ \details Executes a STLH instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr)
+{
+ __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief Store-Release (32 bit)
+ \details Executes a STL instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr)
+{
+ __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief Load-Acquire Exclusive (8 bit)
+ \details Executes a LDAB exclusive instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+#define __LDAEXB (uint8_t)__builtin_arm_ldaex
+
+
+/**
+ \brief Load-Acquire Exclusive (16 bit)
+ \details Executes a LDAH exclusive instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+#define __LDAEXH (uint16_t)__builtin_arm_ldaex
+
+
+/**
+ \brief Load-Acquire Exclusive (32 bit)
+ \details Executes a LDA exclusive instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+#define __LDAEX (uint32_t)__builtin_arm_ldaex
+
+
+/**
+ \brief Store-Release Exclusive (8 bit)
+ \details Executes a STLB exclusive instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STLEXB (uint32_t)__builtin_arm_stlex
+
+
+/**
+ \brief Store-Release Exclusive (16 bit)
+ \details Executes a STLH exclusive instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STLEXH (uint32_t)__builtin_arm_stlex
+
+
+/**
+ \brief Store-Release Exclusive (32 bit)
+ \details Executes a STL exclusive instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STLEX (uint32_t)__builtin_arm_stlex
+
+#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */
+
+/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
+
+
+/* ################### Compiler specific Intrinsics ########################### */
+/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
+ Access to dedicated SIMD instructions
+ @{
+*/
+
+#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1))
+
+__STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+
+__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+
+__STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3)
+{
+ uint32_t result;
+
+ __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+#define __SSAT16(ARG1,ARG2) \
+({ \
+ int32_t __RES, __ARG1 = (ARG1); \
+ __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
+ __RES; \
+ })
+
+#define __USAT16(ARG1,ARG2) \
+({ \
+ uint32_t __RES, __ARG1 = (ARG1); \
+ __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
+ __RES; \
+ })
+
+__STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1)
+{
+ uint32_t result;
+
+ __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1));
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1)
+{
+ uint32_t result;
+
+ __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1));
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3)
+{
+ uint32_t result;
+
+ __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3)
+{
+ uint32_t result;
+
+ __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc)
+{
+ union llreg_u{
+ uint32_t w32[2];
+ uint64_t w64;
+ } llr;
+ llr.w64 = acc;
+
+#ifndef __ARMEB__ /* Little endian */
+ __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
+#else /* Big endian */
+ __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
+#endif
+
+ return(llr.w64);
+}
+
+__STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc)
+{
+ union llreg_u{
+ uint32_t w32[2];
+ uint64_t w64;
+ } llr;
+ llr.w64 = acc;
+
+#ifndef __ARMEB__ /* Little endian */
+ __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
+#else /* Big endian */
+ __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
+#endif
+
+ return(llr.w64);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3)
+{
+ uint32_t result;
+
+ __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3)
+{
+ uint32_t result;
+
+ __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc)
+{
+ union llreg_u{
+ uint32_t w32[2];
+ uint64_t w64;
+ } llr;
+ llr.w64 = acc;
+
+#ifndef __ARMEB__ /* Little endian */
+ __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
+#else /* Big endian */
+ __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
+#endif
+
+ return(llr.w64);
+}
+
+__STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc)
+{
+ union llreg_u{
+ uint32_t w32[2];
+ uint64_t w64;
+ } llr;
+ llr.w64 = acc;
+
+#ifndef __ARMEB__ /* Little endian */
+ __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
+#else /* Big endian */
+ __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
+#endif
+
+ return(llr.w64);
+}
+
+__STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2)
+{
+ int32_t result;
+
+ __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2)
+{
+ int32_t result;
+
+ __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+#if 0
+#define __PKHBT(ARG1,ARG2,ARG3) \
+({ \
+ uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
+ __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \
+ __RES; \
+ })
+
+#define __PKHTB(ARG1,ARG2,ARG3) \
+({ \
+ uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
+ if (ARG3 == 0) \
+ __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \
+ else \
+ __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \
+ __RES; \
+ })
+#endif
+
+#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
+ ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
+
+#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
+ ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
+
+__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3)
+{
+ int32_t result;
+
+ __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+#endif /* (__ARM_FEATURE_DSP == 1) */
+/*@} end of group CMSIS_SIMD_intrinsics */
+
+
+#endif /* __CMSIS_ARMCLANG_H */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/cmsis_compiler.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/cmsis_compiler.h
new file mode 100644
index 0000000..94212eb
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/cmsis_compiler.h
@@ -0,0 +1,266 @@
+/**************************************************************************//**
+ * @file cmsis_compiler.h
+ * @brief CMSIS compiler generic header file
+ * @version V5.0.4
+ * @date 10. January 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CMSIS_COMPILER_H
+#define __CMSIS_COMPILER_H
+
+#include
+
+/*
+ * Arm Compiler 4/5
+ */
+#if defined ( __CC_ARM )
+ #include "cmsis_armcc.h"
+
+
+/*
+ * Arm Compiler 6 (armclang)
+ */
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #include "cmsis_armclang.h"
+
+
+/*
+ * GNU Compiler
+ */
+#elif defined ( __GNUC__ )
+ #include "cmsis_gcc.h"
+
+
+/*
+ * IAR Compiler
+ */
+#elif defined ( __ICCARM__ )
+ #include
+
+
+/*
+ * TI Arm Compiler
+ */
+#elif defined ( __TI_ARM__ )
+ #include
+
+ #ifndef __ASM
+ #define __ASM __asm
+ #endif
+ #ifndef __INLINE
+ #define __INLINE inline
+ #endif
+ #ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static inline
+ #endif
+ #ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __STATIC_INLINE
+ #endif
+ #ifndef __NO_RETURN
+ #define __NO_RETURN __attribute__((noreturn))
+ #endif
+ #ifndef __USED
+ #define __USED __attribute__((used))
+ #endif
+ #ifndef __WEAK
+ #define __WEAK __attribute__((weak))
+ #endif
+ #ifndef __PACKED
+ #define __PACKED __attribute__((packed))
+ #endif
+ #ifndef __PACKED_STRUCT
+ #define __PACKED_STRUCT struct __attribute__((packed))
+ #endif
+ #ifndef __PACKED_UNION
+ #define __PACKED_UNION union __attribute__((packed))
+ #endif
+ #ifndef __UNALIGNED_UINT32 /* deprecated */
+ struct __attribute__((packed)) T_UINT32 { uint32_t v; };
+ #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
+ #endif
+ #ifndef __UNALIGNED_UINT16_WRITE
+ __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
+ #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val))
+ #endif
+ #ifndef __UNALIGNED_UINT16_READ
+ __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
+ #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
+ #endif
+ #ifndef __UNALIGNED_UINT32_WRITE
+ __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
+ #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
+ #endif
+ #ifndef __UNALIGNED_UINT32_READ
+ __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
+ #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
+ #endif
+ #ifndef __ALIGNED
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+ #endif
+ #ifndef __RESTRICT
+ #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
+ #define __RESTRICT
+ #endif
+
+
+/*
+ * TASKING Compiler
+ */
+#elif defined ( __TASKING__ )
+ /*
+ * The CMSIS functions have been implemented as intrinsics in the compiler.
+ * Please use "carm -?i" to get an up to date list of all intrinsics,
+ * Including the CMSIS ones.
+ */
+
+ #ifndef __ASM
+ #define __ASM __asm
+ #endif
+ #ifndef __INLINE
+ #define __INLINE inline
+ #endif
+ #ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static inline
+ #endif
+ #ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __STATIC_INLINE
+ #endif
+ #ifndef __NO_RETURN
+ #define __NO_RETURN __attribute__((noreturn))
+ #endif
+ #ifndef __USED
+ #define __USED __attribute__((used))
+ #endif
+ #ifndef __WEAK
+ #define __WEAK __attribute__((weak))
+ #endif
+ #ifndef __PACKED
+ #define __PACKED __packed__
+ #endif
+ #ifndef __PACKED_STRUCT
+ #define __PACKED_STRUCT struct __packed__
+ #endif
+ #ifndef __PACKED_UNION
+ #define __PACKED_UNION union __packed__
+ #endif
+ #ifndef __UNALIGNED_UINT32 /* deprecated */
+ struct __packed__ T_UINT32 { uint32_t v; };
+ #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
+ #endif
+ #ifndef __UNALIGNED_UINT16_WRITE
+ __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
+ #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
+ #endif
+ #ifndef __UNALIGNED_UINT16_READ
+ __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
+ #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
+ #endif
+ #ifndef __UNALIGNED_UINT32_WRITE
+ __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
+ #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
+ #endif
+ #ifndef __UNALIGNED_UINT32_READ
+ __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
+ #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
+ #endif
+ #ifndef __ALIGNED
+ #define __ALIGNED(x) __align(x)
+ #endif
+ #ifndef __RESTRICT
+ #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
+ #define __RESTRICT
+ #endif
+
+
+/*
+ * COSMIC Compiler
+ */
+#elif defined ( __CSMC__ )
+ #include
+
+ #ifndef __ASM
+ #define __ASM _asm
+ #endif
+ #ifndef __INLINE
+ #define __INLINE inline
+ #endif
+ #ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static inline
+ #endif
+ #ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __STATIC_INLINE
+ #endif
+ #ifndef __NO_RETURN
+ // NO RETURN is automatically detected hence no warning here
+ #define __NO_RETURN
+ #endif
+ #ifndef __USED
+ #warning No compiler specific solution for __USED. __USED is ignored.
+ #define __USED
+ #endif
+ #ifndef __WEAK
+ #define __WEAK __weak
+ #endif
+ #ifndef __PACKED
+ #define __PACKED @packed
+ #endif
+ #ifndef __PACKED_STRUCT
+ #define __PACKED_STRUCT @packed struct
+ #endif
+ #ifndef __PACKED_UNION
+ #define __PACKED_UNION @packed union
+ #endif
+ #ifndef __UNALIGNED_UINT32 /* deprecated */
+ @packed struct T_UINT32 { uint32_t v; };
+ #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
+ #endif
+ #ifndef __UNALIGNED_UINT16_WRITE
+ __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
+ #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
+ #endif
+ #ifndef __UNALIGNED_UINT16_READ
+ __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
+ #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
+ #endif
+ #ifndef __UNALIGNED_UINT32_WRITE
+ __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
+ #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
+ #endif
+ #ifndef __UNALIGNED_UINT32_READ
+ __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
+ #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
+ #endif
+ #ifndef __ALIGNED
+ #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
+ #define __ALIGNED(x)
+ #endif
+ #ifndef __RESTRICT
+ #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
+ #define __RESTRICT
+ #endif
+
+
+#else
+ #error Unknown compiler.
+#endif
+
+
+#endif /* __CMSIS_COMPILER_H */
+
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/cmsis_gcc.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/cmsis_gcc.h
new file mode 100644
index 0000000..2d9db15
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/cmsis_gcc.h
@@ -0,0 +1,2085 @@
+/**************************************************************************//**
+ * @file cmsis_gcc.h
+ * @brief CMSIS compiler GCC header file
+ * @version V5.0.4
+ * @date 09. April 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CMSIS_GCC_H
+#define __CMSIS_GCC_H
+
+/* ignore some GCC warnings */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wsign-conversion"
+#pragma GCC diagnostic ignored "-Wconversion"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+
+/* Fallback for __has_builtin */
+#ifndef __has_builtin
+ #define __has_builtin(x) (0)
+#endif
+
+/* CMSIS compiler specific defines */
+#ifndef __ASM
+ #define __ASM __asm
+#endif
+#ifndef __INLINE
+ #define __INLINE inline
+#endif
+#ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static inline
+#endif
+#ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline
+#endif
+#ifndef __NO_RETURN
+ #define __NO_RETURN __attribute__((__noreturn__))
+#endif
+#ifndef __USED
+ #define __USED __attribute__((used))
+#endif
+#ifndef __WEAK
+ #define __WEAK __attribute__((weak))
+#endif
+#ifndef __PACKED
+ #define __PACKED __attribute__((packed, aligned(1)))
+#endif
+#ifndef __PACKED_STRUCT
+ #define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
+#endif
+#ifndef __PACKED_UNION
+ #define __PACKED_UNION union __attribute__((packed, aligned(1)))
+#endif
+#ifndef __UNALIGNED_UINT32 /* deprecated */
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpacked"
+ #pragma GCC diagnostic ignored "-Wattributes"
+ struct __attribute__((packed)) T_UINT32 { uint32_t v; };
+ #pragma GCC diagnostic pop
+ #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
+#endif
+#ifndef __UNALIGNED_UINT16_WRITE
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpacked"
+ #pragma GCC diagnostic ignored "-Wattributes"
+ __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
+ #pragma GCC diagnostic pop
+ #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
+#endif
+#ifndef __UNALIGNED_UINT16_READ
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpacked"
+ #pragma GCC diagnostic ignored "-Wattributes"
+ __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
+ #pragma GCC diagnostic pop
+ #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
+#endif
+#ifndef __UNALIGNED_UINT32_WRITE
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpacked"
+ #pragma GCC diagnostic ignored "-Wattributes"
+ __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
+ #pragma GCC diagnostic pop
+ #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
+#endif
+#ifndef __UNALIGNED_UINT32_READ
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpacked"
+ #pragma GCC diagnostic ignored "-Wattributes"
+ __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
+ #pragma GCC diagnostic pop
+ #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
+#endif
+#ifndef __ALIGNED
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+#endif
+#ifndef __RESTRICT
+ #define __RESTRICT __restrict
+#endif
+
+
+/* ########################### Core Function Access ########################### */
+/** \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
+ @{
+ */
+
+/**
+ \brief Enable IRQ Interrupts
+ \details Enables IRQ interrupts by clearing the I-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+__STATIC_FORCEINLINE void __enable_irq(void)
+{
+ __ASM volatile ("cpsie i" : : : "memory");
+}
+
+
+/**
+ \brief Disable IRQ Interrupts
+ \details Disables IRQ interrupts by setting the I-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+__STATIC_FORCEINLINE void __disable_irq(void)
+{
+ __ASM volatile ("cpsid i" : : : "memory");
+}
+
+
+/**
+ \brief Get Control Register
+ \details Returns the content of the Control Register.
+ \return Control Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_CONTROL(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, control" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Control Register (non-secure)
+ \details Returns the content of the non-secure Control Register when in secure mode.
+ \return non-secure Control Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, control_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Control Register
+ \details Writes the given value to the Control Register.
+ \param [in] control Control Register value to set
+ */
+__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control)
+{
+ __ASM volatile ("MSR control, %0" : : "r" (control) : "memory");
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Control Register (non-secure)
+ \details Writes the given value to the non-secure Control Register when in secure state.
+ \param [in] control Control Register value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control)
+{
+ __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory");
+}
+#endif
+
+
+/**
+ \brief Get IPSR Register
+ \details Returns the content of the IPSR Register.
+ \return IPSR Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_IPSR(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, ipsr" : "=r" (result) );
+ return(result);
+}
+
+
+/**
+ \brief Get APSR Register
+ \details Returns the content of the APSR Register.
+ \return APSR Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_APSR(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, apsr" : "=r" (result) );
+ return(result);
+}
+
+
+/**
+ \brief Get xPSR Register
+ \details Returns the content of the xPSR Register.
+ \return xPSR Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_xPSR(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, xpsr" : "=r" (result) );
+ return(result);
+}
+
+
+/**
+ \brief Get Process Stack Pointer
+ \details Returns the current value of the Process Stack Pointer (PSP).
+ \return PSP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_PSP(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, psp" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Process Stack Pointer (non-secure)
+ \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state.
+ \return PSP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, psp_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Process Stack Pointer
+ \details Assigns the given value to the Process Stack Pointer (PSP).
+ \param [in] topOfProcStack Process Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack)
+{
+ __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : );
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Process Stack Pointer (non-secure)
+ \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state.
+ \param [in] topOfProcStack Process Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack)
+{
+ __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : );
+}
+#endif
+
+
+/**
+ \brief Get Main Stack Pointer
+ \details Returns the current value of the Main Stack Pointer (MSP).
+ \return MSP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_MSP(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, msp" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Main Stack Pointer (non-secure)
+ \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state.
+ \return MSP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, msp_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Main Stack Pointer
+ \details Assigns the given value to the Main Stack Pointer (MSP).
+ \param [in] topOfMainStack Main Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack)
+{
+ __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : );
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Main Stack Pointer (non-secure)
+ \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state.
+ \param [in] topOfMainStack Main Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack)
+{
+ __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : );
+}
+#endif
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Stack Pointer (non-secure)
+ \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state.
+ \return SP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, sp_ns" : "=r" (result) );
+ return(result);
+}
+
+
+/**
+ \brief Set Stack Pointer (non-secure)
+ \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state.
+ \param [in] topOfStack Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack)
+{
+ __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : );
+}
+#endif
+
+
+/**
+ \brief Get Priority Mask
+ \details Returns the current state of the priority mask bit from the Priority Mask Register.
+ \return Priority Mask value
+ */
+__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, primask" : "=r" (result) :: "memory");
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Priority Mask (non-secure)
+ \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state.
+ \return Priority Mask value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, primask_ns" : "=r" (result) :: "memory");
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Priority Mask
+ \details Assigns the given value to the Priority Mask Register.
+ \param [in] priMask Priority Mask
+ */
+__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask)
+{
+ __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Priority Mask (non-secure)
+ \details Assigns the given value to the non-secure Priority Mask Register when in secure state.
+ \param [in] priMask Priority Mask
+ */
+__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask)
+{
+ __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory");
+}
+#endif
+
+
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) )
+/**
+ \brief Enable FIQ
+ \details Enables FIQ interrupts by clearing the F-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+__STATIC_FORCEINLINE void __enable_fault_irq(void)
+{
+ __ASM volatile ("cpsie f" : : : "memory");
+}
+
+
+/**
+ \brief Disable FIQ
+ \details Disables FIQ interrupts by setting the F-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+__STATIC_FORCEINLINE void __disable_fault_irq(void)
+{
+ __ASM volatile ("cpsid f" : : : "memory");
+}
+
+
+/**
+ \brief Get Base Priority
+ \details Returns the current value of the Base Priority register.
+ \return Base Priority register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, basepri" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Base Priority (non-secure)
+ \details Returns the current value of the non-secure Base Priority register when in secure state.
+ \return Base Priority register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Base Priority
+ \details Assigns the given value to the Base Priority register.
+ \param [in] basePri Base Priority value to set
+ */
+__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri)
+{
+ __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory");
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Base Priority (non-secure)
+ \details Assigns the given value to the non-secure Base Priority register when in secure state.
+ \param [in] basePri Base Priority value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri)
+{
+ __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory");
+}
+#endif
+
+
+/**
+ \brief Set Base Priority with condition
+ \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled,
+ or the new value increases the BASEPRI priority level.
+ \param [in] basePri Base Priority value to set
+ */
+__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri)
+{
+ __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory");
+}
+
+
+/**
+ \brief Get Fault Mask
+ \details Returns the current value of the Fault Mask register.
+ \return Fault Mask register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, faultmask" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Fault Mask (non-secure)
+ \details Returns the current value of the non-secure Fault Mask register when in secure state.
+ \return Fault Mask register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Fault Mask
+ \details Assigns the given value to the Fault Mask register.
+ \param [in] faultMask Fault Mask value to set
+ */
+__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask)
+{
+ __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory");
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Fault Mask (non-secure)
+ \details Assigns the given value to the non-secure Fault Mask register when in secure state.
+ \param [in] faultMask Fault Mask value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask)
+{
+ __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory");
+}
+#endif
+
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */
+
+
+#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
+
+/**
+ \brief Get Process Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always in non-secure
+ mode.
+
+ \details Returns the current value of the Process Stack Pointer Limit (PSPLIM).
+ \return PSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, psplim" : "=r" (result) );
+ return result;
+#endif
+}
+
+#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Process Stack Pointer Limit (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always.
+
+ \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state.
+ \return PSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) );
+ return result;
+#endif
+}
+#endif
+
+
+/**
+ \brief Set Process Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored in non-secure
+ mode.
+
+ \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM).
+ \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set
+ */
+__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ (void)ProcStackPtrLimit;
+#else
+ __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit));
+#endif
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Process Stack Pointer (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored.
+
+ \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state.
+ \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ (void)ProcStackPtrLimit;
+#else
+ __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit));
+#endif
+}
+#endif
+
+
+/**
+ \brief Get Main Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always in non-secure
+ mode.
+
+ \details Returns the current value of the Main Stack Pointer Limit (MSPLIM).
+ \return MSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, msplim" : "=r" (result) );
+ return result;
+#endif
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Main Stack Pointer Limit (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always.
+
+ \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state.
+ \return MSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) );
+ return result;
+#endif
+}
+#endif
+
+
+/**
+ \brief Set Main Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored in non-secure
+ mode.
+
+ \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM).
+ \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set
+ */
+__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ (void)MainStackPtrLimit;
+#else
+ __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit));
+#endif
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Main Stack Pointer Limit (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored.
+
+ \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state.
+ \param [in] MainStackPtrLimit Main Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ (void)MainStackPtrLimit;
+#else
+ __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit));
+#endif
+}
+#endif
+
+#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */
+
+
+/**
+ \brief Get FPSCR
+ \details Returns the current value of the Floating Point Status/Control register.
+ \return Floating Point Status/Control register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_FPSCR(void)
+{
+#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
+#if __has_builtin(__builtin_arm_get_fpscr)
+// Re-enable using built-in when GCC has been fixed
+// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
+ /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
+ return __builtin_arm_get_fpscr();
+#else
+ uint32_t result;
+
+ __ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
+ return(result);
+#endif
+#else
+ return(0U);
+#endif
+}
+
+
+/**
+ \brief Set FPSCR
+ \details Assigns the given value to the Floating Point Status/Control register.
+ \param [in] fpscr Floating Point Status/Control value to set
+ */
+__STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr)
+{
+#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
+#if __has_builtin(__builtin_arm_set_fpscr)
+// Re-enable using built-in when GCC has been fixed
+// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
+ /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
+ __builtin_arm_set_fpscr(fpscr);
+#else
+ __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory");
+#endif
+#else
+ (void)fpscr;
+#endif
+}
+
+
+/*@} end of CMSIS_Core_RegAccFunctions */
+
+
+/* ########################## Core Instruction Access ######################### */
+/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
+ Access to dedicated instructions
+ @{
+*/
+
+/* Define macros for porting to both thumb1 and thumb2.
+ * For thumb1, use low register (r0-r7), specified by constraint "l"
+ * Otherwise, use general registers, specified by constraint "r" */
+#if defined (__thumb__) && !defined (__thumb2__)
+#define __CMSIS_GCC_OUT_REG(r) "=l" (r)
+#define __CMSIS_GCC_RW_REG(r) "+l" (r)
+#define __CMSIS_GCC_USE_REG(r) "l" (r)
+#else
+#define __CMSIS_GCC_OUT_REG(r) "=r" (r)
+#define __CMSIS_GCC_RW_REG(r) "+r" (r)
+#define __CMSIS_GCC_USE_REG(r) "r" (r)
+#endif
+
+/**
+ \brief No Operation
+ \details No Operation does nothing. This instruction can be used for code alignment purposes.
+ */
+#define __NOP() __ASM volatile ("nop")
+
+/**
+ \brief Wait For Interrupt
+ \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
+ */
+#define __WFI() __ASM volatile ("wfi")
+
+
+/**
+ \brief Wait For Event
+ \details Wait For Event is a hint instruction that permits the processor to enter
+ a low-power state until one of a number of events occurs.
+ */
+#define __WFE() __ASM volatile ("wfe")
+
+
+/**
+ \brief Send Event
+ \details Send Event is a hint instruction. It causes an event to be signaled to the CPU.
+ */
+#define __SEV() __ASM volatile ("sev")
+
+
+/**
+ \brief Instruction Synchronization Barrier
+ \details Instruction Synchronization Barrier flushes the pipeline in the processor,
+ so that all instructions following the ISB are fetched from cache or memory,
+ after the instruction has been completed.
+ */
+__STATIC_FORCEINLINE void __ISB(void)
+{
+ __ASM volatile ("isb 0xF":::"memory");
+}
+
+
+/**
+ \brief Data Synchronization Barrier
+ \details Acts as a special kind of Data Memory Barrier.
+ It completes when all explicit memory accesses before this instruction complete.
+ */
+__STATIC_FORCEINLINE void __DSB(void)
+{
+ __ASM volatile ("dsb 0xF":::"memory");
+}
+
+
+/**
+ \brief Data Memory Barrier
+ \details Ensures the apparent order of the explicit memory operations before
+ and after the instruction, without ensuring their completion.
+ */
+__STATIC_FORCEINLINE void __DMB(void)
+{
+ __ASM volatile ("dmb 0xF":::"memory");
+}
+
+
+/**
+ \brief Reverse byte order (32 bit)
+ \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+__STATIC_FORCEINLINE uint32_t __REV(uint32_t value)
+{
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+ return __builtin_bswap32(value);
+#else
+ uint32_t result;
+
+ __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
+ return result;
+#endif
+}
+
+
+/**
+ \brief Reverse byte order (16 bit)
+ \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+__STATIC_FORCEINLINE uint32_t __REV16(uint32_t value)
+{
+ uint32_t result;
+
+ __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
+ return result;
+}
+
+
+/**
+ \brief Reverse byte order (16 bit)
+ \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+__STATIC_FORCEINLINE int16_t __REVSH(int16_t value)
+{
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+ return (int16_t)__builtin_bswap16(value);
+#else
+ int16_t result;
+
+ __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
+ return result;
+#endif
+}
+
+
+/**
+ \brief Rotate Right in unsigned value (32 bit)
+ \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
+ \param [in] op1 Value to rotate
+ \param [in] op2 Number of Bits to rotate
+ \return Rotated value
+ */
+__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
+{
+ op2 %= 32U;
+ if (op2 == 0U)
+ {
+ return op1;
+ }
+ return (op1 >> op2) | (op1 << (32U - op2));
+}
+
+
+/**
+ \brief Breakpoint
+ \details Causes the processor to enter Debug state.
+ Debug tools can use this to investigate system state when the instruction at a particular address is reached.
+ \param [in] value is ignored by the processor.
+ If required, a debugger can use it to store additional information about the breakpoint.
+ */
+#define __BKPT(value) __ASM volatile ("bkpt "#value)
+
+
+/**
+ \brief Reverse bit order of value
+ \details Reverses the bit order of the given value.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+__STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value)
+{
+ uint32_t result;
+
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) )
+ __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
+#else
+ uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */
+
+ result = value; /* r will be reversed bits of v; first get LSB of v */
+ for (value >>= 1U; value != 0U; value >>= 1U)
+ {
+ result <<= 1U;
+ result |= value & 1U;
+ s--;
+ }
+ result <<= s; /* shift when v's highest bits are zero */
+#endif
+ return result;
+}
+
+
+/**
+ \brief Count leading zeros
+ \details Counts the number of leading zeros of a data value.
+ \param [in] value Value to count the leading zeros
+ \return number of leading zeros in value
+ */
+#define __CLZ (uint8_t)__builtin_clz
+
+
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
+/**
+ \brief LDR Exclusive (8 bit)
+ \details Executes a exclusive LDR instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint8_t __LDREXB(volatile uint8_t *addr)
+{
+ uint32_t result;
+
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+ __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) );
+#else
+ /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
+ accepted by assembler. So has to use following less efficient pattern.
+ */
+ __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
+#endif
+ return ((uint8_t) result); /* Add explicit type cast here */
+}
+
+
+/**
+ \brief LDR Exclusive (16 bit)
+ \details Executes a exclusive LDR instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint16_t __LDREXH(volatile uint16_t *addr)
+{
+ uint32_t result;
+
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+ __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) );
+#else
+ /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
+ accepted by assembler. So has to use following less efficient pattern.
+ */
+ __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
+#endif
+ return ((uint16_t) result); /* Add explicit type cast here */
+}
+
+
+/**
+ \brief LDR Exclusive (32 bit)
+ \details Executes a exclusive LDR instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint32_t __LDREXW(volatile uint32_t *addr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) );
+ return(result);
+}
+
+
+/**
+ \brief STR Exclusive (8 bit)
+ \details Executes a exclusive STR instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+__STATIC_FORCEINLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
+{
+ uint32_t result;
+
+ __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
+ return(result);
+}
+
+
+/**
+ \brief STR Exclusive (16 bit)
+ \details Executes a exclusive STR instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+__STATIC_FORCEINLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
+{
+ uint32_t result;
+
+ __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
+ return(result);
+}
+
+
+/**
+ \brief STR Exclusive (32 bit)
+ \details Executes a exclusive STR instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+__STATIC_FORCEINLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
+{
+ uint32_t result;
+
+ __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) );
+ return(result);
+}
+
+
+/**
+ \brief Remove the exclusive lock
+ \details Removes the exclusive lock which is created by LDREX.
+ */
+__STATIC_FORCEINLINE void __CLREX(void)
+{
+ __ASM volatile ("clrex" ::: "memory");
+}
+
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */
+
+
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) )
+/**
+ \brief Signed Saturate
+ \details Saturates a signed value.
+ \param [in] ARG1 Value to be saturated
+ \param [in] ARG2 Bit position to saturate to (1..32)
+ \return Saturated value
+ */
+#define __SSAT(ARG1,ARG2) \
+__extension__ \
+({ \
+ int32_t __RES, __ARG1 = (ARG1); \
+ __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
+ __RES; \
+ })
+
+
+/**
+ \brief Unsigned Saturate
+ \details Saturates an unsigned value.
+ \param [in] ARG1 Value to be saturated
+ \param [in] ARG2 Bit position to saturate to (0..31)
+ \return Saturated value
+ */
+#define __USAT(ARG1,ARG2) \
+ __extension__ \
+({ \
+ uint32_t __RES, __ARG1 = (ARG1); \
+ __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
+ __RES; \
+ })
+
+
+/**
+ \brief Rotate Right with Extend (32 bit)
+ \details Moves each bit of a bitstring right by one bit.
+ The carry input is shifted in at the left end of the bitstring.
+ \param [in] value Value to rotate
+ \return Rotated value
+ */
+__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value)
+{
+ uint32_t result;
+
+ __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
+ return(result);
+}
+
+
+/**
+ \brief LDRT Unprivileged (8 bit)
+ \details Executes a Unprivileged LDRT instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr)
+{
+ uint32_t result;
+
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+ __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) );
+#else
+ /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
+ accepted by assembler. So has to use following less efficient pattern.
+ */
+ __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" );
+#endif
+ return ((uint8_t) result); /* Add explicit type cast here */
+}
+
+
+/**
+ \brief LDRT Unprivileged (16 bit)
+ \details Executes a Unprivileged LDRT instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr)
+{
+ uint32_t result;
+
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+ __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) );
+#else
+ /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
+ accepted by assembler. So has to use following less efficient pattern.
+ */
+ __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" );
+#endif
+ return ((uint16_t) result); /* Add explicit type cast here */
+}
+
+
+/**
+ \brief LDRT Unprivileged (32 bit)
+ \details Executes a Unprivileged LDRT instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return(result);
+}
+
+
+/**
+ \brief STRT Unprivileged (8 bit)
+ \details Executes a Unprivileged STRT instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr)
+{
+ __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief STRT Unprivileged (16 bit)
+ \details Executes a Unprivileged STRT instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr)
+{
+ __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief STRT Unprivileged (32 bit)
+ \details Executes a Unprivileged STRT instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr)
+{
+ __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) );
+}
+
+#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */
+
+/**
+ \brief Signed Saturate
+ \details Saturates a signed value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (1..32)
+ \return Saturated value
+ */
+__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat)
+{
+ if ((sat >= 1U) && (sat <= 32U))
+ {
+ const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
+ const int32_t min = -1 - max ;
+ if (val > max)
+ {
+ return max;
+ }
+ else if (val < min)
+ {
+ return min;
+ }
+ }
+ return val;
+}
+
+/**
+ \brief Unsigned Saturate
+ \details Saturates an unsigned value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (0..31)
+ \return Saturated value
+ */
+__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat)
+{
+ if (sat <= 31U)
+ {
+ const uint32_t max = ((1U << sat) - 1U);
+ if (val > (int32_t)max)
+ {
+ return max;
+ }
+ else if (val < 0)
+ {
+ return 0U;
+ }
+ }
+ return (uint32_t)val;
+}
+
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */
+
+
+#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
+/**
+ \brief Load-Acquire (8 bit)
+ \details Executes a LDAB instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint8_t) result);
+}
+
+
+/**
+ \brief Load-Acquire (16 bit)
+ \details Executes a LDAH instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint16_t) result);
+}
+
+
+/**
+ \brief Load-Acquire (32 bit)
+ \details Executes a LDA instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return(result);
+}
+
+
+/**
+ \brief Store-Release (8 bit)
+ \details Executes a STLB instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr)
+{
+ __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief Store-Release (16 bit)
+ \details Executes a STLH instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr)
+{
+ __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief Store-Release (32 bit)
+ \details Executes a STL instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr)
+{
+ __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief Load-Acquire Exclusive (8 bit)
+ \details Executes a LDAB exclusive instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint8_t __LDAEXB(volatile uint8_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldaexb %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint8_t) result);
+}
+
+
+/**
+ \brief Load-Acquire Exclusive (16 bit)
+ \details Executes a LDAH exclusive instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint16_t __LDAEXH(volatile uint16_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldaexh %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint16_t) result);
+}
+
+
+/**
+ \brief Load-Acquire Exclusive (32 bit)
+ \details Executes a LDA exclusive instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint32_t __LDAEX(volatile uint32_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldaex %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return(result);
+}
+
+
+/**
+ \brief Store-Release Exclusive (8 bit)
+ \details Executes a STLB exclusive instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+__STATIC_FORCEINLINE uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("stlexb %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) );
+ return(result);
+}
+
+
+/**
+ \brief Store-Release Exclusive (16 bit)
+ \details Executes a STLH exclusive instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+__STATIC_FORCEINLINE uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("stlexh %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) );
+ return(result);
+}
+
+
+/**
+ \brief Store-Release Exclusive (32 bit)
+ \details Executes a STL exclusive instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+__STATIC_FORCEINLINE uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("stlex %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) );
+ return(result);
+}
+
+#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */
+
+/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
+
+
+/* ################### Compiler specific Intrinsics ########################### */
+/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
+ Access to dedicated SIMD instructions
+ @{
+*/
+
+#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1))
+
+__STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+
+__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+
+__STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3)
+{
+ uint32_t result;
+
+ __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+#define __SSAT16(ARG1,ARG2) \
+({ \
+ int32_t __RES, __ARG1 = (ARG1); \
+ __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
+ __RES; \
+ })
+
+#define __USAT16(ARG1,ARG2) \
+({ \
+ uint32_t __RES, __ARG1 = (ARG1); \
+ __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
+ __RES; \
+ })
+
+__STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1)
+{
+ uint32_t result;
+
+ __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1));
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1)
+{
+ uint32_t result;
+
+ __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1));
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3)
+{
+ uint32_t result;
+
+ __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3)
+{
+ uint32_t result;
+
+ __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc)
+{
+ union llreg_u{
+ uint32_t w32[2];
+ uint64_t w64;
+ } llr;
+ llr.w64 = acc;
+
+#ifndef __ARMEB__ /* Little endian */
+ __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
+#else /* Big endian */
+ __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
+#endif
+
+ return(llr.w64);
+}
+
+__STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc)
+{
+ union llreg_u{
+ uint32_t w32[2];
+ uint64_t w64;
+ } llr;
+ llr.w64 = acc;
+
+#ifndef __ARMEB__ /* Little endian */
+ __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
+#else /* Big endian */
+ __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
+#endif
+
+ return(llr.w64);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3)
+{
+ uint32_t result;
+
+ __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3)
+{
+ uint32_t result;
+
+ __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc)
+{
+ union llreg_u{
+ uint32_t w32[2];
+ uint64_t w64;
+ } llr;
+ llr.w64 = acc;
+
+#ifndef __ARMEB__ /* Little endian */
+ __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
+#else /* Big endian */
+ __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
+#endif
+
+ return(llr.w64);
+}
+
+__STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc)
+{
+ union llreg_u{
+ uint32_t w32[2];
+ uint64_t w64;
+ } llr;
+ llr.w64 = acc;
+
+#ifndef __ARMEB__ /* Little endian */
+ __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
+#else /* Big endian */
+ __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
+#endif
+
+ return(llr.w64);
+}
+
+__STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2)
+{
+ int32_t result;
+
+ __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2)
+{
+ int32_t result;
+
+ __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+#if 0
+#define __PKHBT(ARG1,ARG2,ARG3) \
+({ \
+ uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
+ __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \
+ __RES; \
+ })
+
+#define __PKHTB(ARG1,ARG2,ARG3) \
+({ \
+ uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
+ if (ARG3 == 0) \
+ __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \
+ else \
+ __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \
+ __RES; \
+ })
+#endif
+
+#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
+ ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
+
+#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
+ ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
+
+__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3)
+{
+ int32_t result;
+
+ __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+#endif /* (__ARM_FEATURE_DSP == 1) */
+/*@} end of group CMSIS_SIMD_intrinsics */
+
+
+#pragma GCC diagnostic pop
+
+#endif /* __CMSIS_GCC_H */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/cmsis_iccarm.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/cmsis_iccarm.h
new file mode 100644
index 0000000..11c4af0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/cmsis_iccarm.h
@@ -0,0 +1,935 @@
+/**************************************************************************//**
+ * @file cmsis_iccarm.h
+ * @brief CMSIS compiler ICCARM (IAR Compiler for Arm) header file
+ * @version V5.0.7
+ * @date 19. June 2018
+ ******************************************************************************/
+
+//------------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2018 IAR Systems
+//
+// Licensed under the Apache License, Version 2.0 (the "License")
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//------------------------------------------------------------------------------
+
+
+#ifndef __CMSIS_ICCARM_H__
+#define __CMSIS_ICCARM_H__
+
+#ifndef __ICCARM__
+ #error This file should only be compiled by ICCARM
+#endif
+
+#pragma system_include
+
+#define __IAR_FT _Pragma("inline=forced") __intrinsic
+
+#if (__VER__ >= 8000000)
+ #define __ICCARM_V8 1
+#else
+ #define __ICCARM_V8 0
+#endif
+
+#ifndef __ALIGNED
+ #if __ICCARM_V8
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+ #elif (__VER__ >= 7080000)
+ /* Needs IAR language extensions */
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+ #else
+ #warning No compiler specific solution for __ALIGNED.__ALIGNED is ignored.
+ #define __ALIGNED(x)
+ #endif
+#endif
+
+
+/* Define compiler macros for CPU architecture, used in CMSIS 5.
+ */
+#if __ARM_ARCH_6M__ || __ARM_ARCH_7M__ || __ARM_ARCH_7EM__ || __ARM_ARCH_8M_BASE__ || __ARM_ARCH_8M_MAIN__
+/* Macros already defined */
+#else
+ #if defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__)
+ #define __ARM_ARCH_8M_MAIN__ 1
+ #elif defined(__ARM8M_BASELINE__)
+ #define __ARM_ARCH_8M_BASE__ 1
+ #elif defined(__ARM_ARCH_PROFILE) && __ARM_ARCH_PROFILE == 'M'
+ #if __ARM_ARCH == 6
+ #define __ARM_ARCH_6M__ 1
+ #elif __ARM_ARCH == 7
+ #if __ARM_FEATURE_DSP
+ #define __ARM_ARCH_7EM__ 1
+ #else
+ #define __ARM_ARCH_7M__ 1
+ #endif
+ #endif /* __ARM_ARCH */
+ #endif /* __ARM_ARCH_PROFILE == 'M' */
+#endif
+
+/* Alternativ core deduction for older ICCARM's */
+#if !defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_7M__) && !defined(__ARM_ARCH_7EM__) && \
+ !defined(__ARM_ARCH_8M_BASE__) && !defined(__ARM_ARCH_8M_MAIN__)
+ #if defined(__ARM6M__) && (__CORE__ == __ARM6M__)
+ #define __ARM_ARCH_6M__ 1
+ #elif defined(__ARM7M__) && (__CORE__ == __ARM7M__)
+ #define __ARM_ARCH_7M__ 1
+ #elif defined(__ARM7EM__) && (__CORE__ == __ARM7EM__)
+ #define __ARM_ARCH_7EM__ 1
+ #elif defined(__ARM8M_BASELINE__) && (__CORE == __ARM8M_BASELINE__)
+ #define __ARM_ARCH_8M_BASE__ 1
+ #elif defined(__ARM8M_MAINLINE__) && (__CORE == __ARM8M_MAINLINE__)
+ #define __ARM_ARCH_8M_MAIN__ 1
+ #elif defined(__ARM8EM_MAINLINE__) && (__CORE == __ARM8EM_MAINLINE__)
+ #define __ARM_ARCH_8M_MAIN__ 1
+ #else
+ #error "Unknown target."
+ #endif
+#endif
+
+
+
+#if defined(__ARM_ARCH_6M__) && __ARM_ARCH_6M__==1
+ #define __IAR_M0_FAMILY 1
+#elif defined(__ARM_ARCH_8M_BASE__) && __ARM_ARCH_8M_BASE__==1
+ #define __IAR_M0_FAMILY 1
+#else
+ #define __IAR_M0_FAMILY 0
+#endif
+
+
+#ifndef __ASM
+ #define __ASM __asm
+#endif
+
+#ifndef __INLINE
+ #define __INLINE inline
+#endif
+
+#ifndef __NO_RETURN
+ #if __ICCARM_V8
+ #define __NO_RETURN __attribute__((__noreturn__))
+ #else
+ #define __NO_RETURN _Pragma("object_attribute=__noreturn")
+ #endif
+#endif
+
+#ifndef __PACKED
+ #if __ICCARM_V8
+ #define __PACKED __attribute__((packed, aligned(1)))
+ #else
+ /* Needs IAR language extensions */
+ #define __PACKED __packed
+ #endif
+#endif
+
+#ifndef __PACKED_STRUCT
+ #if __ICCARM_V8
+ #define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
+ #else
+ /* Needs IAR language extensions */
+ #define __PACKED_STRUCT __packed struct
+ #endif
+#endif
+
+#ifndef __PACKED_UNION
+ #if __ICCARM_V8
+ #define __PACKED_UNION union __attribute__((packed, aligned(1)))
+ #else
+ /* Needs IAR language extensions */
+ #define __PACKED_UNION __packed union
+ #endif
+#endif
+
+#ifndef __RESTRICT
+ #define __RESTRICT __restrict
+#endif
+
+#ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static inline
+#endif
+
+#ifndef __FORCEINLINE
+ #define __FORCEINLINE _Pragma("inline=forced")
+#endif
+
+#ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __FORCEINLINE __STATIC_INLINE
+#endif
+
+#ifndef __UNALIGNED_UINT16_READ
+#pragma language=save
+#pragma language=extended
+__IAR_FT uint16_t __iar_uint16_read(void const *ptr)
+{
+ return *(__packed uint16_t*)(ptr);
+}
+#pragma language=restore
+#define __UNALIGNED_UINT16_READ(PTR) __iar_uint16_read(PTR)
+#endif
+
+
+#ifndef __UNALIGNED_UINT16_WRITE
+#pragma language=save
+#pragma language=extended
+__IAR_FT void __iar_uint16_write(void const *ptr, uint16_t val)
+{
+ *(__packed uint16_t*)(ptr) = val;;
+}
+#pragma language=restore
+#define __UNALIGNED_UINT16_WRITE(PTR,VAL) __iar_uint16_write(PTR,VAL)
+#endif
+
+#ifndef __UNALIGNED_UINT32_READ
+#pragma language=save
+#pragma language=extended
+__IAR_FT uint32_t __iar_uint32_read(void const *ptr)
+{
+ return *(__packed uint32_t*)(ptr);
+}
+#pragma language=restore
+#define __UNALIGNED_UINT32_READ(PTR) __iar_uint32_read(PTR)
+#endif
+
+#ifndef __UNALIGNED_UINT32_WRITE
+#pragma language=save
+#pragma language=extended
+__IAR_FT void __iar_uint32_write(void const *ptr, uint32_t val)
+{
+ *(__packed uint32_t*)(ptr) = val;;
+}
+#pragma language=restore
+#define __UNALIGNED_UINT32_WRITE(PTR,VAL) __iar_uint32_write(PTR,VAL)
+#endif
+
+#ifndef __UNALIGNED_UINT32 /* deprecated */
+#pragma language=save
+#pragma language=extended
+__packed struct __iar_u32 { uint32_t v; };
+#pragma language=restore
+#define __UNALIGNED_UINT32(PTR) (((struct __iar_u32 *)(PTR))->v)
+#endif
+
+#ifndef __USED
+ #if __ICCARM_V8
+ #define __USED __attribute__((used))
+ #else
+ #define __USED _Pragma("__root")
+ #endif
+#endif
+
+#ifndef __WEAK
+ #if __ICCARM_V8
+ #define __WEAK __attribute__((weak))
+ #else
+ #define __WEAK _Pragma("__weak")
+ #endif
+#endif
+
+
+#ifndef __ICCARM_INTRINSICS_VERSION__
+ #define __ICCARM_INTRINSICS_VERSION__ 0
+#endif
+
+#if __ICCARM_INTRINSICS_VERSION__ == 2
+
+ #if defined(__CLZ)
+ #undef __CLZ
+ #endif
+ #if defined(__REVSH)
+ #undef __REVSH
+ #endif
+ #if defined(__RBIT)
+ #undef __RBIT
+ #endif
+ #if defined(__SSAT)
+ #undef __SSAT
+ #endif
+ #if defined(__USAT)
+ #undef __USAT
+ #endif
+
+ #include "iccarm_builtin.h"
+
+ #define __disable_fault_irq __iar_builtin_disable_fiq
+ #define __disable_irq __iar_builtin_disable_interrupt
+ #define __enable_fault_irq __iar_builtin_enable_fiq
+ #define __enable_irq __iar_builtin_enable_interrupt
+ #define __arm_rsr __iar_builtin_rsr
+ #define __arm_wsr __iar_builtin_wsr
+
+
+ #define __get_APSR() (__arm_rsr("APSR"))
+ #define __get_BASEPRI() (__arm_rsr("BASEPRI"))
+ #define __get_CONTROL() (__arm_rsr("CONTROL"))
+ #define __get_FAULTMASK() (__arm_rsr("FAULTMASK"))
+
+ #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
+ #define __get_FPSCR() (__arm_rsr("FPSCR"))
+ #define __set_FPSCR(VALUE) (__arm_wsr("FPSCR", (VALUE)))
+ #else
+ #define __get_FPSCR() ( 0 )
+ #define __set_FPSCR(VALUE) ((void)VALUE)
+ #endif
+
+ #define __get_IPSR() (__arm_rsr("IPSR"))
+ #define __get_MSP() (__arm_rsr("MSP"))
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ #define __get_MSPLIM() (0U)
+ #else
+ #define __get_MSPLIM() (__arm_rsr("MSPLIM"))
+ #endif
+ #define __get_PRIMASK() (__arm_rsr("PRIMASK"))
+ #define __get_PSP() (__arm_rsr("PSP"))
+
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ #define __get_PSPLIM() (0U)
+ #else
+ #define __get_PSPLIM() (__arm_rsr("PSPLIM"))
+ #endif
+
+ #define __get_xPSR() (__arm_rsr("xPSR"))
+
+ #define __set_BASEPRI(VALUE) (__arm_wsr("BASEPRI", (VALUE)))
+ #define __set_BASEPRI_MAX(VALUE) (__arm_wsr("BASEPRI_MAX", (VALUE)))
+ #define __set_CONTROL(VALUE) (__arm_wsr("CONTROL", (VALUE)))
+ #define __set_FAULTMASK(VALUE) (__arm_wsr("FAULTMASK", (VALUE)))
+ #define __set_MSP(VALUE) (__arm_wsr("MSP", (VALUE)))
+
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ #define __set_MSPLIM(VALUE) ((void)(VALUE))
+ #else
+ #define __set_MSPLIM(VALUE) (__arm_wsr("MSPLIM", (VALUE)))
+ #endif
+ #define __set_PRIMASK(VALUE) (__arm_wsr("PRIMASK", (VALUE)))
+ #define __set_PSP(VALUE) (__arm_wsr("PSP", (VALUE)))
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ #define __set_PSPLIM(VALUE) ((void)(VALUE))
+ #else
+ #define __set_PSPLIM(VALUE) (__arm_wsr("PSPLIM", (VALUE)))
+ #endif
+
+ #define __TZ_get_CONTROL_NS() (__arm_rsr("CONTROL_NS"))
+ #define __TZ_set_CONTROL_NS(VALUE) (__arm_wsr("CONTROL_NS", (VALUE)))
+ #define __TZ_get_PSP_NS() (__arm_rsr("PSP_NS"))
+ #define __TZ_set_PSP_NS(VALUE) (__arm_wsr("PSP_NS", (VALUE)))
+ #define __TZ_get_MSP_NS() (__arm_rsr("MSP_NS"))
+ #define __TZ_set_MSP_NS(VALUE) (__arm_wsr("MSP_NS", (VALUE)))
+ #define __TZ_get_SP_NS() (__arm_rsr("SP_NS"))
+ #define __TZ_set_SP_NS(VALUE) (__arm_wsr("SP_NS", (VALUE)))
+ #define __TZ_get_PRIMASK_NS() (__arm_rsr("PRIMASK_NS"))
+ #define __TZ_set_PRIMASK_NS(VALUE) (__arm_wsr("PRIMASK_NS", (VALUE)))
+ #define __TZ_get_BASEPRI_NS() (__arm_rsr("BASEPRI_NS"))
+ #define __TZ_set_BASEPRI_NS(VALUE) (__arm_wsr("BASEPRI_NS", (VALUE)))
+ #define __TZ_get_FAULTMASK_NS() (__arm_rsr("FAULTMASK_NS"))
+ #define __TZ_set_FAULTMASK_NS(VALUE)(__arm_wsr("FAULTMASK_NS", (VALUE)))
+
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ #define __TZ_get_PSPLIM_NS() (0U)
+ #define __TZ_set_PSPLIM_NS(VALUE) ((void)(VALUE))
+ #else
+ #define __TZ_get_PSPLIM_NS() (__arm_rsr("PSPLIM_NS"))
+ #define __TZ_set_PSPLIM_NS(VALUE) (__arm_wsr("PSPLIM_NS", (VALUE)))
+ #endif
+
+ #define __TZ_get_MSPLIM_NS() (__arm_rsr("MSPLIM_NS"))
+ #define __TZ_set_MSPLIM_NS(VALUE) (__arm_wsr("MSPLIM_NS", (VALUE)))
+
+ #define __NOP __iar_builtin_no_operation
+
+ #define __CLZ __iar_builtin_CLZ
+ #define __CLREX __iar_builtin_CLREX
+
+ #define __DMB __iar_builtin_DMB
+ #define __DSB __iar_builtin_DSB
+ #define __ISB __iar_builtin_ISB
+
+ #define __LDREXB __iar_builtin_LDREXB
+ #define __LDREXH __iar_builtin_LDREXH
+ #define __LDREXW __iar_builtin_LDREX
+
+ #define __RBIT __iar_builtin_RBIT
+ #define __REV __iar_builtin_REV
+ #define __REV16 __iar_builtin_REV16
+
+ __IAR_FT int16_t __REVSH(int16_t val)
+ {
+ return (int16_t) __iar_builtin_REVSH(val);
+ }
+
+ #define __ROR __iar_builtin_ROR
+ #define __RRX __iar_builtin_RRX
+
+ #define __SEV __iar_builtin_SEV
+
+ #if !__IAR_M0_FAMILY
+ #define __SSAT __iar_builtin_SSAT
+ #endif
+
+ #define __STREXB __iar_builtin_STREXB
+ #define __STREXH __iar_builtin_STREXH
+ #define __STREXW __iar_builtin_STREX
+
+ #if !__IAR_M0_FAMILY
+ #define __USAT __iar_builtin_USAT
+ #endif
+
+ #define __WFE __iar_builtin_WFE
+ #define __WFI __iar_builtin_WFI
+
+ #if __ARM_MEDIA__
+ #define __SADD8 __iar_builtin_SADD8
+ #define __QADD8 __iar_builtin_QADD8
+ #define __SHADD8 __iar_builtin_SHADD8
+ #define __UADD8 __iar_builtin_UADD8
+ #define __UQADD8 __iar_builtin_UQADD8
+ #define __UHADD8 __iar_builtin_UHADD8
+ #define __SSUB8 __iar_builtin_SSUB8
+ #define __QSUB8 __iar_builtin_QSUB8
+ #define __SHSUB8 __iar_builtin_SHSUB8
+ #define __USUB8 __iar_builtin_USUB8
+ #define __UQSUB8 __iar_builtin_UQSUB8
+ #define __UHSUB8 __iar_builtin_UHSUB8
+ #define __SADD16 __iar_builtin_SADD16
+ #define __QADD16 __iar_builtin_QADD16
+ #define __SHADD16 __iar_builtin_SHADD16
+ #define __UADD16 __iar_builtin_UADD16
+ #define __UQADD16 __iar_builtin_UQADD16
+ #define __UHADD16 __iar_builtin_UHADD16
+ #define __SSUB16 __iar_builtin_SSUB16
+ #define __QSUB16 __iar_builtin_QSUB16
+ #define __SHSUB16 __iar_builtin_SHSUB16
+ #define __USUB16 __iar_builtin_USUB16
+ #define __UQSUB16 __iar_builtin_UQSUB16
+ #define __UHSUB16 __iar_builtin_UHSUB16
+ #define __SASX __iar_builtin_SASX
+ #define __QASX __iar_builtin_QASX
+ #define __SHASX __iar_builtin_SHASX
+ #define __UASX __iar_builtin_UASX
+ #define __UQASX __iar_builtin_UQASX
+ #define __UHASX __iar_builtin_UHASX
+ #define __SSAX __iar_builtin_SSAX
+ #define __QSAX __iar_builtin_QSAX
+ #define __SHSAX __iar_builtin_SHSAX
+ #define __USAX __iar_builtin_USAX
+ #define __UQSAX __iar_builtin_UQSAX
+ #define __UHSAX __iar_builtin_UHSAX
+ #define __USAD8 __iar_builtin_USAD8
+ #define __USADA8 __iar_builtin_USADA8
+ #define __SSAT16 __iar_builtin_SSAT16
+ #define __USAT16 __iar_builtin_USAT16
+ #define __UXTB16 __iar_builtin_UXTB16
+ #define __UXTAB16 __iar_builtin_UXTAB16
+ #define __SXTB16 __iar_builtin_SXTB16
+ #define __SXTAB16 __iar_builtin_SXTAB16
+ #define __SMUAD __iar_builtin_SMUAD
+ #define __SMUADX __iar_builtin_SMUADX
+ #define __SMMLA __iar_builtin_SMMLA
+ #define __SMLAD __iar_builtin_SMLAD
+ #define __SMLADX __iar_builtin_SMLADX
+ #define __SMLALD __iar_builtin_SMLALD
+ #define __SMLALDX __iar_builtin_SMLALDX
+ #define __SMUSD __iar_builtin_SMUSD
+ #define __SMUSDX __iar_builtin_SMUSDX
+ #define __SMLSD __iar_builtin_SMLSD
+ #define __SMLSDX __iar_builtin_SMLSDX
+ #define __SMLSLD __iar_builtin_SMLSLD
+ #define __SMLSLDX __iar_builtin_SMLSLDX
+ #define __SEL __iar_builtin_SEL
+ #define __QADD __iar_builtin_QADD
+ #define __QSUB __iar_builtin_QSUB
+ #define __PKHBT __iar_builtin_PKHBT
+ #define __PKHTB __iar_builtin_PKHTB
+ #endif
+
+#else /* __ICCARM_INTRINSICS_VERSION__ == 2 */
+
+ #if __IAR_M0_FAMILY
+ /* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */
+ #define __CLZ __cmsis_iar_clz_not_active
+ #define __SSAT __cmsis_iar_ssat_not_active
+ #define __USAT __cmsis_iar_usat_not_active
+ #define __RBIT __cmsis_iar_rbit_not_active
+ #define __get_APSR __cmsis_iar_get_APSR_not_active
+ #endif
+
+
+ #if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) ))
+ #define __get_FPSCR __cmsis_iar_get_FPSR_not_active
+ #define __set_FPSCR __cmsis_iar_set_FPSR_not_active
+ #endif
+
+ #ifdef __INTRINSICS_INCLUDED
+ #error intrinsics.h is already included previously!
+ #endif
+
+ #include
+
+ #if __IAR_M0_FAMILY
+ /* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */
+ #undef __CLZ
+ #undef __SSAT
+ #undef __USAT
+ #undef __RBIT
+ #undef __get_APSR
+
+ __STATIC_INLINE uint8_t __CLZ(uint32_t data)
+ {
+ if (data == 0U) { return 32U; }
+
+ uint32_t count = 0U;
+ uint32_t mask = 0x80000000U;
+
+ while ((data & mask) == 0U)
+ {
+ count += 1U;
+ mask = mask >> 1U;
+ }
+ return count;
+ }
+
+ __STATIC_INLINE uint32_t __RBIT(uint32_t v)
+ {
+ uint8_t sc = 31U;
+ uint32_t r = v;
+ for (v >>= 1U; v; v >>= 1U)
+ {
+ r <<= 1U;
+ r |= v & 1U;
+ sc--;
+ }
+ return (r << sc);
+ }
+
+ __STATIC_INLINE uint32_t __get_APSR(void)
+ {
+ uint32_t res;
+ __asm("MRS %0,APSR" : "=r" (res));
+ return res;
+ }
+
+ #endif
+
+ #if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) ))
+ #undef __get_FPSCR
+ #undef __set_FPSCR
+ #define __get_FPSCR() (0)
+ #define __set_FPSCR(VALUE) ((void)VALUE)
+ #endif
+
+ #pragma diag_suppress=Pe940
+ #pragma diag_suppress=Pe177
+
+ #define __enable_irq __enable_interrupt
+ #define __disable_irq __disable_interrupt
+ #define __NOP __no_operation
+
+ #define __get_xPSR __get_PSR
+
+ #if (!defined(__ARM_ARCH_6M__) || __ARM_ARCH_6M__==0)
+
+ __IAR_FT uint32_t __LDREXW(uint32_t volatile *ptr)
+ {
+ return __LDREX((unsigned long *)ptr);
+ }
+
+ __IAR_FT uint32_t __STREXW(uint32_t value, uint32_t volatile *ptr)
+ {
+ return __STREX(value, (unsigned long *)ptr);
+ }
+ #endif
+
+
+ /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */
+ #if (__CORTEX_M >= 0x03)
+
+ __IAR_FT uint32_t __RRX(uint32_t value)
+ {
+ uint32_t result;
+ __ASM("RRX %0, %1" : "=r"(result) : "r" (value) : "cc");
+ return(result);
+ }
+
+ __IAR_FT void __set_BASEPRI_MAX(uint32_t value)
+ {
+ __asm volatile("MSR BASEPRI_MAX,%0"::"r" (value));
+ }
+
+
+ #define __enable_fault_irq __enable_fiq
+ #define __disable_fault_irq __disable_fiq
+
+
+ #endif /* (__CORTEX_M >= 0x03) */
+
+ __IAR_FT uint32_t __ROR(uint32_t op1, uint32_t op2)
+ {
+ return (op1 >> op2) | (op1 << ((sizeof(op1)*8)-op2));
+ }
+
+ #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
+
+ __IAR_FT uint32_t __get_MSPLIM(void)
+ {
+ uint32_t res;
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ res = 0U;
+ #else
+ __asm volatile("MRS %0,MSPLIM" : "=r" (res));
+ #endif
+ return res;
+ }
+
+ __IAR_FT void __set_MSPLIM(uint32_t value)
+ {
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ (void)value;
+ #else
+ __asm volatile("MSR MSPLIM,%0" :: "r" (value));
+ #endif
+ }
+
+ __IAR_FT uint32_t __get_PSPLIM(void)
+ {
+ uint32_t res;
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ res = 0U;
+ #else
+ __asm volatile("MRS %0,PSPLIM" : "=r" (res));
+ #endif
+ return res;
+ }
+
+ __IAR_FT void __set_PSPLIM(uint32_t value)
+ {
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ (void)value;
+ #else
+ __asm volatile("MSR PSPLIM,%0" :: "r" (value));
+ #endif
+ }
+
+ __IAR_FT uint32_t __TZ_get_CONTROL_NS(void)
+ {
+ uint32_t res;
+ __asm volatile("MRS %0,CONTROL_NS" : "=r" (res));
+ return res;
+ }
+
+ __IAR_FT void __TZ_set_CONTROL_NS(uint32_t value)
+ {
+ __asm volatile("MSR CONTROL_NS,%0" :: "r" (value));
+ }
+
+ __IAR_FT uint32_t __TZ_get_PSP_NS(void)
+ {
+ uint32_t res;
+ __asm volatile("MRS %0,PSP_NS" : "=r" (res));
+ return res;
+ }
+
+ __IAR_FT void __TZ_set_PSP_NS(uint32_t value)
+ {
+ __asm volatile("MSR PSP_NS,%0" :: "r" (value));
+ }
+
+ __IAR_FT uint32_t __TZ_get_MSP_NS(void)
+ {
+ uint32_t res;
+ __asm volatile("MRS %0,MSP_NS" : "=r" (res));
+ return res;
+ }
+
+ __IAR_FT void __TZ_set_MSP_NS(uint32_t value)
+ {
+ __asm volatile("MSR MSP_NS,%0" :: "r" (value));
+ }
+
+ __IAR_FT uint32_t __TZ_get_SP_NS(void)
+ {
+ uint32_t res;
+ __asm volatile("MRS %0,SP_NS" : "=r" (res));
+ return res;
+ }
+ __IAR_FT void __TZ_set_SP_NS(uint32_t value)
+ {
+ __asm volatile("MSR SP_NS,%0" :: "r" (value));
+ }
+
+ __IAR_FT uint32_t __TZ_get_PRIMASK_NS(void)
+ {
+ uint32_t res;
+ __asm volatile("MRS %0,PRIMASK_NS" : "=r" (res));
+ return res;
+ }
+
+ __IAR_FT void __TZ_set_PRIMASK_NS(uint32_t value)
+ {
+ __asm volatile("MSR PRIMASK_NS,%0" :: "r" (value));
+ }
+
+ __IAR_FT uint32_t __TZ_get_BASEPRI_NS(void)
+ {
+ uint32_t res;
+ __asm volatile("MRS %0,BASEPRI_NS" : "=r" (res));
+ return res;
+ }
+
+ __IAR_FT void __TZ_set_BASEPRI_NS(uint32_t value)
+ {
+ __asm volatile("MSR BASEPRI_NS,%0" :: "r" (value));
+ }
+
+ __IAR_FT uint32_t __TZ_get_FAULTMASK_NS(void)
+ {
+ uint32_t res;
+ __asm volatile("MRS %0,FAULTMASK_NS" : "=r" (res));
+ return res;
+ }
+
+ __IAR_FT void __TZ_set_FAULTMASK_NS(uint32_t value)
+ {
+ __asm volatile("MSR FAULTMASK_NS,%0" :: "r" (value));
+ }
+
+ __IAR_FT uint32_t __TZ_get_PSPLIM_NS(void)
+ {
+ uint32_t res;
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ res = 0U;
+ #else
+ __asm volatile("MRS %0,PSPLIM_NS" : "=r" (res));
+ #endif
+ return res;
+ }
+
+ __IAR_FT void __TZ_set_PSPLIM_NS(uint32_t value)
+ {
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ (void)value;
+ #else
+ __asm volatile("MSR PSPLIM_NS,%0" :: "r" (value));
+ #endif
+ }
+
+ __IAR_FT uint32_t __TZ_get_MSPLIM_NS(void)
+ {
+ uint32_t res;
+ __asm volatile("MRS %0,MSPLIM_NS" : "=r" (res));
+ return res;
+ }
+
+ __IAR_FT void __TZ_set_MSPLIM_NS(uint32_t value)
+ {
+ __asm volatile("MSR MSPLIM_NS,%0" :: "r" (value));
+ }
+
+ #endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */
+
+#endif /* __ICCARM_INTRINSICS_VERSION__ == 2 */
+
+#define __BKPT(value) __asm volatile ("BKPT %0" : : "i"(value))
+
+#if __IAR_M0_FAMILY
+ __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat)
+ {
+ if ((sat >= 1U) && (sat <= 32U))
+ {
+ const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
+ const int32_t min = -1 - max ;
+ if (val > max)
+ {
+ return max;
+ }
+ else if (val < min)
+ {
+ return min;
+ }
+ }
+ return val;
+ }
+
+ __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat)
+ {
+ if (sat <= 31U)
+ {
+ const uint32_t max = ((1U << sat) - 1U);
+ if (val > (int32_t)max)
+ {
+ return max;
+ }
+ else if (val < 0)
+ {
+ return 0U;
+ }
+ }
+ return (uint32_t)val;
+ }
+#endif
+
+#if (__CORTEX_M >= 0x03) /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */
+
+ __IAR_FT uint8_t __LDRBT(volatile uint8_t *addr)
+ {
+ uint32_t res;
+ __ASM("LDRBT %0, [%1]" : "=r" (res) : "r" (addr) : "memory");
+ return ((uint8_t)res);
+ }
+
+ __IAR_FT uint16_t __LDRHT(volatile uint16_t *addr)
+ {
+ uint32_t res;
+ __ASM("LDRHT %0, [%1]" : "=r" (res) : "r" (addr) : "memory");
+ return ((uint16_t)res);
+ }
+
+ __IAR_FT uint32_t __LDRT(volatile uint32_t *addr)
+ {
+ uint32_t res;
+ __ASM("LDRT %0, [%1]" : "=r" (res) : "r" (addr) : "memory");
+ return res;
+ }
+
+ __IAR_FT void __STRBT(uint8_t value, volatile uint8_t *addr)
+ {
+ __ASM("STRBT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory");
+ }
+
+ __IAR_FT void __STRHT(uint16_t value, volatile uint16_t *addr)
+ {
+ __ASM("STRHT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory");
+ }
+
+ __IAR_FT void __STRT(uint32_t value, volatile uint32_t *addr)
+ {
+ __ASM("STRT %1, [%0]" : : "r" (addr), "r" (value) : "memory");
+ }
+
+#endif /* (__CORTEX_M >= 0x03) */
+
+#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
+
+
+ __IAR_FT uint8_t __LDAB(volatile uint8_t *ptr)
+ {
+ uint32_t res;
+ __ASM volatile ("LDAB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
+ return ((uint8_t)res);
+ }
+
+ __IAR_FT uint16_t __LDAH(volatile uint16_t *ptr)
+ {
+ uint32_t res;
+ __ASM volatile ("LDAH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
+ return ((uint16_t)res);
+ }
+
+ __IAR_FT uint32_t __LDA(volatile uint32_t *ptr)
+ {
+ uint32_t res;
+ __ASM volatile ("LDA %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
+ return res;
+ }
+
+ __IAR_FT void __STLB(uint8_t value, volatile uint8_t *ptr)
+ {
+ __ASM volatile ("STLB %1, [%0]" :: "r" (ptr), "r" (value) : "memory");
+ }
+
+ __IAR_FT void __STLH(uint16_t value, volatile uint16_t *ptr)
+ {
+ __ASM volatile ("STLH %1, [%0]" :: "r" (ptr), "r" (value) : "memory");
+ }
+
+ __IAR_FT void __STL(uint32_t value, volatile uint32_t *ptr)
+ {
+ __ASM volatile ("STL %1, [%0]" :: "r" (ptr), "r" (value) : "memory");
+ }
+
+ __IAR_FT uint8_t __LDAEXB(volatile uint8_t *ptr)
+ {
+ uint32_t res;
+ __ASM volatile ("LDAEXB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
+ return ((uint8_t)res);
+ }
+
+ __IAR_FT uint16_t __LDAEXH(volatile uint16_t *ptr)
+ {
+ uint32_t res;
+ __ASM volatile ("LDAEXH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
+ return ((uint16_t)res);
+ }
+
+ __IAR_FT uint32_t __LDAEX(volatile uint32_t *ptr)
+ {
+ uint32_t res;
+ __ASM volatile ("LDAEX %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
+ return res;
+ }
+
+ __IAR_FT uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr)
+ {
+ uint32_t res;
+ __ASM volatile ("STLEXB %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory");
+ return res;
+ }
+
+ __IAR_FT uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr)
+ {
+ uint32_t res;
+ __ASM volatile ("STLEXH %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory");
+ return res;
+ }
+
+ __IAR_FT uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr)
+ {
+ uint32_t res;
+ __ASM volatile ("STLEX %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory");
+ return res;
+ }
+
+#endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */
+
+#undef __IAR_FT
+#undef __IAR_M0_FAMILY
+#undef __ICCARM_V8
+
+#pragma diag_default=Pe940
+#pragma diag_default=Pe177
+
+#endif /* __CMSIS_ICCARM_H__ */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/cmsis_version.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/cmsis_version.h
new file mode 100644
index 0000000..660f612
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/cmsis_version.h
@@ -0,0 +1,39 @@
+/**************************************************************************//**
+ * @file cmsis_version.h
+ * @brief CMSIS Core(M) Version definitions
+ * @version V5.0.2
+ * @date 19. April 2017
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CMSIS_VERSION_H
+#define __CMSIS_VERSION_H
+
+/* CMSIS Version definitions */
+#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */
+#define __CM_CMSIS_VERSION_SUB ( 1U) /*!< [15:0] CMSIS Core(M) sub version */
+#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \
+ __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */
+#endif
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_armv8mbl.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_armv8mbl.h
new file mode 100644
index 0000000..251e4ed
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_armv8mbl.h
@@ -0,0 +1,1918 @@
+/**************************************************************************//**
+ * @file core_armv8mbl.h
+ * @brief CMSIS Armv8-M Baseline Core Peripheral Access Layer Header File
+ * @version V5.0.7
+ * @date 22. June 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_ARMV8MBL_H_GENERIC
+#define __CORE_ARMV8MBL_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup Cortex_ARMv8MBL
+ @{
+ */
+
+#include "cmsis_version.h"
+
+/* CMSIS definitions */
+#define __ARMv8MBL_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __ARMv8MBL_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __ARMv8MBL_CMSIS_VERSION ((__ARMv8MBL_CMSIS_VERSION_MAIN << 16U) | \
+ __ARMv8MBL_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_M ( 2U) /*!< Cortex-M Core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ This core does not support an FPU at all
+*/
+#define __FPU_USED 0U
+
+#if defined ( __CC_ARM )
+ #if defined __TARGET_FPU_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_PCS_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined __ARMVFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined __TI_VFP_SUPPORT__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined __FPU_VFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_ARMV8MBL_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_ARMV8MBL_H_DEPENDANT
+#define __CORE_ARMV8MBL_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __ARMv8MBL_REV
+ #define __ARMv8MBL_REV 0x0000U
+ #warning "__ARMv8MBL_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __FPU_PRESENT
+ #define __FPU_PRESENT 0U
+ #warning "__FPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MPU_PRESENT
+ #define __MPU_PRESENT 0U
+ #warning "__MPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __SAUREGION_PRESENT
+ #define __SAUREGION_PRESENT 0U
+ #warning "__SAUREGION_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __VTOR_PRESENT
+ #define __VTOR_PRESENT 0U
+ #warning "__VTOR_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 2U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+
+ #ifndef __ETM_PRESENT
+ #define __ETM_PRESENT 0U
+ #warning "__ETM_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MTB_PRESENT
+ #define __MTB_PRESENT 0U
+ #warning "__MTB_PRESENT not defined in device header file; using default!"
+ #endif
+
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group ARMv8MBL */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ - Core Debug Register
+ - Core MPU Register
+ - Core SAU Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
+ uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */
+ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */
+#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[16U];
+ __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[16U];
+ __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[16U];
+ __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[16U];
+ __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
+ uint32_t RESERVED4[16U];
+ __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */
+ uint32_t RESERVED5[16U];
+ __IOM uint32_t IPR[124U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
+} NVIC_Type;
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
+#else
+ uint32_t RESERVED0;
+#endif
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ uint32_t RESERVED1;
+ __IOM uint32_t SHPR[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */
+#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */
+
+#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */
+#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */
+
+#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */
+#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */
+#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */
+#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+/* SCB Vector Table Offset Register Definitions */
+#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
+#endif
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */
+#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */
+
+#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */
+#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */
+
+#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */
+#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */
+#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */
+#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */
+
+#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */
+#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */
+
+#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */
+#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */
+
+#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */
+#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */
+
+#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */
+#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */
+
+#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */
+#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */
+#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */
+#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */
+
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */
+#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */
+
+#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */
+#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */
+
+#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */
+#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */
+
+#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */
+#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */
+
+#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */
+#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT)
+ \brief Type definitions for the Data Watchpoint and Trace (DWT)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Data Watchpoint and Trace Register (DWT).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */
+ uint32_t RESERVED0[6U];
+ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */
+ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */
+ uint32_t RESERVED1[1U];
+ __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */
+ uint32_t RESERVED2[1U];
+ __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */
+ uint32_t RESERVED3[1U];
+ __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */
+ uint32_t RESERVED5[1U];
+ __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */
+ uint32_t RESERVED6[1U];
+ __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */
+ uint32_t RESERVED7[1U];
+ __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */
+ uint32_t RESERVED8[1U];
+ __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */
+ uint32_t RESERVED9[1U];
+ __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */
+ uint32_t RESERVED10[1U];
+ __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */
+ uint32_t RESERVED11[1U];
+ __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */
+ uint32_t RESERVED12[1U];
+ __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */
+ uint32_t RESERVED13[1U];
+ __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */
+ uint32_t RESERVED14[1U];
+ __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */
+ uint32_t RESERVED15[1U];
+ __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */
+ uint32_t RESERVED16[1U];
+ __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */
+ uint32_t RESERVED17[1U];
+ __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */
+ uint32_t RESERVED18[1U];
+ __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */
+ uint32_t RESERVED19[1U];
+ __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */
+ uint32_t RESERVED20[1U];
+ __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */
+ uint32_t RESERVED21[1U];
+ __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */
+ uint32_t RESERVED22[1U];
+ __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */
+ uint32_t RESERVED23[1U];
+ __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */
+ uint32_t RESERVED24[1U];
+ __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */
+ uint32_t RESERVED25[1U];
+ __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */
+ uint32_t RESERVED26[1U];
+ __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */
+ uint32_t RESERVED27[1U];
+ __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */
+ uint32_t RESERVED28[1U];
+ __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */
+ uint32_t RESERVED29[1U];
+ __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */
+ uint32_t RESERVED30[1U];
+ __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */
+ uint32_t RESERVED31[1U];
+ __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */
+} DWT_Type;
+
+/* DWT Control Register Definitions */
+#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */
+#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */
+
+#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */
+#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */
+
+#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */
+#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */
+
+#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */
+#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */
+
+#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */
+#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */
+
+/* DWT Comparator Function Register Definitions */
+#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */
+#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */
+
+#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */
+#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */
+
+#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */
+#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */
+
+#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */
+#define DWT_FUNCTION_ACTION_Msk (0x3UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */
+
+#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */
+#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */
+
+/*@}*/ /* end of group CMSIS_DWT */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_TPI Trace Port Interface (TPI)
+ \brief Type definitions for the Trace Port Interface (TPI)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Trace Port Interface Register (TPI).
+ */
+typedef struct
+{
+ __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Sizes Register */
+ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Sizes Register */
+ uint32_t RESERVED0[2U];
+ __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */
+ uint32_t RESERVED1[55U];
+ __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */
+ uint32_t RESERVED2[131U];
+ __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */
+ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */
+ __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */
+ uint32_t RESERVED3[809U];
+ __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) Software Lock Access Register */
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) Software Lock Status Register */
+ uint32_t RESERVED4[4U];
+ __IM uint32_t TYPE; /*!< Offset: 0xFC8 (R/ ) Device Identifier Register */
+ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Register */
+} TPI_Type;
+
+/* TPI Asynchronous Clock Prescaler Register Definitions */
+#define TPI_ACPR_SWOSCALER_Pos 0U /*!< TPI ACPR: SWOSCALER Position */
+#define TPI_ACPR_SWOSCALER_Msk (0xFFFFUL /*<< TPI_ACPR_SWOSCALER_Pos*/) /*!< TPI ACPR: SWOSCALER Mask */
+
+/* TPI Selected Pin Protocol Register Definitions */
+#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */
+#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */
+
+/* TPI Formatter and Flush Status Register Definitions */
+#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */
+#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */
+
+#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */
+#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */
+
+#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */
+#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */
+
+#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */
+#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */
+
+/* TPI Formatter and Flush Control Register Definitions */
+#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */
+#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */
+
+#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */
+#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */
+
+#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */
+#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */
+
+/* TPI Periodic Synchronization Control Register Definitions */
+#define TPI_PSCR_PSCount_Pos 0U /*!< TPI PSCR: PSCount Position */
+#define TPI_PSCR_PSCount_Msk (0x1FUL /*<< TPI_PSCR_PSCount_Pos*/) /*!< TPI PSCR: TPSCount Mask */
+
+/* TPI Software Lock Status Register Definitions */
+#define TPI_LSR_nTT_Pos 1U /*!< TPI LSR: Not thirty-two bit. Position */
+#define TPI_LSR_nTT_Msk (0x1UL << TPI_LSR_nTT_Pos) /*!< TPI LSR: Not thirty-two bit. Mask */
+
+#define TPI_LSR_SLK_Pos 1U /*!< TPI LSR: Software Lock status Position */
+#define TPI_LSR_SLK_Msk (0x1UL << TPI_LSR_SLK_Pos) /*!< TPI LSR: Software Lock status Mask */
+
+#define TPI_LSR_SLI_Pos 0U /*!< TPI LSR: Software Lock implemented Position */
+#define TPI_LSR_SLI_Msk (0x1UL /*<< TPI_LSR_SLI_Pos*/) /*!< TPI LSR: Software Lock implemented Mask */
+
+/* TPI DEVID Register Definitions */
+#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */
+#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */
+
+#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */
+#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */
+
+#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */
+#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */
+
+#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFO depth Position */
+#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFO depth Mask */
+
+/* TPI DEVTYPE Register Definitions */
+#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */
+
+#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
+
+/*@}*/ /* end of group CMSIS_TPI */
+
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_MPU Memory Protection Unit (MPU)
+ \brief Type definitions for the Memory Protection Unit (MPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+ __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
+ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */
+ uint32_t RESERVED0[7U];
+ union {
+ __IOM uint32_t MAIR[2];
+ struct {
+ __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */
+ __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */
+ };
+ };
+} MPU_Type;
+
+#define MPU_TYPE_RALIASES 1U
+
+/* MPU Type Register Definitions */
+#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register Definitions */
+#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register Definitions */
+#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register Definitions */
+#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */
+#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */
+
+#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */
+#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */
+
+#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */
+#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */
+
+#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */
+#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */
+
+/* MPU Region Limit Address Register Definitions */
+#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */
+#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */
+
+#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */
+#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */
+
+#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: EN Position */
+#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: EN Mask */
+
+/* MPU Memory Attribute Indirection Register 0 Definitions */
+#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */
+#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */
+
+#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */
+#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */
+
+#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */
+#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */
+
+#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */
+#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */
+
+/* MPU Memory Attribute Indirection Register 1 Definitions */
+#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */
+#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */
+
+#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */
+#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */
+
+#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */
+#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */
+
+#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */
+#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SAU Security Attribution Unit (SAU)
+ \brief Type definitions for the Security Attribution Unit (SAU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Security Attribution Unit (SAU).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */
+ __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */
+#endif
+} SAU_Type;
+
+/* SAU Control Register Definitions */
+#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */
+#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */
+
+#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */
+#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */
+
+/* SAU Type Register Definitions */
+#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */
+#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */
+
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+/* SAU Region Number Register Definitions */
+#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */
+#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */
+
+/* SAU Region Base Address Register Definitions */
+#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */
+#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */
+
+/* SAU Region Limit Address Register Definitions */
+#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */
+#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */
+
+#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */
+#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */
+
+#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */
+#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */
+
+#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */
+
+/*@} end of group CMSIS_SAU */
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Type definitions for the Core Debug Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Core Debug Register (CoreDebug).
+ */
+typedef struct
+{
+ __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */
+ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */
+ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */
+ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */
+ __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */
+} CoreDebug_Type;
+
+/* Debug Halting Control and Status Register Definitions */
+#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */
+#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */
+
+#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */
+#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */
+
+#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */
+#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */
+
+#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */
+#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */
+
+#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */
+#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */
+
+#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */
+#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */
+
+#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */
+#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */
+
+#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */
+#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */
+
+#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */
+#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */
+
+#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */
+#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */
+
+#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */
+#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */
+
+#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */
+#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */
+
+/* Debug Core Register Selector Register Definitions */
+#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */
+#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */
+
+#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */
+#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */
+
+/* Debug Exception and Monitor Control Register */
+#define CoreDebug_DEMCR_DWTENA_Pos 24U /*!< CoreDebug DEMCR: DWTENA Position */
+#define CoreDebug_DEMCR_DWTENA_Msk (1UL << CoreDebug_DEMCR_DWTENA_Pos) /*!< CoreDebug DEMCR: DWTENA Mask */
+
+#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */
+#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */
+
+#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */
+#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */
+
+/* Debug Authentication Control Register Definitions */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */
+
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */
+
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */
+
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */
+
+/* Debug Security Control and Status Register Definitions */
+#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */
+#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */
+
+#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */
+#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */
+
+#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */
+#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */
+
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
+ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */
+ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */
+ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+
+ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */
+ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */
+ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
+ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
+ #endif
+
+ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */
+ #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */
+ #endif
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */
+ #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */
+ #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */
+ #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */
+ #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */
+
+ #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */
+ #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */
+ #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */
+ #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */
+ #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */
+ #endif
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+ #define NVIC_GetActive __NVIC_GetActive
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* Special LR values for Secure/Non-Secure call handling and exception handling */
+
+/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */
+#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */
+
+/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */
+#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */
+#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */
+#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */
+#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */
+#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */
+#define EXC_RETURN_SPSEL (0x00000002UL) /* bit [1] stack pointer used to restore context: 0=MSP 1=PSP */
+#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */
+
+/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */
+#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */
+#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */
+#else
+#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */
+#endif
+
+
+/* Interrupt Priorities are WORD accessible only under Armv6-M */
+/* The following MACROS handle generation of the register offset and byte masks */
+#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
+#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) )
+#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
+
+#define __NVIC_SetPriorityGrouping(X) (void)(X)
+#define __NVIC_GetPriorityGrouping() (0U)
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt
+ \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Get Interrupt Target State
+ \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ \return 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Target State
+ \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Clear Interrupt Target State
+ \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+ else
+ {
+ SCB->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return((uint32_t)(((SCB->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ If VTOR is not present address 0 must be mapped to SRAM.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+#else
+ uint32_t *vectors = (uint32_t *)0x0U;
+#endif
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+#else
+ uint32_t *vectors = (uint32_t *)0x0U;
+#endif
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ SCB_AIRCR_SYSRESETREQ_Msk);
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Enable Interrupt (non-secure)
+ \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status (non-secure)
+ \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt (non-secure)
+ \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt (non-secure)
+ \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt (non-secure)
+ \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt (non-secure)
+ \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt (non-secure)
+ \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority (non-secure)
+ \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every non-secure processor exception.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC_NS->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+ else
+ {
+ SCB_NS->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB_NS->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority (non-secure)
+ \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return((uint32_t)(((SCB_NS->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+/* ########################## MPU functions #################################### */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+
+#include "mpu_armv8.h"
+
+#endif
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ return 0U; /* No FPU */
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ########################## SAU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SAUFunctions SAU Functions
+ \brief Functions that configure the SAU.
+ @{
+ */
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+
+/**
+ \brief Enable SAU
+ \details Enables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Enable(void)
+{
+ SAU->CTRL |= (SAU_CTRL_ENABLE_Msk);
+}
+
+
+
+/**
+ \brief Disable SAU
+ \details Disables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Disable(void)
+{
+ SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk);
+}
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_SAUFunctions */
+
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief System Tick Configuration (non-secure)
+ \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function TZ_SysTick_Config_NS is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+
+ */
+__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_ARMV8MBL_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_armv8mml.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_armv8mml.h
new file mode 100644
index 0000000..3a3148e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_armv8mml.h
@@ -0,0 +1,2927 @@
+/**************************************************************************//**
+ * @file core_armv8mml.h
+ * @brief CMSIS Armv8-M Mainline Core Peripheral Access Layer Header File
+ * @version V5.0.7
+ * @date 06. July 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_ARMV8MML_H_GENERIC
+#define __CORE_ARMV8MML_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup Cortex_ARMv8MML
+ @{
+ */
+
+#include "cmsis_version.h"
+
+/* CMSIS Armv8MML definitions */
+#define __ARMv8MML_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __ARMv8MML_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __ARMv8MML_CMSIS_VERSION ((__ARMv8MML_CMSIS_VERSION_MAIN << 16U) | \
+ __ARMv8MML_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_M (81U) /*!< Cortex-M Core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions.
+*/
+#if defined ( __CC_ARM )
+ #if defined __TARGET_FPU_VFP
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined(__ARM_FEATURE_DSP)
+ #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_PCS_VFP
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined(__ARM_FEATURE_DSP)
+ #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined(__ARM_FEATURE_DSP)
+ #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined __ARMVFP__
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined(__ARM_FEATURE_DSP)
+ #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined __TI_VFP_SUPPORT__
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined __FPU_VFP__
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_ARMV8MML_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_ARMV8MML_H_DEPENDANT
+#define __CORE_ARMV8MML_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __ARMv8MML_REV
+ #define __ARMv8MML_REV 0x0000U
+ #warning "__ARMv8MML_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __FPU_PRESENT
+ #define __FPU_PRESENT 0U
+ #warning "__FPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MPU_PRESENT
+ #define __MPU_PRESENT 0U
+ #warning "__MPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __SAUREGION_PRESENT
+ #define __SAUREGION_PRESENT 0U
+ #warning "__SAUREGION_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __DSP_PRESENT
+ #define __DSP_PRESENT 0U
+ #warning "__DSP_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 3U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group ARMv8MML */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ - Core Debug Register
+ - Core MPU Register
+ - Core SAU Register
+ - Core FPU Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */
+ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
+ uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+#define APSR_Q_Pos 27U /*!< APSR: Q Position */
+#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */
+
+#define APSR_GE_Pos 16U /*!< APSR: GE Position */
+#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */
+ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
+ uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
+ uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */
+#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */
+
+#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */
+#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */
+#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */
+ uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */
+ uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */
+ uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */
+#define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */
+
+#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */
+#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */
+
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */
+#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[16U];
+ __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[16U];
+ __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[16U];
+ __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[16U];
+ __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
+ uint32_t RESERVED4[16U];
+ __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */
+ uint32_t RESERVED5[16U];
+ __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
+ uint32_t RESERVED6[580U];
+ __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
+} NVIC_Type;
+
+/* Software Triggered Interrupt Register Definitions */
+#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */
+#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+ __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */
+ __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */
+ __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */
+ __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */
+ __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */
+ __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */
+ __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */
+ __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */
+ __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */
+ __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */
+ __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */
+ __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */
+ __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */
+ __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */
+ __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */
+ __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */
+ __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */
+ uint32_t RESERVED3[92U];
+ __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */
+ uint32_t RESERVED4[15U];
+ __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */
+ __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */
+ __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */
+ uint32_t RESERVED5[1U];
+ __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */
+ uint32_t RESERVED6[1U];
+ __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */
+ __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */
+ __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */
+ __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */
+ __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */
+ __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */
+ __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */
+ __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */
+ uint32_t RESERVED7[6U];
+ __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */
+ __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */
+ __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */
+ __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */
+ __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */
+ uint32_t RESERVED8[1U];
+ __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */
+#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */
+
+#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */
+#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */
+
+#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */
+#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */
+#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */
+#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+/* SCB Vector Table Offset Register Definitions */
+#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */
+#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */
+
+#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */
+#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */
+
+#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */
+#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */
+
+#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */
+#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */
+#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */
+#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */
+
+#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */
+#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */
+
+#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */
+#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */
+
+#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */
+#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */
+
+#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */
+#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */
+
+#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */
+#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */
+#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */
+#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */
+
+#define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */
+#define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */
+
+#define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */
+#define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */
+
+#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */
+#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */
+
+#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */
+#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */
+
+#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */
+#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */
+
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */
+#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */
+
+#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */
+#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */
+
+#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */
+#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */
+
+#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */
+#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */
+
+#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */
+#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */
+
+#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */
+#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */
+
+#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */
+#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */
+
+#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */
+#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */
+
+#define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */
+#define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */
+
+#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */
+#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */
+
+#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */
+#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */
+
+#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */
+#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */
+
+#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */
+#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */
+
+/* SCB Configurable Fault Status Register Definitions */
+#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */
+#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */
+
+#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */
+#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */
+
+#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */
+#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */
+
+/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */
+#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */
+
+#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */
+#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */
+
+#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */
+#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */
+
+#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */
+#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */
+
+#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */
+#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */
+
+#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */
+#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */
+
+/* BusFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */
+#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */
+
+#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */
+#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */
+
+#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */
+#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */
+
+#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */
+#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */
+
+#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */
+#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */
+
+#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */
+#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */
+
+#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */
+#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */
+
+/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */
+#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */
+
+#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */
+#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */
+
+#define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */
+#define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */
+
+#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */
+#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */
+
+#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */
+#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */
+
+#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */
+#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */
+
+#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */
+#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */
+
+/* SCB Hard Fault Status Register Definitions */
+#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */
+#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */
+
+#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */
+#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */
+
+#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */
+#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */
+
+/* SCB Debug Fault Status Register Definitions */
+#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */
+#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */
+
+#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */
+#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */
+
+#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */
+#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */
+
+#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */
+#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */
+
+#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */
+#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */
+
+/* SCB Non-Secure Access Control Register Definitions */
+#define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */
+#define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */
+
+#define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */
+#define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */
+
+#define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */
+#define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */
+
+/* SCB Cache Level ID Register Definitions */
+#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */
+#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */
+
+#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */
+#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */
+
+/* SCB Cache Type Register Definitions */
+#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */
+#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */
+
+#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */
+#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */
+
+#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */
+#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */
+
+#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */
+#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */
+
+#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */
+#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */
+
+/* SCB Cache Size ID Register Definitions */
+#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */
+#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */
+
+#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */
+#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */
+
+#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */
+#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */
+
+#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */
+#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */
+
+#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */
+#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */
+
+#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */
+#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */
+
+#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */
+#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */
+
+/* SCB Cache Size Selection Register Definitions */
+#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */
+#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */
+
+#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */
+#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */
+
+/* SCB Software Triggered Interrupt Register Definitions */
+#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */
+#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */
+
+/* SCB D-Cache Invalidate by Set-way Register Definitions */
+#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */
+#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */
+
+#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */
+#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */
+
+/* SCB D-Cache Clean by Set-way Register Definitions */
+#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */
+#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */
+
+#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */
+#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */
+
+/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */
+#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */
+#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */
+
+#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */
+#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */
+
+/* Instruction Tightly-Coupled Memory Control Register Definitions */
+#define SCB_ITCMCR_SZ_Pos 3U /*!< SCB ITCMCR: SZ Position */
+#define SCB_ITCMCR_SZ_Msk (0xFUL << SCB_ITCMCR_SZ_Pos) /*!< SCB ITCMCR: SZ Mask */
+
+#define SCB_ITCMCR_RETEN_Pos 2U /*!< SCB ITCMCR: RETEN Position */
+#define SCB_ITCMCR_RETEN_Msk (1UL << SCB_ITCMCR_RETEN_Pos) /*!< SCB ITCMCR: RETEN Mask */
+
+#define SCB_ITCMCR_RMW_Pos 1U /*!< SCB ITCMCR: RMW Position */
+#define SCB_ITCMCR_RMW_Msk (1UL << SCB_ITCMCR_RMW_Pos) /*!< SCB ITCMCR: RMW Mask */
+
+#define SCB_ITCMCR_EN_Pos 0U /*!< SCB ITCMCR: EN Position */
+#define SCB_ITCMCR_EN_Msk (1UL /*<< SCB_ITCMCR_EN_Pos*/) /*!< SCB ITCMCR: EN Mask */
+
+/* Data Tightly-Coupled Memory Control Register Definitions */
+#define SCB_DTCMCR_SZ_Pos 3U /*!< SCB DTCMCR: SZ Position */
+#define SCB_DTCMCR_SZ_Msk (0xFUL << SCB_DTCMCR_SZ_Pos) /*!< SCB DTCMCR: SZ Mask */
+
+#define SCB_DTCMCR_RETEN_Pos 2U /*!< SCB DTCMCR: RETEN Position */
+#define SCB_DTCMCR_RETEN_Msk (1UL << SCB_DTCMCR_RETEN_Pos) /*!< SCB DTCMCR: RETEN Mask */
+
+#define SCB_DTCMCR_RMW_Pos 1U /*!< SCB DTCMCR: RMW Position */
+#define SCB_DTCMCR_RMW_Msk (1UL << SCB_DTCMCR_RMW_Pos) /*!< SCB DTCMCR: RMW Mask */
+
+#define SCB_DTCMCR_EN_Pos 0U /*!< SCB DTCMCR: EN Position */
+#define SCB_DTCMCR_EN_Msk (1UL /*<< SCB_DTCMCR_EN_Pos*/) /*!< SCB DTCMCR: EN Mask */
+
+/* AHBP Control Register Definitions */
+#define SCB_AHBPCR_SZ_Pos 1U /*!< SCB AHBPCR: SZ Position */
+#define SCB_AHBPCR_SZ_Msk (7UL << SCB_AHBPCR_SZ_Pos) /*!< SCB AHBPCR: SZ Mask */
+
+#define SCB_AHBPCR_EN_Pos 0U /*!< SCB AHBPCR: EN Position */
+#define SCB_AHBPCR_EN_Msk (1UL /*<< SCB_AHBPCR_EN_Pos*/) /*!< SCB AHBPCR: EN Mask */
+
+/* L1 Cache Control Register Definitions */
+#define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */
+#define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */
+
+#define SCB_CACR_ECCEN_Pos 1U /*!< SCB CACR: ECCEN Position */
+#define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< SCB CACR: ECCEN Mask */
+
+#define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */
+#define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */
+
+/* AHBS Control Register Definitions */
+#define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */
+#define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBPCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */
+
+#define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */
+#define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBPCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */
+
+#define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/
+#define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBPCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */
+
+/* Auxiliary Bus Fault Status Register Definitions */
+#define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/
+#define SCB_ABFSR_AXIMTYPE_Msk (3UL << SCB_ABFSR_AXIMTYPE_Pos) /*!< SCB ABFSR: AXIMTYPE Mask */
+
+#define SCB_ABFSR_EPPB_Pos 4U /*!< SCB ABFSR: EPPB Position*/
+#define SCB_ABFSR_EPPB_Msk (1UL << SCB_ABFSR_EPPB_Pos) /*!< SCB ABFSR: EPPB Mask */
+
+#define SCB_ABFSR_AXIM_Pos 3U /*!< SCB ABFSR: AXIM Position*/
+#define SCB_ABFSR_AXIM_Msk (1UL << SCB_ABFSR_AXIM_Pos) /*!< SCB ABFSR: AXIM Mask */
+
+#define SCB_ABFSR_AHBP_Pos 2U /*!< SCB ABFSR: AHBP Position*/
+#define SCB_ABFSR_AHBP_Msk (1UL << SCB_ABFSR_AHBP_Pos) /*!< SCB ABFSR: AHBP Mask */
+
+#define SCB_ABFSR_DTCM_Pos 1U /*!< SCB ABFSR: DTCM Position*/
+#define SCB_ABFSR_DTCM_Msk (1UL << SCB_ABFSR_DTCM_Pos) /*!< SCB ABFSR: DTCM Mask */
+
+#define SCB_ABFSR_ITCM_Pos 0U /*!< SCB ABFSR: ITCM Position*/
+#define SCB_ABFSR_ITCM_Msk (1UL /*<< SCB_ABFSR_ITCM_Pos*/) /*!< SCB ABFSR: ITCM Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB)
+ \brief Type definitions for the System Control and ID Register not in the SCB
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control and ID Register not in the SCB.
+ */
+typedef struct
+{
+ uint32_t RESERVED0[1U];
+ __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */
+ __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */
+ __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */
+} SCnSCB_Type;
+
+/* Interrupt Controller Type Register Definitions */
+#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */
+#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_SCnotSCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM)
+ \brief Type definitions for the Instrumentation Trace Macrocell (ITM)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM).
+ */
+typedef struct
+{
+ __OM union
+ {
+ __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */
+ __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */
+ __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */
+ } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */
+ uint32_t RESERVED0[864U];
+ __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */
+ uint32_t RESERVED1[15U];
+ __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */
+ uint32_t RESERVED2[15U];
+ __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */
+ uint32_t RESERVED3[29U];
+ __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */
+ __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */
+ __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */
+ uint32_t RESERVED4[43U];
+ __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */
+ uint32_t RESERVED5[1U];
+ __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */
+ uint32_t RESERVED6[4U];
+ __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */
+ __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */
+ __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */
+ __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */
+ __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */
+ __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */
+ __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */
+ __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */
+ __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */
+ __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */
+ __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */
+ __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */
+} ITM_Type;
+
+/* ITM Stimulus Port Register Definitions */
+#define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */
+#define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */
+
+#define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */
+#define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */
+
+/* ITM Trace Privilege Register Definitions */
+#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */
+#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */
+
+/* ITM Trace Control Register Definitions */
+#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */
+#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */
+
+#define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */
+#define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */
+
+#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */
+#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */
+
+#define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */
+#define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */
+
+#define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */
+#define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */
+
+#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */
+#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */
+
+#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */
+#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */
+
+#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */
+#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */
+
+#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */
+#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */
+
+#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */
+#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */
+
+/* ITM Integration Write Register Definitions */
+#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */
+#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */
+
+/* ITM Integration Read Register Definitions */
+#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */
+#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */
+
+/* ITM Integration Mode Control Register Definitions */
+#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */
+#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */
+
+/* ITM Lock Status Register Definitions */
+#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */
+#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */
+
+#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */
+#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */
+
+#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */
+#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */
+
+/*@}*/ /* end of group CMSIS_ITM */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT)
+ \brief Type definitions for the Data Watchpoint and Trace (DWT)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Data Watchpoint and Trace Register (DWT).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */
+ __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */
+ __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */
+ __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */
+ __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */
+ __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */
+ __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */
+ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */
+ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */
+ uint32_t RESERVED1[1U];
+ __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */
+ uint32_t RESERVED2[1U];
+ __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */
+ uint32_t RESERVED3[1U];
+ __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */
+ uint32_t RESERVED5[1U];
+ __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */
+ uint32_t RESERVED6[1U];
+ __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */
+ uint32_t RESERVED7[1U];
+ __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */
+ uint32_t RESERVED8[1U];
+ __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */
+ uint32_t RESERVED9[1U];
+ __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */
+ uint32_t RESERVED10[1U];
+ __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */
+ uint32_t RESERVED11[1U];
+ __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */
+ uint32_t RESERVED12[1U];
+ __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */
+ uint32_t RESERVED13[1U];
+ __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */
+ uint32_t RESERVED14[1U];
+ __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */
+ uint32_t RESERVED15[1U];
+ __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */
+ uint32_t RESERVED16[1U];
+ __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */
+ uint32_t RESERVED17[1U];
+ __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */
+ uint32_t RESERVED18[1U];
+ __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */
+ uint32_t RESERVED19[1U];
+ __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */
+ uint32_t RESERVED20[1U];
+ __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */
+ uint32_t RESERVED21[1U];
+ __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */
+ uint32_t RESERVED22[1U];
+ __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */
+ uint32_t RESERVED23[1U];
+ __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */
+ uint32_t RESERVED24[1U];
+ __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */
+ uint32_t RESERVED25[1U];
+ __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */
+ uint32_t RESERVED26[1U];
+ __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */
+ uint32_t RESERVED27[1U];
+ __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */
+ uint32_t RESERVED28[1U];
+ __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */
+ uint32_t RESERVED29[1U];
+ __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */
+ uint32_t RESERVED30[1U];
+ __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */
+ uint32_t RESERVED31[1U];
+ __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */
+ uint32_t RESERVED32[934U];
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */
+ uint32_t RESERVED33[1U];
+ __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */
+} DWT_Type;
+
+/* DWT Control Register Definitions */
+#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */
+#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */
+
+#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */
+#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */
+
+#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */
+#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */
+
+#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */
+#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */
+
+#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */
+#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */
+
+#define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */
+#define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */
+
+#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */
+#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */
+
+#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */
+#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */
+
+#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */
+#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */
+
+#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */
+#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */
+
+#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */
+#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */
+
+#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */
+#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */
+
+#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */
+#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */
+
+#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */
+#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */
+
+#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */
+#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */
+
+#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */
+#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */
+
+#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */
+#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */
+
+#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */
+#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */
+
+#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */
+#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */
+
+/* DWT CPI Count Register Definitions */
+#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */
+#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */
+
+/* DWT Exception Overhead Count Register Definitions */
+#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */
+#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */
+
+/* DWT Sleep Count Register Definitions */
+#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */
+#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */
+
+/* DWT LSU Count Register Definitions */
+#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */
+#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */
+
+/* DWT Folded-instruction Count Register Definitions */
+#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */
+#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */
+
+/* DWT Comparator Function Register Definitions */
+#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */
+#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */
+
+#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */
+#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */
+
+#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */
+#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */
+
+#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */
+#define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */
+
+#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */
+#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */
+
+/*@}*/ /* end of group CMSIS_DWT */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_TPI Trace Port Interface (TPI)
+ \brief Type definitions for the Trace Port Interface (TPI)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Trace Port Interface Register (TPI).
+ */
+typedef struct
+{
+ __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Sizes Register */
+ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Sizes Register */
+ uint32_t RESERVED0[2U];
+ __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */
+ uint32_t RESERVED1[55U];
+ __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */
+ uint32_t RESERVED2[131U];
+ __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */
+ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */
+ __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */
+ uint32_t RESERVED3[809U];
+ __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) Software Lock Access Register */
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) Software Lock Status Register */
+ uint32_t RESERVED4[4U];
+ __IM uint32_t TYPE; /*!< Offset: 0xFC8 (R/ ) Device Identifier Register */
+ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Register */
+} TPI_Type;
+
+/* TPI Asynchronous Clock Prescaler Register Definitions */
+#define TPI_ACPR_SWOSCALER_Pos 0U /*!< TPI ACPR: SWOSCALER Position */
+#define TPI_ACPR_SWOSCALER_Msk (0xFFFFUL /*<< TPI_ACPR_SWOSCALER_Pos*/) /*!< TPI ACPR: SWOSCALER Mask */
+
+/* TPI Selected Pin Protocol Register Definitions */
+#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */
+#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */
+
+/* TPI Formatter and Flush Status Register Definitions */
+#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */
+#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */
+
+#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */
+#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */
+
+#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */
+#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */
+
+#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */
+#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */
+
+/* TPI Formatter and Flush Control Register Definitions */
+#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */
+#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */
+
+#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */
+#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */
+
+#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */
+#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */
+
+/* TPI Periodic Synchronization Control Register Definitions */
+#define TPI_PSCR_PSCount_Pos 0U /*!< TPI PSCR: PSCount Position */
+#define TPI_PSCR_PSCount_Msk (0x1FUL /*<< TPI_PSCR_PSCount_Pos*/) /*!< TPI PSCR: TPSCount Mask */
+
+/* TPI Software Lock Status Register Definitions */
+#define TPI_LSR_nTT_Pos 1U /*!< TPI LSR: Not thirty-two bit. Position */
+#define TPI_LSR_nTT_Msk (0x1UL << TPI_LSR_nTT_Pos) /*!< TPI LSR: Not thirty-two bit. Mask */
+
+#define TPI_LSR_SLK_Pos 1U /*!< TPI LSR: Software Lock status Position */
+#define TPI_LSR_SLK_Msk (0x1UL << TPI_LSR_SLK_Pos) /*!< TPI LSR: Software Lock status Mask */
+
+#define TPI_LSR_SLI_Pos 0U /*!< TPI LSR: Software Lock implemented Position */
+#define TPI_LSR_SLI_Msk (0x1UL /*<< TPI_LSR_SLI_Pos*/) /*!< TPI LSR: Software Lock implemented Mask */
+
+/* TPI DEVID Register Definitions */
+#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */
+#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */
+
+#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */
+#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */
+
+#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */
+#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */
+
+#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFO depth Position */
+#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFO depth Mask */
+
+/* TPI DEVTYPE Register Definitions */
+#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */
+
+#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
+
+/*@}*/ /* end of group CMSIS_TPI */
+
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_MPU Memory Protection Unit (MPU)
+ \brief Type definitions for the Memory Protection Unit (MPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+ __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
+ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */
+ __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */
+ __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */
+ __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */
+ __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */
+ __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */
+ __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */
+ uint32_t RESERVED0[1];
+ union {
+ __IOM uint32_t MAIR[2];
+ struct {
+ __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */
+ __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */
+ };
+ };
+} MPU_Type;
+
+#define MPU_TYPE_RALIASES 4U
+
+/* MPU Type Register Definitions */
+#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register Definitions */
+#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register Definitions */
+#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register Definitions */
+#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */
+#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */
+
+#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */
+#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */
+
+#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */
+#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */
+
+#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */
+#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */
+
+/* MPU Region Limit Address Register Definitions */
+#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */
+#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */
+
+#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */
+#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */
+
+#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */
+#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */
+
+/* MPU Memory Attribute Indirection Register 0 Definitions */
+#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */
+#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */
+
+#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */
+#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */
+
+#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */
+#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */
+
+#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */
+#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */
+
+/* MPU Memory Attribute Indirection Register 1 Definitions */
+#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */
+#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */
+
+#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */
+#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */
+
+#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */
+#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */
+
+#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */
+#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SAU Security Attribution Unit (SAU)
+ \brief Type definitions for the Security Attribution Unit (SAU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Security Attribution Unit (SAU).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */
+ __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */
+#else
+ uint32_t RESERVED0[3];
+#endif
+ __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */
+ __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */
+} SAU_Type;
+
+/* SAU Control Register Definitions */
+#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */
+#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */
+
+#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */
+#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */
+
+/* SAU Type Register Definitions */
+#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */
+#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */
+
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+/* SAU Region Number Register Definitions */
+#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */
+#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */
+
+/* SAU Region Base Address Register Definitions */
+#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */
+#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */
+
+/* SAU Region Limit Address Register Definitions */
+#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */
+#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */
+
+#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */
+#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */
+
+#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */
+#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */
+
+#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */
+
+/* Secure Fault Status Register Definitions */
+#define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */
+#define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */
+
+#define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */
+#define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */
+
+#define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */
+#define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */
+
+#define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */
+#define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */
+
+#define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */
+#define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */
+
+#define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */
+#define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */
+
+#define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */
+#define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */
+
+#define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */
+#define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */
+
+/*@} end of group CMSIS_SAU */
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_FPU Floating Point Unit (FPU)
+ \brief Type definitions for the Floating Point Unit (FPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Floating Point Unit (FPU).
+ */
+typedef struct
+{
+ uint32_t RESERVED0[1U];
+ __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */
+ __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */
+ __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */
+ __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */
+ __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */
+} FPU_Type;
+
+/* Floating-Point Context Control Register Definitions */
+#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */
+#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */
+
+#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */
+#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */
+
+#define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */
+#define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */
+
+#define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */
+#define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */
+
+#define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */
+#define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */
+
+#define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */
+#define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */
+
+#define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */
+#define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */
+
+#define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */
+#define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */
+
+#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */
+#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */
+
+#define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */
+#define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */
+
+#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */
+#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */
+
+#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */
+#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */
+
+#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */
+#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */
+
+#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */
+#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */
+
+#define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */
+#define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */
+
+#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */
+#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */
+
+#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */
+#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */
+
+/* Floating-Point Context Address Register Definitions */
+#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */
+#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */
+
+/* Floating-Point Default Status Control Register Definitions */
+#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */
+#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */
+
+#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */
+#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */
+
+#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */
+#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */
+
+#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */
+#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */
+
+/* Media and FP Feature Register 0 Definitions */
+#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */
+#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */
+
+#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */
+#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */
+
+#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */
+#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */
+
+#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */
+#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */
+
+#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */
+#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */
+
+#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */
+#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */
+
+#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */
+#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */
+
+#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */
+#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */
+
+/* Media and FP Feature Register 1 Definitions */
+#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */
+#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */
+
+#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */
+#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */
+
+#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */
+#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */
+
+#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */
+#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */
+
+/*@} end of group CMSIS_FPU */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Type definitions for the Core Debug Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Core Debug Register (CoreDebug).
+ */
+typedef struct
+{
+ __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */
+ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */
+ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */
+ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */
+ __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */
+} CoreDebug_Type;
+
+/* Debug Halting Control and Status Register Definitions */
+#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */
+#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */
+
+#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */
+#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */
+
+#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */
+#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */
+
+#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */
+#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */
+
+#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */
+#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */
+
+#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */
+#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */
+
+#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */
+#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */
+
+#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */
+#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */
+
+#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */
+#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */
+
+#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */
+#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */
+
+#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */
+#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */
+
+#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */
+#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */
+
+#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */
+#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */
+
+/* Debug Core Register Selector Register Definitions */
+#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */
+#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */
+
+#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */
+#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */
+
+/* Debug Exception and Monitor Control Register Definitions */
+#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */
+#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */
+
+#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */
+#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */
+
+#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */
+#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */
+
+#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */
+#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */
+
+#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */
+#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */
+
+#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */
+#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */
+
+#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */
+#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */
+
+#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */
+#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */
+
+#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */
+#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */
+
+#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */
+#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */
+
+#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */
+#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */
+
+#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */
+#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */
+
+#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */
+#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */
+
+/* Debug Authentication Control Register Definitions */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */
+
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */
+
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */
+
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */
+
+/* Debug Security Control and Status Register Definitions */
+#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */
+#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */
+
+#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */
+#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */
+
+#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */
+#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */
+
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */
+ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
+ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */
+ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */
+ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+ #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */
+ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+ #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */
+ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */
+ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */
+ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
+ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
+ #endif
+
+ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */
+ #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */
+ #endif
+
+ #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */
+ #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */
+ #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */
+ #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */
+ #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */
+ #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */
+
+ #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */
+ #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */
+ #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */
+ #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */
+ #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */
+ #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */
+ #endif
+
+ #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */
+ #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Debug Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+ #define NVIC_GetActive __NVIC_GetActive
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* Special LR values for Secure/Non-Secure call handling and exception handling */
+
+/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */
+#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */
+
+/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */
+#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */
+#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */
+#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */
+#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */
+#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */
+#define EXC_RETURN_SPSEL (0x00000002UL) /* bit [1] stack pointer used to restore context: 0=MSP 1=PSP */
+#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */
+
+/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */
+#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */
+#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */
+#else
+#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */
+#endif
+
+
+/**
+ \brief Set Priority Grouping
+ \details Sets the priority grouping field using the required unlock sequence.
+ The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
+ Only values from 0..7 are used.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Priority grouping field.
+ */
+__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
+{
+ uint32_t reg_value;
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+
+ reg_value = SCB->AIRCR; /* read old register configuration */
+ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
+ reg_value = (reg_value |
+ ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */
+ SCB->AIRCR = reg_value;
+}
+
+
+/**
+ \brief Get Priority Grouping
+ \details Reads the priority grouping field from the NVIC Interrupt Controller.
+ \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void)
+{
+ return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
+}
+
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt
+ \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Get Interrupt Target State
+ \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ \return 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Target State
+ \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Clear Interrupt Target State
+ \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+ else
+ {
+ SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
+ SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Set Priority Grouping (non-secure)
+ \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence.
+ The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
+ Only values from 0..7 are used.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Priority grouping field.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup)
+{
+ uint32_t reg_value;
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+
+ reg_value = SCB_NS->AIRCR; /* read old register configuration */
+ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
+ reg_value = (reg_value |
+ ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */
+ SCB_NS->AIRCR = reg_value;
+}
+
+
+/**
+ \brief Get Priority Grouping (non-secure)
+ \details Reads the priority grouping field from the non-secure NVIC when in secure state.
+ \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void)
+{
+ return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
+}
+
+
+/**
+ \brief Enable Interrupt (non-secure)
+ \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status (non-secure)
+ \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt (non-secure)
+ \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt (non-secure)
+ \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt (non-secure)
+ \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt (non-secure)
+ \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt (non-secure)
+ \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority (non-secure)
+ \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every non-secure processor exception.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+ else
+ {
+ SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority (non-secure)
+ \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+/* ########################## MPU functions #################################### */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+
+#include "mpu_armv8.h"
+
+#endif
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ uint32_t mvfr0;
+
+ mvfr0 = FPU->MVFR0;
+ if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U)
+ {
+ return 2U; /* Double + Single precision FPU */
+ }
+ else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U)
+ {
+ return 1U; /* Single precision FPU */
+ }
+ else
+ {
+ return 0U; /* No FPU */
+ }
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ########################## SAU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SAUFunctions SAU Functions
+ \brief Functions that configure the SAU.
+ @{
+ */
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+
+/**
+ \brief Enable SAU
+ \details Enables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Enable(void)
+{
+ SAU->CTRL |= (SAU_CTRL_ENABLE_Msk);
+}
+
+
+
+/**
+ \brief Disable SAU
+ \details Disables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Disable(void)
+{
+ SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk);
+}
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_SAUFunctions */
+
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief System Tick Configuration (non-secure)
+ \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function TZ_SysTick_Config_NS is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+
+ */
+__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+/* ##################################### Debug In/Output function ########################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_core_DebugFunctions ITM Functions
+ \brief Functions that access the ITM debug interface.
+ @{
+ */
+
+extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */
+#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
+
+
+/**
+ \brief ITM Send Character
+ \details Transmits a character via the ITM channel 0, and
+ \li Just returns when no debugger is connected that has booked the output.
+ \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted.
+ \param [in] ch Character to transmit.
+ \returns Character to transmit.
+ */
+__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch)
+{
+ if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */
+ ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */
+ {
+ while (ITM->PORT[0U].u32 == 0UL)
+ {
+ __NOP();
+ }
+ ITM->PORT[0U].u8 = (uint8_t)ch;
+ }
+ return (ch);
+}
+
+
+/**
+ \brief ITM Receive Character
+ \details Inputs a character via the external variable \ref ITM_RxBuffer.
+ \return Received character.
+ \return -1 No character pending.
+ */
+__STATIC_INLINE int32_t ITM_ReceiveChar (void)
+{
+ int32_t ch = -1; /* no character available */
+
+ if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY)
+ {
+ ch = ITM_RxBuffer;
+ ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */
+ }
+
+ return (ch);
+}
+
+
+/**
+ \brief ITM Check Character
+ \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer.
+ \return 0 No character available.
+ \return 1 Character available.
+ */
+__STATIC_INLINE int32_t ITM_CheckChar (void)
+{
+
+ if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY)
+ {
+ return (0); /* no character available */
+ }
+ else
+ {
+ return (1); /* character available */
+ }
+}
+
+/*@} end of CMSIS_core_DebugFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_ARMV8MML_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm0.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm0.h
new file mode 100644
index 0000000..f929bba
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm0.h
@@ -0,0 +1,949 @@
+/**************************************************************************//**
+ * @file core_cm0.h
+ * @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File
+ * @version V5.0.5
+ * @date 28. May 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_CM0_H_GENERIC
+#define __CORE_CM0_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup Cortex_M0
+ @{
+ */
+
+#include "cmsis_version.h"
+
+/* CMSIS CM0 definitions */
+#define __CM0_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __CM0_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16U) | \
+ __CM0_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_M (0U) /*!< Cortex-M Core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ This core does not support an FPU at all
+*/
+#define __FPU_USED 0U
+
+#if defined ( __CC_ARM )
+ #if defined __TARGET_FPU_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_PCS_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined __ARMVFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined __TI_VFP_SUPPORT__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined __FPU_VFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM0_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_CM0_H_DEPENDANT
+#define __CORE_CM0_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __CM0_REV
+ #define __CM0_REV 0x0000U
+ #warning "__CM0_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 2U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group Cortex_M0 */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
+ uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:1; /*!< bit: 0 Reserved */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
+ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[31U];
+ __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[31U];
+ __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[31U];
+ __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[31U];
+ uint32_t RESERVED4[64U];
+ __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
+} NVIC_Type;
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+ uint32_t RESERVED0;
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ uint32_t RESERVED1;
+ __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */
+#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */
+#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Cortex-M0 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor.
+ Therefore they are not covered by the Cortex-M0 header file.
+ @{
+ */
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+
+
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+/*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M0 */
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* The following EXC_RETURN values are saved the LR on exception entry */
+#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */
+#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */
+#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */
+
+
+/* Interrupt Priorities are WORD accessible only under Armv6-M */
+/* The following MACROS handle generation of the register offset and byte masks */
+#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
+#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) )
+#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
+
+#define __NVIC_SetPriorityGrouping(X) (void)(X)
+#define __NVIC_GetPriorityGrouping() (0U)
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+ else
+ {
+ SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ Address 0 must be mapped to SRAM.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t *vectors = (uint32_t *)0x0U;
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t *vectors = (uint32_t *)0x0U;
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ SCB_AIRCR_SYSRESETREQ_Msk);
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ return 0U; /* No FPU */
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM0_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm0plus.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm0plus.h
new file mode 100644
index 0000000..424011a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm0plus.h
@@ -0,0 +1,1083 @@
+/**************************************************************************//**
+ * @file core_cm0plus.h
+ * @brief CMSIS Cortex-M0+ Core Peripheral Access Layer Header File
+ * @version V5.0.6
+ * @date 28. May 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_CM0PLUS_H_GENERIC
+#define __CORE_CM0PLUS_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup Cortex-M0+
+ @{
+ */
+
+#include "cmsis_version.h"
+
+/* CMSIS CM0+ definitions */
+#define __CM0PLUS_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __CM0PLUS_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __CM0PLUS_CMSIS_VERSION ((__CM0PLUS_CMSIS_VERSION_MAIN << 16U) | \
+ __CM0PLUS_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_M (0U) /*!< Cortex-M Core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ This core does not support an FPU at all
+*/
+#define __FPU_USED 0U
+
+#if defined ( __CC_ARM )
+ #if defined __TARGET_FPU_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_PCS_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined __ARMVFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined __TI_VFP_SUPPORT__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined __FPU_VFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM0PLUS_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_CM0PLUS_H_DEPENDANT
+#define __CORE_CM0PLUS_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __CM0PLUS_REV
+ #define __CM0PLUS_REV 0x0000U
+ #warning "__CM0PLUS_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MPU_PRESENT
+ #define __MPU_PRESENT 0U
+ #warning "__MPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __VTOR_PRESENT
+ #define __VTOR_PRESENT 0U
+ #warning "__VTOR_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 2U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group Cortex-M0+ */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ - Core MPU Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
+ uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
+ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */
+#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[31U];
+ __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[31U];
+ __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[31U];
+ __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[31U];
+ uint32_t RESERVED4[64U];
+ __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
+} NVIC_Type;
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
+#else
+ uint32_t RESERVED0;
+#endif
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ uint32_t RESERVED1;
+ __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */
+#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_VTOR_TBLOFF_Pos 8U /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk (0xFFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
+#endif
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */
+#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_MPU Memory Protection Unit (MPU)
+ \brief Type definitions for the Memory Protection Unit (MPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+ __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
+ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
+ __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */
+} MPU_Type;
+
+#define MPU_TYPE_RALIASES 1U
+
+/* MPU Type Register Definitions */
+#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register Definitions */
+#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register Definitions */
+#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register Definitions */
+#define MPU_RBAR_ADDR_Pos 8U /*!< MPU RBAR: ADDR Position */
+#define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */
+
+#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */
+#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */
+
+#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */
+#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */
+
+/* MPU Region Attribute and Size Register Definitions */
+#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */
+#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */
+
+#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */
+#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */
+
+#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */
+#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */
+
+#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */
+#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */
+
+#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */
+#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */
+
+#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */
+#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */
+
+#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */
+#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */
+
+#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */
+#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */
+
+#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */
+#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */
+
+#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */
+#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Cortex-M0+ Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor.
+ Therefore they are not covered by the Cortex-M0+ header file.
+ @{
+ */
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
+ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
+#endif
+
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+/*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M0+ */
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* The following EXC_RETURN values are saved the LR on exception entry */
+#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */
+#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */
+#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */
+
+
+/* Interrupt Priorities are WORD accessible only under Armv6-M */
+/* The following MACROS handle generation of the register offset and byte masks */
+#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
+#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) )
+#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
+
+#define __NVIC_SetPriorityGrouping(X) (void)(X)
+#define __NVIC_GetPriorityGrouping() (0U)
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+ else
+ {
+ SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ If VTOR is not present address 0 must be mapped to SRAM.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+#else
+ uint32_t *vectors = (uint32_t *)0x0U;
+#endif
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+#else
+ uint32_t *vectors = (uint32_t *)0x0U;
+#endif
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ SCB_AIRCR_SYSRESETREQ_Msk);
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+/* ########################## MPU functions #################################### */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+
+#include "mpu_armv7.h"
+
+#endif
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ return 0U; /* No FPU */
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM0PLUS_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm1.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm1.h
new file mode 100644
index 0000000..0ed678e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm1.h
@@ -0,0 +1,976 @@
+/**************************************************************************//**
+ * @file core_cm1.h
+ * @brief CMSIS Cortex-M1 Core Peripheral Access Layer Header File
+ * @version V1.0.0
+ * @date 23. July 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_CM1_H_GENERIC
+#define __CORE_CM1_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup Cortex_M1
+ @{
+ */
+
+#include "cmsis_version.h"
+
+/* CMSIS CM1 definitions */
+#define __CM1_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __CM1_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __CM1_CMSIS_VERSION ((__CM1_CMSIS_VERSION_MAIN << 16U) | \
+ __CM1_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_M (1U) /*!< Cortex-M Core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ This core does not support an FPU at all
+*/
+#define __FPU_USED 0U
+
+#if defined ( __CC_ARM )
+ #if defined __TARGET_FPU_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_PCS_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined __ARMVFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined __TI_VFP_SUPPORT__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined __FPU_VFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM1_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_CM1_H_DEPENDANT
+#define __CORE_CM1_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __CM1_REV
+ #define __CM1_REV 0x0100U
+ #warning "__CM1_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 2U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group Cortex_M1 */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
+ uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:1; /*!< bit: 0 Reserved */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
+ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[31U];
+ __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[31U];
+ __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[31U];
+ __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[31U];
+ uint32_t RESERVED4[64U];
+ __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
+} NVIC_Type;
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+ uint32_t RESERVED0;
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ uint32_t RESERVED1;
+ __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */
+#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */
+#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB)
+ \brief Type definitions for the System Control and ID Register not in the SCB
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control and ID Register not in the SCB.
+ */
+typedef struct
+{
+ uint32_t RESERVED0[2U];
+ __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */
+} SCnSCB_Type;
+
+/* Auxiliary Control Register Definitions */
+#define SCnSCB_ACTLR_ITCMUAEN_Pos 4U /*!< ACTLR: Instruction TCM Upper Alias Enable Position */
+#define SCnSCB_ACTLR_ITCMUAEN_Msk (1UL << SCnSCB_ACTLR_ITCMUAEN_Pos) /*!< ACTLR: Instruction TCM Upper Alias Enable Mask */
+
+#define SCnSCB_ACTLR_ITCMLAEN_Pos 3U /*!< ACTLR: Instruction TCM Lower Alias Enable Position */
+#define SCnSCB_ACTLR_ITCMLAEN_Msk (1UL << SCnSCB_ACTLR_ITCMLAEN_Pos) /*!< ACTLR: Instruction TCM Lower Alias Enable Mask */
+
+/*@} end of group CMSIS_SCnotSCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Cortex-M1 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor.
+ Therefore they are not covered by the Cortex-M1 header file.
+ @{
+ */
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */
+#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+
+
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+/*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M1 */
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* The following EXC_RETURN values are saved the LR on exception entry */
+#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */
+#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */
+#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */
+
+
+/* Interrupt Priorities are WORD accessible only under Armv6-M */
+/* The following MACROS handle generation of the register offset and byte masks */
+#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
+#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) )
+#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
+
+#define __NVIC_SetPriorityGrouping(X) (void)(X)
+#define __NVIC_GetPriorityGrouping() (0U)
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+ else
+ {
+ SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ Address 0 must be mapped to SRAM.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t *vectors = (uint32_t *)0x0U;
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t *vectors = (uint32_t *)0x0U;
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ SCB_AIRCR_SYSRESETREQ_Msk);
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ return 0U; /* No FPU */
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM1_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm23.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm23.h
new file mode 100644
index 0000000..acbc5df
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm23.h
@@ -0,0 +1,1993 @@
+/**************************************************************************//**
+ * @file core_cm23.h
+ * @brief CMSIS Cortex-M23 Core Peripheral Access Layer Header File
+ * @version V5.0.7
+ * @date 22. June 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_CM23_H_GENERIC
+#define __CORE_CM23_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup Cortex_M23
+ @{
+ */
+
+#include "cmsis_version.h"
+
+/* CMSIS definitions */
+#define __CM23_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __CM23_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __CM23_CMSIS_VERSION ((__CM23_CMSIS_VERSION_MAIN << 16U) | \
+ __CM23_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_M (23U) /*!< Cortex-M Core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ This core does not support an FPU at all
+*/
+#define __FPU_USED 0U
+
+#if defined ( __CC_ARM )
+ #if defined __TARGET_FPU_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_PCS_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined __ARMVFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined __TI_VFP_SUPPORT__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined __FPU_VFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM23_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_CM23_H_DEPENDANT
+#define __CORE_CM23_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __CM23_REV
+ #define __CM23_REV 0x0000U
+ #warning "__CM23_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __FPU_PRESENT
+ #define __FPU_PRESENT 0U
+ #warning "__FPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MPU_PRESENT
+ #define __MPU_PRESENT 0U
+ #warning "__MPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __SAUREGION_PRESENT
+ #define __SAUREGION_PRESENT 0U
+ #warning "__SAUREGION_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __VTOR_PRESENT
+ #define __VTOR_PRESENT 0U
+ #warning "__VTOR_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 2U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+
+ #ifndef __ETM_PRESENT
+ #define __ETM_PRESENT 0U
+ #warning "__ETM_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MTB_PRESENT
+ #define __MTB_PRESENT 0U
+ #warning "__MTB_PRESENT not defined in device header file; using default!"
+ #endif
+
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group Cortex_M23 */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ - Core Debug Register
+ - Core MPU Register
+ - Core SAU Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
+ uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */
+ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */
+#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[16U];
+ __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[16U];
+ __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[16U];
+ __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[16U];
+ __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
+ uint32_t RESERVED4[16U];
+ __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */
+ uint32_t RESERVED5[16U];
+ __IOM uint32_t IPR[124U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
+} NVIC_Type;
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
+#else
+ uint32_t RESERVED0;
+#endif
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ uint32_t RESERVED1;
+ __IOM uint32_t SHPR[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */
+#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */
+
+#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */
+#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */
+
+#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */
+#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */
+#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */
+#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+/* SCB Vector Table Offset Register Definitions */
+#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
+#endif
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */
+#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */
+
+#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */
+#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */
+
+#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */
+#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */
+#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */
+#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */
+
+#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */
+#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */
+
+#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */
+#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */
+
+#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */
+#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */
+
+#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */
+#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */
+
+#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */
+#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */
+#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */
+#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */
+
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */
+#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */
+
+#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */
+#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */
+
+#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */
+#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */
+
+#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */
+#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */
+
+#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */
+#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT)
+ \brief Type definitions for the Data Watchpoint and Trace (DWT)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Data Watchpoint and Trace Register (DWT).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */
+ uint32_t RESERVED0[6U];
+ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */
+ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */
+ uint32_t RESERVED1[1U];
+ __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */
+ uint32_t RESERVED2[1U];
+ __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */
+ uint32_t RESERVED3[1U];
+ __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */
+ uint32_t RESERVED5[1U];
+ __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */
+ uint32_t RESERVED6[1U];
+ __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */
+ uint32_t RESERVED7[1U];
+ __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */
+ uint32_t RESERVED8[1U];
+ __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */
+ uint32_t RESERVED9[1U];
+ __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */
+ uint32_t RESERVED10[1U];
+ __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */
+ uint32_t RESERVED11[1U];
+ __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */
+ uint32_t RESERVED12[1U];
+ __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */
+ uint32_t RESERVED13[1U];
+ __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */
+ uint32_t RESERVED14[1U];
+ __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */
+ uint32_t RESERVED15[1U];
+ __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */
+ uint32_t RESERVED16[1U];
+ __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */
+ uint32_t RESERVED17[1U];
+ __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */
+ uint32_t RESERVED18[1U];
+ __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */
+ uint32_t RESERVED19[1U];
+ __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */
+ uint32_t RESERVED20[1U];
+ __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */
+ uint32_t RESERVED21[1U];
+ __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */
+ uint32_t RESERVED22[1U];
+ __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */
+ uint32_t RESERVED23[1U];
+ __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */
+ uint32_t RESERVED24[1U];
+ __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */
+ uint32_t RESERVED25[1U];
+ __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */
+ uint32_t RESERVED26[1U];
+ __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */
+ uint32_t RESERVED27[1U];
+ __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */
+ uint32_t RESERVED28[1U];
+ __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */
+ uint32_t RESERVED29[1U];
+ __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */
+ uint32_t RESERVED30[1U];
+ __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */
+ uint32_t RESERVED31[1U];
+ __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */
+} DWT_Type;
+
+/* DWT Control Register Definitions */
+#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */
+#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */
+
+#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */
+#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */
+
+#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */
+#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */
+
+#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */
+#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */
+
+#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */
+#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */
+
+/* DWT Comparator Function Register Definitions */
+#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */
+#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */
+
+#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */
+#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */
+
+#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */
+#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */
+
+#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */
+#define DWT_FUNCTION_ACTION_Msk (0x3UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */
+
+#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */
+#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */
+
+/*@}*/ /* end of group CMSIS_DWT */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_TPI Trace Port Interface (TPI)
+ \brief Type definitions for the Trace Port Interface (TPI)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Trace Port Interface Register (TPI).
+ */
+typedef struct
+{
+ __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */
+ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */
+ uint32_t RESERVED0[2U];
+ __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */
+ uint32_t RESERVED1[55U];
+ __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */
+ uint32_t RESERVED2[131U];
+ __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */
+ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */
+ __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */
+ uint32_t RESERVED3[759U];
+ __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */
+ __IM uint32_t ITFTTD0; /*!< Offset: 0xEEC (R/ ) Integration Test FIFO Test Data 0 Register */
+ __IOM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/W) Integration Test ATB Control Register 2 */
+ uint32_t RESERVED4[1U];
+ __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) Integration Test ATB Control Register 0 */
+ __IM uint32_t ITFTTD1; /*!< Offset: 0xEFC (R/ ) Integration Test FIFO Test Data 1 Register */
+ __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */
+ uint32_t RESERVED5[39U];
+ __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */
+ __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */
+ uint32_t RESERVED7[8U];
+ __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) Device Configuration Register */
+ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Identifier Register */
+} TPI_Type;
+
+/* TPI Asynchronous Clock Prescaler Register Definitions */
+#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */
+#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */
+
+/* TPI Selected Pin Protocol Register Definitions */
+#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */
+#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */
+
+/* TPI Formatter and Flush Status Register Definitions */
+#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */
+#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */
+
+#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */
+#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */
+
+#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */
+#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */
+
+#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */
+#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */
+
+/* TPI Formatter and Flush Control Register Definitions */
+#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */
+#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */
+
+#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */
+#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */
+
+#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */
+#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */
+
+/* TPI TRIGGER Register Definitions */
+#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */
+#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */
+
+/* TPI Integration Test FIFO Test Data 0 Register Definitions */
+#define TPI_ITFTTD0_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD0: ATB Interface 2 ATVALIDPosition */
+#define TPI_ITFTTD0_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 2 ATVALID Mask */
+
+#define TPI_ITFTTD0_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD0: ATB Interface 2 byte count Position */
+#define TPI_ITFTTD0_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 2 byte count Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Position */
+#define TPI_ITFTTD0_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD0: ATB Interface 1 byte count Position */
+#define TPI_ITFTTD0_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 1 byte countt Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_data2_Pos 16U /*!< TPI ITFTTD0: ATB Interface 1 data2 Position */
+#define TPI_ITFTTD0_ATB_IF1_data2_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data2 Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_data1_Pos 8U /*!< TPI ITFTTD0: ATB Interface 1 data1 Position */
+#define TPI_ITFTTD0_ATB_IF1_data1_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data1 Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_data0_Pos 0U /*!< TPI ITFTTD0: ATB Interface 1 data0 Position */
+#define TPI_ITFTTD0_ATB_IF1_data0_Msk (0xFFUL /*<< TPI_ITFTTD0_ATB_IF1_data0_Pos*/) /*!< TPI ITFTTD0: ATB Interface 1 data0 Mask */
+
+/* TPI Integration Test ATB Control Register 2 Register Definitions */
+#define TPI_ITATBCTR2_AFVALID2S_Pos 1U /*!< TPI ITATBCTR2: AFVALID2S Position */
+#define TPI_ITATBCTR2_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID2S_Pos) /*!< TPI ITATBCTR2: AFVALID2SS Mask */
+
+#define TPI_ITATBCTR2_AFVALID1S_Pos 1U /*!< TPI ITATBCTR2: AFVALID1S Position */
+#define TPI_ITATBCTR2_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID1S_Pos) /*!< TPI ITATBCTR2: AFVALID1SS Mask */
+
+#define TPI_ITATBCTR2_ATREADY2S_Pos 0U /*!< TPI ITATBCTR2: ATREADY2S Position */
+#define TPI_ITATBCTR2_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2S_Pos*/) /*!< TPI ITATBCTR2: ATREADY2S Mask */
+
+#define TPI_ITATBCTR2_ATREADY1S_Pos 0U /*!< TPI ITATBCTR2: ATREADY1S Position */
+#define TPI_ITATBCTR2_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1S_Pos*/) /*!< TPI ITATBCTR2: ATREADY1S Mask */
+
+/* TPI Integration Test FIFO Test Data 1 Register Definitions */
+#define TPI_ITFTTD1_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Position */
+#define TPI_ITFTTD1_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD1: ATB Interface 2 byte count Position */
+#define TPI_ITFTTD1_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 2 byte count Mask */
+
+#define TPI_ITFTTD1_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Position */
+#define TPI_ITFTTD1_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Mask */
+
+#define TPI_ITFTTD1_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD1: ATB Interface 1 byte count Position */
+#define TPI_ITFTTD1_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 1 byte countt Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_data2_Pos 16U /*!< TPI ITFTTD1: ATB Interface 2 data2 Position */
+#define TPI_ITFTTD1_ATB_IF2_data2_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data2 Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_data1_Pos 8U /*!< TPI ITFTTD1: ATB Interface 2 data1 Position */
+#define TPI_ITFTTD1_ATB_IF2_data1_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data1 Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_data0_Pos 0U /*!< TPI ITFTTD1: ATB Interface 2 data0 Position */
+#define TPI_ITFTTD1_ATB_IF2_data0_Msk (0xFFUL /*<< TPI_ITFTTD1_ATB_IF2_data0_Pos*/) /*!< TPI ITFTTD1: ATB Interface 2 data0 Mask */
+
+/* TPI Integration Test ATB Control Register 0 Definitions */
+#define TPI_ITATBCTR0_AFVALID2S_Pos 1U /*!< TPI ITATBCTR0: AFVALID2S Position */
+#define TPI_ITATBCTR0_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID2S_Pos) /*!< TPI ITATBCTR0: AFVALID2SS Mask */
+
+#define TPI_ITATBCTR0_AFVALID1S_Pos 1U /*!< TPI ITATBCTR0: AFVALID1S Position */
+#define TPI_ITATBCTR0_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID1S_Pos) /*!< TPI ITATBCTR0: AFVALID1SS Mask */
+
+#define TPI_ITATBCTR0_ATREADY2S_Pos 0U /*!< TPI ITATBCTR0: ATREADY2S Position */
+#define TPI_ITATBCTR0_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2S_Pos*/) /*!< TPI ITATBCTR0: ATREADY2S Mask */
+
+#define TPI_ITATBCTR0_ATREADY1S_Pos 0U /*!< TPI ITATBCTR0: ATREADY1S Position */
+#define TPI_ITATBCTR0_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1S_Pos*/) /*!< TPI ITATBCTR0: ATREADY1S Mask */
+
+/* TPI Integration Mode Control Register Definitions */
+#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */
+#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */
+
+/* TPI DEVID Register Definitions */
+#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */
+#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */
+
+#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */
+#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */
+
+#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */
+#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */
+
+#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFOSZ Position */
+#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFOSZ Mask */
+
+#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */
+#define TPI_DEVID_NrTraceInput_Msk (0x3FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */
+
+/* TPI DEVTYPE Register Definitions */
+#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */
+
+#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
+
+/*@}*/ /* end of group CMSIS_TPI */
+
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_MPU Memory Protection Unit (MPU)
+ \brief Type definitions for the Memory Protection Unit (MPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+ __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
+ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */
+ uint32_t RESERVED0[7U];
+ union {
+ __IOM uint32_t MAIR[2];
+ struct {
+ __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */
+ __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */
+ };
+ };
+} MPU_Type;
+
+#define MPU_TYPE_RALIASES 1U
+
+/* MPU Type Register Definitions */
+#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register Definitions */
+#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register Definitions */
+#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register Definitions */
+#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */
+#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */
+
+#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */
+#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */
+
+#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */
+#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */
+
+#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */
+#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */
+
+/* MPU Region Limit Address Register Definitions */
+#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */
+#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */
+
+#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */
+#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */
+
+#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: EN Position */
+#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: EN Mask */
+
+/* MPU Memory Attribute Indirection Register 0 Definitions */
+#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */
+#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */
+
+#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */
+#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */
+
+#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */
+#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */
+
+#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */
+#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */
+
+/* MPU Memory Attribute Indirection Register 1 Definitions */
+#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */
+#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */
+
+#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */
+#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */
+
+#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */
+#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */
+
+#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */
+#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SAU Security Attribution Unit (SAU)
+ \brief Type definitions for the Security Attribution Unit (SAU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Security Attribution Unit (SAU).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */
+ __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */
+#endif
+} SAU_Type;
+
+/* SAU Control Register Definitions */
+#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */
+#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */
+
+#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */
+#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */
+
+/* SAU Type Register Definitions */
+#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */
+#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */
+
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+/* SAU Region Number Register Definitions */
+#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */
+#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */
+
+/* SAU Region Base Address Register Definitions */
+#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */
+#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */
+
+/* SAU Region Limit Address Register Definitions */
+#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */
+#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */
+
+#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */
+#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */
+
+#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */
+#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */
+
+#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */
+
+/*@} end of group CMSIS_SAU */
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Type definitions for the Core Debug Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Core Debug Register (CoreDebug).
+ */
+typedef struct
+{
+ __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */
+ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */
+ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */
+ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */
+ __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */
+} CoreDebug_Type;
+
+/* Debug Halting Control and Status Register Definitions */
+#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */
+#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */
+
+#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */
+#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */
+
+#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */
+#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */
+
+#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */
+#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */
+
+#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */
+#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */
+
+#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */
+#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */
+
+#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */
+#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */
+
+#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */
+#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */
+
+#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */
+#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */
+
+#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */
+#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */
+
+#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */
+#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */
+
+#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */
+#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */
+
+/* Debug Core Register Selector Register Definitions */
+#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */
+#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */
+
+#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */
+#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */
+
+/* Debug Exception and Monitor Control Register */
+#define CoreDebug_DEMCR_DWTENA_Pos 24U /*!< CoreDebug DEMCR: DWTENA Position */
+#define CoreDebug_DEMCR_DWTENA_Msk (1UL << CoreDebug_DEMCR_DWTENA_Pos) /*!< CoreDebug DEMCR: DWTENA Mask */
+
+#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */
+#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */
+
+#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */
+#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */
+
+/* Debug Authentication Control Register Definitions */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */
+
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */
+
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */
+
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */
+
+/* Debug Security Control and Status Register Definitions */
+#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */
+#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */
+
+#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */
+#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */
+
+#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */
+#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */
+
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
+ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */
+ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */
+ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+
+ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */
+ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */
+ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
+ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
+ #endif
+
+ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */
+ #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */
+ #endif
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */
+ #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */
+ #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */
+ #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */
+ #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */
+
+ #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */
+ #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */
+ #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */
+ #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */
+ #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */
+ #endif
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+/*#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping not available for Cortex-M23 */
+/*#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping not available for Cortex-M23 */
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+ #define NVIC_GetActive __NVIC_GetActive
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* Special LR values for Secure/Non-Secure call handling and exception handling */
+
+/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */
+#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */
+
+/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */
+#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */
+#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */
+#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */
+#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */
+#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */
+#define EXC_RETURN_SPSEL (0x00000002UL) /* bit [1] stack pointer used to restore context: 0=MSP 1=PSP */
+#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */
+
+/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */
+#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */
+#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */
+#else
+#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */
+#endif
+
+
+/* Interrupt Priorities are WORD accessible only under Armv6-M */
+/* The following MACROS handle generation of the register offset and byte masks */
+#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
+#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) )
+#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
+
+#define __NVIC_SetPriorityGrouping(X) (void)(X)
+#define __NVIC_GetPriorityGrouping() (0U)
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt
+ \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Get Interrupt Target State
+ \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ \return 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Target State
+ \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Clear Interrupt Target State
+ \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+ else
+ {
+ SCB->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return((uint32_t)(((SCB->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ If VTOR is not present address 0 must be mapped to SRAM.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+#else
+ uint32_t *vectors = (uint32_t *)0x0U;
+#endif
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+#else
+ uint32_t *vectors = (uint32_t *)0x0U;
+#endif
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ SCB_AIRCR_SYSRESETREQ_Msk);
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Enable Interrupt (non-secure)
+ \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status (non-secure)
+ \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt (non-secure)
+ \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt (non-secure)
+ \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt (non-secure)
+ \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt (non-secure)
+ \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt (non-secure)
+ \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority (non-secure)
+ \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every non-secure processor exception.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC_NS->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+ else
+ {
+ SCB_NS->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB_NS->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority (non-secure)
+ \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return((uint32_t)(((SCB_NS->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+/* ########################## MPU functions #################################### */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+
+#include "mpu_armv8.h"
+
+#endif
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ return 0U; /* No FPU */
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ########################## SAU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SAUFunctions SAU Functions
+ \brief Functions that configure the SAU.
+ @{
+ */
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+
+/**
+ \brief Enable SAU
+ \details Enables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Enable(void)
+{
+ SAU->CTRL |= (SAU_CTRL_ENABLE_Msk);
+}
+
+
+
+/**
+ \brief Disable SAU
+ \details Disables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Disable(void)
+{
+ SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk);
+}
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_SAUFunctions */
+
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief System Tick Configuration (non-secure)
+ \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function TZ_SysTick_Config_NS is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+
+ */
+__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM23_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm3.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm3.h
new file mode 100644
index 0000000..74bff64
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm3.h
@@ -0,0 +1,1941 @@
+/**************************************************************************//**
+ * @file core_cm3.h
+ * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File
+ * @version V5.0.8
+ * @date 04. June 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_CM3_H_GENERIC
+#define __CORE_CM3_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup Cortex_M3
+ @{
+ */
+
+#include "cmsis_version.h"
+
+/* CMSIS CM3 definitions */
+#define __CM3_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __CM3_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16U) | \
+ __CM3_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_M (3U) /*!< Cortex-M Core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ This core does not support an FPU at all
+*/
+#define __FPU_USED 0U
+
+#if defined ( __CC_ARM )
+ #if defined __TARGET_FPU_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_PCS_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined __ARMVFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined __TI_VFP_SUPPORT__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined __FPU_VFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM3_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_CM3_H_DEPENDANT
+#define __CORE_CM3_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __CM3_REV
+ #define __CM3_REV 0x0200U
+ #warning "__CM3_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MPU_PRESENT
+ #define __MPU_PRESENT 0U
+ #warning "__MPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 3U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group Cortex_M3 */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ - Core Debug Register
+ - Core MPU Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+#define APSR_Q_Pos 27U /*!< APSR: Q Position */
+#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:1; /*!< bit: 9 Reserved */
+ uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */
+ uint32_t _reserved1:8; /*!< bit: 16..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit */
+ uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */
+#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */
+
+#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */
+#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */
+#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
+ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */
+#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[24U];
+ __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[24U];
+ __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[24U];
+ __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[24U];
+ __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
+ uint32_t RESERVED4[56U];
+ __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
+ uint32_t RESERVED5[644U];
+ __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
+} NVIC_Type;
+
+/* Software Triggered Interrupt Register Definitions */
+#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */
+#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+ __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */
+ __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */
+ __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */
+ __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */
+ __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */
+ __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */
+ __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */
+ __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */
+ __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */
+ __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */
+ __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */
+ uint32_t RESERVED0[5U];
+ __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */
+#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */
+#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+/* SCB Vector Table Offset Register Definitions */
+#if defined (__CM3_REV) && (__CM3_REV < 0x0201U) /* core r2p1 */
+#define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */
+#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */
+
+#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
+#else
+#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
+#endif
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */
+#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */
+#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */
+#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
+
+#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */
+#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */
+
+#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */
+#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */
+#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */
+
+#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */
+#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */
+#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */
+
+#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */
+#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */
+
+#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */
+#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */
+
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */
+#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */
+
+#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */
+#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */
+
+#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */
+#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */
+
+#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */
+#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */
+
+#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */
+#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */
+
+#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */
+#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */
+
+#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */
+#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */
+
+#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */
+#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */
+
+#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */
+#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */
+
+#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */
+#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */
+
+/* SCB Configurable Fault Status Register Definitions */
+#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */
+#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */
+
+#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */
+#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */
+
+#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */
+#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */
+
+/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */
+#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */
+
+#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */
+#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */
+
+#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */
+#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */
+
+#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */
+#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */
+
+#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */
+#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */
+
+/* BusFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */
+#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */
+
+#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */
+#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */
+
+#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */
+#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */
+
+#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */
+#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */
+
+#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */
+#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */
+
+#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */
+#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */
+
+/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */
+#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */
+
+#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */
+#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */
+
+#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */
+#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */
+
+#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */
+#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */
+
+#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */
+#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */
+
+#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */
+#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */
+
+/* SCB Hard Fault Status Register Definitions */
+#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */
+#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */
+
+#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */
+#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */
+
+#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */
+#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */
+
+/* SCB Debug Fault Status Register Definitions */
+#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */
+#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */
+
+#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */
+#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */
+
+#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */
+#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */
+
+#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */
+#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */
+
+#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */
+#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB)
+ \brief Type definitions for the System Control and ID Register not in the SCB
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control and ID Register not in the SCB.
+ */
+typedef struct
+{
+ uint32_t RESERVED0[1U];
+ __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */
+#if defined (__CM3_REV) && (__CM3_REV >= 0x200U)
+ __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */
+#else
+ uint32_t RESERVED1[1U];
+#endif
+} SCnSCB_Type;
+
+/* Interrupt Controller Type Register Definitions */
+#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */
+#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */
+
+/* Auxiliary Control Register Definitions */
+
+#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */
+#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */
+
+#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */
+#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */
+
+#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */
+#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */
+
+/*@} end of group CMSIS_SCnotSCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM)
+ \brief Type definitions for the Instrumentation Trace Macrocell (ITM)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM).
+ */
+typedef struct
+{
+ __OM union
+ {
+ __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */
+ __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */
+ __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */
+ } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */
+ uint32_t RESERVED0[864U];
+ __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */
+ uint32_t RESERVED1[15U];
+ __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */
+ uint32_t RESERVED2[15U];
+ __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */
+ uint32_t RESERVED3[29U];
+ __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */
+ __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */
+ __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */
+ uint32_t RESERVED4[43U];
+ __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */
+ uint32_t RESERVED5[6U];
+ __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */
+ __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */
+ __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */
+ __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */
+ __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */
+ __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */
+ __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */
+ __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */
+ __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */
+ __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */
+ __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */
+ __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */
+} ITM_Type;
+
+/* ITM Trace Privilege Register Definitions */
+#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */
+#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */
+
+/* ITM Trace Control Register Definitions */
+#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */
+#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */
+
+#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */
+#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */
+
+#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */
+#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */
+
+#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */
+#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */
+
+#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */
+#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */
+
+#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */
+#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */
+
+#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */
+#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */
+
+#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */
+#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */
+
+#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */
+#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */
+
+/* ITM Integration Write Register Definitions */
+#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */
+#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */
+
+/* ITM Integration Read Register Definitions */
+#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */
+#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */
+
+/* ITM Integration Mode Control Register Definitions */
+#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */
+#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */
+
+/* ITM Lock Status Register Definitions */
+#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */
+#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */
+
+#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */
+#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */
+
+#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */
+#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */
+
+/*@}*/ /* end of group CMSIS_ITM */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT)
+ \brief Type definitions for the Data Watchpoint and Trace (DWT)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Data Watchpoint and Trace Register (DWT).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */
+ __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */
+ __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */
+ __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */
+ __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */
+ __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */
+ __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */
+ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */
+ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */
+ __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */
+ __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */
+ uint32_t RESERVED0[1U];
+ __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */
+ __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */
+ __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */
+ uint32_t RESERVED1[1U];
+ __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */
+ __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */
+ __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */
+ uint32_t RESERVED2[1U];
+ __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */
+ __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */
+ __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */
+} DWT_Type;
+
+/* DWT Control Register Definitions */
+#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */
+#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */
+
+#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */
+#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */
+
+#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */
+#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */
+
+#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */
+#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */
+
+#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */
+#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */
+
+#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */
+#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */
+
+#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */
+#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */
+
+#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */
+#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */
+
+#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */
+#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */
+
+#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */
+#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */
+
+#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */
+#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */
+
+#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */
+#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */
+
+#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */
+#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */
+
+#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */
+#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */
+
+#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */
+#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */
+
+#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */
+#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */
+
+#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */
+#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */
+
+#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */
+#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */
+
+/* DWT CPI Count Register Definitions */
+#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */
+#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */
+
+/* DWT Exception Overhead Count Register Definitions */
+#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */
+#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */
+
+/* DWT Sleep Count Register Definitions */
+#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */
+#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */
+
+/* DWT LSU Count Register Definitions */
+#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */
+#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */
+
+/* DWT Folded-instruction Count Register Definitions */
+#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */
+#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */
+
+/* DWT Comparator Mask Register Definitions */
+#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */
+#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */
+
+/* DWT Comparator Function Register Definitions */
+#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */
+#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */
+
+#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */
+#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */
+
+#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */
+#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */
+
+#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */
+#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */
+
+#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */
+#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */
+
+#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */
+#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */
+
+#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */
+#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */
+
+#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */
+#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */
+
+#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */
+#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */
+
+/*@}*/ /* end of group CMSIS_DWT */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_TPI Trace Port Interface (TPI)
+ \brief Type definitions for the Trace Port Interface (TPI)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Trace Port Interface Register (TPI).
+ */
+typedef struct
+{
+ __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */
+ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */
+ uint32_t RESERVED0[2U];
+ __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */
+ uint32_t RESERVED1[55U];
+ __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */
+ uint32_t RESERVED2[131U];
+ __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */
+ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */
+ __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */
+ uint32_t RESERVED3[759U];
+ __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */
+ __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */
+ __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */
+ uint32_t RESERVED4[1U];
+ __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */
+ __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */
+ __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */
+ uint32_t RESERVED5[39U];
+ __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */
+ __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */
+ uint32_t RESERVED7[8U];
+ __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */
+ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */
+} TPI_Type;
+
+/* TPI Asynchronous Clock Prescaler Register Definitions */
+#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */
+#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */
+
+/* TPI Selected Pin Protocol Register Definitions */
+#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */
+#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */
+
+/* TPI Formatter and Flush Status Register Definitions */
+#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */
+#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */
+
+#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */
+#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */
+
+#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */
+#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */
+
+#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */
+#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */
+
+/* TPI Formatter and Flush Control Register Definitions */
+#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */
+#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */
+
+#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */
+#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */
+
+/* TPI TRIGGER Register Definitions */
+#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */
+#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */
+
+/* TPI Integration ETM Data Register Definitions (FIFO0) */
+#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */
+#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */
+
+#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */
+#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */
+
+#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */
+#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */
+
+#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */
+#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */
+
+#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */
+#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */
+
+#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */
+#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */
+
+#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */
+#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */
+
+/* TPI ITATBCTR2 Register Definitions */
+#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */
+#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */
+
+#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */
+#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */
+
+/* TPI Integration ITM Data Register Definitions (FIFO1) */
+#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */
+#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */
+
+#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */
+#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */
+
+#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */
+#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */
+
+#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */
+#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */
+
+#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */
+#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */
+
+#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */
+#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */
+
+#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */
+#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */
+
+/* TPI ITATBCTR0 Register Definitions */
+#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */
+#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */
+
+#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */
+#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */
+
+/* TPI Integration Mode Control Register Definitions */
+#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */
+#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */
+
+/* TPI DEVID Register Definitions */
+#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */
+#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */
+
+#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */
+#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */
+
+#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */
+#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */
+
+#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */
+#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */
+
+#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */
+#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */
+
+#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */
+#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */
+
+/* TPI DEVTYPE Register Definitions */
+#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */
+
+#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
+
+/*@}*/ /* end of group CMSIS_TPI */
+
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_MPU Memory Protection Unit (MPU)
+ \brief Type definitions for the Memory Protection Unit (MPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+ __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
+ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
+ __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */
+ __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */
+ __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */
+ __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */
+ __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */
+ __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */
+ __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */
+} MPU_Type;
+
+#define MPU_TYPE_RALIASES 4U
+
+/* MPU Type Register Definitions */
+#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register Definitions */
+#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register Definitions */
+#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register Definitions */
+#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */
+#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */
+
+#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */
+#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */
+
+#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */
+#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */
+
+/* MPU Region Attribute and Size Register Definitions */
+#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */
+#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */
+
+#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */
+#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */
+
+#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */
+#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */
+
+#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */
+#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */
+
+#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */
+#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */
+
+#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */
+#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */
+
+#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */
+#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */
+
+#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */
+#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */
+
+#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */
+#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */
+
+#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */
+#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Type definitions for the Core Debug Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Core Debug Register (CoreDebug).
+ */
+typedef struct
+{
+ __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */
+ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */
+ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */
+ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */
+} CoreDebug_Type;
+
+/* Debug Halting Control and Status Register Definitions */
+#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */
+#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */
+
+#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */
+#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */
+
+#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */
+#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */
+
+#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */
+#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */
+
+#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */
+#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */
+
+#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */
+#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */
+
+#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */
+#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */
+
+#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */
+#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */
+
+#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */
+#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */
+
+#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */
+#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */
+
+#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */
+#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */
+
+#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */
+#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */
+
+/* Debug Core Register Selector Register Definitions */
+#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */
+#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */
+
+#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */
+#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */
+
+/* Debug Exception and Monitor Control Register Definitions */
+#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */
+#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */
+
+#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */
+#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */
+
+#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */
+#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */
+
+#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */
+#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */
+
+#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */
+#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */
+
+#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */
+#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */
+
+#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */
+#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */
+
+#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */
+#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */
+
+#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */
+#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */
+
+#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */
+#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */
+
+#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */
+#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */
+
+#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */
+#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */
+
+#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */
+#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */
+
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */
+#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
+#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */
+#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */
+#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */
+#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */
+#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */
+#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */
+#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
+ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
+#endif
+
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Debug Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+ #define NVIC_GetActive __NVIC_GetActive
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* The following EXC_RETURN values are saved the LR on exception entry */
+#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */
+#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */
+#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */
+
+
+/**
+ \brief Set Priority Grouping
+ \details Sets the priority grouping field using the required unlock sequence.
+ The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
+ Only values from 0..7 are used.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Priority grouping field.
+ */
+__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
+{
+ uint32_t reg_value;
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+
+ reg_value = SCB->AIRCR; /* read old register configuration */
+ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
+ reg_value = (reg_value |
+ ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */
+ SCB->AIRCR = reg_value;
+}
+
+
+/**
+ \brief Get Priority Grouping
+ \details Reads the priority grouping field from the NVIC Interrupt Controller.
+ \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void)
+{
+ return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
+}
+
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt
+ \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+ else
+ {
+ SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
+ SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+/* ########################## MPU functions #################################### */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+
+#include "mpu_armv7.h"
+
+#endif
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ return 0U; /* No FPU */
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+/* ##################################### Debug In/Output function ########################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_core_DebugFunctions ITM Functions
+ \brief Functions that access the ITM debug interface.
+ @{
+ */
+
+extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */
+#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
+
+
+/**
+ \brief ITM Send Character
+ \details Transmits a character via the ITM channel 0, and
+ \li Just returns when no debugger is connected that has booked the output.
+ \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted.
+ \param [in] ch Character to transmit.
+ \returns Character to transmit.
+ */
+__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch)
+{
+ if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */
+ ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */
+ {
+ while (ITM->PORT[0U].u32 == 0UL)
+ {
+ __NOP();
+ }
+ ITM->PORT[0U].u8 = (uint8_t)ch;
+ }
+ return (ch);
+}
+
+
+/**
+ \brief ITM Receive Character
+ \details Inputs a character via the external variable \ref ITM_RxBuffer.
+ \return Received character.
+ \return -1 No character pending.
+ */
+__STATIC_INLINE int32_t ITM_ReceiveChar (void)
+{
+ int32_t ch = -1; /* no character available */
+
+ if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY)
+ {
+ ch = ITM_RxBuffer;
+ ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */
+ }
+
+ return (ch);
+}
+
+
+/**
+ \brief ITM Check Character
+ \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer.
+ \return 0 No character available.
+ \return 1 Character available.
+ */
+__STATIC_INLINE int32_t ITM_CheckChar (void)
+{
+
+ if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY)
+ {
+ return (0); /* no character available */
+ }
+ else
+ {
+ return (1); /* character available */
+ }
+}
+
+/*@} end of CMSIS_core_DebugFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM3_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm33.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm33.h
new file mode 100644
index 0000000..6cd2db7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm33.h
@@ -0,0 +1,3002 @@
+/**************************************************************************//**
+ * @file core_cm33.h
+ * @brief CMSIS Cortex-M33 Core Peripheral Access Layer Header File
+ * @version V5.0.9
+ * @date 06. July 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_CM33_H_GENERIC
+#define __CORE_CM33_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup Cortex_M33
+ @{
+ */
+
+#include "cmsis_version.h"
+
+/* CMSIS CM33 definitions */
+#define __CM33_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __CM33_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __CM33_CMSIS_VERSION ((__CM33_CMSIS_VERSION_MAIN << 16U) | \
+ __CM33_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_M (33U) /*!< Cortex-M Core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions.
+*/
+#if defined ( __CC_ARM )
+ #if defined (__TARGET_FPU_VFP)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U)
+ #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined (__ARM_PCS_VFP)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U)
+ #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U)
+ #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined (__ARMVFP__)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U)
+ #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined (__TI_VFP_SUPPORT__)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined (__FPU_VFP__)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM33_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_CM33_H_DEPENDANT
+#define __CORE_CM33_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __CM33_REV
+ #define __CM33_REV 0x0000U
+ #warning "__CM33_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __FPU_PRESENT
+ #define __FPU_PRESENT 0U
+ #warning "__FPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MPU_PRESENT
+ #define __MPU_PRESENT 0U
+ #warning "__MPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __SAUREGION_PRESENT
+ #define __SAUREGION_PRESENT 0U
+ #warning "__SAUREGION_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __DSP_PRESENT
+ #define __DSP_PRESENT 0U
+ #warning "__DSP_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 3U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group Cortex_M33 */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ - Core Debug Register
+ - Core MPU Register
+ - Core SAU Register
+ - Core FPU Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */
+ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
+ uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+#define APSR_Q_Pos 27U /*!< APSR: Q Position */
+#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */
+
+#define APSR_GE_Pos 16U /*!< APSR: GE Position */
+#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */
+ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
+ uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
+ uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */
+#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */
+
+#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */
+#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */
+#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */
+ uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */
+ uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */
+ uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */
+#define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */
+
+#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */
+#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */
+
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */
+#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[16U];
+ __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[16U];
+ __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[16U];
+ __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[16U];
+ __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
+ uint32_t RESERVED4[16U];
+ __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */
+ uint32_t RESERVED5[16U];
+ __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
+ uint32_t RESERVED6[580U];
+ __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
+} NVIC_Type;
+
+/* Software Triggered Interrupt Register Definitions */
+#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */
+#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+ __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */
+ __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */
+ __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */
+ __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */
+ __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */
+ __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */
+ __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */
+ __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */
+ __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */
+ __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */
+ __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */
+ __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */
+ __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */
+ __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */
+ __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */
+ __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */
+ __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */
+ uint32_t RESERVED3[92U];
+ __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */
+ uint32_t RESERVED4[15U];
+ __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */
+ __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */
+ __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */
+ uint32_t RESERVED5[1U];
+ __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */
+ uint32_t RESERVED6[1U];
+ __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */
+ __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */
+ __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */
+ __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */
+ __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */
+ __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */
+ __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */
+ __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */
+ uint32_t RESERVED7[6U];
+ __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */
+ __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */
+ __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */
+ __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */
+ __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */
+ uint32_t RESERVED8[1U];
+ __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */
+#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */
+
+#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */
+#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */
+
+#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */
+#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */
+#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */
+#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+/* SCB Vector Table Offset Register Definitions */
+#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */
+#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */
+
+#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */
+#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */
+
+#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */
+#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */
+
+#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */
+#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */
+#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */
+#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */
+
+#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */
+#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */
+
+#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */
+#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */
+
+#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */
+#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */
+
+#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */
+#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */
+
+#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */
+#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */
+#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */
+#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */
+
+#define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */
+#define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */
+
+#define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */
+#define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */
+
+#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */
+#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */
+
+#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */
+#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */
+
+#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */
+#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */
+
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */
+#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */
+
+#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */
+#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */
+
+#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */
+#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */
+
+#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */
+#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */
+
+#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */
+#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */
+
+#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */
+#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */
+
+#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */
+#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */
+
+#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */
+#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */
+
+#define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */
+#define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */
+
+#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */
+#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */
+
+#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */
+#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */
+
+#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */
+#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */
+
+#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */
+#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */
+
+/* SCB Configurable Fault Status Register Definitions */
+#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */
+#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */
+
+#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */
+#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */
+
+#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */
+#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */
+
+/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */
+#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */
+
+#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */
+#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */
+
+#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */
+#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */
+
+#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */
+#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */
+
+#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */
+#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */
+
+#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */
+#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */
+
+/* BusFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */
+#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */
+
+#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */
+#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */
+
+#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */
+#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */
+
+#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */
+#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */
+
+#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */
+#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */
+
+#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */
+#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */
+
+#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */
+#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */
+
+/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */
+#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */
+
+#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */
+#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */
+
+#define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */
+#define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */
+
+#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */
+#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */
+
+#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */
+#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */
+
+#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */
+#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */
+
+#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */
+#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */
+
+/* SCB Hard Fault Status Register Definitions */
+#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */
+#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */
+
+#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */
+#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */
+
+#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */
+#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */
+
+/* SCB Debug Fault Status Register Definitions */
+#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */
+#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */
+
+#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */
+#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */
+
+#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */
+#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */
+
+#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */
+#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */
+
+#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */
+#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */
+
+/* SCB Non-Secure Access Control Register Definitions */
+#define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */
+#define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */
+
+#define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */
+#define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */
+
+#define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */
+#define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */
+
+/* SCB Cache Level ID Register Definitions */
+#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */
+#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */
+
+#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */
+#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */
+
+/* SCB Cache Type Register Definitions */
+#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */
+#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */
+
+#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */
+#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */
+
+#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */
+#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */
+
+#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */
+#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */
+
+#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */
+#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */
+
+/* SCB Cache Size ID Register Definitions */
+#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */
+#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */
+
+#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */
+#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */
+
+#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */
+#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */
+
+#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */
+#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */
+
+#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */
+#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */
+
+#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */
+#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */
+
+#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */
+#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */
+
+/* SCB Cache Size Selection Register Definitions */
+#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */
+#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */
+
+#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */
+#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */
+
+/* SCB Software Triggered Interrupt Register Definitions */
+#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */
+#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */
+
+/* SCB D-Cache Invalidate by Set-way Register Definitions */
+#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */
+#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */
+
+#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */
+#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */
+
+/* SCB D-Cache Clean by Set-way Register Definitions */
+#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */
+#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */
+
+#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */
+#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */
+
+/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */
+#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */
+#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */
+
+#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */
+#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */
+
+/* Instruction Tightly-Coupled Memory Control Register Definitions */
+#define SCB_ITCMCR_SZ_Pos 3U /*!< SCB ITCMCR: SZ Position */
+#define SCB_ITCMCR_SZ_Msk (0xFUL << SCB_ITCMCR_SZ_Pos) /*!< SCB ITCMCR: SZ Mask */
+
+#define SCB_ITCMCR_RETEN_Pos 2U /*!< SCB ITCMCR: RETEN Position */
+#define SCB_ITCMCR_RETEN_Msk (1UL << SCB_ITCMCR_RETEN_Pos) /*!< SCB ITCMCR: RETEN Mask */
+
+#define SCB_ITCMCR_RMW_Pos 1U /*!< SCB ITCMCR: RMW Position */
+#define SCB_ITCMCR_RMW_Msk (1UL << SCB_ITCMCR_RMW_Pos) /*!< SCB ITCMCR: RMW Mask */
+
+#define SCB_ITCMCR_EN_Pos 0U /*!< SCB ITCMCR: EN Position */
+#define SCB_ITCMCR_EN_Msk (1UL /*<< SCB_ITCMCR_EN_Pos*/) /*!< SCB ITCMCR: EN Mask */
+
+/* Data Tightly-Coupled Memory Control Register Definitions */
+#define SCB_DTCMCR_SZ_Pos 3U /*!< SCB DTCMCR: SZ Position */
+#define SCB_DTCMCR_SZ_Msk (0xFUL << SCB_DTCMCR_SZ_Pos) /*!< SCB DTCMCR: SZ Mask */
+
+#define SCB_DTCMCR_RETEN_Pos 2U /*!< SCB DTCMCR: RETEN Position */
+#define SCB_DTCMCR_RETEN_Msk (1UL << SCB_DTCMCR_RETEN_Pos) /*!< SCB DTCMCR: RETEN Mask */
+
+#define SCB_DTCMCR_RMW_Pos 1U /*!< SCB DTCMCR: RMW Position */
+#define SCB_DTCMCR_RMW_Msk (1UL << SCB_DTCMCR_RMW_Pos) /*!< SCB DTCMCR: RMW Mask */
+
+#define SCB_DTCMCR_EN_Pos 0U /*!< SCB DTCMCR: EN Position */
+#define SCB_DTCMCR_EN_Msk (1UL /*<< SCB_DTCMCR_EN_Pos*/) /*!< SCB DTCMCR: EN Mask */
+
+/* AHBP Control Register Definitions */
+#define SCB_AHBPCR_SZ_Pos 1U /*!< SCB AHBPCR: SZ Position */
+#define SCB_AHBPCR_SZ_Msk (7UL << SCB_AHBPCR_SZ_Pos) /*!< SCB AHBPCR: SZ Mask */
+
+#define SCB_AHBPCR_EN_Pos 0U /*!< SCB AHBPCR: EN Position */
+#define SCB_AHBPCR_EN_Msk (1UL /*<< SCB_AHBPCR_EN_Pos*/) /*!< SCB AHBPCR: EN Mask */
+
+/* L1 Cache Control Register Definitions */
+#define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */
+#define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */
+
+#define SCB_CACR_ECCEN_Pos 1U /*!< SCB CACR: ECCEN Position */
+#define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< SCB CACR: ECCEN Mask */
+
+#define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */
+#define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */
+
+/* AHBS Control Register Definitions */
+#define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */
+#define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBPCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */
+
+#define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */
+#define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBPCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */
+
+#define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/
+#define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBPCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */
+
+/* Auxiliary Bus Fault Status Register Definitions */
+#define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/
+#define SCB_ABFSR_AXIMTYPE_Msk (3UL << SCB_ABFSR_AXIMTYPE_Pos) /*!< SCB ABFSR: AXIMTYPE Mask */
+
+#define SCB_ABFSR_EPPB_Pos 4U /*!< SCB ABFSR: EPPB Position*/
+#define SCB_ABFSR_EPPB_Msk (1UL << SCB_ABFSR_EPPB_Pos) /*!< SCB ABFSR: EPPB Mask */
+
+#define SCB_ABFSR_AXIM_Pos 3U /*!< SCB ABFSR: AXIM Position*/
+#define SCB_ABFSR_AXIM_Msk (1UL << SCB_ABFSR_AXIM_Pos) /*!< SCB ABFSR: AXIM Mask */
+
+#define SCB_ABFSR_AHBP_Pos 2U /*!< SCB ABFSR: AHBP Position*/
+#define SCB_ABFSR_AHBP_Msk (1UL << SCB_ABFSR_AHBP_Pos) /*!< SCB ABFSR: AHBP Mask */
+
+#define SCB_ABFSR_DTCM_Pos 1U /*!< SCB ABFSR: DTCM Position*/
+#define SCB_ABFSR_DTCM_Msk (1UL << SCB_ABFSR_DTCM_Pos) /*!< SCB ABFSR: DTCM Mask */
+
+#define SCB_ABFSR_ITCM_Pos 0U /*!< SCB ABFSR: ITCM Position*/
+#define SCB_ABFSR_ITCM_Msk (1UL /*<< SCB_ABFSR_ITCM_Pos*/) /*!< SCB ABFSR: ITCM Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB)
+ \brief Type definitions for the System Control and ID Register not in the SCB
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control and ID Register not in the SCB.
+ */
+typedef struct
+{
+ uint32_t RESERVED0[1U];
+ __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */
+ __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */
+ __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */
+} SCnSCB_Type;
+
+/* Interrupt Controller Type Register Definitions */
+#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */
+#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_SCnotSCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM)
+ \brief Type definitions for the Instrumentation Trace Macrocell (ITM)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM).
+ */
+typedef struct
+{
+ __OM union
+ {
+ __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */
+ __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */
+ __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */
+ } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */
+ uint32_t RESERVED0[864U];
+ __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */
+ uint32_t RESERVED1[15U];
+ __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */
+ uint32_t RESERVED2[15U];
+ __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */
+ uint32_t RESERVED3[29U];
+ __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */
+ __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */
+ __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */
+ uint32_t RESERVED4[43U];
+ __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */
+ uint32_t RESERVED5[1U];
+ __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */
+ uint32_t RESERVED6[4U];
+ __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */
+ __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */
+ __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */
+ __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */
+ __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */
+ __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */
+ __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */
+ __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */
+ __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */
+ __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */
+ __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */
+ __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */
+} ITM_Type;
+
+/* ITM Stimulus Port Register Definitions */
+#define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */
+#define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */
+
+#define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */
+#define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */
+
+/* ITM Trace Privilege Register Definitions */
+#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */
+#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */
+
+/* ITM Trace Control Register Definitions */
+#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */
+#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */
+
+#define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */
+#define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */
+
+#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */
+#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */
+
+#define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */
+#define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */
+
+#define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */
+#define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */
+
+#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */
+#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */
+
+#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */
+#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */
+
+#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */
+#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */
+
+#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */
+#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */
+
+#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */
+#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */
+
+/* ITM Integration Write Register Definitions */
+#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */
+#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */
+
+/* ITM Integration Read Register Definitions */
+#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */
+#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */
+
+/* ITM Integration Mode Control Register Definitions */
+#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */
+#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */
+
+/* ITM Lock Status Register Definitions */
+#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */
+#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */
+
+#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */
+#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */
+
+#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */
+#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */
+
+/*@}*/ /* end of group CMSIS_ITM */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT)
+ \brief Type definitions for the Data Watchpoint and Trace (DWT)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Data Watchpoint and Trace Register (DWT).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */
+ __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */
+ __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */
+ __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */
+ __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */
+ __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */
+ __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */
+ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */
+ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */
+ uint32_t RESERVED1[1U];
+ __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */
+ uint32_t RESERVED2[1U];
+ __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */
+ uint32_t RESERVED3[1U];
+ __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */
+ uint32_t RESERVED5[1U];
+ __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */
+ uint32_t RESERVED6[1U];
+ __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */
+ uint32_t RESERVED7[1U];
+ __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */
+ uint32_t RESERVED8[1U];
+ __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */
+ uint32_t RESERVED9[1U];
+ __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */
+ uint32_t RESERVED10[1U];
+ __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */
+ uint32_t RESERVED11[1U];
+ __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */
+ uint32_t RESERVED12[1U];
+ __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */
+ uint32_t RESERVED13[1U];
+ __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */
+ uint32_t RESERVED14[1U];
+ __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */
+ uint32_t RESERVED15[1U];
+ __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */
+ uint32_t RESERVED16[1U];
+ __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */
+ uint32_t RESERVED17[1U];
+ __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */
+ uint32_t RESERVED18[1U];
+ __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */
+ uint32_t RESERVED19[1U];
+ __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */
+ uint32_t RESERVED20[1U];
+ __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */
+ uint32_t RESERVED21[1U];
+ __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */
+ uint32_t RESERVED22[1U];
+ __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */
+ uint32_t RESERVED23[1U];
+ __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */
+ uint32_t RESERVED24[1U];
+ __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */
+ uint32_t RESERVED25[1U];
+ __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */
+ uint32_t RESERVED26[1U];
+ __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */
+ uint32_t RESERVED27[1U];
+ __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */
+ uint32_t RESERVED28[1U];
+ __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */
+ uint32_t RESERVED29[1U];
+ __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */
+ uint32_t RESERVED30[1U];
+ __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */
+ uint32_t RESERVED31[1U];
+ __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */
+ uint32_t RESERVED32[934U];
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */
+ uint32_t RESERVED33[1U];
+ __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */
+} DWT_Type;
+
+/* DWT Control Register Definitions */
+#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */
+#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */
+
+#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */
+#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */
+
+#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */
+#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */
+
+#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */
+#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */
+
+#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */
+#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */
+
+#define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */
+#define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */
+
+#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */
+#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */
+
+#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */
+#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */
+
+#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */
+#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */
+
+#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */
+#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */
+
+#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */
+#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */
+
+#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */
+#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */
+
+#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */
+#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */
+
+#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */
+#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */
+
+#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */
+#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */
+
+#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */
+#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */
+
+#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */
+#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */
+
+#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */
+#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */
+
+#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */
+#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */
+
+/* DWT CPI Count Register Definitions */
+#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */
+#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */
+
+/* DWT Exception Overhead Count Register Definitions */
+#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */
+#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */
+
+/* DWT Sleep Count Register Definitions */
+#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */
+#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */
+
+/* DWT LSU Count Register Definitions */
+#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */
+#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */
+
+/* DWT Folded-instruction Count Register Definitions */
+#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */
+#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */
+
+/* DWT Comparator Function Register Definitions */
+#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */
+#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */
+
+#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */
+#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */
+
+#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */
+#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */
+
+#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */
+#define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */
+
+#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */
+#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */
+
+/*@}*/ /* end of group CMSIS_DWT */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_TPI Trace Port Interface (TPI)
+ \brief Type definitions for the Trace Port Interface (TPI)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Trace Port Interface Register (TPI).
+ */
+typedef struct
+{
+ __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */
+ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */
+ uint32_t RESERVED0[2U];
+ __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */
+ uint32_t RESERVED1[55U];
+ __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */
+ uint32_t RESERVED2[131U];
+ __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */
+ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */
+ __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */
+ uint32_t RESERVED3[759U];
+ __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */
+ __IM uint32_t ITFTTD0; /*!< Offset: 0xEEC (R/ ) Integration Test FIFO Test Data 0 Register */
+ __IOM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/W) Integration Test ATB Control Register 2 */
+ uint32_t RESERVED4[1U];
+ __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) Integration Test ATB Control Register 0 */
+ __IM uint32_t ITFTTD1; /*!< Offset: 0xEFC (R/ ) Integration Test FIFO Test Data 1 Register */
+ __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */
+ uint32_t RESERVED5[39U];
+ __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */
+ __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */
+ uint32_t RESERVED7[8U];
+ __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) Device Configuration Register */
+ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Identifier Register */
+} TPI_Type;
+
+/* TPI Asynchronous Clock Prescaler Register Definitions */
+#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */
+#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */
+
+/* TPI Selected Pin Protocol Register Definitions */
+#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */
+#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */
+
+/* TPI Formatter and Flush Status Register Definitions */
+#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */
+#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */
+
+#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */
+#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */
+
+#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */
+#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */
+
+#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */
+#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */
+
+/* TPI Formatter and Flush Control Register Definitions */
+#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */
+#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */
+
+#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */
+#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */
+
+#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */
+#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */
+
+/* TPI TRIGGER Register Definitions */
+#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */
+#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */
+
+/* TPI Integration Test FIFO Test Data 0 Register Definitions */
+#define TPI_ITFTTD0_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD0: ATB Interface 2 ATVALIDPosition */
+#define TPI_ITFTTD0_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 2 ATVALID Mask */
+
+#define TPI_ITFTTD0_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD0: ATB Interface 2 byte count Position */
+#define TPI_ITFTTD0_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 2 byte count Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Position */
+#define TPI_ITFTTD0_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD0: ATB Interface 1 byte count Position */
+#define TPI_ITFTTD0_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 1 byte countt Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_data2_Pos 16U /*!< TPI ITFTTD0: ATB Interface 1 data2 Position */
+#define TPI_ITFTTD0_ATB_IF1_data2_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data2 Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_data1_Pos 8U /*!< TPI ITFTTD0: ATB Interface 1 data1 Position */
+#define TPI_ITFTTD0_ATB_IF1_data1_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data1 Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_data0_Pos 0U /*!< TPI ITFTTD0: ATB Interface 1 data0 Position */
+#define TPI_ITFTTD0_ATB_IF1_data0_Msk (0xFFUL /*<< TPI_ITFTTD0_ATB_IF1_data0_Pos*/) /*!< TPI ITFTTD0: ATB Interface 1 data0 Mask */
+
+/* TPI Integration Test ATB Control Register 2 Register Definitions */
+#define TPI_ITATBCTR2_AFVALID2S_Pos 1U /*!< TPI ITATBCTR2: AFVALID2S Position */
+#define TPI_ITATBCTR2_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID2S_Pos) /*!< TPI ITATBCTR2: AFVALID2SS Mask */
+
+#define TPI_ITATBCTR2_AFVALID1S_Pos 1U /*!< TPI ITATBCTR2: AFVALID1S Position */
+#define TPI_ITATBCTR2_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID1S_Pos) /*!< TPI ITATBCTR2: AFVALID1SS Mask */
+
+#define TPI_ITATBCTR2_ATREADY2S_Pos 0U /*!< TPI ITATBCTR2: ATREADY2S Position */
+#define TPI_ITATBCTR2_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2S_Pos*/) /*!< TPI ITATBCTR2: ATREADY2S Mask */
+
+#define TPI_ITATBCTR2_ATREADY1S_Pos 0U /*!< TPI ITATBCTR2: ATREADY1S Position */
+#define TPI_ITATBCTR2_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1S_Pos*/) /*!< TPI ITATBCTR2: ATREADY1S Mask */
+
+/* TPI Integration Test FIFO Test Data 1 Register Definitions */
+#define TPI_ITFTTD1_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Position */
+#define TPI_ITFTTD1_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD1: ATB Interface 2 byte count Position */
+#define TPI_ITFTTD1_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 2 byte count Mask */
+
+#define TPI_ITFTTD1_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Position */
+#define TPI_ITFTTD1_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Mask */
+
+#define TPI_ITFTTD1_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD1: ATB Interface 1 byte count Position */
+#define TPI_ITFTTD1_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 1 byte countt Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_data2_Pos 16U /*!< TPI ITFTTD1: ATB Interface 2 data2 Position */
+#define TPI_ITFTTD1_ATB_IF2_data2_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data2 Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_data1_Pos 8U /*!< TPI ITFTTD1: ATB Interface 2 data1 Position */
+#define TPI_ITFTTD1_ATB_IF2_data1_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data1 Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_data0_Pos 0U /*!< TPI ITFTTD1: ATB Interface 2 data0 Position */
+#define TPI_ITFTTD1_ATB_IF2_data0_Msk (0xFFUL /*<< TPI_ITFTTD1_ATB_IF2_data0_Pos*/) /*!< TPI ITFTTD1: ATB Interface 2 data0 Mask */
+
+/* TPI Integration Test ATB Control Register 0 Definitions */
+#define TPI_ITATBCTR0_AFVALID2S_Pos 1U /*!< TPI ITATBCTR0: AFVALID2S Position */
+#define TPI_ITATBCTR0_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID2S_Pos) /*!< TPI ITATBCTR0: AFVALID2SS Mask */
+
+#define TPI_ITATBCTR0_AFVALID1S_Pos 1U /*!< TPI ITATBCTR0: AFVALID1S Position */
+#define TPI_ITATBCTR0_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID1S_Pos) /*!< TPI ITATBCTR0: AFVALID1SS Mask */
+
+#define TPI_ITATBCTR0_ATREADY2S_Pos 0U /*!< TPI ITATBCTR0: ATREADY2S Position */
+#define TPI_ITATBCTR0_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2S_Pos*/) /*!< TPI ITATBCTR0: ATREADY2S Mask */
+
+#define TPI_ITATBCTR0_ATREADY1S_Pos 0U /*!< TPI ITATBCTR0: ATREADY1S Position */
+#define TPI_ITATBCTR0_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1S_Pos*/) /*!< TPI ITATBCTR0: ATREADY1S Mask */
+
+/* TPI Integration Mode Control Register Definitions */
+#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */
+#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */
+
+/* TPI DEVID Register Definitions */
+#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */
+#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */
+
+#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */
+#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */
+
+#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */
+#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */
+
+#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFOSZ Position */
+#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFOSZ Mask */
+
+#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */
+#define TPI_DEVID_NrTraceInput_Msk (0x3FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */
+
+/* TPI DEVTYPE Register Definitions */
+#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */
+
+#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
+
+/*@}*/ /* end of group CMSIS_TPI */
+
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_MPU Memory Protection Unit (MPU)
+ \brief Type definitions for the Memory Protection Unit (MPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+ __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
+ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */
+ __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */
+ __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */
+ __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */
+ __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */
+ __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */
+ __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */
+ uint32_t RESERVED0[1];
+ union {
+ __IOM uint32_t MAIR[2];
+ struct {
+ __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */
+ __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */
+ };
+ };
+} MPU_Type;
+
+#define MPU_TYPE_RALIASES 4U
+
+/* MPU Type Register Definitions */
+#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register Definitions */
+#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register Definitions */
+#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register Definitions */
+#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */
+#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */
+
+#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */
+#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */
+
+#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */
+#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */
+
+#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */
+#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */
+
+/* MPU Region Limit Address Register Definitions */
+#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */
+#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */
+
+#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */
+#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */
+
+#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */
+#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */
+
+/* MPU Memory Attribute Indirection Register 0 Definitions */
+#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */
+#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */
+
+#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */
+#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */
+
+#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */
+#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */
+
+#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */
+#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */
+
+/* MPU Memory Attribute Indirection Register 1 Definitions */
+#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */
+#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */
+
+#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */
+#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */
+
+#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */
+#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */
+
+#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */
+#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SAU Security Attribution Unit (SAU)
+ \brief Type definitions for the Security Attribution Unit (SAU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Security Attribution Unit (SAU).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */
+ __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */
+#else
+ uint32_t RESERVED0[3];
+#endif
+ __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */
+ __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */
+} SAU_Type;
+
+/* SAU Control Register Definitions */
+#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */
+#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */
+
+#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */
+#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */
+
+/* SAU Type Register Definitions */
+#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */
+#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */
+
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+/* SAU Region Number Register Definitions */
+#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */
+#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */
+
+/* SAU Region Base Address Register Definitions */
+#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */
+#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */
+
+/* SAU Region Limit Address Register Definitions */
+#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */
+#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */
+
+#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */
+#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */
+
+#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */
+#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */
+
+#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */
+
+/* Secure Fault Status Register Definitions */
+#define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */
+#define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */
+
+#define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */
+#define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */
+
+#define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */
+#define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */
+
+#define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */
+#define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */
+
+#define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */
+#define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */
+
+#define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */
+#define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */
+
+#define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */
+#define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */
+
+#define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */
+#define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */
+
+/*@} end of group CMSIS_SAU */
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_FPU Floating Point Unit (FPU)
+ \brief Type definitions for the Floating Point Unit (FPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Floating Point Unit (FPU).
+ */
+typedef struct
+{
+ uint32_t RESERVED0[1U];
+ __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */
+ __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */
+ __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */
+ __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */
+ __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */
+} FPU_Type;
+
+/* Floating-Point Context Control Register Definitions */
+#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */
+#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */
+
+#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */
+#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */
+
+#define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */
+#define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */
+
+#define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */
+#define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */
+
+#define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */
+#define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */
+
+#define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */
+#define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */
+
+#define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */
+#define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */
+
+#define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */
+#define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */
+
+#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */
+#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */
+
+#define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */
+#define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */
+
+#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */
+#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */
+
+#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */
+#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */
+
+#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */
+#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */
+
+#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */
+#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */
+
+#define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */
+#define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */
+
+#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */
+#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */
+
+#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */
+#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */
+
+/* Floating-Point Context Address Register Definitions */
+#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */
+#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */
+
+/* Floating-Point Default Status Control Register Definitions */
+#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */
+#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */
+
+#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */
+#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */
+
+#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */
+#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */
+
+#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */
+#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */
+
+/* Media and FP Feature Register 0 Definitions */
+#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */
+#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */
+
+#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */
+#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */
+
+#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */
+#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */
+
+#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */
+#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */
+
+#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */
+#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */
+
+#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */
+#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */
+
+#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */
+#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */
+
+#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */
+#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */
+
+/* Media and FP Feature Register 1 Definitions */
+#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */
+#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */
+
+#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */
+#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */
+
+#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */
+#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */
+
+#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */
+#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */
+
+/*@} end of group CMSIS_FPU */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Type definitions for the Core Debug Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Core Debug Register (CoreDebug).
+ */
+typedef struct
+{
+ __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */
+ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */
+ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */
+ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */
+ __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */
+} CoreDebug_Type;
+
+/* Debug Halting Control and Status Register Definitions */
+#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */
+#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */
+
+#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */
+#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */
+
+#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */
+#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */
+
+#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */
+#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */
+
+#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */
+#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */
+
+#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */
+#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */
+
+#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */
+#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */
+
+#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */
+#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */
+
+#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */
+#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */
+
+#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */
+#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */
+
+#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */
+#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */
+
+#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */
+#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */
+
+#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */
+#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */
+
+/* Debug Core Register Selector Register Definitions */
+#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */
+#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */
+
+#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */
+#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */
+
+/* Debug Exception and Monitor Control Register Definitions */
+#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */
+#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */
+
+#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */
+#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */
+
+#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */
+#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */
+
+#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */
+#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */
+
+#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */
+#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */
+
+#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */
+#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */
+
+#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */
+#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */
+
+#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */
+#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */
+
+#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */
+#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */
+
+#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */
+#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */
+
+#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */
+#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */
+
+#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */
+#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */
+
+#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */
+#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */
+
+/* Debug Authentication Control Register Definitions */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */
+
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */
+
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */
+
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */
+
+/* Debug Security Control and Status Register Definitions */
+#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */
+#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */
+
+#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */
+#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */
+
+#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */
+#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */
+
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */
+ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
+ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */
+ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */
+ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+ #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */
+ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+ #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */
+ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */
+ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */
+ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
+ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
+ #endif
+
+ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */
+ #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */
+ #endif
+
+ #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */
+ #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */
+ #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */
+ #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */
+ #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */
+ #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */
+
+ #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */
+ #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */
+ #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */
+ #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */
+ #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */
+ #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */
+ #endif
+
+ #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */
+ #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Debug Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+ #define NVIC_GetActive __NVIC_GetActive
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* Special LR values for Secure/Non-Secure call handling and exception handling */
+
+/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */
+#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */
+
+/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */
+#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */
+#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */
+#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */
+#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */
+#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */
+#define EXC_RETURN_SPSEL (0x00000002UL) /* bit [1] stack pointer used to restore context: 0=MSP 1=PSP */
+#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */
+
+/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */
+#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */
+#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */
+#else
+#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */
+#endif
+
+
+/**
+ \brief Set Priority Grouping
+ \details Sets the priority grouping field using the required unlock sequence.
+ The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
+ Only values from 0..7 are used.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Priority grouping field.
+ */
+__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
+{
+ uint32_t reg_value;
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+
+ reg_value = SCB->AIRCR; /* read old register configuration */
+ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
+ reg_value = (reg_value |
+ ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (PriorityGroupTmp << 8U) ); /* Insert write key and priority group */
+ SCB->AIRCR = reg_value;
+}
+
+
+/**
+ \brief Get Priority Grouping
+ \details Reads the priority grouping field from the NVIC Interrupt Controller.
+ \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void)
+{
+ return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
+}
+
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt
+ \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Get Interrupt Target State
+ \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ \return 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Target State
+ \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Clear Interrupt Target State
+ \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+ else
+ {
+ SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
+ SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Set Priority Grouping (non-secure)
+ \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence.
+ The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
+ Only values from 0..7 are used.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Priority grouping field.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup)
+{
+ uint32_t reg_value;
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+
+ reg_value = SCB_NS->AIRCR; /* read old register configuration */
+ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
+ reg_value = (reg_value |
+ ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */
+ SCB_NS->AIRCR = reg_value;
+}
+
+
+/**
+ \brief Get Priority Grouping (non-secure)
+ \details Reads the priority grouping field from the non-secure NVIC when in secure state.
+ \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void)
+{
+ return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
+}
+
+
+/**
+ \brief Enable Interrupt (non-secure)
+ \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status (non-secure)
+ \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt (non-secure)
+ \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt (non-secure)
+ \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt (non-secure)
+ \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt (non-secure)
+ \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt (non-secure)
+ \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority (non-secure)
+ \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every non-secure processor exception.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+ else
+ {
+ SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority (non-secure)
+ \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+/* ########################## MPU functions #################################### */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+
+#include "mpu_armv8.h"
+
+#endif
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ uint32_t mvfr0;
+
+ mvfr0 = FPU->MVFR0;
+ if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U)
+ {
+ return 2U; /* Double + Single precision FPU */
+ }
+ else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U)
+ {
+ return 1U; /* Single precision FPU */
+ }
+ else
+ {
+ return 0U; /* No FPU */
+ }
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ########################## SAU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SAUFunctions SAU Functions
+ \brief Functions that configure the SAU.
+ @{
+ */
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+
+/**
+ \brief Enable SAU
+ \details Enables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Enable(void)
+{
+ SAU->CTRL |= (SAU_CTRL_ENABLE_Msk);
+}
+
+
+
+/**
+ \brief Disable SAU
+ \details Disables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Disable(void)
+{
+ SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk);
+}
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_SAUFunctions */
+
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief System Tick Configuration (non-secure)
+ \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function TZ_SysTick_Config_NS is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+
+ */
+__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+/* ##################################### Debug In/Output function ########################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_core_DebugFunctions ITM Functions
+ \brief Functions that access the ITM debug interface.
+ @{
+ */
+
+extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */
+#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
+
+
+/**
+ \brief ITM Send Character
+ \details Transmits a character via the ITM channel 0, and
+ \li Just returns when no debugger is connected that has booked the output.
+ \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted.
+ \param [in] ch Character to transmit.
+ \returns Character to transmit.
+ */
+__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch)
+{
+ if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */
+ ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */
+ {
+ while (ITM->PORT[0U].u32 == 0UL)
+ {
+ __NOP();
+ }
+ ITM->PORT[0U].u8 = (uint8_t)ch;
+ }
+ return (ch);
+}
+
+
+/**
+ \brief ITM Receive Character
+ \details Inputs a character via the external variable \ref ITM_RxBuffer.
+ \return Received character.
+ \return -1 No character pending.
+ */
+__STATIC_INLINE int32_t ITM_ReceiveChar (void)
+{
+ int32_t ch = -1; /* no character available */
+
+ if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY)
+ {
+ ch = ITM_RxBuffer;
+ ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */
+ }
+
+ return (ch);
+}
+
+
+/**
+ \brief ITM Check Character
+ \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer.
+ \return 0 No character available.
+ \return 1 Character available.
+ */
+__STATIC_INLINE int32_t ITM_CheckChar (void)
+{
+
+ if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY)
+ {
+ return (0); /* no character available */
+ }
+ else
+ {
+ return (1); /* character available */
+ }
+}
+
+/*@} end of CMSIS_core_DebugFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM33_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm4.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm4.h
new file mode 100644
index 0000000..7d56873
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm4.h
@@ -0,0 +1,2129 @@
+/**************************************************************************//**
+ * @file core_cm4.h
+ * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File
+ * @version V5.0.8
+ * @date 04. June 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_CM4_H_GENERIC
+#define __CORE_CM4_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup Cortex_M4
+ @{
+ */
+
+#include "cmsis_version.h"
+
+/* CMSIS CM4 definitions */
+#define __CM4_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __CM4_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16U) | \
+ __CM4_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_M (4U) /*!< Cortex-M Core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions.
+*/
+#if defined ( __CC_ARM )
+ #if defined __TARGET_FPU_VFP
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_PCS_VFP
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined __ARMVFP__
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined __TI_VFP_SUPPORT__
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined __FPU_VFP__
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM4_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_CM4_H_DEPENDANT
+#define __CORE_CM4_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __CM4_REV
+ #define __CM4_REV 0x0000U
+ #warning "__CM4_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __FPU_PRESENT
+ #define __FPU_PRESENT 0U
+ #warning "__FPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MPU_PRESENT
+ #define __MPU_PRESENT 0U
+ #warning "__MPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 3U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group Cortex_M4 */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ - Core Debug Register
+ - Core MPU Register
+ - Core FPU Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */
+ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
+ uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+#define APSR_Q_Pos 27U /*!< APSR: Q Position */
+#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */
+
+#define APSR_GE_Pos 16U /*!< APSR: GE Position */
+#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:1; /*!< bit: 9 Reserved */
+ uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */
+ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
+ uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit */
+ uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */
+#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */
+
+#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */
+#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */
+#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */
+
+#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */
+#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
+ uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */
+ uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */
+#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */
+
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */
+#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[24U];
+ __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[24U];
+ __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[24U];
+ __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[24U];
+ __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
+ uint32_t RESERVED4[56U];
+ __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
+ uint32_t RESERVED5[644U];
+ __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
+} NVIC_Type;
+
+/* Software Triggered Interrupt Register Definitions */
+#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */
+#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+ __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */
+ __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */
+ __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */
+ __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */
+ __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */
+ __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */
+ __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */
+ __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */
+ __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */
+ __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */
+ __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */
+ uint32_t RESERVED0[5U];
+ __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */
+#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */
+#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+/* SCB Vector Table Offset Register Definitions */
+#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */
+#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */
+#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */
+#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
+
+#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */
+#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */
+
+#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */
+#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */
+#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */
+
+#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */
+#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */
+#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */
+
+#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */
+#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */
+
+#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */
+#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */
+
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */
+#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */
+
+#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */
+#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */
+
+#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */
+#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */
+
+#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */
+#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */
+
+#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */
+#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */
+
+#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */
+#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */
+
+#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */
+#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */
+
+#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */
+#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */
+
+#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */
+#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */
+
+#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */
+#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */
+
+/* SCB Configurable Fault Status Register Definitions */
+#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */
+#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */
+
+#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */
+#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */
+
+#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */
+#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */
+
+/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */
+#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */
+
+#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */
+#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */
+
+#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */
+#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */
+
+#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */
+#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */
+
+#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */
+#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */
+
+#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */
+#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */
+
+/* BusFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */
+#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */
+
+#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */
+#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */
+
+#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */
+#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */
+
+#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */
+#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */
+
+#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */
+#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */
+
+#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */
+#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */
+
+#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */
+#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */
+
+/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */
+#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */
+
+#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */
+#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */
+
+#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */
+#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */
+
+#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */
+#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */
+
+#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */
+#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */
+
+#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */
+#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */
+
+/* SCB Hard Fault Status Register Definitions */
+#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */
+#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */
+
+#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */
+#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */
+
+#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */
+#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */
+
+/* SCB Debug Fault Status Register Definitions */
+#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */
+#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */
+
+#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */
+#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */
+
+#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */
+#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */
+
+#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */
+#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */
+
+#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */
+#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB)
+ \brief Type definitions for the System Control and ID Register not in the SCB
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control and ID Register not in the SCB.
+ */
+typedef struct
+{
+ uint32_t RESERVED0[1U];
+ __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */
+ __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */
+} SCnSCB_Type;
+
+/* Interrupt Controller Type Register Definitions */
+#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */
+#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */
+
+/* Auxiliary Control Register Definitions */
+#define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */
+#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */
+
+#define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */
+#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */
+
+#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */
+#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */
+
+#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */
+#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */
+
+#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */
+#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */
+
+/*@} end of group CMSIS_SCnotSCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM)
+ \brief Type definitions for the Instrumentation Trace Macrocell (ITM)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM).
+ */
+typedef struct
+{
+ __OM union
+ {
+ __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */
+ __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */
+ __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */
+ } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */
+ uint32_t RESERVED0[864U];
+ __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */
+ uint32_t RESERVED1[15U];
+ __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */
+ uint32_t RESERVED2[15U];
+ __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */
+ uint32_t RESERVED3[29U];
+ __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */
+ __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */
+ __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */
+ uint32_t RESERVED4[43U];
+ __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */
+ uint32_t RESERVED5[6U];
+ __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */
+ __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */
+ __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */
+ __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */
+ __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */
+ __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */
+ __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */
+ __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */
+ __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */
+ __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */
+ __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */
+ __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */
+} ITM_Type;
+
+/* ITM Trace Privilege Register Definitions */
+#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */
+#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */
+
+/* ITM Trace Control Register Definitions */
+#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */
+#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */
+
+#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */
+#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */
+
+#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */
+#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */
+
+#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */
+#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */
+
+#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */
+#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */
+
+#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */
+#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */
+
+#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */
+#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */
+
+#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */
+#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */
+
+#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */
+#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */
+
+/* ITM Integration Write Register Definitions */
+#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */
+#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */
+
+/* ITM Integration Read Register Definitions */
+#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */
+#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */
+
+/* ITM Integration Mode Control Register Definitions */
+#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */
+#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */
+
+/* ITM Lock Status Register Definitions */
+#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */
+#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */
+
+#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */
+#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */
+
+#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */
+#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */
+
+/*@}*/ /* end of group CMSIS_ITM */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT)
+ \brief Type definitions for the Data Watchpoint and Trace (DWT)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Data Watchpoint and Trace Register (DWT).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */
+ __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */
+ __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */
+ __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */
+ __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */
+ __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */
+ __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */
+ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */
+ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */
+ __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */
+ __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */
+ uint32_t RESERVED0[1U];
+ __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */
+ __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */
+ __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */
+ uint32_t RESERVED1[1U];
+ __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */
+ __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */
+ __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */
+ uint32_t RESERVED2[1U];
+ __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */
+ __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */
+ __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */
+} DWT_Type;
+
+/* DWT Control Register Definitions */
+#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */
+#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */
+
+#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */
+#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */
+
+#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */
+#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */
+
+#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */
+#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */
+
+#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */
+#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */
+
+#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */
+#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */
+
+#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */
+#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */
+
+#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */
+#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */
+
+#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */
+#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */
+
+#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */
+#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */
+
+#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */
+#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */
+
+#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */
+#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */
+
+#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */
+#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */
+
+#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */
+#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */
+
+#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */
+#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */
+
+#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */
+#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */
+
+#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */
+#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */
+
+#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */
+#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */
+
+/* DWT CPI Count Register Definitions */
+#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */
+#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */
+
+/* DWT Exception Overhead Count Register Definitions */
+#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */
+#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */
+
+/* DWT Sleep Count Register Definitions */
+#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */
+#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */
+
+/* DWT LSU Count Register Definitions */
+#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */
+#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */
+
+/* DWT Folded-instruction Count Register Definitions */
+#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */
+#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */
+
+/* DWT Comparator Mask Register Definitions */
+#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */
+#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */
+
+/* DWT Comparator Function Register Definitions */
+#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */
+#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */
+
+#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */
+#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */
+
+#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */
+#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */
+
+#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */
+#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */
+
+#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */
+#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */
+
+#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */
+#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */
+
+#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */
+#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */
+
+#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */
+#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */
+
+#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */
+#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */
+
+/*@}*/ /* end of group CMSIS_DWT */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_TPI Trace Port Interface (TPI)
+ \brief Type definitions for the Trace Port Interface (TPI)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Trace Port Interface Register (TPI).
+ */
+typedef struct
+{
+ __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */
+ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */
+ uint32_t RESERVED0[2U];
+ __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */
+ uint32_t RESERVED1[55U];
+ __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */
+ uint32_t RESERVED2[131U];
+ __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */
+ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */
+ __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */
+ uint32_t RESERVED3[759U];
+ __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */
+ __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */
+ __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */
+ uint32_t RESERVED4[1U];
+ __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */
+ __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */
+ __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */
+ uint32_t RESERVED5[39U];
+ __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */
+ __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */
+ uint32_t RESERVED7[8U];
+ __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */
+ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */
+} TPI_Type;
+
+/* TPI Asynchronous Clock Prescaler Register Definitions */
+#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */
+#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */
+
+/* TPI Selected Pin Protocol Register Definitions */
+#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */
+#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */
+
+/* TPI Formatter and Flush Status Register Definitions */
+#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */
+#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */
+
+#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */
+#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */
+
+#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */
+#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */
+
+#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */
+#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */
+
+/* TPI Formatter and Flush Control Register Definitions */
+#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */
+#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */
+
+#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */
+#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */
+
+/* TPI TRIGGER Register Definitions */
+#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */
+#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */
+
+/* TPI Integration ETM Data Register Definitions (FIFO0) */
+#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */
+#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */
+
+#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */
+#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */
+
+#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */
+#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */
+
+#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */
+#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */
+
+#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */
+#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */
+
+#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */
+#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */
+
+#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */
+#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */
+
+/* TPI ITATBCTR2 Register Definitions */
+#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */
+#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */
+
+#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */
+#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */
+
+/* TPI Integration ITM Data Register Definitions (FIFO1) */
+#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */
+#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */
+
+#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */
+#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */
+
+#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */
+#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */
+
+#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */
+#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */
+
+#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */
+#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */
+
+#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */
+#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */
+
+#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */
+#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */
+
+/* TPI ITATBCTR0 Register Definitions */
+#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */
+#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */
+
+#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */
+#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */
+
+/* TPI Integration Mode Control Register Definitions */
+#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */
+#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */
+
+/* TPI DEVID Register Definitions */
+#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */
+#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */
+
+#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */
+#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */
+
+#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */
+#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */
+
+#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */
+#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */
+
+#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */
+#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */
+
+#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */
+#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */
+
+/* TPI DEVTYPE Register Definitions */
+#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */
+
+#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
+
+/*@}*/ /* end of group CMSIS_TPI */
+
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_MPU Memory Protection Unit (MPU)
+ \brief Type definitions for the Memory Protection Unit (MPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+ __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
+ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
+ __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */
+ __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */
+ __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */
+ __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */
+ __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */
+ __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */
+ __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */
+} MPU_Type;
+
+#define MPU_TYPE_RALIASES 4U
+
+/* MPU Type Register Definitions */
+#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register Definitions */
+#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register Definitions */
+#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register Definitions */
+#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */
+#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */
+
+#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */
+#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */
+
+#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */
+#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */
+
+/* MPU Region Attribute and Size Register Definitions */
+#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */
+#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */
+
+#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */
+#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */
+
+#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */
+#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */
+
+#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */
+#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */
+
+#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */
+#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */
+
+#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */
+#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */
+
+#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */
+#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */
+
+#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */
+#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */
+
+#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */
+#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */
+
+#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */
+#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_FPU Floating Point Unit (FPU)
+ \brief Type definitions for the Floating Point Unit (FPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Floating Point Unit (FPU).
+ */
+typedef struct
+{
+ uint32_t RESERVED0[1U];
+ __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */
+ __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */
+ __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */
+ __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */
+ __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */
+} FPU_Type;
+
+/* Floating-Point Context Control Register Definitions */
+#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */
+#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */
+
+#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */
+#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */
+
+#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */
+#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */
+
+#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */
+#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */
+
+#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */
+#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */
+
+#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */
+#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */
+
+#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */
+#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */
+
+#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */
+#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */
+
+#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */
+#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */
+
+/* Floating-Point Context Address Register Definitions */
+#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */
+#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */
+
+/* Floating-Point Default Status Control Register Definitions */
+#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */
+#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */
+
+#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */
+#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */
+
+#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */
+#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */
+
+#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */
+#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */
+
+/* Media and FP Feature Register 0 Definitions */
+#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */
+#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */
+
+#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */
+#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */
+
+#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */
+#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */
+
+#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */
+#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */
+
+#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */
+#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */
+
+#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */
+#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */
+
+#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */
+#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */
+
+#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */
+#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */
+
+/* Media and FP Feature Register 1 Definitions */
+#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */
+#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */
+
+#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */
+#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */
+
+#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */
+#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */
+
+#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */
+#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */
+
+/*@} end of group CMSIS_FPU */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Type definitions for the Core Debug Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Core Debug Register (CoreDebug).
+ */
+typedef struct
+{
+ __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */
+ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */
+ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */
+ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */
+} CoreDebug_Type;
+
+/* Debug Halting Control and Status Register Definitions */
+#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */
+#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */
+
+#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */
+#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */
+
+#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */
+#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */
+
+#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */
+#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */
+
+#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */
+#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */
+
+#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */
+#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */
+
+#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */
+#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */
+
+#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */
+#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */
+
+#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */
+#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */
+
+#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */
+#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */
+
+#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */
+#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */
+
+#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */
+#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */
+
+/* Debug Core Register Selector Register Definitions */
+#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */
+#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */
+
+#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */
+#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */
+
+/* Debug Exception and Monitor Control Register Definitions */
+#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */
+#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */
+
+#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */
+#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */
+
+#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */
+#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */
+
+#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */
+#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */
+
+#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */
+#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */
+
+#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */
+#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */
+
+#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */
+#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */
+
+#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */
+#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */
+
+#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */
+#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */
+
+#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */
+#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */
+
+#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */
+#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */
+
+#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */
+#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */
+
+#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */
+#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */
+
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */
+#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
+#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */
+#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */
+#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */
+#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */
+#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */
+#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */
+#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
+ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
+#endif
+
+#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */
+#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */
+
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Debug Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+ #define NVIC_GetActive __NVIC_GetActive
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* The following EXC_RETURN values are saved the LR on exception entry */
+#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */
+#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */
+#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */
+#define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */
+#define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */
+#define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */
+
+
+/**
+ \brief Set Priority Grouping
+ \details Sets the priority grouping field using the required unlock sequence.
+ The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
+ Only values from 0..7 are used.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Priority grouping field.
+ */
+__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
+{
+ uint32_t reg_value;
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+
+ reg_value = SCB->AIRCR; /* read old register configuration */
+ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
+ reg_value = (reg_value |
+ ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */
+ SCB->AIRCR = reg_value;
+}
+
+
+/**
+ \brief Get Priority Grouping
+ \details Reads the priority grouping field from the NVIC Interrupt Controller.
+ \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void)
+{
+ return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
+}
+
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt
+ \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+ else
+ {
+ SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
+ SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+/* ########################## MPU functions #################################### */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+
+#include "mpu_armv7.h"
+
+#endif
+
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ uint32_t mvfr0;
+
+ mvfr0 = FPU->MVFR0;
+ if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U)
+ {
+ return 1U; /* Single precision FPU */
+ }
+ else
+ {
+ return 0U; /* No FPU */
+ }
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+/* ##################################### Debug In/Output function ########################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_core_DebugFunctions ITM Functions
+ \brief Functions that access the ITM debug interface.
+ @{
+ */
+
+extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */
+#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
+
+
+/**
+ \brief ITM Send Character
+ \details Transmits a character via the ITM channel 0, and
+ \li Just returns when no debugger is connected that has booked the output.
+ \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted.
+ \param [in] ch Character to transmit.
+ \returns Character to transmit.
+ */
+__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch)
+{
+ if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */
+ ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */
+ {
+ while (ITM->PORT[0U].u32 == 0UL)
+ {
+ __NOP();
+ }
+ ITM->PORT[0U].u8 = (uint8_t)ch;
+ }
+ return (ch);
+}
+
+
+/**
+ \brief ITM Receive Character
+ \details Inputs a character via the external variable \ref ITM_RxBuffer.
+ \return Received character.
+ \return -1 No character pending.
+ */
+__STATIC_INLINE int32_t ITM_ReceiveChar (void)
+{
+ int32_t ch = -1; /* no character available */
+
+ if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY)
+ {
+ ch = ITM_RxBuffer;
+ ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */
+ }
+
+ return (ch);
+}
+
+
+/**
+ \brief ITM Check Character
+ \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer.
+ \return 0 No character available.
+ \return 1 Character available.
+ */
+__STATIC_INLINE int32_t ITM_CheckChar (void)
+{
+
+ if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY)
+ {
+ return (0); /* no character available */
+ }
+ else
+ {
+ return (1); /* character available */
+ }
+}
+
+/*@} end of CMSIS_core_DebugFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM4_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm7.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm7.h
new file mode 100644
index 0000000..a14dc62
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_cm7.h
@@ -0,0 +1,2671 @@
+/**************************************************************************//**
+ * @file core_cm7.h
+ * @brief CMSIS Cortex-M7 Core Peripheral Access Layer Header File
+ * @version V5.0.8
+ * @date 04. June 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_CM7_H_GENERIC
+#define __CORE_CM7_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup Cortex_M7
+ @{
+ */
+
+#include "cmsis_version.h"
+
+/* CMSIS CM7 definitions */
+#define __CM7_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __CM7_CMSIS_VERSION_SUB ( __CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __CM7_CMSIS_VERSION ((__CM7_CMSIS_VERSION_MAIN << 16U) | \
+ __CM7_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_M (7U) /*!< Cortex-M Core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions.
+*/
+#if defined ( __CC_ARM )
+ #if defined __TARGET_FPU_VFP
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_PCS_VFP
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined __ARMVFP__
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined __TI_VFP_SUPPORT__
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined __FPU_VFP__
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM7_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_CM7_H_DEPENDANT
+#define __CORE_CM7_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __CM7_REV
+ #define __CM7_REV 0x0000U
+ #warning "__CM7_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __FPU_PRESENT
+ #define __FPU_PRESENT 0U
+ #warning "__FPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MPU_PRESENT
+ #define __MPU_PRESENT 0U
+ #warning "__MPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __ICACHE_PRESENT
+ #define __ICACHE_PRESENT 0U
+ #warning "__ICACHE_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __DCACHE_PRESENT
+ #define __DCACHE_PRESENT 0U
+ #warning "__DCACHE_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __DTCM_PRESENT
+ #define __DTCM_PRESENT 0U
+ #warning "__DTCM_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 3U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group Cortex_M7 */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ - Core Debug Register
+ - Core MPU Register
+ - Core FPU Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */
+ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
+ uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+#define APSR_Q_Pos 27U /*!< APSR: Q Position */
+#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */
+
+#define APSR_GE_Pos 16U /*!< APSR: GE Position */
+#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:1; /*!< bit: 9 Reserved */
+ uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */
+ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
+ uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit */
+ uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */
+#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */
+
+#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */
+#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */
+#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */
+
+#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */
+#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
+ uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */
+ uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */
+#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */
+
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */
+#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[24U];
+ __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[24U];
+ __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[24U];
+ __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[24U];
+ __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
+ uint32_t RESERVED4[56U];
+ __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
+ uint32_t RESERVED5[644U];
+ __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
+} NVIC_Type;
+
+/* Software Triggered Interrupt Register Definitions */
+#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */
+#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+ __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */
+ __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */
+ __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */
+ __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */
+ __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */
+ __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */
+ __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */
+ __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */
+ __IM uint32_t ID_AFR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */
+ __IM uint32_t ID_MFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */
+ __IM uint32_t ID_ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */
+ uint32_t RESERVED0[1U];
+ __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */
+ __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */
+ __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */
+ __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */
+ __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */
+ uint32_t RESERVED3[93U];
+ __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */
+ uint32_t RESERVED4[15U];
+ __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */
+ __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */
+ __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */
+ uint32_t RESERVED5[1U];
+ __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */
+ uint32_t RESERVED6[1U];
+ __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */
+ __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */
+ __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */
+ __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */
+ __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */
+ __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */
+ __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */
+ __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */
+ uint32_t RESERVED7[6U];
+ __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */
+ __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */
+ __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */
+ __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */
+ __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */
+ uint32_t RESERVED8[1U];
+ __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */
+#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */
+#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+/* SCB Vector Table Offset Register Definitions */
+#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */
+#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */
+#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: Branch prediction enable bit Position */
+#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: Branch prediction enable bit Mask */
+
+#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: Instruction cache enable bit Position */
+#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: Instruction cache enable bit Mask */
+
+#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: Cache enable bit Position */
+#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: Cache enable bit Mask */
+
+#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */
+#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
+
+#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */
+#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */
+
+#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */
+#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */
+#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */
+
+#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */
+#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */
+#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */
+
+#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */
+#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */
+
+#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */
+#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */
+
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */
+#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */
+
+#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */
+#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */
+
+#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */
+#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */
+
+#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */
+#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */
+
+#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */
+#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */
+
+#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */
+#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */
+
+#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */
+#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */
+
+#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */
+#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */
+
+#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */
+#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */
+
+#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */
+#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */
+
+/* SCB Configurable Fault Status Register Definitions */
+#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */
+#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */
+
+#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */
+#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */
+
+#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */
+#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */
+
+/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */
+#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */
+
+#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */
+#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */
+
+#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */
+#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */
+
+#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */
+#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */
+
+#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */
+#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */
+
+#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */
+#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */
+
+/* BusFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */
+#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */
+
+#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */
+#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */
+
+#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */
+#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */
+
+#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */
+#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */
+
+#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */
+#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */
+
+#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */
+#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */
+
+#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */
+#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */
+
+/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */
+#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */
+
+#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */
+#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */
+
+#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */
+#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */
+
+#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */
+#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */
+
+#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */
+#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */
+
+#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */
+#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */
+
+/* SCB Hard Fault Status Register Definitions */
+#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */
+#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */
+
+#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */
+#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */
+
+#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */
+#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */
+
+/* SCB Debug Fault Status Register Definitions */
+#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */
+#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */
+
+#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */
+#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */
+
+#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */
+#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */
+
+#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */
+#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */
+
+#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */
+#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */
+
+/* SCB Cache Level ID Register Definitions */
+#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */
+#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */
+
+#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */
+#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */
+
+/* SCB Cache Type Register Definitions */
+#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */
+#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */
+
+#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */
+#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */
+
+#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */
+#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */
+
+#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */
+#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */
+
+#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */
+#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */
+
+/* SCB Cache Size ID Register Definitions */
+#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */
+#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */
+
+#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */
+#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */
+
+#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */
+#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */
+
+#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */
+#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */
+
+#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */
+#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */
+
+#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */
+#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */
+
+#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */
+#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */
+
+/* SCB Cache Size Selection Register Definitions */
+#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */
+#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */
+
+#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */
+#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */
+
+/* SCB Software Triggered Interrupt Register Definitions */
+#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */
+#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */
+
+/* SCB D-Cache Invalidate by Set-way Register Definitions */
+#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */
+#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */
+
+#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */
+#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */
+
+/* SCB D-Cache Clean by Set-way Register Definitions */
+#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */
+#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */
+
+#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */
+#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */
+
+/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */
+#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */
+#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */
+
+#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */
+#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */
+
+/* Instruction Tightly-Coupled Memory Control Register Definitions */
+#define SCB_ITCMCR_SZ_Pos 3U /*!< SCB ITCMCR: SZ Position */
+#define SCB_ITCMCR_SZ_Msk (0xFUL << SCB_ITCMCR_SZ_Pos) /*!< SCB ITCMCR: SZ Mask */
+
+#define SCB_ITCMCR_RETEN_Pos 2U /*!< SCB ITCMCR: RETEN Position */
+#define SCB_ITCMCR_RETEN_Msk (1UL << SCB_ITCMCR_RETEN_Pos) /*!< SCB ITCMCR: RETEN Mask */
+
+#define SCB_ITCMCR_RMW_Pos 1U /*!< SCB ITCMCR: RMW Position */
+#define SCB_ITCMCR_RMW_Msk (1UL << SCB_ITCMCR_RMW_Pos) /*!< SCB ITCMCR: RMW Mask */
+
+#define SCB_ITCMCR_EN_Pos 0U /*!< SCB ITCMCR: EN Position */
+#define SCB_ITCMCR_EN_Msk (1UL /*<< SCB_ITCMCR_EN_Pos*/) /*!< SCB ITCMCR: EN Mask */
+
+/* Data Tightly-Coupled Memory Control Register Definitions */
+#define SCB_DTCMCR_SZ_Pos 3U /*!< SCB DTCMCR: SZ Position */
+#define SCB_DTCMCR_SZ_Msk (0xFUL << SCB_DTCMCR_SZ_Pos) /*!< SCB DTCMCR: SZ Mask */
+
+#define SCB_DTCMCR_RETEN_Pos 2U /*!< SCB DTCMCR: RETEN Position */
+#define SCB_DTCMCR_RETEN_Msk (1UL << SCB_DTCMCR_RETEN_Pos) /*!< SCB DTCMCR: RETEN Mask */
+
+#define SCB_DTCMCR_RMW_Pos 1U /*!< SCB DTCMCR: RMW Position */
+#define SCB_DTCMCR_RMW_Msk (1UL << SCB_DTCMCR_RMW_Pos) /*!< SCB DTCMCR: RMW Mask */
+
+#define SCB_DTCMCR_EN_Pos 0U /*!< SCB DTCMCR: EN Position */
+#define SCB_DTCMCR_EN_Msk (1UL /*<< SCB_DTCMCR_EN_Pos*/) /*!< SCB DTCMCR: EN Mask */
+
+/* AHBP Control Register Definitions */
+#define SCB_AHBPCR_SZ_Pos 1U /*!< SCB AHBPCR: SZ Position */
+#define SCB_AHBPCR_SZ_Msk (7UL << SCB_AHBPCR_SZ_Pos) /*!< SCB AHBPCR: SZ Mask */
+
+#define SCB_AHBPCR_EN_Pos 0U /*!< SCB AHBPCR: EN Position */
+#define SCB_AHBPCR_EN_Msk (1UL /*<< SCB_AHBPCR_EN_Pos*/) /*!< SCB AHBPCR: EN Mask */
+
+/* L1 Cache Control Register Definitions */
+#define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */
+#define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */
+
+#define SCB_CACR_ECCEN_Pos 1U /*!< SCB CACR: ECCEN Position */
+#define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< SCB CACR: ECCEN Mask */
+
+#define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */
+#define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */
+
+/* AHBS Control Register Definitions */
+#define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */
+#define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBPCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */
+
+#define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */
+#define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBPCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */
+
+#define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/
+#define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBPCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */
+
+/* Auxiliary Bus Fault Status Register Definitions */
+#define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/
+#define SCB_ABFSR_AXIMTYPE_Msk (3UL << SCB_ABFSR_AXIMTYPE_Pos) /*!< SCB ABFSR: AXIMTYPE Mask */
+
+#define SCB_ABFSR_EPPB_Pos 4U /*!< SCB ABFSR: EPPB Position*/
+#define SCB_ABFSR_EPPB_Msk (1UL << SCB_ABFSR_EPPB_Pos) /*!< SCB ABFSR: EPPB Mask */
+
+#define SCB_ABFSR_AXIM_Pos 3U /*!< SCB ABFSR: AXIM Position*/
+#define SCB_ABFSR_AXIM_Msk (1UL << SCB_ABFSR_AXIM_Pos) /*!< SCB ABFSR: AXIM Mask */
+
+#define SCB_ABFSR_AHBP_Pos 2U /*!< SCB ABFSR: AHBP Position*/
+#define SCB_ABFSR_AHBP_Msk (1UL << SCB_ABFSR_AHBP_Pos) /*!< SCB ABFSR: AHBP Mask */
+
+#define SCB_ABFSR_DTCM_Pos 1U /*!< SCB ABFSR: DTCM Position*/
+#define SCB_ABFSR_DTCM_Msk (1UL << SCB_ABFSR_DTCM_Pos) /*!< SCB ABFSR: DTCM Mask */
+
+#define SCB_ABFSR_ITCM_Pos 0U /*!< SCB ABFSR: ITCM Position*/
+#define SCB_ABFSR_ITCM_Msk (1UL /*<< SCB_ABFSR_ITCM_Pos*/) /*!< SCB ABFSR: ITCM Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB)
+ \brief Type definitions for the System Control and ID Register not in the SCB
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control and ID Register not in the SCB.
+ */
+typedef struct
+{
+ uint32_t RESERVED0[1U];
+ __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */
+ __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */
+} SCnSCB_Type;
+
+/* Interrupt Controller Type Register Definitions */
+#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */
+#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */
+
+/* Auxiliary Control Register Definitions */
+#define SCnSCB_ACTLR_DISITMATBFLUSH_Pos 12U /*!< ACTLR: DISITMATBFLUSH Position */
+#define SCnSCB_ACTLR_DISITMATBFLUSH_Msk (1UL << SCnSCB_ACTLR_DISITMATBFLUSH_Pos) /*!< ACTLR: DISITMATBFLUSH Mask */
+
+#define SCnSCB_ACTLR_DISRAMODE_Pos 11U /*!< ACTLR: DISRAMODE Position */
+#define SCnSCB_ACTLR_DISRAMODE_Msk (1UL << SCnSCB_ACTLR_DISRAMODE_Pos) /*!< ACTLR: DISRAMODE Mask */
+
+#define SCnSCB_ACTLR_FPEXCODIS_Pos 10U /*!< ACTLR: FPEXCODIS Position */
+#define SCnSCB_ACTLR_FPEXCODIS_Msk (1UL << SCnSCB_ACTLR_FPEXCODIS_Pos) /*!< ACTLR: FPEXCODIS Mask */
+
+#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */
+#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */
+
+#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */
+#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */
+
+/*@} end of group CMSIS_SCnotSCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM)
+ \brief Type definitions for the Instrumentation Trace Macrocell (ITM)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM).
+ */
+typedef struct
+{
+ __OM union
+ {
+ __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */
+ __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */
+ __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */
+ } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */
+ uint32_t RESERVED0[864U];
+ __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */
+ uint32_t RESERVED1[15U];
+ __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */
+ uint32_t RESERVED2[15U];
+ __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */
+ uint32_t RESERVED3[29U];
+ __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */
+ __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */
+ __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */
+ uint32_t RESERVED4[43U];
+ __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */
+ uint32_t RESERVED5[6U];
+ __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */
+ __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */
+ __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */
+ __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */
+ __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */
+ __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */
+ __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */
+ __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */
+ __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */
+ __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */
+ __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */
+ __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */
+} ITM_Type;
+
+/* ITM Trace Privilege Register Definitions */
+#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */
+#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */
+
+/* ITM Trace Control Register Definitions */
+#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */
+#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */
+
+#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */
+#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */
+
+#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */
+#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */
+
+#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */
+#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */
+
+#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */
+#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */
+
+#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */
+#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */
+
+#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */
+#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */
+
+#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */
+#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */
+
+#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */
+#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */
+
+/* ITM Integration Write Register Definitions */
+#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */
+#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */
+
+/* ITM Integration Read Register Definitions */
+#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */
+#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */
+
+/* ITM Integration Mode Control Register Definitions */
+#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */
+#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */
+
+/* ITM Lock Status Register Definitions */
+#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */
+#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */
+
+#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */
+#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */
+
+#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */
+#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */
+
+/*@}*/ /* end of group CMSIS_ITM */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT)
+ \brief Type definitions for the Data Watchpoint and Trace (DWT)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Data Watchpoint and Trace Register (DWT).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */
+ __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */
+ __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */
+ __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */
+ __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */
+ __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */
+ __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */
+ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */
+ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */
+ __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */
+ __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */
+ uint32_t RESERVED0[1U];
+ __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */
+ __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */
+ __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */
+ uint32_t RESERVED1[1U];
+ __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */
+ __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */
+ __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */
+ uint32_t RESERVED2[1U];
+ __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */
+ __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */
+ __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */
+ uint32_t RESERVED3[981U];
+ __OM uint32_t LAR; /*!< Offset: 0xFB0 ( W) Lock Access Register */
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */
+} DWT_Type;
+
+/* DWT Control Register Definitions */
+#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */
+#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */
+
+#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */
+#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */
+
+#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */
+#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */
+
+#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */
+#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */
+
+#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */
+#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */
+
+#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */
+#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */
+
+#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */
+#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */
+
+#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */
+#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */
+
+#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */
+#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */
+
+#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */
+#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */
+
+#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */
+#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */
+
+#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */
+#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */
+
+#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */
+#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */
+
+#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */
+#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */
+
+#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */
+#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */
+
+#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */
+#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */
+
+#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */
+#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */
+
+#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */
+#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */
+
+/* DWT CPI Count Register Definitions */
+#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */
+#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */
+
+/* DWT Exception Overhead Count Register Definitions */
+#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */
+#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */
+
+/* DWT Sleep Count Register Definitions */
+#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */
+#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */
+
+/* DWT LSU Count Register Definitions */
+#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */
+#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */
+
+/* DWT Folded-instruction Count Register Definitions */
+#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */
+#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */
+
+/* DWT Comparator Mask Register Definitions */
+#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */
+#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */
+
+/* DWT Comparator Function Register Definitions */
+#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */
+#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */
+
+#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */
+#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */
+
+#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */
+#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */
+
+#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */
+#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */
+
+#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */
+#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */
+
+#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */
+#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */
+
+#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */
+#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */
+
+#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */
+#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */
+
+#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */
+#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */
+
+/*@}*/ /* end of group CMSIS_DWT */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_TPI Trace Port Interface (TPI)
+ \brief Type definitions for the Trace Port Interface (TPI)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Trace Port Interface Register (TPI).
+ */
+typedef struct
+{
+ __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */
+ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */
+ uint32_t RESERVED0[2U];
+ __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */
+ uint32_t RESERVED1[55U];
+ __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */
+ uint32_t RESERVED2[131U];
+ __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */
+ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */
+ __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */
+ uint32_t RESERVED3[759U];
+ __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */
+ __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */
+ __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */
+ uint32_t RESERVED4[1U];
+ __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */
+ __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */
+ __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */
+ uint32_t RESERVED5[39U];
+ __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */
+ __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */
+ uint32_t RESERVED7[8U];
+ __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */
+ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */
+} TPI_Type;
+
+/* TPI Asynchronous Clock Prescaler Register Definitions */
+#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */
+#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */
+
+/* TPI Selected Pin Protocol Register Definitions */
+#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */
+#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */
+
+/* TPI Formatter and Flush Status Register Definitions */
+#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */
+#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */
+
+#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */
+#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */
+
+#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */
+#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */
+
+#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */
+#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */
+
+/* TPI Formatter and Flush Control Register Definitions */
+#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */
+#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */
+
+#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */
+#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */
+
+/* TPI TRIGGER Register Definitions */
+#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */
+#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */
+
+/* TPI Integration ETM Data Register Definitions (FIFO0) */
+#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */
+#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */
+
+#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */
+#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */
+
+#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */
+#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */
+
+#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */
+#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */
+
+#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */
+#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */
+
+#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */
+#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */
+
+#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */
+#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */
+
+/* TPI ITATBCTR2 Register Definitions */
+#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */
+#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */
+
+#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */
+#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */
+
+/* TPI Integration ITM Data Register Definitions (FIFO1) */
+#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */
+#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */
+
+#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */
+#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */
+
+#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */
+#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */
+
+#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */
+#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */
+
+#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */
+#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */
+
+#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */
+#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */
+
+#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */
+#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */
+
+/* TPI ITATBCTR0 Register Definitions */
+#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */
+#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */
+
+#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */
+#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */
+
+/* TPI Integration Mode Control Register Definitions */
+#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */
+#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */
+
+/* TPI DEVID Register Definitions */
+#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */
+#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */
+
+#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */
+#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */
+
+#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */
+#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */
+
+#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */
+#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */
+
+#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */
+#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */
+
+#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */
+#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */
+
+/* TPI DEVTYPE Register Definitions */
+#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */
+
+#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
+
+/*@}*/ /* end of group CMSIS_TPI */
+
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_MPU Memory Protection Unit (MPU)
+ \brief Type definitions for the Memory Protection Unit (MPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+ __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
+ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
+ __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */
+ __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */
+ __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */
+ __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */
+ __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */
+ __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */
+ __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */
+} MPU_Type;
+
+#define MPU_TYPE_RALIASES 4U
+
+/* MPU Type Register Definitions */
+#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register Definitions */
+#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register Definitions */
+#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register Definitions */
+#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */
+#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */
+
+#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */
+#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */
+
+#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */
+#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */
+
+/* MPU Region Attribute and Size Register Definitions */
+#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */
+#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */
+
+#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */
+#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */
+
+#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */
+#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */
+
+#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */
+#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */
+
+#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */
+#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */
+
+#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */
+#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */
+
+#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */
+#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */
+
+#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */
+#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */
+
+#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */
+#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */
+
+#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */
+#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_FPU Floating Point Unit (FPU)
+ \brief Type definitions for the Floating Point Unit (FPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Floating Point Unit (FPU).
+ */
+typedef struct
+{
+ uint32_t RESERVED0[1U];
+ __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */
+ __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */
+ __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */
+ __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */
+ __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */
+ __IM uint32_t MVFR2; /*!< Offset: 0x018 (R/ ) Media and FP Feature Register 2 */
+} FPU_Type;
+
+/* Floating-Point Context Control Register Definitions */
+#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */
+#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */
+
+#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */
+#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */
+
+#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */
+#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */
+
+#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */
+#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */
+
+#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */
+#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */
+
+#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */
+#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */
+
+#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */
+#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */
+
+#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */
+#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */
+
+#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */
+#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */
+
+/* Floating-Point Context Address Register Definitions */
+#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */
+#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */
+
+/* Floating-Point Default Status Control Register Definitions */
+#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */
+#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */
+
+#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */
+#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */
+
+#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */
+#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */
+
+#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */
+#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */
+
+/* Media and FP Feature Register 0 Definitions */
+#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */
+#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */
+
+#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */
+#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */
+
+#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */
+#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */
+
+#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */
+#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */
+
+#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */
+#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */
+
+#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */
+#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */
+
+#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */
+#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */
+
+#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */
+#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */
+
+/* Media and FP Feature Register 1 Definitions */
+#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */
+#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */
+
+#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */
+#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */
+
+#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */
+#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */
+
+#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */
+#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */
+
+/* Media and FP Feature Register 2 Definitions */
+
+/*@} end of group CMSIS_FPU */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Type definitions for the Core Debug Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Core Debug Register (CoreDebug).
+ */
+typedef struct
+{
+ __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */
+ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */
+ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */
+ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */
+} CoreDebug_Type;
+
+/* Debug Halting Control and Status Register Definitions */
+#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */
+#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */
+
+#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */
+#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */
+
+#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */
+#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */
+
+#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */
+#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */
+
+#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */
+#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */
+
+#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */
+#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */
+
+#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */
+#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */
+
+#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */
+#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */
+
+#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */
+#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */
+
+#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */
+#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */
+
+#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */
+#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */
+
+#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */
+#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */
+
+/* Debug Core Register Selector Register Definitions */
+#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */
+#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */
+
+#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */
+#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */
+
+/* Debug Exception and Monitor Control Register Definitions */
+#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */
+#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */
+
+#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */
+#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */
+
+#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */
+#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */
+
+#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */
+#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */
+
+#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */
+#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */
+
+#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */
+#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */
+
+#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */
+#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */
+
+#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */
+#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */
+
+#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */
+#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */
+
+#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */
+#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */
+
+#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */
+#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */
+
+#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */
+#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */
+
+#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */
+#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */
+
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */
+#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
+#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */
+#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */
+#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */
+#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */
+#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */
+#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */
+#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
+ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
+#endif
+
+#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */
+#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */
+
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Debug Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+ #define NVIC_GetActive __NVIC_GetActive
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* The following EXC_RETURN values are saved the LR on exception entry */
+#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */
+#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */
+#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */
+#define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */
+#define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */
+#define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */
+
+
+/**
+ \brief Set Priority Grouping
+ \details Sets the priority grouping field using the required unlock sequence.
+ The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
+ Only values from 0..7 are used.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Priority grouping field.
+ */
+__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
+{
+ uint32_t reg_value;
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+
+ reg_value = SCB->AIRCR; /* read old register configuration */
+ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
+ reg_value = (reg_value |
+ ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */
+ SCB->AIRCR = reg_value;
+}
+
+
+/**
+ \brief Get Priority Grouping
+ \details Reads the priority grouping field from the NVIC Interrupt Controller.
+ \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void)
+{
+ return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
+}
+
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt
+ \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+ else
+ {
+ SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
+ SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+/* ########################## MPU functions #################################### */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+
+#include "mpu_armv7.h"
+
+#endif
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ uint32_t mvfr0;
+
+ mvfr0 = SCB->MVFR0;
+ if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U)
+ {
+ return 2U; /* Double + Single precision FPU */
+ }
+ else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U)
+ {
+ return 1U; /* Single precision FPU */
+ }
+ else
+ {
+ return 0U; /* No FPU */
+ }
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ########################## Cache functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_CacheFunctions Cache Functions
+ \brief Functions that configure Instruction and Data cache.
+ @{
+ */
+
+/* Cache Size ID Register Macros */
+#define CCSIDR_WAYS(x) (((x) & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos)
+#define CCSIDR_SETS(x) (((x) & SCB_CCSIDR_NUMSETS_Msk ) >> SCB_CCSIDR_NUMSETS_Pos )
+
+
+/**
+ \brief Enable I-Cache
+ \details Turns on I-Cache
+ */
+__STATIC_INLINE void SCB_EnableICache (void)
+{
+ #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
+ __DSB();
+ __ISB();
+ SCB->ICIALLU = 0UL; /* invalidate I-Cache */
+ __DSB();
+ __ISB();
+ SCB->CCR |= (uint32_t)SCB_CCR_IC_Msk; /* enable I-Cache */
+ __DSB();
+ __ISB();
+ #endif
+}
+
+
+/**
+ \brief Disable I-Cache
+ \details Turns off I-Cache
+ */
+__STATIC_INLINE void SCB_DisableICache (void)
+{
+ #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
+ __DSB();
+ __ISB();
+ SCB->CCR &= ~(uint32_t)SCB_CCR_IC_Msk; /* disable I-Cache */
+ SCB->ICIALLU = 0UL; /* invalidate I-Cache */
+ __DSB();
+ __ISB();
+ #endif
+}
+
+
+/**
+ \brief Invalidate I-Cache
+ \details Invalidates I-Cache
+ */
+__STATIC_INLINE void SCB_InvalidateICache (void)
+{
+ #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
+ __DSB();
+ __ISB();
+ SCB->ICIALLU = 0UL;
+ __DSB();
+ __ISB();
+ #endif
+}
+
+
+/**
+ \brief Enable D-Cache
+ \details Turns on D-Cache
+ */
+__STATIC_INLINE void SCB_EnableDCache (void)
+{
+ #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
+ uint32_t ccsidr;
+ uint32_t sets;
+ uint32_t ways;
+
+ SCB->CSSELR = 0U; /*(0U << 1U) | 0U;*/ /* Level 1 data cache */
+ __DSB();
+
+ ccsidr = SCB->CCSIDR;
+
+ /* invalidate D-Cache */
+ sets = (uint32_t)(CCSIDR_SETS(ccsidr));
+ do {
+ ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
+ do {
+ SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) |
+ ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) );
+ #if defined ( __CC_ARM )
+ __schedule_barrier();
+ #endif
+ } while (ways-- != 0U);
+ } while(sets-- != 0U);
+ __DSB();
+
+ SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */
+
+ __DSB();
+ __ISB();
+ #endif
+}
+
+
+/**
+ \brief Disable D-Cache
+ \details Turns off D-Cache
+ */
+__STATIC_INLINE void SCB_DisableDCache (void)
+{
+ #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
+ uint32_t ccsidr;
+ uint32_t sets;
+ uint32_t ways;
+
+ SCB->CSSELR = 0U; /*(0U << 1U) | 0U;*/ /* Level 1 data cache */
+ __DSB();
+
+ SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk; /* disable D-Cache */
+ __DSB();
+
+ ccsidr = SCB->CCSIDR;
+
+ /* clean & invalidate D-Cache */
+ sets = (uint32_t)(CCSIDR_SETS(ccsidr));
+ do {
+ ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
+ do {
+ SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) |
+ ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) );
+ #if defined ( __CC_ARM )
+ __schedule_barrier();
+ #endif
+ } while (ways-- != 0U);
+ } while(sets-- != 0U);
+
+ __DSB();
+ __ISB();
+ #endif
+}
+
+
+/**
+ \brief Invalidate D-Cache
+ \details Invalidates D-Cache
+ */
+__STATIC_INLINE void SCB_InvalidateDCache (void)
+{
+ #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
+ uint32_t ccsidr;
+ uint32_t sets;
+ uint32_t ways;
+
+ SCB->CSSELR = 0U; /*(0U << 1U) | 0U;*/ /* Level 1 data cache */
+ __DSB();
+
+ ccsidr = SCB->CCSIDR;
+
+ /* invalidate D-Cache */
+ sets = (uint32_t)(CCSIDR_SETS(ccsidr));
+ do {
+ ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
+ do {
+ SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) |
+ ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) );
+ #if defined ( __CC_ARM )
+ __schedule_barrier();
+ #endif
+ } while (ways-- != 0U);
+ } while(sets-- != 0U);
+
+ __DSB();
+ __ISB();
+ #endif
+}
+
+
+/**
+ \brief Clean D-Cache
+ \details Cleans D-Cache
+ */
+__STATIC_INLINE void SCB_CleanDCache (void)
+{
+ #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
+ uint32_t ccsidr;
+ uint32_t sets;
+ uint32_t ways;
+
+ SCB->CSSELR = 0U; /*(0U << 1U) | 0U;*/ /* Level 1 data cache */
+ __DSB();
+
+ ccsidr = SCB->CCSIDR;
+
+ /* clean D-Cache */
+ sets = (uint32_t)(CCSIDR_SETS(ccsidr));
+ do {
+ ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
+ do {
+ SCB->DCCSW = (((sets << SCB_DCCSW_SET_Pos) & SCB_DCCSW_SET_Msk) |
+ ((ways << SCB_DCCSW_WAY_Pos) & SCB_DCCSW_WAY_Msk) );
+ #if defined ( __CC_ARM )
+ __schedule_barrier();
+ #endif
+ } while (ways-- != 0U);
+ } while(sets-- != 0U);
+
+ __DSB();
+ __ISB();
+ #endif
+}
+
+
+/**
+ \brief Clean & Invalidate D-Cache
+ \details Cleans and Invalidates D-Cache
+ */
+__STATIC_INLINE void SCB_CleanInvalidateDCache (void)
+{
+ #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
+ uint32_t ccsidr;
+ uint32_t sets;
+ uint32_t ways;
+
+ SCB->CSSELR = 0U; /*(0U << 1U) | 0U;*/ /* Level 1 data cache */
+ __DSB();
+
+ ccsidr = SCB->CCSIDR;
+
+ /* clean & invalidate D-Cache */
+ sets = (uint32_t)(CCSIDR_SETS(ccsidr));
+ do {
+ ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
+ do {
+ SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) |
+ ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) );
+ #if defined ( __CC_ARM )
+ __schedule_barrier();
+ #endif
+ } while (ways-- != 0U);
+ } while(sets-- != 0U);
+
+ __DSB();
+ __ISB();
+ #endif
+}
+
+
+/**
+ \brief D-Cache Invalidate by address
+ \details Invalidates D-Cache for the given address
+ \param[in] addr address (aligned to 32-byte boundary)
+ \param[in] dsize size of memory block (in number of bytes)
+*/
+__STATIC_INLINE void SCB_InvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize)
+{
+ #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
+ int32_t op_size = dsize;
+ uint32_t op_addr = (uint32_t)addr;
+ int32_t linesize = 32; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */
+
+ __DSB();
+
+ while (op_size > 0) {
+ SCB->DCIMVAC = op_addr;
+ op_addr += (uint32_t)linesize;
+ op_size -= linesize;
+ }
+
+ __DSB();
+ __ISB();
+ #endif
+}
+
+
+/**
+ \brief D-Cache Clean by address
+ \details Cleans D-Cache for the given address
+ \param[in] addr address (aligned to 32-byte boundary)
+ \param[in] dsize size of memory block (in number of bytes)
+*/
+__STATIC_INLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize)
+{
+ #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
+ int32_t op_size = dsize;
+ uint32_t op_addr = (uint32_t) addr;
+ int32_t linesize = 32; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */
+
+ __DSB();
+
+ while (op_size > 0) {
+ SCB->DCCMVAC = op_addr;
+ op_addr += (uint32_t)linesize;
+ op_size -= linesize;
+ }
+
+ __DSB();
+ __ISB();
+ #endif
+}
+
+
+/**
+ \brief D-Cache Clean and Invalidate by address
+ \details Cleans and invalidates D_Cache for the given address
+ \param[in] addr address (aligned to 32-byte boundary)
+ \param[in] dsize size of memory block (in number of bytes)
+*/
+__STATIC_INLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize)
+{
+ #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
+ int32_t op_size = dsize;
+ uint32_t op_addr = (uint32_t) addr;
+ int32_t linesize = 32; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */
+
+ __DSB();
+
+ while (op_size > 0) {
+ SCB->DCCIMVAC = op_addr;
+ op_addr += (uint32_t)linesize;
+ op_size -= linesize;
+ }
+
+ __DSB();
+ __ISB();
+ #endif
+}
+
+
+/*@} end of CMSIS_Core_CacheFunctions */
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+/* ##################################### Debug In/Output function ########################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_core_DebugFunctions ITM Functions
+ \brief Functions that access the ITM debug interface.
+ @{
+ */
+
+extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */
+#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
+
+
+/**
+ \brief ITM Send Character
+ \details Transmits a character via the ITM channel 0, and
+ \li Just returns when no debugger is connected that has booked the output.
+ \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted.
+ \param [in] ch Character to transmit.
+ \returns Character to transmit.
+ */
+__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch)
+{
+ if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */
+ ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */
+ {
+ while (ITM->PORT[0U].u32 == 0UL)
+ {
+ __NOP();
+ }
+ ITM->PORT[0U].u8 = (uint8_t)ch;
+ }
+ return (ch);
+}
+
+
+/**
+ \brief ITM Receive Character
+ \details Inputs a character via the external variable \ref ITM_RxBuffer.
+ \return Received character.
+ \return -1 No character pending.
+ */
+__STATIC_INLINE int32_t ITM_ReceiveChar (void)
+{
+ int32_t ch = -1; /* no character available */
+
+ if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY)
+ {
+ ch = ITM_RxBuffer;
+ ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */
+ }
+
+ return (ch);
+}
+
+
+/**
+ \brief ITM Check Character
+ \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer.
+ \return 0 No character available.
+ \return 1 Character available.
+ */
+__STATIC_INLINE int32_t ITM_CheckChar (void)
+{
+
+ if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY)
+ {
+ return (0); /* no character available */
+ }
+ else
+ {
+ return (1); /* character available */
+ }
+}
+
+/*@} end of CMSIS_core_DebugFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM7_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_sc000.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_sc000.h
new file mode 100644
index 0000000..9b67c92
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_sc000.h
@@ -0,0 +1,1022 @@
+/**************************************************************************//**
+ * @file core_sc000.h
+ * @brief CMSIS SC000 Core Peripheral Access Layer Header File
+ * @version V5.0.5
+ * @date 28. May 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_SC000_H_GENERIC
+#define __CORE_SC000_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup SC000
+ @{
+ */
+
+#include "cmsis_version.h"
+
+/* CMSIS SC000 definitions */
+#define __SC000_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __SC000_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __SC000_CMSIS_VERSION ((__SC000_CMSIS_VERSION_MAIN << 16U) | \
+ __SC000_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_SC (000U) /*!< Cortex secure core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ This core does not support an FPU at all
+*/
+#define __FPU_USED 0U
+
+#if defined ( __CC_ARM )
+ #if defined __TARGET_FPU_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_PCS_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined __ARMVFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined __TI_VFP_SUPPORT__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined __FPU_VFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_SC000_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_SC000_H_DEPENDANT
+#define __CORE_SC000_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __SC000_REV
+ #define __SC000_REV 0x0000U
+ #warning "__SC000_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MPU_PRESENT
+ #define __MPU_PRESENT 0U
+ #warning "__MPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 2U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group SC000 */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ - Core MPU Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
+ uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:1; /*!< bit: 0 Reserved */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
+ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[31U];
+ __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[31U];
+ __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[31U];
+ __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[31U];
+ uint32_t RESERVED4[64U];
+ __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
+} NVIC_Type;
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ uint32_t RESERVED0[1U];
+ __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+ uint32_t RESERVED1[154U];
+ __IOM uint32_t SFCR; /*!< Offset: 0x290 (R/W) Security Features Control Register */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */
+#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */
+#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB)
+ \brief Type definitions for the System Control and ID Register not in the SCB
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control and ID Register not in the SCB.
+ */
+typedef struct
+{
+ uint32_t RESERVED0[2U];
+ __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */
+} SCnSCB_Type;
+
+/* Auxiliary Control Register Definitions */
+#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */
+#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */
+
+/*@} end of group CMSIS_SCnotSCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_MPU Memory Protection Unit (MPU)
+ \brief Type definitions for the Memory Protection Unit (MPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+ __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
+ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
+ __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */
+} MPU_Type;
+
+/* MPU Type Register Definitions */
+#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register Definitions */
+#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register Definitions */
+#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register Definitions */
+#define MPU_RBAR_ADDR_Pos 8U /*!< MPU RBAR: ADDR Position */
+#define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */
+
+#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */
+#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */
+
+#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */
+#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */
+
+/* MPU Region Attribute and Size Register Definitions */
+#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */
+#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */
+
+#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */
+#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */
+
+#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */
+#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */
+
+#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */
+#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */
+
+#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */
+#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */
+
+#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */
+#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */
+
+#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */
+#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */
+
+#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */
+#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */
+
+#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */
+#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */
+
+#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */
+#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief SC000 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor.
+ Therefore they are not covered by the SC000 header file.
+ @{
+ */
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */
+#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
+ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
+#endif
+
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+/*#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping not available for SC000 */
+/*#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping not available for SC000 */
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+/*#define NVIC_GetActive __NVIC_GetActive not available for SC000 */
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* The following EXC_RETURN values are saved the LR on exception entry */
+#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */
+#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */
+#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */
+
+
+/* Interrupt Priorities are WORD accessible only under Armv6-M */
+/* The following MACROS handle generation of the register offset and byte masks */
+#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
+#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) )
+#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
+
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+ else
+ {
+ SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ SCB_AIRCR_SYSRESETREQ_Msk);
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ return 0U; /* No FPU */
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_SC000_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_sc300.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_sc300.h
new file mode 100644
index 0000000..3e8a471
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/core_sc300.h
@@ -0,0 +1,1915 @@
+/**************************************************************************//**
+ * @file core_sc300.h
+ * @brief CMSIS SC300 Core Peripheral Access Layer Header File
+ * @version V5.0.6
+ * @date 04. June 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_SC300_H_GENERIC
+#define __CORE_SC300_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup SC3000
+ @{
+ */
+
+#include "cmsis_version.h"
+
+/* CMSIS SC300 definitions */
+#define __SC300_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __SC300_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __SC300_CMSIS_VERSION ((__SC300_CMSIS_VERSION_MAIN << 16U) | \
+ __SC300_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_SC (300U) /*!< Cortex secure core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ This core does not support an FPU at all
+*/
+#define __FPU_USED 0U
+
+#if defined ( __CC_ARM )
+ #if defined __TARGET_FPU_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_PCS_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined __ARMVFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined __TI_VFP_SUPPORT__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined __FPU_VFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_SC300_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_SC300_H_DEPENDANT
+#define __CORE_SC300_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __SC300_REV
+ #define __SC300_REV 0x0000U
+ #warning "__SC300_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MPU_PRESENT
+ #define __MPU_PRESENT 0U
+ #warning "__MPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 3U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group SC300 */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ - Core Debug Register
+ - Core MPU Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+#define APSR_Q_Pos 27U /*!< APSR: Q Position */
+#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:1; /*!< bit: 9 Reserved */
+ uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */
+ uint32_t _reserved1:8; /*!< bit: 16..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit */
+ uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */
+#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */
+
+#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */
+#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */
+#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
+ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */
+#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[24U];
+ __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[24U];
+ __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[24U];
+ __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[24U];
+ __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
+ uint32_t RESERVED4[56U];
+ __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
+ uint32_t RESERVED5[644U];
+ __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
+} NVIC_Type;
+
+/* Software Triggered Interrupt Register Definitions */
+#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */
+#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+ __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */
+ __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */
+ __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */
+ __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */
+ __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */
+ __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */
+ __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */
+ __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */
+ __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */
+ __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */
+ __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */
+ uint32_t RESERVED0[5U];
+ __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */
+ uint32_t RESERVED1[129U];
+ __IOM uint32_t SFCR; /*!< Offset: 0x290 (R/W) Security Features Control Register */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */
+#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */
+#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+/* SCB Vector Table Offset Register Definitions */
+#define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */
+#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */
+
+#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */
+#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */
+#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */
+#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
+
+#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */
+#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */
+
+#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */
+#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */
+#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */
+
+#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */
+#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */
+#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */
+
+#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */
+#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */
+
+#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */
+#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */
+
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */
+#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */
+
+#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */
+#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */
+
+#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */
+#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */
+
+#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */
+#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */
+
+#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */
+#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */
+
+#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */
+#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */
+
+#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */
+#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */
+
+#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */
+#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */
+
+#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */
+#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */
+
+#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */
+#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */
+
+/* SCB Configurable Fault Status Register Definitions */
+#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */
+#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */
+
+#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */
+#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */
+
+#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */
+#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */
+
+/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */
+#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */
+
+#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */
+#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */
+
+#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */
+#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */
+
+#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */
+#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */
+
+#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */
+#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */
+
+/* BusFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */
+#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */
+
+#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */
+#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */
+
+#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */
+#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */
+
+#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */
+#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */
+
+#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */
+#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */
+
+#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */
+#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */
+
+/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */
+#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */
+
+#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */
+#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */
+
+#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */
+#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */
+
+#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */
+#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */
+
+#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */
+#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */
+
+#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */
+#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */
+
+/* SCB Hard Fault Status Register Definitions */
+#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */
+#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */
+
+#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */
+#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */
+
+#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */
+#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */
+
+/* SCB Debug Fault Status Register Definitions */
+#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */
+#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */
+
+#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */
+#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */
+
+#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */
+#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */
+
+#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */
+#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */
+
+#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */
+#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB)
+ \brief Type definitions for the System Control and ID Register not in the SCB
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control and ID Register not in the SCB.
+ */
+typedef struct
+{
+ uint32_t RESERVED0[1U];
+ __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */
+ uint32_t RESERVED1[1U];
+} SCnSCB_Type;
+
+/* Interrupt Controller Type Register Definitions */
+#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */
+#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_SCnotSCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM)
+ \brief Type definitions for the Instrumentation Trace Macrocell (ITM)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM).
+ */
+typedef struct
+{
+ __OM union
+ {
+ __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */
+ __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */
+ __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */
+ } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */
+ uint32_t RESERVED0[864U];
+ __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */
+ uint32_t RESERVED1[15U];
+ __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */
+ uint32_t RESERVED2[15U];
+ __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */
+ uint32_t RESERVED3[29U];
+ __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */
+ __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */
+ __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */
+ uint32_t RESERVED4[43U];
+ __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */
+ uint32_t RESERVED5[6U];
+ __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */
+ __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */
+ __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */
+ __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */
+ __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */
+ __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */
+ __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */
+ __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */
+ __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */
+ __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */
+ __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */
+ __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */
+} ITM_Type;
+
+/* ITM Trace Privilege Register Definitions */
+#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */
+#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */
+
+/* ITM Trace Control Register Definitions */
+#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */
+#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */
+
+#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */
+#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */
+
+#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */
+#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */
+
+#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */
+#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */
+
+#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */
+#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */
+
+#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */
+#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */
+
+#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */
+#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */
+
+#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */
+#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */
+
+#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */
+#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */
+
+/* ITM Integration Write Register Definitions */
+#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */
+#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */
+
+/* ITM Integration Read Register Definitions */
+#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */
+#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */
+
+/* ITM Integration Mode Control Register Definitions */
+#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */
+#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */
+
+/* ITM Lock Status Register Definitions */
+#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */
+#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */
+
+#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */
+#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */
+
+#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */
+#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */
+
+/*@}*/ /* end of group CMSIS_ITM */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT)
+ \brief Type definitions for the Data Watchpoint and Trace (DWT)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Data Watchpoint and Trace Register (DWT).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */
+ __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */
+ __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */
+ __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */
+ __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */
+ __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */
+ __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */
+ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */
+ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */
+ __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */
+ __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */
+ uint32_t RESERVED0[1U];
+ __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */
+ __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */
+ __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */
+ uint32_t RESERVED1[1U];
+ __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */
+ __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */
+ __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */
+ uint32_t RESERVED2[1U];
+ __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */
+ __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */
+ __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */
+} DWT_Type;
+
+/* DWT Control Register Definitions */
+#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */
+#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */
+
+#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */
+#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */
+
+#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */
+#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */
+
+#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */
+#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */
+
+#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */
+#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */
+
+#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */
+#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */
+
+#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */
+#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */
+
+#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */
+#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */
+
+#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */
+#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */
+
+#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */
+#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */
+
+#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */
+#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */
+
+#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */
+#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */
+
+#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */
+#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */
+
+#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */
+#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */
+
+#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */
+#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */
+
+#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */
+#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */
+
+#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */
+#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */
+
+#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */
+#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */
+
+/* DWT CPI Count Register Definitions */
+#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */
+#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */
+
+/* DWT Exception Overhead Count Register Definitions */
+#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */
+#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */
+
+/* DWT Sleep Count Register Definitions */
+#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */
+#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */
+
+/* DWT LSU Count Register Definitions */
+#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */
+#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */
+
+/* DWT Folded-instruction Count Register Definitions */
+#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */
+#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */
+
+/* DWT Comparator Mask Register Definitions */
+#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */
+#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */
+
+/* DWT Comparator Function Register Definitions */
+#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */
+#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */
+
+#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */
+#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */
+
+#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */
+#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */
+
+#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */
+#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */
+
+#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */
+#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */
+
+#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */
+#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */
+
+#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */
+#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */
+
+#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */
+#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */
+
+#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */
+#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */
+
+/*@}*/ /* end of group CMSIS_DWT */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_TPI Trace Port Interface (TPI)
+ \brief Type definitions for the Trace Port Interface (TPI)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Trace Port Interface Register (TPI).
+ */
+typedef struct
+{
+ __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */
+ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */
+ uint32_t RESERVED0[2U];
+ __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */
+ uint32_t RESERVED1[55U];
+ __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */
+ uint32_t RESERVED2[131U];
+ __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */
+ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */
+ __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */
+ uint32_t RESERVED3[759U];
+ __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */
+ __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */
+ __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */
+ uint32_t RESERVED4[1U];
+ __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */
+ __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */
+ __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */
+ uint32_t RESERVED5[39U];
+ __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */
+ __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */
+ uint32_t RESERVED7[8U];
+ __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */
+ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */
+} TPI_Type;
+
+/* TPI Asynchronous Clock Prescaler Register Definitions */
+#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */
+#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */
+
+/* TPI Selected Pin Protocol Register Definitions */
+#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */
+#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */
+
+/* TPI Formatter and Flush Status Register Definitions */
+#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */
+#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */
+
+#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */
+#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */
+
+#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */
+#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */
+
+#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */
+#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */
+
+/* TPI Formatter and Flush Control Register Definitions */
+#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */
+#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */
+
+#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */
+#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */
+
+/* TPI TRIGGER Register Definitions */
+#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */
+#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */
+
+/* TPI Integration ETM Data Register Definitions (FIFO0) */
+#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */
+#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */
+
+#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */
+#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */
+
+#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */
+#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */
+
+#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */
+#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */
+
+#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */
+#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */
+
+#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */
+#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */
+
+#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */
+#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */
+
+/* TPI ITATBCTR2 Register Definitions */
+#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */
+#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */
+
+#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */
+#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */
+
+/* TPI Integration ITM Data Register Definitions (FIFO1) */
+#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */
+#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */
+
+#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */
+#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */
+
+#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */
+#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */
+
+#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */
+#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */
+
+#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */
+#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */
+
+#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */
+#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */
+
+#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */
+#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */
+
+/* TPI ITATBCTR0 Register Definitions */
+#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */
+#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */
+
+#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */
+#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */
+
+/* TPI Integration Mode Control Register Definitions */
+#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */
+#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */
+
+/* TPI DEVID Register Definitions */
+#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */
+#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */
+
+#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */
+#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */
+
+#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */
+#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */
+
+#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */
+#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */
+
+#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */
+#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */
+
+#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */
+#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */
+
+/* TPI DEVTYPE Register Definitions */
+#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */
+
+#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
+
+/*@}*/ /* end of group CMSIS_TPI */
+
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_MPU Memory Protection Unit (MPU)
+ \brief Type definitions for the Memory Protection Unit (MPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+ __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
+ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
+ __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */
+ __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */
+ __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */
+ __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */
+ __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */
+ __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */
+ __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */
+} MPU_Type;
+
+/* MPU Type Register Definitions */
+#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register Definitions */
+#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register Definitions */
+#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register Definitions */
+#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */
+#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */
+
+#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */
+#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */
+
+#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */
+#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */
+
+/* MPU Region Attribute and Size Register Definitions */
+#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */
+#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */
+
+#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */
+#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */
+
+#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */
+#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */
+
+#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */
+#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */
+
+#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */
+#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */
+
+#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */
+#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */
+
+#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */
+#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */
+
+#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */
+#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */
+
+#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */
+#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */
+
+#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */
+#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Type definitions for the Core Debug Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Core Debug Register (CoreDebug).
+ */
+typedef struct
+{
+ __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */
+ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */
+ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */
+ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */
+} CoreDebug_Type;
+
+/* Debug Halting Control and Status Register Definitions */
+#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */
+#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */
+
+#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */
+#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */
+
+#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */
+#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */
+
+#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */
+#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */
+
+#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */
+#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */
+
+#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */
+#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */
+
+#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */
+#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */
+
+#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */
+#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */
+
+#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */
+#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */
+
+#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */
+#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */
+
+#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */
+#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */
+
+#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */
+#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */
+
+/* Debug Core Register Selector Register Definitions */
+#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */
+#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */
+
+#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */
+#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */
+
+/* Debug Exception and Monitor Control Register Definitions */
+#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */
+#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */
+
+#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */
+#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */
+
+#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */
+#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */
+
+#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */
+#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */
+
+#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */
+#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */
+
+#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */
+#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */
+
+#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */
+#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */
+
+#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */
+#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */
+
+#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */
+#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */
+
+#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */
+#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */
+
+#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */
+#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */
+
+#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */
+#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */
+
+#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */
+#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */
+
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */
+#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
+#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */
+#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */
+#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */
+#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */
+#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */
+#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */
+#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
+ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
+#endif
+
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Debug Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+ #define NVIC_GetActive __NVIC_GetActive
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* The following EXC_RETURN values are saved the LR on exception entry */
+#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */
+#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */
+#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */
+
+
+
+/**
+ \brief Set Priority Grouping
+ \details Sets the priority grouping field using the required unlock sequence.
+ The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
+ Only values from 0..7 are used.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Priority grouping field.
+ */
+__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
+{
+ uint32_t reg_value;
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+
+ reg_value = SCB->AIRCR; /* read old register configuration */
+ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
+ reg_value = (reg_value |
+ ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */
+ SCB->AIRCR = reg_value;
+}
+
+
+/**
+ \brief Get Priority Grouping
+ \details Reads the priority grouping field from the NVIC Interrupt Controller.
+ \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void)
+{
+ return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
+}
+
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt
+ \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+ else
+ {
+ SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
+ SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ return 0U; /* No FPU */
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+/* ##################################### Debug In/Output function ########################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_core_DebugFunctions ITM Functions
+ \brief Functions that access the ITM debug interface.
+ @{
+ */
+
+extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */
+#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
+
+
+/**
+ \brief ITM Send Character
+ \details Transmits a character via the ITM channel 0, and
+ \li Just returns when no debugger is connected that has booked the output.
+ \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted.
+ \param [in] ch Character to transmit.
+ \returns Character to transmit.
+ */
+__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch)
+{
+ if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */
+ ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */
+ {
+ while (ITM->PORT[0U].u32 == 0UL)
+ {
+ __NOP();
+ }
+ ITM->PORT[0U].u8 = (uint8_t)ch;
+ }
+ return (ch);
+}
+
+
+/**
+ \brief ITM Receive Character
+ \details Inputs a character via the external variable \ref ITM_RxBuffer.
+ \return Received character.
+ \return -1 No character pending.
+ */
+__STATIC_INLINE int32_t ITM_ReceiveChar (void)
+{
+ int32_t ch = -1; /* no character available */
+
+ if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY)
+ {
+ ch = ITM_RxBuffer;
+ ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */
+ }
+
+ return (ch);
+}
+
+
+/**
+ \brief ITM Check Character
+ \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer.
+ \return 0 No character available.
+ \return 1 Character available.
+ */
+__STATIC_INLINE int32_t ITM_CheckChar (void)
+{
+
+ if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY)
+ {
+ return (0); /* no character available */
+ }
+ else
+ {
+ return (1); /* character available */
+ }
+}
+
+/*@} end of CMSIS_core_DebugFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_SC300_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/mpu_armv7.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/mpu_armv7.h
new file mode 100644
index 0000000..0142203
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/mpu_armv7.h
@@ -0,0 +1,270 @@
+/******************************************************************************
+ * @file mpu_armv7.h
+ * @brief CMSIS MPU API for Armv7-M MPU
+ * @version V5.0.4
+ * @date 10. January 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2017-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef ARM_MPU_ARMV7_H
+#define ARM_MPU_ARMV7_H
+
+#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes
+#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes
+#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes
+#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes
+#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes
+#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte
+#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes
+#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes
+#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes
+#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes
+#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes
+#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes
+#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes
+#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes
+#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes
+#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte
+#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes
+#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes
+#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes
+#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes
+#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes
+#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes
+#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes
+#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes
+#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes
+#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte
+#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes
+#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes
+
+#define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access
+#define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only
+#define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only
+#define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access
+#define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only
+#define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access
+
+/** MPU Region Base Address Register Value
+*
+* \param Region The region to be configured, number 0 to 15.
+* \param BaseAddress The base address for the region.
+*/
+#define ARM_MPU_RBAR(Region, BaseAddress) \
+ (((BaseAddress) & MPU_RBAR_ADDR_Msk) | \
+ ((Region) & MPU_RBAR_REGION_Msk) | \
+ (MPU_RBAR_VALID_Msk))
+
+/**
+* MPU Memory Access Attributes
+*
+* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
+* \param IsShareable Region is shareable between multiple bus masters.
+* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
+* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
+*/
+#define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \
+ ((((TypeExtField ) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \
+ (((IsShareable ) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \
+ (((IsCacheable ) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \
+ (((IsBufferable ) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk))
+
+/**
+* MPU Region Attribute and Size Register Value
+*
+* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
+* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
+* \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_.
+* \param SubRegionDisable Sub-region disable field.
+* \param Size Region size of the region to be configured, for example 4K, 8K.
+*/
+#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \
+ ((((DisableExec ) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \
+ (((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \
+ (((AccessAttributes) ) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk)))
+
+/**
+* MPU Region Attribute and Size Register Value
+*
+* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
+* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
+* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
+* \param IsShareable Region is shareable between multiple bus masters.
+* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
+* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
+* \param SubRegionDisable Sub-region disable field.
+* \param Size Region size of the region to be configured, for example 4K, 8K.
+*/
+#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \
+ ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size)
+
+/**
+* MPU Memory Access Attribute for strongly ordered memory.
+* - TEX: 000b
+* - Shareable
+* - Non-cacheable
+* - Non-bufferable
+*/
+#define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U)
+
+/**
+* MPU Memory Access Attribute for device memory.
+* - TEX: 000b (if non-shareable) or 010b (if shareable)
+* - Shareable or non-shareable
+* - Non-cacheable
+* - Bufferable (if shareable) or non-bufferable (if non-shareable)
+*
+* \param IsShareable Configures the device memory as shareable or non-shareable.
+*/
+#define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U))
+
+/**
+* MPU Memory Access Attribute for normal memory.
+* - TEX: 1BBb (reflecting outer cacheability rules)
+* - Shareable or non-shareable
+* - Cacheable or non-cacheable (reflecting inner cacheability rules)
+* - Bufferable or non-bufferable (reflecting inner cacheability rules)
+*
+* \param OuterCp Configures the outer cache policy.
+* \param InnerCp Configures the inner cache policy.
+* \param IsShareable Configures the memory as shareable or non-shareable.
+*/
+#define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) & 2U), ((InnerCp) & 1U))
+
+/**
+* MPU Memory Access Attribute non-cacheable policy.
+*/
+#define ARM_MPU_CACHEP_NOCACHE 0U
+
+/**
+* MPU Memory Access Attribute write-back, write and read allocate policy.
+*/
+#define ARM_MPU_CACHEP_WB_WRA 1U
+
+/**
+* MPU Memory Access Attribute write-through, no write allocate policy.
+*/
+#define ARM_MPU_CACHEP_WT_NWA 2U
+
+/**
+* MPU Memory Access Attribute write-back, no write allocate policy.
+*/
+#define ARM_MPU_CACHEP_WB_NWA 3U
+
+
+/**
+* Struct for a single MPU Region
+*/
+typedef struct {
+ uint32_t RBAR; //!< The region base address register value (RBAR)
+ uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR
+} ARM_MPU_Region_t;
+
+/** Enable the MPU.
+* \param MPU_Control Default access permissions for unconfigured regions.
+*/
+__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control)
+{
+ __DSB();
+ __ISB();
+ MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
+#ifdef SCB_SHCSR_MEMFAULTENA_Msk
+ SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
+#endif
+}
+
+/** Disable the MPU.
+*/
+__STATIC_INLINE void ARM_MPU_Disable(void)
+{
+ __DSB();
+ __ISB();
+#ifdef SCB_SHCSR_MEMFAULTENA_Msk
+ SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
+#endif
+ MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
+}
+
+/** Clear and disable the given MPU region.
+* \param rnr Region number to be cleared.
+*/
+__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr)
+{
+ MPU->RNR = rnr;
+ MPU->RASR = 0U;
+}
+
+/** Configure an MPU region.
+* \param rbar Value for RBAR register.
+* \param rsar Value for RSAR register.
+*/
+__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr)
+{
+ MPU->RBAR = rbar;
+ MPU->RASR = rasr;
+}
+
+/** Configure the given MPU region.
+* \param rnr Region number to be configured.
+* \param rbar Value for RBAR register.
+* \param rsar Value for RSAR register.
+*/
+__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr)
+{
+ MPU->RNR = rnr;
+ MPU->RBAR = rbar;
+ MPU->RASR = rasr;
+}
+
+/** Memcopy with strictly ordered memory access, e.g. for register targets.
+* \param dst Destination data is copied to.
+* \param src Source data is copied from.
+* \param len Amount of data words to be copied.
+*/
+__STATIC_INLINE void orderedCpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len)
+{
+ uint32_t i;
+ for (i = 0U; i < len; ++i)
+ {
+ dst[i] = src[i];
+ }
+}
+
+/** Load the given number of MPU regions from a table.
+* \param table Pointer to the MPU configuration table.
+* \param cnt Amount of regions to be configured.
+*/
+__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt)
+{
+ const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U;
+ while (cnt > MPU_TYPE_RALIASES) {
+ orderedCpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize);
+ table += MPU_TYPE_RALIASES;
+ cnt -= MPU_TYPE_RALIASES;
+ }
+ orderedCpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize);
+}
+
+#endif
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/mpu_armv8.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/mpu_armv8.h
new file mode 100644
index 0000000..62571da
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/mpu_armv8.h
@@ -0,0 +1,333 @@
+/******************************************************************************
+ * @file mpu_armv8.h
+ * @brief CMSIS MPU API for Armv8-M MPU
+ * @version V5.0.4
+ * @date 10. January 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2017-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef ARM_MPU_ARMV8_H
+#define ARM_MPU_ARMV8_H
+
+/** \brief Attribute for device memory (outer only) */
+#define ARM_MPU_ATTR_DEVICE ( 0U )
+
+/** \brief Attribute for non-cacheable, normal memory */
+#define ARM_MPU_ATTR_NON_CACHEABLE ( 4U )
+
+/** \brief Attribute for normal memory (outer and inner)
+* \param NT Non-Transient: Set to 1 for non-transient data.
+* \param WB Write-Back: Set to 1 to use write-back update policy.
+* \param RA Read Allocation: Set to 1 to use cache allocation on read miss.
+* \param WA Write Allocation: Set to 1 to use cache allocation on write miss.
+*/
+#define ARM_MPU_ATTR_MEMORY_(NT, WB, RA, WA) \
+ (((NT & 1U) << 3U) | ((WB & 1U) << 2U) | ((RA & 1U) << 1U) | (WA & 1U))
+
+/** \brief Device memory type non Gathering, non Re-ordering, non Early Write Acknowledgement */
+#define ARM_MPU_ATTR_DEVICE_nGnRnE (0U)
+
+/** \brief Device memory type non Gathering, non Re-ordering, Early Write Acknowledgement */
+#define ARM_MPU_ATTR_DEVICE_nGnRE (1U)
+
+/** \brief Device memory type non Gathering, Re-ordering, Early Write Acknowledgement */
+#define ARM_MPU_ATTR_DEVICE_nGRE (2U)
+
+/** \brief Device memory type Gathering, Re-ordering, Early Write Acknowledgement */
+#define ARM_MPU_ATTR_DEVICE_GRE (3U)
+
+/** \brief Memory Attribute
+* \param O Outer memory attributes
+* \param I O == ARM_MPU_ATTR_DEVICE: Device memory attributes, else: Inner memory attributes
+*/
+#define ARM_MPU_ATTR(O, I) (((O & 0xFU) << 4U) | (((O & 0xFU) != 0U) ? (I & 0xFU) : ((I & 0x3U) << 2U)))
+
+/** \brief Normal memory non-shareable */
+#define ARM_MPU_SH_NON (0U)
+
+/** \brief Normal memory outer shareable */
+#define ARM_MPU_SH_OUTER (2U)
+
+/** \brief Normal memory inner shareable */
+#define ARM_MPU_SH_INNER (3U)
+
+/** \brief Memory access permissions
+* \param RO Read-Only: Set to 1 for read-only memory.
+* \param NP Non-Privileged: Set to 1 for non-privileged memory.
+*/
+#define ARM_MPU_AP_(RO, NP) (((RO & 1U) << 1U) | (NP & 1U))
+
+/** \brief Region Base Address Register value
+* \param BASE The base address bits [31:5] of a memory region. The value is zero extended. Effective address gets 32 byte aligned.
+* \param SH Defines the Shareability domain for this memory region.
+* \param RO Read-Only: Set to 1 for a read-only memory region.
+* \param NP Non-Privileged: Set to 1 for a non-privileged memory region.
+* \oaram XN eXecute Never: Set to 1 for a non-executable memory region.
+*/
+#define ARM_MPU_RBAR(BASE, SH, RO, NP, XN) \
+ ((BASE & MPU_RBAR_BASE_Msk) | \
+ ((SH << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk) | \
+ ((ARM_MPU_AP_(RO, NP) << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk) | \
+ ((XN << MPU_RBAR_XN_Pos) & MPU_RBAR_XN_Msk))
+
+/** \brief Region Limit Address Register value
+* \param LIMIT The limit address bits [31:5] for this memory region. The value is one extended.
+* \param IDX The attribute index to be associated with this memory region.
+*/
+#define ARM_MPU_RLAR(LIMIT, IDX) \
+ ((LIMIT & MPU_RLAR_LIMIT_Msk) | \
+ ((IDX << MPU_RLAR_AttrIndx_Pos) & MPU_RLAR_AttrIndx_Msk) | \
+ (MPU_RLAR_EN_Msk))
+
+/**
+* Struct for a single MPU Region
+*/
+typedef struct {
+ uint32_t RBAR; /*!< Region Base Address Register value */
+ uint32_t RLAR; /*!< Region Limit Address Register value */
+} ARM_MPU_Region_t;
+
+/** Enable the MPU.
+* \param MPU_Control Default access permissions for unconfigured regions.
+*/
+__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control)
+{
+ __DSB();
+ __ISB();
+ MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
+#ifdef SCB_SHCSR_MEMFAULTENA_Msk
+ SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
+#endif
+}
+
+/** Disable the MPU.
+*/
+__STATIC_INLINE void ARM_MPU_Disable(void)
+{
+ __DSB();
+ __ISB();
+#ifdef SCB_SHCSR_MEMFAULTENA_Msk
+ SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
+#endif
+ MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
+}
+
+#ifdef MPU_NS
+/** Enable the Non-secure MPU.
+* \param MPU_Control Default access permissions for unconfigured regions.
+*/
+__STATIC_INLINE void ARM_MPU_Enable_NS(uint32_t MPU_Control)
+{
+ __DSB();
+ __ISB();
+ MPU_NS->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
+#ifdef SCB_SHCSR_MEMFAULTENA_Msk
+ SCB_NS->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
+#endif
+}
+
+/** Disable the Non-secure MPU.
+*/
+__STATIC_INLINE void ARM_MPU_Disable_NS(void)
+{
+ __DSB();
+ __ISB();
+#ifdef SCB_SHCSR_MEMFAULTENA_Msk
+ SCB_NS->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
+#endif
+ MPU_NS->CTRL &= ~MPU_CTRL_ENABLE_Msk;
+}
+#endif
+
+/** Set the memory attribute encoding to the given MPU.
+* \param mpu Pointer to the MPU to be configured.
+* \param idx The attribute index to be set [0-7]
+* \param attr The attribute value to be set.
+*/
+__STATIC_INLINE void ARM_MPU_SetMemAttrEx(MPU_Type* mpu, uint8_t idx, uint8_t attr)
+{
+ const uint8_t reg = idx / 4U;
+ const uint32_t pos = ((idx % 4U) * 8U);
+ const uint32_t mask = 0xFFU << pos;
+
+ if (reg >= (sizeof(mpu->MAIR) / sizeof(mpu->MAIR[0]))) {
+ return; // invalid index
+ }
+
+ mpu->MAIR[reg] = ((mpu->MAIR[reg] & ~mask) | ((attr << pos) & mask));
+}
+
+/** Set the memory attribute encoding.
+* \param idx The attribute index to be set [0-7]
+* \param attr The attribute value to be set.
+*/
+__STATIC_INLINE void ARM_MPU_SetMemAttr(uint8_t idx, uint8_t attr)
+{
+ ARM_MPU_SetMemAttrEx(MPU, idx, attr);
+}
+
+#ifdef MPU_NS
+/** Set the memory attribute encoding to the Non-secure MPU.
+* \param idx The attribute index to be set [0-7]
+* \param attr The attribute value to be set.
+*/
+__STATIC_INLINE void ARM_MPU_SetMemAttr_NS(uint8_t idx, uint8_t attr)
+{
+ ARM_MPU_SetMemAttrEx(MPU_NS, idx, attr);
+}
+#endif
+
+/** Clear and disable the given MPU region of the given MPU.
+* \param mpu Pointer to MPU to be used.
+* \param rnr Region number to be cleared.
+*/
+__STATIC_INLINE void ARM_MPU_ClrRegionEx(MPU_Type* mpu, uint32_t rnr)
+{
+ mpu->RNR = rnr;
+ mpu->RLAR = 0U;
+}
+
+/** Clear and disable the given MPU region.
+* \param rnr Region number to be cleared.
+*/
+__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr)
+{
+ ARM_MPU_ClrRegionEx(MPU, rnr);
+}
+
+#ifdef MPU_NS
+/** Clear and disable the given Non-secure MPU region.
+* \param rnr Region number to be cleared.
+*/
+__STATIC_INLINE void ARM_MPU_ClrRegion_NS(uint32_t rnr)
+{
+ ARM_MPU_ClrRegionEx(MPU_NS, rnr);
+}
+#endif
+
+/** Configure the given MPU region of the given MPU.
+* \param mpu Pointer to MPU to be used.
+* \param rnr Region number to be configured.
+* \param rbar Value for RBAR register.
+* \param rlar Value for RLAR register.
+*/
+__STATIC_INLINE void ARM_MPU_SetRegionEx(MPU_Type* mpu, uint32_t rnr, uint32_t rbar, uint32_t rlar)
+{
+ mpu->RNR = rnr;
+ mpu->RBAR = rbar;
+ mpu->RLAR = rlar;
+}
+
+/** Configure the given MPU region.
+* \param rnr Region number to be configured.
+* \param rbar Value for RBAR register.
+* \param rlar Value for RLAR register.
+*/
+__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rnr, uint32_t rbar, uint32_t rlar)
+{
+ ARM_MPU_SetRegionEx(MPU, rnr, rbar, rlar);
+}
+
+#ifdef MPU_NS
+/** Configure the given Non-secure MPU region.
+* \param rnr Region number to be configured.
+* \param rbar Value for RBAR register.
+* \param rlar Value for RLAR register.
+*/
+__STATIC_INLINE void ARM_MPU_SetRegion_NS(uint32_t rnr, uint32_t rbar, uint32_t rlar)
+{
+ ARM_MPU_SetRegionEx(MPU_NS, rnr, rbar, rlar);
+}
+#endif
+
+/** Memcopy with strictly ordered memory access, e.g. for register targets.
+* \param dst Destination data is copied to.
+* \param src Source data is copied from.
+* \param len Amount of data words to be copied.
+*/
+__STATIC_INLINE void orderedCpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len)
+{
+ uint32_t i;
+ for (i = 0U; i < len; ++i)
+ {
+ dst[i] = src[i];
+ }
+}
+
+/** Load the given number of MPU regions from a table to the given MPU.
+* \param mpu Pointer to the MPU registers to be used.
+* \param rnr First region number to be configured.
+* \param table Pointer to the MPU configuration table.
+* \param cnt Amount of regions to be configured.
+*/
+__STATIC_INLINE void ARM_MPU_LoadEx(MPU_Type* mpu, uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt)
+{
+ const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U;
+ if (cnt == 1U) {
+ mpu->RNR = rnr;
+ orderedCpy(&(mpu->RBAR), &(table->RBAR), rowWordSize);
+ } else {
+ uint32_t rnrBase = rnr & ~(MPU_TYPE_RALIASES-1U);
+ uint32_t rnrOffset = rnr % MPU_TYPE_RALIASES;
+
+ mpu->RNR = rnrBase;
+ while ((rnrOffset + cnt) > MPU_TYPE_RALIASES) {
+ uint32_t c = MPU_TYPE_RALIASES - rnrOffset;
+ orderedCpy(&(mpu->RBAR)+(rnrOffset*2U), &(table->RBAR), c*rowWordSize);
+ table += c;
+ cnt -= c;
+ rnrOffset = 0U;
+ rnrBase += MPU_TYPE_RALIASES;
+ mpu->RNR = rnrBase;
+ }
+
+ orderedCpy(&(mpu->RBAR)+(rnrOffset*2U), &(table->RBAR), cnt*rowWordSize);
+ }
+}
+
+/** Load the given number of MPU regions from a table.
+* \param rnr First region number to be configured.
+* \param table Pointer to the MPU configuration table.
+* \param cnt Amount of regions to be configured.
+*/
+__STATIC_INLINE void ARM_MPU_Load(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt)
+{
+ ARM_MPU_LoadEx(MPU, rnr, table, cnt);
+}
+
+#ifdef MPU_NS
+/** Load the given number of MPU regions from a table to the Non-secure MPU.
+* \param rnr First region number to be configured.
+* \param table Pointer to the MPU configuration table.
+* \param cnt Amount of regions to be configured.
+*/
+__STATIC_INLINE void ARM_MPU_Load_NS(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt)
+{
+ ARM_MPU_LoadEx(MPU_NS, rnr, table, cnt);
+}
+#endif
+
+#endif
+
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/tz_context.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/tz_context.h
new file mode 100644
index 0000000..0d09749
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core/Include/tz_context.h
@@ -0,0 +1,70 @@
+/******************************************************************************
+ * @file tz_context.h
+ * @brief Context Management for Armv8-M TrustZone
+ * @version V1.0.1
+ * @date 10. January 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2017-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef TZ_CONTEXT_H
+#define TZ_CONTEXT_H
+
+#include
+
+#ifndef TZ_MODULEID_T
+#define TZ_MODULEID_T
+/// \details Data type that identifies secure software modules called by a process.
+typedef uint32_t TZ_ModuleId_t;
+#endif
+
+/// \details TZ Memory ID identifies an allocated memory slot.
+typedef uint32_t TZ_MemoryId_t;
+
+/// Initialize secure context memory system
+/// \return execution status (1: success, 0: error)
+uint32_t TZ_InitContextSystem_S (void);
+
+/// Allocate context memory for calling secure software modules in TrustZone
+/// \param[in] module identifies software modules called from non-secure mode
+/// \return value != 0 id TrustZone memory slot identifier
+/// \return value 0 no memory available or internal error
+TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module);
+
+/// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S
+/// \param[in] id TrustZone memory slot identifier
+/// \return execution status (1: success, 0: error)
+uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id);
+
+/// Load secure context (called on RTOS thread context switch)
+/// \param[in] id TrustZone memory slot identifier
+/// \return execution status (1: success, 0: error)
+uint32_t TZ_LoadContext_S (TZ_MemoryId_t id);
+
+/// Store secure context (called on RTOS thread context switch)
+/// \param[in] id TrustZone memory slot identifier
+/// \return execution status (1: success, 0: error)
+uint32_t TZ_StoreContext_S (TZ_MemoryId_t id);
+
+#endif // TZ_CONTEXT_H
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/ARMCA5.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/ARMCA5.h
new file mode 100644
index 0000000..70002a7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/ARMCA5.h
@@ -0,0 +1,135 @@
+/******************************************************************************
+ * @file ARMCA5.h
+ * @brief CMSIS Cortex-A5 Core Peripheral Access Layer Header File
+ * @version V1.00
+ * @data 16 Mar 2017
+ *
+ * @note
+ *
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ARMCA5_H__
+#define __ARMCA5_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* ------------------------- Interrupt Number Definition ------------------------ */
+
+typedef enum IRQn
+{
+/****** SGI Interrupts Numbers ****************************************/
+ SGI0_IRQn = 0,
+ SGI1_IRQn = 1,
+ SGI2_IRQn = 2,
+ SGI3_IRQn = 3,
+ SGI4_IRQn = 4,
+ SGI5_IRQn = 5,
+ SGI6_IRQn = 6,
+ SGI7_IRQn = 7,
+ SGI8_IRQn = 8,
+ SGI9_IRQn = 9,
+ SGI10_IRQn = 10,
+ SGI11_IRQn = 11,
+ SGI12_IRQn = 12,
+ SGI13_IRQn = 13,
+ SGI14_IRQn = 14,
+ SGI15_IRQn = 15,
+
+/****** Cortex-A5 Processor Exceptions Numbers ****************************************/
+ GlobalTimer_IRQn = 27, /*!< Global Timer Interrupt */
+ PrivTimer_IRQn = 29, /*!< Private Timer Interrupt */
+ PrivWatchdog_IRQn = 30, /*!< Private Watchdog Interrupt */
+
+/****** Platform Exceptions Numbers ***************************************************/
+ Watchdog_IRQn = 32, /*!< SP805 Interrupt */
+ Timer0_IRQn = 34, /*!< SP804 Interrupt */
+ Timer1_IRQn = 35, /*!< SP804 Interrupt */
+ RTClock_IRQn = 36, /*!< PL031 Interrupt */
+ UART0_IRQn = 37, /*!< PL011 Interrupt */
+ UART1_IRQn = 38, /*!< PL011 Interrupt */
+ UART2_IRQn = 39, /*!< PL011 Interrupt */
+ UART3_IRQn = 40, /*!< PL011 Interrupt */
+ MCI0_IRQn = 41, /*!< PL180 Interrupt (1st) */
+ MCI1_IRQn = 42, /*!< PL180 Interrupt (2nd) */
+ AACI_IRQn = 43, /*!< PL041 Interrupt */
+ Keyboard_IRQn = 44, /*!< PL050 Interrupt */
+ Mouse_IRQn = 45, /*!< PL050 Interrupt */
+ CLCD_IRQn = 46, /*!< PL111 Interrupt */
+ Ethernet_IRQn = 47, /*!< SMSC_91C111 Interrupt */
+ VFS2_IRQn = 73, /*!< VFS2 Interrupt */
+} IRQn_Type;
+
+/******************************************************************************/
+/* Peripheral memory map */
+/******************************************************************************/
+
+/* Peripheral and RAM base address */
+#define VE_A5_MP_FLASH_BASE0 (0x00000000UL) /*!< (FLASH0 ) Base Address */
+#define VE_A5_MP_FLASH_BASE1 (0x08000000UL) /*!< (FLASH1 ) Base Address */
+#define VE_A5_MP_PERIPH_BASE (0x18000000UL) /*!< (Peripheral) Base Address */
+#define VE_A5_MP_SRAM_BASE (0x2E000000UL) /*!< (SRAM ) Base Address */
+#define VE_A5_MP_DRAM_BASE (0x80000000UL) /*!< (DRAM ) Base Address */
+#define VE_A5_MP_VRAM_BASE (0x18000000UL) /*!< (VRAM ) Base Address */
+#define VE_A5_MP_ETHERNET_BASE (0x02000000UL + VE_A5_MP_PERIPH_BASE) /*!< (ETHERNET ) Base Address */
+#define VE_A5_MP_USB_BASE (0x03000000UL + VE_A5_MP_PERIPH_BASE) /*!< (USB ) Base Address */
+#define VE_A5_MP_DAP_BASE (0x1C000000UL) /*!< (DAP ) Base Address */
+#define VE_A5_MP_SYSTEM_REG_BASE (0x00010000UL + 0x1C000000UL) /*!< (SYSTEM REG) Base Address */
+#define VE_A5_MP_SERIAL_BASE (0x00030000UL + 0x1C000000UL) /*!< (SERIAL ) Base Address */
+#define VE_A5_MP_AACI_BASE (0x00040000UL + 0x1C000000UL) /*!< (AACI ) Base Address */
+#define VE_A5_MP_MMCI_BASE (0x00050000UL + 0x1C000000UL) /*!< (MMCI ) Base Address */
+#define VE_A5_MP_KMI0_BASE (0x00060000UL + 0x1C000000UL) /*!< (KMI0 ) Base Address */
+#define VE_A5_MP_UART_BASE (0x00090000UL + 0x1C000000UL) /*!< (UART ) Base Address */
+#define VE_A5_MP_WDT_BASE (0x000F0000UL + 0x1C000000UL) /*!< (WDT ) Base Address */
+#define VE_A5_MP_TIMER_BASE (0x00110000UL + 0x1C000000UL) /*!< (TIMER ) Base Address */
+#define VE_A5_MP_DVI_BASE (0x00160000UL + 0x1C000000UL) /*!< (DVI ) Base Address */
+#define VE_A5_MP_RTC_BASE (0x00170000UL + 0x1C000000UL) /*!< (RTC ) Base Address */
+#define VE_A5_MP_UART4_BASE (0x001B0000UL + 0x1C000000UL) /*!< (UART4 ) Base Address */
+#define VE_A5_MP_CLCD_BASE (0x001F0000UL + 0x1C000000UL) /*!< (CLCD ) Base Address */
+#define VE_A5_MP_GIC_DISTRIBUTOR_BASE (0x00001000UL + 0x2C000000UL) /*!< (GIC DIST ) Base Address */
+#define VE_A5_MP_GIC_INTERFACE_BASE (0x00000100UL + 0x2C000000UL) /*!< (GIC CPU IF) Base Address */
+#define VE_A5_MP_PRIVATE_TIMER (0x00000600UL + 0x2C000000UL) /*!< (PTIM ) Base Address */
+#define GIC_DISTRIBUTOR_BASE VE_A5_MP_GIC_DISTRIBUTOR_BASE
+#define GIC_INTERFACE_BASE VE_A5_MP_GIC_INTERFACE_BASE
+#define TIMER_BASE VE_A5_MP_PRIVATE_TIMER
+
+//The VE-A5 model implements L1 cache as architecturally defined, but does not implement L2 cache.
+//Do not enable the L2 cache if you are running RTX on a VE-A5 model as it may cause a data abort.
+#define VE_A5_MP_PL310_BASE (0x00A00000UL) /*!< (L2C-310 ) Base Address */
+#define L2C_310_BASE VE_A5_MP_PL310_BASE
+
+/* -------- Configuration of the Cortex-A5 Processor and Core Peripherals ------- */
+#define __CA_REV 0x0000U /* Core revision r0p0 */
+#define __CORTEX_A 5U /* Cortex-A5 Core */
+#define __FPU_PRESENT 1U /* FPU present */
+#define __GIC_PRESENT 1U /* GIC present */
+#define __TIM_PRESENT 1U /* TIM present */
+#define __L2C_PRESENT 1U /* L2C present */
+
+#include "core_ca.h"
+#include
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __ARMCA5_H__
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/cmsis_armcc.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/cmsis_armcc.h
new file mode 100644
index 0000000..313d743
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/cmsis_armcc.h
@@ -0,0 +1,544 @@
+/**************************************************************************//**
+ * @file cmsis_armcc.h
+ * @brief CMSIS compiler specific macros, functions, instructions
+ * @version V1.0.2
+ * @date 10. January 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CMSIS_ARMCC_H
+#define __CMSIS_ARMCC_H
+
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677)
+ #error "Please use Arm Compiler Toolchain V4.0.677 or later!"
+#endif
+
+/* CMSIS compiler control architecture macros */
+#if (defined (__TARGET_ARCH_7_A ) && (__TARGET_ARCH_7_A == 1))
+ #define __ARM_ARCH_7A__ 1
+#endif
+
+/* CMSIS compiler specific defines */
+#ifndef __ASM
+ #define __ASM __asm
+#endif
+#ifndef __INLINE
+ #define __INLINE __inline
+#endif
+#ifndef __FORCEINLINE
+ #define __FORCEINLINE __forceinline
+#endif
+#ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static __inline
+#endif
+#ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE static __forceinline
+#endif
+#ifndef __NO_RETURN
+ #define __NO_RETURN __declspec(noreturn)
+#endif
+#ifndef CMSIS_DEPRECATED
+ #define CMSIS_DEPRECATED __attribute__((deprecated))
+#endif
+#ifndef __USED
+ #define __USED __attribute__((used))
+#endif
+#ifndef __WEAK
+ #define __WEAK __attribute__((weak))
+#endif
+#ifndef __PACKED
+ #define __PACKED __attribute__((packed))
+#endif
+#ifndef __PACKED_STRUCT
+ #define __PACKED_STRUCT __packed struct
+#endif
+#ifndef __UNALIGNED_UINT16_WRITE
+ #define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val))
+#endif
+#ifndef __UNALIGNED_UINT16_READ
+ #define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr)))
+#endif
+#ifndef __UNALIGNED_UINT32_WRITE
+ #define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val))
+#endif
+#ifndef __UNALIGNED_UINT32_READ
+ #define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr)))
+#endif
+#ifndef __ALIGNED
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+#endif
+#ifndef __PACKED
+ #define __PACKED __attribute__((packed))
+#endif
+
+/* ########################## Core Instruction Access ######################### */
+/**
+ \brief No Operation
+ */
+#define __NOP __nop
+
+/**
+ \brief Wait For Interrupt
+ */
+#define __WFI __wfi
+
+/**
+ \brief Wait For Event
+ */
+#define __WFE __wfe
+
+/**
+ \brief Send Event
+ */
+#define __SEV __sev
+
+/**
+ \brief Instruction Synchronization Barrier
+ */
+#define __ISB() do {\
+ __schedule_barrier();\
+ __isb(0xF);\
+ __schedule_barrier();\
+ } while (0U)
+
+/**
+ \brief Data Synchronization Barrier
+ */
+#define __DSB() do {\
+ __schedule_barrier();\
+ __dsb(0xF);\
+ __schedule_barrier();\
+ } while (0U)
+
+/**
+ \brief Data Memory Barrier
+ */
+#define __DMB() do {\
+ __schedule_barrier();\
+ __dmb(0xF);\
+ __schedule_barrier();\
+ } while (0U)
+
+/**
+ \brief Reverse byte order (32 bit)
+ \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __REV __rev
+
+/**
+ \brief Reverse byte order (16 bit)
+ \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#ifndef __NO_EMBEDDED_ASM
+__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
+{
+ rev16 r0, r0
+ bx lr
+}
+#endif
+
+/**
+ \brief Reverse byte order (16 bit)
+ \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#ifndef __NO_EMBEDDED_ASM
+__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value)
+{
+ revsh r0, r0
+ bx lr
+}
+#endif
+
+/**
+ \brief Rotate Right in unsigned value (32 bit)
+ \param [in] op1 Value to rotate
+ \param [in] op2 Number of Bits to rotate
+ \return Rotated value
+ */
+#define __ROR __ror
+
+/**
+ \brief Breakpoint
+ \param [in] value is ignored by the processor.
+ If required, a debugger can use it to store additional information about the breakpoint.
+ */
+#define __BKPT(value) __breakpoint(value)
+
+/**
+ \brief Reverse bit order of value
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __RBIT __rbit
+
+/**
+ \brief Count leading zeros
+ \param [in] value Value to count the leading zeros
+ \return number of leading zeros in value
+ */
+#define __CLZ __clz
+
+/**
+ \brief LDR Exclusive (8 bit)
+ \details Executes a exclusive LDR instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
+ #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
+#else
+ #define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop")
+#endif
+
+/**
+ \brief LDR Exclusive (16 bit)
+ \details Executes a exclusive LDR instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
+ #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
+#else
+ #define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop")
+#endif
+
+/**
+ \brief LDR Exclusive (32 bit)
+ \details Executes a exclusive LDR instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
+ #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
+#else
+ #define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop")
+#endif
+
+/**
+ \brief STR Exclusive (8 bit)
+ \details Executes a exclusive STR instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
+ #define __STREXB(value, ptr) __strex(value, ptr)
+#else
+ #define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
+#endif
+
+/**
+ \brief STR Exclusive (16 bit)
+ \details Executes a exclusive STR instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
+ #define __STREXH(value, ptr) __strex(value, ptr)
+#else
+ #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
+#endif
+
+/**
+ \brief STR Exclusive (32 bit)
+ \details Executes a exclusive STR instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
+ #define __STREXW(value, ptr) __strex(value, ptr)
+#else
+ #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
+#endif
+
+/**
+ \brief Remove the exclusive lock
+ \details Removes the exclusive lock which is created by LDREX.
+ */
+#define __CLREX __clrex
+
+
+/**
+ \brief Signed Saturate
+ \details Saturates a signed value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (1..32)
+ \return Saturated value
+ */
+#define __SSAT __ssat
+
+/**
+ \brief Unsigned Saturate
+ \details Saturates an unsigned value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (0..31)
+ \return Saturated value
+ */
+#define __USAT __usat
+
+/* ########################### Core Function Access ########################### */
+
+/**
+ \brief Get FPSCR (Floating Point Status/Control)
+ \return Floating Point Status/Control register value
+ */
+__STATIC_INLINE uint32_t __get_FPSCR(void)
+{
+#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
+ register uint32_t __regfpscr __ASM("fpscr");
+ return(__regfpscr);
+#else
+ return(0U);
+#endif
+}
+
+/**
+ \brief Set FPSCR (Floating Point Status/Control)
+ \param [in] fpscr Floating Point Status/Control value to set
+ */
+__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
+{
+#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
+ register uint32_t __regfpscr __ASM("fpscr");
+ __regfpscr = (fpscr);
+#else
+ (void)fpscr;
+#endif
+}
+
+/** \brief Get CPSR (Current Program Status Register)
+ \return CPSR Register value
+ */
+__STATIC_INLINE uint32_t __get_CPSR(void)
+{
+ register uint32_t __regCPSR __ASM("cpsr");
+ return(__regCPSR);
+}
+
+
+/** \brief Set CPSR (Current Program Status Register)
+ \param [in] cpsr CPSR value to set
+ */
+__STATIC_INLINE void __set_CPSR(uint32_t cpsr)
+{
+ register uint32_t __regCPSR __ASM("cpsr");
+ __regCPSR = cpsr;
+}
+
+/** \brief Get Mode
+ \return Processor Mode
+ */
+__STATIC_INLINE uint32_t __get_mode(void)
+{
+ return (__get_CPSR() & 0x1FU);
+}
+
+/** \brief Set Mode
+ \param [in] mode Mode value to set
+ */
+__STATIC_INLINE __ASM void __set_mode(uint32_t mode)
+{
+ MOV r1, lr
+ MSR CPSR_C, r0
+ BX r1
+}
+
+/** \brief Get Stack Pointer
+ \return Stack Pointer
+ */
+__STATIC_INLINE __ASM uint32_t __get_SP(void)
+{
+ MOV r0, sp
+ BX lr
+}
+
+/** \brief Set Stack Pointer
+ \param [in] stack Stack Pointer value to set
+ */
+__STATIC_INLINE __ASM void __set_SP(uint32_t stack)
+{
+ MOV sp, r0
+ BX lr
+}
+
+
+/** \brief Get USR/SYS Stack Pointer
+ \return USR/SYSStack Pointer
+ */
+__STATIC_INLINE __ASM uint32_t __get_SP_usr(void)
+{
+ ARM
+ PRESERVE8
+
+ MRS R1, CPSR
+ CPS #0x1F ;no effect in USR mode
+ MOV R0, SP
+ MSR CPSR_c, R1 ;no effect in USR mode
+ ISB
+ BX LR
+}
+
+/** \brief Set USR/SYS Stack Pointer
+ \param [in] topOfProcStack USR/SYS Stack Pointer value to set
+ */
+__STATIC_INLINE __ASM void __set_SP_usr(uint32_t topOfProcStack)
+{
+ ARM
+ PRESERVE8
+
+ MRS R1, CPSR
+ CPS #0x1F ;no effect in USR mode
+ MOV SP, R0
+ MSR CPSR_c, R1 ;no effect in USR mode
+ ISB
+ BX LR
+}
+
+/** \brief Get FPEXC (Floating Point Exception Control Register)
+ \return Floating Point Exception Control Register value
+ */
+__STATIC_INLINE uint32_t __get_FPEXC(void)
+{
+#if (__FPU_PRESENT == 1)
+ register uint32_t __regfpexc __ASM("fpexc");
+ return(__regfpexc);
+#else
+ return(0);
+#endif
+}
+
+/** \brief Set FPEXC (Floating Point Exception Control Register)
+ \param [in] fpexc Floating Point Exception Control value to set
+ */
+__STATIC_INLINE void __set_FPEXC(uint32_t fpexc)
+{
+#if (__FPU_PRESENT == 1)
+ register uint32_t __regfpexc __ASM("fpexc");
+ __regfpexc = (fpexc);
+#endif
+}
+
+/*
+ * Include common core functions to access Coprocessor 15 registers
+ */
+
+#define __get_CP(cp, op1, Rt, CRn, CRm, op2) do { register volatile uint32_t tmp __ASM("cp" # cp ":" # op1 ":c" # CRn ":c" # CRm ":" # op2); (Rt) = tmp; } while(0)
+#define __set_CP(cp, op1, Rt, CRn, CRm, op2) do { register volatile uint32_t tmp __ASM("cp" # cp ":" # op1 ":c" # CRn ":c" # CRm ":" # op2); tmp = (Rt); } while(0)
+#define __get_CP64(cp, op1, Rt, CRm) \
+ do { \
+ uint32_t ltmp, htmp; \
+ __ASM volatile("MRRC p" # cp ", " # op1 ", ltmp, htmp, c" # CRm); \
+ (Rt) = ((((uint64_t)htmp) << 32U) | ((uint64_t)ltmp)); \
+ } while(0)
+
+#define __set_CP64(cp, op1, Rt, CRm) \
+ do { \
+ const uint64_t tmp = (Rt); \
+ const uint32_t ltmp = (uint32_t)(tmp); \
+ const uint32_t htmp = (uint32_t)(tmp >> 32U); \
+ __ASM volatile("MCRR p" # cp ", " # op1 ", ltmp, htmp, c" # CRm); \
+ } while(0)
+
+#include "cmsis_cp15.h"
+
+/** \brief Enable Floating Point Unit
+
+ Critical section, called from undef handler, so systick is disabled
+ */
+__STATIC_INLINE __ASM void __FPU_Enable(void)
+{
+ ARM
+
+ //Permit access to VFP/NEON, registers by modifying CPACR
+ MRC p15,0,R1,c1,c0,2
+ ORR R1,R1,#0x00F00000
+ MCR p15,0,R1,c1,c0,2
+
+ //Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
+ ISB
+
+ //Enable VFP/NEON
+ VMRS R1,FPEXC
+ ORR R1,R1,#0x40000000
+ VMSR FPEXC,R1
+
+ //Initialise VFP/NEON registers to 0
+ MOV R2,#0
+
+ //Initialise D16 registers to 0
+ VMOV D0, R2,R2
+ VMOV D1, R2,R2
+ VMOV D2, R2,R2
+ VMOV D3, R2,R2
+ VMOV D4, R2,R2
+ VMOV D5, R2,R2
+ VMOV D6, R2,R2
+ VMOV D7, R2,R2
+ VMOV D8, R2,R2
+ VMOV D9, R2,R2
+ VMOV D10,R2,R2
+ VMOV D11,R2,R2
+ VMOV D12,R2,R2
+ VMOV D13,R2,R2
+ VMOV D14,R2,R2
+ VMOV D15,R2,R2
+
+ IF {TARGET_FEATURE_EXTENSION_REGISTER_COUNT} == 32
+ //Initialise D32 registers to 0
+ VMOV D16,R2,R2
+ VMOV D17,R2,R2
+ VMOV D18,R2,R2
+ VMOV D19,R2,R2
+ VMOV D20,R2,R2
+ VMOV D21,R2,R2
+ VMOV D22,R2,R2
+ VMOV D23,R2,R2
+ VMOV D24,R2,R2
+ VMOV D25,R2,R2
+ VMOV D26,R2,R2
+ VMOV D27,R2,R2
+ VMOV D28,R2,R2
+ VMOV D29,R2,R2
+ VMOV D30,R2,R2
+ VMOV D31,R2,R2
+ ENDIF
+
+ //Initialise FPSCR to a known state
+ VMRS R2,FPSCR
+ LDR R3,=0x00086060 //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
+ AND R2,R2,R3
+ VMSR FPSCR,R2
+
+ BX LR
+}
+
+#endif /* __CMSIS_ARMCC_H */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/cmsis_armclang.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/cmsis_armclang.h
new file mode 100644
index 0000000..5883364
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/cmsis_armclang.h
@@ -0,0 +1,503 @@
+/**************************************************************************//**
+ * @file cmsis_armclang.h
+ * @brief CMSIS compiler specific macros, functions, instructions
+ * @version V1.0.2
+ * @date 10. January 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CMSIS_ARMCLANG_H
+#define __CMSIS_ARMCLANG_H
+
+#pragma clang system_header /* treat file as system include file */
+
+#ifndef __ARM_COMPAT_H
+#include /* Compatibility header for Arm Compiler 5 intrinsics */
+#endif
+
+/* CMSIS compiler specific defines */
+#ifndef __ASM
+ #define __ASM __asm
+#endif
+#ifndef __INLINE
+ #define __INLINE __inline
+#endif
+#ifndef __FORCEINLINE
+ #define __FORCEINLINE __attribute__((always_inline))
+#endif
+#ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static __inline
+#endif
+#ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline
+#endif
+#ifndef __NO_RETURN
+ #define __NO_RETURN __attribute__((__noreturn__))
+#endif
+#ifndef CMSIS_DEPRECATED
+ #define CMSIS_DEPRECATED __attribute__((deprecated))
+#endif
+#ifndef __USED
+ #define __USED __attribute__((used))
+#endif
+#ifndef __WEAK
+ #define __WEAK __attribute__((weak))
+#endif
+#ifndef __PACKED
+ #define __PACKED __attribute__((packed, aligned(1)))
+#endif
+#ifndef __PACKED_STRUCT
+ #define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
+#endif
+#ifndef __UNALIGNED_UINT16_WRITE
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */
+ __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
+#endif
+#ifndef __UNALIGNED_UINT16_READ
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */
+ __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
+#endif
+#ifndef __UNALIGNED_UINT32_WRITE
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */
+ __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
+#endif
+#ifndef __UNALIGNED_UINT32_READ
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+ __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
+#endif
+#ifndef __ALIGNED
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+#endif
+#ifndef __PACKED
+ #define __PACKED __attribute__((packed))
+#endif
+
+/* ########################## Core Instruction Access ######################### */
+/**
+ \brief No Operation
+ */
+#define __NOP __builtin_arm_nop
+
+/**
+ \brief Wait For Interrupt
+ */
+#define __WFI __builtin_arm_wfi
+
+/**
+ \brief Wait For Event
+ */
+#define __WFE __builtin_arm_wfe
+
+/**
+ \brief Send Event
+ */
+#define __SEV __builtin_arm_sev
+
+/**
+ \brief Instruction Synchronization Barrier
+ */
+#define __ISB() do {\
+ __schedule_barrier();\
+ __builtin_arm_isb(0xF);\
+ __schedule_barrier();\
+ } while (0U)
+
+/**
+ \brief Data Synchronization Barrier
+ */
+#define __DSB() do {\
+ __schedule_barrier();\
+ __builtin_arm_dsb(0xF);\
+ __schedule_barrier();\
+ } while (0U)
+
+/**
+ \brief Data Memory Barrier
+ */
+#define __DMB() do {\
+ __schedule_barrier();\
+ __builtin_arm_dmb(0xF);\
+ __schedule_barrier();\
+ } while (0U)
+
+/**
+ \brief Reverse byte order (32 bit)
+ \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __REV(value) __builtin_bswap32(value)
+
+/**
+ \brief Reverse byte order (16 bit)
+ \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __REV16(value) __ROR(__REV(value), 16)
+
+
+/**
+ \brief Reverse byte order (16 bit)
+ \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __REVSH(value) (int16_t)__builtin_bswap16(value)
+
+
+/**
+ \brief Rotate Right in unsigned value (32 bit)
+ \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
+ \param [in] op1 Value to rotate
+ \param [in] op2 Number of Bits to rotate
+ \return Rotated value
+ */
+__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
+{
+ op2 %= 32U;
+ if (op2 == 0U)
+ {
+ return op1;
+ }
+ return (op1 >> op2) | (op1 << (32U - op2));
+}
+
+
+/**
+ \brief Breakpoint
+ \param [in] value is ignored by the processor.
+ If required, a debugger can use it to store additional information about the breakpoint.
+ */
+#define __BKPT(value) __ASM volatile ("bkpt "#value)
+
+/**
+ \brief Reverse bit order of value
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __RBIT __builtin_arm_rbit
+
+/**
+ \brief Count leading zeros
+ \param [in] value Value to count the leading zeros
+ \return number of leading zeros in value
+ */
+#define __CLZ (uint8_t)__builtin_clz
+
+/**
+ \brief LDR Exclusive (8 bit)
+ \details Executes a exclusive LDR instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+#define __LDREXB (uint8_t)__builtin_arm_ldrex
+
+
+/**
+ \brief LDR Exclusive (16 bit)
+ \details Executes a exclusive LDR instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+#define __LDREXH (uint16_t)__builtin_arm_ldrex
+
+/**
+ \brief LDR Exclusive (32 bit)
+ \details Executes a exclusive LDR instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+#define __LDREXW (uint32_t)__builtin_arm_ldrex
+
+/**
+ \brief STR Exclusive (8 bit)
+ \details Executes a exclusive STR instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STREXB (uint32_t)__builtin_arm_strex
+
+/**
+ \brief STR Exclusive (16 bit)
+ \details Executes a exclusive STR instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STREXH (uint32_t)__builtin_arm_strex
+
+/**
+ \brief STR Exclusive (32 bit)
+ \details Executes a exclusive STR instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STREXW (uint32_t)__builtin_arm_strex
+
+/**
+ \brief Remove the exclusive lock
+ \details Removes the exclusive lock which is created by LDREX.
+ */
+#define __CLREX __builtin_arm_clrex
+
+/**
+ \brief Signed Saturate
+ \details Saturates a signed value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (1..32)
+ \return Saturated value
+ */
+#define __SSAT __builtin_arm_ssat
+
+/**
+ \brief Unsigned Saturate
+ \details Saturates an unsigned value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (0..31)
+ \return Saturated value
+ */
+#define __USAT __builtin_arm_usat
+
+
+/* ########################### Core Function Access ########################### */
+
+/**
+ \brief Get FPSCR
+ \details Returns the current value of the Floating Point Status/Control register.
+ \return Floating Point Status/Control register value
+ */
+#define __get_FPSCR __builtin_arm_get_fpscr
+
+/**
+ \brief Set FPSCR
+ \details Assigns the given value to the Floating Point Status/Control register.
+ \param [in] fpscr Floating Point Status/Control value to set
+ */
+#define __set_FPSCR __builtin_arm_set_fpscr
+
+/** \brief Get CPSR Register
+ \return CPSR Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_CPSR(void)
+{
+ uint32_t result;
+ __ASM volatile("MRS %0, cpsr" : "=r" (result) );
+ return(result);
+}
+
+/** \brief Set CPSR Register
+ \param [in] cpsr CPSR value to set
+ */
+__STATIC_FORCEINLINE void __set_CPSR(uint32_t cpsr)
+{
+__ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "memory");
+}
+
+/** \brief Get Mode
+ \return Processor Mode
+ */
+__STATIC_FORCEINLINE uint32_t __get_mode(void)
+{
+ return (__get_CPSR() & 0x1FU);
+}
+
+/** \brief Set Mode
+ \param [in] mode Mode value to set
+ */
+__STATIC_FORCEINLINE void __set_mode(uint32_t mode)
+{
+ __ASM volatile("MSR cpsr_c, %0" : : "r" (mode) : "memory");
+}
+
+/** \brief Get Stack Pointer
+ \return Stack Pointer value
+ */
+__STATIC_FORCEINLINE uint32_t __get_SP()
+{
+ uint32_t result;
+ __ASM volatile("MOV %0, sp" : "=r" (result) : : "memory");
+ return result;
+}
+
+/** \brief Set Stack Pointer
+ \param [in] stack Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __set_SP(uint32_t stack)
+{
+ __ASM volatile("MOV sp, %0" : : "r" (stack) : "memory");
+}
+
+/** \brief Get USR/SYS Stack Pointer
+ \return USR/SYS Stack Pointer value
+ */
+__STATIC_FORCEINLINE uint32_t __get_SP_usr()
+{
+ uint32_t cpsr;
+ uint32_t result;
+ __ASM volatile(
+ "MRS %0, cpsr \n"
+ "CPS #0x1F \n" // no effect in USR mode
+ "MOV %1, sp \n"
+ "MSR cpsr_c, %2 \n" // no effect in USR mode
+ "ISB" : "=r"(cpsr), "=r"(result) : "r"(cpsr) : "memory"
+ );
+ return result;
+}
+
+/** \brief Set USR/SYS Stack Pointer
+ \param [in] topOfProcStack USR/SYS Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __set_SP_usr(uint32_t topOfProcStack)
+{
+ uint32_t cpsr;
+ __ASM volatile(
+ "MRS %0, cpsr \n"
+ "CPS #0x1F \n" // no effect in USR mode
+ "MOV sp, %1 \n"
+ "MSR cpsr_c, %2 \n" // no effect in USR mode
+ "ISB" : "=r"(cpsr) : "r" (topOfProcStack), "r"(cpsr) : "memory"
+ );
+}
+
+/** \brief Get FPEXC
+ \return Floating Point Exception Control register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_FPEXC(void)
+{
+#if (__FPU_PRESENT == 1)
+ uint32_t result;
+ __ASM volatile("VMRS %0, fpexc" : "=r" (result) : : "memory");
+ return(result);
+#else
+ return(0);
+#endif
+}
+
+/** \brief Set FPEXC
+ \param [in] fpexc Floating Point Exception Control value to set
+ */
+__STATIC_FORCEINLINE void __set_FPEXC(uint32_t fpexc)
+{
+#if (__FPU_PRESENT == 1)
+ __ASM volatile ("VMSR fpexc, %0" : : "r" (fpexc) : "memory");
+#endif
+}
+
+/*
+ * Include common core functions to access Coprocessor 15 registers
+ */
+
+#define __get_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MRC p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : "=r" (Rt) : : "memory" )
+#define __set_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MCR p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : : "r" (Rt) : "memory" )
+#define __get_CP64(cp, op1, Rt, CRm) __ASM volatile("MRRC p" # cp ", " # op1 ", %Q0, %R0, c" # CRm : "=r" (Rt) : : "memory" )
+#define __set_CP64(cp, op1, Rt, CRm) __ASM volatile("MCRR p" # cp ", " # op1 ", %Q0, %R0, c" # CRm : : "r" (Rt) : "memory" )
+
+#include "cmsis_cp15.h"
+
+/** \brief Enable Floating Point Unit
+
+ Critical section, called from undef handler, so systick is disabled
+ */
+__STATIC_INLINE void __FPU_Enable(void)
+{
+ __ASM volatile(
+ //Permit access to VFP/NEON, registers by modifying CPACR
+ " MRC p15,0,R1,c1,c0,2 \n"
+ " ORR R1,R1,#0x00F00000 \n"
+ " MCR p15,0,R1,c1,c0,2 \n"
+
+ //Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
+ " ISB \n"
+
+ //Enable VFP/NEON
+ " VMRS R1,FPEXC \n"
+ " ORR R1,R1,#0x40000000 \n"
+ " VMSR FPEXC,R1 \n"
+
+ //Initialise VFP/NEON registers to 0
+ " MOV R2,#0 \n"
+
+ //Initialise D16 registers to 0
+ " VMOV D0, R2,R2 \n"
+ " VMOV D1, R2,R2 \n"
+ " VMOV D2, R2,R2 \n"
+ " VMOV D3, R2,R2 \n"
+ " VMOV D4, R2,R2 \n"
+ " VMOV D5, R2,R2 \n"
+ " VMOV D6, R2,R2 \n"
+ " VMOV D7, R2,R2 \n"
+ " VMOV D8, R2,R2 \n"
+ " VMOV D9, R2,R2 \n"
+ " VMOV D10,R2,R2 \n"
+ " VMOV D11,R2,R2 \n"
+ " VMOV D12,R2,R2 \n"
+ " VMOV D13,R2,R2 \n"
+ " VMOV D14,R2,R2 \n"
+ " VMOV D15,R2,R2 \n"
+
+#if __ARM_NEON == 1
+ //Initialise D32 registers to 0
+ " VMOV D16,R2,R2 \n"
+ " VMOV D17,R2,R2 \n"
+ " VMOV D18,R2,R2 \n"
+ " VMOV D19,R2,R2 \n"
+ " VMOV D20,R2,R2 \n"
+ " VMOV D21,R2,R2 \n"
+ " VMOV D22,R2,R2 \n"
+ " VMOV D23,R2,R2 \n"
+ " VMOV D24,R2,R2 \n"
+ " VMOV D25,R2,R2 \n"
+ " VMOV D26,R2,R2 \n"
+ " VMOV D27,R2,R2 \n"
+ " VMOV D28,R2,R2 \n"
+ " VMOV D29,R2,R2 \n"
+ " VMOV D30,R2,R2 \n"
+ " VMOV D31,R2,R2 \n"
+#endif
+
+ //Initialise FPSCR to a known state
+ " VMRS R2,FPSCR \n"
+ " LDR R3,=0x00086060 \n" //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
+ " AND R2,R2,R3 \n"
+ " VMSR FPSCR,R2 "
+ );
+}
+
+#endif /* __CMSIS_ARMCLANG_H */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/cmsis_compiler.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/cmsis_compiler.h
new file mode 100644
index 0000000..b00c6ba
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/cmsis_compiler.h
@@ -0,0 +1,201 @@
+/**************************************************************************//**
+ * @file cmsis_compiler.h
+ * @brief CMSIS compiler specific macros, functions, instructions
+ * @version V1.0.2
+ * @date 10. January 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CMSIS_COMPILER_H
+#define __CMSIS_COMPILER_H
+
+#include
+
+/*
+ * Arm Compiler 4/5
+ */
+#if defined ( __CC_ARM )
+ #include "cmsis_armcc.h"
+
+
+/*
+ * Arm Compiler 6 (armclang)
+ */
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #include "cmsis_armclang.h"
+
+
+/*
+ * GNU Compiler
+ */
+#elif defined ( __GNUC__ )
+ #include "cmsis_gcc.h"
+
+
+/*
+ * IAR Compiler
+ */
+#elif defined ( __ICCARM__ )
+ #include "cmsis_iccarm.h"
+
+
+/*
+ * TI Arm Compiler
+ */
+#elif defined ( __TI_ARM__ )
+ #include
+
+ #ifndef __ASM
+ #define __ASM __asm
+ #endif
+ #ifndef __INLINE
+ #define __INLINE inline
+ #endif
+ #ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static inline
+ #endif
+ #ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static inline
+ #endif
+ #ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __STATIC_INLINE
+ #endif
+ #ifndef __NO_RETURN
+ #define __NO_RETURN __attribute__((noreturn))
+ #endif
+ #ifndef CMSIS_DEPRECATED
+ #define CMSIS_DEPRECATED __attribute__((deprecated))
+ #endif
+ #ifndef __USED
+ #define __USED __attribute__((used))
+ #endif
+ #ifndef __WEAK
+ #define __WEAK __attribute__((weak))
+ #endif
+ #ifndef __UNALIGNED_UINT32
+ struct __attribute__((packed)) T_UINT32 { uint32_t v; };
+ #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
+ #endif
+ #ifndef __ALIGNED
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+ #endif
+ #ifndef __PACKED
+ #define __PACKED __attribute__((packed))
+ #endif
+
+
+/*
+ * TASKING Compiler
+ */
+#elif defined ( __TASKING__ )
+ /*
+ * The CMSIS functions have been implemented as intrinsics in the compiler.
+ * Please use "carm -?i" to get an up to date list of all intrinsics,
+ * Including the CMSIS ones.
+ */
+
+ #ifndef __ASM
+ #define __ASM __asm
+ #endif
+ #ifndef __INLINE
+ #define __INLINE inline
+ #endif
+ #ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static inline
+ #endif
+ #ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __STATIC_INLINE
+ #endif
+ #ifndef __NO_RETURN
+ #define __NO_RETURN __attribute__((noreturn))
+ #endif
+ #ifndef CMSIS_DEPRECATED
+ #define CMSIS_DEPRECATED __attribute__((deprecated))
+ #endif
+ #ifndef __USED
+ #define __USED __attribute__((used))
+ #endif
+ #ifndef __WEAK
+ #define __WEAK __attribute__((weak))
+ #endif
+ #ifndef __UNALIGNED_UINT32
+ struct __packed__ T_UINT32 { uint32_t v; };
+ #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
+ #endif
+ #ifndef __ALIGNED
+ #define __ALIGNED(x) __align(x)
+ #endif
+ #ifndef __PACKED
+ #define __PACKED __packed__
+ #endif
+
+
+/*
+ * COSMIC Compiler
+ */
+#elif defined ( __CSMC__ )
+ #include
+
+ #ifndef __ASM
+ #define __ASM _asm
+ #endif
+ #ifndef __INLINE
+ #define __INLINE inline
+ #endif
+ #ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static inline
+ #endif
+ #ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __STATIC_INLINE
+ #endif
+ #ifndef __NO_RETURN
+ // NO RETURN is automatically detected hence no warning here
+ #define __NO_RETURN
+ #endif
+ #ifndef __USED
+ #warning No compiler specific solution for __USED. __USED is ignored.
+ #define __USED
+ #endif
+ #ifndef CMSIS_DEPRECATED
+ #warning No compiler specific solution for CMSIS_DEPRECATED. CMSIS_DEPRECATED is ignored.
+ #define CMSIS_DEPRECATED
+ #endif
+ #ifndef __WEAK
+ #define __WEAK __weak
+ #endif
+ #ifndef __UNALIGNED_UINT32
+ @packed struct T_UINT32 { uint32_t v; };
+ #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
+ #endif
+ #ifndef __ALIGNED
+ #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
+ #define __ALIGNED(x)
+ #endif
+ #ifndef __PACKED
+ #define __PACKED @packed
+ #endif
+
+
+#else
+ #error Unknown compiler.
+#endif
+
+
+#endif /* __CMSIS_COMPILER_H */
+
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/cmsis_cp15.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/cmsis_cp15.h
new file mode 100644
index 0000000..891bec2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/cmsis_cp15.h
@@ -0,0 +1,514 @@
+/**************************************************************************//**
+ * @file cmsis_cp15.h
+ * @brief CMSIS compiler specific macros, functions, instructions
+ * @version V1.0.1
+ * @date 07. Sep 2017
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CMSIS_CP15_H
+#define __CMSIS_CP15_H
+
+/** \brief Get ACTLR
+ \return Auxiliary Control register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_ACTLR(void)
+{
+ uint32_t result;
+ __get_CP(15, 0, result, 1, 0, 1);
+ return(result);
+}
+
+/** \brief Set ACTLR
+ \param [in] actlr Auxiliary Control value to set
+ */
+__STATIC_FORCEINLINE void __set_ACTLR(uint32_t actlr)
+{
+ __set_CP(15, 0, actlr, 1, 0, 1);
+}
+
+/** \brief Get CPACR
+ \return Coprocessor Access Control register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_CPACR(void)
+{
+ uint32_t result;
+ __get_CP(15, 0, result, 1, 0, 2);
+ return result;
+}
+
+/** \brief Set CPACR
+ \param [in] cpacr Coprocessor Access Control value to set
+ */
+__STATIC_FORCEINLINE void __set_CPACR(uint32_t cpacr)
+{
+ __set_CP(15, 0, cpacr, 1, 0, 2);
+}
+
+/** \brief Get DFSR
+ \return Data Fault Status Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_DFSR(void)
+{
+ uint32_t result;
+ __get_CP(15, 0, result, 5, 0, 0);
+ return result;
+}
+
+/** \brief Set DFSR
+ \param [in] dfsr Data Fault Status value to set
+ */
+__STATIC_FORCEINLINE void __set_DFSR(uint32_t dfsr)
+{
+ __set_CP(15, 0, dfsr, 5, 0, 0);
+}
+
+/** \brief Get IFSR
+ \return Instruction Fault Status Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_IFSR(void)
+{
+ uint32_t result;
+ __get_CP(15, 0, result, 5, 0, 1);
+ return result;
+}
+
+/** \brief Set IFSR
+ \param [in] ifsr Instruction Fault Status value to set
+ */
+__STATIC_FORCEINLINE void __set_IFSR(uint32_t ifsr)
+{
+ __set_CP(15, 0, ifsr, 5, 0, 1);
+}
+
+/** \brief Get ISR
+ \return Interrupt Status Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_ISR(void)
+{
+ uint32_t result;
+ __get_CP(15, 0, result, 12, 1, 0);
+ return result;
+}
+
+/** \brief Get CBAR
+ \return Configuration Base Address register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_CBAR(void)
+{
+ uint32_t result;
+ __get_CP(15, 4, result, 15, 0, 0);
+ return result;
+}
+
+/** \brief Get TTBR0
+
+ This function returns the value of the Translation Table Base Register 0.
+
+ \return Translation Table Base Register 0 value
+ */
+__STATIC_FORCEINLINE uint32_t __get_TTBR0(void)
+{
+ uint32_t result;
+ __get_CP(15, 0, result, 2, 0, 0);
+ return result;
+}
+
+/** \brief Set TTBR0
+
+ This function assigns the given value to the Translation Table Base Register 0.
+
+ \param [in] ttbr0 Translation Table Base Register 0 value to set
+ */
+__STATIC_FORCEINLINE void __set_TTBR0(uint32_t ttbr0)
+{
+ __set_CP(15, 0, ttbr0, 2, 0, 0);
+}
+
+/** \brief Get DACR
+
+ This function returns the value of the Domain Access Control Register.
+
+ \return Domain Access Control Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_DACR(void)
+{
+ uint32_t result;
+ __get_CP(15, 0, result, 3, 0, 0);
+ return result;
+}
+
+/** \brief Set DACR
+
+ This function assigns the given value to the Domain Access Control Register.
+
+ \param [in] dacr Domain Access Control Register value to set
+ */
+__STATIC_FORCEINLINE void __set_DACR(uint32_t dacr)
+{
+ __set_CP(15, 0, dacr, 3, 0, 0);
+}
+
+/** \brief Set SCTLR
+
+ This function assigns the given value to the System Control Register.
+
+ \param [in] sctlr System Control Register value to set
+ */
+__STATIC_FORCEINLINE void __set_SCTLR(uint32_t sctlr)
+{
+ __set_CP(15, 0, sctlr, 1, 0, 0);
+}
+
+/** \brief Get SCTLR
+ \return System Control Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_SCTLR(void)
+{
+ uint32_t result;
+ __get_CP(15, 0, result, 1, 0, 0);
+ return result;
+}
+
+/** \brief Set ACTRL
+ \param [in] actrl Auxiliary Control Register value to set
+ */
+__STATIC_FORCEINLINE void __set_ACTRL(uint32_t actrl)
+{
+ __set_CP(15, 0, actrl, 1, 0, 1);
+}
+
+/** \brief Get ACTRL
+ \return Auxiliary Control Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_ACTRL(void)
+{
+ uint32_t result;
+ __get_CP(15, 0, result, 1, 0, 1);
+ return result;
+}
+
+/** \brief Get MPIDR
+
+ This function returns the value of the Multiprocessor Affinity Register.
+
+ \return Multiprocessor Affinity Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_MPIDR(void)
+{
+ uint32_t result;
+ __get_CP(15, 0, result, 0, 0, 5);
+ return result;
+}
+
+/** \brief Get VBAR
+
+ This function returns the value of the Vector Base Address Register.
+
+ \return Vector Base Address Register
+ */
+__STATIC_FORCEINLINE uint32_t __get_VBAR(void)
+{
+ uint32_t result;
+ __get_CP(15, 0, result, 12, 0, 0);
+ return result;
+}
+
+/** \brief Set VBAR
+
+ This function assigns the given value to the Vector Base Address Register.
+
+ \param [in] vbar Vector Base Address Register value to set
+ */
+__STATIC_FORCEINLINE void __set_VBAR(uint32_t vbar)
+{
+ __set_CP(15, 0, vbar, 12, 0, 0);
+}
+
+/** \brief Get MVBAR
+
+ This function returns the value of the Monitor Vector Base Address Register.
+
+ \return Monitor Vector Base Address Register
+ */
+__STATIC_FORCEINLINE uint32_t __get_MVBAR(void)
+{
+ uint32_t result;
+ __get_CP(15, 0, result, 12, 0, 1);
+ return result;
+}
+
+/** \brief Set MVBAR
+
+ This function assigns the given value to the Monitor Vector Base Address Register.
+
+ \param [in] mvbar Monitor Vector Base Address Register value to set
+ */
+__STATIC_FORCEINLINE void __set_MVBAR(uint32_t mvbar)
+{
+ __set_CP(15, 0, mvbar, 12, 0, 1);
+}
+
+#if (defined(__CORTEX_A) && (__CORTEX_A == 7U) && \
+ defined(__TIM_PRESENT) && (__TIM_PRESENT == 1U)) || \
+ defined(DOXYGEN)
+
+/** \brief Set CNTFRQ
+
+ This function assigns the given value to PL1 Physical Timer Counter Frequency Register (CNTFRQ).
+
+ \param [in] value CNTFRQ Register value to set
+*/
+__STATIC_FORCEINLINE void __set_CNTFRQ(uint32_t value)
+{
+ __set_CP(15, 0, value, 14, 0, 0);
+}
+
+/** \brief Get CNTFRQ
+
+ This function returns the value of the PL1 Physical Timer Counter Frequency Register (CNTFRQ).
+
+ \return CNTFRQ Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_CNTFRQ(void)
+{
+ uint32_t result;
+ __get_CP(15, 0, result, 14, 0 , 0);
+ return result;
+}
+
+/** \brief Set CNTP_TVAL
+
+ This function assigns the given value to PL1 Physical Timer Value Register (CNTP_TVAL).
+
+ \param [in] value CNTP_TVAL Register value to set
+*/
+__STATIC_FORCEINLINE void __set_CNTP_TVAL(uint32_t value)
+{
+ __set_CP(15, 0, value, 14, 2, 0);
+}
+
+/** \brief Get CNTP_TVAL
+
+ This function returns the value of the PL1 Physical Timer Value Register (CNTP_TVAL).
+
+ \return CNTP_TVAL Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_CNTP_TVAL(void)
+{
+ uint32_t result;
+ __get_CP(15, 0, result, 14, 2, 0);
+ return result;
+}
+
+/** \brief Get CNTPCT
+
+ This function returns the value of the 64 bits PL1 Physical Count Register (CNTPCT).
+
+ \return CNTPCT Register value
+ */
+__STATIC_FORCEINLINE uint64_t __get_CNTPCT(void)
+{
+ uint64_t result;
+ __get_CP64(15, 0, result, 14);
+ return result;
+}
+
+/** \brief Set CNTP_CVAL
+
+ This function assigns the given value to 64bits PL1 Physical Timer CompareValue Register (CNTP_CVAL).
+
+ \param [in] value CNTP_CVAL Register value to set
+*/
+__STATIC_FORCEINLINE void __set_CNTP_CVAL(uint64_t value)
+{
+ __set_CP64(15, 2, value, 14);
+}
+
+/** \brief Get CNTP_CVAL
+
+ This function returns the value of the 64 bits PL1 Physical Timer CompareValue Register (CNTP_CVAL).
+
+ \return CNTP_CVAL Register value
+ */
+__STATIC_FORCEINLINE uint64_t __get_CNTP_CVAL(void)
+{
+ uint64_t result;
+ __get_CP64(15, 2, result, 14);
+ return result;
+}
+
+/** \brief Set CNTP_CTL
+
+ This function assigns the given value to PL1 Physical Timer Control Register (CNTP_CTL).
+
+ \param [in] value CNTP_CTL Register value to set
+*/
+__STATIC_FORCEINLINE void __set_CNTP_CTL(uint32_t value)
+{
+ __set_CP(15, 0, value, 14, 2, 1);
+}
+
+/** \brief Get CNTP_CTL register
+ \return CNTP_CTL Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_CNTP_CTL(void)
+{
+ uint32_t result;
+ __get_CP(15, 0, result, 14, 2, 1);
+ return result;
+}
+
+#endif
+
+/** \brief Set TLBIALL
+
+ TLB Invalidate All
+ */
+__STATIC_FORCEINLINE void __set_TLBIALL(uint32_t value)
+{
+ __set_CP(15, 0, value, 8, 7, 0);
+}
+
+/** \brief Set BPIALL.
+
+ Branch Predictor Invalidate All
+ */
+__STATIC_FORCEINLINE void __set_BPIALL(uint32_t value)
+{
+ __set_CP(15, 0, value, 7, 5, 6);
+}
+
+/** \brief Set ICIALLU
+
+ Instruction Cache Invalidate All
+ */
+__STATIC_FORCEINLINE void __set_ICIALLU(uint32_t value)
+{
+ __set_CP(15, 0, value, 7, 5, 0);
+}
+
+/** \brief Set DCCMVAC
+
+ Data cache clean
+ */
+__STATIC_FORCEINLINE void __set_DCCMVAC(uint32_t value)
+{
+ __set_CP(15, 0, value, 7, 10, 1);
+}
+
+/** \brief Set DCIMVAC
+
+ Data cache invalidate
+ */
+__STATIC_FORCEINLINE void __set_DCIMVAC(uint32_t value)
+{
+ __set_CP(15, 0, value, 7, 6, 1);
+}
+
+/** \brief Set DCCIMVAC
+
+ Data cache clean and invalidate
+ */
+__STATIC_FORCEINLINE void __set_DCCIMVAC(uint32_t value)
+{
+ __set_CP(15, 0, value, 7, 14, 1);
+}
+
+/** \brief Set CSSELR
+ */
+__STATIC_FORCEINLINE void __set_CSSELR(uint32_t value)
+{
+// __ASM volatile("MCR p15, 2, %0, c0, c0, 0" : : "r"(value) : "memory");
+ __set_CP(15, 2, value, 0, 0, 0);
+}
+
+/** \brief Get CSSELR
+ \return CSSELR Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_CSSELR(void)
+{
+ uint32_t result;
+// __ASM volatile("MRC p15, 2, %0, c0, c0, 0" : "=r"(result) : : "memory");
+ __get_CP(15, 2, result, 0, 0, 0);
+ return result;
+}
+
+/** \brief Set CCSIDR
+ \deprecated CCSIDR itself is read-only. Use __set_CSSELR to select cache level instead.
+ */
+CMSIS_DEPRECATED
+__STATIC_FORCEINLINE void __set_CCSIDR(uint32_t value)
+{
+ __set_CSSELR(value);
+}
+
+/** \brief Get CCSIDR
+ \return CCSIDR Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_CCSIDR(void)
+{
+ uint32_t result;
+// __ASM volatile("MRC p15, 1, %0, c0, c0, 0" : "=r"(result) : : "memory");
+ __get_CP(15, 1, result, 0, 0, 0);
+ return result;
+}
+
+/** \brief Get CLIDR
+ \return CLIDR Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_CLIDR(void)
+{
+ uint32_t result;
+// __ASM volatile("MRC p15, 1, %0, c0, c0, 1" : "=r"(result) : : "memory");
+ __get_CP(15, 1, result, 0, 0, 1);
+ return result;
+}
+
+/** \brief Set DCISW
+ */
+__STATIC_FORCEINLINE void __set_DCISW(uint32_t value)
+{
+// __ASM volatile("MCR p15, 0, %0, c7, c6, 2" : : "r"(value) : "memory")
+ __set_CP(15, 0, value, 7, 6, 2);
+}
+
+/** \brief Set DCCSW
+ */
+__STATIC_FORCEINLINE void __set_DCCSW(uint32_t value)
+{
+// __ASM volatile("MCR p15, 0, %0, c7, c10, 2" : : "r"(value) : "memory")
+ __set_CP(15, 0, value, 7, 10, 2);
+}
+
+/** \brief Set DCCISW
+ */
+__STATIC_FORCEINLINE void __set_DCCISW(uint32_t value)
+{
+// __ASM volatile("MCR p15, 0, %0, c7, c14, 2" : : "r"(value) : "memory")
+ __set_CP(15, 0, value, 7, 14, 2);
+}
+
+#endif
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/cmsis_gcc.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/cmsis_gcc.h
new file mode 100644
index 0000000..4f46462
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/cmsis_gcc.h
@@ -0,0 +1,679 @@
+/**************************************************************************//**
+ * @file cmsis_gcc.h
+ * @brief CMSIS compiler specific macros, functions, instructions
+ * @version V1.0.2
+ * @date 09. April 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CMSIS_GCC_H
+#define __CMSIS_GCC_H
+
+/* ignore some GCC warnings */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wsign-conversion"
+#pragma GCC diagnostic ignored "-Wconversion"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+
+/* Fallback for __has_builtin */
+#ifndef __has_builtin
+ #define __has_builtin(x) (0)
+#endif
+
+/* CMSIS compiler specific defines */
+#ifndef __ASM
+ #define __ASM asm
+#endif
+#ifndef __INLINE
+ #define __INLINE inline
+#endif
+#ifndef __FORCEINLINE
+ #define __FORCEINLINE __attribute__((always_inline))
+#endif
+#ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static inline
+#endif
+#ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline
+#endif
+#ifndef __NO_RETURN
+ #define __NO_RETURN __attribute__((__noreturn__))
+#endif
+#ifndef CMSIS_DEPRECATED
+ #define CMSIS_DEPRECATED __attribute__((deprecated))
+#endif
+#ifndef __USED
+ #define __USED __attribute__((used))
+#endif
+#ifndef __WEAK
+ #define __WEAK __attribute__((weak))
+#endif
+#ifndef __PACKED
+ #define __PACKED __attribute__((packed, aligned(1)))
+#endif
+#ifndef __PACKED_STRUCT
+ #define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
+#endif
+#ifndef __UNALIGNED_UINT16_WRITE
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */
+ __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
+ #pragma GCC diagnostic pop
+ #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
+#endif
+#ifndef __UNALIGNED_UINT16_READ
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */
+ __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
+ #pragma GCC diagnostic pop
+ #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
+#endif
+#ifndef __UNALIGNED_UINT32_WRITE
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */
+ __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
+ #pragma GCC diagnostic pop
+ #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
+#endif
+#ifndef __UNALIGNED_UINT32_READ
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpacked"
+ __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
+ #pragma GCC diagnostic pop
+ #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
+#endif
+#ifndef __ALIGNED
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+#endif
+
+/* ########################## Core Instruction Access ######################### */
+/**
+ \brief No Operation
+ */
+#define __NOP() __ASM volatile ("nop")
+
+/**
+ \brief Wait For Interrupt
+ */
+#define __WFI() __ASM volatile ("wfi")
+
+/**
+ \brief Wait For Event
+ */
+#define __WFE() __ASM volatile ("wfe")
+
+/**
+ \brief Send Event
+ */
+#define __SEV() __ASM volatile ("sev")
+
+/**
+ \brief Instruction Synchronization Barrier
+ \details Instruction Synchronization Barrier flushes the pipeline in the processor,
+ so that all instructions following the ISB are fetched from cache or memory,
+ after the instruction has been completed.
+ */
+__STATIC_FORCEINLINE void __ISB(void)
+{
+ __ASM volatile ("isb 0xF":::"memory");
+}
+
+
+/**
+ \brief Data Synchronization Barrier
+ \details Acts as a special kind of Data Memory Barrier.
+ It completes when all explicit memory accesses before this instruction complete.
+ */
+__STATIC_FORCEINLINE void __DSB(void)
+{
+ __ASM volatile ("dsb 0xF":::"memory");
+}
+
+/**
+ \brief Data Memory Barrier
+ \details Ensures the apparent order of the explicit memory operations before
+ and after the instruction, without ensuring their completion.
+ */
+__STATIC_FORCEINLINE void __DMB(void)
+{
+ __ASM volatile ("dmb 0xF":::"memory");
+}
+
+/**
+ \brief Reverse byte order (32 bit)
+ \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+__STATIC_FORCEINLINE uint32_t __REV(uint32_t value)
+{
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+ return __builtin_bswap32(value);
+#else
+ uint32_t result;
+
+ __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
+ return result;
+#endif
+}
+
+/**
+ \brief Reverse byte order (16 bit)
+ \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#ifndef __NO_EMBEDDED_ASM
+__attribute__((section(".rev16_text"))) __STATIC_INLINE uint32_t __REV16(uint32_t value)
+{
+ uint32_t result;
+ __ASM volatile("rev16 %0, %1" : "=r" (result) : "r" (value));
+ return result;
+}
+#endif
+
+/**
+ \brief Reverse byte order (16 bit)
+ \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+__STATIC_FORCEINLINE int16_t __REVSH(int16_t value)
+{
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+ return (int16_t)__builtin_bswap16(value);
+#else
+ int16_t result;
+
+ __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
+ return result;
+#endif
+}
+
+/**
+ \brief Rotate Right in unsigned value (32 bit)
+ \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
+ \param [in] op1 Value to rotate
+ \param [in] op2 Number of Bits to rotate
+ \return Rotated value
+ */
+__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
+{
+ op2 %= 32U;
+ if (op2 == 0U) {
+ return op1;
+ }
+ return (op1 >> op2) | (op1 << (32U - op2));
+}
+
+
+/**
+ \brief Breakpoint
+ \param [in] value is ignored by the processor.
+ If required, a debugger can use it to store additional information about the breakpoint.
+ */
+#define __BKPT(value) __ASM volatile ("bkpt "#value)
+
+/**
+ \brief Reverse bit order of value
+ \details Reverses the bit order of the given value.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+__STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value)
+{
+ uint32_t result;
+
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) )
+ __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
+#else
+ int32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */
+
+ result = value; /* r will be reversed bits of v; first get LSB of v */
+ for (value >>= 1U; value; value >>= 1U)
+ {
+ result <<= 1U;
+ result |= value & 1U;
+ s--;
+ }
+ result <<= s; /* shift when v's highest bits are zero */
+#endif
+ return result;
+}
+
+/**
+ \brief Count leading zeros
+ \param [in] value Value to count the leading zeros
+ \return number of leading zeros in value
+ */
+#define __CLZ (uint8_t)__builtin_clz
+
+/**
+ \brief LDR Exclusive (8 bit)
+ \details Executes a exclusive LDR instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint8_t __LDREXB(volatile uint8_t *addr)
+{
+ uint32_t result;
+
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+ __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) );
+#else
+ /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
+ accepted by assembler. So has to use following less efficient pattern.
+ */
+ __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
+#endif
+ return ((uint8_t) result); /* Add explicit type cast here */
+}
+
+
+/**
+ \brief LDR Exclusive (16 bit)
+ \details Executes a exclusive LDR instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint16_t __LDREXH(volatile uint16_t *addr)
+{
+ uint32_t result;
+
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+ __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) );
+#else
+ /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
+ accepted by assembler. So has to use following less efficient pattern.
+ */
+ __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
+#endif
+ return ((uint16_t) result); /* Add explicit type cast here */
+}
+
+
+/**
+ \brief LDR Exclusive (32 bit)
+ \details Executes a exclusive LDR instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint32_t __LDREXW(volatile uint32_t *addr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) );
+ return(result);
+}
+
+
+/**
+ \brief STR Exclusive (8 bit)
+ \details Executes a exclusive STR instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+__STATIC_FORCEINLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
+{
+ uint32_t result;
+
+ __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
+ return(result);
+}
+
+
+/**
+ \brief STR Exclusive (16 bit)
+ \details Executes a exclusive STR instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+__STATIC_FORCEINLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
+{
+ uint32_t result;
+
+ __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
+ return(result);
+}
+
+
+/**
+ \brief STR Exclusive (32 bit)
+ \details Executes a exclusive STR instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+__STATIC_FORCEINLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
+{
+ uint32_t result;
+
+ __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) );
+ return(result);
+}
+
+
+/**
+ \brief Remove the exclusive lock
+ \details Removes the exclusive lock which is created by LDREX.
+ */
+__STATIC_FORCEINLINE void __CLREX(void)
+{
+ __ASM volatile ("clrex" ::: "memory");
+}
+
+/**
+ \brief Signed Saturate
+ \details Saturates a signed value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (1..32)
+ \return Saturated value
+ */
+#define __SSAT(ARG1,ARG2) \
+__extension__ \
+({ \
+ int32_t __RES, __ARG1 = (ARG1); \
+ __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
+ __RES; \
+ })
+
+
+/**
+ \brief Unsigned Saturate
+ \details Saturates an unsigned value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (0..31)
+ \return Saturated value
+ */
+#define __USAT(ARG1,ARG2) \
+__extension__ \
+({ \
+ uint32_t __RES, __ARG1 = (ARG1); \
+ __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
+ __RES; \
+ })
+
+/* ########################### Core Function Access ########################### */
+
+/**
+ \brief Enable IRQ Interrupts
+ \details Enables IRQ interrupts by clearing the I-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+__STATIC_FORCEINLINE void __enable_irq(void)
+{
+ __ASM volatile ("cpsie i" : : : "memory");
+}
+
+/**
+ \brief Disable IRQ Interrupts
+ \details Disables IRQ interrupts by setting the I-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+__STATIC_FORCEINLINE void __disable_irq(void)
+{
+ __ASM volatile ("cpsid i" : : : "memory");
+}
+
+/**
+ \brief Get FPSCR
+ \details Returns the current value of the Floating Point Status/Control register.
+ \return Floating Point Status/Control register value
+*/
+__STATIC_FORCEINLINE uint32_t __get_FPSCR(void)
+{
+ #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
+ #if __has_builtin(__builtin_arm_get_fpscr)
+ // Re-enable using built-in when GCC has been fixed
+ // || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
+ /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
+ return __builtin_arm_get_fpscr();
+ #else
+ uint32_t result;
+
+ __ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
+ return(result);
+ #endif
+ #else
+ return(0U);
+ #endif
+}
+
+/**
+ \brief Set FPSCR
+ \details Assigns the given value to the Floating Point Status/Control register.
+ \param [in] fpscr Floating Point Status/Control value to set
+*/
+__STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr)
+{
+ #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
+ #if __has_builtin(__builtin_arm_set_fpscr)
+ // Re-enable using built-in when GCC has been fixed
+ // || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
+ /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
+ __builtin_arm_set_fpscr(fpscr);
+ #else
+ __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory");
+ #endif
+ #else
+ (void)fpscr;
+ #endif
+}
+
+/** \brief Get CPSR Register
+ \return CPSR Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_CPSR(void)
+{
+ uint32_t result;
+ __ASM volatile("MRS %0, cpsr" : "=r" (result) );
+ return(result);
+}
+
+/** \brief Set CPSR Register
+ \param [in] cpsr CPSR value to set
+ */
+__STATIC_FORCEINLINE void __set_CPSR(uint32_t cpsr)
+{
+__ASM volatile ("MSR cpsr, %0" : : "r" (cpsr) : "memory");
+}
+
+/** \brief Get Mode
+ \return Processor Mode
+ */
+__STATIC_FORCEINLINE uint32_t __get_mode(void)
+{
+ return (__get_CPSR() & 0x1FU);
+}
+
+/** \brief Set Mode
+ \param [in] mode Mode value to set
+ */
+__STATIC_FORCEINLINE void __set_mode(uint32_t mode)
+{
+ __ASM volatile("MSR cpsr_c, %0" : : "r" (mode) : "memory");
+}
+
+/** \brief Get Stack Pointer
+ \return Stack Pointer value
+ */
+__STATIC_FORCEINLINE uint32_t __get_SP(void)
+{
+ uint32_t result;
+ __ASM volatile("MOV %0, sp" : "=r" (result) : : "memory");
+ return result;
+}
+
+/** \brief Set Stack Pointer
+ \param [in] stack Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __set_SP(uint32_t stack)
+{
+ __ASM volatile("MOV sp, %0" : : "r" (stack) : "memory");
+}
+
+/** \brief Get USR/SYS Stack Pointer
+ \return USR/SYS Stack Pointer value
+ */
+__STATIC_FORCEINLINE uint32_t __get_SP_usr(void)
+{
+ uint32_t cpsr = __get_CPSR();
+ uint32_t result;
+ __ASM volatile(
+ "CPS #0x1F \n"
+ "MOV %0, sp " : "=r"(result) : : "memory"
+ );
+ __set_CPSR(cpsr);
+ __ISB();
+ return result;
+}
+
+/** \brief Set USR/SYS Stack Pointer
+ \param [in] topOfProcStack USR/SYS Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __set_SP_usr(uint32_t topOfProcStack)
+{
+ uint32_t cpsr = __get_CPSR();
+ __ASM volatile(
+ "CPS #0x1F \n"
+ "MOV sp, %0 " : : "r" (topOfProcStack) : "memory"
+ );
+ __set_CPSR(cpsr);
+ __ISB();
+}
+
+/** \brief Get FPEXC
+ \return Floating Point Exception Control register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_FPEXC(void)
+{
+#if (__FPU_PRESENT == 1)
+ uint32_t result;
+ __ASM volatile("VMRS %0, fpexc" : "=r" (result) );
+ return(result);
+#else
+ return(0);
+#endif
+}
+
+/** \brief Set FPEXC
+ \param [in] fpexc Floating Point Exception Control value to set
+ */
+__STATIC_FORCEINLINE void __set_FPEXC(uint32_t fpexc)
+{
+#if (__FPU_PRESENT == 1)
+ __ASM volatile ("VMSR fpexc, %0" : : "r" (fpexc) : "memory");
+#endif
+}
+
+/*
+ * Include common core functions to access Coprocessor 15 registers
+ */
+
+#define __get_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MRC p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : "=r" (Rt) : : "memory" )
+#define __set_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MCR p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : : "r" (Rt) : "memory" )
+#define __get_CP64(cp, op1, Rt, CRm) __ASM volatile("MRRC p" # cp ", " # op1 ", %Q0, %R0, c" # CRm : "=r" (Rt) : : "memory" )
+#define __set_CP64(cp, op1, Rt, CRm) __ASM volatile("MCRR p" # cp ", " # op1 ", %Q0, %R0, c" # CRm : : "r" (Rt) : "memory" )
+
+#include "cmsis_cp15.h"
+
+/** \brief Enable Floating Point Unit
+
+ Critical section, called from undef handler, so systick is disabled
+ */
+__STATIC_INLINE void __FPU_Enable(void)
+{
+ __ASM volatile(
+ //Permit access to VFP/NEON, registers by modifying CPACR
+ " MRC p15,0,R1,c1,c0,2 \n"
+ " ORR R1,R1,#0x00F00000 \n"
+ " MCR p15,0,R1,c1,c0,2 \n"
+
+ //Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
+ " ISB \n"
+
+ //Enable VFP/NEON
+ " VMRS R1,FPEXC \n"
+ " ORR R1,R1,#0x40000000 \n"
+ " VMSR FPEXC,R1 \n"
+
+ //Initialise VFP/NEON registers to 0
+ " MOV R2,#0 \n"
+
+ //Initialise D16 registers to 0
+ " VMOV D0, R2,R2 \n"
+ " VMOV D1, R2,R2 \n"
+ " VMOV D2, R2,R2 \n"
+ " VMOV D3, R2,R2 \n"
+ " VMOV D4, R2,R2 \n"
+ " VMOV D5, R2,R2 \n"
+ " VMOV D6, R2,R2 \n"
+ " VMOV D7, R2,R2 \n"
+ " VMOV D8, R2,R2 \n"
+ " VMOV D9, R2,R2 \n"
+ " VMOV D10,R2,R2 \n"
+ " VMOV D11,R2,R2 \n"
+ " VMOV D12,R2,R2 \n"
+ " VMOV D13,R2,R2 \n"
+ " VMOV D14,R2,R2 \n"
+ " VMOV D15,R2,R2 \n"
+
+#if (defined(__ARM_NEON) && (__ARM_NEON == 1))
+ //Initialise D32 registers to 0
+ " VMOV D16,R2,R2 \n"
+ " VMOV D17,R2,R2 \n"
+ " VMOV D18,R2,R2 \n"
+ " VMOV D19,R2,R2 \n"
+ " VMOV D20,R2,R2 \n"
+ " VMOV D21,R2,R2 \n"
+ " VMOV D22,R2,R2 \n"
+ " VMOV D23,R2,R2 \n"
+ " VMOV D24,R2,R2 \n"
+ " VMOV D25,R2,R2 \n"
+ " VMOV D26,R2,R2 \n"
+ " VMOV D27,R2,R2 \n"
+ " VMOV D28,R2,R2 \n"
+ " VMOV D29,R2,R2 \n"
+ " VMOV D30,R2,R2 \n"
+ " VMOV D31,R2,R2 \n"
+#endif
+
+ //Initialise FPSCR to a known state
+ " VMRS R2,FPSCR \n"
+ " LDR R3,=0x00086060 \n" //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
+ " AND R2,R2,R3 \n"
+ " VMSR FPSCR,R2 "
+ );
+}
+
+#pragma GCC diagnostic pop
+
+#endif /* __CMSIS_GCC_H */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/cmsis_iccarm.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/cmsis_iccarm.h
new file mode 100644
index 0000000..bb0248d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/cmsis_iccarm.h
@@ -0,0 +1,559 @@
+/**************************************************************************//**
+ * @file cmsis_iccarm.h
+ * @brief CMSIS compiler ICCARM (IAR Compiler for Arm) header file
+ * @version V5.0.6
+ * @date 02. March 2018
+ ******************************************************************************/
+
+//------------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2018 IAR Systems
+//
+// Licensed under the Apache License, Version 2.0 (the "License")
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//------------------------------------------------------------------------------
+
+
+#ifndef __CMSIS_ICCARM_H__
+#define __CMSIS_ICCARM_H__
+
+#ifndef __ICCARM__
+ #error This file should only be compiled by ICCARM
+#endif
+
+#pragma system_include
+
+#define __IAR_FT _Pragma("inline=forced") __intrinsic
+
+#if (__VER__ >= 8000000)
+ #define __ICCARM_V8 1
+#else
+ #define __ICCARM_V8 0
+#endif
+
+#pragma language=extended
+
+#ifndef __ALIGNED
+ #if __ICCARM_V8
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+ #elif (__VER__ >= 7080000)
+ /* Needs IAR language extensions */
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+ #else
+ #warning No compiler specific solution for __ALIGNED.__ALIGNED is ignored.
+ #define __ALIGNED(x)
+ #endif
+#endif
+
+
+/* Define compiler macros for CPU architecture, used in CMSIS 5.
+ */
+#if __ARM_ARCH_7A__
+/* Macro already defined */
+#else
+ #if defined(__ARM7A__)
+ #define __ARM_ARCH_7A__ 1
+ #endif
+#endif
+
+#ifndef __ASM
+ #define __ASM __asm
+#endif
+
+#ifndef __INLINE
+ #define __INLINE inline
+#endif
+
+#ifndef __NO_RETURN
+ #if __ICCARM_V8
+ #define __NO_RETURN __attribute__((__noreturn__))
+ #else
+ #define __NO_RETURN _Pragma("object_attribute=__noreturn")
+ #endif
+#endif
+
+#ifndef __PACKED
+ /* Needs IAR language extensions */
+ #if __ICCARM_V8
+ #define __PACKED __attribute__((packed, aligned(1)))
+ #else
+ #define __PACKED __packed
+ #endif
+#endif
+
+#ifndef __PACKED_STRUCT
+ /* Needs IAR language extensions */
+ #if __ICCARM_V8
+ #define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
+ #else
+ #define __PACKED_STRUCT __packed struct
+ #endif
+#endif
+
+#ifndef __PACKED_UNION
+ /* Needs IAR language extensions */
+ #if __ICCARM_V8
+ #define __PACKED_UNION union __attribute__((packed, aligned(1)))
+ #else
+ #define __PACKED_UNION __packed union
+ #endif
+#endif
+
+#ifndef __RESTRICT
+ #define __RESTRICT __restrict
+#endif
+
+#ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static inline
+#endif
+
+#ifndef __FORCEINLINE
+ #define __FORCEINLINE _Pragma("inline=forced")
+#endif
+
+#ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __FORCEINLINE __STATIC_INLINE
+#endif
+
+#ifndef CMSIS_DEPRECATED
+ #define CMSIS_DEPRECATED __attribute__((deprecated))
+#endif
+
+#ifndef __UNALIGNED_UINT16_READ
+ #pragma language=save
+ #pragma language=extended
+ __IAR_FT uint16_t __iar_uint16_read(void const *ptr)
+ {
+ return *(__packed uint16_t*)(ptr);
+ }
+ #pragma language=restore
+ #define __UNALIGNED_UINT16_READ(PTR) __iar_uint16_read(PTR)
+#endif
+
+
+#ifndef __UNALIGNED_UINT16_WRITE
+ #pragma language=save
+ #pragma language=extended
+ __IAR_FT void __iar_uint16_write(void const *ptr, uint16_t val)
+ {
+ *(__packed uint16_t*)(ptr) = val;;
+ }
+ #pragma language=restore
+ #define __UNALIGNED_UINT16_WRITE(PTR,VAL) __iar_uint16_write(PTR,VAL)
+#endif
+
+#ifndef __UNALIGNED_UINT32_READ
+ #pragma language=save
+ #pragma language=extended
+ __IAR_FT uint32_t __iar_uint32_read(void const *ptr)
+ {
+ return *(__packed uint32_t*)(ptr);
+ }
+ #pragma language=restore
+ #define __UNALIGNED_UINT32_READ(PTR) __iar_uint32_read(PTR)
+#endif
+
+#ifndef __UNALIGNED_UINT32_WRITE
+ #pragma language=save
+ #pragma language=extended
+ __IAR_FT void __iar_uint32_write(void const *ptr, uint32_t val)
+ {
+ *(__packed uint32_t*)(ptr) = val;;
+ }
+ #pragma language=restore
+ #define __UNALIGNED_UINT32_WRITE(PTR,VAL) __iar_uint32_write(PTR,VAL)
+#endif
+
+#if 0
+#ifndef __UNALIGNED_UINT32 /* deprecated */
+ #pragma language=save
+ #pragma language=extended
+ __packed struct __iar_u32 { uint32_t v; };
+ #pragma language=restore
+ #define __UNALIGNED_UINT32(PTR) (((struct __iar_u32 *)(PTR))->v)
+#endif
+#endif
+
+#ifndef __USED
+ #if __ICCARM_V8
+ #define __USED __attribute__((used))
+ #else
+ #define __USED _Pragma("__root")
+ #endif
+#endif
+
+#ifndef __WEAK
+ #if __ICCARM_V8
+ #define __WEAK __attribute__((weak))
+ #else
+ #define __WEAK _Pragma("__weak")
+ #endif
+#endif
+
+
+#ifndef __ICCARM_INTRINSICS_VERSION__
+ #define __ICCARM_INTRINSICS_VERSION__ 0
+#endif
+
+#if __ICCARM_INTRINSICS_VERSION__ == 2
+
+ #if defined(__CLZ)
+ #undef __CLZ
+ #endif
+ #if defined(__REVSH)
+ #undef __REVSH
+ #endif
+ #if defined(__RBIT)
+ #undef __RBIT
+ #endif
+ #if defined(__SSAT)
+ #undef __SSAT
+ #endif
+ #if defined(__USAT)
+ #undef __USAT
+ #endif
+
+ #include "iccarm_builtin.h"
+
+ #define __enable_irq __iar_builtin_enable_interrupt
+ #define __disable_irq __iar_builtin_disable_interrupt
+ #define __enable_fault_irq __iar_builtin_enable_fiq
+ #define __disable_fault_irq __iar_builtin_disable_fiq
+ #define __arm_rsr __iar_builtin_rsr
+ #define __arm_wsr __iar_builtin_wsr
+
+ #if __FPU_PRESENT
+ #define __get_FPSCR() (__arm_rsr("FPSCR"))
+ #else
+ #define __get_FPSCR() ( 0 )
+ #endif
+
+ #define __set_FPSCR(VALUE) (__arm_wsr("FPSCR", VALUE))
+
+ #define __get_CPSR() (__arm_rsr("CPSR"))
+ #define __get_mode() (__get_CPSR() & 0x1FU)
+
+ #define __set_CPSR(VALUE) (__arm_wsr("CPSR", (VALUE)))
+ #define __set_mode(VALUE) (__arm_wsr("CPSR_c", (VALUE)))
+
+
+ #define __get_FPEXC() (__arm_rsr("FPEXC"))
+ #define __set_FPEXC(VALUE) (__arm_wsr("FPEXC", VALUE))
+
+ #define __get_CP(cp, op1, RT, CRn, CRm, op2) \
+ ((RT) = __arm_rsr("p" # cp ":" # op1 ":c" # CRn ":c" # CRm ":" # op2))
+
+ #define __set_CP(cp, op1, RT, CRn, CRm, op2) \
+ (__arm_wsr("p" # cp ":" # op1 ":c" # CRn ":c" # CRm ":" # op2, (RT)))
+
+ #define __get_CP64(cp, op1, Rt, CRm) \
+ __ASM volatile("MRRC p" # cp ", " # op1 ", %Q0, %R0, c" # CRm : "=r" (Rt) : : "memory" )
+
+ #define __set_CP64(cp, op1, Rt, CRm) \
+ __ASM volatile("MCRR p" # cp ", " # op1 ", %Q0, %R0, c" # CRm : : "r" (Rt) : "memory" )
+
+ #include "cmsis_cp15.h"
+
+ #define __NOP __iar_builtin_no_operation
+
+ #define __CLZ __iar_builtin_CLZ
+ #define __CLREX __iar_builtin_CLREX
+
+ #define __DMB __iar_builtin_DMB
+ #define __DSB __iar_builtin_DSB
+ #define __ISB __iar_builtin_ISB
+
+ #define __LDREXB __iar_builtin_LDREXB
+ #define __LDREXH __iar_builtin_LDREXH
+ #define __LDREXW __iar_builtin_LDREX
+
+ #define __RBIT __iar_builtin_RBIT
+ #define __REV __iar_builtin_REV
+ #define __REV16 __iar_builtin_REV16
+
+ __IAR_FT int16_t __REVSH(int16_t val)
+ {
+ return (int16_t) __iar_builtin_REVSH(val);
+ }
+
+ #define __ROR __iar_builtin_ROR
+ #define __RRX __iar_builtin_RRX
+
+ #define __SEV __iar_builtin_SEV
+
+ #define __SSAT __iar_builtin_SSAT
+
+ #define __STREXB __iar_builtin_STREXB
+ #define __STREXH __iar_builtin_STREXH
+ #define __STREXW __iar_builtin_STREX
+
+ #define __USAT __iar_builtin_USAT
+
+ #define __WFE __iar_builtin_WFE
+ #define __WFI __iar_builtin_WFI
+
+ #define __SADD8 __iar_builtin_SADD8
+ #define __QADD8 __iar_builtin_QADD8
+ #define __SHADD8 __iar_builtin_SHADD8
+ #define __UADD8 __iar_builtin_UADD8
+ #define __UQADD8 __iar_builtin_UQADD8
+ #define __UHADD8 __iar_builtin_UHADD8
+ #define __SSUB8 __iar_builtin_SSUB8
+ #define __QSUB8 __iar_builtin_QSUB8
+ #define __SHSUB8 __iar_builtin_SHSUB8
+ #define __USUB8 __iar_builtin_USUB8
+ #define __UQSUB8 __iar_builtin_UQSUB8
+ #define __UHSUB8 __iar_builtin_UHSUB8
+ #define __SADD16 __iar_builtin_SADD16
+ #define __QADD16 __iar_builtin_QADD16
+ #define __SHADD16 __iar_builtin_SHADD16
+ #define __UADD16 __iar_builtin_UADD16
+ #define __UQADD16 __iar_builtin_UQADD16
+ #define __UHADD16 __iar_builtin_UHADD16
+ #define __SSUB16 __iar_builtin_SSUB16
+ #define __QSUB16 __iar_builtin_QSUB16
+ #define __SHSUB16 __iar_builtin_SHSUB16
+ #define __USUB16 __iar_builtin_USUB16
+ #define __UQSUB16 __iar_builtin_UQSUB16
+ #define __UHSUB16 __iar_builtin_UHSUB16
+ #define __SASX __iar_builtin_SASX
+ #define __QASX __iar_builtin_QASX
+ #define __SHASX __iar_builtin_SHASX
+ #define __UASX __iar_builtin_UASX
+ #define __UQASX __iar_builtin_UQASX
+ #define __UHASX __iar_builtin_UHASX
+ #define __SSAX __iar_builtin_SSAX
+ #define __QSAX __iar_builtin_QSAX
+ #define __SHSAX __iar_builtin_SHSAX
+ #define __USAX __iar_builtin_USAX
+ #define __UQSAX __iar_builtin_UQSAX
+ #define __UHSAX __iar_builtin_UHSAX
+ #define __USAD8 __iar_builtin_USAD8
+ #define __USADA8 __iar_builtin_USADA8
+ #define __SSAT16 __iar_builtin_SSAT16
+ #define __USAT16 __iar_builtin_USAT16
+ #define __UXTB16 __iar_builtin_UXTB16
+ #define __UXTAB16 __iar_builtin_UXTAB16
+ #define __SXTB16 __iar_builtin_SXTB16
+ #define __SXTAB16 __iar_builtin_SXTAB16
+ #define __SMUAD __iar_builtin_SMUAD
+ #define __SMUADX __iar_builtin_SMUADX
+ #define __SMMLA __iar_builtin_SMMLA
+ #define __SMLAD __iar_builtin_SMLAD
+ #define __SMLADX __iar_builtin_SMLADX
+ #define __SMLALD __iar_builtin_SMLALD
+ #define __SMLALDX __iar_builtin_SMLALDX
+ #define __SMUSD __iar_builtin_SMUSD
+ #define __SMUSDX __iar_builtin_SMUSDX
+ #define __SMLSD __iar_builtin_SMLSD
+ #define __SMLSDX __iar_builtin_SMLSDX
+ #define __SMLSLD __iar_builtin_SMLSLD
+ #define __SMLSLDX __iar_builtin_SMLSLDX
+ #define __SEL __iar_builtin_SEL
+ #define __QADD __iar_builtin_QADD
+ #define __QSUB __iar_builtin_QSUB
+ #define __PKHBT __iar_builtin_PKHBT
+ #define __PKHTB __iar_builtin_PKHTB
+
+#else /* __ICCARM_INTRINSICS_VERSION__ == 2 */
+
+ #if !__FPU_PRESENT
+ #define __get_FPSCR __cmsis_iar_get_FPSR_not_active
+ #endif
+
+ #ifdef __INTRINSICS_INCLUDED
+ #error intrinsics.h is already included previously!
+ #endif
+
+ #include
+
+ #if !__FPU_PRESENT
+ #define __get_FPSCR() (0)
+ #endif
+
+ #pragma diag_suppress=Pe940
+ #pragma diag_suppress=Pe177
+
+ #define __enable_irq __enable_interrupt
+ #define __disable_irq __disable_interrupt
+ #define __enable_fault_irq __enable_fiq
+ #define __disable_fault_irq __disable_fiq
+ #define __NOP __no_operation
+
+ #define __get_xPSR __get_PSR
+
+ __IAR_FT void __set_mode(uint32_t mode)
+ {
+ __ASM volatile("MSR cpsr_c, %0" : : "r" (mode) : "memory");
+ }
+
+ __IAR_FT uint32_t __LDREXW(uint32_t volatile *ptr)
+ {
+ return __LDREX((unsigned long *)ptr);
+ }
+
+ __IAR_FT uint32_t __STREXW(uint32_t value, uint32_t volatile *ptr)
+ {
+ return __STREX(value, (unsigned long *)ptr);
+ }
+
+
+ __IAR_FT uint32_t __RRX(uint32_t value)
+ {
+ uint32_t result;
+ __ASM("RRX %0, %1" : "=r"(result) : "r" (value) : "cc");
+ return(result);
+ }
+
+
+ __IAR_FT uint32_t __ROR(uint32_t op1, uint32_t op2)
+ {
+ return (op1 >> op2) | (op1 << ((sizeof(op1)*8)-op2));
+ }
+
+ __IAR_FT uint32_t __get_FPEXC(void)
+ {
+ #if (__FPU_PRESENT == 1)
+ uint32_t result;
+ __ASM volatile("VMRS %0, fpexc" : "=r" (result) : : "memory");
+ return(result);
+ #else
+ return(0);
+ #endif
+ }
+
+ __IAR_FT void __set_FPEXC(uint32_t fpexc)
+ {
+ #if (__FPU_PRESENT == 1)
+ __ASM volatile ("VMSR fpexc, %0" : : "r" (fpexc) : "memory");
+ #endif
+ }
+
+
+ #define __get_CP(cp, op1, Rt, CRn, CRm, op2) \
+ __ASM volatile("MRC p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : "=r" (Rt) : : "memory" )
+ #define __set_CP(cp, op1, Rt, CRn, CRm, op2) \
+ __ASM volatile("MCR p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : : "r" (Rt) : "memory" )
+ #define __get_CP64(cp, op1, Rt, CRm) \
+ __ASM volatile("MRRC p" # cp ", " # op1 ", %Q0, %R0, c" # CRm : "=r" (Rt) : : "memory" )
+ #define __set_CP64(cp, op1, Rt, CRm) \
+ __ASM volatile("MCRR p" # cp ", " # op1 ", %Q0, %R0, c" # CRm : : "r" (Rt) : "memory" )
+
+ #include "cmsis_cp15.h"
+
+#endif /* __ICCARM_INTRINSICS_VERSION__ == 2 */
+
+#define __BKPT(value) __asm volatile ("BKPT %0" : : "i"(value))
+
+
+__IAR_FT uint32_t __get_SP_usr(void)
+{
+ uint32_t cpsr;
+ uint32_t result;
+ __ASM volatile(
+ "MRS %0, cpsr \n"
+ "CPS #0x1F \n" // no effect in USR mode
+ "MOV %1, sp \n"
+ "MSR cpsr_c, %2 \n" // no effect in USR mode
+ "ISB" : "=r"(cpsr), "=r"(result) : "r"(cpsr) : "memory"
+ );
+ return result;
+}
+
+__IAR_FT void __set_SP_usr(uint32_t topOfProcStack)
+{
+ uint32_t cpsr;
+ __ASM volatile(
+ "MRS %0, cpsr \n"
+ "CPS #0x1F \n" // no effect in USR mode
+ "MOV sp, %1 \n"
+ "MSR cpsr_c, %2 \n" // no effect in USR mode
+ "ISB" : "=r"(cpsr) : "r" (topOfProcStack), "r"(cpsr) : "memory"
+ );
+}
+
+#define __get_mode() (__get_CPSR() & 0x1FU)
+
+__STATIC_INLINE
+void __FPU_Enable(void)
+{
+ __ASM volatile(
+ //Permit access to VFP/NEON, registers by modifying CPACR
+ " MRC p15,0,R1,c1,c0,2 \n"
+ " ORR R1,R1,#0x00F00000 \n"
+ " MCR p15,0,R1,c1,c0,2 \n"
+
+ //Ensure that subsequent instructions occur in the context of VFP/NEON access permitted
+ " ISB \n"
+
+ //Enable VFP/NEON
+ " VMRS R1,FPEXC \n"
+ " ORR R1,R1,#0x40000000 \n"
+ " VMSR FPEXC,R1 \n"
+
+ //Initialise VFP/NEON registers to 0
+ " MOV R2,#0 \n"
+
+ //Initialise D16 registers to 0
+ " VMOV D0, R2,R2 \n"
+ " VMOV D1, R2,R2 \n"
+ " VMOV D2, R2,R2 \n"
+ " VMOV D3, R2,R2 \n"
+ " VMOV D4, R2,R2 \n"
+ " VMOV D5, R2,R2 \n"
+ " VMOV D6, R2,R2 \n"
+ " VMOV D7, R2,R2 \n"
+ " VMOV D8, R2,R2 \n"
+ " VMOV D9, R2,R2 \n"
+ " VMOV D10,R2,R2 \n"
+ " VMOV D11,R2,R2 \n"
+ " VMOV D12,R2,R2 \n"
+ " VMOV D13,R2,R2 \n"
+ " VMOV D14,R2,R2 \n"
+ " VMOV D15,R2,R2 \n"
+
+#ifdef __ARM_ADVANCED_SIMD__
+ //Initialise D32 registers to 0
+ " VMOV D16,R2,R2 \n"
+ " VMOV D17,R2,R2 \n"
+ " VMOV D18,R2,R2 \n"
+ " VMOV D19,R2,R2 \n"
+ " VMOV D20,R2,R2 \n"
+ " VMOV D21,R2,R2 \n"
+ " VMOV D22,R2,R2 \n"
+ " VMOV D23,R2,R2 \n"
+ " VMOV D24,R2,R2 \n"
+ " VMOV D25,R2,R2 \n"
+ " VMOV D26,R2,R2 \n"
+ " VMOV D27,R2,R2 \n"
+ " VMOV D28,R2,R2 \n"
+ " VMOV D29,R2,R2 \n"
+ " VMOV D30,R2,R2 \n"
+ " VMOV D31,R2,R2 \n"
+#endif
+
+ //Initialise FPSCR to a known state
+ " VMRS R2,FPSCR \n"
+ " MOV32 R3,#0x00086060 \n" //Mask off all bits that do not have to be preserved. Non-preserved bits can/should be zero.
+ " AND R2,R2,R3 \n"
+ " VMSR FPSCR,R2 \n");
+}
+
+
+
+#undef __IAR_FT
+#undef __ICCARM_V8
+
+#pragma diag_default=Pe940
+#pragma diag_default=Pe177
+
+#endif /* __CMSIS_ICCARM_H__ */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/core_ca.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/core_ca.h
new file mode 100644
index 0000000..dbe9794
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/core_ca.h
@@ -0,0 +1,2614 @@
+/**************************************************************************//**
+ * @file core_ca.h
+ * @brief CMSIS Cortex-A Core Peripheral Access Layer Header File
+ * @version V1.0.1
+ * @date 07. May 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#ifndef __CORE_CA_H_GENERIC
+#define __CORE_CA_H_GENERIC
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+
+/* CMSIS CA definitions */
+#define __CA_CMSIS_VERSION_MAIN (1U) /*!< \brief [31:16] CMSIS-Core(A) main version */
+#define __CA_CMSIS_VERSION_SUB (1U) /*!< \brief [15:0] CMSIS-Core(A) sub version */
+#define __CA_CMSIS_VERSION ((__CA_CMSIS_VERSION_MAIN << 16U) | \
+ __CA_CMSIS_VERSION_SUB ) /*!< \brief CMSIS-Core(A) version number */
+
+#if defined ( __CC_ARM )
+ #if defined __TARGET_FPU_VFP
+ #if (__FPU_PRESENT == 1)
+ #define __FPU_USED 1U
+ #else
+ #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_PCS_VFP
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined __ARMVFP__
+ #if (__FPU_PRESENT == 1)
+ #define __FPU_USED 1U
+ #else
+ #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __TMS470__ )
+ #if defined __TI_VFP_SUPPORT__
+ #if (__FPU_PRESENT == 1)
+ #define __FPU_USED 1U
+ #else
+ #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #if (__FPU_PRESENT == 1)
+ #define __FPU_USED 1U
+ #else
+ #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined __FPU_VFP__
+ #if (__FPU_PRESENT == 1)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CA_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_CA_H_DEPENDANT
+#define __CORE_CA_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+ /* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __CA_REV
+ #define __CA_REV 0x0000U
+ #warning "__CA_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __FPU_PRESENT
+ #define __FPU_PRESENT 0U
+ #warning "__FPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __GIC_PRESENT
+ #define __GIC_PRESENT 1U
+ #warning "__GIC_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __TIM_PRESENT
+ #define __TIM_PRESENT 1U
+ #warning "__TIM_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __L2C_PRESENT
+ #define __L2C_PRESENT 0U
+ #warning "__L2C_PRESENT not defined in device header file; using default!"
+ #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+#ifdef __cplusplus
+ #define __I volatile /*!< \brief Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< \brief Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< \brief Defines 'write only' permissions */
+#define __IO volatile /*!< \brief Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*!< \brief Defines 'read only' structure member permissions */
+#define __OM volatile /*!< \brief Defines 'write only' structure member permissions */
+#define __IOM volatile /*!< \brief Defines 'read / write' structure member permissions */
+#define RESERVED(N, T) T RESERVED##N; // placeholder struct members used for "reserved" areas
+
+ /*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - CPSR
+ - CP15 Registers
+ - L2C-310 Cache Controller
+ - Generic Interrupt Controller Distributor
+ - Generic Interrupt Controller Interface
+ ******************************************************************************/
+
+/* Core Register CPSR */
+typedef union
+{
+ struct
+ {
+ uint32_t M:5; /*!< \brief bit: 0.. 4 Mode field */
+ uint32_t T:1; /*!< \brief bit: 5 Thumb execution state bit */
+ uint32_t F:1; /*!< \brief bit: 6 FIQ mask bit */
+ uint32_t I:1; /*!< \brief bit: 7 IRQ mask bit */
+ uint32_t A:1; /*!< \brief bit: 8 Asynchronous abort mask bit */
+ uint32_t E:1; /*!< \brief bit: 9 Endianness execution state bit */
+ uint32_t IT1:6; /*!< \brief bit: 10..15 If-Then execution state bits 2-7 */
+ uint32_t GE:4; /*!< \brief bit: 16..19 Greater than or Equal flags */
+ RESERVED(0:4, uint32_t)
+ uint32_t J:1; /*!< \brief bit: 24 Jazelle bit */
+ uint32_t IT0:2; /*!< \brief bit: 25..26 If-Then execution state bits 0-1 */
+ uint32_t Q:1; /*!< \brief bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< \brief bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< \brief bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< \brief bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< \brief bit: 31 Negative condition code flag */
+ } b; /*!< \brief Structure used for bit access */
+ uint32_t w; /*!< \brief Type used for word access */
+} CPSR_Type;
+
+
+
+/* CPSR Register Definitions */
+#define CPSR_N_Pos 31U /*!< \brief CPSR: N Position */
+#define CPSR_N_Msk (1UL << CPSR_N_Pos) /*!< \brief CPSR: N Mask */
+
+#define CPSR_Z_Pos 30U /*!< \brief CPSR: Z Position */
+#define CPSR_Z_Msk (1UL << CPSR_Z_Pos) /*!< \brief CPSR: Z Mask */
+
+#define CPSR_C_Pos 29U /*!< \brief CPSR: C Position */
+#define CPSR_C_Msk (1UL << CPSR_C_Pos) /*!< \brief CPSR: C Mask */
+
+#define CPSR_V_Pos 28U /*!< \brief CPSR: V Position */
+#define CPSR_V_Msk (1UL << CPSR_V_Pos) /*!< \brief CPSR: V Mask */
+
+#define CPSR_Q_Pos 27U /*!< \brief CPSR: Q Position */
+#define CPSR_Q_Msk (1UL << CPSR_Q_Pos) /*!< \brief CPSR: Q Mask */
+
+#define CPSR_IT0_Pos 25U /*!< \brief CPSR: IT0 Position */
+#define CPSR_IT0_Msk (3UL << CPSR_IT0_Pos) /*!< \brief CPSR: IT0 Mask */
+
+#define CPSR_J_Pos 24U /*!< \brief CPSR: J Position */
+#define CPSR_J_Msk (1UL << CPSR_J_Pos) /*!< \brief CPSR: J Mask */
+
+#define CPSR_GE_Pos 16U /*!< \brief CPSR: GE Position */
+#define CPSR_GE_Msk (0xFUL << CPSR_GE_Pos) /*!< \brief CPSR: GE Mask */
+
+#define CPSR_IT1_Pos 10U /*!< \brief CPSR: IT1 Position */
+#define CPSR_IT1_Msk (0x3FUL << CPSR_IT1_Pos) /*!< \brief CPSR: IT1 Mask */
+
+#define CPSR_E_Pos 9U /*!< \brief CPSR: E Position */
+#define CPSR_E_Msk (1UL << CPSR_E_Pos) /*!< \brief CPSR: E Mask */
+
+#define CPSR_A_Pos 8U /*!< \brief CPSR: A Position */
+#define CPSR_A_Msk (1UL << CPSR_A_Pos) /*!< \brief CPSR: A Mask */
+
+#define CPSR_I_Pos 7U /*!< \brief CPSR: I Position */
+#define CPSR_I_Msk (1UL << CPSR_I_Pos) /*!< \brief CPSR: I Mask */
+
+#define CPSR_F_Pos 6U /*!< \brief CPSR: F Position */
+#define CPSR_F_Msk (1UL << CPSR_F_Pos) /*!< \brief CPSR: F Mask */
+
+#define CPSR_T_Pos 5U /*!< \brief CPSR: T Position */
+#define CPSR_T_Msk (1UL << CPSR_T_Pos) /*!< \brief CPSR: T Mask */
+
+#define CPSR_M_Pos 0U /*!< \brief CPSR: M Position */
+#define CPSR_M_Msk (0x1FUL << CPSR_M_Pos) /*!< \brief CPSR: M Mask */
+
+#define CPSR_M_USR 0x10U /*!< \brief CPSR: M User mode (PL0) */
+#define CPSR_M_FIQ 0x11U /*!< \brief CPSR: M Fast Interrupt mode (PL1) */
+#define CPSR_M_IRQ 0x12U /*!< \brief CPSR: M Interrupt mode (PL1) */
+#define CPSR_M_SVC 0x13U /*!< \brief CPSR: M Supervisor mode (PL1) */
+#define CPSR_M_MON 0x16U /*!< \brief CPSR: M Monitor mode (PL1) */
+#define CPSR_M_ABT 0x17U /*!< \brief CPSR: M Abort mode (PL1) */
+#define CPSR_M_HYP 0x1AU /*!< \brief CPSR: M Hypervisor mode (PL2) */
+#define CPSR_M_UND 0x1BU /*!< \brief CPSR: M Undefined mode (PL1) */
+#define CPSR_M_SYS 0x1FU /*!< \brief CPSR: M System mode (PL1) */
+
+/* CP15 Register SCTLR */
+typedef union
+{
+ struct
+ {
+ uint32_t M:1; /*!< \brief bit: 0 MMU enable */
+ uint32_t A:1; /*!< \brief bit: 1 Alignment check enable */
+ uint32_t C:1; /*!< \brief bit: 2 Cache enable */
+ RESERVED(0:2, uint32_t)
+ uint32_t CP15BEN:1; /*!< \brief bit: 5 CP15 barrier enable */
+ RESERVED(1:1, uint32_t)
+ uint32_t B:1; /*!< \brief bit: 7 Endianness model */
+ RESERVED(2:2, uint32_t)
+ uint32_t SW:1; /*!< \brief bit: 10 SWP and SWPB enable */
+ uint32_t Z:1; /*!< \brief bit: 11 Branch prediction enable */
+ uint32_t I:1; /*!< \brief bit: 12 Instruction cache enable */
+ uint32_t V:1; /*!< \brief bit: 13 Vectors bit */
+ uint32_t RR:1; /*!< \brief bit: 14 Round Robin select */
+ RESERVED(3:2, uint32_t)
+ uint32_t HA:1; /*!< \brief bit: 17 Hardware Access flag enable */
+ RESERVED(4:1, uint32_t)
+ uint32_t WXN:1; /*!< \brief bit: 19 Write permission implies XN */
+ uint32_t UWXN:1; /*!< \brief bit: 20 Unprivileged write permission implies PL1 XN */
+ uint32_t FI:1; /*!< \brief bit: 21 Fast interrupts configuration enable */
+ uint32_t U:1; /*!< \brief bit: 22 Alignment model */
+ RESERVED(5:1, uint32_t)
+ uint32_t VE:1; /*!< \brief bit: 24 Interrupt Vectors Enable */
+ uint32_t EE:1; /*!< \brief bit: 25 Exception Endianness */
+ RESERVED(6:1, uint32_t)
+ uint32_t NMFI:1; /*!< \brief bit: 27 Non-maskable FIQ (NMFI) support */
+ uint32_t TRE:1; /*!< \brief bit: 28 TEX remap enable. */
+ uint32_t AFE:1; /*!< \brief bit: 29 Access flag enable */
+ uint32_t TE:1; /*!< \brief bit: 30 Thumb Exception enable */
+ RESERVED(7:1, uint32_t)
+ } b; /*!< \brief Structure used for bit access */
+ uint32_t w; /*!< \brief Type used for word access */
+} SCTLR_Type;
+
+#define SCTLR_TE_Pos 30U /*!< \brief SCTLR: TE Position */
+#define SCTLR_TE_Msk (1UL << SCTLR_TE_Pos) /*!< \brief SCTLR: TE Mask */
+
+#define SCTLR_AFE_Pos 29U /*!< \brief SCTLR: AFE Position */
+#define SCTLR_AFE_Msk (1UL << SCTLR_AFE_Pos) /*!< \brief SCTLR: AFE Mask */
+
+#define SCTLR_TRE_Pos 28U /*!< \brief SCTLR: TRE Position */
+#define SCTLR_TRE_Msk (1UL << SCTLR_TRE_Pos) /*!< \brief SCTLR: TRE Mask */
+
+#define SCTLR_NMFI_Pos 27U /*!< \brief SCTLR: NMFI Position */
+#define SCTLR_NMFI_Msk (1UL << SCTLR_NMFI_Pos) /*!< \brief SCTLR: NMFI Mask */
+
+#define SCTLR_EE_Pos 25U /*!< \brief SCTLR: EE Position */
+#define SCTLR_EE_Msk (1UL << SCTLR_EE_Pos) /*!< \brief SCTLR: EE Mask */
+
+#define SCTLR_VE_Pos 24U /*!< \brief SCTLR: VE Position */
+#define SCTLR_VE_Msk (1UL << SCTLR_VE_Pos) /*!< \brief SCTLR: VE Mask */
+
+#define SCTLR_U_Pos 22U /*!< \brief SCTLR: U Position */
+#define SCTLR_U_Msk (1UL << SCTLR_U_Pos) /*!< \brief SCTLR: U Mask */
+
+#define SCTLR_FI_Pos 21U /*!< \brief SCTLR: FI Position */
+#define SCTLR_FI_Msk (1UL << SCTLR_FI_Pos) /*!< \brief SCTLR: FI Mask */
+
+#define SCTLR_UWXN_Pos 20U /*!< \brief SCTLR: UWXN Position */
+#define SCTLR_UWXN_Msk (1UL << SCTLR_UWXN_Pos) /*!< \brief SCTLR: UWXN Mask */
+
+#define SCTLR_WXN_Pos 19U /*!< \brief SCTLR: WXN Position */
+#define SCTLR_WXN_Msk (1UL << SCTLR_WXN_Pos) /*!< \brief SCTLR: WXN Mask */
+
+#define SCTLR_HA_Pos 17U /*!< \brief SCTLR: HA Position */
+#define SCTLR_HA_Msk (1UL << SCTLR_HA_Pos) /*!< \brief SCTLR: HA Mask */
+
+#define SCTLR_RR_Pos 14U /*!< \brief SCTLR: RR Position */
+#define SCTLR_RR_Msk (1UL << SCTLR_RR_Pos) /*!< \brief SCTLR: RR Mask */
+
+#define SCTLR_V_Pos 13U /*!< \brief SCTLR: V Position */
+#define SCTLR_V_Msk (1UL << SCTLR_V_Pos) /*!< \brief SCTLR: V Mask */
+
+#define SCTLR_I_Pos 12U /*!< \brief SCTLR: I Position */
+#define SCTLR_I_Msk (1UL << SCTLR_I_Pos) /*!< \brief SCTLR: I Mask */
+
+#define SCTLR_Z_Pos 11U /*!< \brief SCTLR: Z Position */
+#define SCTLR_Z_Msk (1UL << SCTLR_Z_Pos) /*!< \brief SCTLR: Z Mask */
+
+#define SCTLR_SW_Pos 10U /*!< \brief SCTLR: SW Position */
+#define SCTLR_SW_Msk (1UL << SCTLR_SW_Pos) /*!< \brief SCTLR: SW Mask */
+
+#define SCTLR_B_Pos 7U /*!< \brief SCTLR: B Position */
+#define SCTLR_B_Msk (1UL << SCTLR_B_Pos) /*!< \brief SCTLR: B Mask */
+
+#define SCTLR_CP15BEN_Pos 5U /*!< \brief SCTLR: CP15BEN Position */
+#define SCTLR_CP15BEN_Msk (1UL << SCTLR_CP15BEN_Pos) /*!< \brief SCTLR: CP15BEN Mask */
+
+#define SCTLR_C_Pos 2U /*!< \brief SCTLR: C Position */
+#define SCTLR_C_Msk (1UL << SCTLR_C_Pos) /*!< \brief SCTLR: C Mask */
+
+#define SCTLR_A_Pos 1U /*!< \brief SCTLR: A Position */
+#define SCTLR_A_Msk (1UL << SCTLR_A_Pos) /*!< \brief SCTLR: A Mask */
+
+#define SCTLR_M_Pos 0U /*!< \brief SCTLR: M Position */
+#define SCTLR_M_Msk (1UL << SCTLR_M_Pos) /*!< \brief SCTLR: M Mask */
+
+/* CP15 Register ACTLR */
+typedef union
+{
+#if __CORTEX_A == 5 || defined(DOXYGEN)
+ /** \brief Structure used for bit access on Cortex-A5 */
+ struct
+ {
+ uint32_t FW:1; /*!< \brief bit: 0 Cache and TLB maintenance broadcast */
+ RESERVED(0:5, uint32_t)
+ uint32_t SMP:1; /*!< \brief bit: 6 Enables coherent requests to the processor */
+ uint32_t EXCL:1; /*!< \brief bit: 7 Exclusive L1/L2 cache control */
+ RESERVED(1:2, uint32_t)
+ uint32_t DODMBS:1; /*!< \brief bit: 10 Disable optimized data memory barrier behavior */
+ uint32_t DWBST:1; /*!< \brief bit: 11 AXI data write bursts to Normal memory */
+ uint32_t RADIS:1; /*!< \brief bit: 12 L1 Data Cache read-allocate mode disable */
+ uint32_t L1PCTL:2; /*!< \brief bit:13..14 L1 Data prefetch control */
+ uint32_t BP:2; /*!< \brief bit:16..15 Branch prediction policy */
+ uint32_t RSDIS:1; /*!< \brief bit: 17 Disable return stack operation */
+ uint32_t BTDIS:1; /*!< \brief bit: 18 Disable indirect Branch Target Address Cache (BTAC) */
+ RESERVED(3:9, uint32_t)
+ uint32_t DBDI:1; /*!< \brief bit: 28 Disable branch dual issue */
+ RESERVED(7:3, uint32_t)
+ } b;
+#endif
+#if __CORTEX_A == 7 || defined(DOXYGEN)
+ /** \brief Structure used for bit access on Cortex-A7 */
+ struct
+ {
+ RESERVED(0:6, uint32_t)
+ uint32_t SMP:1; /*!< \brief bit: 6 Enables coherent requests to the processor */
+ RESERVED(1:3, uint32_t)
+ uint32_t DODMBS:1; /*!< \brief bit: 10 Disable optimized data memory barrier behavior */
+ uint32_t L2RADIS:1; /*!< \brief bit: 11 L2 Data Cache read-allocate mode disable */
+ uint32_t L1RADIS:1; /*!< \brief bit: 12 L1 Data Cache read-allocate mode disable */
+ uint32_t L1PCTL:2; /*!< \brief bit:13..14 L1 Data prefetch control */
+ uint32_t DDVM:1; /*!< \brief bit: 15 Disable Distributed Virtual Memory (DVM) transactions */
+ RESERVED(3:12, uint32_t)
+ uint32_t DDI:1; /*!< \brief bit: 28 Disable dual issue */
+ RESERVED(7:3, uint32_t)
+ } b;
+#endif
+#if __CORTEX_A == 9 || defined(DOXYGEN)
+ /** \brief Structure used for bit access on Cortex-A9 */
+ struct
+ {
+ uint32_t FW:1; /*!< \brief bit: 0 Cache and TLB maintenance broadcast */
+ RESERVED(0:1, uint32_t)
+ uint32_t L1PE:1; /*!< \brief bit: 2 Dside prefetch */
+ uint32_t WFLZM:1; /*!< \brief bit: 3 Cache and TLB maintenance broadcast */
+ RESERVED(1:2, uint32_t)
+ uint32_t SMP:1; /*!< \brief bit: 6 Enables coherent requests to the processor */
+ uint32_t EXCL:1; /*!< \brief bit: 7 Exclusive L1/L2 cache control */
+ uint32_t AOW:1; /*!< \brief bit: 8 Enable allocation in one cache way only */
+ uint32_t PARITY:1; /*!< \brief bit: 9 Support for parity checking, if implemented */
+ RESERVED(7:22, uint32_t)
+ } b;
+#endif
+ uint32_t w; /*!< \brief Type used for word access */
+} ACTLR_Type;
+
+#define ACTLR_DDI_Pos 28U /*!< \brief ACTLR: DDI Position */
+#define ACTLR_DDI_Msk (1UL << ACTLR_DDI_Pos) /*!< \brief ACTLR: DDI Mask */
+
+#define ACTLR_DBDI_Pos 28U /*!< \brief ACTLR: DBDI Position */
+#define ACTLR_DBDI_Msk (1UL << ACTLR_DBDI_Pos) /*!< \brief ACTLR: DBDI Mask */
+
+#define ACTLR_BTDIS_Pos 18U /*!< \brief ACTLR: BTDIS Position */
+#define ACTLR_BTDIS_Msk (1UL << ACTLR_BTDIS_Pos) /*!< \brief ACTLR: BTDIS Mask */
+
+#define ACTLR_RSDIS_Pos 17U /*!< \brief ACTLR: RSDIS Position */
+#define ACTLR_RSDIS_Msk (1UL << ACTLR_RSDIS_Pos) /*!< \brief ACTLR: RSDIS Mask */
+
+#define ACTLR_BP_Pos 15U /*!< \brief ACTLR: BP Position */
+#define ACTLR_BP_Msk (3UL << ACTLR_BP_Pos) /*!< \brief ACTLR: BP Mask */
+
+#define ACTLR_DDVM_Pos 15U /*!< \brief ACTLR: DDVM Position */
+#define ACTLR_DDVM_Msk (1UL << ACTLR_DDVM_Pos) /*!< \brief ACTLR: DDVM Mask */
+
+#define ACTLR_L1PCTL_Pos 13U /*!< \brief ACTLR: L1PCTL Position */
+#define ACTLR_L1PCTL_Msk (3UL << ACTLR_L1PCTL_Pos) /*!< \brief ACTLR: L1PCTL Mask */
+
+#define ACTLR_RADIS_Pos 12U /*!< \brief ACTLR: RADIS Position */
+#define ACTLR_RADIS_Msk (1UL << ACTLR_RADIS_Pos) /*!< \brief ACTLR: RADIS Mask */
+
+#define ACTLR_L1RADIS_Pos 12U /*!< \brief ACTLR: L1RADIS Position */
+#define ACTLR_L1RADIS_Msk (1UL << ACTLR_L1RADIS_Pos) /*!< \brief ACTLR: L1RADIS Mask */
+
+#define ACTLR_DWBST_Pos 11U /*!< \brief ACTLR: DWBST Position */
+#define ACTLR_DWBST_Msk (1UL << ACTLR_DWBST_Pos) /*!< \brief ACTLR: DWBST Mask */
+
+#define ACTLR_L2RADIS_Pos 11U /*!< \brief ACTLR: L2RADIS Position */
+#define ACTLR_L2RADIS_Msk (1UL << ACTLR_L2RADIS_Pos) /*!< \brief ACTLR: L2RADIS Mask */
+
+#define ACTLR_DODMBS_Pos 10U /*!< \brief ACTLR: DODMBS Position */
+#define ACTLR_DODMBS_Msk (1UL << ACTLR_DODMBS_Pos) /*!< \brief ACTLR: DODMBS Mask */
+
+#define ACTLR_PARITY_Pos 9U /*!< \brief ACTLR: PARITY Position */
+#define ACTLR_PARITY_Msk (1UL << ACTLR_PARITY_Pos) /*!< \brief ACTLR: PARITY Mask */
+
+#define ACTLR_AOW_Pos 8U /*!< \brief ACTLR: AOW Position */
+#define ACTLR_AOW_Msk (1UL << ACTLR_AOW_Pos) /*!< \brief ACTLR: AOW Mask */
+
+#define ACTLR_EXCL_Pos 7U /*!< \brief ACTLR: EXCL Position */
+#define ACTLR_EXCL_Msk (1UL << ACTLR_EXCL_Pos) /*!< \brief ACTLR: EXCL Mask */
+
+#define ACTLR_SMP_Pos 6U /*!< \brief ACTLR: SMP Position */
+#define ACTLR_SMP_Msk (1UL << ACTLR_SMP_Pos) /*!< \brief ACTLR: SMP Mask */
+
+#define ACTLR_WFLZM_Pos 3U /*!< \brief ACTLR: WFLZM Position */
+#define ACTLR_WFLZM_Msk (1UL << ACTLR_WFLZM_Pos) /*!< \brief ACTLR: WFLZM Mask */
+
+#define ACTLR_L1PE_Pos 2U /*!< \brief ACTLR: L1PE Position */
+#define ACTLR_L1PE_Msk (1UL << ACTLR_L1PE_Pos) /*!< \brief ACTLR: L1PE Mask */
+
+#define ACTLR_FW_Pos 0U /*!< \brief ACTLR: FW Position */
+#define ACTLR_FW_Msk (1UL << ACTLR_FW_Pos) /*!< \brief ACTLR: FW Mask */
+
+/* CP15 Register CPACR */
+typedef union
+{
+ struct
+ {
+ uint32_t CP0:2; /*!< \brief bit: 0..1 Access rights for coprocessor 0 */
+ uint32_t CP1:2; /*!< \brief bit: 2..3 Access rights for coprocessor 1 */
+ uint32_t CP2:2; /*!< \brief bit: 4..5 Access rights for coprocessor 2 */
+ uint32_t CP3:2; /*!< \brief bit: 6..7 Access rights for coprocessor 3 */
+ uint32_t CP4:2; /*!< \brief bit: 8..9 Access rights for coprocessor 4 */
+ uint32_t CP5:2; /*!< \brief bit:10..11 Access rights for coprocessor 5 */
+ uint32_t CP6:2; /*!< \brief bit:12..13 Access rights for coprocessor 6 */
+ uint32_t CP7:2; /*!< \brief bit:14..15 Access rights for coprocessor 7 */
+ uint32_t CP8:2; /*!< \brief bit:16..17 Access rights for coprocessor 8 */
+ uint32_t CP9:2; /*!< \brief bit:18..19 Access rights for coprocessor 9 */
+ uint32_t CP10:2; /*!< \brief bit:20..21 Access rights for coprocessor 10 */
+ uint32_t CP11:2; /*!< \brief bit:22..23 Access rights for coprocessor 11 */
+ uint32_t CP12:2; /*!< \brief bit:24..25 Access rights for coprocessor 11 */
+ uint32_t CP13:2; /*!< \brief bit:26..27 Access rights for coprocessor 11 */
+ uint32_t TRCDIS:1; /*!< \brief bit: 28 Disable CP14 access to trace registers */
+ RESERVED(0:1, uint32_t)
+ uint32_t D32DIS:1; /*!< \brief bit: 30 Disable use of registers D16-D31 of the VFP register file */
+ uint32_t ASEDIS:1; /*!< \brief bit: 31 Disable Advanced SIMD Functionality */
+ } b; /*!< \brief Structure used for bit access */
+ uint32_t w; /*!< \brief Type used for word access */
+} CPACR_Type;
+
+#define CPACR_ASEDIS_Pos 31U /*!< \brief CPACR: ASEDIS Position */
+#define CPACR_ASEDIS_Msk (1UL << CPACR_ASEDIS_Pos) /*!< \brief CPACR: ASEDIS Mask */
+
+#define CPACR_D32DIS_Pos 30U /*!< \brief CPACR: D32DIS Position */
+#define CPACR_D32DIS_Msk (1UL << CPACR_D32DIS_Pos) /*!< \brief CPACR: D32DIS Mask */
+
+#define CPACR_TRCDIS_Pos 28U /*!< \brief CPACR: D32DIS Position */
+#define CPACR_TRCDIS_Msk (1UL << CPACR_D32DIS_Pos) /*!< \brief CPACR: D32DIS Mask */
+
+#define CPACR_CP_Pos_(n) (n*2U) /*!< \brief CPACR: CPn Position */
+#define CPACR_CP_Msk_(n) (3UL << CPACR_CP_Pos_(n)) /*!< \brief CPACR: CPn Mask */
+
+#define CPACR_CP_NA 0U /*!< \brief CPACR CPn field: Access denied. */
+#define CPACR_CP_PL1 1U /*!< \brief CPACR CPn field: Accessible from PL1 only. */
+#define CPACR_CP_FA 3U /*!< \brief CPACR CPn field: Full access. */
+
+/* CP15 Register DFSR */
+typedef union
+{
+ struct
+ {
+ uint32_t FS0:4; /*!< \brief bit: 0.. 3 Fault Status bits bit 0-3 */
+ uint32_t Domain:4; /*!< \brief bit: 4.. 7 Fault on which domain */
+ RESERVED(0:1, uint32_t)
+ uint32_t LPAE:1; /*!< \brief bit: 9 Large Physical Address Extension */
+ uint32_t FS1:1; /*!< \brief bit: 10 Fault Status bits bit 4 */
+ uint32_t WnR:1; /*!< \brief bit: 11 Write not Read bit */
+ uint32_t ExT:1; /*!< \brief bit: 12 External abort type */
+ uint32_t CM:1; /*!< \brief bit: 13 Cache maintenance fault */
+ RESERVED(1:18, uint32_t)
+ } s; /*!< \brief Structure used for bit access in short format */
+ struct
+ {
+ uint32_t STATUS:5; /*!< \brief bit: 0.. 5 Fault Status bits */
+ RESERVED(0:3, uint32_t)
+ uint32_t LPAE:1; /*!< \brief bit: 9 Large Physical Address Extension */
+ RESERVED(1:1, uint32_t)
+ uint32_t WnR:1; /*!< \brief bit: 11 Write not Read bit */
+ uint32_t ExT:1; /*!< \brief bit: 12 External abort type */
+ uint32_t CM:1; /*!< \brief bit: 13 Cache maintenance fault */
+ RESERVED(2:18, uint32_t)
+ } l; /*!< \brief Structure used for bit access in long format */
+ uint32_t w; /*!< \brief Type used for word access */
+} DFSR_Type;
+
+#define DFSR_CM_Pos 13U /*!< \brief DFSR: CM Position */
+#define DFSR_CM_Msk (1UL << DFSR_CM_Pos) /*!< \brief DFSR: CM Mask */
+
+#define DFSR_Ext_Pos 12U /*!< \brief DFSR: Ext Position */
+#define DFSR_Ext_Msk (1UL << DFSR_Ext_Pos) /*!< \brief DFSR: Ext Mask */
+
+#define DFSR_WnR_Pos 11U /*!< \brief DFSR: WnR Position */
+#define DFSR_WnR_Msk (1UL << DFSR_WnR_Pos) /*!< \brief DFSR: WnR Mask */
+
+#define DFSR_FS1_Pos 10U /*!< \brief DFSR: FS1 Position */
+#define DFSR_FS1_Msk (1UL << DFSR_FS1_Pos) /*!< \brief DFSR: FS1 Mask */
+
+#define DFSR_LPAE_Pos 9U /*!< \brief DFSR: LPAE Position */
+#define DFSR_LPAE_Msk (1UL << DFSR_LPAE_Pos) /*!< \brief DFSR: LPAE Mask */
+
+#define DFSR_Domain_Pos 4U /*!< \brief DFSR: Domain Position */
+#define DFSR_Domain_Msk (0xFUL << DFSR_Domain_Pos) /*!< \brief DFSR: Domain Mask */
+
+#define DFSR_FS0_Pos 0U /*!< \brief DFSR: FS0 Position */
+#define DFSR_FS0_Msk (0xFUL << DFSR_FS0_Pos) /*!< \brief DFSR: FS0 Mask */
+
+#define DFSR_STATUS_Pos 0U /*!< \brief DFSR: STATUS Position */
+#define DFSR_STATUS_Msk (0x3FUL << DFSR_STATUS_Pos) /*!< \brief DFSR: STATUS Mask */
+
+/* CP15 Register IFSR */
+typedef union
+{
+ struct
+ {
+ uint32_t FS0:4; /*!< \brief bit: 0.. 3 Fault Status bits bit 0-3 */
+ RESERVED(0:5, uint32_t)
+ uint32_t LPAE:1; /*!< \brief bit: 9 Large Physical Address Extension */
+ uint32_t FS1:1; /*!< \brief bit: 10 Fault Status bits bit 4 */
+ RESERVED(1:1, uint32_t)
+ uint32_t ExT:1; /*!< \brief bit: 12 External abort type */
+ RESERVED(2:19, uint32_t)
+ } s; /*!< \brief Structure used for bit access in short format */
+ struct
+ {
+ uint32_t STATUS:6; /*!< \brief bit: 0.. 5 Fault Status bits */
+ RESERVED(0:3, uint32_t)
+ uint32_t LPAE:1; /*!< \brief bit: 9 Large Physical Address Extension */
+ RESERVED(1:2, uint32_t)
+ uint32_t ExT:1; /*!< \brief bit: 12 External abort type */
+ RESERVED(2:19, uint32_t)
+ } l; /*!< \brief Structure used for bit access in long format */
+ uint32_t w; /*!< \brief Type used for word access */
+} IFSR_Type;
+
+#define IFSR_ExT_Pos 12U /*!< \brief IFSR: ExT Position */
+#define IFSR_ExT_Msk (1UL << IFSR_ExT_Pos) /*!< \brief IFSR: ExT Mask */
+
+#define IFSR_FS1_Pos 10U /*!< \brief IFSR: FS1 Position */
+#define IFSR_FS1_Msk (1UL << IFSR_FS1_Pos) /*!< \brief IFSR: FS1 Mask */
+
+#define IFSR_LPAE_Pos 9U /*!< \brief IFSR: LPAE Position */
+#define IFSR_LPAE_Msk (0x1UL << IFSR_LPAE_Pos) /*!< \brief IFSR: LPAE Mask */
+
+#define IFSR_FS0_Pos 0U /*!< \brief IFSR: FS0 Position */
+#define IFSR_FS0_Msk (0xFUL << IFSR_FS0_Pos) /*!< \brief IFSR: FS0 Mask */
+
+#define IFSR_STATUS_Pos 0U /*!< \brief IFSR: STATUS Position */
+#define IFSR_STATUS_Msk (0x3FUL << IFSR_STATUS_Pos) /*!< \brief IFSR: STATUS Mask */
+
+/* CP15 Register ISR */
+typedef union
+{
+ struct
+ {
+ RESERVED(0:6, uint32_t)
+ uint32_t F:1; /*!< \brief bit: 6 FIQ pending bit */
+ uint32_t I:1; /*!< \brief bit: 7 IRQ pending bit */
+ uint32_t A:1; /*!< \brief bit: 8 External abort pending bit */
+ RESERVED(1:23, uint32_t)
+ } b; /*!< \brief Structure used for bit access */
+ uint32_t w; /*!< \brief Type used for word access */
+} ISR_Type;
+
+#define ISR_A_Pos 13U /*!< \brief ISR: A Position */
+#define ISR_A_Msk (1UL << ISR_A_Pos) /*!< \brief ISR: A Mask */
+
+#define ISR_I_Pos 12U /*!< \brief ISR: I Position */
+#define ISR_I_Msk (1UL << ISR_I_Pos) /*!< \brief ISR: I Mask */
+
+#define ISR_F_Pos 11U /*!< \brief ISR: F Position */
+#define ISR_F_Msk (1UL << ISR_F_Pos) /*!< \brief ISR: F Mask */
+
+/* DACR Register */
+#define DACR_D_Pos_(n) (2U*n) /*!< \brief DACR: Dn Position */
+#define DACR_D_Msk_(n) (3UL << DACR_D_Pos_(n)) /*!< \brief DACR: Dn Mask */
+#define DACR_Dn_NOACCESS 0U /*!< \brief DACR Dn field: No access */
+#define DACR_Dn_CLIENT 1U /*!< \brief DACR Dn field: Client */
+#define DACR_Dn_MANAGER 3U /*!< \brief DACR Dn field: Manager */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param [in] field Name of the register bit field.
+ \param [in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param [in] field Name of the register bit field.
+ \param [in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+
+/**
+ \brief Union type to access the L2C_310 Cache Controller.
+*/
+#if (__L2C_PRESENT == 1U) || defined(DOXYGEN)
+typedef struct
+{
+ __IM uint32_t CACHE_ID; /*!< \brief Offset: 0x0000 (R/ ) Cache ID Register */
+ __IM uint32_t CACHE_TYPE; /*!< \brief Offset: 0x0004 (R/ ) Cache Type Register */
+ RESERVED(0[0x3e], uint32_t)
+ __IOM uint32_t CONTROL; /*!< \brief Offset: 0x0100 (R/W) Control Register */
+ __IOM uint32_t AUX_CNT; /*!< \brief Offset: 0x0104 (R/W) Auxiliary Control */
+ RESERVED(1[0x3e], uint32_t)
+ __IOM uint32_t EVENT_CONTROL; /*!< \brief Offset: 0x0200 (R/W) Event Counter Control */
+ __IOM uint32_t EVENT_COUNTER1_CONF; /*!< \brief Offset: 0x0204 (R/W) Event Counter 1 Configuration */
+ __IOM uint32_t EVENT_COUNTER0_CONF; /*!< \brief Offset: 0x0208 (R/W) Event Counter 1 Configuration */
+ RESERVED(2[0x2], uint32_t)
+ __IOM uint32_t INTERRUPT_MASK; /*!< \brief Offset: 0x0214 (R/W) Interrupt Mask */
+ __IM uint32_t MASKED_INT_STATUS; /*!< \brief Offset: 0x0218 (R/ ) Masked Interrupt Status */
+ __IM uint32_t RAW_INT_STATUS; /*!< \brief Offset: 0x021c (R/ ) Raw Interrupt Status */
+ __OM uint32_t INTERRUPT_CLEAR; /*!< \brief Offset: 0x0220 ( /W) Interrupt Clear */
+ RESERVED(3[0x143], uint32_t)
+ __IOM uint32_t CACHE_SYNC; /*!< \brief Offset: 0x0730 (R/W) Cache Sync */
+ RESERVED(4[0xf], uint32_t)
+ __IOM uint32_t INV_LINE_PA; /*!< \brief Offset: 0x0770 (R/W) Invalidate Line By PA */
+ RESERVED(6[2], uint32_t)
+ __IOM uint32_t INV_WAY; /*!< \brief Offset: 0x077c (R/W) Invalidate by Way */
+ RESERVED(5[0xc], uint32_t)
+ __IOM uint32_t CLEAN_LINE_PA; /*!< \brief Offset: 0x07b0 (R/W) Clean Line by PA */
+ RESERVED(7[1], uint32_t)
+ __IOM uint32_t CLEAN_LINE_INDEX_WAY; /*!< \brief Offset: 0x07b8 (R/W) Clean Line by Index/Way */
+ __IOM uint32_t CLEAN_WAY; /*!< \brief Offset: 0x07bc (R/W) Clean by Way */
+ RESERVED(8[0xc], uint32_t)
+ __IOM uint32_t CLEAN_INV_LINE_PA; /*!< \brief Offset: 0x07f0 (R/W) Clean and Invalidate Line by PA */
+ RESERVED(9[1], uint32_t)
+ __IOM uint32_t CLEAN_INV_LINE_INDEX_WAY; /*!< \brief Offset: 0x07f8 (R/W) Clean and Invalidate Line by Index/Way */
+ __IOM uint32_t CLEAN_INV_WAY; /*!< \brief Offset: 0x07fc (R/W) Clean and Invalidate by Way */
+ RESERVED(10[0x40], uint32_t)
+ __IOM uint32_t DATA_LOCK_0_WAY; /*!< \brief Offset: 0x0900 (R/W) Data Lockdown 0 by Way */
+ __IOM uint32_t INST_LOCK_0_WAY; /*!< \brief Offset: 0x0904 (R/W) Instruction Lockdown 0 by Way */
+ __IOM uint32_t DATA_LOCK_1_WAY; /*!< \brief Offset: 0x0908 (R/W) Data Lockdown 1 by Way */
+ __IOM uint32_t INST_LOCK_1_WAY; /*!< \brief Offset: 0x090c (R/W) Instruction Lockdown 1 by Way */
+ __IOM uint32_t DATA_LOCK_2_WAY; /*!< \brief Offset: 0x0910 (R/W) Data Lockdown 2 by Way */
+ __IOM uint32_t INST_LOCK_2_WAY; /*!< \brief Offset: 0x0914 (R/W) Instruction Lockdown 2 by Way */
+ __IOM uint32_t DATA_LOCK_3_WAY; /*!< \brief Offset: 0x0918 (R/W) Data Lockdown 3 by Way */
+ __IOM uint32_t INST_LOCK_3_WAY; /*!< \brief Offset: 0x091c (R/W) Instruction Lockdown 3 by Way */
+ __IOM uint32_t DATA_LOCK_4_WAY; /*!< \brief Offset: 0x0920 (R/W) Data Lockdown 4 by Way */
+ __IOM uint32_t INST_LOCK_4_WAY; /*!< \brief Offset: 0x0924 (R/W) Instruction Lockdown 4 by Way */
+ __IOM uint32_t DATA_LOCK_5_WAY; /*!< \brief Offset: 0x0928 (R/W) Data Lockdown 5 by Way */
+ __IOM uint32_t INST_LOCK_5_WAY; /*!< \brief Offset: 0x092c (R/W) Instruction Lockdown 5 by Way */
+ __IOM uint32_t DATA_LOCK_6_WAY; /*!< \brief Offset: 0x0930 (R/W) Data Lockdown 5 by Way */
+ __IOM uint32_t INST_LOCK_6_WAY; /*!< \brief Offset: 0x0934 (R/W) Instruction Lockdown 5 by Way */
+ __IOM uint32_t DATA_LOCK_7_WAY; /*!< \brief Offset: 0x0938 (R/W) Data Lockdown 6 by Way */
+ __IOM uint32_t INST_LOCK_7_WAY; /*!< \brief Offset: 0x093c (R/W) Instruction Lockdown 6 by Way */
+ RESERVED(11[0x4], uint32_t)
+ __IOM uint32_t LOCK_LINE_EN; /*!< \brief Offset: 0x0950 (R/W) Lockdown by Line Enable */
+ __IOM uint32_t UNLOCK_ALL_BY_WAY; /*!< \brief Offset: 0x0954 (R/W) Unlock All Lines by Way */
+ RESERVED(12[0xaa], uint32_t)
+ __IOM uint32_t ADDRESS_FILTER_START; /*!< \brief Offset: 0x0c00 (R/W) Address Filtering Start */
+ __IOM uint32_t ADDRESS_FILTER_END; /*!< \brief Offset: 0x0c04 (R/W) Address Filtering End */
+ RESERVED(13[0xce], uint32_t)
+ __IOM uint32_t DEBUG_CONTROL; /*!< \brief Offset: 0x0f40 (R/W) Debug Control Register */
+} L2C_310_TypeDef;
+
+#define L2C_310 ((L2C_310_TypeDef *)L2C_310_BASE) /*!< \brief L2C_310 register set access pointer */
+#endif
+
+#if (__GIC_PRESENT == 1U) || defined(DOXYGEN)
+
+/** \brief Structure type to access the Generic Interrupt Controller Distributor (GICD)
+*/
+typedef struct
+{
+ __IOM uint32_t CTLR; /*!< \brief Offset: 0x000 (R/W) Distributor Control Register */
+ __IM uint32_t TYPER; /*!< \brief Offset: 0x004 (R/ ) Interrupt Controller Type Register */
+ __IM uint32_t IIDR; /*!< \brief Offset: 0x008 (R/ ) Distributor Implementer Identification Register */
+ RESERVED(0, uint32_t)
+ __IOM uint32_t STATUSR; /*!< \brief Offset: 0x010 (R/W) Error Reporting Status Register, optional */
+ RESERVED(1[11], uint32_t)
+ __OM uint32_t SETSPI_NSR; /*!< \brief Offset: 0x040 ( /W) Set SPI Register */
+ RESERVED(2, uint32_t)
+ __OM uint32_t CLRSPI_NSR; /*!< \brief Offset: 0x048 ( /W) Clear SPI Register */
+ RESERVED(3, uint32_t)
+ __OM uint32_t SETSPI_SR; /*!< \brief Offset: 0x050 ( /W) Set SPI, Secure Register */
+ RESERVED(4, uint32_t)
+ __OM uint32_t CLRSPI_SR; /*!< \brief Offset: 0x058 ( /W) Clear SPI, Secure Register */
+ RESERVED(5[9], uint32_t)
+ __IOM uint32_t IGROUPR[32]; /*!< \brief Offset: 0x080 (R/W) Interrupt Group Registers */
+ __IOM uint32_t ISENABLER[32]; /*!< \brief Offset: 0x100 (R/W) Interrupt Set-Enable Registers */
+ __IOM uint32_t ICENABLER[32]; /*!< \brief Offset: 0x180 (R/W) Interrupt Clear-Enable Registers */
+ __IOM uint32_t ISPENDR[32]; /*!< \brief Offset: 0x200 (R/W) Interrupt Set-Pending Registers */
+ __IOM uint32_t ICPENDR[32]; /*!< \brief Offset: 0x280 (R/W) Interrupt Clear-Pending Registers */
+ __IOM uint32_t ISACTIVER[32]; /*!< \brief Offset: 0x300 (R/W) Interrupt Set-Active Registers */
+ __IOM uint32_t ICACTIVER[32]; /*!< \brief Offset: 0x380 (R/W) Interrupt Clear-Active Registers */
+ __IOM uint32_t IPRIORITYR[255]; /*!< \brief Offset: 0x400 (R/W) Interrupt Priority Registers */
+ RESERVED(6, uint32_t)
+ __IOM uint32_t ITARGETSR[255]; /*!< \brief Offset: 0x800 (R/W) Interrupt Targets Registers */
+ RESERVED(7, uint32_t)
+ __IOM uint32_t ICFGR[64]; /*!< \brief Offset: 0xC00 (R/W) Interrupt Configuration Registers */
+ __IOM uint32_t IGRPMODR[32]; /*!< \brief Offset: 0xD00 (R/W) Interrupt Group Modifier Registers */
+ RESERVED(8[32], uint32_t)
+ __IOM uint32_t NSACR[64]; /*!< \brief Offset: 0xE00 (R/W) Non-secure Access Control Registers */
+ __OM uint32_t SGIR; /*!< \brief Offset: 0xF00 ( /W) Software Generated Interrupt Register */
+ RESERVED(9[3], uint32_t)
+ __IOM uint32_t CPENDSGIR[4]; /*!< \brief Offset: 0xF10 (R/W) SGI Clear-Pending Registers */
+ __IOM uint32_t SPENDSGIR[4]; /*!< \brief Offset: 0xF20 (R/W) SGI Set-Pending Registers */
+ RESERVED(10[5236], uint32_t)
+ __IOM uint64_t IROUTER[988]; /*!< \brief Offset: 0x6100(R/W) Interrupt Routing Registers */
+} GICDistributor_Type;
+
+#define GICDistributor ((GICDistributor_Type *) GIC_DISTRIBUTOR_BASE ) /*!< \brief GIC Distributor register set access pointer */
+
+/** \brief Structure type to access the Generic Interrupt Controller Interface (GICC)
+*/
+typedef struct
+{
+ __IOM uint32_t CTLR; /*!< \brief Offset: 0x000 (R/W) CPU Interface Control Register */
+ __IOM uint32_t PMR; /*!< \brief Offset: 0x004 (R/W) Interrupt Priority Mask Register */
+ __IOM uint32_t BPR; /*!< \brief Offset: 0x008 (R/W) Binary Point Register */
+ __IM uint32_t IAR; /*!< \brief Offset: 0x00C (R/ ) Interrupt Acknowledge Register */
+ __OM uint32_t EOIR; /*!< \brief Offset: 0x010 ( /W) End Of Interrupt Register */
+ __IM uint32_t RPR; /*!< \brief Offset: 0x014 (R/ ) Running Priority Register */
+ __IM uint32_t HPPIR; /*!< \brief Offset: 0x018 (R/ ) Highest Priority Pending Interrupt Register */
+ __IOM uint32_t ABPR; /*!< \brief Offset: 0x01C (R/W) Aliased Binary Point Register */
+ __IM uint32_t AIAR; /*!< \brief Offset: 0x020 (R/ ) Aliased Interrupt Acknowledge Register */
+ __OM uint32_t AEOIR; /*!< \brief Offset: 0x024 ( /W) Aliased End Of Interrupt Register */
+ __IM uint32_t AHPPIR; /*!< \brief Offset: 0x028 (R/ ) Aliased Highest Priority Pending Interrupt Register */
+ __IOM uint32_t STATUSR; /*!< \brief Offset: 0x02C (R/W) Error Reporting Status Register, optional */
+ RESERVED(1[40], uint32_t)
+ __IOM uint32_t APR[4]; /*!< \brief Offset: 0x0D0 (R/W) Active Priority Register */
+ __IOM uint32_t NSAPR[4]; /*!< \brief Offset: 0x0E0 (R/W) Non-secure Active Priority Register */
+ RESERVED(2[3], uint32_t)
+ __IM uint32_t IIDR; /*!< \brief Offset: 0x0FC (R/ ) CPU Interface Identification Register */
+ RESERVED(3[960], uint32_t)
+ __OM uint32_t DIR; /*!< \brief Offset: 0x1000( /W) Deactivate Interrupt Register */
+} GICInterface_Type;
+
+#define GICInterface ((GICInterface_Type *) GIC_INTERFACE_BASE ) /*!< \brief GIC Interface register set access pointer */
+#endif
+
+#if (__TIM_PRESENT == 1U) || defined(DOXYGEN)
+#if ((__CORTEX_A == 5U) || (__CORTEX_A == 9U)) || defined(DOXYGEN)
+/** \brief Structure type to access the Private Timer
+*/
+typedef struct
+{
+ __IOM uint32_t LOAD; //!< \brief Offset: 0x000 (R/W) Private Timer Load Register
+ __IOM uint32_t COUNTER; //!< \brief Offset: 0x004 (R/W) Private Timer Counter Register
+ __IOM uint32_t CONTROL; //!< \brief Offset: 0x008 (R/W) Private Timer Control Register
+ __IOM uint32_t ISR; //!< \brief Offset: 0x00C (R/W) Private Timer Interrupt Status Register
+ RESERVED(0[4], uint32_t)
+ __IOM uint32_t WLOAD; //!< \brief Offset: 0x020 (R/W) Watchdog Load Register
+ __IOM uint32_t WCOUNTER; //!< \brief Offset: 0x024 (R/W) Watchdog Counter Register
+ __IOM uint32_t WCONTROL; //!< \brief Offset: 0x028 (R/W) Watchdog Control Register
+ __IOM uint32_t WISR; //!< \brief Offset: 0x02C (R/W) Watchdog Interrupt Status Register
+ __IOM uint32_t WRESET; //!< \brief Offset: 0x030 (R/W) Watchdog Reset Status Register
+ __OM uint32_t WDISABLE; //!< \brief Offset: 0x034 ( /W) Watchdog Disable Register
+} Timer_Type;
+#define PTIM ((Timer_Type *) TIMER_BASE ) /*!< \brief Timer register struct */
+#endif
+#endif
+
+ /*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - L1 Cache Functions
+ - L2C-310 Cache Controller Functions
+ - PL1 Timer Functions
+ - GIC Functions
+ - MMU Functions
+ ******************************************************************************/
+
+/* ########################## L1 Cache functions ################################# */
+
+/** \brief Enable Caches by setting I and C bits in SCTLR register.
+*/
+__STATIC_FORCEINLINE void L1C_EnableCaches(void) {
+ __set_SCTLR( __get_SCTLR() | SCTLR_I_Msk | SCTLR_C_Msk);
+ __ISB();
+}
+
+/** \brief Disable Caches by clearing I and C bits in SCTLR register.
+*/
+__STATIC_FORCEINLINE void L1C_DisableCaches(void) {
+ __set_SCTLR( __get_SCTLR() & (~SCTLR_I_Msk) & (~SCTLR_C_Msk));
+ __ISB();
+}
+
+/** \brief Enable Branch Prediction by setting Z bit in SCTLR register.
+*/
+__STATIC_FORCEINLINE void L1C_EnableBTAC(void) {
+ __set_SCTLR( __get_SCTLR() | SCTLR_Z_Msk);
+ __ISB();
+}
+
+/** \brief Disable Branch Prediction by clearing Z bit in SCTLR register.
+*/
+__STATIC_FORCEINLINE void L1C_DisableBTAC(void) {
+ __set_SCTLR( __get_SCTLR() & (~SCTLR_Z_Msk));
+ __ISB();
+}
+
+/** \brief Invalidate entire branch predictor array
+*/
+__STATIC_FORCEINLINE void L1C_InvalidateBTAC(void) {
+ __set_BPIALL(0);
+ __DSB(); //ensure completion of the invalidation
+ __ISB(); //ensure instruction fetch path sees new state
+}
+
+/** \brief Invalidate the whole instruction cache
+*/
+__STATIC_FORCEINLINE void L1C_InvalidateICacheAll(void) {
+ __set_ICIALLU(0);
+ __DSB(); //ensure completion of the invalidation
+ __ISB(); //ensure instruction fetch path sees new I cache state
+}
+
+/** \brief Clean data cache line by address.
+* \param [in] va Pointer to data to clear the cache for.
+*/
+__STATIC_FORCEINLINE void L1C_CleanDCacheMVA(void *va) {
+ __set_DCCMVAC((uint32_t)va);
+ __DMB(); //ensure the ordering of data cache maintenance operations and their effects
+}
+
+/** \brief Invalidate data cache line by address.
+* \param [in] va Pointer to data to invalidate the cache for.
+*/
+__STATIC_FORCEINLINE void L1C_InvalidateDCacheMVA(void *va) {
+ __set_DCIMVAC((uint32_t)va);
+ __DMB(); //ensure the ordering of data cache maintenance operations and their effects
+}
+
+/** \brief Clean and Invalidate data cache by address.
+* \param [in] va Pointer to data to invalidate the cache for.
+*/
+__STATIC_FORCEINLINE void L1C_CleanInvalidateDCacheMVA(void *va) {
+ __set_DCCIMVAC((uint32_t)va);
+ __DMB(); //ensure the ordering of data cache maintenance operations and their effects
+}
+
+/** \brief Calculate log2 rounded up
+* - log(0) => 0
+* - log(1) => 0
+* - log(2) => 1
+* - log(3) => 2
+* - log(4) => 2
+* - log(5) => 3
+* : :
+* - log(16) => 4
+* - log(32) => 5
+* : :
+* \param [in] n input value parameter
+* \return log2(n)
+*/
+__STATIC_FORCEINLINE uint8_t __log2_up(uint32_t n)
+{
+ if (n < 2U) {
+ return 0U;
+ }
+ uint8_t log = 0U;
+ uint32_t t = n;
+ while(t > 1U)
+ {
+ log++;
+ t >>= 1U;
+ }
+ if (n & 1U) { log++; }
+ return log;
+}
+
+/** \brief Apply cache maintenance to given cache level.
+* \param [in] level cache level to be maintained
+* \param [in] maint 0 - invalidate, 1 - clean, otherwise - invalidate and clean
+*/
+__STATIC_FORCEINLINE void __L1C_MaintainDCacheSetWay(uint32_t level, uint32_t maint)
+{
+ uint32_t Dummy;
+ uint32_t ccsidr;
+ uint32_t num_sets;
+ uint32_t num_ways;
+ uint32_t shift_way;
+ uint32_t log2_linesize;
+ int32_t log2_num_ways;
+
+ Dummy = level << 1U;
+ /* set csselr, select ccsidr register */
+ __set_CSSELR(Dummy);
+ /* get current ccsidr register */
+ ccsidr = __get_CCSIDR();
+ num_sets = ((ccsidr & 0x0FFFE000U) >> 13U) + 1U;
+ num_ways = ((ccsidr & 0x00001FF8U) >> 3U) + 1U;
+ log2_linesize = (ccsidr & 0x00000007U) + 2U + 2U;
+ log2_num_ways = __log2_up(num_ways);
+ if ((log2_num_ways < 0) || (log2_num_ways > 32)) {
+ return; // FATAL ERROR
+ }
+ shift_way = 32U - (uint32_t)log2_num_ways;
+ for(int32_t way = num_ways-1; way >= 0; way--)
+ {
+ for(int32_t set = num_sets-1; set >= 0; set--)
+ {
+ Dummy = (level << 1U) | (((uint32_t)set) << log2_linesize) | (((uint32_t)way) << shift_way);
+ switch (maint)
+ {
+ case 0U: __set_DCISW(Dummy); break;
+ case 1U: __set_DCCSW(Dummy); break;
+ default: __set_DCCISW(Dummy); break;
+ }
+ }
+ }
+ __DMB();
+}
+
+/** \brief Clean and Invalidate the entire data or unified cache
+* Generic mechanism for cleaning/invalidating the entire data or unified cache to the point of coherency
+* \param [in] op 0 - invalidate, 1 - clean, otherwise - invalidate and clean
+*/
+__STATIC_FORCEINLINE void L1C_CleanInvalidateCache(uint32_t op) {
+ uint32_t clidr;
+ uint32_t cache_type;
+ clidr = __get_CLIDR();
+ for(uint32_t i = 0U; i<7U; i++)
+ {
+ cache_type = (clidr >> i*3U) & 0x7UL;
+ if ((cache_type >= 2U) && (cache_type <= 4U))
+ {
+ __L1C_MaintainDCacheSetWay(i, op);
+ }
+ }
+}
+
+/** \brief Clean and Invalidate the entire data or unified cache
+* Generic mechanism for cleaning/invalidating the entire data or unified cache to the point of coherency
+* \param [in] op 0 - invalidate, 1 - clean, otherwise - invalidate and clean
+* \deprecated Use generic L1C_CleanInvalidateCache instead.
+*/
+CMSIS_DEPRECATED
+__STATIC_FORCEINLINE void __L1C_CleanInvalidateCache(uint32_t op) {
+ L1C_CleanInvalidateCache(op);
+}
+
+/** \brief Invalidate the whole data cache.
+*/
+__STATIC_FORCEINLINE void L1C_InvalidateDCacheAll(void) {
+ L1C_CleanInvalidateCache(0);
+}
+
+/** \brief Clean the whole data cache.
+ */
+__STATIC_FORCEINLINE void L1C_CleanDCacheAll(void) {
+ L1C_CleanInvalidateCache(1);
+}
+
+/** \brief Clean and invalidate the whole data cache.
+ */
+__STATIC_FORCEINLINE void L1C_CleanInvalidateDCacheAll(void) {
+ L1C_CleanInvalidateCache(2);
+}
+
+/* ########################## L2 Cache functions ################################# */
+#if (__L2C_PRESENT == 1U) || defined(DOXYGEN)
+/** \brief Cache Sync operation by writing CACHE_SYNC register.
+*/
+__STATIC_INLINE void L2C_Sync(void)
+{
+ L2C_310->CACHE_SYNC = 0x0;
+}
+
+/** \brief Read cache controller cache ID from CACHE_ID register.
+ * \return L2C_310_TypeDef::CACHE_ID
+ */
+__STATIC_INLINE int L2C_GetID (void)
+{
+ return L2C_310->CACHE_ID;
+}
+
+/** \brief Read cache controller cache type from CACHE_TYPE register.
+* \return L2C_310_TypeDef::CACHE_TYPE
+*/
+__STATIC_INLINE int L2C_GetType (void)
+{
+ return L2C_310->CACHE_TYPE;
+}
+
+/** \brief Invalidate all cache by way
+*/
+__STATIC_INLINE void L2C_InvAllByWay (void)
+{
+ unsigned int assoc;
+
+ if (L2C_310->AUX_CNT & (1U << 16U)) {
+ assoc = 16U;
+ } else {
+ assoc = 8U;
+ }
+
+ L2C_310->INV_WAY = (1U << assoc) - 1U;
+ while(L2C_310->INV_WAY & ((1U << assoc) - 1U)); //poll invalidate
+
+ L2C_Sync();
+}
+
+/** \brief Clean and Invalidate all cache by way
+*/
+__STATIC_INLINE void L2C_CleanInvAllByWay (void)
+{
+ unsigned int assoc;
+
+ if (L2C_310->AUX_CNT & (1U << 16U)) {
+ assoc = 16U;
+ } else {
+ assoc = 8U;
+ }
+
+ L2C_310->CLEAN_INV_WAY = (1U << assoc) - 1U;
+ while(L2C_310->CLEAN_INV_WAY & ((1U << assoc) - 1U)); //poll invalidate
+
+ L2C_Sync();
+}
+
+/** \brief Enable Level 2 Cache
+*/
+__STATIC_INLINE void L2C_Enable(void)
+{
+ L2C_310->CONTROL = 0;
+ L2C_310->INTERRUPT_CLEAR = 0x000001FFuL;
+ L2C_310->DEBUG_CONTROL = 0;
+ L2C_310->DATA_LOCK_0_WAY = 0;
+ L2C_310->CACHE_SYNC = 0;
+ L2C_310->CONTROL = 0x01;
+ L2C_Sync();
+}
+
+/** \brief Disable Level 2 Cache
+*/
+__STATIC_INLINE void L2C_Disable(void)
+{
+ L2C_310->CONTROL = 0x00;
+ L2C_Sync();
+}
+
+/** \brief Invalidate cache by physical address
+* \param [in] pa Pointer to data to invalidate cache for.
+*/
+__STATIC_INLINE void L2C_InvPa (void *pa)
+{
+ L2C_310->INV_LINE_PA = (unsigned int)pa;
+ L2C_Sync();
+}
+
+/** \brief Clean cache by physical address
+* \param [in] pa Pointer to data to invalidate cache for.
+*/
+__STATIC_INLINE void L2C_CleanPa (void *pa)
+{
+ L2C_310->CLEAN_LINE_PA = (unsigned int)pa;
+ L2C_Sync();
+}
+
+/** \brief Clean and invalidate cache by physical address
+* \param [in] pa Pointer to data to invalidate cache for.
+*/
+__STATIC_INLINE void L2C_CleanInvPa (void *pa)
+{
+ L2C_310->CLEAN_INV_LINE_PA = (unsigned int)pa;
+ L2C_Sync();
+}
+#endif
+
+/* ########################## GIC functions ###################################### */
+#if (__GIC_PRESENT == 1U) || defined(DOXYGEN)
+
+/** \brief Enable the interrupt distributor using the GIC's CTLR register.
+*/
+__STATIC_INLINE void GIC_EnableDistributor(void)
+{
+ GICDistributor->CTLR |= 1U;
+}
+
+/** \brief Disable the interrupt distributor using the GIC's CTLR register.
+*/
+__STATIC_INLINE void GIC_DisableDistributor(void)
+{
+ GICDistributor->CTLR &=~1U;
+}
+
+/** \brief Read the GIC's TYPER register.
+* \return GICDistributor_Type::TYPER
+*/
+__STATIC_INLINE uint32_t GIC_DistributorInfo(void)
+{
+ return (GICDistributor->TYPER);
+}
+
+/** \brief Reads the GIC's IIDR register.
+* \return GICDistributor_Type::IIDR
+*/
+__STATIC_INLINE uint32_t GIC_DistributorImplementer(void)
+{
+ return (GICDistributor->IIDR);
+}
+
+/** \brief Sets the GIC's ITARGETSR register for the given interrupt.
+* \param [in] IRQn Interrupt to be configured.
+* \param [in] cpu_target CPU interfaces to assign this interrupt to.
+*/
+__STATIC_INLINE void GIC_SetTarget(IRQn_Type IRQn, uint32_t cpu_target)
+{
+ uint32_t mask = GICDistributor->ITARGETSR[IRQn / 4U] & ~(0xFFUL << ((IRQn % 4U) * 8U));
+ GICDistributor->ITARGETSR[IRQn / 4U] = mask | ((cpu_target & 0xFFUL) << ((IRQn % 4U) * 8U));
+}
+
+/** \brief Read the GIC's ITARGETSR register.
+* \param [in] IRQn Interrupt to acquire the configuration for.
+* \return GICDistributor_Type::ITARGETSR
+*/
+__STATIC_INLINE uint32_t GIC_GetTarget(IRQn_Type IRQn)
+{
+ return (GICDistributor->ITARGETSR[IRQn / 4U] >> ((IRQn % 4U) * 8U)) & 0xFFUL;
+}
+
+/** \brief Enable the CPU's interrupt interface.
+*/
+__STATIC_INLINE void GIC_EnableInterface(void)
+{
+ GICInterface->CTLR |= 1U; //enable interface
+}
+
+/** \brief Disable the CPU's interrupt interface.
+*/
+__STATIC_INLINE void GIC_DisableInterface(void)
+{
+ GICInterface->CTLR &=~1U; //disable distributor
+}
+
+/** \brief Read the CPU's IAR register.
+* \return GICInterface_Type::IAR
+*/
+__STATIC_INLINE IRQn_Type GIC_AcknowledgePending(void)
+{
+ return (IRQn_Type)(GICInterface->IAR);
+}
+
+/** \brief Writes the given interrupt number to the CPU's EOIR register.
+* \param [in] IRQn The interrupt to be signaled as finished.
+*/
+__STATIC_INLINE void GIC_EndInterrupt(IRQn_Type IRQn)
+{
+ GICInterface->EOIR = IRQn;
+}
+
+/** \brief Enables the given interrupt using GIC's ISENABLER register.
+* \param [in] IRQn The interrupt to be enabled.
+*/
+__STATIC_INLINE void GIC_EnableIRQ(IRQn_Type IRQn)
+{
+ GICDistributor->ISENABLER[IRQn / 32U] = 1U << (IRQn % 32U);
+}
+
+/** \brief Get interrupt enable status using GIC's ISENABLER register.
+* \param [in] IRQn The interrupt to be queried.
+* \return 0 - interrupt is not enabled, 1 - interrupt is enabled.
+*/
+__STATIC_INLINE uint32_t GIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ return (GICDistributor->ISENABLER[IRQn / 32U] >> (IRQn % 32U)) & 1UL;
+}
+
+/** \brief Disables the given interrupt using GIC's ICENABLER register.
+* \param [in] IRQn The interrupt to be disabled.
+*/
+__STATIC_INLINE void GIC_DisableIRQ(IRQn_Type IRQn)
+{
+ GICDistributor->ICENABLER[IRQn / 32U] = 1U << (IRQn % 32U);
+}
+
+/** \brief Get interrupt pending status from GIC's ISPENDR register.
+* \param [in] IRQn The interrupt to be queried.
+* \return 0 - interrupt is not pending, 1 - interrupt is pendig.
+*/
+__STATIC_INLINE uint32_t GIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ uint32_t pend;
+
+ if (IRQn >= 16U) {
+ pend = (GICDistributor->ISPENDR[IRQn / 32U] >> (IRQn % 32U)) & 1UL;
+ } else {
+ // INTID 0-15 Software Generated Interrupt
+ pend = (GICDistributor->SPENDSGIR[IRQn / 4U] >> ((IRQn % 4U) * 8U)) & 0xFFUL;
+ // No CPU identification offered
+ if (pend != 0U) {
+ pend = 1U;
+ } else {
+ pend = 0U;
+ }
+ }
+
+ return (pend);
+}
+
+/** \brief Sets the given interrupt as pending using GIC's ISPENDR register.
+* \param [in] IRQn The interrupt to be enabled.
+*/
+__STATIC_INLINE void GIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if (IRQn >= 16U) {
+ GICDistributor->ISPENDR[IRQn / 32U] = 1U << (IRQn % 32U);
+ } else {
+ // INTID 0-15 Software Generated Interrupt
+ GICDistributor->SPENDSGIR[IRQn / 4U] = 1U << ((IRQn % 4U) * 8U);
+ }
+}
+
+/** \brief Clears the given interrupt from being pending using GIC's ICPENDR register.
+* \param [in] IRQn The interrupt to be enabled.
+*/
+__STATIC_INLINE void GIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if (IRQn >= 16U) {
+ GICDistributor->ICPENDR[IRQn / 32U] = 1U << (IRQn % 32U);
+ } else {
+ // INTID 0-15 Software Generated Interrupt
+ GICDistributor->CPENDSGIR[IRQn / 4U] = 1U << ((IRQn % 4U) * 8U);
+ }
+}
+
+/** \brief Sets the interrupt configuration using GIC's ICFGR register.
+* \param [in] IRQn The interrupt to be configured.
+* \param [in] int_config Int_config field value. Bit 0: Reserved (0 - N-N model, 1 - 1-N model for some GIC before v1)
+* Bit 1: 0 - level sensitive, 1 - edge triggered
+*/
+__STATIC_INLINE void GIC_SetConfiguration(IRQn_Type IRQn, uint32_t int_config)
+{
+ uint32_t icfgr = GICDistributor->ICFGR[IRQn / 16U];
+ uint32_t shift = (IRQn % 16U) << 1U;
+
+ icfgr &= (~(3U << shift));
+ icfgr |= ( int_config << shift);
+
+ GICDistributor->ICFGR[IRQn / 16U] = icfgr;
+}
+
+/** \brief Get the interrupt configuration from the GIC's ICFGR register.
+* \param [in] IRQn Interrupt to acquire the configuration for.
+* \return Int_config field value. Bit 0: Reserved (0 - N-N model, 1 - 1-N model for some GIC before v1)
+* Bit 1: 0 - level sensitive, 1 - edge triggered
+*/
+__STATIC_INLINE uint32_t GIC_GetConfiguration(IRQn_Type IRQn)
+{
+ return (GICDistributor->ICFGR[IRQn / 16U] >> ((IRQn % 16U) >> 1U));
+}
+
+/** \brief Set the priority for the given interrupt in the GIC's IPRIORITYR register.
+* \param [in] IRQn The interrupt to be configured.
+* \param [in] priority The priority for the interrupt, lower values denote higher priorities.
+*/
+__STATIC_INLINE void GIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ uint32_t mask = GICDistributor->IPRIORITYR[IRQn / 4U] & ~(0xFFUL << ((IRQn % 4U) * 8U));
+ GICDistributor->IPRIORITYR[IRQn / 4U] = mask | ((priority & 0xFFUL) << ((IRQn % 4U) * 8U));
+}
+
+/** \brief Read the current interrupt priority from GIC's IPRIORITYR register.
+* \param [in] IRQn The interrupt to be queried.
+*/
+__STATIC_INLINE uint32_t GIC_GetPriority(IRQn_Type IRQn)
+{
+ return (GICDistributor->IPRIORITYR[IRQn / 4U] >> ((IRQn % 4U) * 8U)) & 0xFFUL;
+}
+
+/** \brief Set the interrupt priority mask using CPU's PMR register.
+* \param [in] priority Priority mask to be set.
+*/
+__STATIC_INLINE void GIC_SetInterfacePriorityMask(uint32_t priority)
+{
+ GICInterface->PMR = priority & 0xFFUL; //set priority mask
+}
+
+/** \brief Read the current interrupt priority mask from CPU's PMR register.
+* \result GICInterface_Type::PMR
+*/
+__STATIC_INLINE uint32_t GIC_GetInterfacePriorityMask(void)
+{
+ return GICInterface->PMR;
+}
+
+/** \brief Configures the group priority and subpriority split point using CPU's BPR register.
+* \param [in] binary_point Amount of bits used as subpriority.
+*/
+__STATIC_INLINE void GIC_SetBinaryPoint(uint32_t binary_point)
+{
+ GICInterface->BPR = binary_point & 7U; //set binary point
+}
+
+/** \brief Read the current group priority and subpriority split point from CPU's BPR register.
+* \return GICInterface_Type::BPR
+*/
+__STATIC_INLINE uint32_t GIC_GetBinaryPoint(void)
+{
+ return GICInterface->BPR;
+}
+
+/** \brief Get the status for a given interrupt.
+* \param [in] IRQn The interrupt to get status for.
+* \return 0 - not pending/active, 1 - pending, 2 - active, 3 - pending and active
+*/
+__STATIC_INLINE uint32_t GIC_GetIRQStatus(IRQn_Type IRQn)
+{
+ uint32_t pending, active;
+
+ active = ((GICDistributor->ISACTIVER[IRQn / 32U]) >> (IRQn % 32U)) & 1UL;
+ pending = ((GICDistributor->ISPENDR[IRQn / 32U]) >> (IRQn % 32U)) & 1UL;
+
+ return ((active<<1U) | pending);
+}
+
+/** \brief Generate a software interrupt using GIC's SGIR register.
+* \param [in] IRQn Software interrupt to be generated.
+* \param [in] target_list List of CPUs the software interrupt should be forwarded to.
+* \param [in] filter_list Filter to be applied to determine interrupt receivers.
+*/
+__STATIC_INLINE void GIC_SendSGI(IRQn_Type IRQn, uint32_t target_list, uint32_t filter_list)
+{
+ GICDistributor->SGIR = ((filter_list & 3U) << 24U) | ((target_list & 0xFFUL) << 16U) | (IRQn & 0x0FUL);
+}
+
+/** \brief Get the interrupt number of the highest interrupt pending from CPU's HPPIR register.
+* \return GICInterface_Type::HPPIR
+*/
+__STATIC_INLINE uint32_t GIC_GetHighPendingIRQ(void)
+{
+ return GICInterface->HPPIR;
+}
+
+/** \brief Provides information about the implementer and revision of the CPU interface.
+* \return GICInterface_Type::IIDR
+*/
+__STATIC_INLINE uint32_t GIC_GetInterfaceId(void)
+{
+ return GICInterface->IIDR;
+}
+
+/** \brief Set the interrupt group from the GIC's IGROUPR register.
+* \param [in] IRQn The interrupt to be queried.
+* \param [in] group Interrupt group number: 0 - Group 0, 1 - Group 1
+*/
+__STATIC_INLINE void GIC_SetGroup(IRQn_Type IRQn, uint32_t group)
+{
+ uint32_t igroupr = GICDistributor->IGROUPR[IRQn / 32U];
+ uint32_t shift = (IRQn % 32U);
+
+ igroupr &= (~(1U << shift));
+ igroupr |= ( (group & 1U) << shift);
+
+ GICDistributor->IGROUPR[IRQn / 32U] = igroupr;
+}
+#define GIC_SetSecurity GIC_SetGroup
+
+/** \brief Get the interrupt group from the GIC's IGROUPR register.
+* \param [in] IRQn The interrupt to be queried.
+* \return 0 - Group 0, 1 - Group 1
+*/
+__STATIC_INLINE uint32_t GIC_GetGroup(IRQn_Type IRQn)
+{
+ return (GICDistributor->IGROUPR[IRQn / 32U] >> (IRQn % 32U)) & 1UL;
+}
+#define GIC_GetSecurity GIC_GetGroup
+
+/** \brief Initialize the interrupt distributor.
+*/
+__STATIC_INLINE void GIC_DistInit(void)
+{
+ uint32_t i;
+ uint32_t num_irq = 0U;
+ uint32_t priority_field;
+
+ //A reset sets all bits in the IGROUPRs corresponding to the SPIs to 0,
+ //configuring all of the interrupts as Secure.
+
+ //Disable interrupt forwarding
+ GIC_DisableDistributor();
+ //Get the maximum number of interrupts that the GIC supports
+ num_irq = 32U * ((GIC_DistributorInfo() & 0x1FU) + 1U);
+
+ /* Priority level is implementation defined.
+ To determine the number of priority bits implemented write 0xFF to an IPRIORITYR
+ priority field and read back the value stored.*/
+ GIC_SetPriority((IRQn_Type)0U, 0xFFU);
+ priority_field = GIC_GetPriority((IRQn_Type)0U);
+
+ for (i = 32U; i < num_irq; i++)
+ {
+ //Disable the SPI interrupt
+ GIC_DisableIRQ((IRQn_Type)i);
+ //Set level-sensitive (and N-N model)
+ GIC_SetConfiguration((IRQn_Type)i, 0U);
+ //Set priority
+ GIC_SetPriority((IRQn_Type)i, priority_field/2U);
+ //Set target list to CPU0
+ GIC_SetTarget((IRQn_Type)i, 1U);
+ }
+ //Enable distributor
+ GIC_EnableDistributor();
+}
+
+/** \brief Initialize the CPU's interrupt interface
+*/
+__STATIC_INLINE void GIC_CPUInterfaceInit(void)
+{
+ uint32_t i;
+ uint32_t priority_field;
+
+ //A reset sets all bits in the IGROUPRs corresponding to the SPIs to 0,
+ //configuring all of the interrupts as Secure.
+
+ //Disable interrupt forwarding
+ GIC_DisableInterface();
+
+ /* Priority level is implementation defined.
+ To determine the number of priority bits implemented write 0xFF to an IPRIORITYR
+ priority field and read back the value stored.*/
+ GIC_SetPriority((IRQn_Type)0U, 0xFFU);
+ priority_field = GIC_GetPriority((IRQn_Type)0U);
+
+ //SGI and PPI
+ for (i = 0U; i < 32U; i++)
+ {
+ if(i > 15U) {
+ //Set level-sensitive (and N-N model) for PPI
+ GIC_SetConfiguration((IRQn_Type)i, 0U);
+ }
+ //Disable SGI and PPI interrupts
+ GIC_DisableIRQ((IRQn_Type)i);
+ //Set priority
+ GIC_SetPriority((IRQn_Type)i, priority_field/2U);
+ }
+ //Enable interface
+ GIC_EnableInterface();
+ //Set binary point to 0
+ GIC_SetBinaryPoint(0U);
+ //Set priority mask
+ GIC_SetInterfacePriorityMask(0xFFU);
+}
+
+/** \brief Initialize and enable the GIC
+*/
+__STATIC_INLINE void GIC_Enable(void)
+{
+ GIC_DistInit();
+ GIC_CPUInterfaceInit(); //per CPU
+}
+#endif
+
+/* ########################## Generic Timer functions ############################ */
+#if (__TIM_PRESENT == 1U) || defined(DOXYGEN)
+
+/* PL1 Physical Timer */
+#if (__CORTEX_A == 7U) || defined(DOXYGEN)
+
+/** \brief Physical Timer Control register */
+typedef union
+{
+ struct
+ {
+ uint32_t ENABLE:1; /*!< \brief bit: 0 Enables the timer. */
+ uint32_t IMASK:1; /*!< \brief bit: 1 Timer output signal mask bit. */
+ uint32_t ISTATUS:1; /*!< \brief bit: 2 The status of the timer. */
+ RESERVED(0:29, uint32_t)
+ } b; /*!< \brief Structure used for bit access */
+ uint32_t w; /*!< \brief Type used for word access */
+} CNTP_CTL_Type;
+
+/** \brief Configures the frequency the timer shall run at.
+* \param [in] value The timer frequency in Hz.
+*/
+__STATIC_INLINE void PL1_SetCounterFrequency(uint32_t value)
+{
+ __set_CNTFRQ(value);
+ __ISB();
+}
+
+/** \brief Sets the reset value of the timer.
+* \param [in] value The value the timer is loaded with.
+*/
+__STATIC_INLINE void PL1_SetLoadValue(uint32_t value)
+{
+ __set_CNTP_TVAL(value);
+ __ISB();
+}
+
+/** \brief Get the current counter value.
+* \return Current counter value.
+*/
+__STATIC_INLINE uint32_t PL1_GetCurrentValue(void)
+{
+ return(__get_CNTP_TVAL());
+}
+
+/** \brief Get the current physical counter value.
+* \return Current physical counter value.
+*/
+__STATIC_INLINE uint64_t PL1_GetCurrentPhysicalValue(void)
+{
+ return(__get_CNTPCT());
+}
+
+/** \brief Set the physical compare value.
+* \param [in] value New physical timer compare value.
+*/
+__STATIC_INLINE void PL1_SetPhysicalCompareValue(uint64_t value)
+{
+ __set_CNTP_CVAL(value);
+ __ISB();
+}
+
+/** \brief Get the physical compare value.
+* \return Physical compare value.
+*/
+__STATIC_INLINE uint64_t PL1_GetPhysicalCompareValue(void)
+{
+ return(__get_CNTP_CVAL());
+}
+
+/** \brief Configure the timer by setting the control value.
+* \param [in] value New timer control value.
+*/
+__STATIC_INLINE void PL1_SetControl(uint32_t value)
+{
+ __set_CNTP_CTL(value);
+ __ISB();
+}
+
+/** \brief Get the control value.
+* \return Control value.
+*/
+__STATIC_INLINE uint32_t PL1_GetControl(void)
+{
+ return(__get_CNTP_CTL());
+}
+#endif
+
+/* Private Timer */
+#if ((__CORTEX_A == 5U) || (__CORTEX_A == 9U)) || defined(DOXYGEN)
+/** \brief Set the load value to timers LOAD register.
+* \param [in] value The load value to be set.
+*/
+__STATIC_INLINE void PTIM_SetLoadValue(uint32_t value)
+{
+ PTIM->LOAD = value;
+}
+
+/** \brief Get the load value from timers LOAD register.
+* \return Timer_Type::LOAD
+*/
+__STATIC_INLINE uint32_t PTIM_GetLoadValue(void)
+{
+ return(PTIM->LOAD);
+}
+
+/** \brief Set current counter value from its COUNTER register.
+*/
+__STATIC_INLINE void PTIM_SetCurrentValue(uint32_t value)
+{
+ PTIM->COUNTER = value;
+}
+
+/** \brief Get current counter value from timers COUNTER register.
+* \result Timer_Type::COUNTER
+*/
+__STATIC_INLINE uint32_t PTIM_GetCurrentValue(void)
+{
+ return(PTIM->COUNTER);
+}
+
+/** \brief Configure the timer using its CONTROL register.
+* \param [in] value The new configuration value to be set.
+*/
+__STATIC_INLINE void PTIM_SetControl(uint32_t value)
+{
+ PTIM->CONTROL = value;
+}
+
+/** ref Timer_Type::CONTROL Get the current timer configuration from its CONTROL register.
+* \return Timer_Type::CONTROL
+*/
+__STATIC_INLINE uint32_t PTIM_GetControl(void)
+{
+ return(PTIM->CONTROL);
+}
+
+/** ref Timer_Type::CONTROL Get the event flag in timers ISR register.
+* \return 0 - flag is not set, 1- flag is set
+*/
+__STATIC_INLINE uint32_t PTIM_GetEventFlag(void)
+{
+ return (PTIM->ISR & 1UL);
+}
+
+/** ref Timer_Type::CONTROL Clears the event flag in timers ISR register.
+*/
+__STATIC_INLINE void PTIM_ClearEventFlag(void)
+{
+ PTIM->ISR = 1;
+}
+#endif
+#endif
+
+/* ########################## MMU functions ###################################### */
+
+#define SECTION_DESCRIPTOR (0x2)
+#define SECTION_MASK (0xFFFFFFFC)
+
+#define SECTION_TEXCB_MASK (0xFFFF8FF3)
+#define SECTION_B_SHIFT (2)
+#define SECTION_C_SHIFT (3)
+#define SECTION_TEX0_SHIFT (12)
+#define SECTION_TEX1_SHIFT (13)
+#define SECTION_TEX2_SHIFT (14)
+
+#define SECTION_XN_MASK (0xFFFFFFEF)
+#define SECTION_XN_SHIFT (4)
+
+#define SECTION_DOMAIN_MASK (0xFFFFFE1F)
+#define SECTION_DOMAIN_SHIFT (5)
+
+#define SECTION_P_MASK (0xFFFFFDFF)
+#define SECTION_P_SHIFT (9)
+
+#define SECTION_AP_MASK (0xFFFF73FF)
+#define SECTION_AP_SHIFT (10)
+#define SECTION_AP2_SHIFT (15)
+
+#define SECTION_S_MASK (0xFFFEFFFF)
+#define SECTION_S_SHIFT (16)
+
+#define SECTION_NG_MASK (0xFFFDFFFF)
+#define SECTION_NG_SHIFT (17)
+
+#define SECTION_NS_MASK (0xFFF7FFFF)
+#define SECTION_NS_SHIFT (19)
+
+#define PAGE_L1_DESCRIPTOR (0x1)
+#define PAGE_L1_MASK (0xFFFFFFFC)
+
+#define PAGE_L2_4K_DESC (0x2)
+#define PAGE_L2_4K_MASK (0xFFFFFFFD)
+
+#define PAGE_L2_64K_DESC (0x1)
+#define PAGE_L2_64K_MASK (0xFFFFFFFC)
+
+#define PAGE_4K_TEXCB_MASK (0xFFFFFE33)
+#define PAGE_4K_B_SHIFT (2)
+#define PAGE_4K_C_SHIFT (3)
+#define PAGE_4K_TEX0_SHIFT (6)
+#define PAGE_4K_TEX1_SHIFT (7)
+#define PAGE_4K_TEX2_SHIFT (8)
+
+#define PAGE_64K_TEXCB_MASK (0xFFFF8FF3)
+#define PAGE_64K_B_SHIFT (2)
+#define PAGE_64K_C_SHIFT (3)
+#define PAGE_64K_TEX0_SHIFT (12)
+#define PAGE_64K_TEX1_SHIFT (13)
+#define PAGE_64K_TEX2_SHIFT (14)
+
+#define PAGE_TEXCB_MASK (0xFFFF8FF3)
+#define PAGE_B_SHIFT (2)
+#define PAGE_C_SHIFT (3)
+#define PAGE_TEX_SHIFT (12)
+
+#define PAGE_XN_4K_MASK (0xFFFFFFFE)
+#define PAGE_XN_4K_SHIFT (0)
+#define PAGE_XN_64K_MASK (0xFFFF7FFF)
+#define PAGE_XN_64K_SHIFT (15)
+
+#define PAGE_DOMAIN_MASK (0xFFFFFE1F)
+#define PAGE_DOMAIN_SHIFT (5)
+
+#define PAGE_P_MASK (0xFFFFFDFF)
+#define PAGE_P_SHIFT (9)
+
+#define PAGE_AP_MASK (0xFFFFFDCF)
+#define PAGE_AP_SHIFT (4)
+#define PAGE_AP2_SHIFT (9)
+
+#define PAGE_S_MASK (0xFFFFFBFF)
+#define PAGE_S_SHIFT (10)
+
+#define PAGE_NG_MASK (0xFFFFF7FF)
+#define PAGE_NG_SHIFT (11)
+
+#define PAGE_NS_MASK (0xFFFFFFF7)
+#define PAGE_NS_SHIFT (3)
+
+#define OFFSET_1M (0x00100000)
+#define OFFSET_64K (0x00010000)
+#define OFFSET_4K (0x00001000)
+
+#define DESCRIPTOR_FAULT (0x00000000)
+
+/* Attributes enumerations */
+
+/* Region size attributes */
+typedef enum
+{
+ SECTION,
+ PAGE_4k,
+ PAGE_64k,
+} mmu_region_size_Type;
+
+/* Region type attributes */
+typedef enum
+{
+ NORMAL,
+ DEVICE,
+ SHARED_DEVICE,
+ NON_SHARED_DEVICE,
+ STRONGLY_ORDERED
+} mmu_memory_Type;
+
+/* Region cacheability attributes */
+typedef enum
+{
+ NON_CACHEABLE,
+ WB_WA,
+ WT,
+ WB_NO_WA,
+} mmu_cacheability_Type;
+
+/* Region parity check attributes */
+typedef enum
+{
+ ECC_DISABLED,
+ ECC_ENABLED,
+} mmu_ecc_check_Type;
+
+/* Region execution attributes */
+typedef enum
+{
+ EXECUTE,
+ NON_EXECUTE,
+} mmu_execute_Type;
+
+/* Region global attributes */
+typedef enum
+{
+ GLOBAL,
+ NON_GLOBAL,
+} mmu_global_Type;
+
+/* Region shareability attributes */
+typedef enum
+{
+ NON_SHARED,
+ SHARED,
+} mmu_shared_Type;
+
+/* Region security attributes */
+typedef enum
+{
+ SECURE,
+ NON_SECURE,
+} mmu_secure_Type;
+
+/* Region access attributes */
+typedef enum
+{
+ NO_ACCESS,
+ RW,
+ READ,
+} mmu_access_Type;
+
+/* Memory Region definition */
+typedef struct RegionStruct {
+ mmu_region_size_Type rg_t;
+ mmu_memory_Type mem_t;
+ uint8_t domain;
+ mmu_cacheability_Type inner_norm_t;
+ mmu_cacheability_Type outer_norm_t;
+ mmu_ecc_check_Type e_t;
+ mmu_execute_Type xn_t;
+ mmu_global_Type g_t;
+ mmu_secure_Type sec_t;
+ mmu_access_Type priv_t;
+ mmu_access_Type user_t;
+ mmu_shared_Type sh_t;
+
+} mmu_region_attributes_Type;
+
+//Following macros define the descriptors and attributes
+//Sect_Normal. Outer & inner wb/wa, non-shareable, executable, rw, domain 0
+#define section_normal(descriptor_l1, region) region.rg_t = SECTION; \
+ region.domain = 0x0; \
+ region.e_t = ECC_DISABLED; \
+ region.g_t = GLOBAL; \
+ region.inner_norm_t = WB_WA; \
+ region.outer_norm_t = WB_WA; \
+ region.mem_t = NORMAL; \
+ region.sec_t = SECURE; \
+ region.xn_t = EXECUTE; \
+ region.priv_t = RW; \
+ region.user_t = RW; \
+ region.sh_t = NON_SHARED; \
+ MMU_GetSectionDescriptor(&descriptor_l1, region);
+
+//Sect_Normal_NC. Outer & inner non-cacheable, non-shareable, executable, rw, domain 0
+#define section_normal_nc(descriptor_l1, region) region.rg_t = SECTION; \
+ region.domain = 0x0; \
+ region.e_t = ECC_DISABLED; \
+ region.g_t = GLOBAL; \
+ region.inner_norm_t = NON_CACHEABLE; \
+ region.outer_norm_t = NON_CACHEABLE; \
+ region.mem_t = NORMAL; \
+ region.sec_t = SECURE; \
+ region.xn_t = EXECUTE; \
+ region.priv_t = RW; \
+ region.user_t = RW; \
+ region.sh_t = NON_SHARED; \
+ MMU_GetSectionDescriptor(&descriptor_l1, region);
+
+//Sect_Normal_Cod. Outer & inner wb/wa, non-shareable, executable, ro, domain 0
+#define section_normal_cod(descriptor_l1, region) region.rg_t = SECTION; \
+ region.domain = 0x0; \
+ region.e_t = ECC_DISABLED; \
+ region.g_t = GLOBAL; \
+ region.inner_norm_t = WB_WA; \
+ region.outer_norm_t = WB_WA; \
+ region.mem_t = NORMAL; \
+ region.sec_t = SECURE; \
+ region.xn_t = EXECUTE; \
+ region.priv_t = READ; \
+ region.user_t = READ; \
+ region.sh_t = NON_SHARED; \
+ MMU_GetSectionDescriptor(&descriptor_l1, region);
+
+//Sect_Normal_RO. Sect_Normal_Cod, but not executable
+#define section_normal_ro(descriptor_l1, region) region.rg_t = SECTION; \
+ region.domain = 0x0; \
+ region.e_t = ECC_DISABLED; \
+ region.g_t = GLOBAL; \
+ region.inner_norm_t = WB_WA; \
+ region.outer_norm_t = WB_WA; \
+ region.mem_t = NORMAL; \
+ region.sec_t = SECURE; \
+ region.xn_t = NON_EXECUTE; \
+ region.priv_t = READ; \
+ region.user_t = READ; \
+ region.sh_t = NON_SHARED; \
+ MMU_GetSectionDescriptor(&descriptor_l1, region);
+
+//Sect_Normal_RW. Sect_Normal_Cod, but writeable and not executable
+#define section_normal_rw(descriptor_l1, region) region.rg_t = SECTION; \
+ region.domain = 0x0; \
+ region.e_t = ECC_DISABLED; \
+ region.g_t = GLOBAL; \
+ region.inner_norm_t = WB_WA; \
+ region.outer_norm_t = WB_WA; \
+ region.mem_t = NORMAL; \
+ region.sec_t = SECURE; \
+ region.xn_t = NON_EXECUTE; \
+ region.priv_t = RW; \
+ region.user_t = RW; \
+ region.sh_t = NON_SHARED; \
+ MMU_GetSectionDescriptor(&descriptor_l1, region);
+//Sect_SO. Strongly-ordered (therefore shareable), not executable, rw, domain 0, base addr 0
+#define section_so(descriptor_l1, region) region.rg_t = SECTION; \
+ region.domain = 0x0; \
+ region.e_t = ECC_DISABLED; \
+ region.g_t = GLOBAL; \
+ region.inner_norm_t = NON_CACHEABLE; \
+ region.outer_norm_t = NON_CACHEABLE; \
+ region.mem_t = STRONGLY_ORDERED; \
+ region.sec_t = SECURE; \
+ region.xn_t = NON_EXECUTE; \
+ region.priv_t = RW; \
+ region.user_t = RW; \
+ region.sh_t = NON_SHARED; \
+ MMU_GetSectionDescriptor(&descriptor_l1, region);
+
+//Sect_Device_RO. Device, non-shareable, non-executable, ro, domain 0, base addr 0
+#define section_device_ro(descriptor_l1, region) region.rg_t = SECTION; \
+ region.domain = 0x0; \
+ region.e_t = ECC_DISABLED; \
+ region.g_t = GLOBAL; \
+ region.inner_norm_t = NON_CACHEABLE; \
+ region.outer_norm_t = NON_CACHEABLE; \
+ region.mem_t = STRONGLY_ORDERED; \
+ region.sec_t = SECURE; \
+ region.xn_t = NON_EXECUTE; \
+ region.priv_t = READ; \
+ region.user_t = READ; \
+ region.sh_t = NON_SHARED; \
+ MMU_GetSectionDescriptor(&descriptor_l1, region);
+
+//Sect_Device_RW. Sect_Device_RO, but writeable
+#define section_device_rw(descriptor_l1, region) region.rg_t = SECTION; \
+ region.domain = 0x0; \
+ region.e_t = ECC_DISABLED; \
+ region.g_t = GLOBAL; \
+ region.inner_norm_t = NON_CACHEABLE; \
+ region.outer_norm_t = NON_CACHEABLE; \
+ region.mem_t = STRONGLY_ORDERED; \
+ region.sec_t = SECURE; \
+ region.xn_t = NON_EXECUTE; \
+ region.priv_t = RW; \
+ region.user_t = RW; \
+ region.sh_t = NON_SHARED; \
+ MMU_GetSectionDescriptor(&descriptor_l1, region);
+//Page_4k_Device_RW. Shared device, not executable, rw, domain 0
+#define page4k_device_rw(descriptor_l1, descriptor_l2, region) region.rg_t = PAGE_4k; \
+ region.domain = 0x0; \
+ region.e_t = ECC_DISABLED; \
+ region.g_t = GLOBAL; \
+ region.inner_norm_t = NON_CACHEABLE; \
+ region.outer_norm_t = NON_CACHEABLE; \
+ region.mem_t = SHARED_DEVICE; \
+ region.sec_t = SECURE; \
+ region.xn_t = NON_EXECUTE; \
+ region.priv_t = RW; \
+ region.user_t = RW; \
+ region.sh_t = NON_SHARED; \
+ MMU_GetPageDescriptor(&descriptor_l1, &descriptor_l2, region);
+
+//Page_64k_Device_RW. Shared device, not executable, rw, domain 0
+#define page64k_device_rw(descriptor_l1, descriptor_l2, region) region.rg_t = PAGE_64k; \
+ region.domain = 0x0; \
+ region.e_t = ECC_DISABLED; \
+ region.g_t = GLOBAL; \
+ region.inner_norm_t = NON_CACHEABLE; \
+ region.outer_norm_t = NON_CACHEABLE; \
+ region.mem_t = SHARED_DEVICE; \
+ region.sec_t = SECURE; \
+ region.xn_t = NON_EXECUTE; \
+ region.priv_t = RW; \
+ region.user_t = RW; \
+ region.sh_t = NON_SHARED; \
+ MMU_GetPageDescriptor(&descriptor_l1, &descriptor_l2, region);
+
+/** \brief Set section execution-never attribute
+
+ \param [out] descriptor_l1 L1 descriptor.
+ \param [in] xn Section execution-never attribute : EXECUTE , NON_EXECUTE.
+
+ \return 0
+*/
+__STATIC_INLINE int MMU_XNSection(uint32_t *descriptor_l1, mmu_execute_Type xn)
+{
+ *descriptor_l1 &= SECTION_XN_MASK;
+ *descriptor_l1 |= ((xn & 0x1) << SECTION_XN_SHIFT);
+ return 0;
+}
+
+/** \brief Set section domain
+
+ \param [out] descriptor_l1 L1 descriptor.
+ \param [in] domain Section domain
+
+ \return 0
+*/
+__STATIC_INLINE int MMU_DomainSection(uint32_t *descriptor_l1, uint8_t domain)
+{
+ *descriptor_l1 &= SECTION_DOMAIN_MASK;
+ *descriptor_l1 |= ((domain & 0xF) << SECTION_DOMAIN_SHIFT);
+ return 0;
+}
+
+/** \brief Set section parity check
+
+ \param [out] descriptor_l1 L1 descriptor.
+ \param [in] p_bit Parity check: ECC_DISABLED, ECC_ENABLED
+
+ \return 0
+*/
+__STATIC_INLINE int MMU_PSection(uint32_t *descriptor_l1, mmu_ecc_check_Type p_bit)
+{
+ *descriptor_l1 &= SECTION_P_MASK;
+ *descriptor_l1 |= ((p_bit & 0x1) << SECTION_P_SHIFT);
+ return 0;
+}
+
+/** \brief Set section access privileges
+
+ \param [out] descriptor_l1 L1 descriptor.
+ \param [in] user User Level Access: NO_ACCESS, RW, READ
+ \param [in] priv Privilege Level Access: NO_ACCESS, RW, READ
+ \param [in] afe Access flag enable
+
+ \return 0
+*/
+__STATIC_INLINE int MMU_APSection(uint32_t *descriptor_l1, mmu_access_Type user, mmu_access_Type priv, uint32_t afe)
+{
+ uint32_t ap = 0;
+
+ if (afe == 0) { //full access
+ if ((priv == NO_ACCESS) && (user == NO_ACCESS)) { ap = 0x0; }
+ else if ((priv == RW) && (user == NO_ACCESS)) { ap = 0x1; }
+ else if ((priv == RW) && (user == READ)) { ap = 0x2; }
+ else if ((priv == RW) && (user == RW)) { ap = 0x3; }
+ else if ((priv == READ) && (user == NO_ACCESS)) { ap = 0x5; }
+ else if ((priv == READ) && (user == READ)) { ap = 0x7; }
+ }
+
+ else { //Simplified access
+ if ((priv == RW) && (user == NO_ACCESS)) { ap = 0x1; }
+ else if ((priv == RW) && (user == RW)) { ap = 0x3; }
+ else if ((priv == READ) && (user == NO_ACCESS)) { ap = 0x5; }
+ else if ((priv == READ) && (user == READ)) { ap = 0x7; }
+ }
+
+ *descriptor_l1 &= SECTION_AP_MASK;
+ *descriptor_l1 |= (ap & 0x3) << SECTION_AP_SHIFT;
+ *descriptor_l1 |= ((ap & 0x4)>>2) << SECTION_AP2_SHIFT;
+
+ return 0;
+}
+
+/** \brief Set section shareability
+
+ \param [out] descriptor_l1 L1 descriptor.
+ \param [in] s_bit Section shareability: NON_SHARED, SHARED
+
+ \return 0
+*/
+__STATIC_INLINE int MMU_SharedSection(uint32_t *descriptor_l1, mmu_shared_Type s_bit)
+{
+ *descriptor_l1 &= SECTION_S_MASK;
+ *descriptor_l1 |= ((s_bit & 0x1) << SECTION_S_SHIFT);
+ return 0;
+}
+
+/** \brief Set section Global attribute
+
+ \param [out] descriptor_l1 L1 descriptor.
+ \param [in] g_bit Section attribute: GLOBAL, NON_GLOBAL
+
+ \return 0
+*/
+__STATIC_INLINE int MMU_GlobalSection(uint32_t *descriptor_l1, mmu_global_Type g_bit)
+{
+ *descriptor_l1 &= SECTION_NG_MASK;
+ *descriptor_l1 |= ((g_bit & 0x1) << SECTION_NG_SHIFT);
+ return 0;
+}
+
+/** \brief Set section Security attribute
+
+ \param [out] descriptor_l1 L1 descriptor.
+ \param [in] s_bit Section Security attribute: SECURE, NON_SECURE
+
+ \return 0
+*/
+__STATIC_INLINE int MMU_SecureSection(uint32_t *descriptor_l1, mmu_secure_Type s_bit)
+{
+ *descriptor_l1 &= SECTION_NS_MASK;
+ *descriptor_l1 |= ((s_bit & 0x1) << SECTION_NS_SHIFT);
+ return 0;
+}
+
+/* Page 4k or 64k */
+/** \brief Set 4k/64k page execution-never attribute
+
+ \param [out] descriptor_l2 L2 descriptor.
+ \param [in] xn Page execution-never attribute : EXECUTE , NON_EXECUTE.
+ \param [in] page Page size: PAGE_4k, PAGE_64k,
+
+ \return 0
+*/
+__STATIC_INLINE int MMU_XNPage(uint32_t *descriptor_l2, mmu_execute_Type xn, mmu_region_size_Type page)
+{
+ if (page == PAGE_4k)
+ {
+ *descriptor_l2 &= PAGE_XN_4K_MASK;
+ *descriptor_l2 |= ((xn & 0x1) << PAGE_XN_4K_SHIFT);
+ }
+ else
+ {
+ *descriptor_l2 &= PAGE_XN_64K_MASK;
+ *descriptor_l2 |= ((xn & 0x1) << PAGE_XN_64K_SHIFT);
+ }
+ return 0;
+}
+
+/** \brief Set 4k/64k page domain
+
+ \param [out] descriptor_l1 L1 descriptor.
+ \param [in] domain Page domain
+
+ \return 0
+*/
+__STATIC_INLINE int MMU_DomainPage(uint32_t *descriptor_l1, uint8_t domain)
+{
+ *descriptor_l1 &= PAGE_DOMAIN_MASK;
+ *descriptor_l1 |= ((domain & 0xf) << PAGE_DOMAIN_SHIFT);
+ return 0;
+}
+
+/** \brief Set 4k/64k page parity check
+
+ \param [out] descriptor_l1 L1 descriptor.
+ \param [in] p_bit Parity check: ECC_DISABLED, ECC_ENABLED
+
+ \return 0
+*/
+__STATIC_INLINE int MMU_PPage(uint32_t *descriptor_l1, mmu_ecc_check_Type p_bit)
+{
+ *descriptor_l1 &= SECTION_P_MASK;
+ *descriptor_l1 |= ((p_bit & 0x1) << SECTION_P_SHIFT);
+ return 0;
+}
+
+/** \brief Set 4k/64k page access privileges
+
+ \param [out] descriptor_l2 L2 descriptor.
+ \param [in] user User Level Access: NO_ACCESS, RW, READ
+ \param [in] priv Privilege Level Access: NO_ACCESS, RW, READ
+ \param [in] afe Access flag enable
+
+ \return 0
+*/
+__STATIC_INLINE int MMU_APPage(uint32_t *descriptor_l2, mmu_access_Type user, mmu_access_Type priv, uint32_t afe)
+{
+ uint32_t ap = 0;
+
+ if (afe == 0) { //full access
+ if ((priv == NO_ACCESS) && (user == NO_ACCESS)) { ap = 0x0; }
+ else if ((priv == RW) && (user == NO_ACCESS)) { ap = 0x1; }
+ else if ((priv == RW) && (user == READ)) { ap = 0x2; }
+ else if ((priv == RW) && (user == RW)) { ap = 0x3; }
+ else if ((priv == READ) && (user == NO_ACCESS)) { ap = 0x5; }
+ else if ((priv == READ) && (user == READ)) { ap = 0x6; }
+ }
+
+ else { //Simplified access
+ if ((priv == RW) && (user == NO_ACCESS)) { ap = 0x1; }
+ else if ((priv == RW) && (user == RW)) { ap = 0x3; }
+ else if ((priv == READ) && (user == NO_ACCESS)) { ap = 0x5; }
+ else if ((priv == READ) && (user == READ)) { ap = 0x7; }
+ }
+
+ *descriptor_l2 &= PAGE_AP_MASK;
+ *descriptor_l2 |= (ap & 0x3) << PAGE_AP_SHIFT;
+ *descriptor_l2 |= ((ap & 0x4)>>2) << PAGE_AP2_SHIFT;
+
+ return 0;
+}
+
+/** \brief Set 4k/64k page shareability
+
+ \param [out] descriptor_l2 L2 descriptor.
+ \param [in] s_bit 4k/64k page shareability: NON_SHARED, SHARED
+
+ \return 0
+*/
+__STATIC_INLINE int MMU_SharedPage(uint32_t *descriptor_l2, mmu_shared_Type s_bit)
+{
+ *descriptor_l2 &= PAGE_S_MASK;
+ *descriptor_l2 |= ((s_bit & 0x1) << PAGE_S_SHIFT);
+ return 0;
+}
+
+/** \brief Set 4k/64k page Global attribute
+
+ \param [out] descriptor_l2 L2 descriptor.
+ \param [in] g_bit 4k/64k page attribute: GLOBAL, NON_GLOBAL
+
+ \return 0
+*/
+__STATIC_INLINE int MMU_GlobalPage(uint32_t *descriptor_l2, mmu_global_Type g_bit)
+{
+ *descriptor_l2 &= PAGE_NG_MASK;
+ *descriptor_l2 |= ((g_bit & 0x1) << PAGE_NG_SHIFT);
+ return 0;
+}
+
+/** \brief Set 4k/64k page Security attribute
+
+ \param [out] descriptor_l1 L1 descriptor.
+ \param [in] s_bit 4k/64k page Security attribute: SECURE, NON_SECURE
+
+ \return 0
+*/
+__STATIC_INLINE int MMU_SecurePage(uint32_t *descriptor_l1, mmu_secure_Type s_bit)
+{
+ *descriptor_l1 &= PAGE_NS_MASK;
+ *descriptor_l1 |= ((s_bit & 0x1) << PAGE_NS_SHIFT);
+ return 0;
+}
+
+/** \brief Set Section memory attributes
+
+ \param [out] descriptor_l1 L1 descriptor.
+ \param [in] mem Section memory type: NORMAL, DEVICE, SHARED_DEVICE, NON_SHARED_DEVICE, STRONGLY_ORDERED
+ \param [in] outer Outer cacheability: NON_CACHEABLE, WB_WA, WT, WB_NO_WA,
+ \param [in] inner Inner cacheability: NON_CACHEABLE, WB_WA, WT, WB_NO_WA,
+
+ \return 0
+*/
+__STATIC_INLINE int MMU_MemorySection(uint32_t *descriptor_l1, mmu_memory_Type mem, mmu_cacheability_Type outer, mmu_cacheability_Type inner)
+{
+ *descriptor_l1 &= SECTION_TEXCB_MASK;
+
+ if (STRONGLY_ORDERED == mem)
+ {
+ return 0;
+ }
+ else if (SHARED_DEVICE == mem)
+ {
+ *descriptor_l1 |= (1 << SECTION_B_SHIFT);
+ }
+ else if (NON_SHARED_DEVICE == mem)
+ {
+ *descriptor_l1 |= (1 << SECTION_TEX1_SHIFT);
+ }
+ else if (NORMAL == mem)
+ {
+ *descriptor_l1 |= 1 << SECTION_TEX2_SHIFT;
+ switch(inner)
+ {
+ case NON_CACHEABLE:
+ break;
+ case WB_WA:
+ *descriptor_l1 |= (1 << SECTION_B_SHIFT);
+ break;
+ case WT:
+ *descriptor_l1 |= 1 << SECTION_C_SHIFT;
+ break;
+ case WB_NO_WA:
+ *descriptor_l1 |= (1 << SECTION_B_SHIFT) | (1 << SECTION_C_SHIFT);
+ break;
+ }
+ switch(outer)
+ {
+ case NON_CACHEABLE:
+ break;
+ case WB_WA:
+ *descriptor_l1 |= (1 << SECTION_TEX0_SHIFT);
+ break;
+ case WT:
+ *descriptor_l1 |= 1 << SECTION_TEX1_SHIFT;
+ break;
+ case WB_NO_WA:
+ *descriptor_l1 |= (1 << SECTION_TEX0_SHIFT) | (1 << SECTION_TEX0_SHIFT);
+ break;
+ }
+ }
+ return 0;
+}
+
+/** \brief Set 4k/64k page memory attributes
+
+ \param [out] descriptor_l2 L2 descriptor.
+ \param [in] mem 4k/64k page memory type: NORMAL, DEVICE, SHARED_DEVICE, NON_SHARED_DEVICE, STRONGLY_ORDERED
+ \param [in] outer Outer cacheability: NON_CACHEABLE, WB_WA, WT, WB_NO_WA,
+ \param [in] inner Inner cacheability: NON_CACHEABLE, WB_WA, WT, WB_NO_WA,
+ \param [in] page Page size
+
+ \return 0
+*/
+__STATIC_INLINE int MMU_MemoryPage(uint32_t *descriptor_l2, mmu_memory_Type mem, mmu_cacheability_Type outer, mmu_cacheability_Type inner, mmu_region_size_Type page)
+{
+ *descriptor_l2 &= PAGE_4K_TEXCB_MASK;
+
+ if (page == PAGE_64k)
+ {
+ //same as section
+ MMU_MemorySection(descriptor_l2, mem, outer, inner);
+ }
+ else
+ {
+ if (STRONGLY_ORDERED == mem)
+ {
+ return 0;
+ }
+ else if (SHARED_DEVICE == mem)
+ {
+ *descriptor_l2 |= (1 << PAGE_4K_B_SHIFT);
+ }
+ else if (NON_SHARED_DEVICE == mem)
+ {
+ *descriptor_l2 |= (1 << PAGE_4K_TEX1_SHIFT);
+ }
+ else if (NORMAL == mem)
+ {
+ *descriptor_l2 |= 1 << PAGE_4K_TEX2_SHIFT;
+ switch(inner)
+ {
+ case NON_CACHEABLE:
+ break;
+ case WB_WA:
+ *descriptor_l2 |= (1 << PAGE_4K_B_SHIFT);
+ break;
+ case WT:
+ *descriptor_l2 |= 1 << PAGE_4K_C_SHIFT;
+ break;
+ case WB_NO_WA:
+ *descriptor_l2 |= (1 << PAGE_4K_B_SHIFT) | (1 << PAGE_4K_C_SHIFT);
+ break;
+ }
+ switch(outer)
+ {
+ case NON_CACHEABLE:
+ break;
+ case WB_WA:
+ *descriptor_l2 |= (1 << PAGE_4K_TEX0_SHIFT);
+ break;
+ case WT:
+ *descriptor_l2 |= 1 << PAGE_4K_TEX1_SHIFT;
+ break;
+ case WB_NO_WA:
+ *descriptor_l2 |= (1 << PAGE_4K_TEX0_SHIFT) | (1 << PAGE_4K_TEX0_SHIFT);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/** \brief Create a L1 section descriptor
+
+ \param [out] descriptor L1 descriptor
+ \param [in] reg Section attributes
+
+ \return 0
+*/
+__STATIC_INLINE int MMU_GetSectionDescriptor(uint32_t *descriptor, mmu_region_attributes_Type reg)
+{
+ *descriptor = 0;
+
+ MMU_MemorySection(descriptor, reg.mem_t, reg.outer_norm_t, reg.inner_norm_t);
+ MMU_XNSection(descriptor,reg.xn_t);
+ MMU_DomainSection(descriptor, reg.domain);
+ MMU_PSection(descriptor, reg.e_t);
+ MMU_APSection(descriptor, reg.priv_t, reg.user_t, 1);
+ MMU_SharedSection(descriptor,reg.sh_t);
+ MMU_GlobalSection(descriptor,reg.g_t);
+ MMU_SecureSection(descriptor,reg.sec_t);
+ *descriptor &= SECTION_MASK;
+ *descriptor |= SECTION_DESCRIPTOR;
+
+ return 0;
+}
+
+
+/** \brief Create a L1 and L2 4k/64k page descriptor
+
+ \param [out] descriptor L1 descriptor
+ \param [out] descriptor2 L2 descriptor
+ \param [in] reg 4k/64k page attributes
+
+ \return 0
+*/
+__STATIC_INLINE int MMU_GetPageDescriptor(uint32_t *descriptor, uint32_t *descriptor2, mmu_region_attributes_Type reg)
+{
+ *descriptor = 0;
+ *descriptor2 = 0;
+
+ switch (reg.rg_t)
+ {
+ case PAGE_4k:
+ MMU_MemoryPage(descriptor2, reg.mem_t, reg.outer_norm_t, reg.inner_norm_t, PAGE_4k);
+ MMU_XNPage(descriptor2, reg.xn_t, PAGE_4k);
+ MMU_DomainPage(descriptor, reg.domain);
+ MMU_PPage(descriptor, reg.e_t);
+ MMU_APPage(descriptor2, reg.priv_t, reg.user_t, 1);
+ MMU_SharedPage(descriptor2,reg.sh_t);
+ MMU_GlobalPage(descriptor2,reg.g_t);
+ MMU_SecurePage(descriptor,reg.sec_t);
+ *descriptor &= PAGE_L1_MASK;
+ *descriptor |= PAGE_L1_DESCRIPTOR;
+ *descriptor2 &= PAGE_L2_4K_MASK;
+ *descriptor2 |= PAGE_L2_4K_DESC;
+ break;
+
+ case PAGE_64k:
+ MMU_MemoryPage(descriptor2, reg.mem_t, reg.outer_norm_t, reg.inner_norm_t, PAGE_64k);
+ MMU_XNPage(descriptor2, reg.xn_t, PAGE_64k);
+ MMU_DomainPage(descriptor, reg.domain);
+ MMU_PPage(descriptor, reg.e_t);
+ MMU_APPage(descriptor2, reg.priv_t, reg.user_t, 1);
+ MMU_SharedPage(descriptor2,reg.sh_t);
+ MMU_GlobalPage(descriptor2,reg.g_t);
+ MMU_SecurePage(descriptor,reg.sec_t);
+ *descriptor &= PAGE_L1_MASK;
+ *descriptor |= PAGE_L1_DESCRIPTOR;
+ *descriptor2 &= PAGE_L2_64K_MASK;
+ *descriptor2 |= PAGE_L2_64K_DESC;
+ break;
+
+ case SECTION:
+ //error
+ break;
+ }
+
+ return 0;
+}
+
+/** \brief Create a 1MB Section
+
+ \param [in] ttb Translation table base address
+ \param [in] base_address Section base address
+ \param [in] count Number of sections to create
+ \param [in] descriptor_l1 L1 descriptor (region attributes)
+
+*/
+__STATIC_INLINE void MMU_TTSection(uint32_t *ttb, uint32_t base_address, uint32_t count, uint32_t descriptor_l1)
+{
+ uint32_t offset;
+ uint32_t entry;
+ uint32_t i;
+
+ offset = base_address >> 20;
+ entry = (base_address & 0xFFF00000) | descriptor_l1;
+
+ //4 bytes aligned
+ ttb = ttb + offset;
+
+ for (i = 0; i < count; i++ )
+ {
+ //4 bytes aligned
+ *ttb++ = entry;
+ entry += OFFSET_1M;
+ }
+}
+
+/** \brief Create a 4k page entry
+
+ \param [in] ttb L1 table base address
+ \param [in] base_address 4k base address
+ \param [in] count Number of 4k pages to create
+ \param [in] descriptor_l1 L1 descriptor (region attributes)
+ \param [in] ttb_l2 L2 table base address
+ \param [in] descriptor_l2 L2 descriptor (region attributes)
+
+*/
+__STATIC_INLINE void MMU_TTPage4k(uint32_t *ttb, uint32_t base_address, uint32_t count, uint32_t descriptor_l1, uint32_t *ttb_l2, uint32_t descriptor_l2 )
+{
+
+ uint32_t offset, offset2;
+ uint32_t entry, entry2;
+ uint32_t i;
+
+ offset = base_address >> 20;
+ entry = ((int)ttb_l2 & 0xFFFFFC00) | descriptor_l1;
+
+ //4 bytes aligned
+ ttb += offset;
+ //create l1_entry
+ *ttb = entry;
+
+ offset2 = (base_address & 0xff000) >> 12;
+ ttb_l2 += offset2;
+ entry2 = (base_address & 0xFFFFF000) | descriptor_l2;
+ for (i = 0; i < count; i++ )
+ {
+ //4 bytes aligned
+ *ttb_l2++ = entry2;
+ entry2 += OFFSET_4K;
+ }
+}
+
+/** \brief Create a 64k page entry
+
+ \param [in] ttb L1 table base address
+ \param [in] base_address 64k base address
+ \param [in] count Number of 64k pages to create
+ \param [in] descriptor_l1 L1 descriptor (region attributes)
+ \param [in] ttb_l2 L2 table base address
+ \param [in] descriptor_l2 L2 descriptor (region attributes)
+
+*/
+__STATIC_INLINE void MMU_TTPage64k(uint32_t *ttb, uint32_t base_address, uint32_t count, uint32_t descriptor_l1, uint32_t *ttb_l2, uint32_t descriptor_l2 )
+{
+ uint32_t offset, offset2;
+ uint32_t entry, entry2;
+ uint32_t i,j;
+
+
+ offset = base_address >> 20;
+ entry = ((int)ttb_l2 & 0xFFFFFC00) | descriptor_l1;
+
+ //4 bytes aligned
+ ttb += offset;
+ //create l1_entry
+ *ttb = entry;
+
+ offset2 = (base_address & 0xff000) >> 12;
+ ttb_l2 += offset2;
+ entry2 = (base_address & 0xFFFF0000) | descriptor_l2;
+ for (i = 0; i < count; i++ )
+ {
+ //create 16 entries
+ for (j = 0; j < 16; j++)
+ {
+ //4 bytes aligned
+ *ttb_l2++ = entry2;
+ }
+ entry2 += OFFSET_64K;
+ }
+}
+
+/** \brief Enable MMU
+*/
+__STATIC_INLINE void MMU_Enable(void)
+{
+ // Set M bit 0 to enable the MMU
+ // Set AFE bit to enable simplified access permissions model
+ // Clear TRE bit to disable TEX remap and A bit to disable strict alignment fault checking
+ __set_SCTLR( (__get_SCTLR() & ~(1 << 28) & ~(1 << 1)) | 1 | (1 << 29));
+ __ISB();
+}
+
+/** \brief Disable MMU
+*/
+__STATIC_INLINE void MMU_Disable(void)
+{
+ // Clear M bit 0 to disable the MMU
+ __set_SCTLR( __get_SCTLR() & ~1);
+ __ISB();
+}
+
+/** \brief Invalidate entire unified TLB
+*/
+
+__STATIC_INLINE void MMU_InvalidateTLB(void)
+{
+ __set_TLBIALL(0);
+ __DSB(); //ensure completion of the invalidation
+ __ISB(); //ensure instruction fetch path sees new state
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CA_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/irq_ctrl.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/irq_ctrl.h
new file mode 100644
index 0000000..b171ef0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/irq_ctrl.h
@@ -0,0 +1,186 @@
+/**************************************************************************//**
+ * @file irq_ctrl.h
+ * @brief Interrupt Controller API header file
+ * @version V1.0.0
+ * @date 23. June 2017
+ ******************************************************************************/
+/*
+ * Copyright (c) 2017 ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef IRQ_CTRL_H_
+#define IRQ_CTRL_H_
+
+#include
+
+#ifndef IRQHANDLER_T
+#define IRQHANDLER_T
+/// Interrupt handler data type
+typedef void (*IRQHandler_t) (void);
+#endif
+
+#ifndef IRQN_ID_T
+#define IRQN_ID_T
+/// Interrupt ID number data type
+typedef int32_t IRQn_ID_t;
+#endif
+
+/* Interrupt mode bit-masks */
+#define IRQ_MODE_TRIG_Pos (0U)
+#define IRQ_MODE_TRIG_Msk (0x07UL /*<< IRQ_MODE_TRIG_Pos*/)
+#define IRQ_MODE_TRIG_LEVEL (0x00UL /*<< IRQ_MODE_TRIG_Pos*/) ///< Trigger: level triggered interrupt
+#define IRQ_MODE_TRIG_LEVEL_LOW (0x01UL /*<< IRQ_MODE_TRIG_Pos*/) ///< Trigger: low level triggered interrupt
+#define IRQ_MODE_TRIG_LEVEL_HIGH (0x02UL /*<< IRQ_MODE_TRIG_Pos*/) ///< Trigger: high level triggered interrupt
+#define IRQ_MODE_TRIG_EDGE (0x04UL /*<< IRQ_MODE_TRIG_Pos*/) ///< Trigger: edge triggered interrupt
+#define IRQ_MODE_TRIG_EDGE_RISING (0x05UL /*<< IRQ_MODE_TRIG_Pos*/) ///< Trigger: rising edge triggered interrupt
+#define IRQ_MODE_TRIG_EDGE_FALLING (0x06UL /*<< IRQ_MODE_TRIG_Pos*/) ///< Trigger: falling edge triggered interrupt
+#define IRQ_MODE_TRIG_EDGE_BOTH (0x07UL /*<< IRQ_MODE_TRIG_Pos*/) ///< Trigger: rising and falling edge triggered interrupt
+
+#define IRQ_MODE_TYPE_Pos (3U)
+#define IRQ_MODE_TYPE_Msk (0x01UL << IRQ_MODE_TYPE_Pos)
+#define IRQ_MODE_TYPE_IRQ (0x00UL << IRQ_MODE_TYPE_Pos) ///< Type: interrupt source triggers CPU IRQ line
+#define IRQ_MODE_TYPE_FIQ (0x01UL << IRQ_MODE_TYPE_Pos) ///< Type: interrupt source triggers CPU FIQ line
+
+#define IRQ_MODE_DOMAIN_Pos (4U)
+#define IRQ_MODE_DOMAIN_Msk (0x01UL << IRQ_MODE_DOMAIN_Pos)
+#define IRQ_MODE_DOMAIN_NONSECURE (0x00UL << IRQ_MODE_DOMAIN_Pos) ///< Domain: interrupt is targeting non-secure domain
+#define IRQ_MODE_DOMAIN_SECURE (0x01UL << IRQ_MODE_DOMAIN_Pos) ///< Domain: interrupt is targeting secure domain
+
+#define IRQ_MODE_CPU_Pos (5U)
+#define IRQ_MODE_CPU_Msk (0xFFUL << IRQ_MODE_CPU_Pos)
+#define IRQ_MODE_CPU_ALL (0x00UL << IRQ_MODE_CPU_Pos) ///< CPU: interrupt targets all CPUs
+#define IRQ_MODE_CPU_0 (0x01UL << IRQ_MODE_CPU_Pos) ///< CPU: interrupt targets CPU 0
+#define IRQ_MODE_CPU_1 (0x02UL << IRQ_MODE_CPU_Pos) ///< CPU: interrupt targets CPU 1
+#define IRQ_MODE_CPU_2 (0x04UL << IRQ_MODE_CPU_Pos) ///< CPU: interrupt targets CPU 2
+#define IRQ_MODE_CPU_3 (0x08UL << IRQ_MODE_CPU_Pos) ///< CPU: interrupt targets CPU 3
+#define IRQ_MODE_CPU_4 (0x10UL << IRQ_MODE_CPU_Pos) ///< CPU: interrupt targets CPU 4
+#define IRQ_MODE_CPU_5 (0x20UL << IRQ_MODE_CPU_Pos) ///< CPU: interrupt targets CPU 5
+#define IRQ_MODE_CPU_6 (0x40UL << IRQ_MODE_CPU_Pos) ///< CPU: interrupt targets CPU 6
+#define IRQ_MODE_CPU_7 (0x80UL << IRQ_MODE_CPU_Pos) ///< CPU: interrupt targets CPU 7
+
+#define IRQ_MODE_ERROR (0x80000000UL) ///< Bit indicating mode value error
+
+/* Interrupt priority bit-masks */
+#define IRQ_PRIORITY_Msk (0x0000FFFFUL) ///< Interrupt priority value bit-mask
+#define IRQ_PRIORITY_ERROR (0x80000000UL) ///< Bit indicating priority value error
+
+/// Initialize interrupt controller.
+/// \return 0 on success, -1 on error.
+int32_t IRQ_Initialize (void);
+
+/// Register interrupt handler.
+/// \param[in] irqn interrupt ID number
+/// \param[in] handler interrupt handler function address
+/// \return 0 on success, -1 on error.
+int32_t IRQ_SetHandler (IRQn_ID_t irqn, IRQHandler_t handler);
+
+/// Get the registered interrupt handler.
+/// \param[in] irqn interrupt ID number
+/// \return registered interrupt handler function address.
+IRQHandler_t IRQ_GetHandler (IRQn_ID_t irqn);
+
+/// Enable interrupt.
+/// \param[in] irqn interrupt ID number
+/// \return 0 on success, -1 on error.
+int32_t IRQ_Enable (IRQn_ID_t irqn);
+
+/// Disable interrupt.
+/// \param[in] irqn interrupt ID number
+/// \return 0 on success, -1 on error.
+int32_t IRQ_Disable (IRQn_ID_t irqn);
+
+/// Get interrupt enable state.
+/// \param[in] irqn interrupt ID number
+/// \return 0 - interrupt is disabled, 1 - interrupt is enabled.
+uint32_t IRQ_GetEnableState (IRQn_ID_t irqn);
+
+/// Configure interrupt request mode.
+/// \param[in] irqn interrupt ID number
+/// \param[in] mode mode configuration
+/// \return 0 on success, -1 on error.
+int32_t IRQ_SetMode (IRQn_ID_t irqn, uint32_t mode);
+
+/// Get interrupt mode configuration.
+/// \param[in] irqn interrupt ID number
+/// \return current interrupt mode configuration with optional IRQ_MODE_ERROR bit set.
+uint32_t IRQ_GetMode (IRQn_ID_t irqn);
+
+/// Get ID number of current interrupt request (IRQ).
+/// \return interrupt ID number.
+IRQn_ID_t IRQ_GetActiveIRQ (void);
+
+/// Get ID number of current fast interrupt request (FIQ).
+/// \return interrupt ID number.
+IRQn_ID_t IRQ_GetActiveFIQ (void);
+
+/// Signal end of interrupt processing.
+/// \param[in] irqn interrupt ID number
+/// \return 0 on success, -1 on error.
+int32_t IRQ_EndOfInterrupt (IRQn_ID_t irqn);
+
+/// Set interrupt pending flag.
+/// \param[in] irqn interrupt ID number
+/// \return 0 on success, -1 on error.
+int32_t IRQ_SetPending (IRQn_ID_t irqn);
+
+/// Get interrupt pending flag.
+/// \param[in] irqn interrupt ID number
+/// \return 0 - interrupt is not pending, 1 - interrupt is pending.
+uint32_t IRQ_GetPending (IRQn_ID_t irqn);
+
+/// Clear interrupt pending flag.
+/// \param[in] irqn interrupt ID number
+/// \return 0 on success, -1 on error.
+int32_t IRQ_ClearPending (IRQn_ID_t irqn);
+
+/// Set interrupt priority value.
+/// \param[in] irqn interrupt ID number
+/// \param[in] priority interrupt priority value
+/// \return 0 on success, -1 on error.
+int32_t IRQ_SetPriority (IRQn_ID_t irqn, uint32_t priority);
+
+/// Get interrupt priority.
+/// \param[in] irqn interrupt ID number
+/// \return current interrupt priority value with optional IRQ_PRIORITY_ERROR bit set.
+uint32_t IRQ_GetPriority (IRQn_ID_t irqn);
+
+/// Set priority masking threshold.
+/// \param[in] priority priority masking threshold value
+/// \return 0 on success, -1 on error.
+int32_t IRQ_SetPriorityMask (uint32_t priority);
+
+/// Get priority masking threshold
+/// \return current priority masking threshold value with optional IRQ_PRIORITY_ERROR bit set.
+uint32_t IRQ_GetPriorityMask (void);
+
+/// Set priority grouping field split point
+/// \param[in] bits number of MSB bits included in the group priority field comparison
+/// \return 0 on success, -1 on error.
+int32_t IRQ_SetPriorityGroupBits (uint32_t bits);
+
+/// Get priority grouping field split point
+/// \return current number of MSB bits included in the group priority field comparison with
+/// optional IRQ_PRIORITY_ERROR bit set.
+uint32_t IRQ_GetPriorityGroupBits (void);
+
+#endif // IRQ_CTRL_H_
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/system_ARMCA5.h b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/system_ARMCA5.h
new file mode 100644
index 0000000..7d48ceb
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Include/system_ARMCA5.h
@@ -0,0 +1,65 @@
+/******************************************************************************
+ * @file system_ARMCA5.h
+ * @brief CMSIS Device System Header File for ARM Cortex-A Device Series
+ * @version V1.00
+ * @date 16 Mar 2017
+ *
+ * @note
+ *
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __SYSTEM_ARMCA5_H
+#define __SYSTEM_ARMCA5_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+
+extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
+
+/**
+ \brief Setup the microcontroller system.
+
+ Initialize the System and update the SystemCoreClock variable.
+ */
+extern void SystemInit (void);
+
+
+/**
+ \brief Update SystemCoreClock variable.
+
+ Updates the SystemCoreClock with current core Clock retrieved from cpu registers.
+ */
+extern void SystemCoreClockUpdate (void);
+
+/**
+ \brief Create Translation Table.
+
+ Creates Memory Management Unit Translation Table.
+ */
+extern void MMU_CreateTranslationTable(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SYSTEM_ARMCA5_H */
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Source/irq_ctrl_gic.c b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Source/irq_ctrl_gic.c
new file mode 100644
index 0000000..25d1359
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/Core_A/Source/irq_ctrl_gic.c
@@ -0,0 +1,410 @@
+/**************************************************************************//**
+ * @file irq_ctrl_gic.c
+ * @brief Interrupt controller handling implementation for GIC
+ * @version V1.0.1
+ * @date 9. April 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2017 ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+
+#include "RTE_Components.h"
+#include CMSIS_device_header
+
+#include "irq_ctrl.h"
+
+#if defined(__GIC_PRESENT) && (__GIC_PRESENT == 1U)
+
+/// Number of implemented interrupt lines
+#ifndef IRQ_GIC_LINE_COUNT
+#define IRQ_GIC_LINE_COUNT (1020U)
+#endif
+
+static IRQHandler_t IRQTable[IRQ_GIC_LINE_COUNT] = { 0U };
+static uint32_t IRQ_ID0;
+
+/// Initialize interrupt controller.
+__WEAK int32_t IRQ_Initialize (void) {
+ uint32_t i;
+
+ for (i = 0U; i < IRQ_GIC_LINE_COUNT; i++) {
+ IRQTable[i] = (IRQHandler_t)NULL;
+ }
+ GIC_Enable();
+ return (0);
+}
+
+
+/// Register interrupt handler.
+__WEAK int32_t IRQ_SetHandler (IRQn_ID_t irqn, IRQHandler_t handler) {
+ int32_t status;
+
+ if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
+ IRQTable[irqn] = handler;
+ status = 0;
+ } else {
+ status = -1;
+ }
+
+ return (status);
+}
+
+
+/// Get the registered interrupt handler.
+__WEAK IRQHandler_t IRQ_GetHandler (IRQn_ID_t irqn) {
+ IRQHandler_t h;
+
+ // Ignore CPUID field (software generated interrupts)
+ irqn &= 0x3FFU;
+
+ if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
+ h = IRQTable[irqn];
+ } else {
+ h = (IRQHandler_t)0;
+ }
+
+ return (h);
+}
+
+
+/// Enable interrupt.
+__WEAK int32_t IRQ_Enable (IRQn_ID_t irqn) {
+ int32_t status;
+
+ if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
+ GIC_EnableIRQ ((IRQn_Type)irqn);
+ status = 0;
+ } else {
+ status = -1;
+ }
+
+ return (status);
+}
+
+
+/// Disable interrupt.
+__WEAK int32_t IRQ_Disable (IRQn_ID_t irqn) {
+ int32_t status;
+
+ if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
+ GIC_DisableIRQ ((IRQn_Type)irqn);
+ status = 0;
+ } else {
+ status = -1;
+ }
+
+ return (status);
+}
+
+
+/// Get interrupt enable state.
+__WEAK uint32_t IRQ_GetEnableState (IRQn_ID_t irqn) {
+ uint32_t enable;
+
+ if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
+ enable = GIC_GetEnableIRQ((IRQn_Type)irqn);
+ } else {
+ enable = 0U;
+ }
+
+ return (enable);
+}
+
+
+/// Configure interrupt request mode.
+__WEAK int32_t IRQ_SetMode (IRQn_ID_t irqn, uint32_t mode) {
+ uint32_t val;
+ uint8_t cfg;
+ uint8_t secure;
+ uint8_t cpu;
+ int32_t status = 0;
+
+ if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
+ // Check triggering mode
+ val = (mode & IRQ_MODE_TRIG_Msk);
+
+ if (val == IRQ_MODE_TRIG_LEVEL) {
+ cfg = 0x00U;
+ } else if (val == IRQ_MODE_TRIG_EDGE) {
+ cfg = 0x02U;
+ } else {
+ cfg = 0x00U;
+ status = -1;
+ }
+
+ // Check interrupt type
+ val = mode & IRQ_MODE_TYPE_Msk;
+
+ if (val != IRQ_MODE_TYPE_IRQ) {
+ status = -1;
+ }
+
+ // Check interrupt domain
+ val = mode & IRQ_MODE_DOMAIN_Msk;
+
+ if (val == IRQ_MODE_DOMAIN_NONSECURE) {
+ secure = 0U;
+ } else {
+ // Check security extensions support
+ val = GIC_DistributorInfo() & (1UL << 10U);
+
+ if (val != 0U) {
+ // Security extensions are supported
+ secure = 1U;
+ } else {
+ secure = 0U;
+ status = -1;
+ }
+ }
+
+ // Check interrupt CPU targets
+ val = mode & IRQ_MODE_CPU_Msk;
+
+ if (val == IRQ_MODE_CPU_ALL) {
+ cpu = 0xFFU;
+ } else {
+ cpu = val >> IRQ_MODE_CPU_Pos;
+ }
+
+ // Apply configuration if no mode error
+ if (status == 0) {
+ GIC_SetConfiguration((IRQn_Type)irqn, cfg);
+ GIC_SetTarget ((IRQn_Type)irqn, cpu);
+
+ if (secure != 0U) {
+ GIC_SetGroup ((IRQn_Type)irqn, secure);
+ }
+ }
+ }
+
+ return (status);
+}
+
+
+/// Get interrupt mode configuration.
+__WEAK uint32_t IRQ_GetMode (IRQn_ID_t irqn) {
+ uint32_t mode;
+ uint32_t val;
+
+ if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
+ mode = IRQ_MODE_TYPE_IRQ;
+
+ // Get trigger mode
+ val = GIC_GetConfiguration((IRQn_Type)irqn);
+
+ if ((val & 2U) != 0U) {
+ // Corresponding interrupt is edge triggered
+ mode |= IRQ_MODE_TRIG_EDGE;
+ } else {
+ // Corresponding interrupt is level triggered
+ mode |= IRQ_MODE_TRIG_LEVEL;
+ }
+
+ // Get interrupt CPU targets
+ mode |= GIC_GetTarget ((IRQn_Type)irqn) << IRQ_MODE_CPU_Pos;
+
+ } else {
+ mode = IRQ_MODE_ERROR;
+ }
+
+ return (mode);
+}
+
+
+/// Get ID number of current interrupt request (IRQ).
+__WEAK IRQn_ID_t IRQ_GetActiveIRQ (void) {
+ IRQn_ID_t irqn;
+ uint32_t prio;
+
+ /* Dummy read to avoid GIC 390 errata 801120 */
+ GIC_GetHighPendingIRQ();
+
+ irqn = GIC_AcknowledgePending();
+
+ __DSB();
+
+ /* Workaround GIC 390 errata 733075 (GIC-390_Errata_Notice_v6.pdf, 09-Jul-2014) */
+ /* The following workaround code is for a single-core system. It would be */
+ /* different in a multi-core system. */
+ /* If the ID is 0 or 0x3FE or 0x3FF, then the GIC CPU interface may be locked-up */
+ /* so unlock it, otherwise service the interrupt as normal. */
+ /* Special IDs 1020=0x3FC and 1021=0x3FD are reserved values in GICv1 and GICv2 */
+ /* so will not occur here. */
+
+ if ((irqn == 0) || (irqn >= 0x3FE)) {
+ /* Unlock the CPU interface with a dummy write to Interrupt Priority Register */
+ prio = GIC_GetPriority((IRQn_Type)0);
+ GIC_SetPriority ((IRQn_Type)0, prio);
+
+ __DSB();
+
+ if ((irqn == 0U) && ((GIC_GetIRQStatus ((IRQn_Type)irqn) & 1U) != 0U) && (IRQ_ID0 == 0U)) {
+ /* If the ID is 0, is active and has not been seen before */
+ IRQ_ID0 = 1U;
+ }
+ /* End of Workaround GIC 390 errata 733075 */
+ }
+
+ return (irqn);
+}
+
+
+/// Get ID number of current fast interrupt request (FIQ).
+__WEAK IRQn_ID_t IRQ_GetActiveFIQ (void) {
+ return ((IRQn_ID_t)-1);
+}
+
+
+/// Signal end of interrupt processing.
+__WEAK int32_t IRQ_EndOfInterrupt (IRQn_ID_t irqn) {
+ int32_t status;
+ IRQn_Type irq = (IRQn_Type)irqn;
+
+ irqn &= 0x3FFU;
+
+ if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
+ GIC_EndInterrupt (irq);
+
+ if (irqn == 0) {
+ IRQ_ID0 = 0U;
+ }
+
+ status = 0;
+ } else {
+ status = -1;
+ }
+
+ return (status);
+}
+
+
+/// Set interrupt pending flag.
+__WEAK int32_t IRQ_SetPending (IRQn_ID_t irqn) {
+ int32_t status;
+
+ if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
+ GIC_SetPendingIRQ ((IRQn_Type)irqn);
+ status = 0;
+ } else {
+ status = -1;
+ }
+
+ return (status);
+}
+
+/// Get interrupt pending flag.
+__WEAK uint32_t IRQ_GetPending (IRQn_ID_t irqn) {
+ uint32_t pending;
+
+ if ((irqn >= 16) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
+ pending = GIC_GetPendingIRQ ((IRQn_Type)irqn);
+ } else {
+ pending = 0U;
+ }
+
+ return (pending & 1U);
+}
+
+
+/// Clear interrupt pending flag.
+__WEAK int32_t IRQ_ClearPending (IRQn_ID_t irqn) {
+ int32_t status;
+
+ if ((irqn >= 16) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
+ GIC_ClearPendingIRQ ((IRQn_Type)irqn);
+ status = 0;
+ } else {
+ status = -1;
+ }
+
+ return (status);
+}
+
+
+/// Set interrupt priority value.
+__WEAK int32_t IRQ_SetPriority (IRQn_ID_t irqn, uint32_t priority) {
+ int32_t status;
+
+ if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
+ GIC_SetPriority ((IRQn_Type)irqn, priority);
+ status = 0;
+ } else {
+ status = -1;
+ }
+
+ return (status);
+}
+
+
+/// Get interrupt priority.
+__WEAK uint32_t IRQ_GetPriority (IRQn_ID_t irqn) {
+ uint32_t priority;
+
+ if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) {
+ priority = GIC_GetPriority ((IRQn_Type)irqn);
+ } else {
+ priority = IRQ_PRIORITY_ERROR;
+ }
+
+ return (priority);
+}
+
+
+/// Set priority masking threshold.
+__WEAK int32_t IRQ_SetPriorityMask (uint32_t priority) {
+ GIC_SetInterfacePriorityMask (priority);
+ return (0);
+}
+
+
+/// Get priority masking threshold
+__WEAK uint32_t IRQ_GetPriorityMask (void) {
+ return GIC_GetInterfacePriorityMask();
+}
+
+
+/// Set priority grouping field split point
+__WEAK int32_t IRQ_SetPriorityGroupBits (uint32_t bits) {
+ int32_t status;
+
+ if (bits == IRQ_PRIORITY_Msk) {
+ bits = 7U;
+ }
+
+ if (bits < 8U) {
+ GIC_SetBinaryPoint (7U - bits);
+ status = 0;
+ } else {
+ status = -1;
+ }
+
+ return (status);
+}
+
+
+/// Get priority grouping field split point
+__WEAK uint32_t IRQ_GetPriorityGroupBits (void) {
+ uint32_t bp;
+
+ bp = GIC_GetBinaryPoint() & 0x07U;
+
+ return (7U - bp);
+}
+
+#endif
diff --git a/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/readme.txt b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/readme.txt
new file mode 100755
index 0000000..e9d6eb0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ARM/CMSIS/readme.txt
@@ -0,0 +1,6 @@
+CMSIS is Copyright (C) 2011-2013 ARM Limited. All rights reserved.
+
+This directory contains only part of the CMSIS package. If you need the whole
+package please download it from:
+
+http://www.arm.com
diff --git a/ChibiOS_20.3.2/os/common/ext/ST/STM32G4xx/stm32g474xx.h b/ChibiOS_20.3.2/os/common/ext/ST/STM32G4xx/stm32g474xx.h
new file mode 100644
index 0000000..0b725dc
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ST/STM32G4xx/stm32g474xx.h
@@ -0,0 +1,17914 @@
+/**
+ ******************************************************************************
+ * @file stm32g474xx.h
+ * @author MCD Application Team
+ * @brief CMSIS STM32G474xx Device Peripheral Access Layer Header File.
+ *
+ * This file contains:
+ * - Data structures and the address mapping for all peripherals
+ * - Peripheral's registers declarations and bits definition
+ * - Macros to access peripheral’s registers hardware
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/** @addtogroup CMSIS_Device
+ * @{
+ */
+
+/** @addtogroup stm32g474xx
+ * @{
+ */
+
+#ifndef __STM32G474xx_H
+#define __STM32G474xx_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif /* __cplusplus */
+
+/** @addtogroup Configuration_section_for_CMSIS
+ * @{
+ */
+
+/**
+ * @brief Configuration of the Cortex-M4 Processor and Core Peripherals
+ */
+#define __CM4_REV 0x0001 /*!< Cortex-M4 revision r0p1 */
+#define __MPU_PRESENT 1 /*!< STM32G4XX provides an MPU */
+#define __NVIC_PRIO_BITS 4 /*!< STM32G4XX uses 4 Bits for the Priority Levels */
+#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */
+#define __FPU_PRESENT 1 /*!< FPU present */
+
+/**
+ * @}
+ */
+
+/** @addtogroup Peripheral_interrupt_number_definition
+ * @{
+ */
+
+/**
+ * @brief STM32G4XX Interrupt Number Definition, according to the selected device
+ * in @ref Library_configuration_section
+ */
+typedef enum
+{
+/****** Cortex-M4 Processor Exceptions Numbers *********************************************************************************/
+ NonMaskableInt_IRQn = -14, /*!< 2 Cortex-M4 Non Maskable Interrupt */
+ HardFault_IRQn = -13, /*!< 3 Cortex-M4 Hard Fault Interrupt */
+ MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 Memory Management Interrupt */
+ BusFault_IRQn = -11, /*!< 5 Cortex-M4 Bus Fault Interrupt */
+ UsageFault_IRQn = -10, /*!< 6 Cortex-M4 Usage Fault Interrupt */
+ SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV Call Interrupt */
+ DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 Debug Monitor Interrupt */
+ PendSV_IRQn = -2, /*!< 14 Cortex-M4 Pend SV Interrupt */
+ SysTick_IRQn = -1, /*!< 15 Cortex-M4 System Tick Interrupt */
+/****** STM32 specific Interrupt Numbers ***************************************************************************************/
+ WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */
+ PVD_PVM_IRQn = 1, /*!< PVD/PVM1/PVM2/PVM3/PVM4 through EXTI Line detection Interrupts */
+ RTC_TAMP_LSECSS_IRQn = 2, /*!< RTC Tamper and TimeStamp and RCC LSE CSS interrupts through the EXTI */
+ RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI line */
+ FLASH_IRQn = 4, /*!< FLASH global Interrupt */
+ RCC_IRQn = 5, /*!< RCC global Interrupt */
+ EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */
+ EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */
+ EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */
+ EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */
+ EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */
+ DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */
+ DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */
+ DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */
+ DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */
+ DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */
+ DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */
+ DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */
+ ADC1_2_IRQn = 18, /*!< ADC1 and ADC2 global Interrupt */
+ USB_HP_IRQn = 19, /*!< USB HP Interrupt */
+ USB_LP_IRQn = 20, /*!< USB LP Interrupt */
+ FDCAN1_IT0_IRQn = 21, /*!< FDCAN1 IT0 Interrupt */
+ FDCAN1_IT1_IRQn = 22, /*!< FDCAN1 IT1 Interrupt */
+ EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */
+ TIM1_BRK_TIM15_IRQn = 24, /*!< TIM1 Break, Transition error, Index error and TIM15 global interrupt */
+ TIM1_UP_TIM16_IRQn = 25, /*!< TIM1 Update Interrupt and TIM16 global interrupt */
+ TIM1_TRG_COM_TIM17_IRQn = 26, /*!< TIM1 TIM1 Trigger, Commutation, Direction change, Index and TIM17 global interrupt */
+ TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */
+ TIM2_IRQn = 28, /*!< TIM2 global Interrupt */
+ TIM3_IRQn = 29, /*!< TIM3 global Interrupt */
+ TIM4_IRQn = 30, /*!< TIM4 global Interrupt */
+ I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */
+ I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */
+ I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */
+ I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */
+ SPI1_IRQn = 35, /*!< SPI1 global Interrupt */
+ SPI2_IRQn = 36, /*!< SPI2 global Interrupt */
+ USART1_IRQn = 37, /*!< USART1 global Interrupt */
+ USART2_IRQn = 38, /*!< USART2 global Interrupt */
+ USART3_IRQn = 39, /*!< USART3 global Interrupt */
+ EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */
+ RTC_Alarm_IRQn = 41, /*!< RTC Alarm (A and B) through EXTI Line Interrupt */
+ USBWakeUp_IRQn = 42, /*!< USB Wakeup through EXTI line Interrupt */
+ TIM8_BRK_IRQn = 43, /*!< TIM8 Break, Transition error and Index error Interrupt */
+ TIM8_UP_IRQn = 44, /*!< TIM8 Update Interrupt */
+ TIM8_TRG_COM_IRQn = 45, /*!< TIM8 Trigger, Commutation, Direction change and Index Interrupt */
+ TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */
+ ADC3_IRQn = 47, /*!< ADC3 global Interrupt */
+ FMC_IRQn = 48, /*!< FMC global Interrupt */
+ LPTIM1_IRQn = 49, /*!< LP TIM1 Interrupt */
+ TIM5_IRQn = 50, /*!< TIM5 global Interrupt */
+ SPI3_IRQn = 51, /*!< SPI3 global Interrupt */
+ UART4_IRQn = 52, /*!< UART4 global Interrupt */
+ UART5_IRQn = 53, /*!< UART5 global Interrupt */
+ TIM6_DAC_IRQn = 54, /*!< TIM6 global and DAC1&3 underrun error interrupts */
+ TIM7_DAC_IRQn = 55, /*!< TIM7 global and DAC2&4 underrun error interrupts */
+ DMA2_Channel1_IRQn = 56, /*!< DMA2 Channel 1 global Interrupt */
+ DMA2_Channel2_IRQn = 57, /*!< DMA2 Channel 2 global Interrupt */
+ DMA2_Channel3_IRQn = 58, /*!< DMA2 Channel 3 global Interrupt */
+ DMA2_Channel4_IRQn = 59, /*!< DMA2 Channel 4 global Interrupt */
+ DMA2_Channel5_IRQn = 60, /*!< DMA2 Channel 5 global Interrupt */
+ ADC4_IRQn = 61, /*!< ADC4 global Interrupt */
+ ADC5_IRQn = 62, /*!< ADC5 global Interrupt */
+ UCPD1_IRQn = 63, /*!< UCPD global Interrupt */
+ COMP1_2_3_IRQn = 64, /*!< COMP1, COMP2 and COMP3 Interrupts */
+ COMP4_5_6_IRQn = 65, /*!< COMP4, COMP5 and COMP6 */
+ COMP7_IRQn = 66, /*!< COMP7 Interrupt */
+ HRTIM1_Master_IRQn = 67, /*!< HRTIM Master Timer global Interrupt */
+ HRTIM1_TIMA_IRQn = 68, /*!< HRTIM Timer A global Interrupt */
+ HRTIM1_TIMB_IRQn = 69, /*!< HRTIM Timer B global Interrupt */
+ HRTIM1_TIMC_IRQn = 70, /*!< HRTIM Timer C global Interrupt */
+ HRTIM1_TIMD_IRQn = 71, /*!< HRTIM Timer D global Interrupt */
+ HRTIM1_TIME_IRQn = 72, /*!< HRTIM Timer E global Interrupt */
+ HRTIM1_FLT_IRQn = 73, /*!< HRTIM Fault global Interrupt */
+ HRTIM1_TIMF_IRQn = 74, /*!< HRTIM Timer F global Interrupt */
+ CRS_IRQn = 75, /*!< CRS global interrupt */
+ SAI1_IRQn = 76, /*!< Serial Audio Interface global interrupt */
+ TIM20_BRK_IRQn = 77, /*!< TIM20 Break, Transition error and Index error Interrupt */
+ TIM20_UP_IRQn = 78, /*!< TIM20 Update interrupt */
+ TIM20_TRG_COM_IRQn = 79, /*!< TIM20 Trigger, Commutation, Direction change and Index Interrupt */
+ TIM20_CC_IRQn = 80, /*!< TIM20 Capture Compare interrupt */
+ FPU_IRQn = 81, /*!< FPU global interrupt */
+ I2C4_EV_IRQn = 82, /*!< I2C4 Event interrupt */
+ I2C4_ER_IRQn = 83, /*!< I2C4 Error interrupt */
+ SPI4_IRQn = 84, /*!< SPI4 Event interrupt */
+ FDCAN2_IT0_IRQn = 86, /*!< FDCAN2 interrupt line 0 interrupt */
+ FDCAN2_IT1_IRQn = 87, /*!< FDCAN2 interrupt line 1 interrupt */
+ FDCAN3_IT0_IRQn = 88, /*!< FDCAN3 interrupt line 0 interrupt */
+ FDCAN3_IT1_IRQn = 89, /*!< FDCAN3 interrupt line 1 interrupt */
+ RNG_IRQn = 90, /*!< RNG global interrupt */
+ LPUART1_IRQn = 91, /*!< LP UART 1 Interrupt */
+ I2C3_EV_IRQn = 92, /*!< I2C3 Event Interrupt */
+ I2C3_ER_IRQn = 93, /*!< I2C3 Error interrupt */
+ DMAMUX_OVR_IRQn = 94, /*!< DMAMUX overrun global interrupt */
+ QUADSPI_IRQn = 95, /*!< QUADSPI interrupt */
+ DMA1_Channel8_IRQn = 96, /*!< DMA1 Channel 8 interrupt */
+ DMA2_Channel6_IRQn = 97, /*!< DMA2 Channel 6 interrupt */
+ DMA2_Channel7_IRQn = 98, /*!< DMA2 Channel 7 interrupt */
+ DMA2_Channel8_IRQn = 99, /*!< DMA2 Channel 8 interrupt */
+ CORDIC_IRQn = 100, /*!< CORDIC global Interrupt */
+ FMAC_IRQn = 101 /*!< FMAC global Interrupt */
+} IRQn_Type;
+
+/**
+ * @}
+ */
+
+#include "core_cm4.h" /* Cortex-M4 processor and core peripherals */
+#include "system_stm32g4xx.h"
+#include
+
+/** @addtogroup Peripheral_registers_structures
+ * @{
+ */
+
+/**
+ * @brief Analog to Digital Converter
+ */
+
+typedef struct
+{
+ __IO uint32_t ISR; /*!< ADC interrupt and status register, Address offset: 0x00 */
+ __IO uint32_t IER; /*!< ADC interrupt enable register, Address offset: 0x04 */
+ __IO uint32_t CR; /*!< ADC control register, Address offset: 0x08 */
+ __IO uint32_t CFGR; /*!< ADC configuration register 1, Address offset: 0x0C */
+ __IO uint32_t CFGR2; /*!< ADC configuration register 2, Address offset: 0x10 */
+ __IO uint32_t SMPR1; /*!< ADC sampling time register 1, Address offset: 0x14 */
+ __IO uint32_t SMPR2; /*!< ADC sampling time register 2, Address offset: 0x18 */
+ uint32_t RESERVED1; /*!< Reserved, 0x1C */
+ __IO uint32_t TR1; /*!< ADC analog watchdog 1 threshold register, Address offset: 0x20 */
+ __IO uint32_t TR2; /*!< ADC analog watchdog 2 threshold register, Address offset: 0x24 */
+ __IO uint32_t TR3; /*!< ADC analog watchdog 3 threshold register, Address offset: 0x28 */
+ uint32_t RESERVED2; /*!< Reserved, 0x2C */
+ __IO uint32_t SQR1; /*!< ADC group regular sequencer register 1, Address offset: 0x30 */
+ __IO uint32_t SQR2; /*!< ADC group regular sequencer register 2, Address offset: 0x34 */
+ __IO uint32_t SQR3; /*!< ADC group regular sequencer register 3, Address offset: 0x38 */
+ __IO uint32_t SQR4; /*!< ADC group regular sequencer register 4, Address offset: 0x3C */
+ __IO uint32_t DR; /*!< ADC group regular data register, Address offset: 0x40 */
+ uint32_t RESERVED3; /*!< Reserved, 0x44 */
+ uint32_t RESERVED4; /*!< Reserved, 0x48 */
+ __IO uint32_t JSQR; /*!< ADC group injected sequencer register, Address offset: 0x4C */
+ uint32_t RESERVED5[4]; /*!< Reserved, 0x50 - 0x5C */
+ __IO uint32_t OFR1; /*!< ADC offset register 1, Address offset: 0x60 */
+ __IO uint32_t OFR2; /*!< ADC offset register 2, Address offset: 0x64 */
+ __IO uint32_t OFR3; /*!< ADC offset register 3, Address offset: 0x68 */
+ __IO uint32_t OFR4; /*!< ADC offset register 4, Address offset: 0x6C */
+ uint32_t RESERVED6[4]; /*!< Reserved, 0x70 - 0x7C */
+ __IO uint32_t JDR1; /*!< ADC group injected rank 1 data register, Address offset: 0x80 */
+ __IO uint32_t JDR2; /*!< ADC group injected rank 2 data register, Address offset: 0x84 */
+ __IO uint32_t JDR3; /*!< ADC group injected rank 3 data register, Address offset: 0x88 */
+ __IO uint32_t JDR4; /*!< ADC group injected rank 4 data register, Address offset: 0x8C */
+ uint32_t RESERVED7[4]; /*!< Reserved, 0x090 - 0x09C */
+ __IO uint32_t AWD2CR; /*!< ADC analog watchdog 2 configuration register, Address offset: 0xA0 */
+ __IO uint32_t AWD3CR; /*!< ADC analog watchdog 3 Configuration Register, Address offset: 0xA4 */
+ uint32_t RESERVED8; /*!< Reserved, 0x0A8 */
+ uint32_t RESERVED9; /*!< Reserved, 0x0AC */
+ __IO uint32_t DIFSEL; /*!< ADC differential mode selection register, Address offset: 0xB0 */
+ __IO uint32_t CALFACT; /*!< ADC calibration factors, Address offset: 0xB4 */
+ uint32_t RESERVED10[2];/*!< Reserved, 0x0B8 - 0x0BC */
+ __IO uint32_t GCOMP; /*!< ADC calibration factors, Address offset: 0xC0 */
+} ADC_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t CSR; /*!< ADC common status register, Address offset: 0x300 + 0x00 */
+ uint32_t RESERVED1; /*!< Reserved, Address offset: 0x300 + 0x04 */
+ __IO uint32_t CCR; /*!< ADC common configuration register, Address offset: 0x300 + 0x08 */
+ __IO uint32_t CDR; /*!< ADC common group regular data register Address offset: 0x300 + 0x0C */
+} ADC_Common_TypeDef;
+
+/**
+ * @brief FD Controller Area Network
+ */
+
+typedef struct
+{
+ __IO uint32_t CREL; /*!< FDCAN Core Release register, Address offset: 0x000 */
+ __IO uint32_t ENDN; /*!< FDCAN Endian register, Address offset: 0x004 */
+ uint32_t RESERVED1; /*!< Reserved, 0x008 */
+ __IO uint32_t DBTP; /*!< FDCAN Data Bit Timing & Prescaler register, Address offset: 0x00C */
+ __IO uint32_t TEST; /*!< FDCAN Test register, Address offset: 0x010 */
+ __IO uint32_t RWD; /*!< FDCAN RAM Watchdog register, Address offset: 0x014 */
+ __IO uint32_t CCCR; /*!< FDCAN CC Control register, Address offset: 0x018 */
+ __IO uint32_t NBTP; /*!< FDCAN Nominal Bit Timing & Prescaler register, Address offset: 0x01C */
+ __IO uint32_t TSCC; /*!< FDCAN Timestamp Counter Configuration register, Address offset: 0x020 */
+ __IO uint32_t TSCV; /*!< FDCAN Timestamp Counter Value register, Address offset: 0x024 */
+ __IO uint32_t TOCC; /*!< FDCAN Timeout Counter Configuration register, Address offset: 0x028 */
+ __IO uint32_t TOCV; /*!< FDCAN Timeout Counter Value register, Address offset: 0x02C */
+ uint32_t RESERVED2[4]; /*!< Reserved, 0x030 - 0x03C */
+ __IO uint32_t ECR; /*!< FDCAN Error Counter register, Address offset: 0x040 */
+ __IO uint32_t PSR; /*!< FDCAN Protocol Status register, Address offset: 0x044 */
+ __IO uint32_t TDCR; /*!< FDCAN Transmitter Delay Compensation register, Address offset: 0x048 */
+ uint32_t RESERVED3; /*!< Reserved, 0x04C */
+ __IO uint32_t IR; /*!< FDCAN Interrupt register, Address offset: 0x050 */
+ __IO uint32_t IE; /*!< FDCAN Interrupt Enable register, Address offset: 0x054 */
+ __IO uint32_t ILS; /*!< FDCAN Interrupt Line Select register, Address offset: 0x058 */
+ __IO uint32_t ILE; /*!< FDCAN Interrupt Line Enable register, Address offset: 0x05C */
+ uint32_t RESERVED4[8]; /*!< Reserved, 0x060 - 0x07C */
+ __IO uint32_t RXGFC; /*!< FDCAN Global Filter Configuration register, Address offset: 0x080 */
+ __IO uint32_t XIDAM; /*!< FDCAN Extended ID AND Mask register, Address offset: 0x084 */
+ __IO uint32_t HPMS; /*!< FDCAN High Priority Message Status register, Address offset: 0x088 */
+ uint32_t RESERVED5; /*!< Reserved, 0x08C */
+ __IO uint32_t RXF0S; /*!< FDCAN Rx FIFO 0 Status register, Address offset: 0x090 */
+ __IO uint32_t RXF0A; /*!< FDCAN Rx FIFO 0 Acknowledge register, Address offset: 0x094 */
+ __IO uint32_t RXF1S; /*!< FDCAN Rx FIFO 1 Status register, Address offset: 0x098 */
+ __IO uint32_t RXF1A; /*!< FDCAN Rx FIFO 1 Acknowledge register, Address offset: 0x09C */
+ uint32_t RESERVED6[8]; /*!< Reserved, 0x0A0 - 0x0BC */
+ __IO uint32_t TXBC; /*!< FDCAN Tx Buffer Configuration register, Address offset: 0x0C0 */
+ __IO uint32_t TXFQS; /*!< FDCAN Tx FIFO/Queue Status register, Address offset: 0x0C4 */
+ __IO uint32_t TXBRP; /*!< FDCAN Tx Buffer Request Pending register, Address offset: 0x0C8 */
+ __IO uint32_t TXBAR; /*!< FDCAN Tx Buffer Add Request register, Address offset: 0x0CC */
+ __IO uint32_t TXBCR; /*!< FDCAN Tx Buffer Cancellation Request register, Address offset: 0x0D0 */
+ __IO uint32_t TXBTO; /*!< FDCAN Tx Buffer Transmission Occurred register, Address offset: 0x0D4 */
+ __IO uint32_t TXBCF; /*!< FDCAN Tx Buffer Cancellation Finished register, Address offset: 0x0D8 */
+ __IO uint32_t TXBTIE; /*!< FDCAN Tx Buffer Transmission Interrupt Enable register, Address offset: 0x0DC */
+ __IO uint32_t TXBCIE; /*!< FDCAN Tx Buffer Cancellation Finished Interrupt Enable register, Address offset: 0x0E0 */
+ __IO uint32_t TXEFS; /*!< FDCAN Tx Event FIFO Status register, Address offset: 0x0E4 */
+ __IO uint32_t TXEFA; /*!< FDCAN Tx Event FIFO Acknowledge register, Address offset: 0x0E8 */
+} FDCAN_GlobalTypeDef;
+
+/**
+ * @brief FD Controller Area Network Configuration
+ */
+
+typedef struct
+{
+ __IO uint32_t CKDIV; /*!< FDCAN clock divider register, Address offset: 0x100 + 0x000 */
+} FDCAN_Config_TypeDef;
+
+/**
+ * @brief Comparator
+ */
+
+typedef struct
+{
+ __IO uint32_t CSR; /*!< COMP control and status register, Address offset: 0x00 */
+} COMP_TypeDef;
+
+/**
+ * @brief CRC calculation unit
+ */
+
+typedef struct
+{
+ __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */
+ __IO uint32_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */
+ __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */
+ uint32_t RESERVED0; /*!< Reserved, 0x0C */
+ __IO uint32_t INIT; /*!< Initial CRC value register, Address offset: 0x10 */
+ __IO uint32_t POL; /*!< CRC polynomial register, Address offset: 0x14 */
+} CRC_TypeDef;
+
+/**
+ * @brief Clock Recovery System
+ */
+typedef struct
+{
+ __IO uint32_t CR; /*!< CRS ccontrol register, Address offset: 0x00 */
+ __IO uint32_t CFGR; /*!< CRS configuration register, Address offset: 0x04 */
+ __IO uint32_t ISR; /*!< CRS interrupt and status register, Address offset: 0x08 */
+ __IO uint32_t ICR; /*!< CRS interrupt flag clear register, Address offset: 0x0C */
+} CRS_TypeDef;
+
+/**
+ * @brief Digital to Analog Converter
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< DAC control register, Address offset: 0x00 */
+ __IO uint32_t SWTRIGR; /*!< DAC software trigger register, Address offset: 0x04 */
+ __IO uint32_t DHR12R1; /*!< DAC channel1 12-bit right-aligned data holding register, Address offset: 0x08 */
+ __IO uint32_t DHR12L1; /*!< DAC channel1 12-bit left aligned data holding register, Address offset: 0x0C */
+ __IO uint32_t DHR8R1; /*!< DAC channel1 8-bit right aligned data holding register, Address offset: 0x10 */
+ __IO uint32_t DHR12R2; /*!< DAC channel2 12-bit right aligned data holding register, Address offset: 0x14 */
+ __IO uint32_t DHR12L2; /*!< DAC channel2 12-bit left aligned data holding register, Address offset: 0x18 */
+ __IO uint32_t DHR8R2; /*!< DAC channel2 8-bit right-aligned data holding register, Address offset: 0x1C */
+ __IO uint32_t DHR12RD; /*!< Dual DAC 12-bit right-aligned data holding register, Address offset: 0x20 */
+ __IO uint32_t DHR12LD; /*!< DUAL DAC 12-bit left aligned data holding register, Address offset: 0x24 */
+ __IO uint32_t DHR8RD; /*!< DUAL DAC 8-bit right aligned data holding register, Address offset: 0x28 */
+ __IO uint32_t DOR1; /*!< DAC channel1 data output register, Address offset: 0x2C */
+ __IO uint32_t DOR2; /*!< DAC channel2 data output register, Address offset: 0x30 */
+ __IO uint32_t SR; /*!< DAC status register, Address offset: 0x34 */
+ __IO uint32_t CCR; /*!< DAC calibration control register, Address offset: 0x38 */
+ __IO uint32_t MCR; /*!< DAC mode control register, Address offset: 0x3C */
+ __IO uint32_t SHSR1; /*!< DAC Sample and Hold sample time register 1, Address offset: 0x40 */
+ __IO uint32_t SHSR2; /*!< DAC Sample and Hold sample time register 2, Address offset: 0x44 */
+ __IO uint32_t SHHR; /*!< DAC Sample and Hold hold time register, Address offset: 0x48 */
+ __IO uint32_t SHRR; /*!< DAC Sample and Hold refresh time register, Address offset: 0x4C */
+ __IO uint32_t RESERVED[2];
+ __IO uint32_t STR1; /*!< DAC Sawtooth register, Address offset: 0x58 */
+ __IO uint32_t STR2; /*!< DAC Sawtooth register, Address offset: 0x5C */
+ __IO uint32_t STMODR; /*!< DAC Sawtooth Mode register, Address offset: 0x60 */
+} DAC_TypeDef;
+
+/**
+ * @brief Debug MCU
+ */
+
+typedef struct
+{
+ __IO uint32_t IDCODE; /*!< MCU device ID code, Address offset: 0x00 */
+ __IO uint32_t CR; /*!< Debug MCU configuration register, Address offset: 0x04 */
+ __IO uint32_t APB1FZR1; /*!< Debug MCU APB1 freeze register 1, Address offset: 0x08 */
+ __IO uint32_t APB1FZR2; /*!< Debug MCU APB1 freeze register 2, Address offset: 0x0C */
+ __IO uint32_t APB2FZ; /*!< Debug MCU APB2 freeze register, Address offset: 0x10 */
+} DBGMCU_TypeDef;
+
+/**
+ * @brief DMA Controller
+ */
+
+typedef struct
+{
+ __IO uint32_t CCR; /*!< DMA channel x configuration register */
+ __IO uint32_t CNDTR; /*!< DMA channel x number of data register */
+ __IO uint32_t CPAR; /*!< DMA channel x peripheral address register */
+ __IO uint32_t CMAR; /*!< DMA channel x memory address register */
+} DMA_Channel_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t ISR; /*!< DMA interrupt status register, Address offset: 0x00 */
+ __IO uint32_t IFCR; /*!< DMA interrupt flag clear register, Address offset: 0x04 */
+} DMA_TypeDef;
+
+/**
+ * @brief DMA Multiplexer
+ */
+
+typedef struct
+{
+ __IO uint32_t CCR; /*!< DMA Multiplexer Channel x Control Register Address offset: 0x0004 * (channel x) */
+}DMAMUX_Channel_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t CSR; /*!< DMA Channel Status Register Address offset: 0x0080 */
+ __IO uint32_t CFR; /*!< DMA Channel Clear Flag Register Address offset: 0x0084 */
+}DMAMUX_ChannelStatus_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t RGCR; /*!< DMA Request Generator x Control Register Address offset: 0x0100 + 0x0004 * (Req Gen x) */
+}DMAMUX_RequestGen_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t RGSR; /*!< DMA Request Generator Status Register Address offset: 0x0140 */
+ __IO uint32_t RGCFR; /*!< DMA Request Generator Clear Flag Register Address offset: 0x0144 */
+}DMAMUX_RequestGenStatus_TypeDef;
+
+/**
+ * @brief External Interrupt/Event Controller
+ */
+
+typedef struct
+{
+ __IO uint32_t IMR1; /*!< EXTI Interrupt mask register 1, Address offset: 0x00 */
+ __IO uint32_t EMR1; /*!< EXTI Event mask register 1, Address offset: 0x04 */
+ __IO uint32_t RTSR1; /*!< EXTI Rising trigger selection register 1, Address offset: 0x08 */
+ __IO uint32_t FTSR1; /*!< EXTI Falling trigger selection register 1, Address offset: 0x0C */
+ __IO uint32_t SWIER1; /*!< EXTI Software interrupt event register 1, Address offset: 0x10 */
+ __IO uint32_t PR1; /*!< EXTI Pending register 1, Address offset: 0x14 */
+ uint32_t RESERVED1; /*!< Reserved, 0x18 */
+ uint32_t RESERVED2; /*!< Reserved, 0x1C */
+ __IO uint32_t IMR2; /*!< EXTI Interrupt mask register 2, Address offset: 0x20 */
+ __IO uint32_t EMR2; /*!< EXTI Event mask register 2, Address offset: 0x24 */
+ __IO uint32_t RTSR2; /*!< EXTI Rising trigger selection register 2, Address offset: 0x28 */
+ __IO uint32_t FTSR2; /*!< EXTI Falling trigger selection register 2, Address offset: 0x2C */
+ __IO uint32_t SWIER2; /*!< EXTI Software interrupt event register 2, Address offset: 0x30 */
+ __IO uint32_t PR2; /*!< EXTI Pending register 2, Address offset: 0x34 */
+} EXTI_TypeDef;
+
+/**
+ * @brief FLASH Registers
+ */
+
+typedef struct
+{
+ __IO uint32_t ACR; /*!< FLASH access control register, Address offset: 0x00 */
+ __IO uint32_t PDKEYR; /*!< FLASH power down key register, Address offset: 0x04 */
+ __IO uint32_t KEYR; /*!< FLASH key register, Address offset: 0x08 */
+ __IO uint32_t OPTKEYR; /*!< FLASH option key register, Address offset: 0x0C */
+ __IO uint32_t SR; /*!< FLASH status register, Address offset: 0x10 */
+ __IO uint32_t CR; /*!< FLASH control register, Address offset: 0x14 */
+ __IO uint32_t ECCR; /*!< FLASH ECC register, Address offset: 0x18 */
+ uint32_t RESERVED1; /*!< Reserved1, Address offset: 0x1C */
+ __IO uint32_t OPTR; /*!< FLASH option register, Address offset: 0x20 */
+ __IO uint32_t PCROP1SR; /*!< FLASH bank1 PCROP start address register, Address offset: 0x24 */
+ __IO uint32_t PCROP1ER; /*!< FLASH bank1 PCROP end address register, Address offset: 0x28 */
+ __IO uint32_t WRP1AR; /*!< FLASH bank1 WRP area A address register, Address offset: 0x2C */
+ __IO uint32_t WRP1BR; /*!< FLASH bank1 WRP area B address register, Address offset: 0x30 */
+ uint32_t RESERVED2[4]; /*!< Reserved2, Address offset: 0x34 */
+ __IO uint32_t PCROP2SR; /*!< FLASH bank2 PCROP start address register, Address offset: 0x44 */
+ __IO uint32_t PCROP2ER; /*!< FLASH bank2 PCROP end address register, Address offset: 0x48 */
+ __IO uint32_t WRP2AR; /*!< FLASH bank2 WRP area A address register, Address offset: 0x4C */
+ __IO uint32_t WRP2BR; /*!< FLASH bank2 WRP area B address register, Address offset: 0x50 */
+ uint32_t RESERVED3[7]; /*!< Reserved3, Address offset: 0x54 */
+ __IO uint32_t SEC1R; /*!< FLASH Securable memory register bank1, Address offset: 0x70 */
+ __IO uint32_t SEC2R; /*!< FLASH Securable memory register bank2, Address offset: 0x74 */
+} FLASH_TypeDef;
+
+/**
+ * @brief FMAC
+ */
+typedef struct
+{
+ __IO uint32_t X1BUFCFG; /*!< FMAC X1 Buffer Configuration register, Address offset: 0x00 */
+ __IO uint32_t X2BUFCFG; /*!< FMAC X2 Buffer Configuration register, Address offset: 0x04 */
+ __IO uint32_t YBUFCFG; /*!< FMAC Y Buffer Configuration register, Address offset: 0x08 */
+ __IO uint32_t PARAM; /*!< FMAC Parameter register, Address offset: 0x0C */
+ __IO uint32_t CR; /*!< FMAC Control register, Address offset: 0x10 */
+ __IO uint32_t SR; /*!< FMAC Status register, Address offset: 0x14 */
+ __IO uint32_t WDATA; /*!< FMAC Write Data register, Address offset: 0x18 */
+ __IO uint32_t RDATA; /*!< FMAC Read Data register, Address offset: 0x1C */
+} FMAC_TypeDef;
+
+/**
+ * @brief Flexible Memory Controller
+ */
+
+typedef struct
+{
+ __IO uint32_t BTCR[8]; /*!< NOR/PSRAM chip-select control register(BCR) and chip-select timing register(BTR), Address offset: 0x00-1C */
+ __IO uint32_t PCSCNTR; /*!< PSRAM chip-select counter register, Address offset: 0x20 */
+} FMC_Bank1_TypeDef;
+
+/**
+ * @brief Flexible Memory Controller Bank1E
+ */
+
+typedef struct
+{
+ __IO uint32_t BWTR[7]; /*!< NOR/PSRAM write timing registers, Address offset: 0x104-0x11C */
+} FMC_Bank1E_TypeDef;
+
+/**
+ * @brief Flexible Memory Controller Bank3
+ */
+
+typedef struct
+{
+ __IO uint32_t PCR; /*!< NAND Flash control register, Address offset: 0x80 */
+ __IO uint32_t SR; /*!< NAND Flash FIFO status and interrupt register, Address offset: 0x84 */
+ __IO uint32_t PMEM; /*!< NAND Flash Common memory space timing register, Address offset: 0x88 */
+ __IO uint32_t PATT; /*!< NAND Flash Attribute memory space timing register, Address offset: 0x8C */
+ uint32_t RESERVED0; /*!< Reserved, 0x90 */
+ __IO uint32_t ECCR; /*!< NAND Flash ECC result registers, Address offset: 0x94 */
+} FMC_Bank3_TypeDef;
+
+/**
+ * @brief General Purpose I/O
+ */
+
+typedef struct
+{
+ __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */
+ __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */
+ __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */
+ __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */
+ __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */
+ __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */
+ __IO uint32_t BSRR; /*!< GPIO port bit set/reset register, Address offset: 0x18 */
+ __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */
+ __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */
+ __IO uint32_t BRR; /*!< GPIO Bit Reset register, Address offset: 0x28 */
+} GPIO_TypeDef;
+
+/**
+ * @brief Inter-integrated Circuit Interface
+ */
+
+typedef struct
+{
+ __IO uint32_t CR1; /*!< I2C Control register 1, Address offset: 0x00 */
+ __IO uint32_t CR2; /*!< I2C Control register 2, Address offset: 0x04 */
+ __IO uint32_t OAR1; /*!< I2C Own address 1 register, Address offset: 0x08 */
+ __IO uint32_t OAR2; /*!< I2C Own address 2 register, Address offset: 0x0C */
+ __IO uint32_t TIMINGR; /*!< I2C Timing register, Address offset: 0x10 */
+ __IO uint32_t TIMEOUTR; /*!< I2C Timeout register, Address offset: 0x14 */
+ __IO uint32_t ISR; /*!< I2C Interrupt and status register, Address offset: 0x18 */
+ __IO uint32_t ICR; /*!< I2C Interrupt clear register, Address offset: 0x1C */
+ __IO uint32_t PECR; /*!< I2C PEC register, Address offset: 0x20 */
+ __IO uint32_t RXDR; /*!< I2C Receive data register, Address offset: 0x24 */
+ __IO uint32_t TXDR; /*!< I2C Transmit data register, Address offset: 0x28 */
+} I2C_TypeDef;
+
+/**
+ * @brief Independent WATCHDOG
+ */
+
+typedef struct
+{
+ __IO uint32_t KR; /*!< IWDG Key register, Address offset: 0x00 */
+ __IO uint32_t PR; /*!< IWDG Prescaler register, Address offset: 0x04 */
+ __IO uint32_t RLR; /*!< IWDG Reload register, Address offset: 0x08 */
+ __IO uint32_t SR; /*!< IWDG Status register, Address offset: 0x0C */
+ __IO uint32_t WINR; /*!< IWDG Window register, Address offset: 0x10 */
+} IWDG_TypeDef;
+
+/**
+ * @brief LPTIMER
+ */
+
+typedef struct
+{
+ __IO uint32_t ISR; /*!< LPTIM Interrupt and Status register, Address offset: 0x00 */
+ __IO uint32_t ICR; /*!< LPTIM Interrupt Clear register, Address offset: 0x04 */
+ __IO uint32_t IER; /*!< LPTIM Interrupt Enable register, Address offset: 0x08 */
+ __IO uint32_t CFGR; /*!< LPTIM Configuration register, Address offset: 0x0C */
+ __IO uint32_t CR; /*!< LPTIM Control register, Address offset: 0x10 */
+ __IO uint32_t CMP; /*!< LPTIM Compare register, Address offset: 0x14 */
+ __IO uint32_t ARR; /*!< LPTIM Autoreload register, Address offset: 0x18 */
+ __IO uint32_t CNT; /*!< LPTIM Counter register, Address offset: 0x1C */
+ __IO uint32_t OR; /*!< LPTIM Option register, Address offset: 0x20 */
+} LPTIM_TypeDef;
+
+/**
+ * @brief Operational Amplifier (OPAMP)
+ */
+
+typedef struct
+{
+ __IO uint32_t CSR; /*!< OPAMP control/status register, Address offset: 0x00 */
+ __IO uint32_t RESERVED[5]; /*!< OPAMP offset trimming register for normal mode, Address offset: 0x04 */
+ __IO uint32_t TCMR; /*!< OPAMP timer controlled mux mode register, Address offset: 0x18 */
+} OPAMP_TypeDef;
+
+/**
+ * @brief Power Control
+ */
+
+typedef struct
+{
+ __IO uint32_t CR1; /*!< PWR power control register 1, Address offset: 0x00 */
+ __IO uint32_t CR2; /*!< PWR power control register 2, Address offset: 0x04 */
+ __IO uint32_t CR3; /*!< PWR power control register 3, Address offset: 0x08 */
+ __IO uint32_t CR4; /*!< PWR power control register 4, Address offset: 0x0C */
+ __IO uint32_t SR1; /*!< PWR power status register 1, Address offset: 0x10 */
+ __IO uint32_t SR2; /*!< PWR power status register 2, Address offset: 0x14 */
+ __IO uint32_t SCR; /*!< PWR power status reset register, Address offset: 0x18 */
+ uint32_t RESERVED; /*!< Reserved, Address offset: 0x1C */
+ __IO uint32_t PUCRA; /*!< Pull_up control register of portA, Address offset: 0x20 */
+ __IO uint32_t PDCRA; /*!< Pull_Down control register of portA, Address offset: 0x24 */
+ __IO uint32_t PUCRB; /*!< Pull_up control register of portB, Address offset: 0x28 */
+ __IO uint32_t PDCRB; /*!< Pull_Down control register of portB, Address offset: 0x2C */
+ __IO uint32_t PUCRC; /*!< Pull_up control register of portC, Address offset: 0x30 */
+ __IO uint32_t PDCRC; /*!< Pull_Down control register of portC, Address offset: 0x34 */
+ __IO uint32_t PUCRD; /*!< Pull_up control register of portD, Address offset: 0x38 */
+ __IO uint32_t PDCRD; /*!< Pull_Down control register of portD, Address offset: 0x3C */
+ __IO uint32_t PUCRE; /*!< Pull_up control register of portE, Address offset: 0x40 */
+ __IO uint32_t PDCRE; /*!< Pull_Down control register of portE, Address offset: 0x44 */
+ __IO uint32_t PUCRF; /*!< Pull_up control register of portF, Address offset: 0x48 */
+ __IO uint32_t PDCRF; /*!< Pull_Down control register of portF, Address offset: 0x4C */
+ __IO uint32_t PUCRG; /*!< Pull_up control register of portG, Address offset: 0x50 */
+ __IO uint32_t PDCRG; /*!< Pull_Down control register of portG, Address offset: 0x54 */
+ uint32_t RESERVED1[10]; /*!< Reserved Address offset: 0x58 - 0x7C */
+ __IO uint32_t CR5; /*!< PWR power control register 5, Address offset: 0x80 */
+} PWR_TypeDef;
+
+/**
+ * @brief QUAD Serial Peripheral Interface
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< QUADSPI Control register, Address offset: 0x00 */
+ __IO uint32_t DCR; /*!< QUADSPI Device Configuration register, Address offset: 0x04 */
+ __IO uint32_t SR; /*!< QUADSPI Status register, Address offset: 0x08 */
+ __IO uint32_t FCR; /*!< QUADSPI Flag Clear register, Address offset: 0x0C */
+ __IO uint32_t DLR; /*!< QUADSPI Data Length register, Address offset: 0x10 */
+ __IO uint32_t CCR; /*!< QUADSPI Communication Configuration register, Address offset: 0x14 */
+ __IO uint32_t AR; /*!< QUADSPI Address register, Address offset: 0x18 */
+ __IO uint32_t ABR; /*!< QUADSPI Alternate Bytes register, Address offset: 0x1C */
+ __IO uint32_t DR; /*!< QUADSPI Data register, Address offset: 0x20 */
+ __IO uint32_t PSMKR; /*!< QUADSPI Polling Status Mask register, Address offset: 0x24 */
+ __IO uint32_t PSMAR; /*!< QUADSPI Polling Status Match register, Address offset: 0x28 */
+ __IO uint32_t PIR; /*!< QUADSPI Polling Interval register, Address offset: 0x2C */
+ __IO uint32_t LPTR; /*!< QUADSPI Low Power Timeout register, Address offset: 0x30 */
+} QUADSPI_TypeDef;
+
+/**
+ * @brief Reset and Clock Control
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< RCC clock control register, Address offset: 0x00 */
+ __IO uint32_t ICSCR; /*!< RCC internal clock sources calibration register, Address offset: 0x04 */
+ __IO uint32_t CFGR; /*!< RCC clock configuration register, Address offset: 0x08 */
+ __IO uint32_t PLLCFGR; /*!< RCC system PLL configuration register, Address offset: 0x0C */
+ uint32_t RESERVED0; /*!< Reserved, Address offset: 0x10 */
+ uint32_t RESERVED1; /*!< Reserved, Address offset: 0x14 */
+ __IO uint32_t CIER; /*!< RCC clock interrupt enable register, Address offset: 0x18 */
+ __IO uint32_t CIFR; /*!< RCC clock interrupt flag register, Address offset: 0x1C */
+ __IO uint32_t CICR; /*!< RCC clock interrupt clear register, Address offset: 0x20 */
+ uint32_t RESERVED2; /*!< Reserved, Address offset: 0x24 */
+ __IO uint32_t AHB1RSTR; /*!< RCC AHB1 peripheral reset register, Address offset: 0x28 */
+ __IO uint32_t AHB2RSTR; /*!< RCC AHB2 peripheral reset register, Address offset: 0x2C */
+ __IO uint32_t AHB3RSTR; /*!< RCC AHB3 peripheral reset register, Address offset: 0x30 */
+ uint32_t RESERVED3; /*!< Reserved, Address offset: 0x34 */
+ __IO uint32_t APB1RSTR1; /*!< RCC APB1 peripheral reset register 1, Address offset: 0x38 */
+ __IO uint32_t APB1RSTR2; /*!< RCC APB1 peripheral reset register 2, Address offset: 0x3C */
+ __IO uint32_t APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x40 */
+ uint32_t RESERVED4; /*!< Reserved, Address offset: 0x44 */
+ __IO uint32_t AHB1ENR; /*!< RCC AHB1 peripheral clocks enable register, Address offset: 0x48 */
+ __IO uint32_t AHB2ENR; /*!< RCC AHB2 peripheral clocks enable register, Address offset: 0x4C */
+ __IO uint32_t AHB3ENR; /*!< RCC AHB3 peripheral clocks enable register, Address offset: 0x50 */
+ uint32_t RESERVED5; /*!< Reserved, Address offset: 0x54 */
+ __IO uint32_t APB1ENR1; /*!< RCC APB1 peripheral clocks enable register 1, Address offset: 0x58 */
+ __IO uint32_t APB1ENR2; /*!< RCC APB1 peripheral clocks enable register 2, Address offset: 0x5C */
+ __IO uint32_t APB2ENR; /*!< RCC APB2 peripheral clocks enable register, Address offset: 0x60 */
+ uint32_t RESERVED6; /*!< Reserved, Address offset: 0x64 */
+ __IO uint32_t AHB1SMENR; /*!< RCC AHB1 peripheral clocks enable in sleep and stop modes register, Address offset: 0x68 */
+ __IO uint32_t AHB2SMENR; /*!< RCC AHB2 peripheral clocks enable in sleep and stop modes register, Address offset: 0x6C */
+ __IO uint32_t AHB3SMENR; /*!< RCC AHB3 peripheral clocks enable in sleep and stop modes register, Address offset: 0x70 */
+ uint32_t RESERVED7; /*!< Reserved, Address offset: 0x74 */
+ __IO uint32_t APB1SMENR1; /*!< RCC APB1 peripheral clocks enable in sleep mode and stop modes register 1, Address offset: 0x78 */
+ __IO uint32_t APB1SMENR2; /*!< RCC APB1 peripheral clocks enable in sleep mode and stop modes register 2, Address offset: 0x7C */
+ __IO uint32_t APB2SMENR; /*!< RCC APB2 peripheral clocks enable in sleep mode and stop modes register, Address offset: 0x80 */
+ uint32_t RESERVED8; /*!< Reserved, Address offset: 0x84 */
+ __IO uint32_t CCIPR; /*!< RCC peripherals independent clock configuration register, Address offset: 0x88 */
+ uint32_t RESERVED9; /*!< Reserved, Address offset: 0x8C */
+ __IO uint32_t BDCR; /*!< RCC backup domain control register, Address offset: 0x90 */
+ __IO uint32_t CSR; /*!< RCC clock control & status register, Address offset: 0x94 */
+ __IO uint32_t CRRCR; /*!< RCC clock recovery RC register, Address offset: 0x98 */
+ __IO uint32_t CCIPR2; /*!< RCC peripherals independent clock configuration register 2, Address offset: 0x9C */
+} RCC_TypeDef;
+
+/**
+ * @brief Real-Time Clock
+ */
+/*
+* @brief Specific device feature definitions
+*/
+#define RTC_TAMP_INT_6_SUPPORT
+#define RTC_TAMP_INT_NB 4u
+
+#define RTC_TAMP_NB 3u
+#define RTC_BACKUP_NB 32u
+
+
+typedef struct
+{
+ __IO uint32_t TR; /*!< RTC time register, Address offset: 0x00 */
+ __IO uint32_t DR; /*!< RTC date register, Address offset: 0x04 */
+ __IO uint32_t SSR; /*!< RTC sub second register, Address offset: 0x08 */
+ __IO uint32_t ICSR; /*!< RTC initialization control and status register, Address offset: 0x0C */
+ __IO uint32_t PRER; /*!< RTC prescaler register, Address offset: 0x10 */
+ __IO uint32_t WUTR; /*!< RTC wakeup timer register, Address offset: 0x14 */
+ __IO uint32_t CR; /*!< RTC control register, Address offset: 0x18 */
+ uint32_t RESERVED0; /*!< Reserved Address offset: 0x1C */
+ uint32_t RESERVED1; /*!< Reserved Address offset: 0x20 */
+ __IO uint32_t WPR; /*!< RTC write protection register, Address offset: 0x24 */
+ __IO uint32_t CALR; /*!< RTC calibration register, Address offset: 0x28 */
+ __IO uint32_t SHIFTR; /*!< RTC shift control register, Address offset: 0x2C */
+ __IO uint32_t TSTR; /*!< RTC time stamp time register, Address offset: 0x30 */
+ __IO uint32_t TSDR; /*!< RTC time stamp date register, Address offset: 0x34 */
+ __IO uint32_t TSSSR; /*!< RTC time-stamp sub second register, Address offset: 0x38 */
+ uint32_t RESERVED2; /*!< Reserved Address offset: 0x3C */
+ __IO uint32_t ALRMAR; /*!< RTC alarm A register, Address offset: 0x40 */
+ __IO uint32_t ALRMASSR; /*!< RTC alarm A sub second register, Address offset: 0x44 */
+ __IO uint32_t ALRMBR; /*!< RTC alarm B register, Address offset: 0x48 */
+ __IO uint32_t ALRMBSSR; /*!< RTC alarm B sub second register, Address offset: 0x4C */
+ __IO uint32_t SR; /*!< RTC Status register, Address offset: 0x50 */
+ __IO uint32_t MISR; /*!< RTC Masked Interrupt Status register, Address offset: 0x54 */
+ uint32_t RESERVED3; /*!< Reserved Address offset: 0x58 */
+ __IO uint32_t SCR; /*!< RTC Status Clear register, Address offset: 0x5C */
+} RTC_TypeDef;
+
+/**
+ * @brief Tamper and backup registers
+ */
+
+typedef struct
+{
+ __IO uint32_t CR1; /*!< TAMP configuration register 1, Address offset: 0x00 */
+ __IO uint32_t CR2; /*!< TAMP configuration register 2, Address offset: 0x04 */
+ uint32_t RESERVED0; /*!< no configuration register 3, Address offset: 0x08 */
+ __IO uint32_t FLTCR; /*!< TAMP filter control register, Address offset: 0x0C */
+ uint32_t RESERVED1[6]; /*!< Reserved Address offset: 0x10 - 0x24 */
+ uint32_t RESERVED2; /*!< Reserved Address offset: 0x28 */
+ __IO uint32_t IER; /*!< TAMP Interrupt enable register, Address offset: 0x2C */
+ __IO uint32_t SR; /*!< TAMP Status register, Address offset: 0x30 */
+ __IO uint32_t MISR; /*!< TAMP Masked Interrupt Status register Address offset: 0x34 */
+ uint32_t RESERVED3; /*!< Reserved Address offset: 0x38 */
+ __IO uint32_t SCR; /*!< TAMP Status clear register, Address offset: 0x3C */
+ uint32_t RESERVED4[48]; /*!< Reserved Address offset: 0x040 - 0xFC */
+ __IO uint32_t BKP0R; /*!< TAMP backup register 0, Address offset: 0x100 */
+ __IO uint32_t BKP1R; /*!< TAMP backup register 1, Address offset: 0x104 */
+ __IO uint32_t BKP2R; /*!< TAMP backup register 2, Address offset: 0x108 */
+ __IO uint32_t BKP3R; /*!< TAMP backup register 3, Address offset: 0x10C */
+ __IO uint32_t BKP4R; /*!< TAMP backup register 4, Address offset: 0x110 */
+ __IO uint32_t BKP5R; /*!< TAMP backup register 5, Address offset: 0x114 */
+ __IO uint32_t BKP6R; /*!< TAMP backup register 6, Address offset: 0x118 */
+ __IO uint32_t BKP7R; /*!< TAMP backup register 7, Address offset: 0x11C */
+ __IO uint32_t BKP8R; /*!< TAMP backup register 8, Address offset: 0x120 */
+ __IO uint32_t BKP9R; /*!< TAMP backup register 9, Address offset: 0x124 */
+ __IO uint32_t BKP10R; /*!< TAMP backup register 10, Address offset: 0x128 */
+ __IO uint32_t BKP11R; /*!< TAMP backup register 11, Address offset: 0x12C */
+ __IO uint32_t BKP12R; /*!< TAMP backup register 12, Address offset: 0x130 */
+ __IO uint32_t BKP13R; /*!< TAMP backup register 13, Address offset: 0x134 */
+ __IO uint32_t BKP14R; /*!< TAMP backup register 14, Address offset: 0x138 */
+ __IO uint32_t BKP15R; /*!< TAMP backup register 15, Address offset: 0x13C */
+ __IO uint32_t BKP16R; /*!< TAMP backup register 16, Address offset: 0x140 */
+ __IO uint32_t BKP17R; /*!< TAMP backup register 17, Address offset: 0x144 */
+ __IO uint32_t BKP18R; /*!< TAMP backup register 18, Address offset: 0x148 */
+ __IO uint32_t BKP19R; /*!< TAMP backup register 19, Address offset: 0x14C */
+ __IO uint32_t BKP20R; /*!< TAMP backup register 20, Address offset: 0x150 */
+ __IO uint32_t BKP21R; /*!< TAMP backup register 21, Address offset: 0x154 */
+ __IO uint32_t BKP22R; /*!< TAMP backup register 22, Address offset: 0x158 */
+ __IO uint32_t BKP23R; /*!< TAMP backup register 23, Address offset: 0x15C */
+ __IO uint32_t BKP24R; /*!< TAMP backup register 24, Address offset: 0x160 */
+ __IO uint32_t BKP25R; /*!< TAMP backup register 25, Address offset: 0x164 */
+ __IO uint32_t BKP26R; /*!< TAMP backup register 26, Address offset: 0x168 */
+ __IO uint32_t BKP27R; /*!< TAMP backup register 27, Address offset: 0x16C */
+ __IO uint32_t BKP28R; /*!< TAMP backup register 28, Address offset: 0x170 */
+ __IO uint32_t BKP29R; /*!< TAMP backup register 29, Address offset: 0x174 */
+ __IO uint32_t BKP30R; /*!< TAMP backup register 30, Address offset: 0x178 */
+ __IO uint32_t BKP31R; /*!< TAMP backup register 31, Address offset: 0x17C */
+} TAMP_TypeDef;
+
+/**
+ * @brief Serial Audio Interface
+ */
+
+typedef struct
+{
+ __IO uint32_t GCR; /*!< SAI global configuration register, Address offset: 0x00 */
+ uint32_t RESERVED[16]; /*!< Reserved, Address offset: 0x04 to 0x40 */
+ __IO uint32_t PDMCR; /*!< SAI PDM control register, Address offset: 0x44 */
+ __IO uint32_t PDMDLY; /*!< SAI PDM delay register, Address offset: 0x48 */
+} SAI_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t CR1; /*!< SAI block x configuration register 1, Address offset: 0x04 */
+ __IO uint32_t CR2; /*!< SAI block x configuration register 2, Address offset: 0x08 */
+ __IO uint32_t FRCR; /*!< SAI block x frame configuration register, Address offset: 0x0C */
+ __IO uint32_t SLOTR; /*!< SAI block x slot register, Address offset: 0x10 */
+ __IO uint32_t IMR; /*!< SAI block x interrupt mask register, Address offset: 0x14 */
+ __IO uint32_t SR; /*!< SAI block x status register, Address offset: 0x18 */
+ __IO uint32_t CLRFR; /*!< SAI block x clear flag register, Address offset: 0x1C */
+ __IO uint32_t DR; /*!< SAI block x data register, Address offset: 0x20 */
+} SAI_Block_TypeDef;
+
+/**
+ * @brief Serial Peripheral Interface
+ */
+
+typedef struct
+{
+ __IO uint32_t CR1; /*!< SPI Control register 1, Address offset: 0x00 */
+ __IO uint32_t CR2; /*!< SPI Control register 2, Address offset: 0x04 */
+ __IO uint32_t SR; /*!< SPI Status register, Address offset: 0x08 */
+ __IO uint32_t DR; /*!< SPI data register, Address offset: 0x0C */
+ __IO uint32_t CRCPR; /*!< SPI CRC polynomial register, Address offset: 0x10 */
+ __IO uint32_t RXCRCR; /*!< SPI Rx CRC register, Address offset: 0x14 */
+ __IO uint32_t TXCRCR; /*!< SPI Tx CRC register, Address offset: 0x18 */
+ __IO uint32_t I2SCFGR; /*!< SPI_I2S configuration register, Address offset: 0x1C */
+ __IO uint32_t I2SPR; /*!< SPI_I2S prescaler register, Address offset: 0x20 */
+} SPI_TypeDef;
+
+/**
+ * @brief System configuration controller
+ */
+
+typedef struct
+{
+ __IO uint32_t MEMRMP; /*!< SYSCFG memory remap register, Address offset: 0x00 */
+ __IO uint32_t CFGR1; /*!< SYSCFG configuration register 1, Address offset: 0x04 */
+ __IO uint32_t EXTICR[4]; /*!< SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14 */
+ __IO uint32_t SCSR; /*!< SYSCFG CCMSRAM control and status register, Address offset: 0x18 */
+ __IO uint32_t CFGR2; /*!< SYSCFG configuration register 2, Address offset: 0x1C */
+ __IO uint32_t SWPR; /*!< SYSCFG CCMSRAM write protection register, Address offset: 0x20 */
+ __IO uint32_t SKR; /*!< SYSCFG CCMSRAM Key Register, Address offset: 0x24 */
+} SYSCFG_TypeDef;
+
+/**
+ * @brief TIM
+ */
+
+typedef struct
+{
+ __IO uint32_t CR1; /*!< TIM control register 1, Address offset: 0x00 */
+ __IO uint32_t CR2; /*!< TIM control register 2, Address offset: 0x04 */
+ __IO uint32_t SMCR; /*!< TIM slave mode control register, Address offset: 0x08 */
+ __IO uint32_t DIER; /*!< TIM DMA/interrupt enable register, Address offset: 0x0C */
+ __IO uint32_t SR; /*!< TIM status register, Address offset: 0x10 */
+ __IO uint32_t EGR; /*!< TIM event generation register, Address offset: 0x14 */
+ __IO uint32_t CCMR1; /*!< TIM capture/compare mode register 1, Address offset: 0x18 */
+ __IO uint32_t CCMR2; /*!< TIM capture/compare mode register 2, Address offset: 0x1C */
+ __IO uint32_t CCER; /*!< TIM capture/compare enable register, Address offset: 0x20 */
+ __IO uint32_t CNT; /*!< TIM counter register, Address offset: 0x24 */
+ __IO uint32_t PSC; /*!< TIM prescaler, Address offset: 0x28 */
+ __IO uint32_t ARR; /*!< TIM auto-reload register, Address offset: 0x2C */
+ __IO uint32_t RCR; /*!< TIM repetition counter register, Address offset: 0x30 */
+ __IO uint32_t CCR1; /*!< TIM capture/compare register 1, Address offset: 0x34 */
+ __IO uint32_t CCR2; /*!< TIM capture/compare register 2, Address offset: 0x38 */
+ __IO uint32_t CCR3; /*!< TIM capture/compare register 3, Address offset: 0x3C */
+ __IO uint32_t CCR4; /*!< TIM capture/compare register 4, Address offset: 0x40 */
+ __IO uint32_t BDTR; /*!< TIM break and dead-time register, Address offset: 0x44 */
+ __IO uint32_t CCR5; /*!< TIM capture/compare register 5, Address offset: 0x48 */
+ __IO uint32_t CCR6; /*!< TIM capture/compare register 6, Address offset: 0x4C */
+ __IO uint32_t CCMR3; /*!< TIM capture/compare mode register 3, Address offset: 0x50 */
+ __IO uint32_t DTR2; /*!< TIM deadtime register 2, Address offset: 0x54 */
+ __IO uint32_t ECR; /*!< TIM encoder control register, Address offset: 0x58 */
+ __IO uint32_t TISEL; /*!< TIM Input Selection register, Address offset: 0x5C */
+ __IO uint32_t AF1; /*!< TIM alternate function option register 1, Address offset: 0x60 */
+ __IO uint32_t AF2; /*!< TIM alternate function option register 2, Address offset: 0x64 */
+ __IO uint32_t OR ; /*!< TIM option register, Address offset: 0x68 */
+ uint32_t RESERVED0[220];/*!< Reserved, Address offset: 0x6C */
+ __IO uint32_t DCR; /*!< TIM DMA control register, Address offset: 0x3DC */
+ __IO uint32_t DMAR; /*!< TIM DMA address for full transfer, Address offset: 0x3E0 */
+} TIM_TypeDef;
+
+/**
+ * @brief Universal Synchronous Asynchronous Receiver Transmitter
+ */
+typedef struct
+{
+ __IO uint32_t CR1; /*!< USART Control register 1, Address offset: 0x00 */
+ __IO uint32_t CR2; /*!< USART Control register 2, Address offset: 0x04 */
+ __IO uint32_t CR3; /*!< USART Control register 3, Address offset: 0x08 */
+ __IO uint32_t BRR; /*!< USART Baud rate register, Address offset: 0x0C */
+ __IO uint32_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x10 */
+ __IO uint32_t RTOR; /*!< USART Receiver Timeout register, Address offset: 0x14 */
+ __IO uint32_t RQR; /*!< USART Request register, Address offset: 0x18 */
+ __IO uint32_t ISR; /*!< USART Interrupt and status register, Address offset: 0x1C */
+ __IO uint32_t ICR; /*!< USART Interrupt flag Clear register, Address offset: 0x20 */
+ __IO uint32_t RDR; /*!< USART Receive Data register, Address offset: 0x24 */
+ __IO uint32_t TDR; /*!< USART Transmit Data register, Address offset: 0x28 */
+ __IO uint32_t PRESC; /*!< USART Prescaler register, Address offset: 0x2C */
+} USART_TypeDef;
+
+/**
+ * @brief Universal Serial Bus Full Speed Device
+ */
+
+typedef struct
+{
+ __IO uint16_t EP0R; /*!< USB Endpoint 0 register, Address offset: 0x00 */
+ __IO uint16_t RESERVED0; /*!< Reserved */
+ __IO uint16_t EP1R; /*!< USB Endpoint 1 register, Address offset: 0x04 */
+ __IO uint16_t RESERVED1; /*!< Reserved */
+ __IO uint16_t EP2R; /*!< USB Endpoint 2 register, Address offset: 0x08 */
+ __IO uint16_t RESERVED2; /*!< Reserved */
+ __IO uint16_t EP3R; /*!< USB Endpoint 3 register, Address offset: 0x0C */
+ __IO uint16_t RESERVED3; /*!< Reserved */
+ __IO uint16_t EP4R; /*!< USB Endpoint 4 register, Address offset: 0x10 */
+ __IO uint16_t RESERVED4; /*!< Reserved */
+ __IO uint16_t EP5R; /*!< USB Endpoint 5 register, Address offset: 0x14 */
+ __IO uint16_t RESERVED5; /*!< Reserved */
+ __IO uint16_t EP6R; /*!< USB Endpoint 6 register, Address offset: 0x18 */
+ __IO uint16_t RESERVED6; /*!< Reserved */
+ __IO uint16_t EP7R; /*!< USB Endpoint 7 register, Address offset: 0x1C */
+ __IO uint16_t RESERVED7[17]; /*!< Reserved */
+ __IO uint16_t CNTR; /*!< Control register, Address offset: 0x40 */
+ __IO uint16_t RESERVED8; /*!< Reserved */
+ __IO uint16_t ISTR; /*!< Interrupt status register, Address offset: 0x44 */
+ __IO uint16_t RESERVED9; /*!< Reserved */
+ __IO uint16_t FNR; /*!< Frame number register, Address offset: 0x48 */
+ __IO uint16_t RESERVEDA; /*!< Reserved */
+ __IO uint16_t DADDR; /*!< Device address register, Address offset: 0x4C */
+ __IO uint16_t RESERVEDB; /*!< Reserved */
+ __IO uint16_t BTABLE; /*!< Buffer Table address register, Address offset: 0x50 */
+ __IO uint16_t RESERVEDC; /*!< Reserved */
+ __IO uint16_t LPMCSR; /*!< LPM Control and Status register, Address offset: 0x54 */
+ __IO uint16_t RESERVEDD; /*!< Reserved */
+ __IO uint16_t BCDR; /*!< Battery Charging detector register, Address offset: 0x58 */
+ __IO uint16_t RESERVEDE; /*!< Reserved */
+} USB_TypeDef;
+
+/**
+ * @brief VREFBUF
+ */
+
+typedef struct
+{
+ __IO uint32_t CSR; /*!< VREFBUF control and status register, Address offset: 0x00 */
+ __IO uint32_t CCR; /*!< VREFBUF calibration and control register, Address offset: 0x04 */
+} VREFBUF_TypeDef;
+
+/**
+ * @brief Window WATCHDOG
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< WWDG Control register, Address offset: 0x00 */
+ __IO uint32_t CFR; /*!< WWDG Configuration register, Address offset: 0x04 */
+ __IO uint32_t SR; /*!< WWDG Status register, Address offset: 0x08 */
+} WWDG_TypeDef;
+
+
+/**
+ * @brief RNG
+ */
+typedef struct
+{
+ __IO uint32_t CR; /*!< RNG control register, Address offset: 0x00 */
+ __IO uint32_t SR; /*!< RNG status register, Address offset: 0x04 */
+ __IO uint32_t DR; /*!< RNG data register, Address offset: 0x08 */
+} RNG_TypeDef;
+
+/**
+ * @brief CORDIC
+ */
+
+typedef struct
+{
+ __IO uint32_t CSR; /*!< CORDIC control and status register, Address offset: 0x00 */
+ __IO uint32_t WDATA; /*!< CORDIC argument register, Address offset: 0x04 */
+ __IO uint32_t RDATA; /*!< CORDIC result register, Address offset: 0x08 */
+} CORDIC_TypeDef;
+
+/**
+ * @brief UCPD
+ */
+
+typedef struct
+{
+ __IO uint32_t CFG1; /*!< UCPD configuration register 1, Address offset: 0x00 */
+ __IO uint32_t CFG2; /*!< UCPD configuration register 2, Address offset: 0x04 */
+ __IO uint32_t RESERVED0; /*!< UCPD reserved register, Address offset: 0x08 */
+ __IO uint32_t CR; /*!< UCPD control register, Address offset: 0x0C */
+ __IO uint32_t IMR; /*!< UCPD interrupt mask register, Address offset: 0x10 */
+ __IO uint32_t SR; /*!< UCPD status register, Address offset: 0x14 */
+ __IO uint32_t ICR; /*!< UCPD interrupt flag clear register Address offset: 0x18 */
+ __IO uint32_t TX_ORDSET; /*!< UCPD Tx ordered set type register, Address offset: 0x1C */
+ __IO uint32_t TX_PAYSZ; /*!< UCPD Tx payload size register, Address offset: 0x20 */
+ __IO uint32_t TXDR; /*!< UCPD Tx data register, Address offset: 0x24 */
+ __IO uint32_t RX_ORDSET; /*!< UCPD Rx ordered set type register, Address offset: 0x28 */
+ __IO uint32_t RX_PAYSZ; /*!< UCPD Rx payload size register, Address offset: 0x2C */
+ __IO uint32_t RXDR; /*!< UCPD Rx data register, Address offset: 0x30 */
+ __IO uint32_t RX_ORDEXT1; /*!< UCPD Rx ordered set extension 1 register, Address offset: 0x34 */
+ __IO uint32_t RX_ORDEXT2; /*!< UCPD Rx ordered set extension 2 register, Address offset: 0x38 */
+} UCPD_TypeDef;
+
+/**
+ * @brief High resolution Timer (HRTIM)
+ */
+
+#define c7amba_hrtim1_v2_0
+
+/* HRTIM master registers definition */
+typedef struct
+{
+ __IO uint32_t MCR; /*!< HRTIM Master Timer control register, Address offset: 0x00 */
+ __IO uint32_t MISR; /*!< HRTIM Master Timer interrupt status register, Address offset: 0x04 */
+ __IO uint32_t MICR; /*!< HRTIM Master Timer interupt clear register, Address offset: 0x08 */
+ __IO uint32_t MDIER; /*!< HRTIM Master Timer DMA/interrupt enable register Address offset: 0x0C */
+ __IO uint32_t MCNTR; /*!< HRTIM Master Timer counter register, Address offset: 0x10 */
+ __IO uint32_t MPER; /*!< HRTIM Master Timer period register, Address offset: 0x14 */
+ __IO uint32_t MREP; /*!< HRTIM Master Timer repetition register, Address offset: 0x18 */
+ __IO uint32_t MCMP1R; /*!< HRTIM Master Timer compare 1 register, Address offset: 0x1C */
+ uint32_t RESERVED0; /*!< Reserved, 0x20 */
+ __IO uint32_t MCMP2R; /*!< HRTIM Master Timer compare 2 register, Address offset: 0x24 */
+ __IO uint32_t MCMP3R; /*!< HRTIM Master Timer compare 3 register, Address offset: 0x28 */
+ __IO uint32_t MCMP4R; /*!< HRTIM Master Timer compare 4 register, Address offset: 0x2C */
+ uint32_t RESERVED1[20]; /*!< Reserved, 0x30..0x7C */
+}HRTIM_Master_TypeDef;
+
+/* HRTIM Timer A to F registers definition */
+typedef struct
+{
+ __IO uint32_t TIMxCR; /*!< HRTIM Timerx control register, Address offset: 0x00 */
+ __IO uint32_t TIMxISR; /*!< HRTIM Timerx interrupt status register, Address offset: 0x04 */
+ __IO uint32_t TIMxICR; /*!< HRTIM Timerx interrupt clear register, Address offset: 0x08 */
+ __IO uint32_t TIMxDIER; /*!< HRTIM Timerx DMA/interrupt enable register, Address offset: 0x0C */
+ __IO uint32_t CNTxR; /*!< HRTIM Timerx counter register, Address offset: 0x10 */
+ __IO uint32_t PERxR; /*!< HRTIM Timerx period register, Address offset: 0x14 */
+ __IO uint32_t REPxR; /*!< HRTIM Timerx repetition register, Address offset: 0x18 */
+ __IO uint32_t CMP1xR; /*!< HRTIM Timerx compare 1 register, Address offset: 0x1C */
+ __IO uint32_t CMP1CxR; /*!< HRTIM Timerx compare 1 compound register, Address offset: 0x20 */
+ __IO uint32_t CMP2xR; /*!< HRTIM Timerx compare 2 register, Address offset: 0x24 */
+ __IO uint32_t CMP3xR; /*!< HRTIM Timerx compare 3 register, Address offset: 0x28 */
+ __IO uint32_t CMP4xR; /*!< HRTIM Timerx compare 4 register, Address offset: 0x2C */
+ __IO uint32_t CPT1xR; /*!< HRTIM Timerx capture 1 register, Address offset: 0x30 */
+ __IO uint32_t CPT2xR; /*!< HRTIM Timerx capture 2 register, Address offset: 0x34 */
+ __IO uint32_t DTxR; /*!< HRTIM Timerx dead time register, Address offset: 0x38 */
+ __IO uint32_t SETx1R; /*!< HRTIM Timerx output 1 set register, Address offset: 0x3C */
+ __IO uint32_t RSTx1R; /*!< HRTIM Timerx output 1 reset register, Address offset: 0x40 */
+ __IO uint32_t SETx2R; /*!< HRTIM Timerx output 2 set register, Address offset: 0x44 */
+ __IO uint32_t RSTx2R; /*!< HRTIM Timerx output 2 reset register, Address offset: 0x48 */
+ __IO uint32_t EEFxR1; /*!< HRTIM Timerx external event filtering 1 register, Address offset: 0x4C */
+ __IO uint32_t EEFxR2; /*!< HRTIM Timerx external event filtering 2 register, Address offset: 0x50 */
+ __IO uint32_t RSTxR; /*!< HRTIM Timerx Reset register, Address offset: 0x54 */
+ __IO uint32_t CHPxR; /*!< HRTIM Timerx Chopper register, Address offset: 0x58 */
+ __IO uint32_t CPT1xCR; /*!< HRTIM Timerx Capture 1 register, Address offset: 0x5C */
+ __IO uint32_t CPT2xCR; /*!< HRTIM Timerx Capture 2 register, Address offset: 0x60 */
+ __IO uint32_t OUTxR; /*!< HRTIM Timerx Output register, Address offset: 0x64 */
+ __IO uint32_t FLTxR; /*!< HRTIM Timerx Fault register, Address offset: 0x68 */
+ __IO uint32_t TIMxCR2; /*!< HRTIM Timerx Control register 2, Address offset: 0x6C */
+ __IO uint32_t EEFxR3; /*!< HRTIM Timerx external event filtering 3 register, Address offset: 0x70 */
+ uint32_t RESERVED0[3]; /*!< Reserved, 0x74..0x7C */
+}HRTIM_Timerx_TypeDef;
+
+/* HRTIM common register definition */
+typedef struct
+{
+ __IO uint32_t CR1; /*!< HRTIM control register1, Address offset: 0x00 */
+ __IO uint32_t CR2; /*!< HRTIM control register2, Address offset: 0x04 */
+ __IO uint32_t ISR; /*!< HRTIM interrupt status register, Address offset: 0x08 */
+ __IO uint32_t ICR; /*!< HRTIM interrupt clear register, Address offset: 0x0C */
+ __IO uint32_t IER; /*!< HRTIM interrupt enable register, Address offset: 0x10 */
+ __IO uint32_t OENR; /*!< HRTIM Output enable register, Address offset: 0x14 */
+ __IO uint32_t ODISR; /*!< HRTIM Output disable register, Address offset: 0x18 */
+ __IO uint32_t ODSR; /*!< HRTIM Output disable status register, Address offset: 0x1C */
+ __IO uint32_t BMCR; /*!< HRTIM Burst mode control register, Address offset: 0x20 */
+ __IO uint32_t BMTRGR; /*!< HRTIM Busrt mode trigger register, Address offset: 0x24 */
+ __IO uint32_t BMCMPR; /*!< HRTIM Burst mode compare register, Address offset: 0x28 */
+ __IO uint32_t BMPER; /*!< HRTIM Burst mode period register, Address offset: 0x2C */
+ __IO uint32_t EECR1; /*!< HRTIM Timer external event control register1, Address offset: 0x30 */
+ __IO uint32_t EECR2; /*!< HRTIM Timer external event control register2, Address offset: 0x34 */
+ __IO uint32_t EECR3; /*!< HRTIM Timer external event control register3, Address offset: 0x38 */
+ __IO uint32_t ADC1R; /*!< HRTIM ADC Trigger 1 register, Address offset: 0x3C */
+ __IO uint32_t ADC2R; /*!< HRTIM ADC Trigger 2 register, Address offset: 0x40 */
+ __IO uint32_t ADC3R; /*!< HRTIM ADC Trigger 3 register, Address offset: 0x44 */
+ __IO uint32_t ADC4R; /*!< HRTIM ADC Trigger 4 register, Address offset: 0x48 */
+ __IO uint32_t DLLCR; /*!< HRTIM DLL control register, Address offset: 0x4C */
+ __IO uint32_t FLTINR1; /*!< HRTIM Fault input register1, Address offset: 0x50 */
+ __IO uint32_t FLTINR2; /*!< HRTIM Fault input register2, Address offset: 0x54 */
+ __IO uint32_t BDMUPR; /*!< HRTIM Burst DMA Master Timer update register, Address offset: 0x58 */
+ __IO uint32_t BDTAUPR; /*!< HRTIM Burst DMA Timerx update register, Address offset: 0x5C */
+ __IO uint32_t BDTBUPR; /*!< HRTIM Burst DMA Timerx update register, Address offset: 0x60 */
+ __IO uint32_t BDTCUPR; /*!< HRTIM Burst DMA Timerx update register, Address offset: 0x64 */
+ __IO uint32_t BDTDUPR; /*!< HRTIM Burst DMA Timerx update register, Address offset: 0x68 */
+ __IO uint32_t BDTEUPR; /*!< HRTIM Burst DMA Timerx update register, Address offset: 0x6C */
+ __IO uint32_t BDMADR; /*!< HRTIM Burst DMA Master Data register, Address offset: 0x70 */
+ __IO uint32_t BDTFUPR; /*!< HRTIM Burst DMA Timerx update register, Address offset: 0x74 */
+ __IO uint32_t ADCER; /*!< HRTIM ADC Extended Trigger register, Address offset: 0x78 */
+ __IO uint32_t ADCUR; /*!< HRTIM ADC Trigger Update register, Address offset: 0x7C */
+ __IO uint32_t ADCPS1; /*!< HRTIM ADC Post Scaler Register 1, Address offset: 0x80 */
+ __IO uint32_t ADCPS2; /*!< HRTIM ADC Post Scaler Register 2, Address offset: 0x84 */
+ __IO uint32_t FLTINR3; /*!< HRTIM Fault input register3, Address offset: 0x88 */
+ __IO uint32_t FLTINR4; /*!< HRTIM Fault input register4, Address offset: 0x8C */
+}HRTIM_Common_TypeDef;
+
+/* HRTIM register definition */
+typedef struct {
+ HRTIM_Master_TypeDef sMasterRegs;
+ HRTIM_Timerx_TypeDef sTimerxRegs[6];
+// uint32_t RESERVED0[32];
+ HRTIM_Common_TypeDef sCommonRegs;
+}HRTIM_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @addtogroup Peripheral_memory_map
+ * @{
+ */
+
+#define FLASH_BASE (0x08000000UL) /*!< FLASH (up to 512 kB) base address */
+#define SRAM1_BASE (0x20000000UL) /*!< SRAM1(up to 80 KB) base address */
+#define SRAM2_BASE (0x20014000UL) /*!< SRAM2(16 KB) base address */
+#define CCMSRAM_BASE (0x10000000UL) /*!< CCMSRAM(32 KB) base address */
+#define PERIPH_BASE (0x40000000UL) /*!< Peripheral base address */
+#define FMC_BASE (0x60000000UL) /*!< FMC base address */
+#define QSPI_BASE (0x90000000UL) /*!< QUADSPI memories accessible over AHB base address */
+
+#define FMC_R_BASE (0xA0000000UL) /*!< FMC control registers base address */
+#define QSPI_R_BASE (0xA0001000UL) /*!< QUADSPI control registers base address */
+#define SRAM1_BB_BASE (0x22000000UL) /*!< SRAM1(80 KB) base address in the bit-band region */
+#define SRAM2_BB_BASE (0x22280000UL) /*!< SRAM2(16 KB) base address in the bit-band region */
+#define CCMSRAM_BB_BASE (0x22300000UL) /*!< CCMSRAM(32 KB) base address in the bit-band region */
+#define PERIPH_BB_BASE (0x42000000UL) /*!< Peripheral base address in the bit-band region */
+/* Legacy defines */
+#define SRAM_BASE SRAM1_BASE
+#define SRAM_BB_BASE SRAM1_BB_BASE
+
+#define SRAM1_SIZE_MAX (0x00014000UL) /*!< maximum SRAM1 size (up to 80 KBytes) */
+#define SRAM2_SIZE (0x00004000UL) /*!< SRAM2 size (16 KBytes) */
+#define CCMSRAM_SIZE (0x00008000UL) /*!< CCMSRAM size (32 KBytes) */
+
+/*!< Peripheral memory map */
+#define APB1PERIPH_BASE PERIPH_BASE
+#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL)
+#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL)
+#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000UL)
+
+#define FMC_BANK1 FMC_BASE
+#define FMC_BANK1_1 FMC_BANK1
+#define FMC_BANK1_2 (FMC_BANK1 + 0x04000000UL)
+#define FMC_BANK1_3 (FMC_BANK1 + 0x08000000UL)
+#define FMC_BANK1_4 (FMC_BANK1 + 0x0C000000UL)
+#define FMC_BANK3 (FMC_BASE + 0x20000000UL)
+
+/*!< APB1 peripherals */
+#define TIM2_BASE (APB1PERIPH_BASE + 0x0000UL)
+#define TIM3_BASE (APB1PERIPH_BASE + 0x0400UL)
+#define TIM4_BASE (APB1PERIPH_BASE + 0x0800UL)
+#define TIM5_BASE (APB1PERIPH_BASE + 0x0C00UL)
+#define TIM6_BASE (APB1PERIPH_BASE + 0x1000UL)
+#define TIM7_BASE (APB1PERIPH_BASE + 0x1400UL)
+#define CRS_BASE (APB1PERIPH_BASE + 0x2000UL)
+#define TAMP_BASE (APB1PERIPH_BASE + 0x2400UL)
+#define RTC_BASE (APB1PERIPH_BASE + 0x2800UL)
+#define WWDG_BASE (APB1PERIPH_BASE + 0x2C00UL)
+#define IWDG_BASE (APB1PERIPH_BASE + 0x3000UL)
+#define SPI2_BASE (APB1PERIPH_BASE + 0x3800UL)
+#define SPI3_BASE (APB1PERIPH_BASE + 0x3C00UL)
+#define USART2_BASE (APB1PERIPH_BASE + 0x4400UL)
+#define USART3_BASE (APB1PERIPH_BASE + 0x4800UL)
+#define UART4_BASE (APB1PERIPH_BASE + 0x4C00UL)
+#define UART5_BASE (APB1PERIPH_BASE + 0x5000UL)
+#define I2C1_BASE (APB1PERIPH_BASE + 0x5400UL)
+#define I2C2_BASE (APB1PERIPH_BASE + 0x5800UL)
+#define USB_BASE (APB1PERIPH_BASE + 0x5C00UL) /*!< USB_IP Peripheral Registers base address */
+#define USB_PMAADDR (APB1PERIPH_BASE + 0x6000UL) /*!< USB_IP Packet Memory Area base address */
+#define FDCAN1_BASE (APB1PERIPH_BASE + 0x6400UL)
+#define FDCAN_CONFIG_BASE (APB1PERIPH_BASE + 0x6500UL) /*!< FDCAN configuration registers base address */
+#define FDCAN2_BASE (APB1PERIPH_BASE + 0x6800UL)
+#define FDCAN3_BASE (APB1PERIPH_BASE + 0x6C00UL)
+#define PWR_BASE (APB1PERIPH_BASE + 0x7000UL)
+#define I2C3_BASE (APB1PERIPH_BASE + 0x7800UL)
+#define LPTIM1_BASE (APB1PERIPH_BASE + 0x7C00UL)
+#define LPUART1_BASE (APB1PERIPH_BASE + 0x8000UL)
+#define I2C4_BASE (APB1PERIPH_BASE + 0x8400UL)
+#define UCPD1_BASE (APB1PERIPH_BASE + 0xA000UL)
+#define SRAMCAN_BASE (APB1PERIPH_BASE + 0xA400UL)
+
+/*!< APB2 peripherals */
+#define SYSCFG_BASE (APB2PERIPH_BASE + 0x0000UL)
+#define VREFBUF_BASE (APB2PERIPH_BASE + 0x0030UL)
+#define COMP1_BASE (APB2PERIPH_BASE + 0x0200UL)
+#define COMP2_BASE (APB2PERIPH_BASE + 0x0204UL)
+#define COMP3_BASE (APB2PERIPH_BASE + 0x0208UL)
+#define COMP4_BASE (APB2PERIPH_BASE + 0x020CUL)
+#define COMP5_BASE (APB2PERIPH_BASE + 0x0210UL)
+#define COMP6_BASE (APB2PERIPH_BASE + 0x0214UL)
+#define COMP7_BASE (APB2PERIPH_BASE + 0x0218UL)
+#define OPAMP_BASE (APB2PERIPH_BASE + 0x0300UL)
+#define OPAMP1_BASE (APB2PERIPH_BASE + 0x0300UL)
+#define OPAMP2_BASE (APB2PERIPH_BASE + 0x0304UL)
+#define OPAMP3_BASE (APB2PERIPH_BASE + 0x0308UL)
+#define OPAMP4_BASE (APB2PERIPH_BASE + 0x030CUL)
+#define OPAMP5_BASE (APB2PERIPH_BASE + 0x0310UL)
+#define OPAMP6_BASE (APB2PERIPH_BASE + 0x0314UL)
+
+#define EXTI_BASE (APB2PERIPH_BASE + 0x0400UL)
+#define TIM1_BASE (APB2PERIPH_BASE + 0x2C00UL)
+#define SPI1_BASE (APB2PERIPH_BASE + 0x3000UL)
+#define TIM8_BASE (APB2PERIPH_BASE + 0x3400UL)
+#define USART1_BASE (APB2PERIPH_BASE + 0x3800UL)
+#define SPI4_BASE (APB2PERIPH_BASE + 0x3C00UL)
+#define TIM15_BASE (APB2PERIPH_BASE + 0x4000UL)
+#define TIM16_BASE (APB2PERIPH_BASE + 0x4400UL)
+#define TIM17_BASE (APB2PERIPH_BASE + 0x4800UL)
+#define TIM20_BASE (APB2PERIPH_BASE + 0x5000UL)
+#define SAI1_BASE (APB2PERIPH_BASE + 0x5400UL)
+#define SAI1_Block_A_BASE (SAI1_BASE + 0x0004UL)
+#define SAI1_Block_B_BASE (SAI1_BASE + 0x0024UL)
+#define HRTIM1_BASE (APB2PERIPH_BASE + 0x6800UL)
+#define HRTIM1_TIMA_BASE (HRTIM1_BASE + 0x0080UL)
+#define HRTIM1_TIMB_BASE (HRTIM1_BASE + 0x0100UL)
+#define HRTIM1_TIMC_BASE (HRTIM1_BASE + 0x0180UL)
+#define HRTIM1_TIMD_BASE (HRTIM1_BASE + 0x0200UL)
+#define HRTIM1_TIME_BASE (HRTIM1_BASE + 0x0280UL)
+#define HRTIM1_TIMF_BASE (HRTIM1_BASE + 0x0300UL)
+#define HRTIM1_COMMON_BASE (HRTIM1_BASE + 0x0380UL)
+
+/*!< AHB1 peripherals */
+#define DMA1_BASE (AHB1PERIPH_BASE)
+#define DMA2_BASE (AHB1PERIPH_BASE + 0x0400UL)
+#define DMAMUX1_BASE (AHB1PERIPH_BASE + 0x0800UL)
+#define CORDIC_BASE (AHB1PERIPH_BASE + 0x0C00UL)
+#define RCC_BASE (AHB1PERIPH_BASE + 0x1000UL)
+#define FMAC_BASE (AHB1PERIPH_BASE + 0x1400UL)
+#define FLASH_R_BASE (AHB1PERIPH_BASE + 0x2000UL)
+#define CRC_BASE (AHB1PERIPH_BASE + 0x3000UL)
+
+#define DMA1_Channel1_BASE (DMA1_BASE + 0x0008UL)
+#define DMA1_Channel2_BASE (DMA1_BASE + 0x001CUL)
+#define DMA1_Channel3_BASE (DMA1_BASE + 0x0030UL)
+#define DMA1_Channel4_BASE (DMA1_BASE + 0x0044UL)
+#define DMA1_Channel5_BASE (DMA1_BASE + 0x0058UL)
+#define DMA1_Channel6_BASE (DMA1_BASE + 0x006CUL)
+#define DMA1_Channel7_BASE (DMA1_BASE + 0x0080UL)
+#define DMA1_Channel8_BASE (DMA1_BASE + 0x0094UL)
+
+#define DMA2_Channel1_BASE (DMA2_BASE + 0x0008UL)
+#define DMA2_Channel2_BASE (DMA2_BASE + 0x001CUL)
+#define DMA2_Channel3_BASE (DMA2_BASE + 0x0030UL)
+#define DMA2_Channel4_BASE (DMA2_BASE + 0x0044UL)
+#define DMA2_Channel5_BASE (DMA2_BASE + 0x0058UL)
+#define DMA2_Channel6_BASE (DMA2_BASE + 0x006CUL)
+#define DMA2_Channel7_BASE (DMA2_BASE + 0x0080UL)
+#define DMA2_Channel8_BASE (DMA2_BASE + 0x0094UL)
+
+#define DMAMUX1_Channel0_BASE (DMAMUX1_BASE)
+#define DMAMUX1_Channel1_BASE (DMAMUX1_BASE + 0x0004UL)
+#define DMAMUX1_Channel2_BASE (DMAMUX1_BASE + 0x0008UL)
+#define DMAMUX1_Channel3_BASE (DMAMUX1_BASE + 0x000CUL)
+#define DMAMUX1_Channel4_BASE (DMAMUX1_BASE + 0x0010UL)
+#define DMAMUX1_Channel5_BASE (DMAMUX1_BASE + 0x0014UL)
+#define DMAMUX1_Channel6_BASE (DMAMUX1_BASE + 0x0018UL)
+#define DMAMUX1_Channel7_BASE (DMAMUX1_BASE + 0x001CUL)
+#define DMAMUX1_Channel8_BASE (DMAMUX1_BASE + 0x0020UL)
+#define DMAMUX1_Channel9_BASE (DMAMUX1_BASE + 0x0024UL)
+#define DMAMUX1_Channel10_BASE (DMAMUX1_BASE + 0x0028UL)
+#define DMAMUX1_Channel11_BASE (DMAMUX1_BASE + 0x002CUL)
+#define DMAMUX1_Channel12_BASE (DMAMUX1_BASE + 0x0030UL)
+#define DMAMUX1_Channel13_BASE (DMAMUX1_BASE + 0x0034UL)
+#define DMAMUX1_Channel14_BASE (DMAMUX1_BASE + 0x0038UL)
+#define DMAMUX1_Channel15_BASE (DMAMUX1_BASE + 0x003CUL)
+#define DMAMUX1_RequestGenerator0_BASE (DMAMUX1_BASE + 0x0100UL)
+#define DMAMUX1_RequestGenerator1_BASE (DMAMUX1_BASE + 0x0104UL)
+#define DMAMUX1_RequestGenerator2_BASE (DMAMUX1_BASE + 0x0108UL)
+#define DMAMUX1_RequestGenerator3_BASE (DMAMUX1_BASE + 0x010CUL)
+
+#define DMAMUX1_ChannelStatus_BASE (DMAMUX1_BASE + 0x0080UL)
+#define DMAMUX1_RequestGenStatus_BASE (DMAMUX1_BASE + 0x0140UL)
+
+/*!< AHB2 peripherals */
+#define GPIOA_BASE (AHB2PERIPH_BASE + 0x0000UL)
+#define GPIOB_BASE (AHB2PERIPH_BASE + 0x0400UL)
+#define GPIOC_BASE (AHB2PERIPH_BASE + 0x0800UL)
+#define GPIOD_BASE (AHB2PERIPH_BASE + 0x0C00UL)
+#define GPIOE_BASE (AHB2PERIPH_BASE + 0x1000UL)
+#define GPIOF_BASE (AHB2PERIPH_BASE + 0x1400UL)
+#define GPIOG_BASE (AHB2PERIPH_BASE + 0x1800UL)
+
+#define ADC1_BASE (AHB2PERIPH_BASE + 0x08000000UL)
+#define ADC2_BASE (AHB2PERIPH_BASE + 0x08000100UL)
+#define ADC12_COMMON_BASE (AHB2PERIPH_BASE + 0x08000300UL)
+#define ADC3_BASE (AHB2PERIPH_BASE + 0x08000400UL)
+#define ADC4_BASE (AHB2PERIPH_BASE + 0x08000500UL)
+#define ADC5_BASE (AHB2PERIPH_BASE + 0x08000600UL)
+#define ADC345_COMMON_BASE (AHB2PERIPH_BASE + 0x08000700UL)
+
+#define DAC_BASE (AHB2PERIPH_BASE + 0x08000800UL)
+#define DAC1_BASE (AHB2PERIPH_BASE + 0x08000800UL)
+#define DAC2_BASE (AHB2PERIPH_BASE + 0x08000C00UL)
+#define DAC3_BASE (AHB2PERIPH_BASE + 0x08001000UL)
+#define DAC4_BASE (AHB2PERIPH_BASE + 0x08001400UL)
+
+/*!< FMC Banks registers base address */
+#define FMC_Bank1_R_BASE (FMC_R_BASE + 0x0000UL)
+#define FMC_Bank1E_R_BASE (FMC_R_BASE + 0x0104UL)
+#define FMC_Bank3_R_BASE (FMC_R_BASE + 0x0080UL)
+#define RNG_BASE (AHB2PERIPH_BASE + 0x08060800UL)
+/* Debug MCU registers base address */
+#define DBGMCU_BASE (0xE0042000UL)
+
+#define PACKAGE_BASE (0x1FFF7500UL) /*!< Package data register base address */
+#define UID_BASE (0x1FFF7590UL) /*!< Unique device ID register base address */
+#define FLASHSIZE_BASE (0x1FFF75E0UL) /*!< Flash size data register base address */
+/**
+ * @}
+ */
+
+/** @addtogroup Peripheral_declaration
+ * @{
+ */
+#define TIM2 ((TIM_TypeDef *) TIM2_BASE)
+#define TIM3 ((TIM_TypeDef *) TIM3_BASE)
+#define TIM4 ((TIM_TypeDef *) TIM4_BASE)
+#define TIM5 ((TIM_TypeDef *) TIM5_BASE)
+#define TIM6 ((TIM_TypeDef *) TIM6_BASE)
+#define TIM7 ((TIM_TypeDef *) TIM7_BASE)
+#define CRS ((CRS_TypeDef *) CRS_BASE)
+#define TAMP ((TAMP_TypeDef *) TAMP_BASE)
+#define RTC ((RTC_TypeDef *) RTC_BASE)
+#define WWDG ((WWDG_TypeDef *) WWDG_BASE)
+#define IWDG ((IWDG_TypeDef *) IWDG_BASE)
+#define SPI2 ((SPI_TypeDef *) SPI2_BASE)
+#define SPI3 ((SPI_TypeDef *) SPI3_BASE)
+#define USART2 ((USART_TypeDef *) USART2_BASE)
+#define USART3 ((USART_TypeDef *) USART3_BASE)
+#define UART4 ((USART_TypeDef *) UART4_BASE)
+#define UART5 ((USART_TypeDef *) UART5_BASE)
+#define I2C1 ((I2C_TypeDef *) I2C1_BASE)
+#define I2C2 ((I2C_TypeDef *) I2C2_BASE)
+#define USB ((USB_TypeDef *) USB_BASE)
+#define FDCAN1 ((FDCAN_GlobalTypeDef *) FDCAN1_BASE)
+#define FDCAN_CONFIG ((FDCAN_Config_TypeDef *) FDCAN_CONFIG_BASE)
+#define FDCAN2 ((FDCAN_GlobalTypeDef *) FDCAN2_BASE)
+#define FDCAN3 ((FDCAN_GlobalTypeDef *) FDCAN3_BASE)
+#define PWR ((PWR_TypeDef *) PWR_BASE)
+#define I2C3 ((I2C_TypeDef *) I2C3_BASE)
+#define LPTIM1 ((LPTIM_TypeDef *) LPTIM1_BASE)
+#define LPUART1 ((USART_TypeDef *) LPUART1_BASE)
+#define I2C4 ((I2C_TypeDef *) I2C4_BASE)
+#define UCPD1 ((UCPD_TypeDef *) UCPD1_BASE)
+
+#define SYSCFG ((SYSCFG_TypeDef *) SYSCFG_BASE)
+#define VREFBUF ((VREFBUF_TypeDef *) VREFBUF_BASE)
+#define COMP1 ((COMP_TypeDef *) COMP1_BASE)
+#define COMP2 ((COMP_TypeDef *) COMP2_BASE)
+#define COMP3 ((COMP_TypeDef *) COMP3_BASE)
+#define COMP4 ((COMP_TypeDef *) COMP4_BASE)
+#define COMP5 ((COMP_TypeDef *) COMP5_BASE)
+#define COMP6 ((COMP_TypeDef *) COMP6_BASE)
+#define COMP7 ((COMP_TypeDef *) COMP7_BASE)
+
+#define OPAMP ((OPAMP_TypeDef *) OPAMP_BASE)
+#define OPAMP1 ((OPAMP_TypeDef *) OPAMP1_BASE)
+#define OPAMP2 ((OPAMP_TypeDef *) OPAMP2_BASE)
+#define OPAMP3 ((OPAMP_TypeDef *) OPAMP3_BASE)
+#define OPAMP4 ((OPAMP_TypeDef *) OPAMP4_BASE)
+#define OPAMP5 ((OPAMP_TypeDef *) OPAMP5_BASE)
+#define OPAMP6 ((OPAMP_TypeDef *) OPAMP6_BASE)
+
+#define EXTI ((EXTI_TypeDef *) EXTI_BASE)
+#define TIM1 ((TIM_TypeDef *) TIM1_BASE)
+#define SPI1 ((SPI_TypeDef *) SPI1_BASE)
+#define TIM8 ((TIM_TypeDef *) TIM8_BASE)
+#define USART1 ((USART_TypeDef *) USART1_BASE)
+#define SPI4 ((SPI_TypeDef *) SPI4_BASE)
+#define TIM15 ((TIM_TypeDef *) TIM15_BASE)
+#define TIM16 ((TIM_TypeDef *) TIM16_BASE)
+#define TIM17 ((TIM_TypeDef *) TIM17_BASE)
+#define TIM20 ((TIM_TypeDef *) TIM20_BASE)
+#define SAI1 ((SAI_TypeDef *) SAI1_BASE)
+#define SAI1_Block_A ((SAI_Block_TypeDef *)SAI1_Block_A_BASE)
+#define SAI1_Block_B ((SAI_Block_TypeDef *)SAI1_Block_B_BASE)
+#define HRTIM1 ((HRTIM_TypeDef *) HRTIM1_BASE)
+#define HRTIM1_TIMA ((HRTIM_Timerx_TypeDef *) HRTIM1_TIMA_BASE)
+#define HRTIM1_TIMB ((HRTIM_Timerx_TypeDef *) HRTIM1_TIMB_BASE)
+#define HRTIM1_TIMC ((HRTIM_Timerx_TypeDef *) HRTIM1_TIMC_BASE)
+#define HRTIM1_TIMD ((HRTIM_Timerx_TypeDef *) HRTIM1_TIMD_BASE)
+#define HRTIM1_TIME ((HRTIM_Timerx_TypeDef *) HRTIM1_TIME_BASE)
+#define HRTIM1_TIMF ((HRTIM_Timerx_TypeDef *) HRTIM1_TIMF_BASE)
+#define HRTIM1_COMMON ((HRTIM_Common_TypeDef *) HRTIM1_COMMON_BASE)
+#define DMA1 ((DMA_TypeDef *) DMA1_BASE)
+#define DMA2 ((DMA_TypeDef *) DMA2_BASE)
+#define DMAMUX1 ((DMAMUX_Channel_TypeDef *) DMAMUX1_BASE)
+#define CORDIC ((CORDIC_TypeDef *) CORDIC_BASE)
+#define RCC ((RCC_TypeDef *) RCC_BASE)
+#define FMAC ((FMAC_TypeDef *) FMAC_BASE)
+#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE)
+#define CRC ((CRC_TypeDef *) CRC_BASE)
+
+#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
+#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
+#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)
+#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)
+#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)
+#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE)
+#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE)
+#define ADC1 ((ADC_TypeDef *) ADC1_BASE)
+#define ADC2 ((ADC_TypeDef *) ADC2_BASE)
+#define ADC12_COMMON ((ADC_Common_TypeDef *) ADC12_COMMON_BASE)
+#define ADC3 ((ADC_TypeDef *) ADC3_BASE)
+#define ADC4 ((ADC_TypeDef *) ADC4_BASE)
+#define ADC5 ((ADC_TypeDef *) ADC5_BASE)
+#define ADC345_COMMON ((ADC_Common_TypeDef *) ADC345_COMMON_BASE)
+#define DAC ((DAC_TypeDef *) DAC_BASE)
+#define DAC1 ((DAC_TypeDef *) DAC1_BASE)
+#define DAC2 ((DAC_TypeDef *) DAC2_BASE)
+#define DAC3 ((DAC_TypeDef *) DAC3_BASE)
+#define DAC4 ((DAC_TypeDef *) DAC4_BASE)
+#define RNG ((RNG_TypeDef *) RNG_BASE)
+
+#define DMA1_Channel1 ((DMA_Channel_TypeDef *) DMA1_Channel1_BASE)
+#define DMA1_Channel2 ((DMA_Channel_TypeDef *) DMA1_Channel2_BASE)
+#define DMA1_Channel3 ((DMA_Channel_TypeDef *) DMA1_Channel3_BASE)
+#define DMA1_Channel4 ((DMA_Channel_TypeDef *) DMA1_Channel4_BASE)
+#define DMA1_Channel5 ((DMA_Channel_TypeDef *) DMA1_Channel5_BASE)
+#define DMA1_Channel6 ((DMA_Channel_TypeDef *) DMA1_Channel6_BASE)
+#define DMA1_Channel7 ((DMA_Channel_TypeDef *) DMA1_Channel7_BASE)
+#define DMA1_Channel8 ((DMA_Channel_TypeDef *) DMA1_Channel8_BASE)
+
+#define DMA2_Channel1 ((DMA_Channel_TypeDef *) DMA2_Channel1_BASE)
+#define DMA2_Channel2 ((DMA_Channel_TypeDef *) DMA2_Channel2_BASE)
+#define DMA2_Channel3 ((DMA_Channel_TypeDef *) DMA2_Channel3_BASE)
+#define DMA2_Channel4 ((DMA_Channel_TypeDef *) DMA2_Channel4_BASE)
+#define DMA2_Channel5 ((DMA_Channel_TypeDef *) DMA2_Channel5_BASE)
+#define DMA2_Channel6 ((DMA_Channel_TypeDef *) DMA2_Channel6_BASE)
+#define DMA2_Channel7 ((DMA_Channel_TypeDef *) DMA2_Channel7_BASE)
+#define DMA2_Channel8 ((DMA_Channel_TypeDef *) DMA2_Channel8_BASE)
+
+#define DMAMUX1_Channel0 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel0_BASE)
+#define DMAMUX1_Channel1 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel1_BASE)
+#define DMAMUX1_Channel2 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel2_BASE)
+#define DMAMUX1_Channel3 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel3_BASE)
+#define DMAMUX1_Channel4 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel4_BASE)
+#define DMAMUX1_Channel5 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel5_BASE)
+#define DMAMUX1_Channel6 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel6_BASE)
+#define DMAMUX1_Channel7 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel7_BASE)
+#define DMAMUX1_Channel8 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel8_BASE)
+#define DMAMUX1_Channel9 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel9_BASE)
+#define DMAMUX1_Channel10 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel10_BASE)
+#define DMAMUX1_Channel11 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel11_BASE)
+#define DMAMUX1_Channel12 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel12_BASE)
+#define DMAMUX1_Channel13 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel13_BASE)
+#define DMAMUX1_Channel14 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel14_BASE)
+#define DMAMUX1_Channel15 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel15_BASE)
+
+#define DMAMUX1_RequestGenerator0 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator0_BASE)
+#define DMAMUX1_RequestGenerator1 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator1_BASE)
+#define DMAMUX1_RequestGenerator2 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator2_BASE)
+#define DMAMUX1_RequestGenerator3 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator3_BASE)
+
+#define DMAMUX1_ChannelStatus ((DMAMUX_ChannelStatus_TypeDef *) DMAMUX1_ChannelStatus_BASE)
+#define DMAMUX1_RequestGenStatus ((DMAMUX_RequestGenStatus_TypeDef *) DMAMUX1_RequestGenStatus_BASE)
+
+#define FMC_Bank1_R ((FMC_Bank1_TypeDef *) FMC_Bank1_R_BASE)
+#define FMC_Bank1E_R ((FMC_Bank1E_TypeDef *) FMC_Bank1E_R_BASE)
+#define FMC_Bank3_R ((FMC_Bank3_TypeDef *) FMC_Bank3_R_BASE)
+
+#define QUADSPI ((QUADSPI_TypeDef *) QSPI_R_BASE)
+
+#define DBGMCU ((DBGMCU_TypeDef *) DBGMCU_BASE)
+
+/**
+ * @}
+ */
+
+/** @addtogroup Exported_constants
+ * @{
+ */
+
+/** @addtogroup Peripheral_Registers_Bits_Definition
+ * @{
+ */
+
+/******************************************************************************/
+/* Peripheral Registers_Bits_Definition */
+/******************************************************************************/
+
+/******************************************************************************/
+/* */
+/* Analog to Digital Converter */
+/* */
+/******************************************************************************/
+
+/*
+ * @brief Specific device feature definitions (not present on all devices in the STM32G4 serie)
+ */
+#define ADC_MULTIMODE_SUPPORT /*!< ADC feature available only on specific devices: multimode available on devices with several ADC instances */
+
+/******************** Bit definition for ADC_ISR register *******************/
+#define ADC_ISR_ADRDY_Pos (0U)
+#define ADC_ISR_ADRDY_Msk (0x1UL << ADC_ISR_ADRDY_Pos) /*!< 0x00000001 */
+#define ADC_ISR_ADRDY ADC_ISR_ADRDY_Msk /*!< ADC ready flag */
+#define ADC_ISR_EOSMP_Pos (1U)
+#define ADC_ISR_EOSMP_Msk (0x1UL << ADC_ISR_EOSMP_Pos) /*!< 0x00000002 */
+#define ADC_ISR_EOSMP ADC_ISR_EOSMP_Msk /*!< ADC group regular end of sampling flag */
+#define ADC_ISR_EOC_Pos (2U)
+#define ADC_ISR_EOC_Msk (0x1UL << ADC_ISR_EOC_Pos) /*!< 0x00000004 */
+#define ADC_ISR_EOC ADC_ISR_EOC_Msk /*!< ADC group regular end of unitary conversion flag */
+#define ADC_ISR_EOS_Pos (3U)
+#define ADC_ISR_EOS_Msk (0x1UL << ADC_ISR_EOS_Pos) /*!< 0x00000008 */
+#define ADC_ISR_EOS ADC_ISR_EOS_Msk /*!< ADC group regular end of sequence conversions flag */
+#define ADC_ISR_OVR_Pos (4U)
+#define ADC_ISR_OVR_Msk (0x1UL << ADC_ISR_OVR_Pos) /*!< 0x00000010 */
+#define ADC_ISR_OVR ADC_ISR_OVR_Msk /*!< ADC group regular overrun flag */
+#define ADC_ISR_JEOC_Pos (5U)
+#define ADC_ISR_JEOC_Msk (0x1UL << ADC_ISR_JEOC_Pos) /*!< 0x00000020 */
+#define ADC_ISR_JEOC ADC_ISR_JEOC_Msk /*!< ADC group injected end of unitary conversion flag */
+#define ADC_ISR_JEOS_Pos (6U)
+#define ADC_ISR_JEOS_Msk (0x1UL << ADC_ISR_JEOS_Pos) /*!< 0x00000040 */
+#define ADC_ISR_JEOS ADC_ISR_JEOS_Msk /*!< ADC group injected end of sequence conversions flag */
+#define ADC_ISR_AWD1_Pos (7U)
+#define ADC_ISR_AWD1_Msk (0x1UL << ADC_ISR_AWD1_Pos) /*!< 0x00000080 */
+#define ADC_ISR_AWD1 ADC_ISR_AWD1_Msk /*!< ADC analog watchdog 1 flag */
+#define ADC_ISR_AWD2_Pos (8U)
+#define ADC_ISR_AWD2_Msk (0x1UL << ADC_ISR_AWD2_Pos) /*!< 0x00000100 */
+#define ADC_ISR_AWD2 ADC_ISR_AWD2_Msk /*!< ADC analog watchdog 2 flag */
+#define ADC_ISR_AWD3_Pos (9U)
+#define ADC_ISR_AWD3_Msk (0x1UL << ADC_ISR_AWD3_Pos) /*!< 0x00000200 */
+#define ADC_ISR_AWD3 ADC_ISR_AWD3_Msk /*!< ADC analog watchdog 3 flag */
+#define ADC_ISR_JQOVF_Pos (10U)
+#define ADC_ISR_JQOVF_Msk (0x1UL << ADC_ISR_JQOVF_Pos) /*!< 0x00000400 */
+#define ADC_ISR_JQOVF ADC_ISR_JQOVF_Msk /*!< ADC group injected contexts queue overflow flag */
+
+/******************** Bit definition for ADC_IER register *******************/
+#define ADC_IER_ADRDYIE_Pos (0U)
+#define ADC_IER_ADRDYIE_Msk (0x1UL << ADC_IER_ADRDYIE_Pos) /*!< 0x00000001 */
+#define ADC_IER_ADRDYIE ADC_IER_ADRDYIE_Msk /*!< ADC ready interrupt */
+#define ADC_IER_EOSMPIE_Pos (1U)
+#define ADC_IER_EOSMPIE_Msk (0x1UL << ADC_IER_EOSMPIE_Pos) /*!< 0x00000002 */
+#define ADC_IER_EOSMPIE ADC_IER_EOSMPIE_Msk /*!< ADC group regular end of sampling interrupt */
+#define ADC_IER_EOCIE_Pos (2U)
+#define ADC_IER_EOCIE_Msk (0x1UL << ADC_IER_EOCIE_Pos) /*!< 0x00000004 */
+#define ADC_IER_EOCIE ADC_IER_EOCIE_Msk /*!< ADC group regular end of unitary conversion interrupt */
+#define ADC_IER_EOSIE_Pos (3U)
+#define ADC_IER_EOSIE_Msk (0x1UL << ADC_IER_EOSIE_Pos) /*!< 0x00000008 */
+#define ADC_IER_EOSIE ADC_IER_EOSIE_Msk /*!< ADC group regular end of sequence conversions interrupt */
+#define ADC_IER_OVRIE_Pos (4U)
+#define ADC_IER_OVRIE_Msk (0x1UL << ADC_IER_OVRIE_Pos) /*!< 0x00000010 */
+#define ADC_IER_OVRIE ADC_IER_OVRIE_Msk /*!< ADC group regular overrun interrupt */
+#define ADC_IER_JEOCIE_Pos (5U)
+#define ADC_IER_JEOCIE_Msk (0x1UL << ADC_IER_JEOCIE_Pos) /*!< 0x00000020 */
+#define ADC_IER_JEOCIE ADC_IER_JEOCIE_Msk /*!< ADC group injected end of unitary conversion interrupt */
+#define ADC_IER_JEOSIE_Pos (6U)
+#define ADC_IER_JEOSIE_Msk (0x1UL << ADC_IER_JEOSIE_Pos) /*!< 0x00000040 */
+#define ADC_IER_JEOSIE ADC_IER_JEOSIE_Msk /*!< ADC group injected end of sequence conversions interrupt */
+#define ADC_IER_AWD1IE_Pos (7U)
+#define ADC_IER_AWD1IE_Msk (0x1UL << ADC_IER_AWD1IE_Pos) /*!< 0x00000080 */
+#define ADC_IER_AWD1IE ADC_IER_AWD1IE_Msk /*!< ADC analog watchdog 1 interrupt */
+#define ADC_IER_AWD2IE_Pos (8U)
+#define ADC_IER_AWD2IE_Msk (0x1UL << ADC_IER_AWD2IE_Pos) /*!< 0x00000100 */
+#define ADC_IER_AWD2IE ADC_IER_AWD2IE_Msk /*!< ADC analog watchdog 2 interrupt */
+#define ADC_IER_AWD3IE_Pos (9U)
+#define ADC_IER_AWD3IE_Msk (0x1UL << ADC_IER_AWD3IE_Pos) /*!< 0x00000200 */
+#define ADC_IER_AWD3IE ADC_IER_AWD3IE_Msk /*!< ADC analog watchdog 3 interrupt */
+#define ADC_IER_JQOVFIE_Pos (10U)
+#define ADC_IER_JQOVFIE_Msk (0x1UL << ADC_IER_JQOVFIE_Pos) /*!< 0x00000400 */
+#define ADC_IER_JQOVFIE ADC_IER_JQOVFIE_Msk /*!< ADC group injected contexts queue overflow interrupt */
+
+/******************** Bit definition for ADC_CR register ********************/
+#define ADC_CR_ADEN_Pos (0U)
+#define ADC_CR_ADEN_Msk (0x1UL << ADC_CR_ADEN_Pos) /*!< 0x00000001 */
+#define ADC_CR_ADEN ADC_CR_ADEN_Msk /*!< ADC enable */
+#define ADC_CR_ADDIS_Pos (1U)
+#define ADC_CR_ADDIS_Msk (0x1UL << ADC_CR_ADDIS_Pos) /*!< 0x00000002 */
+#define ADC_CR_ADDIS ADC_CR_ADDIS_Msk /*!< ADC disable */
+#define ADC_CR_ADSTART_Pos (2U)
+#define ADC_CR_ADSTART_Msk (0x1UL << ADC_CR_ADSTART_Pos) /*!< 0x00000004 */
+#define ADC_CR_ADSTART ADC_CR_ADSTART_Msk /*!< ADC group regular conversion start */
+#define ADC_CR_JADSTART_Pos (3U)
+#define ADC_CR_JADSTART_Msk (0x1UL << ADC_CR_JADSTART_Pos) /*!< 0x00000008 */
+#define ADC_CR_JADSTART ADC_CR_JADSTART_Msk /*!< ADC group injected conversion start */
+#define ADC_CR_ADSTP_Pos (4U)
+#define ADC_CR_ADSTP_Msk (0x1UL << ADC_CR_ADSTP_Pos) /*!< 0x00000010 */
+#define ADC_CR_ADSTP ADC_CR_ADSTP_Msk /*!< ADC group regular conversion stop */
+#define ADC_CR_JADSTP_Pos (5U)
+#define ADC_CR_JADSTP_Msk (0x1UL << ADC_CR_JADSTP_Pos) /*!< 0x00000020 */
+#define ADC_CR_JADSTP ADC_CR_JADSTP_Msk /*!< ADC group injected conversion stop */
+#define ADC_CR_ADVREGEN_Pos (28U)
+#define ADC_CR_ADVREGEN_Msk (0x1UL << ADC_CR_ADVREGEN_Pos) /*!< 0x10000000 */
+#define ADC_CR_ADVREGEN ADC_CR_ADVREGEN_Msk /*!< ADC voltage regulator enable */
+#define ADC_CR_DEEPPWD_Pos (29U)
+#define ADC_CR_DEEPPWD_Msk (0x1UL << ADC_CR_DEEPPWD_Pos) /*!< 0x20000000 */
+#define ADC_CR_DEEPPWD ADC_CR_DEEPPWD_Msk /*!< ADC deep power down enable */
+#define ADC_CR_ADCALDIF_Pos (30U)
+#define ADC_CR_ADCALDIF_Msk (0x1UL << ADC_CR_ADCALDIF_Pos) /*!< 0x40000000 */
+#define ADC_CR_ADCALDIF ADC_CR_ADCALDIF_Msk /*!< ADC differential mode for calibration */
+#define ADC_CR_ADCAL_Pos (31U)
+#define ADC_CR_ADCAL_Msk (0x1UL << ADC_CR_ADCAL_Pos) /*!< 0x80000000 */
+#define ADC_CR_ADCAL ADC_CR_ADCAL_Msk /*!< ADC calibration */
+
+/******************** Bit definition for ADC_CFGR register ******************/
+#define ADC_CFGR_DMAEN_Pos (0U)
+#define ADC_CFGR_DMAEN_Msk (0x1UL << ADC_CFGR_DMAEN_Pos) /*!< 0x00000001 */
+#define ADC_CFGR_DMAEN ADC_CFGR_DMAEN_Msk /*!< ADC DMA transfer enable */
+#define ADC_CFGR_DMACFG_Pos (1U)
+#define ADC_CFGR_DMACFG_Msk (0x1UL << ADC_CFGR_DMACFG_Pos) /*!< 0x00000002 */
+#define ADC_CFGR_DMACFG ADC_CFGR_DMACFG_Msk /*!< ADC DMA transfer configuration */
+
+#define ADC_CFGR_RES_Pos (3U)
+#define ADC_CFGR_RES_Msk (0x3UL << ADC_CFGR_RES_Pos) /*!< 0x00000018 */
+#define ADC_CFGR_RES ADC_CFGR_RES_Msk /*!< ADC data resolution */
+#define ADC_CFGR_RES_0 (0x1UL << ADC_CFGR_RES_Pos) /*!< 0x00000008 */
+#define ADC_CFGR_RES_1 (0x2UL << ADC_CFGR_RES_Pos) /*!< 0x00000010 */
+
+#define ADC_CFGR_EXTSEL_Pos (5U)
+#define ADC_CFGR_EXTSEL_Msk (0x1FUL << ADC_CFGR_EXTSEL_Pos) /*!< 0x000003E0 */
+#define ADC_CFGR_EXTSEL ADC_CFGR_EXTSEL_Msk /*!< ADC group regular external trigger source */
+#define ADC_CFGR_EXTSEL_0 (0x1UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000020 */
+#define ADC_CFGR_EXTSEL_1 (0x2UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000040 */
+#define ADC_CFGR_EXTSEL_2 (0x4UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000080 */
+#define ADC_CFGR_EXTSEL_3 (0x8UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000100 */
+#define ADC_CFGR_EXTSEL_4 (0x10UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000200 */
+
+#define ADC_CFGR_EXTEN_Pos (10U)
+#define ADC_CFGR_EXTEN_Msk (0x3UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000C00 */
+#define ADC_CFGR_EXTEN ADC_CFGR_EXTEN_Msk /*!< ADC group regular external trigger polarity */
+#define ADC_CFGR_EXTEN_0 (0x1UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000400 */
+#define ADC_CFGR_EXTEN_1 (0x2UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000800 */
+
+#define ADC_CFGR_OVRMOD_Pos (12U)
+#define ADC_CFGR_OVRMOD_Msk (0x1UL << ADC_CFGR_OVRMOD_Pos) /*!< 0x00001000 */
+#define ADC_CFGR_OVRMOD ADC_CFGR_OVRMOD_Msk /*!< ADC group regular overrun configuration */
+#define ADC_CFGR_CONT_Pos (13U)
+#define ADC_CFGR_CONT_Msk (0x1UL << ADC_CFGR_CONT_Pos) /*!< 0x00002000 */
+#define ADC_CFGR_CONT ADC_CFGR_CONT_Msk /*!< ADC group regular continuous conversion mode */
+#define ADC_CFGR_AUTDLY_Pos (14U)
+#define ADC_CFGR_AUTDLY_Msk (0x1UL << ADC_CFGR_AUTDLY_Pos) /*!< 0x00004000 */
+#define ADC_CFGR_AUTDLY ADC_CFGR_AUTDLY_Msk /*!< ADC low power auto wait */
+#define ADC_CFGR_ALIGN_Pos (15U)
+#define ADC_CFGR_ALIGN_Msk (0x1UL << ADC_CFGR_ALIGN_Pos) /*!< 0x00008000 */
+#define ADC_CFGR_ALIGN ADC_CFGR_ALIGN_Msk /*!< ADC data alignement */
+#define ADC_CFGR_DISCEN_Pos (16U)
+#define ADC_CFGR_DISCEN_Msk (0x1UL << ADC_CFGR_DISCEN_Pos) /*!< 0x00010000 */
+#define ADC_CFGR_DISCEN ADC_CFGR_DISCEN_Msk /*!< ADC group regular sequencer discontinuous mode */
+
+#define ADC_CFGR_DISCNUM_Pos (17U)
+#define ADC_CFGR_DISCNUM_Msk (0x7UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x000E0000 */
+#define ADC_CFGR_DISCNUM ADC_CFGR_DISCNUM_Msk /*!< ADC group regular sequencer discontinuous number of ranks */
+#define ADC_CFGR_DISCNUM_0 (0x1UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00020000 */
+#define ADC_CFGR_DISCNUM_1 (0x2UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00040000 */
+#define ADC_CFGR_DISCNUM_2 (0x4UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00080000 */
+
+#define ADC_CFGR_JDISCEN_Pos (20U)
+#define ADC_CFGR_JDISCEN_Msk (0x1UL << ADC_CFGR_JDISCEN_Pos) /*!< 0x00100000 */
+#define ADC_CFGR_JDISCEN ADC_CFGR_JDISCEN_Msk /*!< ADC group injected sequencer discontinuous mode */
+#define ADC_CFGR_JQM_Pos (21U)
+#define ADC_CFGR_JQM_Msk (0x1UL << ADC_CFGR_JQM_Pos) /*!< 0x00200000 */
+#define ADC_CFGR_JQM ADC_CFGR_JQM_Msk /*!< ADC group injected contexts queue mode */
+#define ADC_CFGR_AWD1SGL_Pos (22U)
+#define ADC_CFGR_AWD1SGL_Msk (0x1UL << ADC_CFGR_AWD1SGL_Pos) /*!< 0x00400000 */
+#define ADC_CFGR_AWD1SGL ADC_CFGR_AWD1SGL_Msk /*!< ADC analog watchdog 1 monitoring a single channel or all channels */
+#define ADC_CFGR_AWD1EN_Pos (23U)
+#define ADC_CFGR_AWD1EN_Msk (0x1UL << ADC_CFGR_AWD1EN_Pos) /*!< 0x00800000 */
+#define ADC_CFGR_AWD1EN ADC_CFGR_AWD1EN_Msk /*!< ADC analog watchdog 1 enable on scope ADC group regular */
+#define ADC_CFGR_JAWD1EN_Pos (24U)
+#define ADC_CFGR_JAWD1EN_Msk (0x1UL << ADC_CFGR_JAWD1EN_Pos) /*!< 0x01000000 */
+#define ADC_CFGR_JAWD1EN ADC_CFGR_JAWD1EN_Msk /*!< ADC analog watchdog 1 enable on scope ADC group injected */
+#define ADC_CFGR_JAUTO_Pos (25U)
+#define ADC_CFGR_JAUTO_Msk (0x1UL << ADC_CFGR_JAUTO_Pos) /*!< 0x02000000 */
+#define ADC_CFGR_JAUTO ADC_CFGR_JAUTO_Msk /*!< ADC group injected automatic trigger mode */
+
+#define ADC_CFGR_AWD1CH_Pos (26U)
+#define ADC_CFGR_AWD1CH_Msk (0x1FUL << ADC_CFGR_AWD1CH_Pos) /*!< 0x7C000000 */
+#define ADC_CFGR_AWD1CH ADC_CFGR_AWD1CH_Msk /*!< ADC analog watchdog 1 monitored channel selection */
+#define ADC_CFGR_AWD1CH_0 (0x01UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x04000000 */
+#define ADC_CFGR_AWD1CH_1 (0x02UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x08000000 */
+#define ADC_CFGR_AWD1CH_2 (0x04UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x10000000 */
+#define ADC_CFGR_AWD1CH_3 (0x08UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x20000000 */
+#define ADC_CFGR_AWD1CH_4 (0x10UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x40000000 */
+
+#define ADC_CFGR_JQDIS_Pos (31U)
+#define ADC_CFGR_JQDIS_Msk (0x1UL << ADC_CFGR_JQDIS_Pos) /*!< 0x80000000 */
+#define ADC_CFGR_JQDIS ADC_CFGR_JQDIS_Msk /*!< ADC group injected contexts queue disable */
+
+/******************** Bit definition for ADC_CFGR2 register *****************/
+#define ADC_CFGR2_ROVSE_Pos (0U)
+#define ADC_CFGR2_ROVSE_Msk (0x1UL << ADC_CFGR2_ROVSE_Pos) /*!< 0x00000001 */
+#define ADC_CFGR2_ROVSE ADC_CFGR2_ROVSE_Msk /*!< ADC oversampler enable on scope ADC group regular */
+#define ADC_CFGR2_JOVSE_Pos (1U)
+#define ADC_CFGR2_JOVSE_Msk (0x1UL << ADC_CFGR2_JOVSE_Pos) /*!< 0x00000002 */
+#define ADC_CFGR2_JOVSE ADC_CFGR2_JOVSE_Msk /*!< ADC oversampler enable on scope ADC group injected */
+
+#define ADC_CFGR2_OVSR_Pos (2U)
+#define ADC_CFGR2_OVSR_Msk (0x7UL << ADC_CFGR2_OVSR_Pos) /*!< 0x0000001C */
+#define ADC_CFGR2_OVSR ADC_CFGR2_OVSR_Msk /*!< ADC oversampling ratio */
+#define ADC_CFGR2_OVSR_0 (0x1UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00000004 */
+#define ADC_CFGR2_OVSR_1 (0x2UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00000008 */
+#define ADC_CFGR2_OVSR_2 (0x4UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00000010 */
+
+#define ADC_CFGR2_OVSS_Pos (5U)
+#define ADC_CFGR2_OVSS_Msk (0xFUL << ADC_CFGR2_OVSS_Pos) /*!< 0x000001E0 */
+#define ADC_CFGR2_OVSS ADC_CFGR2_OVSS_Msk /*!< ADC oversampling shift */
+#define ADC_CFGR2_OVSS_0 (0x1UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000020 */
+#define ADC_CFGR2_OVSS_1 (0x2UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000040 */
+#define ADC_CFGR2_OVSS_2 (0x4UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000080 */
+#define ADC_CFGR2_OVSS_3 (0x8UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000100 */
+
+#define ADC_CFGR2_TROVS_Pos (9U)
+#define ADC_CFGR2_TROVS_Msk (0x1UL << ADC_CFGR2_TROVS_Pos) /*!< 0x00000200 */
+#define ADC_CFGR2_TROVS ADC_CFGR2_TROVS_Msk /*!< ADC oversampling discontinuous mode (triggered mode) for ADC group regular */
+#define ADC_CFGR2_ROVSM_Pos (10U)
+#define ADC_CFGR2_ROVSM_Msk (0x1UL << ADC_CFGR2_ROVSM_Pos) /*!< 0x00000400 */
+#define ADC_CFGR2_ROVSM ADC_CFGR2_ROVSM_Msk /*!< ADC oversampling mode managing interlaced conversions of ADC group regular and group injected */
+
+#define ADC_CFGR2_GCOMP_Pos (16U)
+#define ADC_CFGR2_GCOMP_Msk (0x1UL << ADC_CFGR2_GCOMP_Pos) /*!< 0x00010000 */
+#define ADC_CFGR2_GCOMP ADC_CFGR2_GCOMP_Msk /*!< ADC Gain Compensation mode */
+
+#define ADC_CFGR2_SWTRIG_Pos (25U)
+#define ADC_CFGR2_SWTRIG_Msk (0x1UL << ADC_CFGR2_SWTRIG_Pos) /*!< 0x02000000 */
+#define ADC_CFGR2_SWTRIG ADC_CFGR2_SWTRIG_Msk /*!< ADC Software Trigger Bit for Sample time control trigger mode */
+#define ADC_CFGR2_BULB_Pos (26U)
+#define ADC_CFGR2_BULB_Msk (0x1UL << ADC_CFGR2_BULB_Pos) /*!< 0x04000000 */
+#define ADC_CFGR2_BULB ADC_CFGR2_BULB_Msk /*!< ADC Bulb sampling mode */
+#define ADC_CFGR2_SMPTRIG_Pos (27U)
+#define ADC_CFGR2_SMPTRIG_Msk (0x1UL << ADC_CFGR2_SMPTRIG_Pos) /*!< 0x08000000 */
+#define ADC_CFGR2_SMPTRIG ADC_CFGR2_SMPTRIG_Msk /*!< ADC Sample Time Control Trigger mode */
+
+#define ADC_CFGR2_LFTRIG_Pos (29U)
+#define ADC_CFGR2_LFTRIG_Msk (0x1UL << ADC_CFGR2_LFTRIG_Pos) /*!< 0x20000000 */
+#define ADC_CFGR2_LFTRIG ADC_CFGR2_LFTRIG_Msk /*!< ADC Low Frequency Trigger */
+
+/******************** Bit definition for ADC_SMPR1 register *****************/
+#define ADC_SMPR1_SMP0_Pos (0U)
+#define ADC_SMPR1_SMP0_Msk (0x7UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000007 */
+#define ADC_SMPR1_SMP0 ADC_SMPR1_SMP0_Msk /*!< ADC channel 0 sampling time selection */
+#define ADC_SMPR1_SMP0_0 (0x1UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000001 */
+#define ADC_SMPR1_SMP0_1 (0x2UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000002 */
+#define ADC_SMPR1_SMP0_2 (0x4UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000004 */
+
+#define ADC_SMPR1_SMP1_Pos (3U)
+#define ADC_SMPR1_SMP1_Msk (0x7UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000038 */
+#define ADC_SMPR1_SMP1 ADC_SMPR1_SMP1_Msk /*!< ADC channel 1 sampling time selection */
+#define ADC_SMPR1_SMP1_0 (0x1UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000008 */
+#define ADC_SMPR1_SMP1_1 (0x2UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000010 */
+#define ADC_SMPR1_SMP1_2 (0x4UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000020 */
+
+#define ADC_SMPR1_SMP2_Pos (6U)
+#define ADC_SMPR1_SMP2_Msk (0x7UL << ADC_SMPR1_SMP2_Pos) /*!< 0x000001C0 */
+#define ADC_SMPR1_SMP2 ADC_SMPR1_SMP2_Msk /*!< ADC channel 2 sampling time selection */
+#define ADC_SMPR1_SMP2_0 (0x1UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000040 */
+#define ADC_SMPR1_SMP2_1 (0x2UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000080 */
+#define ADC_SMPR1_SMP2_2 (0x4UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000100 */
+
+#define ADC_SMPR1_SMP3_Pos (9U)
+#define ADC_SMPR1_SMP3_Msk (0x7UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000E00 */
+#define ADC_SMPR1_SMP3 ADC_SMPR1_SMP3_Msk /*!< ADC channel 3 sampling time selection */
+#define ADC_SMPR1_SMP3_0 (0x1UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000200 */
+#define ADC_SMPR1_SMP3_1 (0x2UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000400 */
+#define ADC_SMPR1_SMP3_2 (0x4UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000800 */
+
+#define ADC_SMPR1_SMP4_Pos (12U)
+#define ADC_SMPR1_SMP4_Msk (0x7UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00007000 */
+#define ADC_SMPR1_SMP4 ADC_SMPR1_SMP4_Msk /*!< ADC channel 4 sampling time selection */
+#define ADC_SMPR1_SMP4_0 (0x1UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00001000 */
+#define ADC_SMPR1_SMP4_1 (0x2UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00002000 */
+#define ADC_SMPR1_SMP4_2 (0x4UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00004000 */
+
+#define ADC_SMPR1_SMP5_Pos (15U)
+#define ADC_SMPR1_SMP5_Msk (0x7UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00038000 */
+#define ADC_SMPR1_SMP5 ADC_SMPR1_SMP5_Msk /*!< ADC channel 5 sampling time selection */
+#define ADC_SMPR1_SMP5_0 (0x1UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00008000 */
+#define ADC_SMPR1_SMP5_1 (0x2UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00010000 */
+#define ADC_SMPR1_SMP5_2 (0x4UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00020000 */
+
+#define ADC_SMPR1_SMP6_Pos (18U)
+#define ADC_SMPR1_SMP6_Msk (0x7UL << ADC_SMPR1_SMP6_Pos) /*!< 0x001C0000 */
+#define ADC_SMPR1_SMP6 ADC_SMPR1_SMP6_Msk /*!< ADC channel 6 sampling time selection */
+#define ADC_SMPR1_SMP6_0 (0x1UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00040000 */
+#define ADC_SMPR1_SMP6_1 (0x2UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00080000 */
+#define ADC_SMPR1_SMP6_2 (0x4UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00100000 */
+
+#define ADC_SMPR1_SMP7_Pos (21U)
+#define ADC_SMPR1_SMP7_Msk (0x7UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00E00000 */
+#define ADC_SMPR1_SMP7 ADC_SMPR1_SMP7_Msk /*!< ADC channel 7 sampling time selection */
+#define ADC_SMPR1_SMP7_0 (0x1UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00200000 */
+#define ADC_SMPR1_SMP7_1 (0x2UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00400000 */
+#define ADC_SMPR1_SMP7_2 (0x4UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00800000 */
+
+#define ADC_SMPR1_SMP8_Pos (24U)
+#define ADC_SMPR1_SMP8_Msk (0x7UL << ADC_SMPR1_SMP8_Pos) /*!< 0x07000000 */
+#define ADC_SMPR1_SMP8 ADC_SMPR1_SMP8_Msk /*!< ADC channel 8 sampling time selection */
+#define ADC_SMPR1_SMP8_0 (0x1UL << ADC_SMPR1_SMP8_Pos) /*!< 0x01000000 */
+#define ADC_SMPR1_SMP8_1 (0x2UL << ADC_SMPR1_SMP8_Pos) /*!< 0x02000000 */
+#define ADC_SMPR1_SMP8_2 (0x4UL << ADC_SMPR1_SMP8_Pos) /*!< 0x04000000 */
+
+#define ADC_SMPR1_SMP9_Pos (27U)
+#define ADC_SMPR1_SMP9_Msk (0x7UL << ADC_SMPR1_SMP9_Pos) /*!< 0x38000000 */
+#define ADC_SMPR1_SMP9 ADC_SMPR1_SMP9_Msk /*!< ADC channel 9 sampling time selection */
+#define ADC_SMPR1_SMP9_0 (0x1UL << ADC_SMPR1_SMP9_Pos) /*!< 0x08000000 */
+#define ADC_SMPR1_SMP9_1 (0x2UL << ADC_SMPR1_SMP9_Pos) /*!< 0x10000000 */
+#define ADC_SMPR1_SMP9_2 (0x4UL << ADC_SMPR1_SMP9_Pos) /*!< 0x20000000 */
+
+#define ADC_SMPR1_SMPPLUS_Pos (31U)
+#define ADC_SMPR1_SMPPLUS_Msk (0x1UL << ADC_SMPR1_SMPPLUS_Pos) /*!< 0x80000000 */
+#define ADC_SMPR1_SMPPLUS ADC_SMPR1_SMPPLUS_Msk /*!< ADC channels sampling time additional setting */
+
+/******************** Bit definition for ADC_SMPR2 register *****************/
+#define ADC_SMPR2_SMP10_Pos (0U)
+#define ADC_SMPR2_SMP10_Msk (0x7UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000007 */
+#define ADC_SMPR2_SMP10 ADC_SMPR2_SMP10_Msk /*!< ADC channel 10 sampling time selection */
+#define ADC_SMPR2_SMP10_0 (0x1UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000001 */
+#define ADC_SMPR2_SMP10_1 (0x2UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000002 */
+#define ADC_SMPR2_SMP10_2 (0x4UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000004 */
+
+#define ADC_SMPR2_SMP11_Pos (3U)
+#define ADC_SMPR2_SMP11_Msk (0x7UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000038 */
+#define ADC_SMPR2_SMP11 ADC_SMPR2_SMP11_Msk /*!< ADC channel 11 sampling time selection */
+#define ADC_SMPR2_SMP11_0 (0x1UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000008 */
+#define ADC_SMPR2_SMP11_1 (0x2UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000010 */
+#define ADC_SMPR2_SMP11_2 (0x4UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000020 */
+
+#define ADC_SMPR2_SMP12_Pos (6U)
+#define ADC_SMPR2_SMP12_Msk (0x7UL << ADC_SMPR2_SMP12_Pos) /*!< 0x000001C0 */
+#define ADC_SMPR2_SMP12 ADC_SMPR2_SMP12_Msk /*!< ADC channel 12 sampling time selection */
+#define ADC_SMPR2_SMP12_0 (0x1UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000040 */
+#define ADC_SMPR2_SMP12_1 (0x2UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000080 */
+#define ADC_SMPR2_SMP12_2 (0x4UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000100 */
+
+#define ADC_SMPR2_SMP13_Pos (9U)
+#define ADC_SMPR2_SMP13_Msk (0x7UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000E00 */
+#define ADC_SMPR2_SMP13 ADC_SMPR2_SMP13_Msk /*!< ADC channel 13 sampling time selection */
+#define ADC_SMPR2_SMP13_0 (0x1UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000200 */
+#define ADC_SMPR2_SMP13_1 (0x2UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000400 */
+#define ADC_SMPR2_SMP13_2 (0x4UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000800 */
+
+#define ADC_SMPR2_SMP14_Pos (12U)
+#define ADC_SMPR2_SMP14_Msk (0x7UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00007000 */
+#define ADC_SMPR2_SMP14 ADC_SMPR2_SMP14_Msk /*!< ADC channel 14 sampling time selection */
+#define ADC_SMPR2_SMP14_0 (0x1UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00001000 */
+#define ADC_SMPR2_SMP14_1 (0x2UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00002000 */
+#define ADC_SMPR2_SMP14_2 (0x4UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00004000 */
+
+#define ADC_SMPR2_SMP15_Pos (15U)
+#define ADC_SMPR2_SMP15_Msk (0x7UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00038000 */
+#define ADC_SMPR2_SMP15 ADC_SMPR2_SMP15_Msk /*!< ADC channel 15 sampling time selection */
+#define ADC_SMPR2_SMP15_0 (0x1UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00008000 */
+#define ADC_SMPR2_SMP15_1 (0x2UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00010000 */
+#define ADC_SMPR2_SMP15_2 (0x4UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00020000 */
+
+#define ADC_SMPR2_SMP16_Pos (18U)
+#define ADC_SMPR2_SMP16_Msk (0x7UL << ADC_SMPR2_SMP16_Pos) /*!< 0x001C0000 */
+#define ADC_SMPR2_SMP16 ADC_SMPR2_SMP16_Msk /*!< ADC channel 16 sampling time selection */
+#define ADC_SMPR2_SMP16_0 (0x1UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00040000 */
+#define ADC_SMPR2_SMP16_1 (0x2UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00080000 */
+#define ADC_SMPR2_SMP16_2 (0x4UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00100000 */
+
+#define ADC_SMPR2_SMP17_Pos (21U)
+#define ADC_SMPR2_SMP17_Msk (0x7UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00E00000 */
+#define ADC_SMPR2_SMP17 ADC_SMPR2_SMP17_Msk /*!< ADC channel 17 sampling time selection */
+#define ADC_SMPR2_SMP17_0 (0x1UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00200000 */
+#define ADC_SMPR2_SMP17_1 (0x2UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00400000 */
+#define ADC_SMPR2_SMP17_2 (0x4UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00800000 */
+
+#define ADC_SMPR2_SMP18_Pos (24U)
+#define ADC_SMPR2_SMP18_Msk (0x7UL << ADC_SMPR2_SMP18_Pos) /*!< 0x07000000 */
+#define ADC_SMPR2_SMP18 ADC_SMPR2_SMP18_Msk /*!< ADC channel 18 sampling time selection */
+#define ADC_SMPR2_SMP18_0 (0x1UL << ADC_SMPR2_SMP18_Pos) /*!< 0x01000000 */
+#define ADC_SMPR2_SMP18_1 (0x2UL << ADC_SMPR2_SMP18_Pos) /*!< 0x02000000 */
+#define ADC_SMPR2_SMP18_2 (0x4UL << ADC_SMPR2_SMP18_Pos) /*!< 0x04000000 */
+
+/******************** Bit definition for ADC_TR1 register *******************/
+#define ADC_TR1_LT1_Pos (0U)
+#define ADC_TR1_LT1_Msk (0xFFFUL << ADC_TR1_LT1_Pos) /*!< 0x00000FFF */
+#define ADC_TR1_LT1 ADC_TR1_LT1_Msk /*!< ADC analog watchdog 1 threshold low */
+
+#define ADC_TR1_AWDFILT_Pos (12U)
+#define ADC_TR1_AWDFILT_Msk (0x7UL << ADC_TR1_AWDFILT_Pos) /*!< 0x00007000 */
+#define ADC_TR1_AWDFILT ADC_TR1_AWDFILT_Msk /*!< ADC analog watchdog filtering parameter */
+#define ADC_TR1_AWDFILT_0 (0x1UL << ADC_TR1_AWDFILT_Pos) /*!< 0x00001000 */
+#define ADC_TR1_AWDFILT_1 (0x2UL << ADC_TR1_AWDFILT_Pos) /*!< 0x00002000 */
+#define ADC_TR1_AWDFILT_2 (0x4UL << ADC_TR1_AWDFILT_Pos) /*!< 0x00004000 */
+
+#define ADC_TR1_HT1_Pos (16U)
+#define ADC_TR1_HT1_Msk (0xFFFUL << ADC_TR1_HT1_Pos) /*!< 0x0FFF0000 */
+#define ADC_TR1_HT1 ADC_TR1_HT1_Msk /*!< ADC analog watchdog 1 threshold high */
+
+/******************** Bit definition for ADC_TR2 register *******************/
+#define ADC_TR2_LT2_Pos (0U)
+#define ADC_TR2_LT2_Msk (0xFFUL << ADC_TR2_LT2_Pos) /*!< 0x000000FF */
+#define ADC_TR2_LT2 ADC_TR2_LT2_Msk /*!< ADC analog watchdog 2 threshold low */
+
+#define ADC_TR2_HT2_Pos (16U)
+#define ADC_TR2_HT2_Msk (0xFFUL << ADC_TR2_HT2_Pos) /*!< 0x00FF0000 */
+#define ADC_TR2_HT2 ADC_TR2_HT2_Msk /*!< ADC analog watchdog 2 threshold high */
+
+/******************** Bit definition for ADC_TR3 register *******************/
+#define ADC_TR3_LT3_Pos (0U)
+#define ADC_TR3_LT3_Msk (0xFFUL << ADC_TR3_LT3_Pos) /*!< 0x000000FF */
+#define ADC_TR3_LT3 ADC_TR3_LT3_Msk /*!< ADC analog watchdog 3 threshold low */
+
+#define ADC_TR3_HT3_Pos (16U)
+#define ADC_TR3_HT3_Msk (0xFFUL << ADC_TR3_HT3_Pos) /*!< 0x00FF0000 */
+#define ADC_TR3_HT3 ADC_TR3_HT3_Msk /*!< ADC analog watchdog 3 threshold high */
+
+/******************** Bit definition for ADC_SQR1 register ******************/
+#define ADC_SQR1_L_Pos (0U)
+#define ADC_SQR1_L_Msk (0xFUL << ADC_SQR1_L_Pos) /*!< 0x0000000F */
+#define ADC_SQR1_L ADC_SQR1_L_Msk /*!< ADC group regular sequencer scan length */
+#define ADC_SQR1_L_0 (0x1UL << ADC_SQR1_L_Pos) /*!< 0x00000001 */
+#define ADC_SQR1_L_1 (0x2UL << ADC_SQR1_L_Pos) /*!< 0x00000002 */
+#define ADC_SQR1_L_2 (0x4UL << ADC_SQR1_L_Pos) /*!< 0x00000004 */
+#define ADC_SQR1_L_3 (0x8UL << ADC_SQR1_L_Pos) /*!< 0x00000008 */
+
+#define ADC_SQR1_SQ1_Pos (6U)
+#define ADC_SQR1_SQ1_Msk (0x1FUL << ADC_SQR1_SQ1_Pos) /*!< 0x000007C0 */
+#define ADC_SQR1_SQ1 ADC_SQR1_SQ1_Msk /*!< ADC group regular sequencer rank 1 */
+#define ADC_SQR1_SQ1_0 (0x01UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000040 */
+#define ADC_SQR1_SQ1_1 (0x02UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000080 */
+#define ADC_SQR1_SQ1_2 (0x04UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000100 */
+#define ADC_SQR1_SQ1_3 (0x08UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000200 */
+#define ADC_SQR1_SQ1_4 (0x10UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000400 */
+
+#define ADC_SQR1_SQ2_Pos (12U)
+#define ADC_SQR1_SQ2_Msk (0x1FUL << ADC_SQR1_SQ2_Pos) /*!< 0x0001F000 */
+#define ADC_SQR1_SQ2 ADC_SQR1_SQ2_Msk /*!< ADC group regular sequencer rank 2 */
+#define ADC_SQR1_SQ2_0 (0x01UL << ADC_SQR1_SQ2_Pos) /*!< 0x00001000 */
+#define ADC_SQR1_SQ2_1 (0x02UL << ADC_SQR1_SQ2_Pos) /*!< 0x00002000 */
+#define ADC_SQR1_SQ2_2 (0x04UL << ADC_SQR1_SQ2_Pos) /*!< 0x00004000 */
+#define ADC_SQR1_SQ2_3 (0x08UL << ADC_SQR1_SQ2_Pos) /*!< 0x00008000 */
+#define ADC_SQR1_SQ2_4 (0x10UL << ADC_SQR1_SQ2_Pos) /*!< 0x00010000 */
+
+#define ADC_SQR1_SQ3_Pos (18U)
+#define ADC_SQR1_SQ3_Msk (0x1FUL << ADC_SQR1_SQ3_Pos) /*!< 0x007C0000 */
+#define ADC_SQR1_SQ3 ADC_SQR1_SQ3_Msk /*!< ADC group regular sequencer rank 3 */
+#define ADC_SQR1_SQ3_0 (0x01UL << ADC_SQR1_SQ3_Pos) /*!< 0x00040000 */
+#define ADC_SQR1_SQ3_1 (0x02UL << ADC_SQR1_SQ3_Pos) /*!< 0x00080000 */
+#define ADC_SQR1_SQ3_2 (0x04UL << ADC_SQR1_SQ3_Pos) /*!< 0x00100000 */
+#define ADC_SQR1_SQ3_3 (0x08UL << ADC_SQR1_SQ3_Pos) /*!< 0x00200000 */
+#define ADC_SQR1_SQ3_4 (0x10UL<< ADC_SQR1_SQ3_Pos) /*!< 0x00400000 */
+
+#define ADC_SQR1_SQ4_Pos (24U)
+#define ADC_SQR1_SQ4_Msk (0x1FUL << ADC_SQR1_SQ4_Pos) /*!< 0x1F000000 */
+#define ADC_SQR1_SQ4 ADC_SQR1_SQ4_Msk /*!< ADC group regular sequencer rank 4 */
+#define ADC_SQR1_SQ4_0 (0x01UL << ADC_SQR1_SQ4_Pos) /*!< 0x01000000 */
+#define ADC_SQR1_SQ4_1 (0x02UL << ADC_SQR1_SQ4_Pos) /*!< 0x02000000 */
+#define ADC_SQR1_SQ4_2 (0x04UL << ADC_SQR1_SQ4_Pos) /*!< 0x04000000 */
+#define ADC_SQR1_SQ4_3 (0x08UL << ADC_SQR1_SQ4_Pos) /*!< 0x08000000 */
+#define ADC_SQR1_SQ4_4 (0x10UL << ADC_SQR1_SQ4_Pos) /*!< 0x10000000 */
+
+/******************** Bit definition for ADC_SQR2 register ******************/
+#define ADC_SQR2_SQ5_Pos (0U)
+#define ADC_SQR2_SQ5_Msk (0x1FUL << ADC_SQR2_SQ5_Pos) /*!< 0x0000001F */
+#define ADC_SQR2_SQ5 ADC_SQR2_SQ5_Msk /*!< ADC group regular sequencer rank 5 */
+#define ADC_SQR2_SQ5_0 (0x01UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000001 */
+#define ADC_SQR2_SQ5_1 (0x02UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000002 */
+#define ADC_SQR2_SQ5_2 (0x04UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000004 */
+#define ADC_SQR2_SQ5_3 (0x08UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000008 */
+#define ADC_SQR2_SQ5_4 (0x10UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000010 */
+
+#define ADC_SQR2_SQ6_Pos (6U)
+#define ADC_SQR2_SQ6_Msk (0x1FUL << ADC_SQR2_SQ6_Pos) /*!< 0x000007C0 */
+#define ADC_SQR2_SQ6 ADC_SQR2_SQ6_Msk /*!< ADC group regular sequencer rank 6 */
+#define ADC_SQR2_SQ6_0 (0x01UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000040 */
+#define ADC_SQR2_SQ6_1 (0x02UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000080 */
+#define ADC_SQR2_SQ6_2 (0x04UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000100 */
+#define ADC_SQR2_SQ6_3 (0x08UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000200 */
+#define ADC_SQR2_SQ6_4 (0x10UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000400 */
+
+#define ADC_SQR2_SQ7_Pos (12U)
+#define ADC_SQR2_SQ7_Msk (0x1FUL << ADC_SQR2_SQ7_Pos) /*!< 0x0001F000 */
+#define ADC_SQR2_SQ7 ADC_SQR2_SQ7_Msk /*!< ADC group regular sequencer rank 7 */
+#define ADC_SQR2_SQ7_0 (0x01UL << ADC_SQR2_SQ7_Pos) /*!< 0x00001000 */
+#define ADC_SQR2_SQ7_1 (0x02UL << ADC_SQR2_SQ7_Pos) /*!< 0x00002000 */
+#define ADC_SQR2_SQ7_2 (0x04UL << ADC_SQR2_SQ7_Pos) /*!< 0x00004000 */
+#define ADC_SQR2_SQ7_3 (0x08UL << ADC_SQR2_SQ7_Pos) /*!< 0x00008000 */
+#define ADC_SQR2_SQ7_4 (0x10UL << ADC_SQR2_SQ7_Pos) /*!< 0x00010000 */
+
+#define ADC_SQR2_SQ8_Pos (18U)
+#define ADC_SQR2_SQ8_Msk (0x1FUL << ADC_SQR2_SQ8_Pos) /*!< 0x007C0000 */
+#define ADC_SQR2_SQ8 ADC_SQR2_SQ8_Msk /*!< ADC group regular sequencer rank 8 */
+#define ADC_SQR2_SQ8_0 (0x01UL << ADC_SQR2_SQ8_Pos) /*!< 0x00040000 */
+#define ADC_SQR2_SQ8_1 (0x02UL << ADC_SQR2_SQ8_Pos) /*!< 0x00080000 */
+#define ADC_SQR2_SQ8_2 (0x04UL << ADC_SQR2_SQ8_Pos) /*!< 0x00100000 */
+#define ADC_SQR2_SQ8_3 (0x08UL << ADC_SQR2_SQ8_Pos) /*!< 0x00200000 */
+#define ADC_SQR2_SQ8_4 (0x10UL << ADC_SQR2_SQ8_Pos) /*!< 0x00400000 */
+
+#define ADC_SQR2_SQ9_Pos (24U)
+#define ADC_SQR2_SQ9_Msk (0x1FUL << ADC_SQR2_SQ9_Pos) /*!< 0x1F000000 */
+#define ADC_SQR2_SQ9 ADC_SQR2_SQ9_Msk /*!< ADC group regular sequencer rank 9 */
+#define ADC_SQR2_SQ9_0 (0x01UL << ADC_SQR2_SQ9_Pos) /*!< 0x01000000 */
+#define ADC_SQR2_SQ9_1 (0x02UL << ADC_SQR2_SQ9_Pos) /*!< 0x02000000 */
+#define ADC_SQR2_SQ9_2 (0x04UL << ADC_SQR2_SQ9_Pos) /*!< 0x04000000 */
+#define ADC_SQR2_SQ9_3 (0x08UL << ADC_SQR2_SQ9_Pos) /*!< 0x08000000 */
+#define ADC_SQR2_SQ9_4 (0x10UL << ADC_SQR2_SQ9_Pos) /*!< 0x10000000 */
+
+/******************** Bit definition for ADC_SQR3 register ******************/
+#define ADC_SQR3_SQ10_Pos (0U)
+#define ADC_SQR3_SQ10_Msk (0x1FUL << ADC_SQR3_SQ10_Pos) /*!< 0x0000001F */
+#define ADC_SQR3_SQ10 ADC_SQR3_SQ10_Msk /*!< ADC group regular sequencer rank 10 */
+#define ADC_SQR3_SQ10_0 (0x01UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000001 */
+#define ADC_SQR3_SQ10_1 (0x02UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000002 */
+#define ADC_SQR3_SQ10_2 (0x04UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000004 */
+#define ADC_SQR3_SQ10_3 (0x08UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000008 */
+#define ADC_SQR3_SQ10_4 (0x10UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000010 */
+
+#define ADC_SQR3_SQ11_Pos (6U)
+#define ADC_SQR3_SQ11_Msk (0x1FUL << ADC_SQR3_SQ11_Pos) /*!< 0x000007C0 */
+#define ADC_SQR3_SQ11 ADC_SQR3_SQ11_Msk /*!< ADC group regular sequencer rank 11 */
+#define ADC_SQR3_SQ11_0 (0x01UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000040 */
+#define ADC_SQR3_SQ11_1 (0x02UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000080 */
+#define ADC_SQR3_SQ11_2 (0x04UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000100 */
+#define ADC_SQR3_SQ11_3 (0x08UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000200 */
+#define ADC_SQR3_SQ11_4 (0x10UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000400 */
+
+#define ADC_SQR3_SQ12_Pos (12U)
+#define ADC_SQR3_SQ12_Msk (0x1FUL << ADC_SQR3_SQ12_Pos) /*!< 0x0001F000 */
+#define ADC_SQR3_SQ12 ADC_SQR3_SQ12_Msk /*!< ADC group regular sequencer rank 12 */
+#define ADC_SQR3_SQ12_0 (0x01UL << ADC_SQR3_SQ12_Pos) /*!< 0x00001000 */
+#define ADC_SQR3_SQ12_1 (0x02UL << ADC_SQR3_SQ12_Pos) /*!< 0x00002000 */
+#define ADC_SQR3_SQ12_2 (0x04UL << ADC_SQR3_SQ12_Pos) /*!< 0x00004000 */
+#define ADC_SQR3_SQ12_3 (0x08UL << ADC_SQR3_SQ12_Pos) /*!< 0x00008000 */
+#define ADC_SQR3_SQ12_4 (0x10UL << ADC_SQR3_SQ12_Pos) /*!< 0x00010000 */
+
+#define ADC_SQR3_SQ13_Pos (18U)
+#define ADC_SQR3_SQ13_Msk (0x1FUL << ADC_SQR3_SQ13_Pos) /*!< 0x007C0000 */
+#define ADC_SQR3_SQ13 ADC_SQR3_SQ13_Msk /*!< ADC group regular sequencer rank 13 */
+#define ADC_SQR3_SQ13_0 (0x01UL << ADC_SQR3_SQ13_Pos) /*!< 0x00040000 */
+#define ADC_SQR3_SQ13_1 (0x02UL << ADC_SQR3_SQ13_Pos) /*!< 0x00080000 */
+#define ADC_SQR3_SQ13_2 (0x04UL << ADC_SQR3_SQ13_Pos) /*!< 0x00100000 */
+#define ADC_SQR3_SQ13_3 (0x08UL << ADC_SQR3_SQ13_Pos) /*!< 0x00200000 */
+#define ADC_SQR3_SQ13_4 (0x10UL << ADC_SQR3_SQ13_Pos) /*!< 0x00400000 */
+
+#define ADC_SQR3_SQ14_Pos (24U)
+#define ADC_SQR3_SQ14_Msk (0x1FUL << ADC_SQR3_SQ14_Pos) /*!< 0x1F000000 */
+#define ADC_SQR3_SQ14 ADC_SQR3_SQ14_Msk /*!< ADC group regular sequencer rank 14 */
+#define ADC_SQR3_SQ14_0 (0x01UL << ADC_SQR3_SQ14_Pos) /*!< 0x01000000 */
+#define ADC_SQR3_SQ14_1 (0x02UL << ADC_SQR3_SQ14_Pos) /*!< 0x02000000 */
+#define ADC_SQR3_SQ14_2 (0x04UL << ADC_SQR3_SQ14_Pos) /*!< 0x04000000 */
+#define ADC_SQR3_SQ14_3 (0x08UL << ADC_SQR3_SQ14_Pos) /*!< 0x08000000 */
+#define ADC_SQR3_SQ14_4 (0x10UL << ADC_SQR3_SQ14_Pos) /*!< 0x10000000 */
+
+/******************** Bit definition for ADC_SQR4 register ******************/
+#define ADC_SQR4_SQ15_Pos (0U)
+#define ADC_SQR4_SQ15_Msk (0x1FUL << ADC_SQR4_SQ15_Pos) /*!< 0x0000001F */
+#define ADC_SQR4_SQ15 ADC_SQR4_SQ15_Msk /*!< ADC group regular sequencer rank 15 */
+#define ADC_SQR4_SQ15_0 (0x01UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000001 */
+#define ADC_SQR4_SQ15_1 (0x02UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000002 */
+#define ADC_SQR4_SQ15_2 (0x04UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000004 */
+#define ADC_SQR4_SQ15_3 (0x08UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000008 */
+#define ADC_SQR4_SQ15_4 (0x10UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000010 */
+
+#define ADC_SQR4_SQ16_Pos (6U)
+#define ADC_SQR4_SQ16_Msk (0x1FUL << ADC_SQR4_SQ16_Pos) /*!< 0x000007C0 */
+#define ADC_SQR4_SQ16 ADC_SQR4_SQ16_Msk /*!< ADC group regular sequencer rank 16 */
+#define ADC_SQR4_SQ16_0 (0x01UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000040 */
+#define ADC_SQR4_SQ16_1 (0x02UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000080 */
+#define ADC_SQR4_SQ16_2 (0x04UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000100 */
+#define ADC_SQR4_SQ16_3 (0x08UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000200 */
+#define ADC_SQR4_SQ16_4 (0x10UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000400 */
+
+/******************** Bit definition for ADC_DR register ********************/
+#define ADC_DR_RDATA_Pos (0U)
+#define ADC_DR_RDATA_Msk (0xFFFFUL << ADC_DR_RDATA_Pos) /*!< 0x0000FFFF */
+#define ADC_DR_RDATA ADC_DR_RDATA_Msk /*!< ADC group regular conversion data */
+
+/******************** Bit definition for ADC_JSQR register ******************/
+#define ADC_JSQR_JL_Pos (0U)
+#define ADC_JSQR_JL_Msk (0x3UL << ADC_JSQR_JL_Pos) /*!< 0x00000003 */
+#define ADC_JSQR_JL ADC_JSQR_JL_Msk /*!< ADC group injected sequencer scan length */
+#define ADC_JSQR_JL_0 (0x1UL << ADC_JSQR_JL_Pos) /*!< 0x00000001 */
+#define ADC_JSQR_JL_1 (0x2UL << ADC_JSQR_JL_Pos) /*!< 0x00000002 */
+
+#define ADC_JSQR_JEXTSEL_Pos (2U)
+#define ADC_JSQR_JEXTSEL_Msk (0x1FUL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x0000007C */
+#define ADC_JSQR_JEXTSEL ADC_JSQR_JEXTSEL_Msk /*!< ADC group injected external trigger source */
+#define ADC_JSQR_JEXTSEL_0 (0x1UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000004 */
+#define ADC_JSQR_JEXTSEL_1 (0x2UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000008 */
+#define ADC_JSQR_JEXTSEL_2 (0x4UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000010 */
+#define ADC_JSQR_JEXTSEL_3 (0x8UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000020 */
+#define ADC_JSQR_JEXTSEL_4 (0x10UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000040 */
+
+#define ADC_JSQR_JEXTEN_Pos (7U)
+#define ADC_JSQR_JEXTEN_Msk (0x3UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000180 */
+#define ADC_JSQR_JEXTEN ADC_JSQR_JEXTEN_Msk /*!< ADC group injected external trigger polarity */
+#define ADC_JSQR_JEXTEN_0 (0x1UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000080 */
+#define ADC_JSQR_JEXTEN_1 (0x2UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000100 */
+
+#define ADC_JSQR_JSQ1_Pos (9U)
+#define ADC_JSQR_JSQ1_Msk (0x1FUL << ADC_JSQR_JSQ1_Pos) /*!< 0x00003E00 */
+#define ADC_JSQR_JSQ1 ADC_JSQR_JSQ1_Msk /*!< ADC group injected sequencer rank 1 */
+#define ADC_JSQR_JSQ1_0 (0x01UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000200 */
+#define ADC_JSQR_JSQ1_1 (0x02UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000400 */
+#define ADC_JSQR_JSQ1_2 (0x04UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000800 */
+#define ADC_JSQR_JSQ1_3 (0x08UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00001000 */
+#define ADC_JSQR_JSQ1_4 (0x10UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00002000 */
+
+#define ADC_JSQR_JSQ2_Pos (15U)
+#define ADC_JSQR_JSQ2_Msk (0x1FUL << ADC_JSQR_JSQ2_Pos) /*!< 0x0007C000 */
+#define ADC_JSQR_JSQ2 ADC_JSQR_JSQ2_Msk /*!< ADC group injected sequencer rank 2 */
+#define ADC_JSQR_JSQ2_0 (0x01UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00004000 */
+#define ADC_JSQR_JSQ2_1 (0x02UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00008000 */
+#define ADC_JSQR_JSQ2_2 (0x04UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00010000 */
+#define ADC_JSQR_JSQ2_3 (0x08UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00020000 */
+#define ADC_JSQR_JSQ2_4 (0x10UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00040000 */
+
+#define ADC_JSQR_JSQ3_Pos (21U)
+#define ADC_JSQR_JSQ3_Msk (0x1FUL << ADC_JSQR_JSQ3_Pos) /*!< 0x03E00000 */
+#define ADC_JSQR_JSQ3 ADC_JSQR_JSQ3_Msk /*!< ADC group injected sequencer rank 3 */
+#define ADC_JSQR_JSQ3_0 (0x01UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00200000 */
+#define ADC_JSQR_JSQ3_1 (0x02UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00400000 */
+#define ADC_JSQR_JSQ3_2 (0x04UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00800000 */
+#define ADC_JSQR_JSQ3_3 (0x08UL << ADC_JSQR_JSQ3_Pos) /*!< 0x01000000 */
+#define ADC_JSQR_JSQ3_4 (0x10UL << ADC_JSQR_JSQ3_Pos) /*!< 0x02000000 */
+
+#define ADC_JSQR_JSQ4_Pos (27U)
+#define ADC_JSQR_JSQ4_Msk (0x1FUL << ADC_JSQR_JSQ4_Pos) /*!< 0xF8000000 */
+#define ADC_JSQR_JSQ4 ADC_JSQR_JSQ4_Msk /*!< ADC group injected sequencer rank 4 */
+#define ADC_JSQR_JSQ4_0 (0x01UL << ADC_JSQR_JSQ4_Pos) /*!< 0x08000000 */
+#define ADC_JSQR_JSQ4_1 (0x02UL << ADC_JSQR_JSQ4_Pos) /*!< 0x10000000 */
+#define ADC_JSQR_JSQ4_2 (0x04UL << ADC_JSQR_JSQ4_Pos) /*!< 0x20000000 */
+#define ADC_JSQR_JSQ4_3 (0x08UL << ADC_JSQR_JSQ4_Pos) /*!< 0x40000000 */
+#define ADC_JSQR_JSQ4_4 (0x10UL << ADC_JSQR_JSQ4_Pos) /*!< 0x80000000 */
+
+/******************** Bit definition for ADC_OFR1 register ******************/
+#define ADC_OFR1_OFFSET1_Pos (0U)
+#define ADC_OFR1_OFFSET1_Msk (0xFFFUL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000FFF */
+#define ADC_OFR1_OFFSET1 ADC_OFR1_OFFSET1_Msk /*!< ADC offset number 1 offset level */
+
+#define ADC_OFR1_OFFSETPOS_Pos (24U)
+#define ADC_OFR1_OFFSETPOS_Msk (0x1UL << ADC_OFR1_OFFSETPOS_Pos) /*!< 0x01000000 */
+#define ADC_OFR1_OFFSETPOS ADC_OFR1_OFFSETPOS_Msk /*!< ADC offset number 1 positive */
+#define ADC_OFR1_SATEN_Pos (25U)
+#define ADC_OFR1_SATEN_Msk (0x1UL << ADC_OFR1_SATEN_Pos) /*!< 0x02000000 */
+#define ADC_OFR1_SATEN ADC_OFR1_SATEN_Msk /*!< ADC offset number 1 saturation enable */
+
+#define ADC_OFR1_OFFSET1_CH_Pos (26U)
+#define ADC_OFR1_OFFSET1_CH_Msk (0x1FUL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x7C000000 */
+#define ADC_OFR1_OFFSET1_CH ADC_OFR1_OFFSET1_CH_Msk /*!< ADC offset number 1 channel selection */
+#define ADC_OFR1_OFFSET1_CH_0 (0x01UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x04000000 */
+#define ADC_OFR1_OFFSET1_CH_1 (0x02UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x08000000 */
+#define ADC_OFR1_OFFSET1_CH_2 (0x04UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x10000000 */
+#define ADC_OFR1_OFFSET1_CH_3 (0x08UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x20000000 */
+#define ADC_OFR1_OFFSET1_CH_4 (0x10UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x40000000 */
+
+#define ADC_OFR1_OFFSET1_EN_Pos (31U)
+#define ADC_OFR1_OFFSET1_EN_Msk (0x1UL << ADC_OFR1_OFFSET1_EN_Pos) /*!< 0x80000000 */
+#define ADC_OFR1_OFFSET1_EN ADC_OFR1_OFFSET1_EN_Msk /*!< ADC offset number 1 enable */
+
+/******************** Bit definition for ADC_OFR2 register ******************/
+#define ADC_OFR2_OFFSET2_Pos (0U)
+#define ADC_OFR2_OFFSET2_Msk (0xFFFUL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000FFF */
+#define ADC_OFR2_OFFSET2 ADC_OFR2_OFFSET2_Msk /*!< ADC offset number 2 offset level */
+
+#define ADC_OFR2_OFFSETPOS_Pos (24U)
+#define ADC_OFR2_OFFSETPOS_Msk (0x1UL << ADC_OFR2_OFFSETPOS_Pos) /*!< 0x01000000 */
+#define ADC_OFR2_OFFSETPOS ADC_OFR2_OFFSETPOS_Msk /*!< ADC offset number 2 positive */
+#define ADC_OFR2_SATEN_Pos (25U)
+#define ADC_OFR2_SATEN_Msk (0x1UL << ADC_OFR2_SATEN_Pos) /*!< 0x02000000 */
+#define ADC_OFR2_SATEN ADC_OFR2_SATEN_Msk /*!< ADC offset number 2 saturation enable */
+
+#define ADC_OFR2_OFFSET2_CH_Pos (26U)
+#define ADC_OFR2_OFFSET2_CH_Msk (0x1FUL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x7C000000 */
+#define ADC_OFR2_OFFSET2_CH ADC_OFR2_OFFSET2_CH_Msk /*!< ADC offset number 2 channel selection */
+#define ADC_OFR2_OFFSET2_CH_0 (0x01UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x04000000 */
+#define ADC_OFR2_OFFSET2_CH_1 (0x02UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x08000000 */
+#define ADC_OFR2_OFFSET2_CH_2 (0x04UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x10000000 */
+#define ADC_OFR2_OFFSET2_CH_3 (0x08UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x20000000 */
+#define ADC_OFR2_OFFSET2_CH_4 (0x10UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x40000000 */
+
+#define ADC_OFR2_OFFSET2_EN_Pos (31U)
+#define ADC_OFR2_OFFSET2_EN_Msk (0x1UL << ADC_OFR2_OFFSET2_EN_Pos) /*!< 0x80000000 */
+#define ADC_OFR2_OFFSET2_EN ADC_OFR2_OFFSET2_EN_Msk /*!< ADC offset number 2 enable */
+
+/******************** Bit definition for ADC_OFR3 register ******************/
+#define ADC_OFR3_OFFSET3_Pos (0U)
+#define ADC_OFR3_OFFSET3_Msk (0xFFFUL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000FFF */
+#define ADC_OFR3_OFFSET3 ADC_OFR3_OFFSET3_Msk /*!< ADC offset number 3 offset level */
+
+#define ADC_OFR3_OFFSETPOS_Pos (24U)
+#define ADC_OFR3_OFFSETPOS_Msk (0x1UL << ADC_OFR3_OFFSETPOS_Pos) /*!< 0x01000000 */
+#define ADC_OFR3_OFFSETPOS ADC_OFR3_OFFSETPOS_Msk /*!< ADC offset number 3 positive */
+#define ADC_OFR3_SATEN_Pos (25U)
+#define ADC_OFR3_SATEN_Msk (0x1UL << ADC_OFR3_SATEN_Pos) /*!< 0x02000000 */
+#define ADC_OFR3_SATEN ADC_OFR3_SATEN_Msk /*!< ADC offset number 3 saturation enable */
+
+#define ADC_OFR3_OFFSET3_CH_Pos (26U)
+#define ADC_OFR3_OFFSET3_CH_Msk (0x1FUL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x7C000000 */
+#define ADC_OFR3_OFFSET3_CH ADC_OFR3_OFFSET3_CH_Msk /*!< ADC offset number 3 channel selection */
+#define ADC_OFR3_OFFSET3_CH_0 (0x01UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x04000000 */
+#define ADC_OFR3_OFFSET3_CH_1 (0x02UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x08000000 */
+#define ADC_OFR3_OFFSET3_CH_2 (0x04UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x10000000 */
+#define ADC_OFR3_OFFSET3_CH_3 (0x08UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x20000000 */
+#define ADC_OFR3_OFFSET3_CH_4 (0x10UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x40000000 */
+
+#define ADC_OFR3_OFFSET3_EN_Pos (31U)
+#define ADC_OFR3_OFFSET3_EN_Msk (0x1UL << ADC_OFR3_OFFSET3_EN_Pos) /*!< 0x80000000 */
+#define ADC_OFR3_OFFSET3_EN ADC_OFR3_OFFSET3_EN_Msk /*!< ADC offset number 3 enable */
+
+/******************** Bit definition for ADC_OFR4 register ******************/
+#define ADC_OFR4_OFFSET4_Pos (0U)
+#define ADC_OFR4_OFFSET4_Msk (0xFFFUL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000FFF */
+#define ADC_OFR4_OFFSET4 ADC_OFR4_OFFSET4_Msk /*!< ADC offset number 4 offset level */
+
+#define ADC_OFR4_OFFSETPOS_Pos (24U)
+#define ADC_OFR4_OFFSETPOS_Msk (0x1UL << ADC_OFR4_OFFSETPOS_Pos) /*!< 0x01000000 */
+#define ADC_OFR4_OFFSETPOS ADC_OFR4_OFFSETPOS_Msk /*!< ADC offset number 4 positive */
+#define ADC_OFR4_SATEN_Pos (25U)
+#define ADC_OFR4_SATEN_Msk (0x1UL << ADC_OFR4_SATEN_Pos) /*!< 0x02000000 */
+#define ADC_OFR4_SATEN ADC_OFR4_SATEN_Msk /*!< ADC offset number 4 saturation enable */
+
+#define ADC_OFR4_OFFSET4_CH_Pos (26U)
+#define ADC_OFR4_OFFSET4_CH_Msk (0x1FUL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x7C000000 */
+#define ADC_OFR4_OFFSET4_CH ADC_OFR4_OFFSET4_CH_Msk /*!< ADC offset number 4 channel selection */
+#define ADC_OFR4_OFFSET4_CH_0 (0x01UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x04000000 */
+#define ADC_OFR4_OFFSET4_CH_1 (0x02UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x08000000 */
+#define ADC_OFR4_OFFSET4_CH_2 (0x04UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x10000000 */
+#define ADC_OFR4_OFFSET4_CH_3 (0x08UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x20000000 */
+#define ADC_OFR4_OFFSET4_CH_4 (0x10UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x40000000 */
+
+#define ADC_OFR4_OFFSET4_EN_Pos (31U)
+#define ADC_OFR4_OFFSET4_EN_Msk (0x1UL << ADC_OFR4_OFFSET4_EN_Pos) /*!< 0x80000000 */
+#define ADC_OFR4_OFFSET4_EN ADC_OFR4_OFFSET4_EN_Msk /*!< ADC offset number 4 enable */
+
+/******************** Bit definition for ADC_JDR1 register ******************/
+#define ADC_JDR1_JDATA_Pos (0U)
+#define ADC_JDR1_JDATA_Msk (0xFFFFUL << ADC_JDR1_JDATA_Pos) /*!< 0x0000FFFF */
+#define ADC_JDR1_JDATA ADC_JDR1_JDATA_Msk /*!< ADC group injected sequencer rank 1 conversion data */
+
+/******************** Bit definition for ADC_JDR2 register ******************/
+#define ADC_JDR2_JDATA_Pos (0U)
+#define ADC_JDR2_JDATA_Msk (0xFFFFUL << ADC_JDR2_JDATA_Pos) /*!< 0x0000FFFF */
+#define ADC_JDR2_JDATA ADC_JDR2_JDATA_Msk /*!< ADC group injected sequencer rank 2 conversion data */
+
+/******************** Bit definition for ADC_JDR3 register ******************/
+#define ADC_JDR3_JDATA_Pos (0U)
+#define ADC_JDR3_JDATA_Msk (0xFFFFUL << ADC_JDR3_JDATA_Pos) /*!< 0x0000FFFF */
+#define ADC_JDR3_JDATA ADC_JDR3_JDATA_Msk /*!< ADC group injected sequencer rank 3 conversion data */
+
+/******************** Bit definition for ADC_JDR4 register ******************/
+#define ADC_JDR4_JDATA_Pos (0U)
+#define ADC_JDR4_JDATA_Msk (0xFFFFUL << ADC_JDR4_JDATA_Pos) /*!< 0x0000FFFF */
+#define ADC_JDR4_JDATA ADC_JDR4_JDATA_Msk /*!< ADC group injected sequencer rank 4 conversion data */
+
+/******************** Bit definition for ADC_AWD2CR register ****************/
+#define ADC_AWD2CR_AWD2CH_Pos (0U)
+#define ADC_AWD2CR_AWD2CH_Msk (0x7FFFFUL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x0007FFFF */
+#define ADC_AWD2CR_AWD2CH ADC_AWD2CR_AWD2CH_Msk /*!< ADC analog watchdog 2 monitored channel selection */
+#define ADC_AWD2CR_AWD2CH_0 (0x00001UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000001 */
+#define ADC_AWD2CR_AWD2CH_1 (0x00002UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000002 */
+#define ADC_AWD2CR_AWD2CH_2 (0x00004UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000004 */
+#define ADC_AWD2CR_AWD2CH_3 (0x00008UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000008 */
+#define ADC_AWD2CR_AWD2CH_4 (0x00010UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000010 */
+#define ADC_AWD2CR_AWD2CH_5 (0x00020UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000020 */
+#define ADC_AWD2CR_AWD2CH_6 (0x00040UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000040 */
+#define ADC_AWD2CR_AWD2CH_7 (0x00080UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000080 */
+#define ADC_AWD2CR_AWD2CH_8 (0x00100UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000100 */
+#define ADC_AWD2CR_AWD2CH_9 (0x00200UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000200 */
+#define ADC_AWD2CR_AWD2CH_10 (0x00400UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000400 */
+#define ADC_AWD2CR_AWD2CH_11 (0x00800UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000800 */
+#define ADC_AWD2CR_AWD2CH_12 (0x01000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00001000 */
+#define ADC_AWD2CR_AWD2CH_13 (0x02000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00002000 */
+#define ADC_AWD2CR_AWD2CH_14 (0x04000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00004000 */
+#define ADC_AWD2CR_AWD2CH_15 (0x08000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00008000 */
+#define ADC_AWD2CR_AWD2CH_16 (0x10000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00010000 */
+#define ADC_AWD2CR_AWD2CH_17 (0x20000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00020000 */
+#define ADC_AWD2CR_AWD2CH_18 (0x40000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00040000 */
+
+/******************** Bit definition for ADC_AWD3CR register ****************/
+#define ADC_AWD3CR_AWD3CH_Pos (0U)
+#define ADC_AWD3CR_AWD3CH_Msk (0x7FFFFUL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x0007FFFF */
+#define ADC_AWD3CR_AWD3CH ADC_AWD3CR_AWD3CH_Msk /*!< ADC analog watchdog 3 monitored channel selection */
+#define ADC_AWD3CR_AWD3CH_0 (0x00001UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000001 */
+#define ADC_AWD3CR_AWD3CH_1 (0x00002UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000002 */
+#define ADC_AWD3CR_AWD3CH_2 (0x00004UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000004 */
+#define ADC_AWD3CR_AWD3CH_3 (0x00008UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000008 */
+#define ADC_AWD3CR_AWD3CH_4 (0x00010UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000010 */
+#define ADC_AWD3CR_AWD3CH_5 (0x00020UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000020 */
+#define ADC_AWD3CR_AWD3CH_6 (0x00040UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000040 */
+#define ADC_AWD3CR_AWD3CH_7 (0x00080UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000080 */
+#define ADC_AWD3CR_AWD3CH_8 (0x00100UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000100 */
+#define ADC_AWD3CR_AWD3CH_9 (0x00200UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000200 */
+#define ADC_AWD3CR_AWD3CH_10 (0x00400UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000400 */
+#define ADC_AWD3CR_AWD3CH_11 (0x00800UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000800 */
+#define ADC_AWD3CR_AWD3CH_12 (0x01000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00001000 */
+#define ADC_AWD3CR_AWD3CH_13 (0x02000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00002000 */
+#define ADC_AWD3CR_AWD3CH_14 (0x04000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00004000 */
+#define ADC_AWD3CR_AWD3CH_15 (0x08000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00008000 */
+#define ADC_AWD3CR_AWD3CH_16 (0x10000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00010000 */
+#define ADC_AWD3CR_AWD3CH_17 (0x20000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00020000 */
+#define ADC_AWD3CR_AWD3CH_18 (0x40000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00040000 */
+
+/******************** Bit definition for ADC_DIFSEL register ****************/
+#define ADC_DIFSEL_DIFSEL_Pos (0U)
+#define ADC_DIFSEL_DIFSEL_Msk (0x7FFFFUL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x0007FFFF */
+#define ADC_DIFSEL_DIFSEL ADC_DIFSEL_DIFSEL_Msk /*!< ADC channel differential or single-ended mode */
+#define ADC_DIFSEL_DIFSEL_0 (0x00001UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000001 */
+#define ADC_DIFSEL_DIFSEL_1 (0x00002UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000002 */
+#define ADC_DIFSEL_DIFSEL_2 (0x00004UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000004 */
+#define ADC_DIFSEL_DIFSEL_3 (0x00008UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000008 */
+#define ADC_DIFSEL_DIFSEL_4 (0x00010UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000010 */
+#define ADC_DIFSEL_DIFSEL_5 (0x00020UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000020 */
+#define ADC_DIFSEL_DIFSEL_6 (0x00040UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000040 */
+#define ADC_DIFSEL_DIFSEL_7 (0x00080UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000080 */
+#define ADC_DIFSEL_DIFSEL_8 (0x00100UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000100 */
+#define ADC_DIFSEL_DIFSEL_9 (0x00200UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000200 */
+#define ADC_DIFSEL_DIFSEL_10 (0x00400UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000400 */
+#define ADC_DIFSEL_DIFSEL_11 (0x00800UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000800 */
+#define ADC_DIFSEL_DIFSEL_12 (0x01000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00001000 */
+#define ADC_DIFSEL_DIFSEL_13 (0x02000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00002000 */
+#define ADC_DIFSEL_DIFSEL_14 (0x04000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00004000 */
+#define ADC_DIFSEL_DIFSEL_15 (0x08000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00008000 */
+#define ADC_DIFSEL_DIFSEL_16 (0x10000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00010000 */
+#define ADC_DIFSEL_DIFSEL_17 (0x20000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00020000 */
+#define ADC_DIFSEL_DIFSEL_18 (0x40000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00040000 */
+
+/******************** Bit definition for ADC_CALFACT register ***************/
+#define ADC_CALFACT_CALFACT_S_Pos (0U)
+#define ADC_CALFACT_CALFACT_S_Msk (0x7FUL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x0000007F */
+#define ADC_CALFACT_CALFACT_S ADC_CALFACT_CALFACT_S_Msk /*!< ADC calibration factor in single-ended mode */
+#define ADC_CALFACT_CALFACT_S_0 (0x01UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000001 */
+#define ADC_CALFACT_CALFACT_S_1 (0x02UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000002 */
+#define ADC_CALFACT_CALFACT_S_2 (0x04UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000004 */
+#define ADC_CALFACT_CALFACT_S_3 (0x08UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000008 */
+#define ADC_CALFACT_CALFACT_S_4 (0x10UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000010 */
+#define ADC_CALFACT_CALFACT_S_5 (0x20UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000020 */
+#define ADC_CALFACT_CALFACT_S_6 (0x40UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000030 */
+
+#define ADC_CALFACT_CALFACT_D_Pos (16U)
+#define ADC_CALFACT_CALFACT_D_Msk (0x7FUL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x007F0000 */
+#define ADC_CALFACT_CALFACT_D ADC_CALFACT_CALFACT_D_Msk /*!< ADC calibration factor in differential mode */
+#define ADC_CALFACT_CALFACT_D_0 (0x01UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00010000 */
+#define ADC_CALFACT_CALFACT_D_1 (0x02UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00020000 */
+#define ADC_CALFACT_CALFACT_D_2 (0x04UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00040000 */
+#define ADC_CALFACT_CALFACT_D_3 (0x08UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00080000 */
+#define ADC_CALFACT_CALFACT_D_4 (0x10UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00100000 */
+#define ADC_CALFACT_CALFACT_D_5 (0x20UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00200000 */
+#define ADC_CALFACT_CALFACT_D_6 (0x40UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00300000 */
+
+/******************** Bit definition for ADC_GCOMP register *****************/
+#define ADC_GCOMP_GCOMPCOEFF_Pos (0U)
+#define ADC_GCOMP_GCOMPCOEFF_Msk (0x3FFFUL << ADC_GCOMP_GCOMPCOEFF_Pos) /*!< 0x00003FFF */
+#define ADC_GCOMP_GCOMPCOEFF ADC_GCOMP_GCOMPCOEFF_Msk /*!< ADC Gain Compensation Coefficient */
+
+/************************* ADC Common registers *****************************/
+/******************** Bit definition for ADC_CSR register *******************/
+#define ADC_CSR_ADRDY_MST_Pos (0U)
+#define ADC_CSR_ADRDY_MST_Msk (0x1UL << ADC_CSR_ADRDY_MST_Pos) /*!< 0x00000001 */
+#define ADC_CSR_ADRDY_MST ADC_CSR_ADRDY_MST_Msk /*!< ADC multimode master ready flag */
+#define ADC_CSR_EOSMP_MST_Pos (1U)
+#define ADC_CSR_EOSMP_MST_Msk (0x1UL << ADC_CSR_EOSMP_MST_Pos) /*!< 0x00000002 */
+#define ADC_CSR_EOSMP_MST ADC_CSR_EOSMP_MST_Msk /*!< ADC multimode master group regular end of sampling flag */
+#define ADC_CSR_EOC_MST_Pos (2U)
+#define ADC_CSR_EOC_MST_Msk (0x1UL << ADC_CSR_EOC_MST_Pos) /*!< 0x00000004 */
+#define ADC_CSR_EOC_MST ADC_CSR_EOC_MST_Msk /*!< ADC multimode master group regular end of unitary conversion flag */
+#define ADC_CSR_EOS_MST_Pos (3U)
+#define ADC_CSR_EOS_MST_Msk (0x1UL << ADC_CSR_EOS_MST_Pos) /*!< 0x00000008 */
+#define ADC_CSR_EOS_MST ADC_CSR_EOS_MST_Msk /*!< ADC multimode master group regular end of sequence conversions flag */
+#define ADC_CSR_OVR_MST_Pos (4U)
+#define ADC_CSR_OVR_MST_Msk (0x1UL << ADC_CSR_OVR_MST_Pos) /*!< 0x00000010 */
+#define ADC_CSR_OVR_MST ADC_CSR_OVR_MST_Msk /*!< ADC multimode master group regular overrun flag */
+#define ADC_CSR_JEOC_MST_Pos (5U)
+#define ADC_CSR_JEOC_MST_Msk (0x1UL << ADC_CSR_JEOC_MST_Pos) /*!< 0x00000020 */
+#define ADC_CSR_JEOC_MST ADC_CSR_JEOC_MST_Msk /*!< ADC multimode master group injected end of unitary conversion flag */
+#define ADC_CSR_JEOS_MST_Pos (6U)
+#define ADC_CSR_JEOS_MST_Msk (0x1UL << ADC_CSR_JEOS_MST_Pos) /*!< 0x00000040 */
+#define ADC_CSR_JEOS_MST ADC_CSR_JEOS_MST_Msk /*!< ADC multimode master group injected end of sequence conversions flag */
+#define ADC_CSR_AWD1_MST_Pos (7U)
+#define ADC_CSR_AWD1_MST_Msk (0x1UL << ADC_CSR_AWD1_MST_Pos) /*!< 0x00000080 */
+#define ADC_CSR_AWD1_MST ADC_CSR_AWD1_MST_Msk /*!< ADC multimode master analog watchdog 1 flag */
+#define ADC_CSR_AWD2_MST_Pos (8U)
+#define ADC_CSR_AWD2_MST_Msk (0x1UL << ADC_CSR_AWD2_MST_Pos) /*!< 0x00000100 */
+#define ADC_CSR_AWD2_MST ADC_CSR_AWD2_MST_Msk /*!< ADC multimode master analog watchdog 2 flag */
+#define ADC_CSR_AWD3_MST_Pos (9U)
+#define ADC_CSR_AWD3_MST_Msk (0x1UL << ADC_CSR_AWD3_MST_Pos) /*!< 0x00000200 */
+#define ADC_CSR_AWD3_MST ADC_CSR_AWD3_MST_Msk /*!< ADC multimode master analog watchdog 3 flag */
+#define ADC_CSR_JQOVF_MST_Pos (10U)
+#define ADC_CSR_JQOVF_MST_Msk (0x1UL << ADC_CSR_JQOVF_MST_Pos) /*!< 0x00000400 */
+#define ADC_CSR_JQOVF_MST ADC_CSR_JQOVF_MST_Msk /*!< ADC multimode master group injected contexts queue overflow flag */
+
+#define ADC_CSR_ADRDY_SLV_Pos (16U)
+#define ADC_CSR_ADRDY_SLV_Msk (0x1UL << ADC_CSR_ADRDY_SLV_Pos) /*!< 0x00010000 */
+#define ADC_CSR_ADRDY_SLV ADC_CSR_ADRDY_SLV_Msk /*!< ADC multimode slave ready flag */
+#define ADC_CSR_EOSMP_SLV_Pos (17U)
+#define ADC_CSR_EOSMP_SLV_Msk (0x1UL << ADC_CSR_EOSMP_SLV_Pos) /*!< 0x00020000 */
+#define ADC_CSR_EOSMP_SLV ADC_CSR_EOSMP_SLV_Msk /*!< ADC multimode slave group regular end of sampling flag */
+#define ADC_CSR_EOC_SLV_Pos (18U)
+#define ADC_CSR_EOC_SLV_Msk (0x1UL << ADC_CSR_EOC_SLV_Pos) /*!< 0x00040000 */
+#define ADC_CSR_EOC_SLV ADC_CSR_EOC_SLV_Msk /*!< ADC multimode slave group regular end of unitary conversion flag */
+#define ADC_CSR_EOS_SLV_Pos (19U)
+#define ADC_CSR_EOS_SLV_Msk (0x1UL << ADC_CSR_EOS_SLV_Pos) /*!< 0x00080000 */
+#define ADC_CSR_EOS_SLV ADC_CSR_EOS_SLV_Msk /*!< ADC multimode slave group regular end of sequence conversions flag */
+#define ADC_CSR_OVR_SLV_Pos (20U)
+#define ADC_CSR_OVR_SLV_Msk (0x1UL << ADC_CSR_OVR_SLV_Pos) /*!< 0x00100000 */
+#define ADC_CSR_OVR_SLV ADC_CSR_OVR_SLV_Msk /*!< ADC multimode slave group regular overrun flag */
+#define ADC_CSR_JEOC_SLV_Pos (21U)
+#define ADC_CSR_JEOC_SLV_Msk (0x1UL << ADC_CSR_JEOC_SLV_Pos) /*!< 0x00200000 */
+#define ADC_CSR_JEOC_SLV ADC_CSR_JEOC_SLV_Msk /*!< ADC multimode slave group injected end of unitary conversion flag */
+#define ADC_CSR_JEOS_SLV_Pos (22U)
+#define ADC_CSR_JEOS_SLV_Msk (0x1UL << ADC_CSR_JEOS_SLV_Pos) /*!< 0x00400000 */
+#define ADC_CSR_JEOS_SLV ADC_CSR_JEOS_SLV_Msk /*!< ADC multimode slave group injected end of sequence conversions flag */
+#define ADC_CSR_AWD1_SLV_Pos (23U)
+#define ADC_CSR_AWD1_SLV_Msk (0x1UL << ADC_CSR_AWD1_SLV_Pos) /*!< 0x00800000 */
+#define ADC_CSR_AWD1_SLV ADC_CSR_AWD1_SLV_Msk /*!< ADC multimode slave analog watchdog 1 flag */
+#define ADC_CSR_AWD2_SLV_Pos (24U)
+#define ADC_CSR_AWD2_SLV_Msk (0x1UL << ADC_CSR_AWD2_SLV_Pos) /*!< 0x01000000 */
+#define ADC_CSR_AWD2_SLV ADC_CSR_AWD2_SLV_Msk /*!< ADC multimode slave analog watchdog 2 flag */
+#define ADC_CSR_AWD3_SLV_Pos (25U)
+#define ADC_CSR_AWD3_SLV_Msk (0x1UL << ADC_CSR_AWD3_SLV_Pos) /*!< 0x02000000 */
+#define ADC_CSR_AWD3_SLV ADC_CSR_AWD3_SLV_Msk /*!< ADC multimode slave analog watchdog 3 flag */
+#define ADC_CSR_JQOVF_SLV_Pos (26U)
+#define ADC_CSR_JQOVF_SLV_Msk (0x1UL << ADC_CSR_JQOVF_SLV_Pos) /*!< 0x04000000 */
+#define ADC_CSR_JQOVF_SLV ADC_CSR_JQOVF_SLV_Msk /*!< ADC multimode slave group injected contexts queue overflow flag */
+
+/******************** Bit definition for ADC_CCR register *******************/
+#define ADC_CCR_DUAL_Pos (0U)
+#define ADC_CCR_DUAL_Msk (0x1FUL << ADC_CCR_DUAL_Pos) /*!< 0x0000001F */
+#define ADC_CCR_DUAL ADC_CCR_DUAL_Msk /*!< ADC multimode mode selection */
+#define ADC_CCR_DUAL_0 (0x01UL << ADC_CCR_DUAL_Pos) /*!< 0x00000001 */
+#define ADC_CCR_DUAL_1 (0x02UL << ADC_CCR_DUAL_Pos) /*!< 0x00000002 */
+#define ADC_CCR_DUAL_2 (0x04UL << ADC_CCR_DUAL_Pos) /*!< 0x00000004 */
+#define ADC_CCR_DUAL_3 (0x08UL << ADC_CCR_DUAL_Pos) /*!< 0x00000008 */
+#define ADC_CCR_DUAL_4 (0x10UL << ADC_CCR_DUAL_Pos) /*!< 0x00000010 */
+
+#define ADC_CCR_DELAY_Pos (8U)
+#define ADC_CCR_DELAY_Msk (0xFUL << ADC_CCR_DELAY_Pos) /*!< 0x00000F00 */
+#define ADC_CCR_DELAY ADC_CCR_DELAY_Msk /*!< ADC multimode delay between 2 sampling phases */
+#define ADC_CCR_DELAY_0 (0x1UL << ADC_CCR_DELAY_Pos) /*!< 0x00000100 */
+#define ADC_CCR_DELAY_1 (0x2UL << ADC_CCR_DELAY_Pos) /*!< 0x00000200 */
+#define ADC_CCR_DELAY_2 (0x4UL << ADC_CCR_DELAY_Pos) /*!< 0x00000400 */
+#define ADC_CCR_DELAY_3 (0x8UL << ADC_CCR_DELAY_Pos) /*!< 0x00000800 */
+
+#define ADC_CCR_DMACFG_Pos (13U)
+#define ADC_CCR_DMACFG_Msk (0x1UL << ADC_CCR_DMACFG_Pos) /*!< 0x00002000 */
+#define ADC_CCR_DMACFG ADC_CCR_DMACFG_Msk /*!< ADC multimode DMA transfer configuration */
+
+#define ADC_CCR_MDMA_Pos (14U)
+#define ADC_CCR_MDMA_Msk (0x3UL << ADC_CCR_MDMA_Pos) /*!< 0x0000C000 */
+#define ADC_CCR_MDMA ADC_CCR_MDMA_Msk /*!< ADC multimode DMA transfer enable */
+#define ADC_CCR_MDMA_0 (0x1UL << ADC_CCR_MDMA_Pos) /*!< 0x00004000 */
+#define ADC_CCR_MDMA_1 (0x2UL << ADC_CCR_MDMA_Pos) /*!< 0x00008000 */
+
+#define ADC_CCR_CKMODE_Pos (16U)
+#define ADC_CCR_CKMODE_Msk (0x3UL << ADC_CCR_CKMODE_Pos) /*!< 0x00030000 */
+#define ADC_CCR_CKMODE ADC_CCR_CKMODE_Msk /*!< ADC common clock source and prescaler (prescaler only for clock source synchronous) */
+#define ADC_CCR_CKMODE_0 (0x1UL << ADC_CCR_CKMODE_Pos) /*!< 0x00010000 */
+#define ADC_CCR_CKMODE_1 (0x2UL << ADC_CCR_CKMODE_Pos) /*!< 0x00020000 */
+
+#define ADC_CCR_PRESC_Pos (18U)
+#define ADC_CCR_PRESC_Msk (0xFUL << ADC_CCR_PRESC_Pos) /*!< 0x003C0000 */
+#define ADC_CCR_PRESC ADC_CCR_PRESC_Msk /*!< ADC common clock prescaler, only for clock source asynchronous */
+#define ADC_CCR_PRESC_0 (0x1UL << ADC_CCR_PRESC_Pos) /*!< 0x00040000 */
+#define ADC_CCR_PRESC_1 (0x2UL << ADC_CCR_PRESC_Pos) /*!< 0x00080000 */
+#define ADC_CCR_PRESC_2 (0x4UL << ADC_CCR_PRESC_Pos) /*!< 0x00100000 */
+#define ADC_CCR_PRESC_3 (0x8UL << ADC_CCR_PRESC_Pos) /*!< 0x00200000 */
+
+#define ADC_CCR_VREFEN_Pos (22U)
+#define ADC_CCR_VREFEN_Msk (0x1UL << ADC_CCR_VREFEN_Pos) /*!< 0x00400000 */
+#define ADC_CCR_VREFEN ADC_CCR_VREFEN_Msk /*!< ADC internal path to VrefInt enable */
+#define ADC_CCR_VSENSESEL_Pos (23U)
+#define ADC_CCR_VSENSESEL_Msk (0x1UL << ADC_CCR_VSENSESEL_Pos) /*!< 0x00800000 */
+#define ADC_CCR_VSENSESEL ADC_CCR_VSENSESEL_Msk /*!< ADC internal path to temperature sensor enable */
+#define ADC_CCR_VBATSEL_Pos (24U)
+#define ADC_CCR_VBATSEL_Msk (0x1UL << ADC_CCR_VBATSEL_Pos) /*!< 0x01000000 */
+#define ADC_CCR_VBATSEL ADC_CCR_VBATSEL_Msk /*!< ADC internal path to battery voltage enable */
+
+/******************** Bit definition for ADC_CDR register *******************/
+#define ADC_CDR_RDATA_MST_Pos (0U)
+#define ADC_CDR_RDATA_MST_Msk (0xFFFFUL << ADC_CDR_RDATA_MST_Pos) /*!< 0x0000FFFF */
+#define ADC_CDR_RDATA_MST ADC_CDR_RDATA_MST_Msk /*!< ADC multimode master group regular conversion data */
+
+#define ADC_CDR_RDATA_SLV_Pos (16U)
+#define ADC_CDR_RDATA_SLV_Msk (0xFFFFUL << ADC_CDR_RDATA_SLV_Pos) /*!< 0xFFFF0000 */
+#define ADC_CDR_RDATA_SLV ADC_CDR_RDATA_SLV_Msk /*!< ADC multimode slave group regular conversion data */
+
+
+/******************************************************************************/
+/* */
+/* Analog Comparators (COMP) */
+/* */
+/******************************************************************************/
+/********************** Bit definition for COMP_CSR register ****************/
+#define COMP_CSR_EN_Pos (0U)
+#define COMP_CSR_EN_Msk (0x1UL << COMP_CSR_EN_Pos) /*!< 0x00000001 */
+#define COMP_CSR_EN COMP_CSR_EN_Msk /*!< Comparator enable */
+
+#define COMP_CSR_INMSEL_Pos (4U)
+#define COMP_CSR_INMSEL_Msk (0xFUL << COMP_CSR_INMSEL_Pos) /*!< 0x00000070 */
+#define COMP_CSR_INMSEL COMP_CSR_INMSEL_Msk /*!< Comparator input minus selection */
+#define COMP_CSR_INMSEL_0 (0x1UL << COMP_CSR_INMSEL_Pos) /*!< 0x00000010 */
+#define COMP_CSR_INMSEL_1 (0x2UL << COMP_CSR_INMSEL_Pos) /*!< 0x00000020 */
+#define COMP_CSR_INMSEL_2 (0x4UL << COMP_CSR_INMSEL_Pos) /*!< 0x00000040 */
+#define COMP_CSR_INMSEL_3 (0x8UL << COMP_CSR_INMSEL_Pos) /*!< 0x00000080 */
+
+#define COMP_CSR_INPSEL_Pos (8U)
+#define COMP_CSR_INPSEL_Msk (0x1UL << COMP_CSR_INPSEL_Pos) /*!< 0x00000100 */
+#define COMP_CSR_INPSEL COMP_CSR_INPSEL_Msk /*!< Comparator input plus selection */
+
+#define COMP_CSR_POLARITY_Pos (15U)
+#define COMP_CSR_POLARITY_Msk (0x1UL << COMP_CSR_POLARITY_Pos) /*!< 0x00008000 */
+#define COMP_CSR_POLARITY COMP_CSR_POLARITY_Msk /*!< Comparator output polarity */
+
+#define COMP_CSR_HYST_Pos (16U)
+#define COMP_CSR_HYST_Msk (0x7UL << COMP_CSR_HYST_Pos) /*!< 0x00070000 */
+#define COMP_CSR_HYST COMP_CSR_HYST_Msk /*!< Comparator hysteresis */
+#define COMP_CSR_HYST_0 (0x1UL << COMP_CSR_HYST_Pos) /*!< 0x00010000 */
+#define COMP_CSR_HYST_1 (0x2UL << COMP_CSR_HYST_Pos) /*!< 0x00020000 */
+#define COMP_CSR_HYST_2 (0x4UL << COMP_CSR_HYST_Pos) /*!< 0x00040000 */
+
+#define COMP_CSR_BLANKING_Pos (19U)
+#define COMP_CSR_BLANKING_Msk (0x7UL << COMP_CSR_BLANKING_Pos) /*!< 0x00380000 */
+#define COMP_CSR_BLANKING COMP_CSR_BLANKING_Msk /*!< Comparator blanking source */
+#define COMP_CSR_BLANKING_0 (0x1UL << COMP_CSR_BLANKING_Pos) /*!< 0x00080000 */
+#define COMP_CSR_BLANKING_1 (0x2UL << COMP_CSR_BLANKING_Pos) /*!< 0x00100000 */
+#define COMP_CSR_BLANKING_2 (0x4UL << COMP_CSR_BLANKING_Pos) /*!< 0x00200000 */
+
+#define COMP_CSR_BRGEN_Pos (22U)
+#define COMP_CSR_BRGEN_Msk (0x1UL << COMP_CSR_BRGEN_Pos) /*!< 0x00400000 */
+#define COMP_CSR_BRGEN COMP_CSR_BRGEN_Msk /*!< Comparator voltage scaler enable */
+
+#define COMP_CSR_SCALEN_Pos (23U)
+#define COMP_CSR_SCALEN_Msk (0x1UL << COMP_CSR_SCALEN_Pos) /*!< 0x00800000 */
+#define COMP_CSR_SCALEN COMP_CSR_SCALEN_Msk /*!< Comparator scaler bridge enable */
+
+#define COMP_CSR_VALUE_Pos (30U)
+#define COMP_CSR_VALUE_Msk (0x1UL << COMP_CSR_VALUE_Pos) /*!< 0x40000000 */
+#define COMP_CSR_VALUE COMP_CSR_VALUE_Msk /*!< Comparator output level */
+
+#define COMP_CSR_LOCK_Pos (31U)
+#define COMP_CSR_LOCK_Msk (0x1UL << COMP_CSR_LOCK_Pos) /*!< 0x80000000 */
+#define COMP_CSR_LOCK COMP_CSR_LOCK_Msk /*!< Comparator lock */
+
+/******************************************************************************/
+/* */
+/* CORDIC calculation unit */
+/* */
+/******************************************************************************/
+/******************* Bit definition for CORDIC_CSR register *****************/
+#define CORDIC_CSR_FUNC_Pos (0U)
+#define CORDIC_CSR_FUNC_Msk (0xFUL << CORDIC_CSR_FUNC_Pos) /*!< 0x0000000F */
+#define CORDIC_CSR_FUNC CORDIC_CSR_FUNC_Msk /*!< Function */
+#define CORDIC_CSR_FUNC_0 (0x1UL << CORDIC_CSR_FUNC_Pos) /*!< 0x00000001 */
+#define CORDIC_CSR_FUNC_1 (0x2UL << CORDIC_CSR_FUNC_Pos) /*!< 0x00000002 */
+#define CORDIC_CSR_FUNC_2 (0x4UL << CORDIC_CSR_FUNC_Pos) /*!< 0x00000004 */
+#define CORDIC_CSR_FUNC_3 (0x8UL << CORDIC_CSR_FUNC_Pos) /*!< 0x00000008 */
+#define CORDIC_CSR_PRECISION_Pos (4U)
+#define CORDIC_CSR_PRECISION_Msk (0xFUL << CORDIC_CSR_PRECISION_Pos) /*!< 0x000000F0 */
+#define CORDIC_CSR_PRECISION CORDIC_CSR_PRECISION_Msk /*!< Precision */
+#define CORDIC_CSR_PRECISION_0 (0x1UL << CORDIC_CSR_PRECISION_Pos) /*!< 0x00000010 */
+#define CORDIC_CSR_PRECISION_1 (0x2UL << CORDIC_CSR_PRECISION_Pos) /*!< 0x00000020 */
+#define CORDIC_CSR_PRECISION_2 (0x4UL << CORDIC_CSR_PRECISION_Pos) /*!< 0x00000040 */
+#define CORDIC_CSR_PRECISION_3 (0x8UL << CORDIC_CSR_PRECISION_Pos) /*!< 0x00000080 */
+#define CORDIC_CSR_SCALE_Pos (8U)
+#define CORDIC_CSR_SCALE_Msk (0x7UL << CORDIC_CSR_SCALE_Pos) /*!< 0x00000700 */
+#define CORDIC_CSR_SCALE CORDIC_CSR_SCALE_Msk /*!< Scaling factor */
+#define CORDIC_CSR_SCALE_0 (0x1UL << CORDIC_CSR_SCALE_Pos) /*!< 0x00000100 */
+#define CORDIC_CSR_SCALE_1 (0x2UL << CORDIC_CSR_SCALE_Pos) /*!< 0x00000200 */
+#define CORDIC_CSR_SCALE_2 (0x4UL << CORDIC_CSR_SCALE_Pos) /*!< 0x00000400 */
+#define CORDIC_CSR_IEN_Pos (16U)
+#define CORDIC_CSR_IEN_Msk (0x1UL << CORDIC_CSR_IEN_Pos) /*!< 0x00010000 */
+#define CORDIC_CSR_IEN CORDIC_CSR_IEN_Msk /*!< Interrupt Enable */
+#define CORDIC_CSR_DMAREN_Pos (17U)
+#define CORDIC_CSR_DMAREN_Msk (0x1UL << CORDIC_CSR_DMAREN_Pos) /*!< 0x00020000 */
+#define CORDIC_CSR_DMAREN CORDIC_CSR_DMAREN_Msk /*!< DMA Read channel Enable */
+#define CORDIC_CSR_DMAWEN_Pos (18U)
+#define CORDIC_CSR_DMAWEN_Msk (0x1UL << CORDIC_CSR_DMAWEN_Pos) /*!< 0x00040000 */
+#define CORDIC_CSR_DMAWEN CORDIC_CSR_DMAWEN_Msk /*!< DMA Write channel Enable */
+#define CORDIC_CSR_NRES_Pos (19U)
+#define CORDIC_CSR_NRES_Msk (0x1UL << CORDIC_CSR_NRES_Pos) /*!< 0x00080000 */
+#define CORDIC_CSR_NRES CORDIC_CSR_NRES_Msk /*!< Number of results in WDATA register */
+#define CORDIC_CSR_NARGS_Pos (20U)
+#define CORDIC_CSR_NARGS_Msk (0x1UL << CORDIC_CSR_NARGS_Pos) /*!< 0x00100000 */
+#define CORDIC_CSR_NARGS CORDIC_CSR_NARGS_Msk /*!< Number of arguments in RDATA register */
+#define CORDIC_CSR_RESSIZE_Pos (21U)
+#define CORDIC_CSR_RESSIZE_Msk (0x1UL << CORDIC_CSR_RESSIZE_Pos) /*!< 0x00200000 */
+#define CORDIC_CSR_RESSIZE CORDIC_CSR_RESSIZE_Msk /*!< Width of output data */
+#define CORDIC_CSR_ARGSIZE_Pos (22U)
+#define CORDIC_CSR_ARGSIZE_Msk (0x1UL << CORDIC_CSR_ARGSIZE_Pos) /*!< 0x00400000 */
+#define CORDIC_CSR_ARGSIZE CORDIC_CSR_ARGSIZE_Msk /*!< Width of input data */
+#define CORDIC_CSR_RRDY_Pos (31U)
+#define CORDIC_CSR_RRDY_Msk (0x1UL << CORDIC_CSR_RRDY_Pos) /*!< 0x80000000 */
+#define CORDIC_CSR_RRDY CORDIC_CSR_RRDY_Msk /*!< Result Ready Flag */
+
+/******************* Bit definition for CORDIC_WDATA register ***************/
+#define CORDIC_WDATA_ARG_Pos (0U)
+#define CORDIC_WDATA_ARG_Msk (0xFFFFFFFFUL << CORDIC_WDATA_ARG_Pos) /*!< 0xFFFFFFFF */
+#define CORDIC_WDATA_ARG CORDIC_WDATA_ARG_Msk /*!< Input Argument */
+
+/******************* Bit definition for CORDIC_RDATA register ***************/
+#define CORDIC_RDATA_RES_Pos (0U)
+#define CORDIC_RDATA_RES_Msk (0xFFFFFFFFUL << CORDIC_RDATA_RES_Pos) /*!< 0xFFFFFFFF */
+#define CORDIC_RDATA_RES CORDIC_RDATA_RES_Msk /*!< Output Result */
+
+
+/******************************************************************************/
+/* */
+/* CRC calculation unit */
+/* */
+/******************************************************************************/
+/******************* Bit definition for CRC_DR register *********************/
+#define CRC_DR_DR_Pos (0U)
+#define CRC_DR_DR_Msk (0xFFFFFFFFUL << CRC_DR_DR_Pos) /*!< 0xFFFFFFFF */
+#define CRC_DR_DR CRC_DR_DR_Msk /*!< Data register bits */
+
+/******************* Bit definition for CRC_IDR register ********************/
+#define CRC_IDR_IDR_Pos (0U)
+#define CRC_IDR_IDR_Msk (0xFFFFFFFFUL << CRC_IDR_IDR_Pos) /*!< 0xFFFFFFFF */
+#define CRC_IDR_IDR CRC_IDR_IDR_Msk /*!< General-purpose 32-bit data register bits */
+
+/******************** Bit definition for CRC_CR register ********************/
+#define CRC_CR_RESET_Pos (0U)
+#define CRC_CR_RESET_Msk (0x1UL << CRC_CR_RESET_Pos) /*!< 0x00000001 */
+#define CRC_CR_RESET CRC_CR_RESET_Msk /*!< RESET the CRC computation unit bit */
+#define CRC_CR_POLYSIZE_Pos (3U)
+#define CRC_CR_POLYSIZE_Msk (0x3UL << CRC_CR_POLYSIZE_Pos) /*!< 0x00000018 */
+#define CRC_CR_POLYSIZE CRC_CR_POLYSIZE_Msk /*!< Polynomial size bits */
+#define CRC_CR_POLYSIZE_0 (0x1UL << CRC_CR_POLYSIZE_Pos) /*!< 0x00000008 */
+#define CRC_CR_POLYSIZE_1 (0x2UL << CRC_CR_POLYSIZE_Pos) /*!< 0x00000010 */
+#define CRC_CR_REV_IN_Pos (5U)
+#define CRC_CR_REV_IN_Msk (0x3UL << CRC_CR_REV_IN_Pos) /*!< 0x00000060 */
+#define CRC_CR_REV_IN CRC_CR_REV_IN_Msk /*!< REV_IN Reverse Input Data bits */
+#define CRC_CR_REV_IN_0 (0x1UL << CRC_CR_REV_IN_Pos) /*!< 0x00000020 */
+#define CRC_CR_REV_IN_1 (0x2UL << CRC_CR_REV_IN_Pos) /*!< 0x00000040 */
+#define CRC_CR_REV_OUT_Pos (7U)
+#define CRC_CR_REV_OUT_Msk (0x1UL << CRC_CR_REV_OUT_Pos) /*!< 0x00000080 */
+#define CRC_CR_REV_OUT CRC_CR_REV_OUT_Msk /*!< REV_OUT Reverse Output Data bits */
+
+/******************* Bit definition for CRC_INIT register *******************/
+#define CRC_INIT_INIT_Pos (0U)
+#define CRC_INIT_INIT_Msk (0xFFFFFFFFUL << CRC_INIT_INIT_Pos) /*!< 0xFFFFFFFF */
+#define CRC_INIT_INIT CRC_INIT_INIT_Msk /*!< Initial CRC value bits */
+
+/******************* Bit definition for CRC_POL register ********************/
+#define CRC_POL_POL_Pos (0U)
+#define CRC_POL_POL_Msk (0xFFFFFFFFUL << CRC_POL_POL_Pos) /*!< 0xFFFFFFFF */
+#define CRC_POL_POL CRC_POL_POL_Msk /*!< Coefficients of the polynomial */
+
+/******************************************************************************/
+/* */
+/* CRS Clock Recovery System */
+/******************************************************************************/
+
+/******************* Bit definition for CRS_CR register *********************/
+#define CRS_CR_SYNCOKIE_Pos (0U)
+#define CRS_CR_SYNCOKIE_Msk (0x1UL << CRS_CR_SYNCOKIE_Pos) /*!< 0x00000001 */
+#define CRS_CR_SYNCOKIE CRS_CR_SYNCOKIE_Msk /*!< SYNC event OK interrupt enable */
+#define CRS_CR_SYNCWARNIE_Pos (1U)
+#define CRS_CR_SYNCWARNIE_Msk (0x1UL << CRS_CR_SYNCWARNIE_Pos) /*!< 0x00000002 */
+#define CRS_CR_SYNCWARNIE CRS_CR_SYNCWARNIE_Msk /*!< SYNC warning interrupt enable */
+#define CRS_CR_ERRIE_Pos (2U)
+#define CRS_CR_ERRIE_Msk (0x1UL << CRS_CR_ERRIE_Pos) /*!< 0x00000004 */
+#define CRS_CR_ERRIE CRS_CR_ERRIE_Msk /*!< SYNC error or trimming error interrupt enable */
+#define CRS_CR_ESYNCIE_Pos (3U)
+#define CRS_CR_ESYNCIE_Msk (0x1UL << CRS_CR_ESYNCIE_Pos) /*!< 0x00000008 */
+#define CRS_CR_ESYNCIE CRS_CR_ESYNCIE_Msk /*!< Expected SYNC interrupt enable */
+#define CRS_CR_CEN_Pos (5U)
+#define CRS_CR_CEN_Msk (0x1UL << CRS_CR_CEN_Pos) /*!< 0x00000020 */
+#define CRS_CR_CEN CRS_CR_CEN_Msk /*!< Frequency error counter enable */
+#define CRS_CR_AUTOTRIMEN_Pos (6U)
+#define CRS_CR_AUTOTRIMEN_Msk (0x1UL << CRS_CR_AUTOTRIMEN_Pos) /*!< 0x00000040 */
+#define CRS_CR_AUTOTRIMEN CRS_CR_AUTOTRIMEN_Msk /*!< Automatic trimming enable */
+#define CRS_CR_SWSYNC_Pos (7U)
+#define CRS_CR_SWSYNC_Msk (0x1UL << CRS_CR_SWSYNC_Pos) /*!< 0x00000080 */
+#define CRS_CR_SWSYNC CRS_CR_SWSYNC_Msk /*!< Generate software SYNC event */
+#define CRS_CR_TRIM_Pos (8U)
+#define CRS_CR_TRIM_Msk (0x7FUL << CRS_CR_TRIM_Pos) /*!< 0x00007F00 */
+#define CRS_CR_TRIM CRS_CR_TRIM_Msk /*!< HSI48 oscillator smooth trimming */
+
+/******************* Bit definition for CRS_CFGR register *********************/
+#define CRS_CFGR_RELOAD_Pos (0U)
+#define CRS_CFGR_RELOAD_Msk (0xFFFFUL << CRS_CFGR_RELOAD_Pos) /*!< 0x0000FFFF */
+#define CRS_CFGR_RELOAD CRS_CFGR_RELOAD_Msk /*!< Counter reload value */
+#define CRS_CFGR_FELIM_Pos (16U)
+#define CRS_CFGR_FELIM_Msk (0xFFUL << CRS_CFGR_FELIM_Pos) /*!< 0x00FF0000 */
+#define CRS_CFGR_FELIM CRS_CFGR_FELIM_Msk /*!< Frequency error limit */
+
+#define CRS_CFGR_SYNCDIV_Pos (24U)
+#define CRS_CFGR_SYNCDIV_Msk (0x7UL << CRS_CFGR_SYNCDIV_Pos) /*!< 0x07000000 */
+#define CRS_CFGR_SYNCDIV CRS_CFGR_SYNCDIV_Msk /*!< SYNC divider */
+#define CRS_CFGR_SYNCDIV_0 (0x1UL << CRS_CFGR_SYNCDIV_Pos) /*!< 0x01000000 */
+#define CRS_CFGR_SYNCDIV_1 (0x2UL << CRS_CFGR_SYNCDIV_Pos) /*!< 0x02000000 */
+#define CRS_CFGR_SYNCDIV_2 (0x4UL << CRS_CFGR_SYNCDIV_Pos) /*!< 0x04000000 */
+
+#define CRS_CFGR_SYNCSRC_Pos (28U)
+#define CRS_CFGR_SYNCSRC_Msk (0x3UL << CRS_CFGR_SYNCSRC_Pos) /*!< 0x30000000 */
+#define CRS_CFGR_SYNCSRC CRS_CFGR_SYNCSRC_Msk /*!< SYNC signal source selection */
+#define CRS_CFGR_SYNCSRC_0 (0x1UL << CRS_CFGR_SYNCSRC_Pos) /*!< 0x10000000 */
+#define CRS_CFGR_SYNCSRC_1 (0x2UL << CRS_CFGR_SYNCSRC_Pos) /*!< 0x20000000 */
+
+#define CRS_CFGR_SYNCPOL_Pos (31U)
+#define CRS_CFGR_SYNCPOL_Msk (0x1UL << CRS_CFGR_SYNCPOL_Pos) /*!< 0x80000000 */
+#define CRS_CFGR_SYNCPOL CRS_CFGR_SYNCPOL_Msk /*!< SYNC polarity selection */
+
+/******************* Bit definition for CRS_ISR register *********************/
+#define CRS_ISR_SYNCOKF_Pos (0U)
+#define CRS_ISR_SYNCOKF_Msk (0x1UL << CRS_ISR_SYNCOKF_Pos) /*!< 0x00000001 */
+#define CRS_ISR_SYNCOKF CRS_ISR_SYNCOKF_Msk /*!< SYNC event OK flag */
+#define CRS_ISR_SYNCWARNF_Pos (1U)
+#define CRS_ISR_SYNCWARNF_Msk (0x1UL << CRS_ISR_SYNCWARNF_Pos) /*!< 0x00000002 */
+#define CRS_ISR_SYNCWARNF CRS_ISR_SYNCWARNF_Msk /*!< SYNC warning flag */
+#define CRS_ISR_ERRF_Pos (2U)
+#define CRS_ISR_ERRF_Msk (0x1UL << CRS_ISR_ERRF_Pos) /*!< 0x00000004 */
+#define CRS_ISR_ERRF CRS_ISR_ERRF_Msk /*!< Error flag */
+#define CRS_ISR_ESYNCF_Pos (3U)
+#define CRS_ISR_ESYNCF_Msk (0x1UL << CRS_ISR_ESYNCF_Pos) /*!< 0x00000008 */
+#define CRS_ISR_ESYNCF CRS_ISR_ESYNCF_Msk /*!< Expected SYNC flag */
+#define CRS_ISR_SYNCERR_Pos (8U)
+#define CRS_ISR_SYNCERR_Msk (0x1UL << CRS_ISR_SYNCERR_Pos) /*!< 0x00000100 */
+#define CRS_ISR_SYNCERR CRS_ISR_SYNCERR_Msk /*!< SYNC error */
+#define CRS_ISR_SYNCMISS_Pos (9U)
+#define CRS_ISR_SYNCMISS_Msk (0x1UL << CRS_ISR_SYNCMISS_Pos) /*!< 0x00000200 */
+#define CRS_ISR_SYNCMISS CRS_ISR_SYNCMISS_Msk /*!< SYNC missed */
+#define CRS_ISR_TRIMOVF_Pos (10U)
+#define CRS_ISR_TRIMOVF_Msk (0x1UL << CRS_ISR_TRIMOVF_Pos) /*!< 0x00000400 */
+#define CRS_ISR_TRIMOVF CRS_ISR_TRIMOVF_Msk /*!< Trimming overflow or underflow */
+#define CRS_ISR_FEDIR_Pos (15U)
+#define CRS_ISR_FEDIR_Msk (0x1UL << CRS_ISR_FEDIR_Pos) /*!< 0x00008000 */
+#define CRS_ISR_FEDIR CRS_ISR_FEDIR_Msk /*!< Frequency error direction */
+#define CRS_ISR_FECAP_Pos (16U)
+#define CRS_ISR_FECAP_Msk (0xFFFFUL << CRS_ISR_FECAP_Pos) /*!< 0xFFFF0000 */
+#define CRS_ISR_FECAP CRS_ISR_FECAP_Msk /*!< Frequency error capture */
+
+/******************* Bit definition for CRS_ICR register *********************/
+#define CRS_ICR_SYNCOKC_Pos (0U)
+#define CRS_ICR_SYNCOKC_Msk (0x1UL << CRS_ICR_SYNCOKC_Pos) /*!< 0x00000001 */
+#define CRS_ICR_SYNCOKC CRS_ICR_SYNCOKC_Msk /*!< SYNC event OK clear flag */
+#define CRS_ICR_SYNCWARNC_Pos (1U)
+#define CRS_ICR_SYNCWARNC_Msk (0x1UL << CRS_ICR_SYNCWARNC_Pos) /*!< 0x00000002 */
+#define CRS_ICR_SYNCWARNC CRS_ICR_SYNCWARNC_Msk /*!< SYNC warning clear flag */
+#define CRS_ICR_ERRC_Pos (2U)
+#define CRS_ICR_ERRC_Msk (0x1UL << CRS_ICR_ERRC_Pos) /*!< 0x00000004 */
+#define CRS_ICR_ERRC CRS_ICR_ERRC_Msk /*!< Error clear flag */
+#define CRS_ICR_ESYNCC_Pos (3U)
+#define CRS_ICR_ESYNCC_Msk (0x1UL << CRS_ICR_ESYNCC_Pos) /*!< 0x00000008 */
+#define CRS_ICR_ESYNCC CRS_ICR_ESYNCC_Msk /*!< Expected SYNC clear flag */
+
+/******************************************************************************/
+/* */
+/* Digital to Analog Converter */
+/* */
+/******************************************************************************/
+/*
+ * @brief Specific device feature definitions (not present on all devices in the STM32G4 serie)
+ */
+ #define DAC_CHANNEL2_SUPPORT /*!< DAC feature available only on specific devices: DAC channel 2 available */
+
+/******************** Bit definition for DAC_CR register ********************/
+#define DAC_CR_EN1_Pos (0U)
+#define DAC_CR_EN1_Msk (0x1UL << DAC_CR_EN1_Pos) /*!< 0x00000001 */
+#define DAC_CR_EN1 DAC_CR_EN1_Msk /*!*/
+#define DAC_CR_CEN1_Pos (14U)
+#define DAC_CR_CEN1_Msk (0x1UL << DAC_CR_CEN1_Pos) /*!< 0x00004000 */
+#define DAC_CR_CEN1 DAC_CR_CEN1_Msk /*!*/
+
+#define DAC_CR_HFSEL_Pos (15U)
+#define DAC_CR_HFSEL_Msk (0x1UL << DAC_CR_HFSEL_Pos) /*!< 0x00008000 */
+#define DAC_CR_HFSEL DAC_CR_HFSEL_Msk /*!*/
+
+#define DAC_CR_EN2_Pos (16U)
+#define DAC_CR_EN2_Msk (0x1UL << DAC_CR_EN2_Pos) /*!< 0x00010000 */
+#define DAC_CR_EN2 DAC_CR_EN2_Msk /*!*/
+#define DAC_CR_CEN2_Pos (30U)
+#define DAC_CR_CEN2_Msk (0x1UL << DAC_CR_CEN2_Pos) /*!< 0x40000000 */
+#define DAC_CR_CEN2 DAC_CR_CEN2_Msk /*!*/
+
+/***************** Bit definition for DAC_SWTRIGR register ******************/
+#define DAC_SWTRIGR_SWTRIG1_Pos (0U)
+#define DAC_SWTRIGR_SWTRIG1_Msk (0x1UL << DAC_SWTRIGR_SWTRIG1_Pos) /*!< 0x00000001 */
+#define DAC_SWTRIGR_SWTRIG1 DAC_SWTRIGR_SWTRIG1_Msk /*! */
+
+/******************* Bit definition for HRTIM_CPT2R register ****************/
+#define HRTIM_CPT2R_CPT2R_Pos (0U)
+#define HRTIM_CPT2R_CPT2R_Msk (0x0000FFFFUL << HRTIM_CPT2R_CPT2R_Pos) /*!< 0x0000FFFF */
+#define HRTIM_CPT2R_CPT2R HRTIM_CPT2R_CPT2R_Msk /*!< Capture 2 Value */
+#define HRTIM_CPT2R_DIR_Pos (16U)
+#define HRTIM_CPT2R_DIR_Msk (0x1UL << HRTIM_CPT2R_DIR_Pos) /*!< 0x00010000 */
+#define HRTIM_CPT2R_DIR HRTIM_CPT2R_DIR_Msk /*!< Capture 2 direction */
+
+/******************** Bit definition for Slave Deadtime register **************/
+#define HRTIM_DTR_DTR_Pos (0U)
+#define HRTIM_DTR_DTR_Msk (0x1FFUL << HRTIM_DTR_DTR_Pos) /*!< 0x000001FF */
+#define HRTIM_DTR_DTR HRTIM_DTR_DTR_Msk /*!< Dead time rising value */
+#define HRTIM_DTR_DTR_0 (0x001UL << HRTIM_DTR_DTR_Pos) /*!< 0x00000001 */
+#define HRTIM_DTR_DTR_1 (0x002UL << HRTIM_DTR_DTR_Pos) /*!< 0x00000002 */
+#define HRTIM_DTR_DTR_2 (0x004UL << HRTIM_DTR_DTR_Pos) /*!< 0x00000004 */
+#define HRTIM_DTR_DTR_3 (0x008UL << HRTIM_DTR_DTR_Pos) /*!< 0x00000008 */
+#define HRTIM_DTR_DTR_4 (0x010UL << HRTIM_DTR_DTR_Pos) /*!< 0x00000010 */
+#define HRTIM_DTR_DTR_5 (0x020UL << HRTIM_DTR_DTR_Pos) /*!< 0x00000020 */
+#define HRTIM_DTR_DTR_6 (0x040UL << HRTIM_DTR_DTR_Pos) /*!< 0x00000040 */
+#define HRTIM_DTR_DTR_7 (0x080UL << HRTIM_DTR_DTR_Pos) /*!< 0x00000080 */
+#define HRTIM_DTR_DTR_8 (0x100UL << HRTIM_DTR_DTR_Pos) /*!< 0x00000100 */
+#define HRTIM_DTR_SDTR_Pos (9U)
+#define HRTIM_DTR_SDTR_Msk (0x1UL << HRTIM_DTR_SDTR_Pos) /*!< 0x00000200 */
+#define HRTIM_DTR_SDTR HRTIM_DTR_SDTR_Msk /*!< Sign dead time rising value */
+#define HRTIM_DTR_DTPRSC_Pos (10U)
+#define HRTIM_DTR_DTPRSC_Msk (0x7UL << HRTIM_DTR_DTPRSC_Pos) /*!< 0x00001C00 */
+#define HRTIM_DTR_DTPRSC HRTIM_DTR_DTPRSC_Msk /*!< Dead time prescaler */
+#define HRTIM_DTR_DTPRSC_0 (0x1UL << HRTIM_DTR_DTPRSC_Pos) /*!< 0x00000400 */
+#define HRTIM_DTR_DTPRSC_1 (0x2UL << HRTIM_DTR_DTPRSC_Pos) /*!< 0x00000800 */
+#define HRTIM_DTR_DTPRSC_2 (0x4UL << HRTIM_DTR_DTPRSC_Pos) /*!< 0x00001000 */
+#define HRTIM_DTR_DTRSLK_Pos (14U)
+#define HRTIM_DTR_DTRSLK_Msk (0x1UL << HRTIM_DTR_DTRSLK_Pos) /*!< 0x00004000 */
+#define HRTIM_DTR_DTRSLK HRTIM_DTR_DTRSLK_Msk /*!< Dead time rising sign lock */
+#define HRTIM_DTR_DTRLK_Pos (15U)
+#define HRTIM_DTR_DTRLK_Msk (0x1UL << HRTIM_DTR_DTRLK_Pos) /*!< 0x00008000 */
+#define HRTIM_DTR_DTRLK HRTIM_DTR_DTRLK_Msk /*!< Dead time rising lock */
+#define HRTIM_DTR_DTF_Pos (16U)
+#define HRTIM_DTR_DTF_Msk (0x1FFUL << HRTIM_DTR_DTF_Pos) /*!< 0x01FF0000 */
+#define HRTIM_DTR_DTF HRTIM_DTR_DTF_Msk /*!< Dead time falling value */
+#define HRTIM_DTR_DTF_0 (0x001UL << HRTIM_DTR_DTF_Pos) /*!< 0x00010000 */
+#define HRTIM_DTR_DTF_1 (0x002UL << HRTIM_DTR_DTF_Pos) /*!< 0x00020000 */
+#define HRTIM_DTR_DTF_2 (0x004UL << HRTIM_DTR_DTF_Pos) /*!< 0x00040000 */
+#define HRTIM_DTR_DTF_3 (0x008UL << HRTIM_DTR_DTF_Pos) /*!< 0x00080000 */
+#define HRTIM_DTR_DTF_4 (0x010UL << HRTIM_DTR_DTF_Pos) /*!< 0x00100000 */
+#define HRTIM_DTR_DTF_5 (0x020UL << HRTIM_DTR_DTF_Pos) /*!< 0x00200000 */
+#define HRTIM_DTR_DTF_6 (0x040UL << HRTIM_DTR_DTF_Pos) /*!< 0x00400000 */
+#define HRTIM_DTR_DTF_7 (0x080UL << HRTIM_DTR_DTF_Pos) /*!< 0x00800000 */
+#define HRTIM_DTR_DTF_8 (0x100UL << HRTIM_DTR_DTF_Pos) /*!< 0x01000000 */
+#define HRTIM_DTR_SDTF_Pos (25U)
+#define HRTIM_DTR_SDTF_Msk (0x1UL << HRTIM_DTR_SDTF_Pos) /*!< 0x02000000 */
+#define HRTIM_DTR_SDTF HRTIM_DTR_SDTF_Msk /*!< Sign dead time falling value */
+#define HRTIM_DTR_DTFSLK_Pos (30U)
+#define HRTIM_DTR_DTFSLK_Msk (0x1UL << HRTIM_DTR_DTFSLK_Pos) /*!< 0x40000000 */
+#define HRTIM_DTR_DTFSLK HRTIM_DTR_DTFSLK_Msk /*!< Dead time falling sign lock */
+#define HRTIM_DTR_DTFLK_Pos (31U)
+#define HRTIM_DTR_DTFLK_Msk (0x1UL << HRTIM_DTR_DTFLK_Pos) /*!< 0x80000000 */
+#define HRTIM_DTR_DTFLK HRTIM_DTR_DTFLK_Msk /*!< Dead time falling lock */
+
+/**** Bit definition for Slave Output 1 set register **************************/
+#define HRTIM_SET1R_SST_Pos (0U)
+#define HRTIM_SET1R_SST_Msk (0x1UL << HRTIM_SET1R_SST_Pos) /*!< 0x00000001 */
+#define HRTIM_SET1R_SST HRTIM_SET1R_SST_Msk /*!< software set trigger */
+#define HRTIM_SET1R_RESYNC_Pos (1U)
+#define HRTIM_SET1R_RESYNC_Msk (0x1UL << HRTIM_SET1R_RESYNC_Pos) /*!< 0x00000002 */
+#define HRTIM_SET1R_RESYNC HRTIM_SET1R_RESYNC_Msk /*!< Timer A resynchronization */
+#define HRTIM_SET1R_PER_Pos (2U)
+#define HRTIM_SET1R_PER_Msk (0x1UL << HRTIM_SET1R_PER_Pos) /*!< 0x00000004 */
+#define HRTIM_SET1R_PER HRTIM_SET1R_PER_Msk /*!< Timer A period */
+#define HRTIM_SET1R_CMP1_Pos (3U)
+#define HRTIM_SET1R_CMP1_Msk (0x1UL << HRTIM_SET1R_CMP1_Pos) /*!< 0x00000008 */
+#define HRTIM_SET1R_CMP1 HRTIM_SET1R_CMP1_Msk /*!< Timer A compare 1 */
+#define HRTIM_SET1R_CMP2_Pos (4U)
+#define HRTIM_SET1R_CMP2_Msk (0x1UL << HRTIM_SET1R_CMP2_Pos) /*!< 0x00000010 */
+#define HRTIM_SET1R_CMP2 HRTIM_SET1R_CMP2_Msk /*!< Timer A compare 2 */
+#define HRTIM_SET1R_CMP3_Pos (5U)
+#define HRTIM_SET1R_CMP3_Msk (0x1UL << HRTIM_SET1R_CMP3_Pos) /*!< 0x00000020 */
+#define HRTIM_SET1R_CMP3 HRTIM_SET1R_CMP3_Msk /*!< Timer A compare 3 */
+#define HRTIM_SET1R_CMP4_Pos (6U)
+#define HRTIM_SET1R_CMP4_Msk (0x1UL << HRTIM_SET1R_CMP4_Pos) /*!< 0x00000040 */
+#define HRTIM_SET1R_CMP4 HRTIM_SET1R_CMP4_Msk /*!< Timer A compare 4 */
+
+#define HRTIM_SET1R_MSTPER_Pos (7U)
+#define HRTIM_SET1R_MSTPER_Msk (0x1UL << HRTIM_SET1R_MSTPER_Pos) /*!< 0x00000080 */
+#define HRTIM_SET1R_MSTPER HRTIM_SET1R_MSTPER_Msk /*!< Master period */
+#define HRTIM_SET1R_MSTCMP1_Pos (8U)
+#define HRTIM_SET1R_MSTCMP1_Msk (0x1UL << HRTIM_SET1R_MSTCMP1_Pos) /*!< 0x00000100 */
+#define HRTIM_SET1R_MSTCMP1 HRTIM_SET1R_MSTCMP1_Msk /*!< Master compare 1 */
+#define HRTIM_SET1R_MSTCMP2_Pos (9U)
+#define HRTIM_SET1R_MSTCMP2_Msk (0x1UL << HRTIM_SET1R_MSTCMP2_Pos) /*!< 0x00000200 */
+#define HRTIM_SET1R_MSTCMP2 HRTIM_SET1R_MSTCMP2_Msk /*!< Master compare 2 */
+#define HRTIM_SET1R_MSTCMP3_Pos (10U)
+#define HRTIM_SET1R_MSTCMP3_Msk (0x1UL << HRTIM_SET1R_MSTCMP3_Pos) /*!< 0x00000400 */
+#define HRTIM_SET1R_MSTCMP3 HRTIM_SET1R_MSTCMP3_Msk /*!< Master compare 3 */
+#define HRTIM_SET1R_MSTCMP4_Pos (11U)
+#define HRTIM_SET1R_MSTCMP4_Msk (0x1UL << HRTIM_SET1R_MSTCMP4_Pos) /*!< 0x00000800 */
+#define HRTIM_SET1R_MSTCMP4 HRTIM_SET1R_MSTCMP4_Msk /*!< Master compare 4 */
+
+#define HRTIM_SET1R_TIMEVNT1_Pos (12U)
+#define HRTIM_SET1R_TIMEVNT1_Msk (0x1UL << HRTIM_SET1R_TIMEVNT1_Pos) /*!< 0x00001000 */
+#define HRTIM_SET1R_TIMEVNT1 HRTIM_SET1R_TIMEVNT1_Msk /*!< Timer event 1 */
+#define HRTIM_SET1R_TIMEVNT2_Pos (13U)
+#define HRTIM_SET1R_TIMEVNT2_Msk (0x1UL << HRTIM_SET1R_TIMEVNT2_Pos) /*!< 0x00002000 */
+#define HRTIM_SET1R_TIMEVNT2 HRTIM_SET1R_TIMEVNT2_Msk /*!< Timer event 2 */
+#define HRTIM_SET1R_TIMEVNT3_Pos (14U)
+#define HRTIM_SET1R_TIMEVNT3_Msk (0x1UL << HRTIM_SET1R_TIMEVNT3_Pos) /*!< 0x00004000 */
+#define HRTIM_SET1R_TIMEVNT3 HRTIM_SET1R_TIMEVNT3_Msk /*!< Timer event 3 */
+#define HRTIM_SET1R_TIMEVNT4_Pos (15U)
+#define HRTIM_SET1R_TIMEVNT4_Msk (0x1UL << HRTIM_SET1R_TIMEVNT4_Pos) /*!< 0x00008000 */
+#define HRTIM_SET1R_TIMEVNT4 HRTIM_SET1R_TIMEVNT4_Msk /*!< Timer event 4 */
+#define HRTIM_SET1R_TIMEVNT5_Pos (16U)
+#define HRTIM_SET1R_TIMEVNT5_Msk (0x1UL << HRTIM_SET1R_TIMEVNT5_Pos) /*!< 0x00010000 */
+#define HRTIM_SET1R_TIMEVNT5 HRTIM_SET1R_TIMEVNT5_Msk /*!< Timer event 5 */
+#define HRTIM_SET1R_TIMEVNT6_Pos (17U)
+#define HRTIM_SET1R_TIMEVNT6_Msk (0x1UL << HRTIM_SET1R_TIMEVNT6_Pos) /*!< 0x00020000 */
+#define HRTIM_SET1R_TIMEVNT6 HRTIM_SET1R_TIMEVNT6_Msk /*!< Timer event 6 */
+#define HRTIM_SET1R_TIMEVNT7_Pos (18U)
+#define HRTIM_SET1R_TIMEVNT7_Msk (0x1UL << HRTIM_SET1R_TIMEVNT7_Pos) /*!< 0x00040000 */
+#define HRTIM_SET1R_TIMEVNT7 HRTIM_SET1R_TIMEVNT7_Msk /*!< Timer event 7 */
+#define HRTIM_SET1R_TIMEVNT8_Pos (19U)
+#define HRTIM_SET1R_TIMEVNT8_Msk (0x1UL << HRTIM_SET1R_TIMEVNT8_Pos) /*!< 0x00080000 */
+#define HRTIM_SET1R_TIMEVNT8 HRTIM_SET1R_TIMEVNT8_Msk /*!< Timer event 8 */
+#define HRTIM_SET1R_TIMEVNT9_Pos (20U)
+#define HRTIM_SET1R_TIMEVNT9_Msk (0x1UL << HRTIM_SET1R_TIMEVNT9_Pos) /*!< 0x00100000 */
+#define HRTIM_SET1R_TIMEVNT9 HRTIM_SET1R_TIMEVNT9_Msk /*!< Timer event 9 */
+
+#define HRTIM_SET1R_EXTVNT1_Pos (21U)
+#define HRTIM_SET1R_EXTVNT1_Msk (0x1UL << HRTIM_SET1R_EXTVNT1_Pos) /*!< 0x00200000 */
+#define HRTIM_SET1R_EXTVNT1 HRTIM_SET1R_EXTVNT1_Msk /*!< External event 1 */
+#define HRTIM_SET1R_EXTVNT2_Pos (22U)
+#define HRTIM_SET1R_EXTVNT2_Msk (0x1UL << HRTIM_SET1R_EXTVNT2_Pos) /*!< 0x00400000 */
+#define HRTIM_SET1R_EXTVNT2 HRTIM_SET1R_EXTVNT2_Msk /*!< External event 2 */
+#define HRTIM_SET1R_EXTVNT3_Pos (23U)
+#define HRTIM_SET1R_EXTVNT3_Msk (0x1UL << HRTIM_SET1R_EXTVNT3_Pos) /*!< 0x00800000 */
+#define HRTIM_SET1R_EXTVNT3 HRTIM_SET1R_EXTVNT3_Msk /*!< External event 3 */
+#define HRTIM_SET1R_EXTVNT4_Pos (24U)
+#define HRTIM_SET1R_EXTVNT4_Msk (0x1UL << HRTIM_SET1R_EXTVNT4_Pos) /*!< 0x01000000 */
+#define HRTIM_SET1R_EXTVNT4 HRTIM_SET1R_EXTVNT4_Msk /*!< External event 4 */
+#define HRTIM_SET1R_EXTVNT5_Pos (25U)
+#define HRTIM_SET1R_EXTVNT5_Msk (0x1UL << HRTIM_SET1R_EXTVNT5_Pos) /*!< 0x02000000 */
+#define HRTIM_SET1R_EXTVNT5 HRTIM_SET1R_EXTVNT5_Msk /*!< External event 5 */
+#define HRTIM_SET1R_EXTVNT6_Pos (26U)
+#define HRTIM_SET1R_EXTVNT6_Msk (0x1UL << HRTIM_SET1R_EXTVNT6_Pos) /*!< 0x04000000 */
+#define HRTIM_SET1R_EXTVNT6 HRTIM_SET1R_EXTVNT6_Msk /*!< External event 6 */
+#define HRTIM_SET1R_EXTVNT7_Pos (27U)
+#define HRTIM_SET1R_EXTVNT7_Msk (0x1UL << HRTIM_SET1R_EXTVNT7_Pos) /*!< 0x08000000 */
+#define HRTIM_SET1R_EXTVNT7 HRTIM_SET1R_EXTVNT7_Msk /*!< External event 7 */
+#define HRTIM_SET1R_EXTVNT8_Pos (28U)
+#define HRTIM_SET1R_EXTVNT8_Msk (0x1UL << HRTIM_SET1R_EXTVNT8_Pos) /*!< 0x10000000 */
+#define HRTIM_SET1R_EXTVNT8 HRTIM_SET1R_EXTVNT8_Msk /*!< External event 8 */
+#define HRTIM_SET1R_EXTVNT9_Pos (29U)
+#define HRTIM_SET1R_EXTVNT9_Msk (0x1UL << HRTIM_SET1R_EXTVNT9_Pos) /*!< 0x20000000 */
+#define HRTIM_SET1R_EXTVNT9 HRTIM_SET1R_EXTVNT9_Msk /*!< External event 9 */
+#define HRTIM_SET1R_EXTVNT10_Pos (30U)
+#define HRTIM_SET1R_EXTVNT10_Msk (0x1UL << HRTIM_SET1R_EXTVNT10_Pos) /*!< 0x40000000 */
+#define HRTIM_SET1R_EXTVNT10 HRTIM_SET1R_EXTVNT10_Msk /*!< External event 10 */
+
+#define HRTIM_SET1R_UPDATE_Pos (31U)
+#define HRTIM_SET1R_UPDATE_Msk (0x1UL << HRTIM_SET1R_UPDATE_Pos) /*!< 0x80000000 */
+#define HRTIM_SET1R_UPDATE HRTIM_SET1R_UPDATE_Msk /*!< Register update (transfer preload to active) */
+
+/**** Bit definition for Slave Output 1 reset register ************************/
+#define HRTIM_RST1R_SRT_Pos (0U)
+#define HRTIM_RST1R_SRT_Msk (0x1UL << HRTIM_RST1R_SRT_Pos) /*!< 0x00000001 */
+#define HRTIM_RST1R_SRT HRTIM_RST1R_SRT_Msk /*!< software reset trigger */
+#define HRTIM_RST1R_RESYNC_Pos (1U)
+#define HRTIM_RST1R_RESYNC_Msk (0x1UL << HRTIM_RST1R_RESYNC_Pos) /*!< 0x00000002 */
+#define HRTIM_RST1R_RESYNC HRTIM_RST1R_RESYNC_Msk /*!< Timer A resynchronization */
+#define HRTIM_RST1R_PER_Pos (2U)
+#define HRTIM_RST1R_PER_Msk (0x1UL << HRTIM_RST1R_PER_Pos) /*!< 0x00000004 */
+#define HRTIM_RST1R_PER HRTIM_RST1R_PER_Msk /*!< Timer A period */
+#define HRTIM_RST1R_CMP1_Pos (3U)
+#define HRTIM_RST1R_CMP1_Msk (0x1UL << HRTIM_RST1R_CMP1_Pos) /*!< 0x00000008 */
+#define HRTIM_RST1R_CMP1 HRTIM_RST1R_CMP1_Msk /*!< Timer A compare 1 */
+#define HRTIM_RST1R_CMP2_Pos (4U)
+#define HRTIM_RST1R_CMP2_Msk (0x1UL << HRTIM_RST1R_CMP2_Pos) /*!< 0x00000010 */
+#define HRTIM_RST1R_CMP2 HRTIM_RST1R_CMP2_Msk /*!< Timer A compare 2 */
+#define HRTIM_RST1R_CMP3_Pos (5U)
+#define HRTIM_RST1R_CMP3_Msk (0x1UL << HRTIM_RST1R_CMP3_Pos) /*!< 0x00000020 */
+#define HRTIM_RST1R_CMP3 HRTIM_RST1R_CMP3_Msk /*!< Timer A compare 3 */
+#define HRTIM_RST1R_CMP4_Pos (6U)
+#define HRTIM_RST1R_CMP4_Msk (0x1UL << HRTIM_RST1R_CMP4_Pos) /*!< 0x00000040 */
+#define HRTIM_RST1R_CMP4 HRTIM_RST1R_CMP4_Msk /*!< Timer A compare 4 */
+
+#define HRTIM_RST1R_MSTPER_Pos (7U)
+#define HRTIM_RST1R_MSTPER_Msk (0x1UL << HRTIM_RST1R_MSTPER_Pos) /*!< 0x00000080 */
+#define HRTIM_RST1R_MSTPER HRTIM_RST1R_MSTPER_Msk /*!< Master period */
+#define HRTIM_RST1R_MSTCMP1_Pos (8U)
+#define HRTIM_RST1R_MSTCMP1_Msk (0x1UL << HRTIM_RST1R_MSTCMP1_Pos) /*!< 0x00000100 */
+#define HRTIM_RST1R_MSTCMP1 HRTIM_RST1R_MSTCMP1_Msk /*!< Master compare 1 */
+#define HRTIM_RST1R_MSTCMP2_Pos (9U)
+#define HRTIM_RST1R_MSTCMP2_Msk (0x1UL << HRTIM_RST1R_MSTCMP2_Pos) /*!< 0x00000200 */
+#define HRTIM_RST1R_MSTCMP2 HRTIM_RST1R_MSTCMP2_Msk /*!< Master compare 2 */
+#define HRTIM_RST1R_MSTCMP3_Pos (10U)
+#define HRTIM_RST1R_MSTCMP3_Msk (0x1UL << HRTIM_RST1R_MSTCMP3_Pos) /*!< 0x00000400 */
+#define HRTIM_RST1R_MSTCMP3 HRTIM_RST1R_MSTCMP3_Msk /*!< Master compare 3 */
+#define HRTIM_RST1R_MSTCMP4_Pos (11U)
+#define HRTIM_RST1R_MSTCMP4_Msk (0x1UL << HRTIM_RST1R_MSTCMP4_Pos) /*!< 0x00000800 */
+#define HRTIM_RST1R_MSTCMP4 HRTIM_RST1R_MSTCMP4_Msk /*!< Master compare 4 */
+
+#define HRTIM_RST1R_TIMEVNT1_Pos (12U)
+#define HRTIM_RST1R_TIMEVNT1_Msk (0x1UL << HRTIM_RST1R_TIMEVNT1_Pos) /*!< 0x00001000 */
+#define HRTIM_RST1R_TIMEVNT1 HRTIM_RST1R_TIMEVNT1_Msk /*!< Timer event 1 */
+#define HRTIM_RST1R_TIMEVNT2_Pos (13U)
+#define HRTIM_RST1R_TIMEVNT2_Msk (0x1UL << HRTIM_RST1R_TIMEVNT2_Pos) /*!< 0x00002000 */
+#define HRTIM_RST1R_TIMEVNT2 HRTIM_RST1R_TIMEVNT2_Msk /*!< Timer event 2 */
+#define HRTIM_RST1R_TIMEVNT3_Pos (14U)
+#define HRTIM_RST1R_TIMEVNT3_Msk (0x1UL << HRTIM_RST1R_TIMEVNT3_Pos) /*!< 0x00004000 */
+#define HRTIM_RST1R_TIMEVNT3 HRTIM_RST1R_TIMEVNT3_Msk /*!< Timer event 3 */
+#define HRTIM_RST1R_TIMEVNT4_Pos (15U)
+#define HRTIM_RST1R_TIMEVNT4_Msk (0x1UL << HRTIM_RST1R_TIMEVNT4_Pos) /*!< 0x00008000 */
+#define HRTIM_RST1R_TIMEVNT4 HRTIM_RST1R_TIMEVNT4_Msk /*!< Timer event 4 */
+#define HRTIM_RST1R_TIMEVNT5_Pos (16U)
+#define HRTIM_RST1R_TIMEVNT5_Msk (0x1UL << HRTIM_RST1R_TIMEVNT5_Pos) /*!< 0x00010000 */
+#define HRTIM_RST1R_TIMEVNT5 HRTIM_RST1R_TIMEVNT5_Msk /*!< Timer event 5 */
+#define HRTIM_RST1R_TIMEVNT6_Pos (17U)
+#define HRTIM_RST1R_TIMEVNT6_Msk (0x1UL << HRTIM_RST1R_TIMEVNT6_Pos) /*!< 0x00020000 */
+#define HRTIM_RST1R_TIMEVNT6 HRTIM_RST1R_TIMEVNT6_Msk /*!< Timer event 6 */
+#define HRTIM_RST1R_TIMEVNT7_Pos (18U)
+#define HRTIM_RST1R_TIMEVNT7_Msk (0x1UL << HRTIM_RST1R_TIMEVNT7_Pos) /*!< 0x00040000 */
+#define HRTIM_RST1R_TIMEVNT7 HRTIM_RST1R_TIMEVNT7_Msk /*!< Timer event 7 */
+#define HRTIM_RST1R_TIMEVNT8_Pos (19U)
+#define HRTIM_RST1R_TIMEVNT8_Msk (0x1UL << HRTIM_RST1R_TIMEVNT8_Pos) /*!< 0x00080000 */
+#define HRTIM_RST1R_TIMEVNT8 HRTIM_RST1R_TIMEVNT8_Msk /*!< Timer event 8 */
+#define HRTIM_RST1R_TIMEVNT9_Pos (20U)
+#define HRTIM_RST1R_TIMEVNT9_Msk (0x1UL << HRTIM_RST1R_TIMEVNT9_Pos) /*!< 0x00100000 */
+#define HRTIM_RST1R_TIMEVNT9 HRTIM_RST1R_TIMEVNT9_Msk /*!< Timer event 9 */
+
+#define HRTIM_RST1R_EXTVNT1_Pos (21U)
+#define HRTIM_RST1R_EXTVNT1_Msk (0x1UL << HRTIM_RST1R_EXTVNT1_Pos) /*!< 0x00200000 */
+#define HRTIM_RST1R_EXTVNT1 HRTIM_RST1R_EXTVNT1_Msk /*!< External event 1 */
+#define HRTIM_RST1R_EXTVNT2_Pos (22U)
+#define HRTIM_RST1R_EXTVNT2_Msk (0x1UL << HRTIM_RST1R_EXTVNT2_Pos) /*!< 0x00400000 */
+#define HRTIM_RST1R_EXTVNT2 HRTIM_RST1R_EXTVNT2_Msk /*!< External event 2 */
+#define HRTIM_RST1R_EXTVNT3_Pos (23U)
+#define HRTIM_RST1R_EXTVNT3_Msk (0x1UL << HRTIM_RST1R_EXTVNT3_Pos) /*!< 0x00800000 */
+#define HRTIM_RST1R_EXTVNT3 HRTIM_RST1R_EXTVNT3_Msk /*!< External event 3 */
+#define HRTIM_RST1R_EXTVNT4_Pos (24U)
+#define HRTIM_RST1R_EXTVNT4_Msk (0x1UL << HRTIM_RST1R_EXTVNT4_Pos) /*!< 0x01000000 */
+#define HRTIM_RST1R_EXTVNT4 HRTIM_RST1R_EXTVNT4_Msk /*!< External event 4 */
+#define HRTIM_RST1R_EXTVNT5_Pos (25U)
+#define HRTIM_RST1R_EXTVNT5_Msk (0x1UL << HRTIM_RST1R_EXTVNT5_Pos) /*!< 0x02000000 */
+#define HRTIM_RST1R_EXTVNT5 HRTIM_RST1R_EXTVNT5_Msk /*!< External event 5 */
+#define HRTIM_RST1R_EXTVNT6_Pos (26U)
+#define HRTIM_RST1R_EXTVNT6_Msk (0x1UL << HRTIM_RST1R_EXTVNT6_Pos) /*!< 0x04000000 */
+#define HRTIM_RST1R_EXTVNT6 HRTIM_RST1R_EXTVNT6_Msk /*!< External event 6 */
+#define HRTIM_RST1R_EXTVNT7_Pos (27U)
+#define HRTIM_RST1R_EXTVNT7_Msk (0x1UL << HRTIM_RST1R_EXTVNT7_Pos) /*!< 0x08000000 */
+#define HRTIM_RST1R_EXTVNT7 HRTIM_RST1R_EXTVNT7_Msk /*!< External event 7 */
+#define HRTIM_RST1R_EXTVNT8_Pos (28U)
+#define HRTIM_RST1R_EXTVNT8_Msk (0x1UL << HRTIM_RST1R_EXTVNT8_Pos) /*!< 0x10000000 */
+#define HRTIM_RST1R_EXTVNT8 HRTIM_RST1R_EXTVNT8_Msk /*!< External event 8 */
+#define HRTIM_RST1R_EXTVNT9_Pos (29U)
+#define HRTIM_RST1R_EXTVNT9_Msk (0x1UL << HRTIM_RST1R_EXTVNT9_Pos) /*!< 0x20000000 */
+#define HRTIM_RST1R_EXTVNT9 HRTIM_RST1R_EXTVNT9_Msk /*!< External event 9 */
+#define HRTIM_RST1R_EXTVNT10_Pos (30U)
+#define HRTIM_RST1R_EXTVNT10_Msk (0x1UL << HRTIM_RST1R_EXTVNT10_Pos) /*!< 0x40000000 */
+#define HRTIM_RST1R_EXTVNT10 HRTIM_RST1R_EXTVNT10_Msk /*!< External event 10 */
+#define HRTIM_RST1R_UPDATE_Pos (31U)
+#define HRTIM_RST1R_UPDATE_Msk (0x1UL << HRTIM_RST1R_UPDATE_Pos) /*!< 0x80000000 */
+#define HRTIM_RST1R_UPDATE HRTIM_RST1R_UPDATE_Msk /*!< Register update (transfer preload to active) */
+
+/**** Bit definition for Slave Output 2 set register **************************/
+#define HRTIM_SET2R_SST_Pos (0U)
+#define HRTIM_SET2R_SST_Msk (0x1UL << HRTIM_SET2R_SST_Pos) /*!< 0x00000001 */
+#define HRTIM_SET2R_SST HRTIM_SET2R_SST_Msk /*!< software set trigger */
+#define HRTIM_SET2R_RESYNC_Pos (1U)
+#define HRTIM_SET2R_RESYNC_Msk (0x1UL << HRTIM_SET2R_RESYNC_Pos) /*!< 0x00000002 */
+#define HRTIM_SET2R_RESYNC HRTIM_SET2R_RESYNC_Msk /*!< Timer A resynchronization */
+#define HRTIM_SET2R_PER_Pos (2U)
+#define HRTIM_SET2R_PER_Msk (0x1UL << HRTIM_SET2R_PER_Pos) /*!< 0x00000004 */
+#define HRTIM_SET2R_PER HRTIM_SET2R_PER_Msk /*!< Timer A period */
+#define HRTIM_SET2R_CMP1_Pos (3U)
+#define HRTIM_SET2R_CMP1_Msk (0x1UL << HRTIM_SET2R_CMP1_Pos) /*!< 0x00000008 */
+#define HRTIM_SET2R_CMP1 HRTIM_SET2R_CMP1_Msk /*!< Timer A compare 1 */
+#define HRTIM_SET2R_CMP2_Pos (4U)
+#define HRTIM_SET2R_CMP2_Msk (0x1UL << HRTIM_SET2R_CMP2_Pos) /*!< 0x00000010 */
+#define HRTIM_SET2R_CMP2 HRTIM_SET2R_CMP2_Msk /*!< Timer A compare 2 */
+#define HRTIM_SET2R_CMP3_Pos (5U)
+#define HRTIM_SET2R_CMP3_Msk (0x1UL << HRTIM_SET2R_CMP3_Pos) /*!< 0x00000020 */
+#define HRTIM_SET2R_CMP3 HRTIM_SET2R_CMP3_Msk /*!< Timer A compare 3 */
+#define HRTIM_SET2R_CMP4_Pos (6U)
+#define HRTIM_SET2R_CMP4_Msk (0x1UL << HRTIM_SET2R_CMP4_Pos) /*!< 0x00000040 */
+#define HRTIM_SET2R_CMP4 HRTIM_SET2R_CMP4_Msk /*!< Timer A compare 4 */
+
+#define HRTIM_SET2R_MSTPER_Pos (7U)
+#define HRTIM_SET2R_MSTPER_Msk (0x1UL << HRTIM_SET2R_MSTPER_Pos) /*!< 0x00000080 */
+#define HRTIM_SET2R_MSTPER HRTIM_SET2R_MSTPER_Msk /*!< Master period */
+#define HRTIM_SET2R_MSTCMP1_Pos (8U)
+#define HRTIM_SET2R_MSTCMP1_Msk (0x1UL << HRTIM_SET2R_MSTCMP1_Pos) /*!< 0x00000100 */
+#define HRTIM_SET2R_MSTCMP1 HRTIM_SET2R_MSTCMP1_Msk /*!< Master compare 1 */
+#define HRTIM_SET2R_MSTCMP2_Pos (9U)
+#define HRTIM_SET2R_MSTCMP2_Msk (0x1UL << HRTIM_SET2R_MSTCMP2_Pos) /*!< 0x00000200 */
+#define HRTIM_SET2R_MSTCMP2 HRTIM_SET2R_MSTCMP2_Msk /*!< Master compare 2 */
+#define HRTIM_SET2R_MSTCMP3_Pos (10U)
+#define HRTIM_SET2R_MSTCMP3_Msk (0x1UL << HRTIM_SET2R_MSTCMP3_Pos) /*!< 0x00000400 */
+#define HRTIM_SET2R_MSTCMP3 HRTIM_SET2R_MSTCMP3_Msk /*!< Master compare 3 */
+#define HRTIM_SET2R_MSTCMP4_Pos (11U)
+#define HRTIM_SET2R_MSTCMP4_Msk (0x1UL << HRTIM_SET2R_MSTCMP4_Pos) /*!< 0x00000800 */
+#define HRTIM_SET2R_MSTCMP4 HRTIM_SET2R_MSTCMP4_Msk /*!< Master compare 4 */
+
+#define HRTIM_SET2R_TIMEVNT1_Pos (12U)
+#define HRTIM_SET2R_TIMEVNT1_Msk (0x1UL << HRTIM_SET2R_TIMEVNT1_Pos) /*!< 0x00001000 */
+#define HRTIM_SET2R_TIMEVNT1 HRTIM_SET2R_TIMEVNT1_Msk /*!< Timer event 1 */
+#define HRTIM_SET2R_TIMEVNT2_Pos (13U)
+#define HRTIM_SET2R_TIMEVNT2_Msk (0x1UL << HRTIM_SET2R_TIMEVNT2_Pos) /*!< 0x00002000 */
+#define HRTIM_SET2R_TIMEVNT2 HRTIM_SET2R_TIMEVNT2_Msk /*!< Timer event 2 */
+#define HRTIM_SET2R_TIMEVNT3_Pos (14U)
+#define HRTIM_SET2R_TIMEVNT3_Msk (0x1UL << HRTIM_SET2R_TIMEVNT3_Pos) /*!< 0x00004000 */
+#define HRTIM_SET2R_TIMEVNT3 HRTIM_SET2R_TIMEVNT3_Msk /*!< Timer event 3 */
+#define HRTIM_SET2R_TIMEVNT4_Pos (15U)
+#define HRTIM_SET2R_TIMEVNT4_Msk (0x1UL << HRTIM_SET2R_TIMEVNT4_Pos) /*!< 0x00008000 */
+#define HRTIM_SET2R_TIMEVNT4 HRTIM_SET2R_TIMEVNT4_Msk /*!< Timer event 4 */
+#define HRTIM_SET2R_TIMEVNT5_Pos (16U)
+#define HRTIM_SET2R_TIMEVNT5_Msk (0x1UL << HRTIM_SET2R_TIMEVNT5_Pos) /*!< 0x00010000 */
+#define HRTIM_SET2R_TIMEVNT5 HRTIM_SET2R_TIMEVNT5_Msk /*!< Timer event 5 */
+#define HRTIM_SET2R_TIMEVNT6_Pos (17U)
+#define HRTIM_SET2R_TIMEVNT6_Msk (0x1UL << HRTIM_SET2R_TIMEVNT6_Pos) /*!< 0x00020000 */
+#define HRTIM_SET2R_TIMEVNT6 HRTIM_SET2R_TIMEVNT6_Msk /*!< Timer event 6 */
+#define HRTIM_SET2R_TIMEVNT7_Pos (18U)
+#define HRTIM_SET2R_TIMEVNT7_Msk (0x1UL << HRTIM_SET2R_TIMEVNT7_Pos) /*!< 0x00040000 */
+#define HRTIM_SET2R_TIMEVNT7 HRTIM_SET2R_TIMEVNT7_Msk /*!< Timer event 7 */
+#define HRTIM_SET2R_TIMEVNT8_Pos (19U)
+#define HRTIM_SET2R_TIMEVNT8_Msk (0x1UL << HRTIM_SET2R_TIMEVNT8_Pos) /*!< 0x00080000 */
+#define HRTIM_SET2R_TIMEVNT8 HRTIM_SET2R_TIMEVNT8_Msk /*!< Timer event 8 */
+#define HRTIM_SET2R_TIMEVNT9_Pos (20U)
+#define HRTIM_SET2R_TIMEVNT9_Msk (0x1UL << HRTIM_SET2R_TIMEVNT9_Pos) /*!< 0x00100000 */
+#define HRTIM_SET2R_TIMEVNT9 HRTIM_SET2R_TIMEVNT9_Msk /*!< Timer event 9 */
+
+#define HRTIM_SET2R_EXTVNT1_Pos (21U)
+#define HRTIM_SET2R_EXTVNT1_Msk (0x1UL << HRTIM_SET2R_EXTVNT1_Pos) /*!< 0x00200000 */
+#define HRTIM_SET2R_EXTVNT1 HRTIM_SET2R_EXTVNT1_Msk /*!< External event 1 */
+#define HRTIM_SET2R_EXTVNT2_Pos (22U)
+#define HRTIM_SET2R_EXTVNT2_Msk (0x1UL << HRTIM_SET2R_EXTVNT2_Pos) /*!< 0x00400000 */
+#define HRTIM_SET2R_EXTVNT2 HRTIM_SET2R_EXTVNT2_Msk /*!< External event 2 */
+#define HRTIM_SET2R_EXTVNT3_Pos (23U)
+#define HRTIM_SET2R_EXTVNT3_Msk (0x1UL << HRTIM_SET2R_EXTVNT3_Pos) /*!< 0x00800000 */
+#define HRTIM_SET2R_EXTVNT3 HRTIM_SET2R_EXTVNT3_Msk /*!< External event 3 */
+#define HRTIM_SET2R_EXTVNT4_Pos (24U)
+#define HRTIM_SET2R_EXTVNT4_Msk (0x1UL << HRTIM_SET2R_EXTVNT4_Pos) /*!< 0x01000000 */
+#define HRTIM_SET2R_EXTVNT4 HRTIM_SET2R_EXTVNT4_Msk /*!< External event 4 */
+#define HRTIM_SET2R_EXTVNT5_Pos (25U)
+#define HRTIM_SET2R_EXTVNT5_Msk (0x1UL << HRTIM_SET2R_EXTVNT5_Pos) /*!< 0x02000000 */
+#define HRTIM_SET2R_EXTVNT5 HRTIM_SET2R_EXTVNT5_Msk /*!< External event 5 */
+#define HRTIM_SET2R_EXTVNT6_Pos (26U)
+#define HRTIM_SET2R_EXTVNT6_Msk (0x1UL << HRTIM_SET2R_EXTVNT6_Pos) /*!< 0x04000000 */
+#define HRTIM_SET2R_EXTVNT6 HRTIM_SET2R_EXTVNT6_Msk /*!< External event 6 */
+#define HRTIM_SET2R_EXTVNT7_Pos (27U)
+#define HRTIM_SET2R_EXTVNT7_Msk (0x1UL << HRTIM_SET2R_EXTVNT7_Pos) /*!< 0x08000000 */
+#define HRTIM_SET2R_EXTVNT7 HRTIM_SET2R_EXTVNT7_Msk /*!< External event 7 */
+#define HRTIM_SET2R_EXTVNT8_Pos (28U)
+#define HRTIM_SET2R_EXTVNT8_Msk (0x1UL << HRTIM_SET2R_EXTVNT8_Pos) /*!< 0x10000000 */
+#define HRTIM_SET2R_EXTVNT8 HRTIM_SET2R_EXTVNT8_Msk /*!< External event 8 */
+#define HRTIM_SET2R_EXTVNT9_Pos (29U)
+#define HRTIM_SET2R_EXTVNT9_Msk (0x1UL << HRTIM_SET2R_EXTVNT9_Pos) /*!< 0x20000000 */
+#define HRTIM_SET2R_EXTVNT9 HRTIM_SET2R_EXTVNT9_Msk /*!< External event 9 */
+#define HRTIM_SET2R_EXTVNT10_Pos (30U)
+#define HRTIM_SET2R_EXTVNT10_Msk (0x1UL << HRTIM_SET2R_EXTVNT10_Pos) /*!< 0x40000000 */
+#define HRTIM_SET2R_EXTVNT10 HRTIM_SET2R_EXTVNT10_Msk /*!< External event 10 */
+
+#define HRTIM_SET2R_UPDATE_Pos (31U)
+#define HRTIM_SET2R_UPDATE_Msk (0x1UL << HRTIM_SET2R_UPDATE_Pos) /*!< 0x80000000 */
+#define HRTIM_SET2R_UPDATE HRTIM_SET2R_UPDATE_Msk /*!< Register update (transfer preload to active) */
+
+/**** Bit definition for Slave Output 2 reset register ************************/
+#define HRTIM_RST2R_SRT_Pos (0U)
+#define HRTIM_RST2R_SRT_Msk (0x1UL << HRTIM_RST2R_SRT_Pos) /*!< 0x00000001 */
+#define HRTIM_RST2R_SRT HRTIM_RST2R_SRT_Msk /*!< software reset trigger */
+#define HRTIM_RST2R_RESYNC_Pos (1U)
+#define HRTIM_RST2R_RESYNC_Msk (0x1UL << HRTIM_RST2R_RESYNC_Pos) /*!< 0x00000002 */
+#define HRTIM_RST2R_RESYNC HRTIM_RST2R_RESYNC_Msk /*!< Timer A resynchronization */
+#define HRTIM_RST2R_PER_Pos (2U)
+#define HRTIM_RST2R_PER_Msk (0x1UL << HRTIM_RST2R_PER_Pos) /*!< 0x00000004 */
+#define HRTIM_RST2R_PER HRTIM_RST2R_PER_Msk /*!< Timer A period */
+#define HRTIM_RST2R_CMP1_Pos (3U)
+#define HRTIM_RST2R_CMP1_Msk (0x1UL << HRTIM_RST2R_CMP1_Pos) /*!< 0x00000008 */
+#define HRTIM_RST2R_CMP1 HRTIM_RST2R_CMP1_Msk /*!< Timer A compare 1 */
+#define HRTIM_RST2R_CMP2_Pos (4U)
+#define HRTIM_RST2R_CMP2_Msk (0x1UL << HRTIM_RST2R_CMP2_Pos) /*!< 0x00000010 */
+#define HRTIM_RST2R_CMP2 HRTIM_RST2R_CMP2_Msk /*!< Timer A compare 2 */
+#define HRTIM_RST2R_CMP3_Pos (5U)
+#define HRTIM_RST2R_CMP3_Msk (0x1UL << HRTIM_RST2R_CMP3_Pos) /*!< 0x00000020 */
+#define HRTIM_RST2R_CMP3 HRTIM_RST2R_CMP3_Msk /*!< Timer A compare 3 */
+#define HRTIM_RST2R_CMP4_Pos (6U)
+#define HRTIM_RST2R_CMP4_Msk (0x1UL << HRTIM_RST2R_CMP4_Pos) /*!< 0x00000040 */
+#define HRTIM_RST2R_CMP4 HRTIM_RST2R_CMP4_Msk /*!< Timer A compare 4 */
+#define HRTIM_RST2R_MSTPER_Pos (7U)
+#define HRTIM_RST2R_MSTPER_Msk (0x1UL << HRTIM_RST2R_MSTPER_Pos) /*!< 0x00000080 */
+#define HRTIM_RST2R_MSTPER HRTIM_RST2R_MSTPER_Msk /*!< Master period */
+#define HRTIM_RST2R_MSTCMP1_Pos (8U)
+#define HRTIM_RST2R_MSTCMP1_Msk (0x1UL << HRTIM_RST2R_MSTCMP1_Pos) /*!< 0x00000100 */
+#define HRTIM_RST2R_MSTCMP1 HRTIM_RST2R_MSTCMP1_Msk /*!< Master compare 1 */
+#define HRTIM_RST2R_MSTCMP2_Pos (9U)
+#define HRTIM_RST2R_MSTCMP2_Msk (0x1UL << HRTIM_RST2R_MSTCMP2_Pos) /*!< 0x00000200 */
+#define HRTIM_RST2R_MSTCMP2 HRTIM_RST2R_MSTCMP2_Msk /*!< Master compare 2 */
+#define HRTIM_RST2R_MSTCMP3_Pos (10U)
+#define HRTIM_RST2R_MSTCMP3_Msk (0x1UL << HRTIM_RST2R_MSTCMP3_Pos) /*!< 0x00000400 */
+#define HRTIM_RST2R_MSTCMP3 HRTIM_RST2R_MSTCMP3_Msk /*!< Master compare 3 */
+#define HRTIM_RST2R_MSTCMP4_Pos (11U)
+#define HRTIM_RST2R_MSTCMP4_Msk (0x1UL << HRTIM_RST2R_MSTCMP4_Pos) /*!< 0x00000800 */
+#define HRTIM_RST2R_MSTCMP4 HRTIM_RST2R_MSTCMP4_Msk /*!< Master compare 4 */
+
+#define HRTIM_RST2R_TIMEVNT1_Pos (12U)
+#define HRTIM_RST2R_TIMEVNT1_Msk (0x1UL << HRTIM_RST2R_TIMEVNT1_Pos) /*!< 0x00001000 */
+#define HRTIM_RST2R_TIMEVNT1 HRTIM_RST2R_TIMEVNT1_Msk /*!< Timer event 1 */
+#define HRTIM_RST2R_TIMEVNT2_Pos (13U)
+#define HRTIM_RST2R_TIMEVNT2_Msk (0x1UL << HRTIM_RST2R_TIMEVNT2_Pos) /*!< 0x00002000 */
+#define HRTIM_RST2R_TIMEVNT2 HRTIM_RST2R_TIMEVNT2_Msk /*!< Timer event 2 */
+#define HRTIM_RST2R_TIMEVNT3_Pos (14U)
+#define HRTIM_RST2R_TIMEVNT3_Msk (0x1UL << HRTIM_RST2R_TIMEVNT3_Pos) /*!< 0x00004000 */
+#define HRTIM_RST2R_TIMEVNT3 HRTIM_RST2R_TIMEVNT3_Msk /*!< Timer event 3 */
+#define HRTIM_RST2R_TIMEVNT4_Pos (15U)
+#define HRTIM_RST2R_TIMEVNT4_Msk (0x1UL << HRTIM_RST2R_TIMEVNT4_Pos) /*!< 0x00008000 */
+#define HRTIM_RST2R_TIMEVNT4 HRTIM_RST2R_TIMEVNT4_Msk /*!< Timer event 4 */
+#define HRTIM_RST2R_TIMEVNT5_Pos (16U)
+#define HRTIM_RST2R_TIMEVNT5_Msk (0x1UL << HRTIM_RST2R_TIMEVNT5_Pos) /*!< 0x00010000 */
+#define HRTIM_RST2R_TIMEVNT5 HRTIM_RST2R_TIMEVNT5_Msk /*!< Timer event 5 */
+#define HRTIM_RST2R_TIMEVNT6_Pos (17U)
+#define HRTIM_RST2R_TIMEVNT6_Msk (0x1UL << HRTIM_RST2R_TIMEVNT6_Pos) /*!< 0x00020000 */
+#define HRTIM_RST2R_TIMEVNT6 HRTIM_RST2R_TIMEVNT6_Msk /*!< Timer event 6 */
+#define HRTIM_RST2R_TIMEVNT7_Pos (18U)
+#define HRTIM_RST2R_TIMEVNT7_Msk (0x1UL << HRTIM_RST2R_TIMEVNT7_Pos) /*!< 0x00040000 */
+#define HRTIM_RST2R_TIMEVNT7 HRTIM_RST2R_TIMEVNT7_Msk /*!< Timer event 7 */
+#define HRTIM_RST2R_TIMEVNT8_Pos (19U)
+#define HRTIM_RST2R_TIMEVNT8_Msk (0x1UL << HRTIM_RST2R_TIMEVNT8_Pos) /*!< 0x00080000 */
+#define HRTIM_RST2R_TIMEVNT8 HRTIM_RST2R_TIMEVNT8_Msk /*!< Timer event 8 */
+#define HRTIM_RST2R_TIMEVNT9_Pos (20U)
+#define HRTIM_RST2R_TIMEVNT9_Msk (0x1UL << HRTIM_RST2R_TIMEVNT9_Pos) /*!< 0x00100000 */
+#define HRTIM_RST2R_TIMEVNT9 HRTIM_RST2R_TIMEVNT9_Msk /*!< Timer event 9 */
+
+#define HRTIM_RST2R_EXTVNT1_Pos (21U)
+#define HRTIM_RST2R_EXTVNT1_Msk (0x1UL << HRTIM_RST2R_EXTVNT1_Pos) /*!< 0x00200000 */
+#define HRTIM_RST2R_EXTVNT1 HRTIM_RST2R_EXTVNT1_Msk /*!< External event 1 */
+#define HRTIM_RST2R_EXTVNT2_Pos (22U)
+#define HRTIM_RST2R_EXTVNT2_Msk (0x1UL << HRTIM_RST2R_EXTVNT2_Pos) /*!< 0x00400000 */
+#define HRTIM_RST2R_EXTVNT2 HRTIM_RST2R_EXTVNT2_Msk /*!< External event 2 */
+#define HRTIM_RST2R_EXTVNT3_Pos (23U)
+#define HRTIM_RST2R_EXTVNT3_Msk (0x1UL << HRTIM_RST2R_EXTVNT3_Pos) /*!< 0x00800000 */
+#define HRTIM_RST2R_EXTVNT3 HRTIM_RST2R_EXTVNT3_Msk /*!< External event 3 */
+#define HRTIM_RST2R_EXTVNT4_Pos (24U)
+#define HRTIM_RST2R_EXTVNT4_Msk (0x1UL << HRTIM_RST2R_EXTVNT4_Pos) /*!< 0x01000000 */
+#define HRTIM_RST2R_EXTVNT4 HRTIM_RST2R_EXTVNT4_Msk /*!< External event 4 */
+#define HRTIM_RST2R_EXTVNT5_Pos (25U)
+#define HRTIM_RST2R_EXTVNT5_Msk (0x1UL << HRTIM_RST2R_EXTVNT5_Pos) /*!< 0x02000000 */
+#define HRTIM_RST2R_EXTVNT5 HRTIM_RST2R_EXTVNT5_Msk /*!< External event 5 */
+#define HRTIM_RST2R_EXTVNT6_Pos (26U)
+#define HRTIM_RST2R_EXTVNT6_Msk (0x1UL << HRTIM_RST2R_EXTVNT6_Pos) /*!< 0x04000000 */
+#define HRTIM_RST2R_EXTVNT6 HRTIM_RST2R_EXTVNT6_Msk /*!< External event 6 */
+#define HRTIM_RST2R_EXTVNT7_Pos (27U)
+#define HRTIM_RST2R_EXTVNT7_Msk (0x1UL << HRTIM_RST2R_EXTVNT7_Pos) /*!< 0x08000000 */
+#define HRTIM_RST2R_EXTVNT7 HRTIM_RST2R_EXTVNT7_Msk /*!< External event 7 */
+#define HRTIM_RST2R_EXTVNT8_Pos (28U)
+#define HRTIM_RST2R_EXTVNT8_Msk (0x1UL << HRTIM_RST2R_EXTVNT8_Pos) /*!< 0x10000000 */
+#define HRTIM_RST2R_EXTVNT8 HRTIM_RST2R_EXTVNT8_Msk /*!< External event 8 */
+#define HRTIM_RST2R_EXTVNT9_Pos (29U)
+#define HRTIM_RST2R_EXTVNT9_Msk (0x1UL << HRTIM_RST2R_EXTVNT9_Pos) /*!< 0x20000000 */
+#define HRTIM_RST2R_EXTVNT9 HRTIM_RST2R_EXTVNT9_Msk /*!< External event 9 */
+#define HRTIM_RST2R_EXTVNT10_Pos (30U)
+#define HRTIM_RST2R_EXTVNT10_Msk (0x1UL << HRTIM_RST2R_EXTVNT10_Pos) /*!< 0x40000000 */
+#define HRTIM_RST2R_EXTVNT10 HRTIM_RST2R_EXTVNT10_Msk /*!< External event 10 */
+#define HRTIM_RST2R_UPDATE_Pos (31U)
+#define HRTIM_RST2R_UPDATE_Msk (0x1UL << HRTIM_RST2R_UPDATE_Pos) /*!< 0x80000000 */
+#define HRTIM_RST2R_UPDATE HRTIM_RST2R_UPDATE_Msk /*!< Register update (transfer preload to active) */
+
+/**** Bit definition for Slave external event filtering register 1 ***********/
+#define HRTIM_EEFR1_EE1LTCH_Pos (0U)
+#define HRTIM_EEFR1_EE1LTCH_Msk (0x1UL << HRTIM_EEFR1_EE1LTCH_Pos) /*!< 0x00000001 */
+#define HRTIM_EEFR1_EE1LTCH HRTIM_EEFR1_EE1LTCH_Msk /*!< External Event 1 latch */
+#define HRTIM_EEFR1_EE1FLTR_Pos (1U)
+#define HRTIM_EEFR1_EE1FLTR_Msk (0xFUL << HRTIM_EEFR1_EE1FLTR_Pos) /*!< 0x0000001E */
+#define HRTIM_EEFR1_EE1FLTR HRTIM_EEFR1_EE1FLTR_Msk /*!< External Event 1 filter mask */
+#define HRTIM_EEFR1_EE1FLTR_0 (0x1UL << HRTIM_EEFR1_EE1FLTR_Pos) /*!< 0x00000002 */
+#define HRTIM_EEFR1_EE1FLTR_1 (0x2UL << HRTIM_EEFR1_EE1FLTR_Pos) /*!< 0x00000004 */
+#define HRTIM_EEFR1_EE1FLTR_2 (0x4UL << HRTIM_EEFR1_EE1FLTR_Pos) /*!< 0x00000008 */
+#define HRTIM_EEFR1_EE1FLTR_3 (0x8UL << HRTIM_EEFR1_EE1FLTR_Pos) /*!< 0x00000010 */
+
+#define HRTIM_EEFR1_EE2LTCH_Pos (6U)
+#define HRTIM_EEFR1_EE2LTCH_Msk (0x1UL << HRTIM_EEFR1_EE2LTCH_Pos) /*!< 0x00000040 */
+#define HRTIM_EEFR1_EE2LTCH HRTIM_EEFR1_EE2LTCH_Msk /*!< External Event 2 latch */
+#define HRTIM_EEFR1_EE2FLTR_Pos (7U)
+#define HRTIM_EEFR1_EE2FLTR_Msk (0xFUL << HRTIM_EEFR1_EE2FLTR_Pos) /*!< 0x00000780 */
+#define HRTIM_EEFR1_EE2FLTR HRTIM_EEFR1_EE2FLTR_Msk /*!< External Event 2 filter mask */
+#define HRTIM_EEFR1_EE2FLTR_0 (0x1UL << HRTIM_EEFR1_EE2FLTR_Pos) /*!< 0x00000080 */
+#define HRTIM_EEFR1_EE2FLTR_1 (0x2UL << HRTIM_EEFR1_EE2FLTR_Pos) /*!< 0x00000100 */
+#define HRTIM_EEFR1_EE2FLTR_2 (0x4UL << HRTIM_EEFR1_EE2FLTR_Pos) /*!< 0x00000200 */
+#define HRTIM_EEFR1_EE2FLTR_3 (0x8UL << HRTIM_EEFR1_EE2FLTR_Pos) /*!< 0x00000400 */
+
+#define HRTIM_EEFR1_EE3LTCH_Pos (12U)
+#define HRTIM_EEFR1_EE3LTCH_Msk (0x1UL << HRTIM_EEFR1_EE3LTCH_Pos) /*!< 0x00001000 */
+#define HRTIM_EEFR1_EE3LTCH HRTIM_EEFR1_EE3LTCH_Msk /*!< External Event 3 latch */
+#define HRTIM_EEFR1_EE3FLTR_Pos (13U)
+#define HRTIM_EEFR1_EE3FLTR_Msk (0xFUL << HRTIM_EEFR1_EE3FLTR_Pos) /*!< 0x0001E000 */
+#define HRTIM_EEFR1_EE3FLTR HRTIM_EEFR1_EE3FLTR_Msk /*!< External Event 3 filter mask */
+#define HRTIM_EEFR1_EE3FLTR_0 (0x1UL << HRTIM_EEFR1_EE3FLTR_Pos) /*!< 0x00002000 */
+#define HRTIM_EEFR1_EE3FLTR_1 (0x2UL << HRTIM_EEFR1_EE3FLTR_Pos) /*!< 0x00004000 */
+#define HRTIM_EEFR1_EE3FLTR_2 (0x4UL << HRTIM_EEFR1_EE3FLTR_Pos) /*!< 0x00008000 */
+#define HRTIM_EEFR1_EE3FLTR_3 (0x8UL << HRTIM_EEFR1_EE3FLTR_Pos) /*!< 0x00010000 */
+
+#define HRTIM_EEFR1_EE4LTCH_Pos (18U)
+#define HRTIM_EEFR1_EE4LTCH_Msk (0x1UL << HRTIM_EEFR1_EE4LTCH_Pos) /*!< 0x00040000 */
+#define HRTIM_EEFR1_EE4LTCH HRTIM_EEFR1_EE4LTCH_Msk /*!< External Event 4 latch */
+#define HRTIM_EEFR1_EE4FLTR_Pos (19U)
+#define HRTIM_EEFR1_EE4FLTR_Msk (0xFUL << HRTIM_EEFR1_EE4FLTR_Pos) /*!< 0x00780000 */
+#define HRTIM_EEFR1_EE4FLTR HRTIM_EEFR1_EE4FLTR_Msk /*!< External Event 4 filter mask */
+#define HRTIM_EEFR1_EE4FLTR_0 (0x1UL << HRTIM_EEFR1_EE4FLTR_Pos) /*!< 0x00080000 */
+#define HRTIM_EEFR1_EE4FLTR_1 (0x2UL << HRTIM_EEFR1_EE4FLTR_Pos) /*!< 0x00100000 */
+#define HRTIM_EEFR1_EE4FLTR_2 (0x4UL << HRTIM_EEFR1_EE4FLTR_Pos) /*!< 0x00200000 */
+#define HRTIM_EEFR1_EE4FLTR_3 (0x8UL << HRTIM_EEFR1_EE4FLTR_Pos) /*!< 0x00400000 */
+
+#define HRTIM_EEFR1_EE5LTCH_Pos (24U)
+#define HRTIM_EEFR1_EE5LTCH_Msk (0x1UL << HRTIM_EEFR1_EE5LTCH_Pos) /*!< 0x01000000 */
+#define HRTIM_EEFR1_EE5LTCH HRTIM_EEFR1_EE5LTCH_Msk /*!< External Event 5 latch */
+#define HRTIM_EEFR1_EE5FLTR_Pos (25U)
+#define HRTIM_EEFR1_EE5FLTR_Msk (0xFUL << HRTIM_EEFR1_EE5FLTR_Pos) /*!< 0x1E000000 */
+#define HRTIM_EEFR1_EE5FLTR HRTIM_EEFR1_EE5FLTR_Msk /*!< External Event 5 filter mask */
+#define HRTIM_EEFR1_EE5FLTR_0 (0x1UL << HRTIM_EEFR1_EE5FLTR_Pos) /*!< 0x02000000 */
+#define HRTIM_EEFR1_EE5FLTR_1 (0x2UL << HRTIM_EEFR1_EE5FLTR_Pos) /*!< 0x04000000 */
+#define HRTIM_EEFR1_EE5FLTR_2 (0x4UL << HRTIM_EEFR1_EE5FLTR_Pos) /*!< 0x08000000 */
+#define HRTIM_EEFR1_EE5FLTR_3 (0x8UL << HRTIM_EEFR1_EE5FLTR_Pos) /*!< 0x10000000 */
+
+/**** Bit definition for Slave external event filtering register 2 ***********/
+#define HRTIM_EEFR2_EE6LTCH_Pos (0U)
+#define HRTIM_EEFR2_EE6LTCH_Msk (0x1UL << HRTIM_EEFR2_EE6LTCH_Pos) /*!< 0x00000001 */
+#define HRTIM_EEFR2_EE6LTCH HRTIM_EEFR2_EE6LTCH_Msk /*!< External Event 6 latch */
+#define HRTIM_EEFR2_EE6FLTR_Pos (1U)
+#define HRTIM_EEFR2_EE6FLTR_Msk (0xFUL << HRTIM_EEFR2_EE6FLTR_Pos) /*!< 0x0000001E */
+#define HRTIM_EEFR2_EE6FLTR HRTIM_EEFR2_EE6FLTR_Msk /*!< External Event 6 filter mask */
+#define HRTIM_EEFR2_EE6FLTR_0 (0x1UL << HRTIM_EEFR2_EE6FLTR_Pos) /*!< 0x00000002 */
+#define HRTIM_EEFR2_EE6FLTR_1 (0x2UL << HRTIM_EEFR2_EE6FLTR_Pos) /*!< 0x00000004 */
+#define HRTIM_EEFR2_EE6FLTR_2 (0x4UL << HRTIM_EEFR2_EE6FLTR_Pos) /*!< 0x00000008 */
+#define HRTIM_EEFR2_EE6FLTR_3 (0x8UL << HRTIM_EEFR2_EE6FLTR_Pos) /*!< 0x00000010 */
+
+#define HRTIM_EEFR2_EE7LTCH_Pos (6U)
+#define HRTIM_EEFR2_EE7LTCH_Msk (0x1UL << HRTIM_EEFR2_EE7LTCH_Pos) /*!< 0x00000040 */
+#define HRTIM_EEFR2_EE7LTCH HRTIM_EEFR2_EE7LTCH_Msk /*!< External Event 7 latch */
+#define HRTIM_EEFR2_EE7FLTR_Pos (7U)
+#define HRTIM_EEFR2_EE7FLTR_Msk (0xFUL << HRTIM_EEFR2_EE7FLTR_Pos) /*!< 0x00000780 */
+#define HRTIM_EEFR2_EE7FLTR HRTIM_EEFR2_EE7FLTR_Msk /*!< External Event 7 filter mask */
+#define HRTIM_EEFR2_EE7FLTR_0 (0x1UL << HRTIM_EEFR2_EE7FLTR_Pos) /*!< 0x00000080 */
+#define HRTIM_EEFR2_EE7FLTR_1 (0x2UL << HRTIM_EEFR2_EE7FLTR_Pos) /*!< 0x00000100 */
+#define HRTIM_EEFR2_EE7FLTR_2 (0x4UL << HRTIM_EEFR2_EE7FLTR_Pos) /*!< 0x00000200 */
+#define HRTIM_EEFR2_EE7FLTR_3 (0x8UL << HRTIM_EEFR2_EE7FLTR_Pos) /*!< 0x00000400 */
+
+#define HRTIM_EEFR2_EE8LTCH_Pos (12U)
+#define HRTIM_EEFR2_EE8LTCH_Msk (0x1UL << HRTIM_EEFR2_EE8LTCH_Pos) /*!< 0x00001000 */
+#define HRTIM_EEFR2_EE8LTCH HRTIM_EEFR2_EE8LTCH_Msk /*!< External Event 8 latch */
+#define HRTIM_EEFR2_EE8FLTR_Pos (13U)
+#define HRTIM_EEFR2_EE8FLTR_Msk (0xFUL << HRTIM_EEFR2_EE8FLTR_Pos) /*!< 0x0001E000 */
+#define HRTIM_EEFR2_EE8FLTR HRTIM_EEFR2_EE8FLTR_Msk /*!< External Event 8 filter mask */
+#define HRTIM_EEFR2_EE8FLTR_0 (0x1UL << HRTIM_EEFR2_EE8FLTR_Pos) /*!< 0x00002000 */
+#define HRTIM_EEFR2_EE8FLTR_1 (0x2UL << HRTIM_EEFR2_EE8FLTR_Pos) /*!< 0x00004000 */
+#define HRTIM_EEFR2_EE8FLTR_2 (0x4UL << HRTIM_EEFR2_EE8FLTR_Pos) /*!< 0x00008000 */
+#define HRTIM_EEFR2_EE8FLTR_3 (0x8UL << HRTIM_EEFR2_EE8FLTR_Pos) /*!< 0x00010000 */
+
+#define HRTIM_EEFR2_EE9LTCH_Pos (18U)
+#define HRTIM_EEFR2_EE9LTCH_Msk (0x1UL << HRTIM_EEFR2_EE9LTCH_Pos) /*!< 0x00040000 */
+#define HRTIM_EEFR2_EE9LTCH HRTIM_EEFR2_EE9LTCH_Msk /*!< External Event 9 latch */
+#define HRTIM_EEFR2_EE9FLTR_Pos (19U)
+#define HRTIM_EEFR2_EE9FLTR_Msk (0xFUL << HRTIM_EEFR2_EE9FLTR_Pos) /*!< 0x00780000 */
+#define HRTIM_EEFR2_EE9FLTR HRTIM_EEFR2_EE9FLTR_Msk /*!< External Event 9 filter mask */
+#define HRTIM_EEFR2_EE9FLTR_0 (0x1UL << HRTIM_EEFR2_EE9FLTR_Pos) /*!< 0x00080000 */
+#define HRTIM_EEFR2_EE9FLTR_1 (0x2UL << HRTIM_EEFR2_EE9FLTR_Pos) /*!< 0x00100000 */
+#define HRTIM_EEFR2_EE9FLTR_2 (0x4UL << HRTIM_EEFR2_EE9FLTR_Pos) /*!< 0x00200000 */
+#define HRTIM_EEFR2_EE9FLTR_3 (0x8UL << HRTIM_EEFR2_EE9FLTR_Pos) /*!< 0x00400000 */
+
+#define HRTIM_EEFR2_EE10LTCH_Pos (24U)
+#define HRTIM_EEFR2_EE10LTCH_Msk (0x1UL << HRTIM_EEFR2_EE10LTCH_Pos) /*!< 0x01000000 */
+#define HRTIM_EEFR2_EE10LTCH HRTIM_EEFR2_EE10LTCH_Msk /*!< External Event 10 latch */
+#define HRTIM_EEFR2_EE10FLTR_Pos (25U)
+#define HRTIM_EEFR2_EE10FLTR_Msk (0xFUL << HRTIM_EEFR2_EE10FLTR_Pos) /*!< 0x1E000000 */
+#define HRTIM_EEFR2_EE10FLTR HRTIM_EEFR2_EE10FLTR_Msk /*!< External Event 10 filter mask */
+#define HRTIM_EEFR2_EE10FLTR_0 (0x1UL << HRTIM_EEFR2_EE10FLTR_Pos) /*!< 0x02000000 */
+#define HRTIM_EEFR2_EE10FLTR_1 (0x2UL << HRTIM_EEFR2_EE10FLTR_Pos) /*!< 0x04000000 */
+#define HRTIM_EEFR2_EE10FLTR_2 (0x4UL << HRTIM_EEFR2_EE10FLTR_Pos) /*!< 0x08000000 */
+#define HRTIM_EEFR2_EE10FLTR_3 (0x8UL << HRTIM_EEFR2_EE10FLTR_Pos) /*!< 0x10000000 */
+
+/**** Bit definition for Slave Timer reset register ***************************/
+
+#define HRTIM_RSTR_TIMFCMP1_Pos (0U)
+#define HRTIM_RSTR_TIMFCMP1_Msk (0x1UL << HRTIM_RSTR_TIMFCMP1_Pos) /*!< 0x00000001 */
+#define HRTIM_RSTR_TIMFCMP1 HRTIM_RSTR_TIMFCMP1_Msk /*!< Timer F compare 1 */
+#define HRTIM_RSTR_UPDATE_Pos (1U)
+#define HRTIM_RSTR_UPDATE_Msk (0x1UL << HRTIM_RSTR_UPDATE_Pos) /*!< 0x00000002 */
+#define HRTIM_RSTR_UPDATE HRTIM_RSTR_UPDATE_Msk /*!< Timer update */
+#define HRTIM_RSTR_CMP2_Pos (2U)
+#define HRTIM_RSTR_CMP2_Msk (0x1UL << HRTIM_RSTR_CMP2_Pos) /*!< 0x00000004 */
+#define HRTIM_RSTR_CMP2 HRTIM_RSTR_CMP2_Msk /*!< Timer compare2 */
+#define HRTIM_RSTR_CMP4_Pos (3U)
+#define HRTIM_RSTR_CMP4_Msk (0x1UL << HRTIM_RSTR_CMP4_Pos) /*!< 0x00000008 */
+#define HRTIM_RSTR_CMP4 HRTIM_RSTR_CMP4_Msk /*!< Timer compare4 */
+#define HRTIM_RSTR_MSTPER_Pos (4U)
+#define HRTIM_RSTR_MSTPER_Msk (0x1UL << HRTIM_RSTR_MSTPER_Pos) /*!< 0x00000010 */
+#define HRTIM_RSTR_MSTPER HRTIM_RSTR_MSTPER_Msk /*!< Master period */
+#define HRTIM_RSTR_MSTCMP1_Pos (5U)
+#define HRTIM_RSTR_MSTCMP1_Msk (0x1UL << HRTIM_RSTR_MSTCMP1_Pos) /*!< 0x00000020 */
+#define HRTIM_RSTR_MSTCMP1 HRTIM_RSTR_MSTCMP1_Msk /*!< Master compare1 */
+#define HRTIM_RSTR_MSTCMP2_Pos (6U)
+#define HRTIM_RSTR_MSTCMP2_Msk (0x1UL << HRTIM_RSTR_MSTCMP2_Pos) /*!< 0x00000040 */
+#define HRTIM_RSTR_MSTCMP2 HRTIM_RSTR_MSTCMP2_Msk /*!< Master compare2 */
+#define HRTIM_RSTR_MSTCMP3_Pos (7U)
+#define HRTIM_RSTR_MSTCMP3_Msk (0x1UL << HRTIM_RSTR_MSTCMP3_Pos) /*!< 0x00000080 */
+#define HRTIM_RSTR_MSTCMP3 HRTIM_RSTR_MSTCMP3_Msk /*!< Master compare3 */
+#define HRTIM_RSTR_MSTCMP4_Pos (8U)
+#define HRTIM_RSTR_MSTCMP4_Msk (0x1UL << HRTIM_RSTR_MSTCMP4_Pos) /*!< 0x00000100 */
+#define HRTIM_RSTR_MSTCMP4 HRTIM_RSTR_MSTCMP4_Msk /*!< Master compare4 */
+#define HRTIM_RSTR_EXTEVNT1_Pos (9U)
+#define HRTIM_RSTR_EXTEVNT1_Msk (0x1UL << HRTIM_RSTR_EXTEVNT1_Pos) /*!< 0x00000200 */
+#define HRTIM_RSTR_EXTEVNT1 HRTIM_RSTR_EXTEVNT1_Msk /*!< External event 1 */
+#define HRTIM_RSTR_EXTEVNT2_Pos (10U)
+#define HRTIM_RSTR_EXTEVNT2_Msk (0x1UL << HRTIM_RSTR_EXTEVNT2_Pos) /*!< 0x00000400 */
+#define HRTIM_RSTR_EXTEVNT2 HRTIM_RSTR_EXTEVNT2_Msk /*!< External event 2 */
+#define HRTIM_RSTR_EXTEVNT3_Pos (11U)
+#define HRTIM_RSTR_EXTEVNT3_Msk (0x1UL << HRTIM_RSTR_EXTEVNT3_Pos) /*!< 0x00000800 */
+#define HRTIM_RSTR_EXTEVNT3 HRTIM_RSTR_EXTEVNT3_Msk /*!< External event 3 */
+#define HRTIM_RSTR_EXTEVNT4_Pos (12U)
+#define HRTIM_RSTR_EXTEVNT4_Msk (0x1UL << HRTIM_RSTR_EXTEVNT4_Pos) /*!< 0x00001000 */
+#define HRTIM_RSTR_EXTEVNT4 HRTIM_RSTR_EXTEVNT4_Msk /*!< External event 4 */
+#define HRTIM_RSTR_EXTEVNT5_Pos (13U)
+#define HRTIM_RSTR_EXTEVNT5_Msk (0x1UL << HRTIM_RSTR_EXTEVNT5_Pos) /*!< 0x00002000 */
+#define HRTIM_RSTR_EXTEVNT5 HRTIM_RSTR_EXTEVNT5_Msk /*!< External event 5 */
+#define HRTIM_RSTR_EXTEVNT6_Pos (14U)
+#define HRTIM_RSTR_EXTEVNT6_Msk (0x1UL << HRTIM_RSTR_EXTEVNT6_Pos) /*!< 0x00004000 */
+#define HRTIM_RSTR_EXTEVNT6 HRTIM_RSTR_EXTEVNT6_Msk /*!< External event 6 */
+#define HRTIM_RSTR_EXTEVNT7_Pos (15U)
+#define HRTIM_RSTR_EXTEVNT7_Msk (0x1UL << HRTIM_RSTR_EXTEVNT7_Pos) /*!< 0x00008000 */
+#define HRTIM_RSTR_EXTEVNT7 HRTIM_RSTR_EXTEVNT7_Msk /*!< External event 7 */
+#define HRTIM_RSTR_EXTEVNT8_Pos (16U)
+#define HRTIM_RSTR_EXTEVNT8_Msk (0x1UL << HRTIM_RSTR_EXTEVNT8_Pos) /*!< 0x00010000 */
+#define HRTIM_RSTR_EXTEVNT8 HRTIM_RSTR_EXTEVNT8_Msk /*!< External event 8 */
+#define HRTIM_RSTR_EXTEVNT9_Pos (17U)
+#define HRTIM_RSTR_EXTEVNT9_Msk (0x1UL << HRTIM_RSTR_EXTEVNT9_Pos) /*!< 0x00020000 */
+#define HRTIM_RSTR_EXTEVNT9 HRTIM_RSTR_EXTEVNT9_Msk /*!< External event 9 */
+#define HRTIM_RSTR_EXTEVNT10_Pos (18U)
+#define HRTIM_RSTR_EXTEVNT10_Msk (0x1UL << HRTIM_RSTR_EXTEVNT10_Pos) /*!< 0x00040000 */
+#define HRTIM_RSTR_EXTEVNT10 HRTIM_RSTR_EXTEVNT10_Msk /*!< External event 10 */
+#define HRTIM_RSTR_TIMBCMP1_Pos (19U)
+#define HRTIM_RSTR_TIMBCMP1_Msk (0x1UL << HRTIM_RSTR_TIMBCMP1_Pos) /*!< 0x00080000 */
+#define HRTIM_RSTR_TIMBCMP1 HRTIM_RSTR_TIMBCMP1_Msk /*!< Timer B compare 1 */
+#define HRTIM_RSTR_TIMBCMP2_Pos (20U)
+#define HRTIM_RSTR_TIMBCMP2_Msk (0x1UL << HRTIM_RSTR_TIMBCMP2_Pos) /*!< 0x00100000 */
+#define HRTIM_RSTR_TIMBCMP2 HRTIM_RSTR_TIMBCMP2_Msk /*!< Timer B compare 2 */
+#define HRTIM_RSTR_TIMBCMP4_Pos (21U)
+#define HRTIM_RSTR_TIMBCMP4_Msk (0x1UL << HRTIM_RSTR_TIMBCMP4_Pos) /*!< 0x00200000 */
+#define HRTIM_RSTR_TIMBCMP4 HRTIM_RSTR_TIMBCMP4_Msk /*!< Timer B compare 4 */
+#define HRTIM_RSTR_TIMCCMP1_Pos (22U)
+#define HRTIM_RSTR_TIMCCMP1_Msk (0x1UL << HRTIM_RSTR_TIMCCMP1_Pos) /*!< 0x00400000 */
+#define HRTIM_RSTR_TIMCCMP1 HRTIM_RSTR_TIMCCMP1_Msk /*!< Timer C compare 1 */
+#define HRTIM_RSTR_TIMCCMP2_Pos (23U)
+#define HRTIM_RSTR_TIMCCMP2_Msk (0x1UL << HRTIM_RSTR_TIMCCMP2_Pos) /*!< 0x00800000 */
+#define HRTIM_RSTR_TIMCCMP2 HRTIM_RSTR_TIMCCMP2_Msk /*!< Timer C compare 2 */
+#define HRTIM_RSTR_TIMCCMP4_Pos (24U)
+#define HRTIM_RSTR_TIMCCMP4_Msk (0x1UL << HRTIM_RSTR_TIMCCMP4_Pos) /*!< 0x01000000 */
+#define HRTIM_RSTR_TIMCCMP4 HRTIM_RSTR_TIMCCMP4_Msk /*!< Timer C compare 4 */
+#define HRTIM_RSTR_TIMDCMP1_Pos (25U)
+#define HRTIM_RSTR_TIMDCMP1_Msk (0x1UL << HRTIM_RSTR_TIMDCMP1_Pos) /*!< 0x02000000 */
+#define HRTIM_RSTR_TIMDCMP1 HRTIM_RSTR_TIMDCMP1_Msk /*!< Timer D compare 1 */
+#define HRTIM_RSTR_TIMDCMP2_Pos (26U)
+#define HRTIM_RSTR_TIMDCMP2_Msk (0x1UL << HRTIM_RSTR_TIMDCMP2_Pos) /*!< 0x04000000 */
+#define HRTIM_RSTR_TIMDCMP2 HRTIM_RSTR_TIMDCMP2_Msk /*!< Timer D compare 2 */
+#define HRTIM_RSTR_TIMDCMP4_Pos (27U)
+#define HRTIM_RSTR_TIMDCMP4_Msk (0x1UL << HRTIM_RSTR_TIMDCMP4_Pos) /*!< 0x08000000 */
+#define HRTIM_RSTR_TIMDCMP4 HRTIM_RSTR_TIMDCMP4_Msk /*!< Timer D compare 4 */
+#define HRTIM_RSTR_TIMECMP1_Pos (28U)
+#define HRTIM_RSTR_TIMECMP1_Msk (0x1UL << HRTIM_RSTR_TIMECMP1_Pos) /*!< 0x10000000 */
+#define HRTIM_RSTR_TIMECMP1 HRTIM_RSTR_TIMECMP1_Msk /*!< Timer E compare 1 */
+#define HRTIM_RSTR_TIMECMP2_Pos (29U)
+#define HRTIM_RSTR_TIMECMP2_Msk (0x1UL << HRTIM_RSTR_TIMECMP2_Pos) /*!< 0x20000000 */
+#define HRTIM_RSTR_TIMECMP2 HRTIM_RSTR_TIMECMP2_Msk /*!< Timer E compare 2 */
+#define HRTIM_RSTR_TIMECMP4_Pos (30U)
+#define HRTIM_RSTR_TIMECMP4_Msk (0x1UL << HRTIM_RSTR_TIMECMP4_Pos) /*!< 0x40000000 */
+#define HRTIM_RSTR_TIMECMP4 HRTIM_RSTR_TIMECMP4_Msk /*!< Timer E compare 4 */
+#define HRTIM_RSTR_TIMFCMP2_Pos (31U)
+#define HRTIM_RSTR_TIMFCMP2_Msk (0x1UL << HRTIM_RSTR_TIMFCMP2_Pos) /*!< 0x80000000 */
+#define HRTIM_RSTR_TIMFCMP2 HRTIM_RSTR_TIMFCMP2_Msk /*!< Timer F compare 2 */
+
+/**** Bit definition for Slave Timer Chopper register *************************/
+#define HRTIM_CHPR_CARFRQ_Pos (0U)
+#define HRTIM_CHPR_CARFRQ_Msk (0xFUL << HRTIM_CHPR_CARFRQ_Pos) /*!< 0x0000000F */
+#define HRTIM_CHPR_CARFRQ HRTIM_CHPR_CARFRQ_Msk /*!< Timer carrier frequency value */
+#define HRTIM_CHPR_CARFRQ_0 (0x1UL << HRTIM_CHPR_CARFRQ_Pos) /*!< 0x00000001 */
+#define HRTIM_CHPR_CARFRQ_1 (0x2UL << HRTIM_CHPR_CARFRQ_Pos) /*!< 0x00000002 */
+#define HRTIM_CHPR_CARFRQ_2 (0x4UL << HRTIM_CHPR_CARFRQ_Pos) /*!< 0x00000004 */
+#define HRTIM_CHPR_CARFRQ_3 (0x8UL << HRTIM_CHPR_CARFRQ_Pos) /*!< 0x00000008 */
+
+#define HRTIM_CHPR_CARDTY_Pos (4U)
+#define HRTIM_CHPR_CARDTY_Msk (0x7UL << HRTIM_CHPR_CARDTY_Pos) /*!< 0x00000070 */
+#define HRTIM_CHPR_CARDTY HRTIM_CHPR_CARDTY_Msk /*!< Timer chopper duty cycle value */
+#define HRTIM_CHPR_CARDTY_0 (0x1UL << HRTIM_CHPR_CARDTY_Pos) /*!< 0x00000010 */
+#define HRTIM_CHPR_CARDTY_1 (0x2UL << HRTIM_CHPR_CARDTY_Pos) /*!< 0x00000020 */
+#define HRTIM_CHPR_CARDTY_2 (0x4UL << HRTIM_CHPR_CARDTY_Pos) /*!< 0x00000040 */
+
+#define HRTIM_CHPR_STRPW_Pos (7U)
+#define HRTIM_CHPR_STRPW_Msk (0xFUL << HRTIM_CHPR_STRPW_Pos) /*!< 0x00000780 */
+#define HRTIM_CHPR_STRPW HRTIM_CHPR_STRPW_Msk /*!< Timer start pulse width value */
+#define HRTIM_CHPR_STRPW_0 (0x1UL << HRTIM_CHPR_STRPW_Pos) /*!< 0x00000080 */
+#define HRTIM_CHPR_STRPW_1 (0x2UL << HRTIM_CHPR_STRPW_Pos) /*!< 0x00000100 */
+#define HRTIM_CHPR_STRPW_2 (0x4UL << HRTIM_CHPR_STRPW_Pos) /*!< 0x00000200 */
+#define HRTIM_CHPR_STRPW_3 (0x8UL << HRTIM_CHPR_STRPW_Pos) /*!< 0x00000400 */
+
+/**** Bit definition for Slave Timer Capture 1 control register ***************/
+#define HRTIM_CPT1CR_SWCPT_Pos (0U)
+#define HRTIM_CPT1CR_SWCPT_Msk (0x1UL << HRTIM_CPT1CR_SWCPT_Pos) /*!< 0x00000001 */
+#define HRTIM_CPT1CR_SWCPT HRTIM_CPT1CR_SWCPT_Msk /*!< Software capture */
+#define HRTIM_CPT1CR_UPDCPT_Pos (1U)
+#define HRTIM_CPT1CR_UPDCPT_Msk (0x1UL << HRTIM_CPT1CR_UPDCPT_Pos) /*!< 0x00000002 */
+#define HRTIM_CPT1CR_UPDCPT HRTIM_CPT1CR_UPDCPT_Msk /*!< Update capture */
+#define HRTIM_CPT1CR_EXEV1CPT_Pos (2U)
+#define HRTIM_CPT1CR_EXEV1CPT_Msk (0x1UL << HRTIM_CPT1CR_EXEV1CPT_Pos) /*!< 0x00000004 */
+#define HRTIM_CPT1CR_EXEV1CPT HRTIM_CPT1CR_EXEV1CPT_Msk /*!< External event 1 capture */
+#define HRTIM_CPT1CR_EXEV2CPT_Pos (3U)
+#define HRTIM_CPT1CR_EXEV2CPT_Msk (0x1UL << HRTIM_CPT1CR_EXEV2CPT_Pos) /*!< 0x00000008 */
+#define HRTIM_CPT1CR_EXEV2CPT HRTIM_CPT1CR_EXEV2CPT_Msk /*!< External event 2 capture */
+#define HRTIM_CPT1CR_EXEV3CPT_Pos (4U)
+#define HRTIM_CPT1CR_EXEV3CPT_Msk (0x1UL << HRTIM_CPT1CR_EXEV3CPT_Pos) /*!< 0x00000010 */
+#define HRTIM_CPT1CR_EXEV3CPT HRTIM_CPT1CR_EXEV3CPT_Msk /*!< External event 3 capture */
+#define HRTIM_CPT1CR_EXEV4CPT_Pos (5U)
+#define HRTIM_CPT1CR_EXEV4CPT_Msk (0x1UL << HRTIM_CPT1CR_EXEV4CPT_Pos) /*!< 0x00000020 */
+#define HRTIM_CPT1CR_EXEV4CPT HRTIM_CPT1CR_EXEV4CPT_Msk /*!< External event 4 capture */
+#define HRTIM_CPT1CR_EXEV5CPT_Pos (6U)
+#define HRTIM_CPT1CR_EXEV5CPT_Msk (0x1UL << HRTIM_CPT1CR_EXEV5CPT_Pos) /*!< 0x00000040 */
+#define HRTIM_CPT1CR_EXEV5CPT HRTIM_CPT1CR_EXEV5CPT_Msk /*!< External event 5 capture */
+#define HRTIM_CPT1CR_EXEV6CPT_Pos (7U)
+#define HRTIM_CPT1CR_EXEV6CPT_Msk (0x1UL << HRTIM_CPT1CR_EXEV6CPT_Pos) /*!< 0x00000080 */
+#define HRTIM_CPT1CR_EXEV6CPT HRTIM_CPT1CR_EXEV6CPT_Msk /*!< External event 6 capture */
+#define HRTIM_CPT1CR_EXEV7CPT_Pos (8U)
+#define HRTIM_CPT1CR_EXEV7CPT_Msk (0x1UL << HRTIM_CPT1CR_EXEV7CPT_Pos) /*!< 0x00000100 */
+#define HRTIM_CPT1CR_EXEV7CPT HRTIM_CPT1CR_EXEV7CPT_Msk /*!< External event 7 capture */
+#define HRTIM_CPT1CR_EXEV8CPT_Pos (9U)
+#define HRTIM_CPT1CR_EXEV8CPT_Msk (0x1UL << HRTIM_CPT1CR_EXEV8CPT_Pos) /*!< 0x00000200 */
+#define HRTIM_CPT1CR_EXEV8CPT HRTIM_CPT1CR_EXEV8CPT_Msk /*!< External event 8 capture */
+#define HRTIM_CPT1CR_EXEV9CPT_Pos (10U)
+#define HRTIM_CPT1CR_EXEV9CPT_Msk (0x1UL << HRTIM_CPT1CR_EXEV9CPT_Pos) /*!< 0x00000400 */
+#define HRTIM_CPT1CR_EXEV9CPT HRTIM_CPT1CR_EXEV9CPT_Msk /*!< External event 9 capture */
+#define HRTIM_CPT1CR_EXEV10CPT_Pos (11U)
+#define HRTIM_CPT1CR_EXEV10CPT_Msk (0x1UL << HRTIM_CPT1CR_EXEV10CPT_Pos) /*!< 0x00000800 */
+#define HRTIM_CPT1CR_EXEV10CPT HRTIM_CPT1CR_EXEV10CPT_Msk /*!< External event 10 capture */
+
+#define HRTIM_CPT1CR_TF1SET_Pos (0U)
+#define HRTIM_CPT1CR_TF1SET_Msk (0x1UL << HRTIM_CPT1CR_TF1SET_Pos) /*!< 0x00000001 */
+#define HRTIM_CPT1CR_TF1SET HRTIM_CPT1CR_TF1SET_Msk /*!< Timer F output 1 set */
+#define HRTIM_CPT1CR_TF1RST_Pos (1U)
+#define HRTIM_CPT1CR_TF1RST_Msk (0x1UL << HRTIM_CPT1CR_TF1RST_Pos) /*!< 0x00000002 */
+#define HRTIM_CPT1CR_TF1RST HRTIM_CPT1CR_TF1RST_Msk /*!< Timer F output 1 reset */
+#define HRTIM_CPT1CR_TIMFCMP1_Pos (2U)
+#define HRTIM_CPT1CR_TIMFCMP1_Msk (0x1UL << HRTIM_CPT1CR_TIMFCMP1_Pos) /*!< 0x00000004 */
+#define HRTIM_CPT1CR_TIMFCMP1 HRTIM_CPT1CR_TIMFCMP1_Msk /*!< Timer F compare 1 */
+#define HRTIM_CPT1CR_TIMFCMP2_Pos (3U)
+#define HRTIM_CPT1CR_TIMFCMP2_Msk (0x1UL << HRTIM_CPT1CR_TIMFCMP2_Pos) /*!< 0x00000008 */
+#define HRTIM_CPT1CR_TIMFCMP2 HRTIM_CPT1CR_TIMFCMP2_Msk /*!< Timer F compare 2 */
+
+#define HRTIM_CPT1CR_TA1SET_Pos (12U)
+#define HRTIM_CPT1CR_TA1SET_Msk (0x1UL << HRTIM_CPT1CR_TA1SET_Pos) /*!< 0x00001000 */
+#define HRTIM_CPT1CR_TA1SET HRTIM_CPT1CR_TA1SET_Msk /*!< Timer A output 1 set */
+#define HRTIM_CPT1CR_TA1RST_Pos (13U)
+#define HRTIM_CPT1CR_TA1RST_Msk (0x1UL << HRTIM_CPT1CR_TA1RST_Pos) /*!< 0x00002000 */
+#define HRTIM_CPT1CR_TA1RST HRTIM_CPT1CR_TA1RST_Msk /*!< Timer A output 1 reset */
+#define HRTIM_CPT1CR_TIMACMP1_Pos (14U)
+#define HRTIM_CPT1CR_TIMACMP1_Msk (0x1UL << HRTIM_CPT1CR_TIMACMP1_Pos) /*!< 0x00004000 */
+#define HRTIM_CPT1CR_TIMACMP1 HRTIM_CPT1CR_TIMACMP1_Msk /*!< Timer A compare 1 */
+#define HRTIM_CPT1CR_TIMACMP2_Pos (15U)
+#define HRTIM_CPT1CR_TIMACMP2_Msk (0x1UL << HRTIM_CPT1CR_TIMACMP2_Pos) /*!< 0x00008000 */
+#define HRTIM_CPT1CR_TIMACMP2 HRTIM_CPT1CR_TIMACMP2_Msk /*!< Timer A compare 2 */
+
+#define HRTIM_CPT1CR_TB1SET_Pos (16U)
+#define HRTIM_CPT1CR_TB1SET_Msk (0x1UL << HRTIM_CPT1CR_TB1SET_Pos) /*!< 0x00010000 */
+#define HRTIM_CPT1CR_TB1SET HRTIM_CPT1CR_TB1SET_Msk /*!< Timer B output 1 set */
+#define HRTIM_CPT1CR_TB1RST_Pos (17U)
+#define HRTIM_CPT1CR_TB1RST_Msk (0x1UL << HRTIM_CPT1CR_TB1RST_Pos) /*!< 0x00020000 */
+#define HRTIM_CPT1CR_TB1RST HRTIM_CPT1CR_TB1RST_Msk /*!< Timer B output 1 reset */
+#define HRTIM_CPT1CR_TIMBCMP1_Pos (18U)
+#define HRTIM_CPT1CR_TIMBCMP1_Msk (0x1UL << HRTIM_CPT1CR_TIMBCMP1_Pos) /*!< 0x00040000 */
+#define HRTIM_CPT1CR_TIMBCMP1 HRTIM_CPT1CR_TIMBCMP1_Msk /*!< Timer B compare 1 */
+#define HRTIM_CPT1CR_TIMBCMP2_Pos (19U)
+#define HRTIM_CPT1CR_TIMBCMP2_Msk (0x1UL << HRTIM_CPT1CR_TIMBCMP2_Pos) /*!< 0x00080000 */
+#define HRTIM_CPT1CR_TIMBCMP2 HRTIM_CPT1CR_TIMBCMP2_Msk /*!< Timer B compare 2 */
+
+#define HRTIM_CPT1CR_TC1SET_Pos (20U)
+#define HRTIM_CPT1CR_TC1SET_Msk (0x1UL << HRTIM_CPT1CR_TC1SET_Pos) /*!< 0x00100000 */
+#define HRTIM_CPT1CR_TC1SET HRTIM_CPT1CR_TC1SET_Msk /*!< Timer C output 1 set */
+#define HRTIM_CPT1CR_TC1RST_Pos (21U)
+#define HRTIM_CPT1CR_TC1RST_Msk (0x1UL << HRTIM_CPT1CR_TC1RST_Pos) /*!< 0x00200000 */
+#define HRTIM_CPT1CR_TC1RST HRTIM_CPT1CR_TC1RST_Msk /*!< Timer C output 1 reset */
+#define HRTIM_CPT1CR_TIMCCMP1_Pos (22U)
+#define HRTIM_CPT1CR_TIMCCMP1_Msk (0x1UL << HRTIM_CPT1CR_TIMCCMP1_Pos) /*!< 0x00400000 */
+#define HRTIM_CPT1CR_TIMCCMP1 HRTIM_CPT1CR_TIMCCMP1_Msk /*!< Timer C compare 1 */
+#define HRTIM_CPT1CR_TIMCCMP2_Pos (23U)
+#define HRTIM_CPT1CR_TIMCCMP2_Msk (0x1UL << HRTIM_CPT1CR_TIMCCMP2_Pos) /*!< 0x00800000 */
+#define HRTIM_CPT1CR_TIMCCMP2 HRTIM_CPT1CR_TIMCCMP2_Msk /*!< Timer C compare 2 */
+
+#define HRTIM_CPT1CR_TD1SET_Pos (24U)
+#define HRTIM_CPT1CR_TD1SET_Msk (0x1UL << HRTIM_CPT1CR_TD1SET_Pos) /*!< 0x01000000 */
+#define HRTIM_CPT1CR_TD1SET HRTIM_CPT1CR_TD1SET_Msk /*!< Timer D output 1 set */
+#define HRTIM_CPT1CR_TD1RST_Pos (25U)
+#define HRTIM_CPT1CR_TD1RST_Msk (0x1UL << HRTIM_CPT1CR_TD1RST_Pos) /*!< 0x02000000 */
+#define HRTIM_CPT1CR_TD1RST HRTIM_CPT1CR_TD1RST_Msk /*!< Timer D output 1 reset */
+#define HRTIM_CPT1CR_TIMDCMP1_Pos (26U)
+#define HRTIM_CPT1CR_TIMDCMP1_Msk (0x1UL << HRTIM_CPT1CR_TIMDCMP1_Pos) /*!< 0x04000000 */
+#define HRTIM_CPT1CR_TIMDCMP1 HRTIM_CPT1CR_TIMDCMP1_Msk /*!< Timer D compare 1 */
+#define HRTIM_CPT1CR_TIMDCMP2_Pos (27U)
+#define HRTIM_CPT1CR_TIMDCMP2_Msk (0x1UL << HRTIM_CPT1CR_TIMDCMP2_Pos) /*!< 0x08000000 */
+#define HRTIM_CPT1CR_TIMDCMP2 HRTIM_CPT1CR_TIMDCMP2_Msk /*!< Timer D compare 2 */
+
+#define HRTIM_CPT1CR_TE1SET_Pos (28U)
+#define HRTIM_CPT1CR_TE1SET_Msk (0x1UL << HRTIM_CPT1CR_TE1SET_Pos) /*!< 0x10000000 */
+#define HRTIM_CPT1CR_TE1SET HRTIM_CPT1CR_TE1SET_Msk /*!< Timer E output 1 set */
+#define HRTIM_CPT1CR_TE1RST_Pos (29U)
+#define HRTIM_CPT1CR_TE1RST_Msk (0x1UL << HRTIM_CPT1CR_TE1RST_Pos) /*!< 0x20000000 */
+#define HRTIM_CPT1CR_TE1RST HRTIM_CPT1CR_TE1RST_Msk /*!< Timer E output 1 reset */
+#define HRTIM_CPT1CR_TIMECMP1_Pos (30U)
+#define HRTIM_CPT1CR_TIMECMP1_Msk (0x1UL << HRTIM_CPT1CR_TIMECMP1_Pos) /*!< 0x40000000 */
+#define HRTIM_CPT1CR_TIMECMP1 HRTIM_CPT1CR_TIMECMP1_Msk /*!< Timer E compare 1 */
+#define HRTIM_CPT1CR_TIMECMP2_Pos (31U)
+#define HRTIM_CPT1CR_TIMECMP2_Msk (0x1UL << HRTIM_CPT1CR_TIMECMP2_Pos) /*!< 0x80000000 */
+#define HRTIM_CPT1CR_TIMECMP2 HRTIM_CPT1CR_TIMECMP2_Msk /*!< Timer E compare 2 */
+
+/**** Bit definition for Slave Timer Capture 2 control register ***************/
+#define HRTIM_CPT2CR_SWCPT_Pos (0U)
+#define HRTIM_CPT2CR_SWCPT_Msk (0x1UL << HRTIM_CPT2CR_SWCPT_Pos) /*!< 0x00000001 */
+#define HRTIM_CPT2CR_SWCPT HRTIM_CPT2CR_SWCPT_Msk /*!< Software capture */
+#define HRTIM_CPT2CR_UPDCPT_Pos (1U)
+#define HRTIM_CPT2CR_UPDCPT_Msk (0x1UL << HRTIM_CPT2CR_UPDCPT_Pos) /*!< 0x00000002 */
+#define HRTIM_CPT2CR_UPDCPT HRTIM_CPT2CR_UPDCPT_Msk /*!< Update capture */
+#define HRTIM_CPT2CR_EXEV1CPT_Pos (2U)
+#define HRTIM_CPT2CR_EXEV1CPT_Msk (0x1UL << HRTIM_CPT2CR_EXEV1CPT_Pos) /*!< 0x00000004 */
+#define HRTIM_CPT2CR_EXEV1CPT HRTIM_CPT2CR_EXEV1CPT_Msk /*!< External event 1 capture */
+#define HRTIM_CPT2CR_EXEV2CPT_Pos (3U)
+#define HRTIM_CPT2CR_EXEV2CPT_Msk (0x1UL << HRTIM_CPT2CR_EXEV2CPT_Pos) /*!< 0x00000008 */
+#define HRTIM_CPT2CR_EXEV2CPT HRTIM_CPT2CR_EXEV2CPT_Msk /*!< External event 2 capture */
+#define HRTIM_CPT2CR_EXEV3CPT_Pos (4U)
+#define HRTIM_CPT2CR_EXEV3CPT_Msk (0x1UL << HRTIM_CPT2CR_EXEV3CPT_Pos) /*!< 0x00000010 */
+#define HRTIM_CPT2CR_EXEV3CPT HRTIM_CPT2CR_EXEV3CPT_Msk /*!< External event 3 capture */
+#define HRTIM_CPT2CR_EXEV4CPT_Pos (5U)
+#define HRTIM_CPT2CR_EXEV4CPT_Msk (0x1UL << HRTIM_CPT2CR_EXEV4CPT_Pos) /*!< 0x00000020 */
+#define HRTIM_CPT2CR_EXEV4CPT HRTIM_CPT2CR_EXEV4CPT_Msk /*!< External event 4 capture */
+#define HRTIM_CPT2CR_EXEV5CPT_Pos (6U)
+#define HRTIM_CPT2CR_EXEV5CPT_Msk (0x1UL << HRTIM_CPT2CR_EXEV5CPT_Pos) /*!< 0x00000040 */
+#define HRTIM_CPT2CR_EXEV5CPT HRTIM_CPT2CR_EXEV5CPT_Msk /*!< External event 5 capture */
+#define HRTIM_CPT2CR_EXEV6CPT_Pos (7U)
+#define HRTIM_CPT2CR_EXEV6CPT_Msk (0x1UL << HRTIM_CPT2CR_EXEV6CPT_Pos) /*!< 0x00000080 */
+#define HRTIM_CPT2CR_EXEV6CPT HRTIM_CPT2CR_EXEV6CPT_Msk /*!< External event 6 capture */
+#define HRTIM_CPT2CR_EXEV7CPT_Pos (8U)
+#define HRTIM_CPT2CR_EXEV7CPT_Msk (0x1UL << HRTIM_CPT2CR_EXEV7CPT_Pos) /*!< 0x00000100 */
+#define HRTIM_CPT2CR_EXEV7CPT HRTIM_CPT2CR_EXEV7CPT_Msk /*!< External event 7 capture */
+#define HRTIM_CPT2CR_EXEV8CPT_Pos (9U)
+#define HRTIM_CPT2CR_EXEV8CPT_Msk (0x1UL << HRTIM_CPT2CR_EXEV8CPT_Pos) /*!< 0x00000200 */
+#define HRTIM_CPT2CR_EXEV8CPT HRTIM_CPT2CR_EXEV8CPT_Msk /*!< External event 8 capture */
+#define HRTIM_CPT2CR_EXEV9CPT_Pos (10U)
+#define HRTIM_CPT2CR_EXEV9CPT_Msk (0x1UL << HRTIM_CPT2CR_EXEV9CPT_Pos) /*!< 0x00000400 */
+#define HRTIM_CPT2CR_EXEV9CPT HRTIM_CPT2CR_EXEV9CPT_Msk /*!< External event 9 capture */
+#define HRTIM_CPT2CR_EXEV10CPT_Pos (11U)
+#define HRTIM_CPT2CR_EXEV10CPT_Msk (0x1UL << HRTIM_CPT2CR_EXEV10CPT_Pos) /*!< 0x00000800 */
+#define HRTIM_CPT2CR_EXEV10CPT HRTIM_CPT2CR_EXEV10CPT_Msk /*!< External event 10 capture */
+
+#define HRTIM_CPT2CR_TF1SET_Pos (0U)
+#define HRTIM_CPT2CR_TF1SET_Msk (0x1UL << HRTIM_CPT2CR_TF1SET_Pos) /*!< 0x00000001 */
+#define HRTIM_CPT2CR_TF1SET HRTIM_CPT2CR_TF1SET_Msk /*!< Timer F output 1 set */
+#define HRTIM_CPT2CR_TF1RST_Pos (1U)
+#define HRTIM_CPT2CR_TF1RST_Msk (0x1UL << HRTIM_CPT2CR_TF1RST_Pos) /*!< 0x00000002 */
+#define HRTIM_CPT2CR_TF1RST HRTIM_CPT2CR_TF1RST_Msk /*!< Timer F output 1 reset */
+#define HRTIM_CPT2CR_TIMFCMP1_Pos (2U)
+#define HRTIM_CPT2CR_TIMFCMP1_Msk (0x1UL << HRTIM_CPT2CR_TIMFCMP1_Pos) /*!< 0x00000004 */
+#define HRTIM_CPT2CR_TIMFCMP1 HRTIM_CPT2CR_TIMFCMP1_Msk /*!< Timer F compare 1 */
+#define HRTIM_CPT2CR_TIMFCMP2_Pos (3U)
+#define HRTIM_CPT2CR_TIMFCMP2_Msk (0x1UL << HRTIM_CPT2CR_TIMFCMP2_Pos) /*!< 0x00000008 */
+#define HRTIM_CPT2CR_TIMFCMP2 HRTIM_CPT2CR_TIMFCMP2_Msk /*!< Timer F compare 2 */
+
+#define HRTIM_CPT2CR_TA1SET_Pos (12U)
+#define HRTIM_CPT2CR_TA1SET_Msk (0x1UL << HRTIM_CPT2CR_TA1SET_Pos) /*!< 0x00001000 */
+#define HRTIM_CPT2CR_TA1SET HRTIM_CPT2CR_TA1SET_Msk /*!< Timer A output 1 set */
+#define HRTIM_CPT2CR_TA1RST_Pos (13U)
+#define HRTIM_CPT2CR_TA1RST_Msk (0x1UL << HRTIM_CPT2CR_TA1RST_Pos) /*!< 0x00002000 */
+#define HRTIM_CPT2CR_TA1RST HRTIM_CPT2CR_TA1RST_Msk /*!< Timer A output 1 reset */
+#define HRTIM_CPT2CR_TIMACMP1_Pos (14U)
+#define HRTIM_CPT2CR_TIMACMP1_Msk (0x1UL << HRTIM_CPT2CR_TIMACMP1_Pos) /*!< 0x00004000 */
+#define HRTIM_CPT2CR_TIMACMP1 HRTIM_CPT2CR_TIMACMP1_Msk /*!< Timer A compare 1 */
+#define HRTIM_CPT2CR_TIMACMP2_Pos (15U)
+#define HRTIM_CPT2CR_TIMACMP2_Msk (0x1UL << HRTIM_CPT2CR_TIMACMP2_Pos) /*!< 0x00008000 */
+#define HRTIM_CPT2CR_TIMACMP2 HRTIM_CPT2CR_TIMACMP2_Msk /*!< Timer A compare 2 */
+
+#define HRTIM_CPT2CR_TB1SET_Pos (16U)
+#define HRTIM_CPT2CR_TB1SET_Msk (0x1UL << HRTIM_CPT2CR_TB1SET_Pos) /*!< 0x00010000 */
+#define HRTIM_CPT2CR_TB1SET HRTIM_CPT2CR_TB1SET_Msk /*!< Timer B output 1 set */
+#define HRTIM_CPT2CR_TB1RST_Pos (17U)
+#define HRTIM_CPT2CR_TB1RST_Msk (0x1UL << HRTIM_CPT2CR_TB1RST_Pos) /*!< 0x00020000 */
+#define HRTIM_CPT2CR_TB1RST HRTIM_CPT2CR_TB1RST_Msk /*!< Timer B output 1 reset */
+#define HRTIM_CPT2CR_TIMBCMP1_Pos (18U)
+#define HRTIM_CPT2CR_TIMBCMP1_Msk (0x1UL << HRTIM_CPT2CR_TIMBCMP1_Pos) /*!< 0x00040000 */
+#define HRTIM_CPT2CR_TIMBCMP1 HRTIM_CPT2CR_TIMBCMP1_Msk /*!< Timer B compare 1 */
+#define HRTIM_CPT2CR_TIMBCMP2_Pos (19U)
+#define HRTIM_CPT2CR_TIMBCMP2_Msk (0x1UL << HRTIM_CPT2CR_TIMBCMP2_Pos) /*!< 0x00080000 */
+#define HRTIM_CPT2CR_TIMBCMP2 HRTIM_CPT2CR_TIMBCMP2_Msk /*!< Timer B compare 2 */
+
+#define HRTIM_CPT2CR_TC1SET_Pos (20U)
+#define HRTIM_CPT2CR_TC1SET_Msk (0x1UL << HRTIM_CPT2CR_TC1SET_Pos) /*!< 0x00100000 */
+#define HRTIM_CPT2CR_TC1SET HRTIM_CPT2CR_TC1SET_Msk /*!< Timer C output 1 set */
+#define HRTIM_CPT2CR_TC1RST_Pos (21U)
+#define HRTIM_CPT2CR_TC1RST_Msk (0x1UL << HRTIM_CPT2CR_TC1RST_Pos) /*!< 0x00200000 */
+#define HRTIM_CPT2CR_TC1RST HRTIM_CPT2CR_TC1RST_Msk /*!< Timer C output 1 reset */
+#define HRTIM_CPT2CR_TIMCCMP1_Pos (22U)
+#define HRTIM_CPT2CR_TIMCCMP1_Msk (0x1UL << HRTIM_CPT2CR_TIMCCMP1_Pos) /*!< 0x00400000 */
+#define HRTIM_CPT2CR_TIMCCMP1 HRTIM_CPT2CR_TIMCCMP1_Msk /*!< Timer C compare 1 */
+#define HRTIM_CPT2CR_TIMCCMP2_Pos (23U)
+#define HRTIM_CPT2CR_TIMCCMP2_Msk (0x1UL << HRTIM_CPT2CR_TIMCCMP2_Pos) /*!< 0x00800000 */
+#define HRTIM_CPT2CR_TIMCCMP2 HRTIM_CPT2CR_TIMCCMP2_Msk /*!< Timer C compare 2 */
+
+#define HRTIM_CPT2CR_TD1SET_Pos (24U)
+#define HRTIM_CPT2CR_TD1SET_Msk (0x1UL << HRTIM_CPT2CR_TD1SET_Pos) /*!< 0x01000000 */
+#define HRTIM_CPT2CR_TD1SET HRTIM_CPT2CR_TD1SET_Msk /*!< Timer D output 1 set */
+#define HRTIM_CPT2CR_TD1RST_Pos (25U)
+#define HRTIM_CPT2CR_TD1RST_Msk (0x1UL << HRTIM_CPT2CR_TD1RST_Pos) /*!< 0x02000000 */
+#define HRTIM_CPT2CR_TD1RST HRTIM_CPT2CR_TD1RST_Msk /*!< Timer D output 1 reset */
+#define HRTIM_CPT2CR_TIMDCMP1_Pos (26U)
+#define HRTIM_CPT2CR_TIMDCMP1_Msk (0x1UL << HRTIM_CPT2CR_TIMDCMP1_Pos) /*!< 0x04000000 */
+#define HRTIM_CPT2CR_TIMDCMP1 HRTIM_CPT2CR_TIMDCMP1_Msk /*!< Timer D compare 1 */
+#define HRTIM_CPT2CR_TIMDCMP2_Pos (27U)
+#define HRTIM_CPT2CR_TIMDCMP2_Msk (0x1UL << HRTIM_CPT2CR_TIMDCMP2_Pos) /*!< 0x08000000 */
+#define HRTIM_CPT2CR_TIMDCMP2 HRTIM_CPT2CR_TIMDCMP2_Msk /*!< Timer D compare 2 */
+
+#define HRTIM_CPT2CR_TE1SET_Pos (28U)
+#define HRTIM_CPT2CR_TE1SET_Msk (0x1UL << HRTIM_CPT2CR_TE1SET_Pos) /*!< 0x10000000 */
+#define HRTIM_CPT2CR_TE1SET HRTIM_CPT2CR_TE1SET_Msk /*!< Timer E output 1 set */
+#define HRTIM_CPT2CR_TE1RST_Pos (29U)
+#define HRTIM_CPT2CR_TE1RST_Msk (0x1UL << HRTIM_CPT2CR_TE1RST_Pos) /*!< 0x20000000 */
+#define HRTIM_CPT2CR_TE1RST HRTIM_CPT2CR_TE1RST_Msk /*!< Timer E output 1 reset */
+#define HRTIM_CPT2CR_TIMECMP1_Pos (30U)
+#define HRTIM_CPT2CR_TIMECMP1_Msk (0x1UL << HRTIM_CPT2CR_TIMECMP1_Pos) /*!< 0x40000000 */
+#define HRTIM_CPT2CR_TIMECMP1 HRTIM_CPT2CR_TIMECMP1_Msk /*!< Timer E compare 1 */
+#define HRTIM_CPT2CR_TIMECMP2_Pos (31U)
+#define HRTIM_CPT2CR_TIMECMP2_Msk (0x1UL << HRTIM_CPT2CR_TIMECMP2_Pos) /*!< 0x80000000 */
+#define HRTIM_CPT2CR_TIMECMP2 HRTIM_CPT2CR_TIMECMP2_Msk /*!< Timer E compare 2 */
+
+/**** Bit definition for Slave Timer Output register **************************/
+#define HRTIM_OUTR_POL1_Pos (1U)
+#define HRTIM_OUTR_POL1_Msk (0x1UL << HRTIM_OUTR_POL1_Pos) /*!< 0x00000002 */
+#define HRTIM_OUTR_POL1 HRTIM_OUTR_POL1_Msk /*!< Slave output 1 polarity */
+#define HRTIM_OUTR_IDLM1_Pos (2U)
+#define HRTIM_OUTR_IDLM1_Msk (0x1UL << HRTIM_OUTR_IDLM1_Pos) /*!< 0x00000004 */
+#define HRTIM_OUTR_IDLM1 HRTIM_OUTR_IDLM1_Msk /*!< Slave output 1 idle mode */
+#define HRTIM_OUTR_IDLES1_Pos (3U)
+#define HRTIM_OUTR_IDLES1_Msk (0x1UL << HRTIM_OUTR_IDLES1_Pos) /*!< 0x00000008 */
+#define HRTIM_OUTR_IDLES1 HRTIM_OUTR_IDLES1_Msk /*!< Slave output 1 idle state */
+#define HRTIM_OUTR_FAULT1_Pos (4U)
+#define HRTIM_OUTR_FAULT1_Msk (0x3UL << HRTIM_OUTR_FAULT1_Pos) /*!< 0x00000030 */
+#define HRTIM_OUTR_FAULT1 HRTIM_OUTR_FAULT1_Msk /*!< Slave output 1 fault state */
+#define HRTIM_OUTR_FAULT1_0 (0x1UL << HRTIM_OUTR_FAULT1_Pos) /*!< 0x00000010 */
+#define HRTIM_OUTR_FAULT1_1 (0x2UL << HRTIM_OUTR_FAULT1_Pos) /*!< 0x00000020 */
+#define HRTIM_OUTR_CHP1_Pos (6U)
+#define HRTIM_OUTR_CHP1_Msk (0x1UL << HRTIM_OUTR_CHP1_Pos) /*!< 0x00000040 */
+#define HRTIM_OUTR_CHP1 HRTIM_OUTR_CHP1_Msk /*!< Slave output 1 chopper enable */
+#define HRTIM_OUTR_DIDL1_Pos (7U)
+#define HRTIM_OUTR_DIDL1_Msk (0x1UL << HRTIM_OUTR_DIDL1_Pos) /*!< 0x00000080 */
+#define HRTIM_OUTR_DIDL1 HRTIM_OUTR_DIDL1_Msk /*!< Slave output 1 dead time idle */
+
+#define HRTIM_OUTR_DTEN_Pos (8U)
+#define HRTIM_OUTR_DTEN_Msk (0x1UL << HRTIM_OUTR_DTEN_Pos) /*!< 0x00000100 */
+#define HRTIM_OUTR_DTEN HRTIM_OUTR_DTEN_Msk /*!< Slave output deadtime enable */
+#define HRTIM_OUTR_DLYPRTEN_Pos (9U)
+#define HRTIM_OUTR_DLYPRTEN_Msk (0x1UL << HRTIM_OUTR_DLYPRTEN_Pos) /*!< 0x00000200 */
+#define HRTIM_OUTR_DLYPRTEN HRTIM_OUTR_DLYPRTEN_Msk /*!< Slave output delay protection enable */
+#define HRTIM_OUTR_DLYPRT_Pos (10U)
+#define HRTIM_OUTR_DLYPRT_Msk (0x7UL << HRTIM_OUTR_DLYPRT_Pos) /*!< 0x00001C00 */
+#define HRTIM_OUTR_DLYPRT HRTIM_OUTR_DLYPRT_Msk /*!< Slave output delay protection */
+#define HRTIM_OUTR_DLYPRT_0 (0x1UL << HRTIM_OUTR_DLYPRT_Pos) /*!< 0x00000400 */
+#define HRTIM_OUTR_DLYPRT_1 (0x2UL << HRTIM_OUTR_DLYPRT_Pos) /*!< 0x00000800 */
+#define HRTIM_OUTR_DLYPRT_2 (0x4UL << HRTIM_OUTR_DLYPRT_Pos) /*!< 0x00001000 */
+#define HRTIM_OUTR_BIAR_Pos (14U)
+#define HRTIM_OUTR_BIAR_Msk (0x1UL << HRTIM_OUTR_BIAR_Pos) /*!< 0x00004000 */
+#define HRTIM_OUTR_BIAR HRTIM_OUTR_BIAR_Msk /*!< Slave output Balanced Idle Automatic resume */
+#define HRTIM_OUTR_POL2_Pos (17U)
+#define HRTIM_OUTR_POL2_Msk (0x1UL << HRTIM_OUTR_POL2_Pos) /*!< 0x00020000 */
+#define HRTIM_OUTR_POL2 HRTIM_OUTR_POL2_Msk /*!< Slave output 2 polarity */
+#define HRTIM_OUTR_IDLM2_Pos (18U)
+#define HRTIM_OUTR_IDLM2_Msk (0x1UL << HRTIM_OUTR_IDLM2_Pos) /*!< 0x00040000 */
+#define HRTIM_OUTR_IDLM2 HRTIM_OUTR_IDLM2_Msk /*!< Slave output 2 idle mode */
+#define HRTIM_OUTR_IDLES2_Pos (19U)
+#define HRTIM_OUTR_IDLES2_Msk (0x1UL << HRTIM_OUTR_IDLES2_Pos) /*!< 0x00080000 */
+#define HRTIM_OUTR_IDLES2 HRTIM_OUTR_IDLES2_Msk /*!< Slave output 2 idle state */
+#define HRTIM_OUTR_FAULT2_Pos (20U)
+#define HRTIM_OUTR_FAULT2_Msk (0x3UL << HRTIM_OUTR_FAULT2_Pos) /*!< 0x00300000 */
+#define HRTIM_OUTR_FAULT2 HRTIM_OUTR_FAULT2_Msk /*!< Slave output 2 fault state */
+#define HRTIM_OUTR_FAULT2_0 (0x1UL << HRTIM_OUTR_FAULT2_Pos) /*!< 0x00100000 */
+#define HRTIM_OUTR_FAULT2_1 (0x2UL << HRTIM_OUTR_FAULT2_Pos) /*!< 0x00200000 */
+#define HRTIM_OUTR_CHP2_Pos (22U)
+#define HRTIM_OUTR_CHP2_Msk (0x1UL << HRTIM_OUTR_CHP2_Pos) /*!< 0x00400000 */
+#define HRTIM_OUTR_CHP2 HRTIM_OUTR_CHP2_Msk /*!< Slave output 2 chopper enable */
+#define HRTIM_OUTR_DIDL2_Pos (23U)
+#define HRTIM_OUTR_DIDL2_Msk (0x1UL << HRTIM_OUTR_DIDL2_Pos) /*!< 0x00800000 */
+#define HRTIM_OUTR_DIDL2 HRTIM_OUTR_DIDL2_Msk /*!< Slave output 2 dead time idle */
+
+/**** Bit definition for Timerx Fault register ***************************/
+#define HRTIM_FLTR_FLT1EN_Pos (0U)
+#define HRTIM_FLTR_FLT1EN_Msk (0x1UL << HRTIM_FLTR_FLT1EN_Pos) /*!< 0x00000001 */
+#define HRTIM_FLTR_FLT1EN HRTIM_FLTR_FLT1EN_Msk /*!< Fault 1 enable */
+#define HRTIM_FLTR_FLT2EN_Pos (1U)
+#define HRTIM_FLTR_FLT2EN_Msk (0x1UL << HRTIM_FLTR_FLT2EN_Pos) /*!< 0x00000002 */
+#define HRTIM_FLTR_FLT2EN HRTIM_FLTR_FLT2EN_Msk /*!< Fault 2 enable */
+#define HRTIM_FLTR_FLT3EN_Pos (2U)
+#define HRTIM_FLTR_FLT3EN_Msk (0x1UL << HRTIM_FLTR_FLT3EN_Pos) /*!< 0x00000004 */
+#define HRTIM_FLTR_FLT3EN HRTIM_FLTR_FLT3EN_Msk /*!< Fault 3 enable */
+#define HRTIM_FLTR_FLT4EN_Pos (3U)
+#define HRTIM_FLTR_FLT4EN_Msk (0x1UL << HRTIM_FLTR_FLT4EN_Pos) /*!< 0x00000008 */
+#define HRTIM_FLTR_FLT4EN HRTIM_FLTR_FLT4EN_Msk /*!< Fault 4 enable */
+#define HRTIM_FLTR_FLT5EN_Pos (4U)
+#define HRTIM_FLTR_FLT5EN_Msk (0x1UL << HRTIM_FLTR_FLT5EN_Pos) /*!< 0x00000010 */
+#define HRTIM_FLTR_FLT5EN HRTIM_FLTR_FLT5EN_Msk /*!< Fault 5 enable */
+#define HRTIM_FLTR_FLT6EN_Pos (5U)
+#define HRTIM_FLTR_FLT6EN_Msk (0x1UL << HRTIM_FLTR_FLT6EN_Pos) /*!< 0x00000020 */
+#define HRTIM_FLTR_FLT6EN HRTIM_FLTR_FLT6EN_Msk /*!< Fault 6 enable */
+#define HRTIM_FLTR_FLTLCK_Pos (31U)
+#define HRTIM_FLTR_FLTLCK_Msk (0x1UL << HRTIM_FLTR_FLTLCK_Pos) /*!< 0x80000000 */
+#define HRTIM_FLTR_FLTLCK HRTIM_FLTR_FLTLCK_Msk /*!< Fault sources lock */
+
+/**** Bit definition for HRTIM Timerx control register 2 ****************/
+#define HRTIM_TIMCR2_DCDE_Pos (0U)
+#define HRTIM_TIMCR2_DCDE_Msk (0x1UL << HRTIM_TIMCR2_DCDE_Pos) /*!< 0x00000001 */
+#define HRTIM_TIMCR2_DCDE HRTIM_TIMCR2_DCDE_Msk /*!< Dual Channel DAC trigger enable */
+#define HRTIM_TIMCR2_DCDS_Pos (1U)
+#define HRTIM_TIMCR2_DCDS_Msk (0x1UL << HRTIM_TIMCR2_DCDS_Pos) /*!< 0x00000002 */
+#define HRTIM_TIMCR2_DCDS HRTIM_TIMCR2_DCDS_Msk /*!< Dual Channel DAC step trigger */
+#define HRTIM_TIMCR2_DCDR_Pos (2U)
+#define HRTIM_TIMCR2_DCDR_Msk (0x1UL << HRTIM_TIMCR2_DCDR_Pos) /*!< 0x00000004 */
+#define HRTIM_TIMCR2_DCDR HRTIM_TIMCR2_DCDR_Msk /*!< Dual Channel DAC reset trigger */
+#define HRTIM_TIMCR2_UDM_Pos (4U)
+#define HRTIM_TIMCR2_UDM_Msk (0x1UL << HRTIM_TIMCR2_UDM_Pos) /*!< 0x00000010 */
+#define HRTIM_TIMCR2_UDM HRTIM_TIMCR2_UDM_Msk /*!< Up-Down Mode*/
+#define HRTIM_TIMCR2_ROM_Pos (6U)
+#define HRTIM_TIMCR2_ROM_Msk (0x3UL << HRTIM_TIMCR2_ROM_Pos) /*!< 0x000000C0 */
+#define HRTIM_TIMCR2_ROM HRTIM_TIMCR2_ROM_Msk /*!< Roll-over Mode */
+#define HRTIM_TIMCR2_ROM_0 (0x1UL << HRTIM_TIMCR2_ROM_Pos) /*!< 0x00000040 */
+#define HRTIM_TIMCR2_ROM_1 (0x2UL << HRTIM_TIMCR2_ROM_Pos) /*!< 0x00000080 */
+#define HRTIM_TIMCR2_OUTROM_Pos (8U)
+#define HRTIM_TIMCR2_OUTROM_Msk (0x3UL << HRTIM_TIMCR2_OUTROM_Pos) /*!< 0x00000300 */
+#define HRTIM_TIMCR2_OUTROM HRTIM_TIMCR2_OUTROM_Msk /*!< Output Roll-Over Mode */
+#define HRTIM_TIMCR2_OUTROM_0 (0x1UL << HRTIM_TIMCR2_OUTROM_Pos) /*!< 0x00000100 */
+#define HRTIM_TIMCR2_OUTROM_1 (0x2UL << HRTIM_TIMCR2_OUTROM_Pos) /*!< 0x00000200 */
+#define HRTIM_TIMCR2_ADROM_Pos (10U)
+#define HRTIM_TIMCR2_ADROM_Msk (0x3UL << HRTIM_TIMCR2_ADROM_Pos) /*!< 0x00000C00 */
+#define HRTIM_TIMCR2_ADROM HRTIM_TIMCR2_ADROM_Msk /*!< ADC Roll-Over Mode */
+#define HRTIM_TIMCR2_ADROM_0 (0x1UL << HRTIM_TIMCR2_ADROM_Pos) /*!< 0x00000400 */
+#define HRTIM_TIMCR2_ADROM_1 (0x2UL << HRTIM_TIMCR2_ADROM_Pos) /*!< 0x00000800 */
+#define HRTIM_TIMCR2_BMROM_Pos (12U)
+#define HRTIM_TIMCR2_BMROM_Msk (0x3UL << HRTIM_TIMCR2_BMROM_Pos) /*!< 0x00003000 */
+#define HRTIM_TIMCR2_BMROM HRTIM_TIMCR2_BMROM_Msk /*!< Burst Mode Rollover Mode */
+#define HRTIM_TIMCR2_BMROM_0 (0x1UL << HRTIM_TIMCR2_BMROM_Pos) /*!< 0x00001000 */
+#define HRTIM_TIMCR2_BMROM_1 (0x2UL << HRTIM_TIMCR2_BMROM_Pos) /*!< 0x00002000 */
+#define HRTIM_TIMCR2_FEROM_Pos (14U)
+#define HRTIM_TIMCR2_FEROM_Msk (0x3UL << HRTIM_TIMCR2_FEROM_Pos) /*!< 0x0000C000 */
+#define HRTIM_TIMCR2_FEROM HRTIM_TIMCR2_FEROM_Msk /*!< Fault and Event Rollover Mode */
+#define HRTIM_TIMCR2_FEROM_0 (0x1UL << HRTIM_TIMCR2_FEROM_Pos) /*!< 0x00004000 */
+#define HRTIM_TIMCR2_FEROM_1 (0x2UL << HRTIM_TIMCR2_FEROM_Pos) /*!< 0x00008000 */
+#define HRTIM_TIMCR2_GTCMP1_Pos (16U)
+#define HRTIM_TIMCR2_GTCMP1_Msk (0x1UL << HRTIM_TIMCR2_GTCMP1_Pos) /*!< 0x00010000 */
+#define HRTIM_TIMCR2_GTCMP1 HRTIM_TIMCR2_GTCMP1_Msk /*!< Greater than Compare 1 PWM mode */
+#define HRTIM_TIMCR2_GTCMP3_Pos (17U)
+#define HRTIM_TIMCR2_GTCMP3_Msk (0x1UL << HRTIM_TIMCR2_GTCMP3_Pos) /*!< 0x00020000 */
+#define HRTIM_TIMCR2_GTCMP3 HRTIM_TIMCR2_GTCMP3_Msk /*!< Greater than Compare 3 PWM mode */
+#define HRTIM_TIMCR2_TRGHLF_Pos (20U)
+#define HRTIM_TIMCR2_TRGHLF_Msk (0x1UL << HRTIM_TIMCR2_TRGHLF_Pos) /*!< 0x00100000 */
+#define HRTIM_TIMCR2_TRGHLF HRTIM_TIMCR2_TRGHLF_Msk /*!< Triggered-Half mode */
+
+/**** Bit definition for Slave external event filtering register 3 ***********/
+#define HRTIM_EEFR3_EEVACE_Pos (0U)
+#define HRTIM_EEFR3_EEVACE_Msk (0x1UL << HRTIM_EEFR3_EEVACE_Pos) /*!< 0x00000001 */
+#define HRTIM_EEFR3_EEVACE HRTIM_EEFR3_EEVACE_Msk /*!< External Event A Counter Enable */
+#define HRTIM_EEFR3_EEVACRES_Pos (1U)
+#define HRTIM_EEFR3_EEVACRES_Msk (0x1UL << HRTIM_EEFR3_EEVACRES_Pos) /*!< 0x00000002 */
+#define HRTIM_EEFR3_EEVACRES HRTIM_EEFR3_EEVACRES_Msk /*!< External Event A Counter Reset */
+#define HRTIM_EEFR3_EEVARSTM_Pos (2U)
+#define HRTIM_EEFR3_EEVARSTM_Msk (0x1UL << HRTIM_EEFR3_EEVARSTM_Pos) /*!< 0x00000004 */
+#define HRTIM_EEFR3_EEVARSTM HRTIM_EEFR3_EEVARSTM_Msk /*!< External Event A Counter Reset Mode */
+#define HRTIM_EEFR3_EEVASEL_Pos (4U)
+#define HRTIM_EEFR3_EEVASEL_Msk (0xFUL << HRTIM_EEFR3_EEVASEL_Pos) /*!< 0x000000F0 */
+#define HRTIM_EEFR3_EEVASEL HRTIM_EEFR3_EEVASEL_Msk /*!< External Event A Selection */
+#define HRTIM_EEFR3_EEVASEL_0 (0x1UL << HRTIM_EEFR3_EEVASEL_Pos) /*!< 0x00000010 */
+#define HRTIM_EEFR3_EEVASEL_1 (0x2UL << HRTIM_EEFR3_EEVASEL_Pos) /*!< 0x00000020 */
+#define HRTIM_EEFR3_EEVASEL_2 (0x4UL << HRTIM_EEFR3_EEVASEL_Pos) /*!< 0x00000040 */
+#define HRTIM_EEFR3_EEVASEL_3 (0x8UL << HRTIM_EEFR3_EEVASEL_Pos) /*!< 0x00000080 */
+#define HRTIM_EEFR3_EEVACNT_Pos (8U)
+#define HRTIM_EEFR3_EEVACNT_Msk (0x3FUL << HRTIM_EEFR3_EEVACNT_Pos) /*!< 0x00003F00 */
+#define HRTIM_EEFR3_EEVACNT HRTIM_EEFR3_EEVACNT_Msk /*!< External Event A Selection */
+#define HRTIM_EEFR3_EEVACNT_0 (0x1UL << HRTIM_EEFR3_EEVACNT_Pos) /*!< 0x00000100 */
+#define HRTIM_EEFR3_EEVACNT_1 (0x2UL << HRTIM_EEFR3_EEVACNT_Pos) /*!< 0x00000200 */
+#define HRTIM_EEFR3_EEVACNT_2 (0x4UL << HRTIM_EEFR3_EEVACNT_Pos) /*!< 0x00000400 */
+#define HRTIM_EEFR3_EEVACNT_3 (0x8UL << HRTIM_EEFR3_EEVACNT_Pos) /*!< 0x00000800 */
+#define HRTIM_EEFR3_EEVACNT_4 (0x10UL << HRTIM_EEFR3_EEVACNT_Pos) /*!< 0x00001000 */
+#define HRTIM_EEFR3_EEVACNT_5 (0x20UL << HRTIM_EEFR3_EEVACNT_Pos) /*!< 0x00002000 */
+#define HRTIM_EEFR3_EEVBCE_Pos (16U)
+#define HRTIM_EEFR3_EEVBCE_Msk (0x1UL << HRTIM_EEFR3_EEVBCE_Pos) /*!< 0x00010000 */
+#define HRTIM_EEFR3_EEVBCE HRTIM_EEFR3_EEVBCE_Msk /*!< External Event B Counter Enable */
+#define HRTIM_EEFR3_EEVBCRES_Pos (17U)
+#define HRTIM_EEFR3_EEVBCRES_Msk (0x1UL << HRTIM_EEFR3_EEVBCRES_Pos) /*!< 0x00020000 */
+#define HRTIM_EEFR3_EEVBCRES HRTIM_EEFR3_EEVBCRES_Msk /*!< External Event B Counter Reset */
+#define HRTIM_EEFR3_EEVBRSTM_Pos (18U)
+#define HRTIM_EEFR3_EEVBRSTM_Msk (0x1UL << HRTIM_EEFR3_EEVBRSTM_Pos) /*!< 0x00040000 */
+#define HRTIM_EEFR3_EEVBRSTM HRTIM_EEFR3_EEVBRSTM_Msk /*!< External Event B Counter Reset Mode */
+#define HRTIM_EEFR3_EEVBSEL_Pos (20U)
+#define HRTIM_EEFR3_EEVBSEL_Msk (0xFUL << HRTIM_EEFR3_EEVBSEL_Pos) /*!< 0x00F00000 */
+#define HRTIM_EEFR3_EEVBSEL HRTIM_EEFR3_EEVBSEL_Msk /*!< External Event B Selection */
+#define HRTIM_EEFR3_EEVBSEL_0 (0x1UL << HRTIM_EEFR3_EEVBSEL_Pos) /*!< 0x00100000 */
+#define HRTIM_EEFR3_EEVBSEL_1 (0x2UL << HRTIM_EEFR3_EEVBSEL_Pos) /*!< 0x00200000 */
+#define HRTIM_EEFR3_EEVBSEL_2 (0x4UL << HRTIM_EEFR3_EEVBSEL_Pos) /*!< 0x00400000 */
+#define HRTIM_EEFR3_EEVBSEL_3 (0x8UL << HRTIM_EEFR3_EEVBSEL_Pos) /*!< 0x00800000 */
+#define HRTIM_EEFR3_EEVBCNT_Pos (24U)
+#define HRTIM_EEFR3_EEVBCNT_Msk (0x3FUL << HRTIM_EEFR3_EEVBCNT_Pos) /*!< 0x3F000000 */
+#define HRTIM_EEFR3_EEVBCNT HRTIM_EEFR3_EEVBCNT_Msk /*!< External Event B Counter */
+#define HRTIM_EEFR3_EEVBCNT_0 (0x1UL << HRTIM_EEFR3_EEVBCNT_Pos) /*!< 0x01000000 */
+#define HRTIM_EEFR3_EEVBCNT_1 (0x2UL << HRTIM_EEFR3_EEVBCNT_Pos) /*!< 0x02000000 */
+#define HRTIM_EEFR3_EEVBCNT_2 (0x4UL << HRTIM_EEFR3_EEVBCNT_Pos) /*!< 0x04000000 */
+#define HRTIM_EEFR3_EEVBCNT_3 (0x8UL << HRTIM_EEFR3_EEVBCNT_Pos) /*!< 0x08000000 */
+#define HRTIM_EEFR3_EEVBCNT_4 (0x10UL << HRTIM_EEFR3_EEVACNT_Pos) /*!< 0x10000000 */
+#define HRTIM_EEFR3_EEVBCNT_5 (0x20UL << HRTIM_EEFR3_EEVACNT_Pos) /*!< 0x20000000 */
+
+/**** Bit definition for Common HRTIM Timer control register 1 ****************/
+#define HRTIM_CR1_MUDIS_Pos (0U)
+#define HRTIM_CR1_MUDIS_Msk (0x1UL << HRTIM_CR1_MUDIS_Pos) /*!< 0x00000001 */
+#define HRTIM_CR1_MUDIS HRTIM_CR1_MUDIS_Msk /*!< Master update disable*/
+#define HRTIM_CR1_TAUDIS_Pos (1U)
+#define HRTIM_CR1_TAUDIS_Msk (0x1UL << HRTIM_CR1_TAUDIS_Pos) /*!< 0x00000002 */
+#define HRTIM_CR1_TAUDIS HRTIM_CR1_TAUDIS_Msk /*!< Timer A update disable*/
+#define HRTIM_CR1_TBUDIS_Pos (2U)
+#define HRTIM_CR1_TBUDIS_Msk (0x1UL << HRTIM_CR1_TBUDIS_Pos) /*!< 0x00000004 */
+#define HRTIM_CR1_TBUDIS HRTIM_CR1_TBUDIS_Msk /*!< Timer B update disable*/
+#define HRTIM_CR1_TCUDIS_Pos (3U)
+#define HRTIM_CR1_TCUDIS_Msk (0x1UL << HRTIM_CR1_TCUDIS_Pos) /*!< 0x00000008 */
+#define HRTIM_CR1_TCUDIS HRTIM_CR1_TCUDIS_Msk /*!< Timer C update disable*/
+#define HRTIM_CR1_TDUDIS_Pos (4U)
+#define HRTIM_CR1_TDUDIS_Msk (0x1UL << HRTIM_CR1_TDUDIS_Pos) /*!< 0x00000010 */
+#define HRTIM_CR1_TDUDIS HRTIM_CR1_TDUDIS_Msk /*!< Timer D update disable*/
+#define HRTIM_CR1_TEUDIS_Pos (5U)
+#define HRTIM_CR1_TEUDIS_Msk (0x1UL << HRTIM_CR1_TEUDIS_Pos) /*!< 0x00000020 */
+#define HRTIM_CR1_TEUDIS HRTIM_CR1_TEUDIS_Msk /*!< Timer E update disable*/
+#define HRTIM_CR1_TFUDIS_Pos (6U)
+#define HRTIM_CR1_TFUDIS_Msk (0x1UL << HRTIM_CR1_TFUDIS_Pos) /*!< 0x00000040 */
+#define HRTIM_CR1_TFUDIS HRTIM_CR1_TFUDIS_Msk /*!< Timer F update disable*/
+#define HRTIM_CR1_ADC1USRC_Pos (16U)
+#define HRTIM_CR1_ADC1USRC_Msk (0x7UL << HRTIM_CR1_ADC1USRC_Pos) /*!< 0x00070000 */
+#define HRTIM_CR1_ADC1USRC HRTIM_CR1_ADC1USRC_Msk /*!< ADC Trigger 1 update source */
+#define HRTIM_CR1_ADC1USRC_0 (0x1UL << HRTIM_CR1_ADC1USRC_Pos) /*!< 0x00010000 */
+#define HRTIM_CR1_ADC1USRC_1 (0x2UL << HRTIM_CR1_ADC1USRC_Pos) /*!< 0x00020000 */
+#define HRTIM_CR1_ADC1USRC_2 (0x4UL << HRTIM_CR1_ADC1USRC_Pos) /*!< 0x00040000 */
+#define HRTIM_CR1_ADC2USRC_Pos (19U)
+#define HRTIM_CR1_ADC2USRC_Msk (0x7UL << HRTIM_CR1_ADC2USRC_Pos) /*!< 0x00380000 */
+#define HRTIM_CR1_ADC2USRC HRTIM_CR1_ADC2USRC_Msk /*!< ADC Trigger 2 update source */
+#define HRTIM_CR1_ADC2USRC_0 (0x1UL << HRTIM_CR1_ADC2USRC_Pos) /*!< 0x00080000 */
+#define HRTIM_CR1_ADC2USRC_1 (0x2UL << HRTIM_CR1_ADC2USRC_Pos) /*!< 0x00100000 */
+#define HRTIM_CR1_ADC2USRC_2 (0x4UL << HRTIM_CR1_ADC2USRC_Pos) /*!< 0x00200000 */
+#define HRTIM_CR1_ADC3USRC_Pos (22U)
+#define HRTIM_CR1_ADC3USRC_Msk (0x7UL << HRTIM_CR1_ADC3USRC_Pos) /*!< 0x01C00000 */
+#define HRTIM_CR1_ADC3USRC HRTIM_CR1_ADC3USRC_Msk /*!< ADC Trigger 3 update source */
+#define HRTIM_CR1_ADC3USRC_0 (0x1UL << HRTIM_CR1_ADC3USRC_Pos) /*!< 0x00400000 */
+#define HRTIM_CR1_ADC3USRC_1 (0x2UL << HRTIM_CR1_ADC3USRC_Pos) /*!< 0x00800000 */
+#define HRTIM_CR1_ADC3USRC_2 (0x4UL << HRTIM_CR1_ADC3USRC_Pos) /*!< 0x01000000 */
+#define HRTIM_CR1_ADC4USRC_Pos (25U)
+#define HRTIM_CR1_ADC4USRC_Msk (0x7UL << HRTIM_CR1_ADC4USRC_Pos) /*!< 0x0E000000 */
+#define HRTIM_CR1_ADC4USRC HRTIM_CR1_ADC4USRC_Msk /*!< ADC Trigger 4 update source */
+#define HRTIM_CR1_ADC4USRC_0 (0x1UL << HRTIM_CR1_ADC4USRC_Pos) /*!< 0x02000000 */
+#define HRTIM_CR1_ADC4USRC_1 (0x2UL << HRTIM_CR1_ADC4USRC_Pos) /*!< 0x04000000 */
+#define HRTIM_CR1_ADC4USRC_2 (0x0UL << HRTIM_CR1_ADC4USRC_Pos) /*!< 0x0800000 */
+
+/**** Bit definition for Common HRTIM Timer control register 2 ****************/
+#define HRTIM_CR2_MSWU_Pos (0U)
+#define HRTIM_CR2_MSWU_Msk (0x1UL << HRTIM_CR2_MSWU_Pos) /*!< 0x00000001 */
+#define HRTIM_CR2_MSWU HRTIM_CR2_MSWU_Msk /*!< Master software update */
+#define HRTIM_CR2_TASWU_Pos (1U)
+#define HRTIM_CR2_TASWU_Msk (0x1UL << HRTIM_CR2_TASWU_Pos) /*!< 0x00000002 */
+#define HRTIM_CR2_TASWU HRTIM_CR2_TASWU_Msk /*!< Timer A software update */
+#define HRTIM_CR2_TBSWU_Pos (2U)
+#define HRTIM_CR2_TBSWU_Msk (0x1UL << HRTIM_CR2_TBSWU_Pos) /*!< 0x00000004 */
+#define HRTIM_CR2_TBSWU HRTIM_CR2_TBSWU_Msk /*!< Timer B software update */
+#define HRTIM_CR2_TCSWU_Pos (3U)
+#define HRTIM_CR2_TCSWU_Msk (0x1UL << HRTIM_CR2_TCSWU_Pos) /*!< 0x00000008 */
+#define HRTIM_CR2_TCSWU HRTIM_CR2_TCSWU_Msk /*!< Timer C software update */
+#define HRTIM_CR2_TDSWU_Pos (4U)
+#define HRTIM_CR2_TDSWU_Msk (0x1UL << HRTIM_CR2_TDSWU_Pos) /*!< 0x00000010 */
+#define HRTIM_CR2_TDSWU HRTIM_CR2_TDSWU_Msk /*!< Timer D software update */
+#define HRTIM_CR2_TESWU_Pos (5U)
+#define HRTIM_CR2_TESWU_Msk (0x1UL << HRTIM_CR2_TESWU_Pos) /*!< 0x00000020 */
+#define HRTIM_CR2_TESWU HRTIM_CR2_TESWU_Msk /*!< Timer E software update */
+#define HRTIM_CR2_TFSWU_Pos (6U)
+#define HRTIM_CR2_TFSWU_Msk (0x1UL << HRTIM_CR2_TFSWU_Pos) /*!< 0x00000040 */
+#define HRTIM_CR2_TFSWU HRTIM_CR2_TFSWU_Msk /*!< Timer F software update */
+#define HRTIM_CR2_MRST_Pos (8U)
+#define HRTIM_CR2_MRST_Msk (0x1UL << HRTIM_CR2_MRST_Pos) /*!< 0x00000100 */
+#define HRTIM_CR2_MRST HRTIM_CR2_MRST_Msk /*!< Master count software reset */
+#define HRTIM_CR2_TARST_Pos (9U)
+#define HRTIM_CR2_TARST_Msk (0x1UL << HRTIM_CR2_TARST_Pos) /*!< 0x00000200 */
+#define HRTIM_CR2_TARST HRTIM_CR2_TARST_Msk /*!< Timer A count software reset */
+#define HRTIM_CR2_TBRST_Pos (10U)
+#define HRTIM_CR2_TBRST_Msk (0x1UL << HRTIM_CR2_TBRST_Pos) /*!< 0x00000400 */
+#define HRTIM_CR2_TBRST HRTIM_CR2_TBRST_Msk /*!< Timer B count software reset */
+#define HRTIM_CR2_TCRST_Pos (11U)
+#define HRTIM_CR2_TCRST_Msk (0x1UL << HRTIM_CR2_TCRST_Pos) /*!< 0x00000800 */
+#define HRTIM_CR2_TCRST HRTIM_CR2_TCRST_Msk /*!< Timer C count software reset */
+#define HRTIM_CR2_TDRST_Pos (12U)
+#define HRTIM_CR2_TDRST_Msk (0x1UL << HRTIM_CR2_TDRST_Pos) /*!< 0x00001000 */
+#define HRTIM_CR2_TDRST HRTIM_CR2_TDRST_Msk /*!< Timer D count software reset */
+#define HRTIM_CR2_TERST_Pos (13U)
+#define HRTIM_CR2_TERST_Msk (0x1UL << HRTIM_CR2_TERST_Pos) /*!< 0x00002000 */
+#define HRTIM_CR2_TERST HRTIM_CR2_TERST_Msk /*!< Timer E count software reset */
+#define HRTIM_CR2_TFRST_Pos (14U)
+#define HRTIM_CR2_TFRST_Msk (0x1UL << HRTIM_CR2_TFRST_Pos) /*!< 0x00004000 */
+#define HRTIM_CR2_TFRST HRTIM_CR2_TFRST_Msk /*!< Timer F count software reset */
+#define HRTIM_CR2_SWPA_Pos (16U)
+#define HRTIM_CR2_SWPA_Msk (0x1UL << HRTIM_CR2_SWPA_Pos) /*!< 0x00010000 */
+#define HRTIM_CR2_SWPA HRTIM_CR2_SWPA_Msk /*!< Timer A swap outputs */
+#define HRTIM_CR2_SWPB_Pos (17U)
+#define HRTIM_CR2_SWPB_Msk (0x1UL << HRTIM_CR2_SWPB_Pos) /*!< 0x00020000 */
+#define HRTIM_CR2_SWPB HRTIM_CR2_SWPB_Msk /*!< Timer B swap outputs */
+#define HRTIM_CR2_SWPC_Pos (18U)
+#define HRTIM_CR2_SWPC_Msk (0x1UL << HRTIM_CR2_SWPC_Pos) /*!< 0x00040000 */
+#define HRTIM_CR2_SWPC HRTIM_CR2_SWPC_Msk /*!< Timer C swap outputs */
+#define HRTIM_CR2_SWPD_Pos (19U)
+#define HRTIM_CR2_SWPD_Msk (0x1UL << HRTIM_CR2_SWPD_Pos) /*!< 0x00080000 */
+#define HRTIM_CR2_SWPD HRTIM_CR2_SWPD_Msk /*!< Timer D swap outputs */
+#define HRTIM_CR2_SWPE_Pos (20U)
+#define HRTIM_CR2_SWPE_Msk (0x1UL << HRTIM_CR2_SWPE_Pos) /*!< 0x00100000 */
+#define HRTIM_CR2_SWPE HRTIM_CR2_SWPE_Msk /*!< Timer E swap outputs */
+#define HRTIM_CR2_SWPF_Pos (21U)
+#define HRTIM_CR2_SWPF_Msk (0x1UL << HRTIM_CR2_SWPF_Pos) /*!< 0x00200000 */
+#define HRTIM_CR2_SWPF HRTIM_CR2_SWPF_Msk /*!< Timer F swap outputs */
+
+/**** Bit definition for Common HRTIM Timer interrupt status register *********/
+#define HRTIM_ISR_FLT1_Pos (0U)
+#define HRTIM_ISR_FLT1_Msk (0x1UL << HRTIM_ISR_FLT1_Pos) /*!< 0x00000001 */
+#define HRTIM_ISR_FLT1 HRTIM_ISR_FLT1_Msk /*!< Fault 1 interrupt flag */
+#define HRTIM_ISR_FLT2_Pos (1U)
+#define HRTIM_ISR_FLT2_Msk (0x1UL << HRTIM_ISR_FLT2_Pos) /*!< 0x00000002 */
+#define HRTIM_ISR_FLT2 HRTIM_ISR_FLT2_Msk /*!< Fault 2 interrupt flag */
+#define HRTIM_ISR_FLT3_Pos (2U)
+#define HRTIM_ISR_FLT3_Msk (0x1UL << HRTIM_ISR_FLT3_Pos) /*!< 0x00000004 */
+#define HRTIM_ISR_FLT3 HRTIM_ISR_FLT3_Msk /*!< Fault 3 interrupt flag */
+#define HRTIM_ISR_FLT4_Pos (3U)
+#define HRTIM_ISR_FLT4_Msk (0x1UL << HRTIM_ISR_FLT4_Pos) /*!< 0x00000008 */
+#define HRTIM_ISR_FLT4 HRTIM_ISR_FLT4_Msk /*!< Fault 4 interrupt flag */
+#define HRTIM_ISR_FLT5_Pos (4U)
+#define HRTIM_ISR_FLT5_Msk (0x1UL << HRTIM_ISR_FLT5_Pos) /*!< 0x00000010 */
+#define HRTIM_ISR_FLT5 HRTIM_ISR_FLT5_Msk /*!< Fault 5 interrupt flag */
+#define HRTIM_ISR_SYSFLT_Pos (5U)
+#define HRTIM_ISR_SYSFLT_Msk (0x1UL << HRTIM_ISR_SYSFLT_Pos) /*!< 0x00000020 */
+#define HRTIM_ISR_SYSFLT HRTIM_ISR_SYSFLT_Msk /*!< System Fault interrupt flag */
+#define HRTIM_ISR_FLT6_Pos (6U)
+#define HRTIM_ISR_FLT6_Msk (0x1UL << HRTIM_ISR_FLT6_Pos) /*!< 0x00000040 */
+#define HRTIM_ISR_FLT6 HRTIM_ISR_FLT6_Msk /*!< Fault 6 interrupt flag */
+#define HRTIM_ISR_DLLRDY_Pos (16U)
+#define HRTIM_ISR_DLLRDY_Msk (0x1UL << HRTIM_ISR_DLLRDY_Pos) /*!< 0x00010000 */
+#define HRTIM_ISR_DLLRDY HRTIM_ISR_DLLRDY_Msk /*!< DLL ready interrupt flag */
+#define HRTIM_ISR_BMPER_Pos (17U)
+#define HRTIM_ISR_BMPER_Msk (0x1UL << HRTIM_ISR_BMPER_Pos) /*!< 0x00020000 */
+#define HRTIM_ISR_BMPER HRTIM_ISR_BMPER_Msk /*!< Burst mode period interrupt flag */
+
+/**** Bit definition for Common HRTIM Timer interrupt clear register **********/
+#define HRTIM_ICR_FLT1C_Pos (0U)
+#define HRTIM_ICR_FLT1C_Msk (0x1UL << HRTIM_ICR_FLT1C_Pos) /*!< 0x00000001 */
+#define HRTIM_ICR_FLT1C HRTIM_ICR_FLT1C_Msk /*!< Fault 1 interrupt flag clear */
+#define HRTIM_ICR_FLT2C_Pos (1U)
+#define HRTIM_ICR_FLT2C_Msk (0x1UL << HRTIM_ICR_FLT2C_Pos) /*!< 0x00000002 */
+#define HRTIM_ICR_FLT2C HRTIM_ICR_FLT2C_Msk /*!< Fault 2 interrupt flag clear */
+#define HRTIM_ICR_FLT3C_Pos (2U)
+#define HRTIM_ICR_FLT3C_Msk (0x1UL << HRTIM_ICR_FLT3C_Pos) /*!< 0x00000004 */
+#define HRTIM_ICR_FLT3C HRTIM_ICR_FLT3C_Msk /*!< Fault 3 interrupt flag clear */
+#define HRTIM_ICR_FLT4C_Pos (3U)
+#define HRTIM_ICR_FLT4C_Msk (0x1UL << HRTIM_ICR_FLT4C_Pos) /*!< 0x00000008 */
+#define HRTIM_ICR_FLT4C HRTIM_ICR_FLT4C_Msk /*!< Fault 4 interrupt flag clear */
+#define HRTIM_ICR_FLT5C_Pos (4U)
+#define HRTIM_ICR_FLT5C_Msk (0x1UL << HRTIM_ICR_FLT5C_Pos) /*!< 0x00000010 */
+#define HRTIM_ICR_FLT5C HRTIM_ICR_FLT5C_Msk /*!< Fault 5 interrupt flag clear */
+#define HRTIM_ICR_SYSFLTC_Pos (5U)
+#define HRTIM_ICR_SYSFLTC_Msk (0x1UL << HRTIM_ICR_SYSFLTC_Pos) /*!< 0x00000020 */
+#define HRTIM_ICR_SYSFLTC HRTIM_ICR_SYSFLTC_Msk /*!< System Fault interrupt flag clear */
+
+#define HRTIM_ICR_FLT6C_Pos (6U)
+#define HRTIM_ICR_FLT6C_Msk (0x1UL << HRTIM_ICR_FLT6C_Pos) /*!< 0x00000040 */
+#define HRTIM_ICR_FLT6C HRTIM_ICR_FLT6C_Msk /*!< Fault 6 interrupt flag clear */
+
+#define HRTIM_ICR_DLLRDYC_Pos (16U)
+#define HRTIM_ICR_DLLRDYC_Msk (0x1UL << HRTIM_ICR_DLLRDYC_Pos) /*!< 0x00010000 */
+#define HRTIM_ICR_DLLRDYC HRTIM_ICR_DLLRDYC_Msk /*!< DLL ready interrupt flag clear */
+#define HRTIM_ICR_BMPERC_Pos (17U)
+#define HRTIM_ICR_BMPERC_Msk (0x1UL << HRTIM_ICR_BMPERC_Pos) /*!< 0x00020000 */
+#define HRTIM_ICR_BMPERC HRTIM_ICR_BMPERC_Msk /*!< Burst mode period interrupt flag clear */
+
+/**** Bit definition for Common HRTIM Timer interrupt enable register *********/
+#define HRTIM_IER_FLT1_Pos (0U)
+#define HRTIM_IER_FLT1_Msk (0x1UL << HRTIM_IER_FLT1_Pos) /*!< 0x00000001 */
+#define HRTIM_IER_FLT1 HRTIM_IER_FLT1_Msk /*!< Fault 1 interrupt enable */
+#define HRTIM_IER_FLT2_Pos (1U)
+#define HRTIM_IER_FLT2_Msk (0x1UL << HRTIM_IER_FLT2_Pos) /*!< 0x00000002 */
+#define HRTIM_IER_FLT2 HRTIM_IER_FLT2_Msk /*!< Fault 2 interrupt enable */
+#define HRTIM_IER_FLT3_Pos (2U)
+#define HRTIM_IER_FLT3_Msk (0x1UL << HRTIM_IER_FLT3_Pos) /*!< 0x00000004 */
+#define HRTIM_IER_FLT3 HRTIM_IER_FLT3_Msk /*!< Fault 3 interrupt enable */
+#define HRTIM_IER_FLT4_Pos (3U)
+#define HRTIM_IER_FLT4_Msk (0x1UL << HRTIM_IER_FLT4_Pos) /*!< 0x00000008 */
+#define HRTIM_IER_FLT4 HRTIM_IER_FLT4_Msk /*!< Fault 4 interrupt enable */
+#define HRTIM_IER_FLT5_Pos (4U)
+#define HRTIM_IER_FLT5_Msk (0x1UL << HRTIM_IER_FLT5_Pos) /*!< 0x00000010 */
+#define HRTIM_IER_FLT5 HRTIM_IER_FLT5_Msk /*!< Fault 5 interrupt enable */
+#define HRTIM_IER_SYSFLT_Pos (5U)
+#define HRTIM_IER_SYSFLT_Msk (0x1UL << HRTIM_IER_SYSFLT_Pos) /*!< 0x00000020 */
+#define HRTIM_IER_SYSFLT HRTIM_IER_SYSFLT_Msk /*!< System Fault interrupt enable */
+#define HRTIM_IER_FLT6_Pos (6U)
+#define HRTIM_IER_FLT6_Msk (0x1UL << HRTIM_IER_FLT6_Pos) /*!< 0x00000040 */
+#define HRTIM_IER_FLT6 HRTIM_IER_FLT6_Msk /*!< Fault 6 interrupt enable */
+
+#define HRTIM_IER_DLLRDY_Pos (16U)
+#define HRTIM_IER_DLLRDY_Msk (0x1UL << HRTIM_IER_DLLRDY_Pos) /*!< 0x00010000 */
+#define HRTIM_IER_DLLRDY HRTIM_IER_DLLRDY_Msk /*!< DLL ready interrupt enable */
+#define HRTIM_IER_BMPER_Pos (17U)
+#define HRTIM_IER_BMPER_Msk (0x1UL << HRTIM_IER_BMPER_Pos) /*!< 0x00020000 */
+#define HRTIM_IER_BMPER HRTIM_IER_BMPER_Msk /*!< Burst mode period interrupt enable */
+
+/**** Bit definition for Common HRTIM Timer output enable register ************/
+#define HRTIM_OENR_TA1OEN_Pos (0U)
+#define HRTIM_OENR_TA1OEN_Msk (0x1UL << HRTIM_OENR_TA1OEN_Pos) /*!< 0x00000001 */
+#define HRTIM_OENR_TA1OEN HRTIM_OENR_TA1OEN_Msk /*!< Timer A Output 1 enable */
+#define HRTIM_OENR_TA2OEN_Pos (1U)
+#define HRTIM_OENR_TA2OEN_Msk (0x1UL << HRTIM_OENR_TA2OEN_Pos) /*!< 0x00000002 */
+#define HRTIM_OENR_TA2OEN HRTIM_OENR_TA2OEN_Msk /*!< Timer A Output 2 enable */
+#define HRTIM_OENR_TB1OEN_Pos (2U)
+#define HRTIM_OENR_TB1OEN_Msk (0x1UL << HRTIM_OENR_TB1OEN_Pos) /*!< 0x00000004 */
+#define HRTIM_OENR_TB1OEN HRTIM_OENR_TB1OEN_Msk /*!< Timer B Output 1 enable */
+#define HRTIM_OENR_TB2OEN_Pos (3U)
+#define HRTIM_OENR_TB2OEN_Msk (0x1UL << HRTIM_OENR_TB2OEN_Pos) /*!< 0x00000008 */
+#define HRTIM_OENR_TB2OEN HRTIM_OENR_TB2OEN_Msk /*!< Timer B Output 2 enable */
+#define HRTIM_OENR_TC1OEN_Pos (4U)
+#define HRTIM_OENR_TC1OEN_Msk (0x1UL << HRTIM_OENR_TC1OEN_Pos) /*!< 0x00000010 */
+#define HRTIM_OENR_TC1OEN HRTIM_OENR_TC1OEN_Msk /*!< Timer C Output 1 enable */
+#define HRTIM_OENR_TC2OEN_Pos (5U)
+#define HRTIM_OENR_TC2OEN_Msk (0x1UL << HRTIM_OENR_TC2OEN_Pos) /*!< 0x00000020 */
+#define HRTIM_OENR_TC2OEN HRTIM_OENR_TC2OEN_Msk /*!< Timer C Output 2 enable */
+#define HRTIM_OENR_TD1OEN_Pos (6U)
+#define HRTIM_OENR_TD1OEN_Msk (0x1UL << HRTIM_OENR_TD1OEN_Pos) /*!< 0x00000040 */
+#define HRTIM_OENR_TD1OEN HRTIM_OENR_TD1OEN_Msk /*!< Timer D Output 1 enable */
+#define HRTIM_OENR_TD2OEN_Pos (7U)
+#define HRTIM_OENR_TD2OEN_Msk (0x1UL << HRTIM_OENR_TD2OEN_Pos) /*!< 0x00000080 */
+#define HRTIM_OENR_TD2OEN HRTIM_OENR_TD2OEN_Msk /*!< Timer D Output 2 enable */
+#define HRTIM_OENR_TE1OEN_Pos (8U)
+#define HRTIM_OENR_TE1OEN_Msk (0x1UL << HRTIM_OENR_TE1OEN_Pos) /*!< 0x00000100 */
+#define HRTIM_OENR_TE1OEN HRTIM_OENR_TE1OEN_Msk /*!< Timer E Output 1 enable */
+#define HRTIM_OENR_TE2OEN_Pos (9U)
+#define HRTIM_OENR_TE2OEN_Msk (0x1UL << HRTIM_OENR_TE2OEN_Pos) /*!< 0x00000200 */
+#define HRTIM_OENR_TE2OEN HRTIM_OENR_TE2OEN_Msk /*!< Timer E Output 2 enable */
+#define HRTIM_OENR_TF1OEN_Pos (10U)
+#define HRTIM_OENR_TF1OEN_Msk (0x1UL << HRTIM_OENR_TF1OEN_Pos) /*!< 0x00000400 */
+#define HRTIM_OENR_TF1OEN HRTIM_OENR_TF1OEN_Msk /*!< Timer F Output 1 enable */
+#define HRTIM_OENR_TF2OEN_Pos (11U)
+#define HRTIM_OENR_TF2OEN_Msk (0x1UL << HRTIM_OENR_TF2OEN_Pos) /*!< 0x00000800 */
+#define HRTIM_OENR_TF2OEN HRTIM_OENR_TF2OEN_Msk /*!< Timer F Output 2 enable */
+
+/**** Bit definition for Common HRTIM Timer output disable register ***********/
+#define HRTIM_ODISR_TA1ODIS_Pos (0U)
+#define HRTIM_ODISR_TA1ODIS_Msk (0x1UL << HRTIM_ODISR_TA1ODIS_Pos) /*!< 0x00000001 */
+#define HRTIM_ODISR_TA1ODIS HRTIM_ODISR_TA1ODIS_Msk /*!< Timer A Output 1 disable */
+#define HRTIM_ODISR_TA2ODIS_Pos (1U)
+#define HRTIM_ODISR_TA2ODIS_Msk (0x1UL << HRTIM_ODISR_TA2ODIS_Pos) /*!< 0x00000002 */
+#define HRTIM_ODISR_TA2ODIS HRTIM_ODISR_TA2ODIS_Msk /*!< Timer A Output 2 disable */
+#define HRTIM_ODISR_TB1ODIS_Pos (2U)
+#define HRTIM_ODISR_TB1ODIS_Msk (0x1UL << HRTIM_ODISR_TB1ODIS_Pos) /*!< 0x00000004 */
+#define HRTIM_ODISR_TB1ODIS HRTIM_ODISR_TB1ODIS_Msk /*!< Timer B Output 1 disable */
+#define HRTIM_ODISR_TB2ODIS_Pos (3U)
+#define HRTIM_ODISR_TB2ODIS_Msk (0x1UL << HRTIM_ODISR_TB2ODIS_Pos) /*!< 0x00000008 */
+#define HRTIM_ODISR_TB2ODIS HRTIM_ODISR_TB2ODIS_Msk /*!< Timer B Output 2 disable */
+#define HRTIM_ODISR_TC1ODIS_Pos (4U)
+#define HRTIM_ODISR_TC1ODIS_Msk (0x1UL << HRTIM_ODISR_TC1ODIS_Pos) /*!< 0x00000010 */
+#define HRTIM_ODISR_TC1ODIS HRTIM_ODISR_TC1ODIS_Msk /*!< Timer C Output 1 disable */
+#define HRTIM_ODISR_TC2ODIS_Pos (5U)
+#define HRTIM_ODISR_TC2ODIS_Msk (0x1UL << HRTIM_ODISR_TC2ODIS_Pos) /*!< 0x00000020 */
+#define HRTIM_ODISR_TC2ODIS HRTIM_ODISR_TC2ODIS_Msk /*!< Timer C Output 2 disable */
+#define HRTIM_ODISR_TD1ODIS_Pos (6U)
+#define HRTIM_ODISR_TD1ODIS_Msk (0x1UL << HRTIM_ODISR_TD1ODIS_Pos) /*!< 0x00000040 */
+#define HRTIM_ODISR_TD1ODIS HRTIM_ODISR_TD1ODIS_Msk /*!< Timer D Output 1 disable */
+#define HRTIM_ODISR_TD2ODIS_Pos (7U)
+#define HRTIM_ODISR_TD2ODIS_Msk (0x1UL << HRTIM_ODISR_TD2ODIS_Pos) /*!< 0x00000080 */
+#define HRTIM_ODISR_TD2ODIS HRTIM_ODISR_TD2ODIS_Msk /*!< Timer D Output 2 disable */
+#define HRTIM_ODISR_TE1ODIS_Pos (8U)
+#define HRTIM_ODISR_TE1ODIS_Msk (0x1UL << HRTIM_ODISR_TE1ODIS_Pos) /*!< 0x00000100 */
+#define HRTIM_ODISR_TE1ODIS HRTIM_ODISR_TE1ODIS_Msk /*!< Timer E Output 1 disable */
+#define HRTIM_ODISR_TE2ODIS_Pos (9U)
+#define HRTIM_ODISR_TE2ODIS_Msk (0x1UL << HRTIM_ODISR_TE2ODIS_Pos) /*!< 0x00000200 */
+#define HRTIM_ODISR_TE2ODIS HRTIM_ODISR_TE2ODIS_Msk /*!< Timer E Output 2 disable */
+#define HRTIM_ODISR_TF1ODIS_Pos (10U)
+#define HRTIM_ODISR_TF1ODIS_Msk (0x1UL << HRTIM_ODISR_TF1ODIS_Pos) /*!< 0x00000100 */
+#define HRTIM_ODISR_TF1ODIS HRTIM_ODISR_TF1ODIS_Msk /*!< Timer F Output 1 disable */
+#define HRTIM_ODISR_TF2ODIS_Pos (11U)
+#define HRTIM_ODISR_TF2ODIS_Msk (0x1UL << HRTIM_ODISR_TF2ODIS_Pos) /*!< 0x00000200 */
+#define HRTIM_ODISR_TF2ODIS HRTIM_ODISR_TF2ODIS_Msk /*!< Timer F Output 2 disable */
+
+/**** Bit definition for Common HRTIM Timer output disable status register *****/
+#define HRTIM_ODSR_TA1ODS_Pos (0U)
+#define HRTIM_ODSR_TA1ODS_Msk (0x1UL << HRTIM_ODSR_TA1ODS_Pos) /*!< 0x00000001 */
+#define HRTIM_ODSR_TA1ODS HRTIM_ODSR_TA1ODS_Msk /*!< Timer A Output 1 disable status */
+#define HRTIM_ODSR_TA2ODS_Pos (1U)
+#define HRTIM_ODSR_TA2ODS_Msk (0x1UL << HRTIM_ODSR_TA2ODS_Pos) /*!< 0x00000002 */
+#define HRTIM_ODSR_TA2ODS HRTIM_ODSR_TA2ODS_Msk /*!< Timer A Output 2 disable status */
+#define HRTIM_ODSR_TB1ODS_Pos (2U)
+#define HRTIM_ODSR_TB1ODS_Msk (0x1UL << HRTIM_ODSR_TB1ODS_Pos) /*!< 0x00000004 */
+#define HRTIM_ODSR_TB1ODS HRTIM_ODSR_TB1ODS_Msk /*!< Timer B Output 1 disable status */
+#define HRTIM_ODSR_TB2ODS_Pos (3U)
+#define HRTIM_ODSR_TB2ODS_Msk (0x1UL << HRTIM_ODSR_TB2ODS_Pos) /*!< 0x00000008 */
+#define HRTIM_ODSR_TB2ODS HRTIM_ODSR_TB2ODS_Msk /*!< Timer B Output 2 disable status */
+#define HRTIM_ODSR_TC1ODS_Pos (4U)
+#define HRTIM_ODSR_TC1ODS_Msk (0x1UL << HRTIM_ODSR_TC1ODS_Pos) /*!< 0x00000010 */
+#define HRTIM_ODSR_TC1ODS HRTIM_ODSR_TC1ODS_Msk /*!< Timer C Output 1 disable status */
+#define HRTIM_ODSR_TC2ODS_Pos (5U)
+#define HRTIM_ODSR_TC2ODS_Msk (0x1UL << HRTIM_ODSR_TC2ODS_Pos) /*!< 0x00000020 */
+#define HRTIM_ODSR_TC2ODS HRTIM_ODSR_TC2ODS_Msk /*!< Timer C Output 2 disable status */
+#define HRTIM_ODSR_TD1ODS_Pos (6U)
+#define HRTIM_ODSR_TD1ODS_Msk (0x1UL << HRTIM_ODSR_TD1ODS_Pos) /*!< 0x00000040 */
+#define HRTIM_ODSR_TD1ODS HRTIM_ODSR_TD1ODS_Msk /*!< Timer D Output 1 disable status */
+#define HRTIM_ODSR_TD2ODS_Pos (7U)
+#define HRTIM_ODSR_TD2ODS_Msk (0x1UL << HRTIM_ODSR_TD2ODS_Pos) /*!< 0x00000080 */
+#define HRTIM_ODSR_TD2ODS HRTIM_ODSR_TD2ODS_Msk /*!< Timer D Output 2 disable status */
+#define HRTIM_ODSR_TE1ODS_Pos (8U)
+#define HRTIM_ODSR_TE1ODS_Msk (0x1UL << HRTIM_ODSR_TE1ODS_Pos) /*!< 0x00000100 */
+#define HRTIM_ODSR_TE1ODS HRTIM_ODSR_TE1ODS_Msk /*!< Timer E Output 1 disable status */
+#define HRTIM_ODSR_TE2ODS_Pos (9U)
+#define HRTIM_ODSR_TE2ODS_Msk (0x1UL << HRTIM_ODSR_TE2ODS_Pos) /*!< 0x00000200 */
+#define HRTIM_ODSR_TE2ODS HRTIM_ODSR_TE2ODS_Msk /*!< Timer E Output 2 disable status */
+#define HRTIM_ODSR_TF1ODS_Pos (10U)
+#define HRTIM_ODSR_TF1ODS_Msk (0x1UL << HRTIM_ODSR_TF1ODS_Pos) /*!< 0x00000100 */
+#define HRTIM_ODSR_TF1ODS HRTIM_ODSR_TF1ODS_Msk /*!< Timer F Output 1 disable status */
+#define HRTIM_ODSR_TF2ODS_Pos (11U)
+#define HRTIM_ODSR_TF2ODS_Msk (0x1UL << HRTIM_ODSR_TF2ODS_Pos) /*!< 0x00000200 */
+#define HRTIM_ODSR_TF2ODS HRTIM_ODSR_TF2ODS_Msk /*!< Timer F Output 2 disable status */
+
+/**** Bit definition for Common HRTIM Timer Burst mode control register ********/
+#define HRTIM_BMCR_BME_Pos (0U)
+#define HRTIM_BMCR_BME_Msk (0x1UL << HRTIM_BMCR_BME_Pos) /*!< 0x00000001 */
+#define HRTIM_BMCR_BME HRTIM_BMCR_BME_Msk /*!< Burst mode enbale */
+#define HRTIM_BMCR_BMOM_Pos (1U)
+#define HRTIM_BMCR_BMOM_Msk (0x1UL << HRTIM_BMCR_BMOM_Pos) /*!< 0x00000002 */
+#define HRTIM_BMCR_BMOM HRTIM_BMCR_BMOM_Msk /*!< Burst mode operating mode */
+#define HRTIM_BMCR_BMCLK_Pos (2U)
+#define HRTIM_BMCR_BMCLK_Msk (0xFUL << HRTIM_BMCR_BMCLK_Pos) /*!< 0x0000003C */
+#define HRTIM_BMCR_BMCLK HRTIM_BMCR_BMCLK_Msk /*!< Burst mode clock source */
+#define HRTIM_BMCR_BMCLK_0 (0x1UL << HRTIM_BMCR_BMCLK_Pos) /*!< 0x00000004 */
+#define HRTIM_BMCR_BMCLK_1 (0x2UL << HRTIM_BMCR_BMCLK_Pos) /*!< 0x00000008 */
+#define HRTIM_BMCR_BMCLK_2 (0x4UL << HRTIM_BMCR_BMCLK_Pos) /*!< 0x00000010 */
+#define HRTIM_BMCR_BMCLK_3 (0x8UL << HRTIM_BMCR_BMCLK_Pos) /*!< 0x00000020 */
+#define HRTIM_BMCR_BMPRSC_Pos (6U)
+#define HRTIM_BMCR_BMPRSC_Msk (0xFUL << HRTIM_BMCR_BMPRSC_Pos) /*!< 0x000003C0 */
+#define HRTIM_BMCR_BMPRSC HRTIM_BMCR_BMPRSC_Msk /*!< Burst mode prescaler */
+#define HRTIM_BMCR_BMPRSC_0 (0x1UL << HRTIM_BMCR_BMPRSC_Pos) /*!< 0x00000040 */
+#define HRTIM_BMCR_BMPRSC_1 (0x2UL << HRTIM_BMCR_BMPRSC_Pos) /*!< 0x00000080 */
+#define HRTIM_BMCR_BMPRSC_2 (0x4UL << HRTIM_BMCR_BMPRSC_Pos) /*!< 0x00000100 */
+#define HRTIM_BMCR_BMPRSC_3 (0x8UL << HRTIM_BMCR_BMPRSC_Pos) /*!< 0x00000200 */
+#define HRTIM_BMCR_BMPREN_Pos (10U)
+#define HRTIM_BMCR_BMPREN_Msk (0x1UL << HRTIM_BMCR_BMPREN_Pos) /*!< 0x00000400 */
+#define HRTIM_BMCR_BMPREN HRTIM_BMCR_BMPREN_Msk /*!< Burst mode Preload bit */
+#define HRTIM_BMCR_MTBM_Pos (16U)
+#define HRTIM_BMCR_MTBM_Msk (0x1UL << HRTIM_BMCR_MTBM_Pos) /*!< 0x00010000 */
+#define HRTIM_BMCR_MTBM HRTIM_BMCR_MTBM_Msk /*!< Master Timer Burst mode */
+#define HRTIM_BMCR_TABM_Pos (17U)
+#define HRTIM_BMCR_TABM_Msk (0x1UL << HRTIM_BMCR_TABM_Pos) /*!< 0x00020000 */
+#define HRTIM_BMCR_TABM HRTIM_BMCR_TABM_Msk /*!< Timer A Burst mode */
+#define HRTIM_BMCR_TBBM_Pos (18U)
+#define HRTIM_BMCR_TBBM_Msk (0x1UL << HRTIM_BMCR_TBBM_Pos) /*!< 0x00040000 */
+#define HRTIM_BMCR_TBBM HRTIM_BMCR_TBBM_Msk /*!< Timer B Burst mode */
+#define HRTIM_BMCR_TCBM_Pos (19U)
+#define HRTIM_BMCR_TCBM_Msk (0x1UL << HRTIM_BMCR_TCBM_Pos) /*!< 0x00080000 */
+#define HRTIM_BMCR_TCBM HRTIM_BMCR_TCBM_Msk /*!< Timer C Burst mode */
+#define HRTIM_BMCR_TDBM_Pos (20U)
+#define HRTIM_BMCR_TDBM_Msk (0x1UL << HRTIM_BMCR_TDBM_Pos) /*!< 0x00100000 */
+#define HRTIM_BMCR_TDBM HRTIM_BMCR_TDBM_Msk /*!< Timer D Burst mode */
+#define HRTIM_BMCR_TEBM_Pos (21U)
+#define HRTIM_BMCR_TEBM_Msk (0x1UL << HRTIM_BMCR_TEBM_Pos) /*!< 0x00200000 */
+#define HRTIM_BMCR_TEBM HRTIM_BMCR_TEBM_Msk /*!< Timer E Burst mode */
+
+#define HRTIM_BMCR_TFBM_Pos (22U)
+#define HRTIM_BMCR_TFBM_Msk (0x1UL << HRTIM_BMCR_TFBM_Pos) /*!< 0x00400000 */
+#define HRTIM_BMCR_TFBM HRTIM_BMCR_TFBM_Msk /*!< Timer F Burst mode */
+
+#define HRTIM_BMCR_BMSTAT_Pos (31U)
+#define HRTIM_BMCR_BMSTAT_Msk (0x1UL << HRTIM_BMCR_BMSTAT_Pos) /*!< 0x80000000 */
+#define HRTIM_BMCR_BMSTAT HRTIM_BMCR_BMSTAT_Msk /*!< Burst mode status */
+
+/**** Bit definition for Common HRTIM Timer Burst mode Trigger register *******/
+#define HRTIM_BMTRGR_SW_Pos (0U)
+#define HRTIM_BMTRGR_SW_Msk (0x1UL << HRTIM_BMTRGR_SW_Pos) /*!< 0x00000001 */
+#define HRTIM_BMTRGR_SW HRTIM_BMTRGR_SW_Msk /*!< Software start */
+#define HRTIM_BMTRGR_MSTRST_Pos (1U)
+#define HRTIM_BMTRGR_MSTRST_Msk (0x1UL << HRTIM_BMTRGR_MSTRST_Pos) /*!< 0x00000002 */
+#define HRTIM_BMTRGR_MSTRST HRTIM_BMTRGR_MSTRST_Msk /*!< Master reset */
+#define HRTIM_BMTRGR_MSTREP_Pos (2U)
+#define HRTIM_BMTRGR_MSTREP_Msk (0x1UL << HRTIM_BMTRGR_MSTREP_Pos) /*!< 0x00000004 */
+#define HRTIM_BMTRGR_MSTREP HRTIM_BMTRGR_MSTREP_Msk /*!< Master repetition */
+#define HRTIM_BMTRGR_MSTCMP1_Pos (3U)
+#define HRTIM_BMTRGR_MSTCMP1_Msk (0x1UL << HRTIM_BMTRGR_MSTCMP1_Pos) /*!< 0x00000008 */
+#define HRTIM_BMTRGR_MSTCMP1 HRTIM_BMTRGR_MSTCMP1_Msk /*!< Master compare 1 */
+#define HRTIM_BMTRGR_MSTCMP2_Pos (4U)
+#define HRTIM_BMTRGR_MSTCMP2_Msk (0x1UL << HRTIM_BMTRGR_MSTCMP2_Pos) /*!< 0x00000010 */
+#define HRTIM_BMTRGR_MSTCMP2 HRTIM_BMTRGR_MSTCMP2_Msk /*!< Master compare 2 */
+#define HRTIM_BMTRGR_MSTCMP3_Pos (5U)
+#define HRTIM_BMTRGR_MSTCMP3_Msk (0x1UL << HRTIM_BMTRGR_MSTCMP3_Pos) /*!< 0x00000020 */
+#define HRTIM_BMTRGR_MSTCMP3 HRTIM_BMTRGR_MSTCMP3_Msk /*!< Master compare 3 */
+#define HRTIM_BMTRGR_MSTCMP4_Pos (6U)
+#define HRTIM_BMTRGR_MSTCMP4_Msk (0x1UL << HRTIM_BMTRGR_MSTCMP4_Pos) /*!< 0x00000040 */
+#define HRTIM_BMTRGR_MSTCMP4 HRTIM_BMTRGR_MSTCMP4_Msk /*!< Master compare 4 */
+#define HRTIM_BMTRGR_TARST_Pos (7U)
+#define HRTIM_BMTRGR_TARST_Msk (0x1UL << HRTIM_BMTRGR_TARST_Pos) /*!< 0x00000080 */
+#define HRTIM_BMTRGR_TARST HRTIM_BMTRGR_TARST_Msk /*!< Timer A reset */
+#define HRTIM_BMTRGR_TAREP_Pos (8U)
+#define HRTIM_BMTRGR_TAREP_Msk (0x1UL << HRTIM_BMTRGR_TAREP_Pos) /*!< 0x00000100 */
+#define HRTIM_BMTRGR_TAREP HRTIM_BMTRGR_TAREP_Msk /*!< Timer A repetition */
+#define HRTIM_BMTRGR_TACMP1_Pos (9U)
+#define HRTIM_BMTRGR_TACMP1_Msk (0x1UL << HRTIM_BMTRGR_TACMP1_Pos) /*!< 0x00000200 */
+#define HRTIM_BMTRGR_TACMP1 HRTIM_BMTRGR_TACMP1_Msk /*!< Timer A compare 1 */
+#define HRTIM_BMTRGR_TACMP2_Pos (10U)
+#define HRTIM_BMTRGR_TACMP2_Msk (0x1UL << HRTIM_BMTRGR_TACMP2_Pos) /*!< 0x00000400 */
+#define HRTIM_BMTRGR_TACMP2 HRTIM_BMTRGR_TACMP2_Msk /*!< Timer A compare 2 */
+#define HRTIM_BMTRGR_TBRST_Pos (11U)
+#define HRTIM_BMTRGR_TBRST_Msk (0x1UL << HRTIM_BMTRGR_TBRST_Pos) /*!< 0x00000800 */
+#define HRTIM_BMTRGR_TBRST HRTIM_BMTRGR_TBRST_Msk /*!< Timer B reset */
+#define HRTIM_BMTRGR_TBREP_Pos (12U)
+#define HRTIM_BMTRGR_TBREP_Msk (0x1UL << HRTIM_BMTRGR_TBREP_Pos) /*!< 0x00001000 */
+#define HRTIM_BMTRGR_TBREP HRTIM_BMTRGR_TBREP_Msk /*!< Timer B repetition */
+#define HRTIM_BMTRGR_TBCMP1_Pos (13U)
+#define HRTIM_BMTRGR_TBCMP1_Msk (0x1UL << HRTIM_BMTRGR_TBCMP1_Pos) /*!< 0x00002000 */
+#define HRTIM_BMTRGR_TBCMP1 HRTIM_BMTRGR_TBCMP1_Msk /*!< Timer B compare 1 */
+#define HRTIM_BMTRGR_TBCMP2_Pos (14U)
+#define HRTIM_BMTRGR_TBCMP2_Msk (0x1UL << HRTIM_BMTRGR_TBCMP2_Pos) /*!< 0x00004000 */
+#define HRTIM_BMTRGR_TBCMP2 HRTIM_BMTRGR_TBCMP2_Msk /*!< Timer B compare 2 */
+#define HRTIM_BMTRGR_TCRST_Pos (15U)
+#define HRTIM_BMTRGR_TCRST_Msk (0x1UL << HRTIM_BMTRGR_TCRST_Pos) /*!< 0x00008000 */
+#define HRTIM_BMTRGR_TCRST HRTIM_BMTRGR_TCRST_Msk /*!< Timer C reset */
+#define HRTIM_BMTRGR_TCREP_Pos (16U)
+#define HRTIM_BMTRGR_TCREP_Msk (0x1UL << HRTIM_BMTRGR_TCREP_Pos) /*!< 0x00010000 */
+#define HRTIM_BMTRGR_TCREP HRTIM_BMTRGR_TCREP_Msk /*!< Timer C repetition */
+#define HRTIM_BMTRGR_TCCMP1_Pos (17U)
+#define HRTIM_BMTRGR_TCCMP1_Msk (0x1UL << HRTIM_BMTRGR_TCCMP1_Pos) /*!< 0x00020000 */
+#define HRTIM_BMTRGR_TCCMP1 HRTIM_BMTRGR_TCCMP1_Msk /*!< Timer C compare 1 */
+#define HRTIM_BMTRGR_TFRST_Pos (18U)
+#define HRTIM_BMTRGR_TFRST_Msk (0x1UL << HRTIM_BMTRGR_TFRST_Pos) /*!< 0x00040000 */
+#define HRTIM_BMTRGR_TFRST HRTIM_BMTRGR_TFRST_Msk /*!< Timer F reset */
+#define HRTIM_BMTRGR_TCCMP2_Pos (18U)
+#define HRTIM_BMTRGR_TCCMP2_Msk (0x1UL << HRTIM_BMTRGR_TCCMP2_Pos) /*!< 0x00040000 */
+#define HRTIM_BMTRGR_TCCMP2 HRTIM_BMTRGR_TCCMP2_Msk /*!< Timer C compare 2 */
+#define HRTIM_BMTRGR_TDRST_Pos (19U)
+#define HRTIM_BMTRGR_TDRST_Msk (0x1UL << HRTIM_BMTRGR_TDRST_Pos) /*!< 0x00080000 */
+#define HRTIM_BMTRGR_TDRST HRTIM_BMTRGR_TDRST_Msk /*!< Timer D reset */
+#define HRTIM_BMTRGR_TDREP_Pos (20U)
+#define HRTIM_BMTRGR_TDREP_Msk (0x1UL << HRTIM_BMTRGR_TDREP_Pos) /*!< 0x00100000 */
+#define HRTIM_BMTRGR_TDREP HRTIM_BMTRGR_TDREP_Msk /*!< Timer D repetition */
+#define HRTIM_BMTRGR_TFREP_Pos (21U)
+#define HRTIM_BMTRGR_TFREP_Msk (0x1UL << HRTIM_BMTRGR_TFREP_Pos) /*!< 0x00200000 */
+#define HRTIM_BMTRGR_TFREP HRTIM_BMTRGR_TFREP_Msk /*!< Timer F repetition*/
+#define HRTIM_BMTRGR_TDCMP1_Pos (21U)
+#define HRTIM_BMTRGR_TDCMP1_Msk (0x1UL << HRTIM_BMTRGR_TDCMP1_Pos) /*!< 0x00200000 */
+#define HRTIM_BMTRGR_TDCMP1 HRTIM_BMTRGR_TDCMP1_Msk /*!< Timer D compare 1 */
+#define HRTIM_BMTRGR_TDCMP2_Pos (22U)
+#define HRTIM_BMTRGR_TDCMP2_Msk (0x1UL << HRTIM_BMTRGR_TDCMP2_Pos) /*!< 0x00400000 */
+#define HRTIM_BMTRGR_TDCMP2 HRTIM_BMTRGR_TDCMP2_Msk /*!< Timer D compare 2 */
+#define HRTIM_BMTRGR_TFCMP1_Pos (23U)
+#define HRTIM_BMTRGR_TFCMP1_Msk (0x1UL << HRTIM_BMTRGR_TFCMP1_Pos) /*!< 0x00800000 */
+#define HRTIM_BMTRGR_TFCMP1 HRTIM_BMTRGR_TFCMP1_Msk /*!< Timer F compare 1 */
+#define HRTIM_BMTRGR_TERST_Pos (23U)
+#define HRTIM_BMTRGR_TERST_Msk (HRTIM_BMTRGR_TERST_Pos) /*!< 0x00800000 */
+#define HRTIM_BMTRGR_TERST HRTIM_BMTRGR_TERST_Msk /*!< Timer E reset */
+#define HRTIM_BMTRGR_TEREP_Pos (24U)
+#define HRTIM_BMTRGR_TEREP_Msk (0x1UL << HRTIM_BMTRGR_TEREP_Pos) /*!< 0x01000000 */
+#define HRTIM_BMTRGR_TEREP HRTIM_BMTRGR_TEREP_Msk /*!< Timer E repetition */
+#define HRTIM_BMTRGR_TECMP1_Pos (25U)
+#define HRTIM_BMTRGR_TECMP1_Msk (0x1UL << HRTIM_BMTRGR_TECMP1_Pos) /*!< 0x02000000 */
+#define HRTIM_BMTRGR_TECMP1 HRTIM_BMTRGR_TECMP1_Msk /*!< Timer E compare 1 */
+#define HRTIM_BMTRGR_TECMP2_Pos (26U)
+#define HRTIM_BMTRGR_TECMP2_Msk (0x1UL << HRTIM_BMTRGR_TECMP2_Pos) /*!< 0x04000000 */
+#define HRTIM_BMTRGR_TECMP2 HRTIM_BMTRGR_TECMP2_Msk /*!< Timer E compare 2 */
+#define HRTIM_BMTRGR_TAEEV7_Pos (27U)
+#define HRTIM_BMTRGR_TAEEV7_Msk (0x1UL << HRTIM_BMTRGR_TAEEV7_Pos) /*!< 0x08000000 */
+#define HRTIM_BMTRGR_TAEEV7 HRTIM_BMTRGR_TAEEV7_Msk /*!< Timer A period following External Event7 */
+#define HRTIM_BMTRGR_TDEEV8_Pos (28U)
+#define HRTIM_BMTRGR_TDEEV8_Msk (0x1UL << HRTIM_BMTRGR_TDEEV8_Pos) /*!< 0x10000000 */
+#define HRTIM_BMTRGR_TDEEV8 HRTIM_BMTRGR_TDEEV8_Msk /*!< Timer D period following External Event8 */
+#define HRTIM_BMTRGR_EEV7_Pos (29U)
+#define HRTIM_BMTRGR_EEV7_Msk (0x1UL << HRTIM_BMTRGR_EEV7_Pos) /*!< 0x20000000 */
+#define HRTIM_BMTRGR_EEV7 HRTIM_BMTRGR_EEV7_Msk /*!< External Event 7 */
+#define HRTIM_BMTRGR_EEV8_Pos (30U)
+#define HRTIM_BMTRGR_EEV8_Msk (0x1UL << HRTIM_BMTRGR_EEV8_Pos) /*!< 0x40000000 */
+#define HRTIM_BMTRGR_EEV8 HRTIM_BMTRGR_EEV8_Msk /*!< External Event 8 */
+#define HRTIM_BMTRGR_OCHPEV_Pos (31U)
+#define HRTIM_BMTRGR_OCHPEV_Msk (0x1UL << HRTIM_BMTRGR_OCHPEV_Pos) /*!< 0x80000000 */
+#define HRTIM_BMTRGR_OCHPEV HRTIM_BMTRGR_OCHPEV_Msk /*!< on-chip Event */
+
+/******************* Bit definition for HRTIM_BMCMPR register ***************/
+#define HRTIM_BMCMPR_BMCMPR_Pos (0U)
+#define HRTIM_BMCMPR_BMCMPR_Msk (0xFFFFUL << HRTIM_BMCMPR_BMCMPR_Pos) /*!< 0x0000FFFF */
+#define HRTIM_BMCMPR_BMCMPR HRTIM_BMCMPR_BMCMPR_Msk /*!© Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/** @addtogroup CMSIS
+ * @{
+ */
+
+/** @addtogroup stm32g4xx
+ * @{
+ */
+
+#ifndef __STM32G4xx_H
+#define __STM32G4xx_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif /* __cplusplus */
+
+/** @addtogroup Library_configuration_section
+ * @{
+ */
+
+/**
+ * @brief STM32 Family
+ */
+#if !defined (STM32G4)
+#define STM32G4
+#endif /* STM32G4 */
+
+/* Uncomment the line below according to the target STM32G4 device used in your
+ application
+ */
+
+#if !defined (STM32G431xx) && !defined (STM32G441xx) && \
+ !defined (STM32G471xx) && !defined (STM32G473xx) && !defined (STM32G474xx) && !defined (STM32G483xx) && !defined (STM32G484xx) && !defined (STM32GBK1CB)
+ /* #define STM32G431xx */ /*!< STM32G431xx Devices */
+ /* #define STM32G441xx */ /*!< STM32G441xx Devices */
+ /* #define STM32G471xx */ /*!< STM32G471xx Devices */
+ /* #define STM32G473xx */ /*!< STM32G473xx Devices */
+ /* #define STM32G483xx */ /*!< STM32G483xx Devices */
+ /* #define STM32G474xx */ /*!< STM32G474xx Devices */
+ /* #define STM32G484xx */ /*!< STM32G484xx Devices */
+ /* #define STM32GBK1CB */ /*!< STM32GBK1CB Devices */
+#endif
+
+/* Tip: To avoid modifying this file each time you need to switch between these
+ devices, you can define the device in your toolchain compiler preprocessor.
+ */
+#if !defined (USE_HAL_DRIVER)
+/**
+ * @brief Comment the line below if you will not use the peripherals drivers.
+ In this case, these drivers will not be included and the application code will
+ be based on direct access to peripherals registers
+ */
+ /*#define USE_HAL_DRIVER */
+#endif /* USE_HAL_DRIVER */
+
+/**
+ * @brief CMSIS Device version number $VERSION$
+ */
+#define __STM32G4_CMSIS_VERSION_MAIN (0x01U) /*!< [31:24] main version */
+#define __STM32G4_CMSIS_VERSION_SUB1 (0x01U) /*!< [23:16] sub1 version */
+#define __STM32G4_CMSIS_VERSION_SUB2 (0x00U) /*!< [15:8] sub2 version */
+#define __STM32G4_CMSIS_VERSION_RC (0x00U) /*!< [7:0] release candidate */
+#define __STM32G4_CMSIS_VERSION ((__STM32G4_CMSIS_VERSION_MAIN << 24)\
+ |(__STM32G4_CMSIS_VERSION_SUB1 << 16)\
+ |(__STM32G4_CMSIS_VERSION_SUB2 << 8 )\
+ |(__STM32G4_CMSIS_VERSION_RC))
+
+/**
+ * @}
+ */
+
+/** @addtogroup Device_Included
+ * @{
+ */
+
+#if defined(STM32G431xx)
+ #include "stm32g431xx.h"
+#elif defined(STM32G441xx)
+ #include "stm32g441xx.h"
+#elif defined(STM32G471xx)
+ #include "stm32g471xx.h"
+#elif defined(STM32G473xx)
+ #include "stm32g473xx.h"
+#elif defined(STM32G483xx)
+ #include "stm32g483xx.h"
+#elif defined(STM32G474xx)
+ #include "stm32g474xx.h"
+#elif defined(STM32G484xx)
+ #include "stm32g484xx.h"
+#elif defined(STM32GBK1CB)
+ #include "stm32gbk1cb.h"
+#else
+ #error "Please select first the target STM32G4xx device used in your application (in stm32g4xx.h file)"
+#endif
+
+/**
+ * @}
+ */
+
+/** @addtogroup Exported_types
+ * @{
+ */
+typedef enum
+{
+ RESET = 0,
+ SET = !RESET
+} FlagStatus, ITStatus;
+
+typedef enum
+{
+ DISABLE = 0,
+ ENABLE = !DISABLE
+} FunctionalState;
+#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))
+
+typedef enum
+{
+ SUCCESS = 0,
+ ERROR = !SUCCESS
+} ErrorStatus;
+
+/**
+ * @}
+ */
+
+
+/** @addtogroup Exported_macros
+ * @{
+ */
+#define SET_BIT(REG, BIT) ((REG) |= (BIT))
+
+#define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT))
+
+#define READ_BIT(REG, BIT) ((REG) & (BIT))
+
+#define CLEAR_REG(REG) ((REG) = (0x0))
+
+#define WRITE_REG(REG, VAL) ((REG) = (VAL))
+
+#define READ_REG(REG) ((REG))
+
+#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))
+
+#define POSITION_VAL(VAL) (__CLZ(__RBIT(VAL)))
+
+
+/**
+ * @}
+ */
+
+#if defined (USE_HAL_DRIVER)
+ #include "stm32g4xx_hal.h"
+#endif /* USE_HAL_DRIVER */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __STM32G4xx_H */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ChibiOS_20.3.2/os/common/ext/ST/STM32G4xx/system_stm32g4xx.h b/ChibiOS_20.3.2/os/common/ext/ST/STM32G4xx/system_stm32g4xx.h
new file mode 100644
index 0000000..fbff611
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ST/STM32G4xx/system_stm32g4xx.h
@@ -0,0 +1,106 @@
+/**
+ ******************************************************************************
+ * @file system_stm32g4xx.h
+ * @author MCD Application Team
+ * @brief CMSIS Cortex-M4 Device System Source File for STM32G4xx devices.
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/** @addtogroup CMSIS
+ * @{
+ */
+
+/** @addtogroup stm32g4xx_system
+ * @{
+ */
+
+/**
+ * @brief Define to prevent recursive inclusion
+ */
+#ifndef __SYSTEM_STM32G4XX_H
+#define __SYSTEM_STM32G4XX_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/** @addtogroup STM32G4xx_System_Includes
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @addtogroup STM32G4xx_System_Exported_Variables
+ * @{
+ */
+ /* The SystemCoreClock variable is updated in three ways:
+ 1) by calling CMSIS function SystemCoreClockUpdate()
+ 2) by calling HAL API function HAL_RCC_GetSysClockFreq()
+ 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
+ Note: If you use this function to configure the system clock; then there
+ is no need to call the 2 first functions listed above, since SystemCoreClock
+ variable is updated automatically.
+ */
+extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
+
+extern const uint8_t AHBPrescTable[16]; /*!< AHB prescalers table values */
+extern const uint8_t APBPrescTable[8]; /*!< APB prescalers table values */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32G4xx_System_Exported_Constants
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32G4xx_System_Exported_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32G4xx_System_Exported_Functions
+ * @{
+ */
+
+extern void SystemInit(void);
+extern void SystemCoreClockUpdate(void);
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__SYSTEM_STM32G4XX_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ChibiOS_20.3.2/os/common/ext/ST/STM32H7xx/stm32h723xx.h b/ChibiOS_20.3.2/os/common/ext/ST/STM32H7xx/stm32h723xx.h
new file mode 100644
index 0000000..ce185aa
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ST/STM32H7xx/stm32h723xx.h
@@ -0,0 +1,24175 @@
+/**
+ ******************************************************************************
+ * @file stm32h723xx.h
+ * @author MCD Application Team
+ * @brief CMSIS STM32H723xx Device Peripheral Access Layer Header File.
+ *
+ * This file contains:
+ * - Data structures and the address mapping for all peripherals
+ * - Peripheral's registers declarations and bits definition
+ * - Macros to access peripheral's registers hardware
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/** @addtogroup CMSIS_Device
+ * @{
+ */
+
+/** @addtogroup stm32h723xx
+ * @{
+ */
+
+#ifndef STM32H723xx_H
+#define STM32H723xx_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif /* __cplusplus */
+
+/** @addtogroup Peripheral_interrupt_number_definition
+ * @{
+ */
+
+/**
+ * @brief STM32H7XX Interrupt Number Definition, according to the selected device
+ * in @ref Library_configuration_section
+ */
+typedef enum
+{
+/****** Cortex-M Processor Exceptions Numbers *****************************************************************/
+ NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */
+ HardFault_IRQn = -13, /*!< 4 Cortex-M Memory Management Interrupt */
+ MemoryManagement_IRQn = -12, /*!< 4 Cortex-M Memory Management Interrupt */
+ BusFault_IRQn = -11, /*!< 5 Cortex-M Bus Fault Interrupt */
+ UsageFault_IRQn = -10, /*!< 6 Cortex-M Usage Fault Interrupt */
+ SVCall_IRQn = -5, /*!< 11 Cortex-M SV Call Interrupt */
+ DebugMonitor_IRQn = -4, /*!< 12 Cortex-M Debug Monitor Interrupt */
+ PendSV_IRQn = -2, /*!< 14 Cortex-M Pend SV Interrupt */
+ SysTick_IRQn = -1, /*!< 15 Cortex-M System Tick Interrupt */
+/****** STM32 specific Interrupt Numbers **********************************************************************/
+ WWDG_IRQn = 0, /*!< Window WatchDog Interrupt ( wwdg1_it, wwdg2_it) */
+ PVD_AVD_IRQn = 1, /*!< PVD/AVD through EXTI Line detection Interrupt */
+ TAMP_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts through the EXTI line */
+ RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI line */
+ FLASH_IRQn = 4, /*!< FLASH global Interrupt */
+ RCC_IRQn = 5, /*!< RCC global Interrupt */
+ EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */
+ EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */
+ EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */
+ EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */
+ EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */
+ DMA1_Stream0_IRQn = 11, /*!< DMA1 Stream 0 global Interrupt */
+ DMA1_Stream1_IRQn = 12, /*!< DMA1 Stream 1 global Interrupt */
+ DMA1_Stream2_IRQn = 13, /*!< DMA1 Stream 2 global Interrupt */
+ DMA1_Stream3_IRQn = 14, /*!< DMA1 Stream 3 global Interrupt */
+ DMA1_Stream4_IRQn = 15, /*!< DMA1 Stream 4 global Interrupt */
+ DMA1_Stream5_IRQn = 16, /*!< DMA1 Stream 5 global Interrupt */
+ DMA1_Stream6_IRQn = 17, /*!< DMA1 Stream 6 global Interrupt */
+ ADC_IRQn = 18, /*!< ADC1 and ADC2 global Interrupts */
+ FDCAN1_IT0_IRQn = 19, /*!< FDCAN1 Interrupt line 0 */
+ FDCAN2_IT0_IRQn = 20, /*!< FDCAN2 Interrupt line 0 */
+ FDCAN1_IT1_IRQn = 21, /*!< FDCAN1 Interrupt line 1 */
+ FDCAN2_IT1_IRQn = 22, /*!< FDCAN2 Interrupt line 1 */
+ EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */
+ TIM1_BRK_IRQn = 24, /*!< TIM1 Break Interrupt */
+ TIM1_UP_IRQn = 25, /*!< TIM1 Update Interrupt */
+ TIM1_TRG_COM_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt */
+ TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */
+ TIM2_IRQn = 28, /*!< TIM2 global Interrupt */
+ TIM3_IRQn = 29, /*!< TIM3 global Interrupt */
+ TIM4_IRQn = 30, /*!< TIM4 global Interrupt */
+ I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */
+ I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */
+ I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */
+ I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */
+ SPI1_IRQn = 35, /*!< SPI1 global Interrupt */
+ SPI2_IRQn = 36, /*!< SPI2 global Interrupt */
+ USART1_IRQn = 37, /*!< USART1 global Interrupt */
+ USART2_IRQn = 38, /*!< USART2 global Interrupt */
+ USART3_IRQn = 39, /*!< USART3 global Interrupt */
+ EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */
+ RTC_Alarm_IRQn = 41, /*!< RTC Alarm (A and B) through EXTI Line Interrupt */
+ TIM8_BRK_TIM12_IRQn = 43, /*!< TIM8 Break Interrupt and TIM12 global interrupt */
+ TIM8_UP_TIM13_IRQn = 44, /*!< TIM8 Update Interrupt and TIM13 global interrupt */
+ TIM8_TRG_COM_TIM14_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */
+ TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */
+ DMA1_Stream7_IRQn = 47, /*!< DMA1 Stream7 Interrupt */
+ FMC_IRQn = 48, /*!< FMC global Interrupt */
+ SDMMC1_IRQn = 49, /*!< SDMMC1 global Interrupt */
+ TIM5_IRQn = 50, /*!< TIM5 global Interrupt */
+ SPI3_IRQn = 51, /*!< SPI3 global Interrupt */
+ UART4_IRQn = 52, /*!< UART4 global Interrupt */
+ UART5_IRQn = 53, /*!< UART5 global Interrupt */
+ TIM6_DAC_IRQn = 54, /*!< TIM6 global and DAC1&2 underrun error interrupts */
+ TIM7_IRQn = 55, /*!< TIM7 global interrupt */
+ DMA2_Stream0_IRQn = 56, /*!< DMA2 Stream 0 global Interrupt */
+ DMA2_Stream1_IRQn = 57, /*!< DMA2 Stream 1 global Interrupt */
+ DMA2_Stream2_IRQn = 58, /*!< DMA2 Stream 2 global Interrupt */
+ DMA2_Stream3_IRQn = 59, /*!< DMA2 Stream 3 global Interrupt */
+ DMA2_Stream4_IRQn = 60, /*!< DMA2 Stream 4 global Interrupt */
+ ETH_IRQn = 61, /*!< Ethernet global Interrupt */
+ ETH_WKUP_IRQn = 62, /*!< Ethernet Wakeup through EXTI line Interrupt */
+ FDCAN_CAL_IRQn = 63, /*!< FDCAN Calibration unit Interrupt */
+ DMA2_Stream5_IRQn = 68, /*!< DMA2 Stream 5 global interrupt */
+ DMA2_Stream6_IRQn = 69, /*!< DMA2 Stream 6 global interrupt */
+ DMA2_Stream7_IRQn = 70, /*!< DMA2 Stream 7 global interrupt */
+ USART6_IRQn = 71, /*!< USART6 global interrupt */
+ I2C3_EV_IRQn = 72, /*!< I2C3 event interrupt */
+ I2C3_ER_IRQn = 73, /*!< I2C3 error interrupt */
+ OTG_HS_EP1_OUT_IRQn = 74, /*!< USB OTG HS End Point 1 Out global interrupt */
+ OTG_HS_EP1_IN_IRQn = 75, /*!< USB OTG HS End Point 1 In global interrupt */
+ OTG_HS_WKUP_IRQn = 76, /*!< USB OTG HS Wakeup through EXTI interrupt */
+ OTG_HS_IRQn = 77, /*!< USB OTG HS global interrupt */
+ DCMI_PSSI_IRQn = 78, /*!< DCMI and PSSI global interrupt */
+ RNG_IRQn = 80, /*!< RNG global interrupt */
+ FPU_IRQn = 81, /*!< FPU global interrupt */
+ UART7_IRQn = 82, /*!< UART7 global interrupt */
+ UART8_IRQn = 83, /*!< UART8 global interrupt */
+ SPI4_IRQn = 84, /*!< SPI4 global Interrupt */
+ SPI5_IRQn = 85, /*!< SPI5 global Interrupt */
+ SPI6_IRQn = 86, /*!< SPI6 global Interrupt */
+ SAI1_IRQn = 87, /*!< SAI1 global Interrupt */
+ LTDC_IRQn = 88, /*!< LTDC global Interrupt */
+ LTDC_ER_IRQn = 89, /*!< LTDC Error global Interrupt */
+ DMA2D_IRQn = 90, /*!< DMA2D global Interrupt */
+ OCTOSPI1_IRQn = 92, /*!< OCTOSPI1 global interrupt */
+ LPTIM1_IRQn = 93, /*!< LP TIM1 interrupt */
+ CEC_IRQn = 94, /*!< HDMI-CEC global Interrupt */
+ I2C4_EV_IRQn = 95, /*!< I2C4 Event Interrupt */
+ I2C4_ER_IRQn = 96, /*!< I2C4 Error Interrupt */
+ SPDIF_RX_IRQn = 97, /*!< SPDIF-RX global Interrupt */
+ DMAMUX1_OVR_IRQn = 102, /*!
+
+/** @addtogroup Peripheral_registers_structures
+ * @{
+ */
+
+/**
+ * @brief Analog to Digital Converter
+ */
+
+typedef struct
+{
+ __IO uint32_t ISR; /*!< ADC Interrupt and Status Register, Address offset: 0x00 */
+ __IO uint32_t IER; /*!< ADC Interrupt Enable Register, Address offset: 0x04 */
+ __IO uint32_t CR; /*!< ADC control register, Address offset: 0x08 */
+ __IO uint32_t CFGR; /*!< ADC Configuration register, Address offset: 0x0C */
+ __IO uint32_t CFGR2; /*!< ADC Configuration register 2, Address offset: 0x10 */
+ __IO uint32_t SMPR1; /*!< ADC sample time register 1, Address offset: 0x14 */
+ __IO uint32_t SMPR2; /*!< ADC sample time register 2, Address offset: 0x18 */
+ __IO uint32_t PCSEL; /*!< Rserved for ADC3, ADC1/2 pre-channel selection, Address offset: 0x1C */
+ __IO uint32_t LTR1; /*!< ADC watchdog Lower threshold register 1, Address offset: 0x20 */
+ __IO uint32_t HTR1; /*!< ADC watchdog higher threshold register 1, Address offset: 0x24 */
+ __IO uint32_t RES1; /*!< Rserved for ADC1/2, ADC3 threshold register, Address offset: 0x28 */
+ uint32_t RESERVED2; /*!< Reserved, 0x02C */
+ __IO uint32_t SQR1; /*!< ADC regular sequence register 1, Address offset: 0x30 */
+ __IO uint32_t SQR2; /*!< ADC regular sequence register 2, Address offset: 0x34 */
+ __IO uint32_t SQR3; /*!< ADC regular sequence register 3, Address offset: 0x38 */
+ __IO uint32_t SQR4; /*!< ADC regular sequence register 4, Address offset: 0x3C */
+ __IO uint32_t DR; /*!< ADC regular data register, Address offset: 0x40 */
+ uint32_t RESERVED3; /*!< Reserved, 0x044 */
+ uint32_t RESERVED4; /*!< Reserved, 0x048 */
+ __IO uint32_t JSQR; /*!< ADC injected sequence register, Address offset: 0x4C */
+ uint32_t RESERVED5[4]; /*!< Reserved, 0x050 - 0x05C */
+ __IO uint32_t OFR1; /*!< ADC offset register 1, Address offset: 0x60 */
+ __IO uint32_t OFR2; /*!< ADC offset register 2, Address offset: 0x64 */
+ __IO uint32_t OFR3; /*!< ADC offset register 3, Address offset: 0x68 */
+ __IO uint32_t OFR4; /*!< ADC offset register 4, Address offset: 0x6C */
+ uint32_t RESERVED6[4]; /*!< Reserved, 0x070 - 0x07C */
+ __IO uint32_t JDR1; /*!< ADC injected data register 1, Address offset: 0x80 */
+ __IO uint32_t JDR2; /*!< ADC injected data register 2, Address offset: 0x84 */
+ __IO uint32_t JDR3; /*!< ADC injected data register 3, Address offset: 0x88 */
+ __IO uint32_t JDR4; /*!< ADC injected data register 4, Address offset: 0x8C */
+ uint32_t RESERVED7[4]; /*!< Reserved, 0x090 - 0x09C */
+ __IO uint32_t AWD2CR; /*!< ADC Analog Watchdog 2 Configuration Register, Address offset: 0xA0 */
+ __IO uint32_t AWD3CR; /*!< ADC Analog Watchdog 3 Configuration Register, Address offset: 0xA4 */
+ uint32_t RESERVED8; /*!< Reserved, 0x0A8 */
+ uint32_t RESERVED9; /*!< Reserved, 0x0AC */
+ __IO uint32_t LTR2; /*!< ADC watchdog Lower threshold register 2, Difsel for ADC3, Address offset: 0xB0 */
+ __IO uint32_t HTR2; /*!< ADC watchdog Higher threshold register 2, Calfact for ADC3, Address offset: 0xB4 */
+ __IO uint32_t LTR3; /*!< ADC watchdog Lower threshold register 3, specific ADC1/2, Address offset: 0xB8 */
+ __IO uint32_t HTR3; /*!< ADC watchdog Higher threshold register 3, specific ADC1/2, Address offset: 0xBC */
+ __IO uint32_t DIFSEL; /*!< ADC Differential Mode Selection Register specific ADC1/2, Address offset: 0xC0 */
+ __IO uint32_t CALFACT; /*!< ADC Calibration Factors specific ADC1/2, Address offset: 0xC4 */
+ __IO uint32_t CALFACT2; /*!< ADC Linearity Calibration Factors specific ADC1/2, Address offset: 0xC8 */
+} ADC12_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t ISR; /*!< ADC Interrupt and Status Register, Address offset: 0x00 */
+ __IO uint32_t IER; /*!< ADC Interrupt Enable Register, Address offset: 0x04 */
+ __IO uint32_t CR; /*!< ADC control register, Address offset: 0x08 */
+ __IO uint32_t CFGR; /*!< ADC Configuration register, Address offset: 0x0C */
+ __IO uint32_t CFGR2; /*!< ADC Configuration register 2, Address offset: 0x10 */
+ __IO uint32_t SMPR1; /*!< ADC sample time register 1, Address offset: 0x14 */
+ __IO uint32_t SMPR2; /*!< ADC sample time register 2, Address offset: 0x18 */
+ __IO uint32_t RES0; /*!< Rserved for ADC3, ADC1/2 pre-channel selection, Address offset: 0x1C */
+ __IO uint16_t LTR1; /*!< ADC watchdog Lower threshold register 1, Address offset: 0x20 */
+ __IO uint16_t HTR1; /*!< ADC watchdog Lower threshold register 1, Address offset: 0x20 */
+ __IO uint16_t LTR2; /*!< ADC watchdog higher threshold register 1, Address offset: 0x24 */
+ __IO uint16_t HTR2; /*!< ADC watchdog higher threshold register 1, Address offset: 0x24 */
+ __IO uint16_t LTR3; /*!< Rserved for ADC1/2, ADC3 threshold register, Address offset: 0x28 */
+ __IO uint16_t HTR3; /*!< Rserved for ADC1/2, ADC3 threshold register, Address offset: 0x28 */
+ uint32_t RESERVED2; /*!< Reserved, 0x02C */
+ __IO uint32_t SQR1; /*!< ADC regular sequence register 1, Address offset: 0x30 */
+ __IO uint32_t SQR2; /*!< ADC regular sequence register 2, Address offset: 0x34 */
+ __IO uint32_t SQR3; /*!< ADC regular sequence register 3, Address offset: 0x38 */
+ __IO uint32_t SQR4; /*!< ADC regular sequence register 4, Address offset: 0x3C */
+ __IO uint32_t DR; /*!< ADC regular data register, Address offset: 0x40 */
+ uint32_t RESERVED3; /*!< Reserved, 0x044 */
+ uint32_t RESERVED4; /*!< Reserved, 0x048 */
+ __IO uint32_t JSQR; /*!< ADC injected sequence register, Address offset: 0x4C */
+ uint32_t RESERVED5[4]; /*!< Reserved, 0x050 - 0x05C */
+ __IO uint32_t OFR1; /*!< ADC offset register 1, Address offset: 0x60 */
+ __IO uint32_t OFR2; /*!< ADC offset register 2, Address offset: 0x64 */
+ __IO uint32_t OFR3; /*!< ADC offset register 3, Address offset: 0x68 */
+ __IO uint32_t OFR4; /*!< ADC offset register 4, Address offset: 0x6C */
+ uint32_t RESERVED6[4]; /*!< Reserved, 0x070 - 0x07C */
+ __IO uint32_t JDR1; /*!< ADC injected data register 1, Address offset: 0x80 */
+ __IO uint32_t JDR2; /*!< ADC injected data register 2, Address offset: 0x84 */
+ __IO uint32_t JDR3; /*!< ADC injected data register 3, Address offset: 0x88 */
+ __IO uint32_t JDR4; /*!< ADC injected data register 4, Address offset: 0x8C */
+ uint32_t RESERVED7[4]; /*!< Reserved, 0x090 - 0x09C */
+ __IO uint32_t AWD2CR; /*!< ADC Analog Watchdog 2 Configuration Register, Address offset: 0xA0 */
+ __IO uint32_t AWD3CR; /*!< ADC Analog Watchdog 3 Configuration Register, Address offset: 0xA4 */
+ uint32_t RESERVED8; /*!< Reserved, 0x0A8 */
+ uint32_t RESERVED9; /*!< Reserved, 0x0AC */
+ __IO uint32_t DIFSEL; /*!< ADC watchdog Lower threshold register 2, Difsel for ADC3, Address offset: 0xB0 */
+ __IO uint32_t CALFACT; /*!< ADC watchdog Higher threshold register 2, Calfact for ADC3, Address offset: 0xB4 */
+ __IO uint32_t RES10; /*!< ADC watchdog Lower threshold register 3, specific ADC1/2, Address offset: 0xB8 */
+ __IO uint32_t RES11; /*!< ADC watchdog Higher threshold register 3, specific ADC1/2, Address offset: 0xBC */
+ __IO uint32_t RES12; /*!< ADC Differential Mode Selection Register specific ADC1/2, Address offset: 0xC0 */
+ __IO uint32_t RES13; /*!< ADC Calibration Factors specific ADC1/2, Address offset: 0xC4 */
+ __IO uint32_t RES14; /*!< ADC Linearity Calibration Factors specific ADC1/2, Address offset: 0xC8 */
+} ADC3_TypeDef;
+
+
+typedef struct
+{
+__IO uint32_t CSR; /*!< ADC Common status register, Address offset: ADC1/3 base address + 0x300 */
+uint32_t RESERVED; /*!< Reserved, ADC1/3 base address + 0x304 */
+__IO uint32_t CCR; /*!< ADC common control register, Address offset: ADC1/3 base address + 0x308 */
+__IO uint32_t CDR; /*!< ADC common regular data register for dual Address offset: ADC1/3 base address + 0x30C */
+__IO uint32_t CDR2; /*!< ADC common regular data register for 32-bit dual mode Address offset: ADC1/3 base address + 0x310 */
+
+} ADC_Common_TypeDef;
+
+
+/**
+ * @brief VREFBUF
+ */
+
+typedef struct
+{
+ __IO uint32_t CSR; /*!< VREFBUF control and status register, Address offset: 0x00 */
+ __IO uint32_t CCR; /*!< VREFBUF calibration and control register, Address offset: 0x04 */
+} VREFBUF_TypeDef;
+
+
+/**
+ * @brief FD Controller Area Network
+ */
+
+typedef struct
+{
+ __IO uint32_t CREL; /*!< FDCAN Core Release register, Address offset: 0x000 */
+ __IO uint32_t ENDN; /*!< FDCAN Endian register, Address offset: 0x004 */
+ __IO uint32_t RESERVED1; /*!< Reserved, 0x008 */
+ __IO uint32_t DBTP; /*!< FDCAN Data Bit Timing & Prescaler register, Address offset: 0x00C */
+ __IO uint32_t TEST; /*!< FDCAN Test register, Address offset: 0x010 */
+ __IO uint32_t RWD; /*!< FDCAN RAM Watchdog register, Address offset: 0x014 */
+ __IO uint32_t CCCR; /*!< FDCAN CC Control register, Address offset: 0x018 */
+ __IO uint32_t NBTP; /*!< FDCAN Nominal Bit Timing & Prescaler register, Address offset: 0x01C */
+ __IO uint32_t TSCC; /*!< FDCAN Timestamp Counter Configuration register, Address offset: 0x020 */
+ __IO uint32_t TSCV; /*!< FDCAN Timestamp Counter Value register, Address offset: 0x024 */
+ __IO uint32_t TOCC; /*!< FDCAN Timeout Counter Configuration register, Address offset: 0x028 */
+ __IO uint32_t TOCV; /*!< FDCAN Timeout Counter Value register, Address offset: 0x02C */
+ __IO uint32_t RESERVED2[4]; /*!< Reserved, 0x030 - 0x03C */
+ __IO uint32_t ECR; /*!< FDCAN Error Counter register, Address offset: 0x040 */
+ __IO uint32_t PSR; /*!< FDCAN Protocol Status register, Address offset: 0x044 */
+ __IO uint32_t TDCR; /*!< FDCAN Transmitter Delay Compensation register, Address offset: 0x048 */
+ __IO uint32_t RESERVED3; /*!< Reserved, 0x04C */
+ __IO uint32_t IR; /*!< FDCAN Interrupt register, Address offset: 0x050 */
+ __IO uint32_t IE; /*!< FDCAN Interrupt Enable register, Address offset: 0x054 */
+ __IO uint32_t ILS; /*!< FDCAN Interrupt Line Select register, Address offset: 0x058 */
+ __IO uint32_t ILE; /*!< FDCAN Interrupt Line Enable register, Address offset: 0x05C */
+ __IO uint32_t RESERVED4[8]; /*!< Reserved, 0x060 - 0x07C */
+ __IO uint32_t GFC; /*!< FDCAN Global Filter Configuration register, Address offset: 0x080 */
+ __IO uint32_t SIDFC; /*!< FDCAN Standard ID Filter Configuration register, Address offset: 0x084 */
+ __IO uint32_t XIDFC; /*!< FDCAN Extended ID Filter Configuration register, Address offset: 0x088 */
+ __IO uint32_t RESERVED5; /*!< Reserved, 0x08C */
+ __IO uint32_t XIDAM; /*!< FDCAN Extended ID AND Mask register, Address offset: 0x090 */
+ __IO uint32_t HPMS; /*!< FDCAN High Priority Message Status register, Address offset: 0x094 */
+ __IO uint32_t NDAT1; /*!< FDCAN New Data 1 register, Address offset: 0x098 */
+ __IO uint32_t NDAT2; /*!< FDCAN New Data 2 register, Address offset: 0x09C */
+ __IO uint32_t RXF0C; /*!< FDCAN Rx FIFO 0 Configuration register, Address offset: 0x0A0 */
+ __IO uint32_t RXF0S; /*!< FDCAN Rx FIFO 0 Status register, Address offset: 0x0A4 */
+ __IO uint32_t RXF0A; /*!< FDCAN Rx FIFO 0 Acknowledge register, Address offset: 0x0A8 */
+ __IO uint32_t RXBC; /*!< FDCAN Rx Buffer Configuration register, Address offset: 0x0AC */
+ __IO uint32_t RXF1C; /*!< FDCAN Rx FIFO 1 Configuration register, Address offset: 0x0B0 */
+ __IO uint32_t RXF1S; /*!< FDCAN Rx FIFO 1 Status register, Address offset: 0x0B4 */
+ __IO uint32_t RXF1A; /*!< FDCAN Rx FIFO 1 Acknowledge register, Address offset: 0x0B8 */
+ __IO uint32_t RXESC; /*!< FDCAN Rx Buffer/FIFO Element Size Configuration register, Address offset: 0x0BC */
+ __IO uint32_t TXBC; /*!< FDCAN Tx Buffer Configuration register, Address offset: 0x0C0 */
+ __IO uint32_t TXFQS; /*!< FDCAN Tx FIFO/Queue Status register, Address offset: 0x0C4 */
+ __IO uint32_t TXESC; /*!< FDCAN Tx Buffer Element Size Configuration register, Address offset: 0x0C8 */
+ __IO uint32_t TXBRP; /*!< FDCAN Tx Buffer Request Pending register, Address offset: 0x0CC */
+ __IO uint32_t TXBAR; /*!< FDCAN Tx Buffer Add Request register, Address offset: 0x0D0 */
+ __IO uint32_t TXBCR; /*!< FDCAN Tx Buffer Cancellation Request register, Address offset: 0x0D4 */
+ __IO uint32_t TXBTO; /*!< FDCAN Tx Buffer Transmission Occurred register, Address offset: 0x0D8 */
+ __IO uint32_t TXBCF; /*!< FDCAN Tx Buffer Cancellation Finished register, Address offset: 0x0DC */
+ __IO uint32_t TXBTIE; /*!< FDCAN Tx Buffer Transmission Interrupt Enable register, Address offset: 0x0E0 */
+ __IO uint32_t TXBCIE; /*!< FDCAN Tx Buffer Cancellation Finished Interrupt Enable register, Address offset: 0x0E4 */
+ __IO uint32_t RESERVED6[2]; /*!< Reserved, 0x0E8 - 0x0EC */
+ __IO uint32_t TXEFC; /*!< FDCAN Tx Event FIFO Configuration register, Address offset: 0x0F0 */
+ __IO uint32_t TXEFS; /*!< FDCAN Tx Event FIFO Status register, Address offset: 0x0F4 */
+ __IO uint32_t TXEFA; /*!< FDCAN Tx Event FIFO Acknowledge register, Address offset: 0x0F8 */
+ __IO uint32_t RESERVED7; /*!< Reserved, 0x0FC */
+} FDCAN_GlobalTypeDef;
+
+/**
+ * @brief TTFD Controller Area Network
+ */
+
+typedef struct
+{
+ __IO uint32_t TTTMC; /*!< TT Trigger Memory Configuration register, Address offset: 0x100 */
+ __IO uint32_t TTRMC; /*!< TT Reference Message Configuration register, Address offset: 0x104 */
+ __IO uint32_t TTOCF; /*!< TT Operation Configuration register, Address offset: 0x108 */
+ __IO uint32_t TTMLM; /*!< TT Matrix Limits register, Address offset: 0x10C */
+ __IO uint32_t TURCF; /*!< TUR Configuration register, Address offset: 0x110 */
+ __IO uint32_t TTOCN; /*!< TT Operation Control register, Address offset: 0x114 */
+ __IO uint32_t TTGTP; /*!< TT Global Time Preset register, Address offset: 0x118 */
+ __IO uint32_t TTTMK; /*!< TT Time Mark register, Address offset: 0x11C */
+ __IO uint32_t TTIR; /*!< TT Interrupt register, Address offset: 0x120 */
+ __IO uint32_t TTIE; /*!< TT Interrupt Enable register, Address offset: 0x124 */
+ __IO uint32_t TTILS; /*!< TT Interrupt Line Select register, Address offset: 0x128 */
+ __IO uint32_t TTOST; /*!< TT Operation Status register, Address offset: 0x12C */
+ __IO uint32_t TURNA; /*!< TT TUR Numerator Actual register, Address offset: 0x130 */
+ __IO uint32_t TTLGT; /*!< TT Local and Global Time register, Address offset: 0x134 */
+ __IO uint32_t TTCTC; /*!< TT Cycle Time and Count register, Address offset: 0x138 */
+ __IO uint32_t TTCPT; /*!< TT Capture Time register, Address offset: 0x13C */
+ __IO uint32_t TTCSM; /*!< TT Cycle Sync Mark register, Address offset: 0x140 */
+ __IO uint32_t RESERVED1[111]; /*!< Reserved, 0x144 - 0x2FC */
+ __IO uint32_t TTTS; /*!< TT Trigger Select register, Address offset: 0x300 */
+} TTCAN_TypeDef;
+
+/**
+ * @brief FD Controller Area Network
+ */
+
+typedef struct
+{
+ __IO uint32_t CREL; /*!< Clock Calibration Unit Core Release register, Address offset: 0x00 */
+ __IO uint32_t CCFG; /*!< Calibration Configuration register, Address offset: 0x04 */
+ __IO uint32_t CSTAT; /*!< Calibration Status register, Address offset: 0x08 */
+ __IO uint32_t CWD; /*!< Calibration Watchdog register, Address offset: 0x0C */
+ __IO uint32_t IR; /*!< CCU Interrupt register, Address offset: 0x10 */
+ __IO uint32_t IE; /*!< CCU Interrupt Enable register, Address offset: 0x14 */
+} FDCAN_ClockCalibrationUnit_TypeDef;
+
+
+/**
+ * @brief Consumer Electronics Control
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< CEC control register, Address offset:0x00 */
+ __IO uint32_t CFGR; /*!< CEC configuration register, Address offset:0x04 */
+ __IO uint32_t TXDR; /*!< CEC Tx data register , Address offset:0x08 */
+ __IO uint32_t RXDR; /*!< CEC Rx Data Register, Address offset:0x0C */
+ __IO uint32_t ISR; /*!< CEC Interrupt and Status Register, Address offset:0x10 */
+ __IO uint32_t IER; /*!< CEC interrupt enable register, Address offset:0x14 */
+}CEC_TypeDef;
+
+/**
+ * @brief COordincate Rotation DIgital Computer
+ */
+typedef struct
+{
+ __IO uint32_t CSR; /*!< CORDIC control and status register, Address offset: 0x00 */
+ __IO uint32_t WDATA; /*!< CORDIC argument register, Address offset: 0x04 */
+ __IO uint32_t RDATA; /*!< CORDIC result register, Address offset: 0x08 */
+} CORDIC_TypeDef;
+
+/**
+ * @brief CRC calculation unit
+ */
+
+typedef struct
+{
+ __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */
+ __IO uint32_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */
+ __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */
+ uint32_t RESERVED2; /*!< Reserved, 0x0C */
+ __IO uint32_t INIT; /*!< Initial CRC value register, Address offset: 0x10 */
+ __IO uint32_t POL; /*!< CRC polynomial register, Address offset: 0x14 */
+} CRC_TypeDef;
+
+
+/**
+ * @brief Clock Recovery System
+ */
+typedef struct
+{
+__IO uint32_t CR; /*!< CRS ccontrol register, Address offset: 0x00 */
+__IO uint32_t CFGR; /*!< CRS configuration register, Address offset: 0x04 */
+__IO uint32_t ISR; /*!< CRS interrupt and status register, Address offset: 0x08 */
+__IO uint32_t ICR; /*!< CRS interrupt flag clear register, Address offset: 0x0C */
+} CRS_TypeDef;
+
+
+/**
+ * @brief Digital to Analog Converter
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< DAC control register, Address offset: 0x00 */
+ __IO uint32_t SWTRIGR; /*!< DAC software trigger register, Address offset: 0x04 */
+ __IO uint32_t DHR12R1; /*!< DAC channel1 12-bit right-aligned data holding register, Address offset: 0x08 */
+ __IO uint32_t DHR12L1; /*!< DAC channel1 12-bit left aligned data holding register, Address offset: 0x0C */
+ __IO uint32_t DHR8R1; /*!< DAC channel1 8-bit right aligned data holding register, Address offset: 0x10 */
+ __IO uint32_t DHR12R2; /*!< DAC channel2 12-bit right aligned data holding register, Address offset: 0x14 */
+ __IO uint32_t DHR12L2; /*!< DAC channel2 12-bit left aligned data holding register, Address offset: 0x18 */
+ __IO uint32_t DHR8R2; /*!< DAC channel2 8-bit right-aligned data holding register, Address offset: 0x1C */
+ __IO uint32_t DHR12RD; /*!< Dual DAC 12-bit right-aligned data holding register, Address offset: 0x20 */
+ __IO uint32_t DHR12LD; /*!< DUAL DAC 12-bit left aligned data holding register, Address offset: 0x24 */
+ __IO uint32_t DHR8RD; /*!< DUAL DAC 8-bit right aligned data holding register, Address offset: 0x28 */
+ __IO uint32_t DOR1; /*!< DAC channel1 data output register, Address offset: 0x2C */
+ __IO uint32_t DOR2; /*!< DAC channel2 data output register, Address offset: 0x30 */
+ __IO uint32_t SR; /*!< DAC status register, Address offset: 0x34 */
+ __IO uint32_t CCR; /*!< DAC calibration control register, Address offset: 0x38 */
+ __IO uint32_t MCR; /*!< DAC mode control register, Address offset: 0x3C */
+ __IO uint32_t SHSR1; /*!< DAC Sample and Hold sample time register 1, Address offset: 0x40 */
+ __IO uint32_t SHSR2; /*!< DAC Sample and Hold sample time register 2, Address offset: 0x44 */
+ __IO uint32_t SHHR; /*!< DAC Sample and Hold hold time register, Address offset: 0x48 */
+ __IO uint32_t SHRR; /*!< DAC Sample and Hold refresh time register, Address offset: 0x4C */
+} DAC_TypeDef;
+
+/**
+ * @brief DFSDM module registers
+ */
+typedef struct
+{
+ __IO uint32_t FLTCR1; /*!< DFSDM control register1, Address offset: 0x100 */
+ __IO uint32_t FLTCR2; /*!< DFSDM control register2, Address offset: 0x104 */
+ __IO uint32_t FLTISR; /*!< DFSDM interrupt and status register, Address offset: 0x108 */
+ __IO uint32_t FLTICR; /*!< DFSDM interrupt flag clear register, Address offset: 0x10C */
+ __IO uint32_t FLTJCHGR; /*!< DFSDM injected channel group selection register, Address offset: 0x110 */
+ __IO uint32_t FLTFCR; /*!< DFSDM filter control register, Address offset: 0x114 */
+ __IO uint32_t FLTJDATAR; /*!< DFSDM data register for injected group, Address offset: 0x118 */
+ __IO uint32_t FLTRDATAR; /*!< DFSDM data register for regular group, Address offset: 0x11C */
+ __IO uint32_t FLTAWHTR; /*!< DFSDM analog watchdog high threshold register, Address offset: 0x120 */
+ __IO uint32_t FLTAWLTR; /*!< DFSDM analog watchdog low threshold register, Address offset: 0x124 */
+ __IO uint32_t FLTAWSR; /*!< DFSDM analog watchdog status register Address offset: 0x128 */
+ __IO uint32_t FLTAWCFR; /*!< DFSDM analog watchdog clear flag register Address offset: 0x12C */
+ __IO uint32_t FLTEXMAX; /*!< DFSDM extreme detector maximum register, Address offset: 0x130 */
+ __IO uint32_t FLTEXMIN; /*!< DFSDM extreme detector minimum register Address offset: 0x134 */
+ __IO uint32_t FLTCNVTIMR; /*!< DFSDM conversion timer, Address offset: 0x138 */
+} DFSDM_Filter_TypeDef;
+
+/**
+ * @brief DFSDM channel configuration registers
+ */
+typedef struct
+{
+ __IO uint32_t CHCFGR1; /*!< DFSDM channel configuration register1, Address offset: 0x00 */
+ __IO uint32_t CHCFGR2; /*!< DFSDM channel configuration register2, Address offset: 0x04 */
+ __IO uint32_t CHAWSCDR; /*!< DFSDM channel analog watchdog and
+ short circuit detector register, Address offset: 0x08 */
+ __IO uint32_t CHWDATAR; /*!< DFSDM channel watchdog filter data register, Address offset: 0x0C */
+ __IO uint32_t CHDATINR; /*!< DFSDM channel data input register, Address offset: 0x10 */
+} DFSDM_Channel_TypeDef;
+
+/**
+ * @brief Debug MCU
+ */
+typedef struct
+{
+ __IO uint32_t IDCODE; /*!< MCU device ID code, Address offset: 0x00 */
+ __IO uint32_t CR; /*!< Debug MCU configuration register, Address offset: 0x04 */
+ uint32_t RESERVED4[11]; /*!< Reserved, Address offset: 0x08 */
+ __IO uint32_t APB3FZ1; /*!< Debug MCU APB3FZ1 freeze register, Address offset: 0x34 */
+ uint32_t RESERVED5; /*!< Reserved, Address offset: 0x38 */
+ __IO uint32_t APB1LFZ1; /*!< Debug MCU APB1LFZ1 freeze register, Address offset: 0x3C */
+ uint32_t RESERVED6; /*!< Reserved, Address offset: 0x40 */
+ __IO uint32_t APB1HFZ1; /*!< Debug MCU APB1LFZ1 freeze register, Address offset: 0x44 */
+ uint32_t RESERVED7; /*!< Reserved, Address offset: 0x48 */
+ __IO uint32_t APB2FZ1; /*!< Debug MCU APB2FZ1 freeze register, Address offset: 0x4C */
+ uint32_t RESERVED8; /*!< Reserved, Address offset: 0x50 */
+ __IO uint32_t APB4FZ1; /*!< Debug MCU APB4FZ1 freeze register, Address offset: 0x54 */
+ __IO uint32_t RESERVED9[990]; /*!< Reserved, Address offset: 0x58-0xFCC */
+ __IO uint32_t PIDR4; /*!< Debug MCU peripheral identity register 4, Address offset: 0xFD0 */
+ __IO uint32_t RESERVED10[3];/*!< Reserved, Address offset: 0xFD4-0xFDC */
+ __IO uint32_t PIDR0; /*!< Debug MCU peripheral identity register 0, Address offset: 0xFE0 */
+ __IO uint32_t PIDR1; /*!< Debug MCU peripheral identity register 1, Address offset: 0xFE4 */
+ __IO uint32_t PIDR2; /*!< Debug MCU peripheral identity register 2, Address offset: 0xFE8 */
+ __IO uint32_t PIDR3; /*!< Debug MCU peripheral identity register 3, Address offset: 0xFEC */
+ __IO uint32_t CIDR0; /*!< Debug MCU component identity register 0, Address offset: 0xFF0 */
+ __IO uint32_t CIDR1; /*!< Debug MCU component identity register 1, Address offset: 0xFF4 */
+ __IO uint32_t CIDR2; /*!< Debug MCU component identity register 2, Address offset: 0xFF8 */
+ __IO uint32_t CIDR3; /*!< Debug MCU component identity register 3, Address offset: 0xFFC */
+}DBGMCU_TypeDef;
+/**
+ * @brief DCMI
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< DCMI control register 1, Address offset: 0x00 */
+ __IO uint32_t SR; /*!< DCMI status register, Address offset: 0x04 */
+ __IO uint32_t RISR; /*!< DCMI raw interrupt status register, Address offset: 0x08 */
+ __IO uint32_t IER; /*!< DCMI interrupt enable register, Address offset: 0x0C */
+ __IO uint32_t MISR; /*!< DCMI masked interrupt status register, Address offset: 0x10 */
+ __IO uint32_t ICR; /*!< DCMI interrupt clear register, Address offset: 0x14 */
+ __IO uint32_t ESCR; /*!< DCMI embedded synchronization code register, Address offset: 0x18 */
+ __IO uint32_t ESUR; /*!< DCMI embedded synchronization unmask register, Address offset: 0x1C */
+ __IO uint32_t CWSTRTR; /*!< DCMI crop window start, Address offset: 0x20 */
+ __IO uint32_t CWSIZER; /*!< DCMI crop window size, Address offset: 0x24 */
+ __IO uint32_t DR; /*!< DCMI data register, Address offset: 0x28 */
+} DCMI_TypeDef;
+
+/**
+ * @brief PSSI
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< PSSI control register 1, Address offset: 0x000 */
+ __IO uint32_t SR; /*!< PSSI status register, Address offset: 0x004 */
+ __IO uint32_t RIS; /*!< PSSI raw interrupt status register, Address offset: 0x008 */
+ __IO uint32_t IER; /*!< PSSI interrupt enable register, Address offset: 0x00C */
+ __IO uint32_t MIS; /*!< PSSI masked interrupt status register, Address offset: 0x010 */
+ __IO uint32_t ICR; /*!< PSSI interrupt clear register, Address offset: 0x014 */
+ __IO uint32_t RESERVED1[4]; /*!< Reserved, 0x018 - 0x024 */
+ __IO uint32_t DR; /*!< PSSI data register, Address offset: 0x028 */
+ __IO uint32_t RESERVED2[241]; /*!< Reserved, 0x02C - 0x3EC */
+ __IO uint32_t HWCFGR; /*!< PSSI IP HW configuration register, Address offset: 0x3F0 */
+ __IO uint32_t VERR; /*!< PSSI IP version register, Address offset: 0x3F4 */
+ __IO uint32_t IPIDR; /*!< PSSI IP ID register, Address offset: 0x3F8 */
+ __IO uint32_t SIDR; /*!< PSSI SIZE ID register, Address offset: 0x3FC */
+} PSSI_TypeDef;
+
+/**
+ * @brief DMA Controller
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< DMA stream x configuration register */
+ __IO uint32_t NDTR; /*!< DMA stream x number of data register */
+ __IO uint32_t PAR; /*!< DMA stream x peripheral address register */
+ __IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
+ __IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
+ __IO uint32_t FCR; /*!< DMA stream x FIFO control register */
+} DMA_Stream_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t LISR; /*!< DMA low interrupt status register, Address offset: 0x00 */
+ __IO uint32_t HISR; /*!< DMA high interrupt status register, Address offset: 0x04 */
+ __IO uint32_t LIFCR; /*!< DMA low interrupt flag clear register, Address offset: 0x08 */
+ __IO uint32_t HIFCR; /*!< DMA high interrupt flag clear register, Address offset: 0x0C */
+} DMA_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t CCR; /*!< DMA channel x configuration register */
+ __IO uint32_t CNDTR; /*!< DMA channel x number of data register */
+ __IO uint32_t CPAR; /*!< DMA channel x peripheral address register */
+ __IO uint32_t CM0AR; /*!< DMA channel x memory 0 address register */
+ __IO uint32_t CM1AR; /*!< DMA channel x memory 1 address register */
+} BDMA_Channel_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t ISR; /*!< DMA interrupt status register, Address offset: 0x00 */
+ __IO uint32_t IFCR; /*!< DMA interrupt flag clear register, Address offset: 0x04 */
+} BDMA_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t CCR; /*!< DMA Multiplexer Channel x Control Register */
+}DMAMUX_Channel_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t CSR; /*!< DMA Channel Status Register */
+ __IO uint32_t CFR; /*!< DMA Channel Clear Flag Register */
+}DMAMUX_ChannelStatus_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t RGCR; /*!< DMA Request Generator x Control Register */
+}DMAMUX_RequestGen_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t RGSR; /*!< DMA Request Generator Status Register */
+ __IO uint32_t RGCFR; /*!< DMA Request Generator Clear Flag Register */
+}DMAMUX_RequestGenStatus_TypeDef;
+
+/**
+ * @brief MDMA Controller
+ */
+typedef struct
+{
+ __IO uint32_t GISR0; /*!< MDMA Global Interrupt/Status Register 0, Address offset: 0x00 */
+}MDMA_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t CISR; /*!< MDMA channel x interrupt/status register, Address offset: 0x40 */
+ __IO uint32_t CIFCR; /*!< MDMA channel x interrupt flag clear register, Address offset: 0x44 */
+ __IO uint32_t CESR; /*!< MDMA Channel x error status register, Address offset: 0x48 */
+ __IO uint32_t CCR; /*!< MDMA channel x control register, Address offset: 0x4C */
+ __IO uint32_t CTCR; /*!< MDMA channel x Transfer Configuration register, Address offset: 0x50 */
+ __IO uint32_t CBNDTR; /*!< MDMA Channel x block number of data register, Address offset: 0x54 */
+ __IO uint32_t CSAR; /*!< MDMA channel x source address register, Address offset: 0x58 */
+ __IO uint32_t CDAR; /*!< MDMA channel x destination address register, Address offset: 0x5C */
+ __IO uint32_t CBRUR; /*!< MDMA channel x Block Repeat address Update register, Address offset: 0x60 */
+ __IO uint32_t CLAR; /*!< MDMA channel x Link Address register, Address offset: 0x64 */
+ __IO uint32_t CTBR; /*!< MDMA channel x Trigger and Bus selection Register, Address offset: 0x68 */
+ uint32_t RESERVED0; /*!< Reserved, 0x68 */
+ __IO uint32_t CMAR; /*!< MDMA channel x Mask address register, Address offset: 0x70 */
+ __IO uint32_t CMDR; /*!< MDMA channel x Mask Data register, Address offset: 0x74 */
+}MDMA_Channel_TypeDef;
+
+/**
+ * @brief DMA2D Controller
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< DMA2D Control Register, Address offset: 0x00 */
+ __IO uint32_t ISR; /*!< DMA2D Interrupt Status Register, Address offset: 0x04 */
+ __IO uint32_t IFCR; /*!< DMA2D Interrupt Flag Clear Register, Address offset: 0x08 */
+ __IO uint32_t FGMAR; /*!< DMA2D Foreground Memory Address Register, Address offset: 0x0C */
+ __IO uint32_t FGOR; /*!< DMA2D Foreground Offset Register, Address offset: 0x10 */
+ __IO uint32_t BGMAR; /*!< DMA2D Background Memory Address Register, Address offset: 0x14 */
+ __IO uint32_t BGOR; /*!< DMA2D Background Offset Register, Address offset: 0x18 */
+ __IO uint32_t FGPFCCR; /*!< DMA2D Foreground PFC Control Register, Address offset: 0x1C */
+ __IO uint32_t FGCOLR; /*!< DMA2D Foreground Color Register, Address offset: 0x20 */
+ __IO uint32_t BGPFCCR; /*!< DMA2D Background PFC Control Register, Address offset: 0x24 */
+ __IO uint32_t BGCOLR; /*!< DMA2D Background Color Register, Address offset: 0x28 */
+ __IO uint32_t FGCMAR; /*!< DMA2D Foreground CLUT Memory Address Register, Address offset: 0x2C */
+ __IO uint32_t BGCMAR; /*!< DMA2D Background CLUT Memory Address Register, Address offset: 0x30 */
+ __IO uint32_t OPFCCR; /*!< DMA2D Output PFC Control Register, Address offset: 0x34 */
+ __IO uint32_t OCOLR; /*!< DMA2D Output Color Register, Address offset: 0x38 */
+ __IO uint32_t OMAR; /*!< DMA2D Output Memory Address Register, Address offset: 0x3C */
+ __IO uint32_t OOR; /*!< DMA2D Output Offset Register, Address offset: 0x40 */
+ __IO uint32_t NLR; /*!< DMA2D Number of Line Register, Address offset: 0x44 */
+ __IO uint32_t LWR; /*!< DMA2D Line Watermark Register, Address offset: 0x48 */
+ __IO uint32_t AMTCR; /*!< DMA2D AHB Master Timer Configuration Register, Address offset: 0x4C */
+ uint32_t RESERVED[236]; /*!< Reserved, 0x50-0x3FF */
+ __IO uint32_t FGCLUT[256]; /*!< DMA2D Foreground CLUT, Address offset:400-7FF */
+ __IO uint32_t BGCLUT[256]; /*!< DMA2D Background CLUT, Address offset:800-BFF */
+} DMA2D_TypeDef;
+
+
+/**
+ * @brief Ethernet MAC
+ */
+typedef struct
+{
+ __IO uint32_t MACCR;
+ __IO uint32_t MACECR;
+ __IO uint32_t MACPFR;
+ __IO uint32_t MACWTR;
+ __IO uint32_t MACHT0R;
+ __IO uint32_t MACHT1R;
+ uint32_t RESERVED1[14];
+ __IO uint32_t MACVTR;
+ uint32_t RESERVED2;
+ __IO uint32_t MACVHTR;
+ uint32_t RESERVED3;
+ __IO uint32_t MACVIR;
+ __IO uint32_t MACIVIR;
+ uint32_t RESERVED4[2];
+ __IO uint32_t MACTFCR;
+ uint32_t RESERVED5[7];
+ __IO uint32_t MACRFCR;
+ uint32_t RESERVED6[7];
+ __IO uint32_t MACISR;
+ __IO uint32_t MACIER;
+ __IO uint32_t MACRXTXSR;
+ uint32_t RESERVED7;
+ __IO uint32_t MACPCSR;
+ __IO uint32_t MACRWKPFR;
+ uint32_t RESERVED8[2];
+ __IO uint32_t MACLCSR;
+ __IO uint32_t MACLTCR;
+ __IO uint32_t MACLETR;
+ __IO uint32_t MAC1USTCR;
+ uint32_t RESERVED9[12];
+ __IO uint32_t MACVR;
+ __IO uint32_t MACDR;
+ uint32_t RESERVED10;
+ __IO uint32_t MACHWF0R;
+ __IO uint32_t MACHWF1R;
+ __IO uint32_t MACHWF2R;
+ uint32_t RESERVED11[54];
+ __IO uint32_t MACMDIOAR;
+ __IO uint32_t MACMDIODR;
+ uint32_t RESERVED12[2];
+ __IO uint32_t MACARPAR;
+ uint32_t RESERVED13[59];
+ __IO uint32_t MACA0HR;
+ __IO uint32_t MACA0LR;
+ __IO uint32_t MACA1HR;
+ __IO uint32_t MACA1LR;
+ __IO uint32_t MACA2HR;
+ __IO uint32_t MACA2LR;
+ __IO uint32_t MACA3HR;
+ __IO uint32_t MACA3LR;
+ uint32_t RESERVED14[248];
+ __IO uint32_t MMCCR;
+ __IO uint32_t MMCRIR;
+ __IO uint32_t MMCTIR;
+ __IO uint32_t MMCRIMR;
+ __IO uint32_t MMCTIMR;
+ uint32_t RESERVED15[14];
+ __IO uint32_t MMCTSCGPR;
+ __IO uint32_t MMCTMCGPR;
+ uint32_t RESERVED16[5];
+ __IO uint32_t MMCTPCGR;
+ uint32_t RESERVED17[10];
+ __IO uint32_t MMCRCRCEPR;
+ __IO uint32_t MMCRAEPR;
+ uint32_t RESERVED18[10];
+ __IO uint32_t MMCRUPGR;
+ uint32_t RESERVED19[9];
+ __IO uint32_t MMCTLPIMSTR;
+ __IO uint32_t MMCTLPITCR;
+ __IO uint32_t MMCRLPIMSTR;
+ __IO uint32_t MMCRLPITCR;
+ uint32_t RESERVED20[65];
+ __IO uint32_t MACL3L4C0R;
+ __IO uint32_t MACL4A0R;
+ uint32_t RESERVED21[2];
+ __IO uint32_t MACL3A0R0R;
+ __IO uint32_t MACL3A1R0R;
+ __IO uint32_t MACL3A2R0R;
+ __IO uint32_t MACL3A3R0R;
+ uint32_t RESERVED22[4];
+ __IO uint32_t MACL3L4C1R;
+ __IO uint32_t MACL4A1R;
+ uint32_t RESERVED23[2];
+ __IO uint32_t MACL3A0R1R;
+ __IO uint32_t MACL3A1R1R;
+ __IO uint32_t MACL3A2R1R;
+ __IO uint32_t MACL3A3R1R;
+ uint32_t RESERVED24[108];
+ __IO uint32_t MACTSCR;
+ __IO uint32_t MACSSIR;
+ __IO uint32_t MACSTSR;
+ __IO uint32_t MACSTNR;
+ __IO uint32_t MACSTSUR;
+ __IO uint32_t MACSTNUR;
+ __IO uint32_t MACTSAR;
+ uint32_t RESERVED25;
+ __IO uint32_t MACTSSR;
+ uint32_t RESERVED26[3];
+ __IO uint32_t MACTTSSNR;
+ __IO uint32_t MACTTSSSR;
+ uint32_t RESERVED27[2];
+ __IO uint32_t MACACR;
+ uint32_t RESERVED28;
+ __IO uint32_t MACATSNR;
+ __IO uint32_t MACATSSR;
+ __IO uint32_t MACTSIACR;
+ __IO uint32_t MACTSEACR;
+ __IO uint32_t MACTSICNR;
+ __IO uint32_t MACTSECNR;
+ uint32_t RESERVED29[4];
+ __IO uint32_t MACPPSCR;
+ uint32_t RESERVED30[3];
+ __IO uint32_t MACPPSTTSR;
+ __IO uint32_t MACPPSTTNR;
+ __IO uint32_t MACPPSIR;
+ __IO uint32_t MACPPSWR;
+ uint32_t RESERVED31[12];
+ __IO uint32_t MACPOCR;
+ __IO uint32_t MACSPI0R;
+ __IO uint32_t MACSPI1R;
+ __IO uint32_t MACSPI2R;
+ __IO uint32_t MACLMIR;
+ uint32_t RESERVED32[11];
+ __IO uint32_t MTLOMR;
+ uint32_t RESERVED33[7];
+ __IO uint32_t MTLISR;
+ uint32_t RESERVED34[55];
+ __IO uint32_t MTLTQOMR;
+ __IO uint32_t MTLTQUR;
+ __IO uint32_t MTLTQDR;
+ uint32_t RESERVED35[8];
+ __IO uint32_t MTLQICSR;
+ __IO uint32_t MTLRQOMR;
+ __IO uint32_t MTLRQMPOCR;
+ __IO uint32_t MTLRQDR;
+ uint32_t RESERVED36[177];
+ __IO uint32_t DMAMR;
+ __IO uint32_t DMASBMR;
+ __IO uint32_t DMAISR;
+ __IO uint32_t DMADSR;
+ uint32_t RESERVED37[60];
+ __IO uint32_t DMACCR;
+ __IO uint32_t DMACTCR;
+ __IO uint32_t DMACRCR;
+ uint32_t RESERVED38[2];
+ __IO uint32_t DMACTDLAR;
+ uint32_t RESERVED39;
+ __IO uint32_t DMACRDLAR;
+ __IO uint32_t DMACTDTPR;
+ uint32_t RESERVED40;
+ __IO uint32_t DMACRDTPR;
+ __IO uint32_t DMACTDRLR;
+ __IO uint32_t DMACRDRLR;
+ __IO uint32_t DMACIER;
+ __IO uint32_t DMACRIWTR;
+__IO uint32_t DMACSFCSR;
+ uint32_t RESERVED41;
+ __IO uint32_t DMACCATDR;
+ uint32_t RESERVED42;
+ __IO uint32_t DMACCARDR;
+ uint32_t RESERVED43;
+ __IO uint32_t DMACCATBR;
+ uint32_t RESERVED44;
+ __IO uint32_t DMACCARBR;
+ __IO uint32_t DMACSR;
+uint32_t RESERVED45[2];
+__IO uint32_t DMACMFCR;
+}ETH_TypeDef;
+/**
+ * @brief External Interrupt/Event Controller
+ */
+
+typedef struct
+{
+__IO uint32_t RTSR1; /*!< EXTI Rising trigger selection register, Address offset: 0x00 */
+__IO uint32_t FTSR1; /*!< EXTI Falling trigger selection register, Address offset: 0x04 */
+__IO uint32_t SWIER1; /*!< EXTI Software interrupt event register, Address offset: 0x08 */
+__IO uint32_t D3PMR1; /*!< EXTI D3 Pending mask register, (same register as to SRDPMR1) Address offset: 0x0C */
+__IO uint32_t D3PCR1L; /*!< EXTI D3 Pending clear selection register low, (same register as to SRDPCR1L) Address offset: 0x10 */
+__IO uint32_t D3PCR1H; /*!< EXTI D3 Pending clear selection register High, (same register as to SRDPCR1H) Address offset: 0x14 */
+uint32_t RESERVED1[2]; /*!< Reserved, 0x18 to 0x1C */
+__IO uint32_t RTSR2; /*!< EXTI Rising trigger selection register, Address offset: 0x20 */
+__IO uint32_t FTSR2; /*!< EXTI Falling trigger selection register, Address offset: 0x24 */
+__IO uint32_t SWIER2; /*!< EXTI Software interrupt event register, Address offset: 0x28 */
+__IO uint32_t D3PMR2; /*!< EXTI D3 Pending mask register, (same register as to SRDPMR2) Address offset: 0x2C */
+__IO uint32_t D3PCR2L; /*!< EXTI D3 Pending clear selection register low, (same register as to SRDPCR2L) Address offset: 0x30 */
+__IO uint32_t D3PCR2H; /*!< EXTI D3 Pending clear selection register High, (same register as to SRDPCR2H) Address offset: 0x34 */
+uint32_t RESERVED2[2]; /*!< Reserved, 0x38 to 0x3C */
+__IO uint32_t RTSR3; /*!< EXTI Rising trigger selection register, Address offset: 0x40 */
+__IO uint32_t FTSR3; /*!< EXTI Falling trigger selection register, Address offset: 0x44 */
+__IO uint32_t SWIER3; /*!< EXTI Software interrupt event register, Address offset: 0x48 */
+__IO uint32_t D3PMR3; /*!< EXTI D3 Pending mask register, (same register as to SRDPMR3) Address offset: 0x4C */
+__IO uint32_t D3PCR3L; /*!< EXTI D3 Pending clear selection register low, (same register as to SRDPCR3L) Address offset: 0x50 */
+__IO uint32_t D3PCR3H; /*!< EXTI D3 Pending clear selection register High, (same register as to SRDPCR3H) Address offset: 0x54 */
+uint32_t RESERVED3[10]; /*!< Reserved, 0x58 to 0x7C */
+__IO uint32_t IMR1; /*!< EXTI Interrupt mask register, Address offset: 0x80 */
+__IO uint32_t EMR1; /*!< EXTI Event mask register, Address offset: 0x84 */
+__IO uint32_t PR1; /*!< EXTI Pending register, Address offset: 0x88 */
+uint32_t RESERVED4; /*!< Reserved, 0x8C */
+__IO uint32_t IMR2; /*!< EXTI Interrupt mask register, Address offset: 0x90 */
+__IO uint32_t EMR2; /*!< EXTI Event mask register, Address offset: 0x94 */
+__IO uint32_t PR2; /*!< EXTI Pending register, Address offset: 0x98 */
+uint32_t RESERVED5; /*!< Reserved, 0x9C */
+__IO uint32_t IMR3; /*!< EXTI Interrupt mask register, Address offset: 0xA0 */
+__IO uint32_t EMR3; /*!< EXTI Event mask register, Address offset: 0xA4 */
+__IO uint32_t PR3; /*!< EXTI Pending register, Address offset: 0xA8 */
+}EXTI_TypeDef;
+
+typedef struct
+{
+__IO uint32_t IMR1; /*!< EXTI Interrupt mask register, Address offset: 0x00 */
+__IO uint32_t EMR1; /*!< EXTI Event mask register, Address offset: 0x04 */
+__IO uint32_t PR1; /*!< EXTI Pending register, Address offset: 0x08 */
+uint32_t RESERVED1; /*!< Reserved, 0x0C */
+__IO uint32_t IMR2; /*!< EXTI Interrupt mask register, Address offset: 0x10 */
+__IO uint32_t EMR2; /*!< EXTI Event mask register, Address offset: 0x14 */
+__IO uint32_t PR2; /*!< EXTI Pending register, Address offset: 0x18 */
+uint32_t RESERVED2; /*!< Reserved, 0x1C */
+__IO uint32_t IMR3; /*!< EXTI Interrupt mask register, Address offset: 0x20 */
+__IO uint32_t EMR3; /*!< EXTI Event mask register, Address offset: 0x24 */
+__IO uint32_t PR3; /*!< EXTI Pending register, Address offset: 0x28 */
+}EXTI_Core_TypeDef;
+
+
+/**
+ * @brief FLASH Registers
+ */
+
+typedef struct
+{
+ __IO uint32_t ACR; /*!< FLASH access control register, Address offset: 0x00 */
+ __IO uint32_t KEYR1; /*!< Flash Key Register for bank1, Address offset: 0x04 */
+ __IO uint32_t OPTKEYR; /*!< Flash Option Key Register, Address offset: 0x08 */
+ __IO uint32_t CR1; /*!< Flash Control Register for bank1, Address offset: 0x0C */
+ __IO uint32_t SR1; /*!< Flash Status Register for bank1, Address offset: 0x10 */
+ __IO uint32_t CCR1; /*!< Flash Control Register for bank1, Address offset: 0x14 */
+ __IO uint32_t OPTCR; /*!< Flash Option Control Register, Address offset: 0x18 */
+ __IO uint32_t OPTSR_CUR; /*!< Flash Option Status Current Register, Address offset: 0x1C */
+ __IO uint32_t OPTSR_PRG; /*!< Flash Option Status to Program Register, Address offset: 0x20 */
+ __IO uint32_t OPTCCR; /*!< Flash Option Clear Control Register, Address offset: 0x24 */
+ __IO uint32_t PRAR_CUR1; /*!< Flash Current Protection Address Register for bank1, Address offset: 0x28 */
+ __IO uint32_t PRAR_PRG1; /*!< Flash Protection Address to Program Register for bank1, Address offset: 0x2C */
+ __IO uint32_t SCAR_CUR1; /*!< Flash Current Secure Address Register for bank1, Address offset: 0x30 */
+ __IO uint32_t SCAR_PRG1; /*!< Flash Secure Address to Program Register for bank1, Address offset: 0x34 */
+ __IO uint32_t WPSN_CUR1; /*!< Flash Current Write Protection Register on bank1, Address offset: 0x38 */
+ __IO uint32_t WPSN_PRG1; /*!< Flash Write Protection to Program Register on bank1, Address offset: 0x3C */
+ __IO uint32_t BOOT_CUR; /*!< Flash Current Boot Address for Pelican Core Register, Address offset: 0x40 */
+ __IO uint32_t BOOT_PRG; /*!< Flash Boot Address to Program for Pelican Core Register, Address offset: 0x44 */
+ uint32_t RESERVED0[2]; /*!< Reserved, 0x48 to 0x4C */
+ __IO uint32_t CRCCR1; /*!< Flash CRC Control register For Bank1 Register , Address offset: 0x50 */
+ __IO uint32_t CRCSADD1; /*!< Flash CRC Start Address Register for Bank1 , Address offset: 0x54 */
+ __IO uint32_t CRCEADD1; /*!< Flash CRC End Address Register for Bank1 , Address offset: 0x58 */
+ __IO uint32_t CRCDATA; /*!< Flash CRC Data Register for Bank1 , Address offset: 0x5C */
+ __IO uint32_t ECC_FA1; /*!< Flash ECC Fail Address For Bank1 Register , Address offset: 0x60 */
+ uint32_t RESERVED[3]; /*!< Reserved, 0x64 to 0x6C */
+ __IO uint32_t OPTSR2_CUR; /*!< Flash Option Status Current Register 2, Address offset: 0x70 */
+ __IO uint32_t OPTSR2_PRG; /*!< Flash Option Status to Program Register 2, Address offset: 0x74 */
+} FLASH_TypeDef;
+
+/**
+ * @brief Filter and Mathematical ACcelerator
+ */
+typedef struct
+{
+ __IO uint32_t X1BUFCFG; /*!< FMAC X1 Buffer Configuration register, Address offset: 0x00 */
+ __IO uint32_t X2BUFCFG; /*!< FMAC X2 Buffer Configuration register, Address offset: 0x04 */
+ __IO uint32_t YBUFCFG; /*!< FMAC Y Buffer Configuration register, Address offset: 0x08 */
+ __IO uint32_t PARAM; /*!< FMAC Parameter register, Address offset: 0x0C */
+ __IO uint32_t CR; /*!< FMAC Control register, Address offset: 0x10 */
+ __IO uint32_t SR; /*!< FMAC Status register, Address offset: 0x14 */
+ __IO uint32_t WDATA; /*!< FMAC Write Data register, Address offset: 0x18 */
+ __IO uint32_t RDATA; /*!< FMAC Read Data register, Address offset: 0x1C */
+} FMAC_TypeDef;
+
+/**
+ * @brief Flexible Memory Controller
+ */
+
+typedef struct
+{
+ __IO uint32_t BTCR[8]; /*!< NOR/PSRAM chip-select control register(BCR) and chip-select timing register(BTR), Address offset: 0x00-1C */
+} FMC_Bank1_TypeDef;
+
+/**
+ * @brief Flexible Memory Controller Bank1E
+ */
+
+typedef struct
+{
+ __IO uint32_t BWTR[7]; /*!< NOR/PSRAM write timing registers, Address offset: 0x104-0x11C */
+} FMC_Bank1E_TypeDef;
+
+/**
+ * @brief Flexible Memory Controller Bank2
+ */
+
+typedef struct
+{
+ __IO uint32_t PCR2; /*!< NAND Flash control register 2, Address offset: 0x60 */
+ __IO uint32_t SR2; /*!< NAND Flash FIFO status and interrupt register 2, Address offset: 0x64 */
+ __IO uint32_t PMEM2; /*!< NAND Flash Common memory space timing register 2, Address offset: 0x68 */
+ __IO uint32_t PATT2; /*!< NAND Flash Attribute memory space timing register 2, Address offset: 0x6C */
+ uint32_t RESERVED0; /*!< Reserved, 0x70 */
+ __IO uint32_t ECCR2; /*!< NAND Flash ECC result registers 2, Address offset: 0x74 */
+} FMC_Bank2_TypeDef;
+
+/**
+ * @brief Flexible Memory Controller Bank3
+ */
+
+typedef struct
+{
+ __IO uint32_t PCR; /*!< NAND Flash control register 3, Address offset: 0x80 */
+ __IO uint32_t SR; /*!< NAND Flash FIFO status and interrupt register 3, Address offset: 0x84 */
+ __IO uint32_t PMEM; /*!< NAND Flash Common memory space timing register 3, Address offset: 0x88 */
+ __IO uint32_t PATT; /*!< NAND Flash Attribute memory space timing register 3, Address offset: 0x8C */
+ uint32_t RESERVED; /*!< Reserved, 0x90 */
+ __IO uint32_t ECCR; /*!< NAND Flash ECC result registers 3, Address offset: 0x94 */
+} FMC_Bank3_TypeDef;
+
+/**
+ * @brief Flexible Memory Controller Bank5 and 6
+ */
+
+
+typedef struct
+{
+ __IO uint32_t SDCR[2]; /*!< SDRAM Control registers , Address offset: 0x140-0x144 */
+ __IO uint32_t SDTR[2]; /*!< SDRAM Timing registers , Address offset: 0x148-0x14C */
+ __IO uint32_t SDCMR; /*!< SDRAM Command Mode register, Address offset: 0x150 */
+ __IO uint32_t SDRTR; /*!< SDRAM Refresh Timer register, Address offset: 0x154 */
+ __IO uint32_t SDSR; /*!< SDRAM Status register, Address offset: 0x158 */
+} FMC_Bank5_6_TypeDef;
+
+/**
+ * @brief General Purpose I/O
+ */
+
+typedef struct
+{
+ __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */
+ __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */
+ __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */
+ __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */
+ __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */
+ __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */
+ __IO uint32_t BSRR; /*!< GPIO port bit set/reset, Address offset: 0x18 */
+ __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */
+ __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */
+} GPIO_TypeDef;
+
+/**
+ * @brief Operational Amplifier (OPAMP)
+ */
+
+typedef struct
+{
+ __IO uint32_t CSR; /*!< OPAMP control/status register, Address offset: 0x00 */
+ __IO uint32_t OTR; /*!< OPAMP offset trimming register for normal mode, Address offset: 0x04 */
+ __IO uint32_t HSOTR; /*!< OPAMP offset trimming register for high speed mode, Address offset: 0x08 */
+} OPAMP_TypeDef;
+
+/**
+ * @brief System configuration controller
+ */
+
+typedef struct
+{
+ uint32_t RESERVED1; /*!< Reserved, Address offset: 0x00 */
+ __IO uint32_t PMCR; /*!< SYSCFG peripheral mode configuration register, Address offset: 0x04 */
+ __IO uint32_t EXTICR[4]; /*!< SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14 */
+ __IO uint32_t CFGR; /*!< SYSCFG configuration registers, Address offset: 0x18 */
+ uint32_t RESERVED2; /*!< Reserved, Address offset: 0x1C */
+ __IO uint32_t CCCSR; /*!< SYSCFG compensation cell control/status register, Address offset: 0x20 */
+ __IO uint32_t CCVR; /*!< SYSCFG compensation cell value register, Address offset: 0x24 */
+ __IO uint32_t CCCR; /*!< SYSCFG compensation cell code register, Address offset: 0x28 */
+ uint32_t RESERVED3; /*!< Reserved, Address offset: 0x2C */
+ __IO uint32_t ADC2ALT; /*!< ADC2 internal input alternate connection register, Address offset: 0x30 */
+ uint32_t RESERVED4[60]; /*!< Reserved, 0x34-0x120 */
+ __IO uint32_t PKGR; /*!< SYSCFG package register, Address offset: 0x124 */
+ uint32_t RESERVED5[118]; /*!< Reserved, 0x128-0x2FC */
+ __IO uint32_t UR0; /*!< SYSCFG user register 0, Address offset: 0x300 */
+ __IO uint32_t UR1; /*!< SYSCFG user register 1, Address offset: 0x304 */
+ __IO uint32_t UR2; /*!< SYSCFG user register 2, Address offset: 0x308 */
+ __IO uint32_t UR3; /*!< SYSCFG user register 3, Address offset: 0x30C */
+ __IO uint32_t UR4; /*!< SYSCFG user register 4, Address offset: 0x310 */
+ __IO uint32_t UR5; /*!< SYSCFG user register 5, Address offset: 0x314 */
+ __IO uint32_t UR6; /*!< SYSCFG user register 6, Address offset: 0x318 */
+ __IO uint32_t UR7; /*!< SYSCFG user register 7, Address offset: 0x31C */
+ uint32_t RESERVED6[3]; /*!< Reserved, Address offset: 0x320-0x328 */
+ __IO uint32_t UR11; /*!< SYSCFG user register 11, Address offset: 0x32C */
+ __IO uint32_t UR12; /*!< SYSCFG user register 12, Address offset: 0x330 */
+ __IO uint32_t UR13; /*!< SYSCFG user register 13, Address offset: 0x334 */
+ __IO uint32_t UR14; /*!< SYSCFG user register 14, Address offset: 0x338 */
+ __IO uint32_t UR15; /*!< SYSCFG user register 15, Address offset: 0x33C */
+ __IO uint32_t UR16; /*!< SYSCFG user register 16, Address offset: 0x340 */
+ __IO uint32_t UR17; /*!< SYSCFG user register 17, Address offset: 0x344 */
+ __IO uint32_t UR18; /*!< SYSCFG user register 18, Address offset: 0x348 */
+
+} SYSCFG_TypeDef;
+
+/**
+ * @brief Inter-integrated Circuit Interface
+ */
+
+typedef struct
+{
+ __IO uint32_t CR1; /*!< I2C Control register 1, Address offset: 0x00 */
+ __IO uint32_t CR2; /*!< I2C Control register 2, Address offset: 0x04 */
+ __IO uint32_t OAR1; /*!< I2C Own address 1 register, Address offset: 0x08 */
+ __IO uint32_t OAR2; /*!< I2C Own address 2 register, Address offset: 0x0C */
+ __IO uint32_t TIMINGR; /*!< I2C Timing register, Address offset: 0x10 */
+ __IO uint32_t TIMEOUTR; /*!< I2C Timeout register, Address offset: 0x14 */
+ __IO uint32_t ISR; /*!< I2C Interrupt and status register, Address offset: 0x18 */
+ __IO uint32_t ICR; /*!< I2C Interrupt clear register, Address offset: 0x1C */
+ __IO uint32_t PECR; /*!< I2C PEC register, Address offset: 0x20 */
+ __IO uint32_t RXDR; /*!< I2C Receive data register, Address offset: 0x24 */
+ __IO uint32_t TXDR; /*!< I2C Transmit data register, Address offset: 0x28 */
+} I2C_TypeDef;
+
+/**
+ * @brief Independent WATCHDOG
+ */
+
+typedef struct
+{
+ __IO uint32_t KR; /*!< IWDG Key register, Address offset: 0x00 */
+ __IO uint32_t PR; /*!< IWDG Prescaler register, Address offset: 0x04 */
+ __IO uint32_t RLR; /*!< IWDG Reload register, Address offset: 0x08 */
+ __IO uint32_t SR; /*!< IWDG Status register, Address offset: 0x0C */
+ __IO uint32_t WINR; /*!< IWDG Window register, Address offset: 0x10 */
+} IWDG_TypeDef;
+
+
+/**
+ * @brief LCD-TFT Display Controller
+ */
+
+typedef struct
+{
+ uint32_t RESERVED0[2]; /*!< Reserved, 0x00-0x04 */
+ __IO uint32_t SSCR; /*!< LTDC Synchronization Size Configuration Register, Address offset: 0x08 */
+ __IO uint32_t BPCR; /*!< LTDC Back Porch Configuration Register, Address offset: 0x0C */
+ __IO uint32_t AWCR; /*!< LTDC Active Width Configuration Register, Address offset: 0x10 */
+ __IO uint32_t TWCR; /*!< LTDC Total Width Configuration Register, Address offset: 0x14 */
+ __IO uint32_t GCR; /*!< LTDC Global Control Register, Address offset: 0x18 */
+ uint32_t RESERVED1[2]; /*!< Reserved, 0x1C-0x20 */
+ __IO uint32_t SRCR; /*!< LTDC Shadow Reload Configuration Register, Address offset: 0x24 */
+ uint32_t RESERVED2[1]; /*!< Reserved, 0x28 */
+ __IO uint32_t BCCR; /*!< LTDC Background Color Configuration Register, Address offset: 0x2C */
+ uint32_t RESERVED3[1]; /*!< Reserved, 0x30 */
+ __IO uint32_t IER; /*!< LTDC Interrupt Enable Register, Address offset: 0x34 */
+ __IO uint32_t ISR; /*!< LTDC Interrupt Status Register, Address offset: 0x38 */
+ __IO uint32_t ICR; /*!< LTDC Interrupt Clear Register, Address offset: 0x3C */
+ __IO uint32_t LIPCR; /*!< LTDC Line Interrupt Position Configuration Register, Address offset: 0x40 */
+ __IO uint32_t CPSR; /*!< LTDC Current Position Status Register, Address offset: 0x44 */
+ __IO uint32_t CDSR; /*!< LTDC Current Display Status Register, Address offset: 0x48 */
+} LTDC_TypeDef;
+
+/**
+ * @brief LCD-TFT Display layer x Controller
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< LTDC Layerx Control Register Address offset: 0x84 */
+ __IO uint32_t WHPCR; /*!< LTDC Layerx Window Horizontal Position Configuration Register Address offset: 0x88 */
+ __IO uint32_t WVPCR; /*!< LTDC Layerx Window Vertical Position Configuration Register Address offset: 0x8C */
+ __IO uint32_t CKCR; /*!< LTDC Layerx Color Keying Configuration Register Address offset: 0x90 */
+ __IO uint32_t PFCR; /*!< LTDC Layerx Pixel Format Configuration Register Address offset: 0x94 */
+ __IO uint32_t CACR; /*!< LTDC Layerx Constant Alpha Configuration Register Address offset: 0x98 */
+ __IO uint32_t DCCR; /*!< LTDC Layerx Default Color Configuration Register Address offset: 0x9C */
+ __IO uint32_t BFCR; /*!< LTDC Layerx Blending Factors Configuration Register Address offset: 0xA0 */
+ uint32_t RESERVED0[2]; /*!< Reserved */
+ __IO uint32_t CFBAR; /*!< LTDC Layerx Color Frame Buffer Address Register Address offset: 0xAC */
+ __IO uint32_t CFBLR; /*!< LTDC Layerx Color Frame Buffer Length Register Address offset: 0xB0 */
+ __IO uint32_t CFBLNR; /*!< LTDC Layerx ColorFrame Buffer Line Number Register Address offset: 0xB4 */
+ uint32_t RESERVED1[3]; /*!< Reserved */
+ __IO uint32_t CLUTWR; /*!< LTDC Layerx CLUT Write Register Address offset: 0x144 */
+
+} LTDC_Layer_TypeDef;
+
+/**
+ * @brief Power Control
+ */
+
+typedef struct
+{
+ __IO uint32_t CR1; /*!< PWR power control register 1, Address offset: 0x00 */
+ __IO uint32_t CSR1; /*!< PWR power control status register 1, Address offset: 0x04 */
+ __IO uint32_t CR2; /*!< PWR power control register 2, Address offset: 0x08 */
+ __IO uint32_t CR3; /*!< PWR power control register 3, Address offset: 0x0C */
+ __IO uint32_t CPUCR; /*!< PWR CPU control register, Address offset: 0x10 */
+ uint32_t RESERVED0; /*!< Reserved, Address offset: 0x14 */
+ __IO uint32_t D3CR; /*!< PWR D3 domain control register, Address offset: 0x18 */
+ uint32_t RESERVED1; /*!< Reserved, Address offset: 0x1C */
+ __IO uint32_t WKUPCR; /*!< PWR wakeup clear register, Address offset: 0x20 */
+ __IO uint32_t WKUPFR; /*!< PWR wakeup flag register, Address offset: 0x24 */
+ __IO uint32_t WKUPEPR; /*!< PWR wakeup enable and polarity register, Address offset: 0x28 */
+} PWR_TypeDef;
+
+/**
+ * @brief Reset and Clock Control
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< RCC clock control register, Address offset: 0x00 */
+ __IO uint32_t HSICFGR; /*!< HSI Clock Calibration Register, Address offset: 0x04 */
+ __IO uint32_t CRRCR; /*!< Clock Recovery RC Register, Address offset: 0x08 */
+ __IO uint32_t CSICFGR; /*!< CSI Clock Calibration Register, Address offset: 0x0C */
+ __IO uint32_t CFGR; /*!< RCC clock configuration register, Address offset: 0x10 */
+ uint32_t RESERVED1; /*!< Reserved, Address offset: 0x14 */
+ __IO uint32_t D1CFGR; /*!< RCC Domain 1 configuration register, Address offset: 0x18 */
+ __IO uint32_t D2CFGR; /*!< RCC Domain 2 configuration register, Address offset: 0x1C */
+ __IO uint32_t D3CFGR; /*!< RCC Domain 3 configuration register, Address offset: 0x20 */
+ uint32_t RESERVED2; /*!< Reserved, Address offset: 0x24 */
+ __IO uint32_t PLLCKSELR; /*!< RCC PLLs Clock Source Selection Register, Address offset: 0x28 */
+ __IO uint32_t PLLCFGR; /*!< RCC PLLs Configuration Register, Address offset: 0x2C */
+ __IO uint32_t PLL1DIVR; /*!< RCC PLL1 Dividers Configuration Register, Address offset: 0x30 */
+ __IO uint32_t PLL1FRACR; /*!< RCC PLL1 Fractional Divider Configuration Register, Address offset: 0x34 */
+ __IO uint32_t PLL2DIVR; /*!< RCC PLL2 Dividers Configuration Register, Address offset: 0x38 */
+ __IO uint32_t PLL2FRACR; /*!< RCC PLL2 Fractional Divider Configuration Register, Address offset: 0x3C */
+ __IO uint32_t PLL3DIVR; /*!< RCC PLL3 Dividers Configuration Register, Address offset: 0x40 */
+ __IO uint32_t PLL3FRACR; /*!< RCC PLL3 Fractional Divider Configuration Register, Address offset: 0x44 */
+ uint32_t RESERVED3; /*!< Reserved, Address offset: 0x48 */
+ __IO uint32_t D1CCIPR; /*!< RCC Domain 1 Kernel Clock Configuration Register Address offset: 0x4C */
+ __IO uint32_t D2CCIP1R; /*!< RCC Domain 2 Kernel Clock Configuration Register Address offset: 0x50 */
+ __IO uint32_t D2CCIP2R; /*!< RCC Domain 2 Kernel Clock Configuration Register Address offset: 0x54 */
+ __IO uint32_t D3CCIPR; /*!< RCC Domain 3 Kernel Clock Configuration Register Address offset: 0x58 */
+ uint32_t RESERVED4; /*!< Reserved, Address offset: 0x5C */
+ __IO uint32_t CIER; /*!< RCC Clock Source Interrupt Enable Register Address offset: 0x60 */
+ __IO uint32_t CIFR; /*!< RCC Clock Source Interrupt Flag Register Address offset: 0x64 */
+ __IO uint32_t CICR; /*!< RCC Clock Source Interrupt Clear Register Address offset: 0x68 */
+ uint32_t RESERVED5; /*!< Reserved, Address offset: 0x6C */
+ __IO uint32_t BDCR; /*!< RCC Vswitch Backup Domain Control Register, Address offset: 0x70 */
+ __IO uint32_t CSR; /*!< RCC clock control & status register, Address offset: 0x74 */
+ uint32_t RESERVED6; /*!< Reserved, Address offset: 0x78 */
+ __IO uint32_t AHB3RSTR; /*!< RCC AHB3 peripheral reset register, Address offset: 0x7C */
+ __IO uint32_t AHB1RSTR; /*!< RCC AHB1 peripheral reset register, Address offset: 0x80 */
+ __IO uint32_t AHB2RSTR; /*!< RCC AHB2 peripheral reset register, Address offset: 0x84 */
+ __IO uint32_t AHB4RSTR; /*!< RCC AHB4 peripheral reset register, Address offset: 0x88 */
+ __IO uint32_t APB3RSTR; /*!< RCC APB3 peripheral reset register, Address offset: 0x8C */
+ __IO uint32_t APB1LRSTR; /*!< RCC APB1 peripheral reset Low Word register, Address offset: 0x90 */
+ __IO uint32_t APB1HRSTR; /*!< RCC APB1 peripheral reset High Word register, Address offset: 0x94 */
+ __IO uint32_t APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x98 */
+ __IO uint32_t APB4RSTR; /*!< RCC APB4 peripheral reset register, Address offset: 0x9C */
+ __IO uint32_t GCR; /*!< RCC RCC Global Control Register, Address offset: 0xA0 */
+ uint32_t RESERVED8; /*!< Reserved, Address offset: 0xA4 */
+ __IO uint32_t D3AMR; /*!< RCC Domain 3 Autonomous Mode Register, Address offset: 0xA8 */
+ uint32_t RESERVED11[9]; /*!< Reserved, 0xAC-0xCC Address offset: 0xAC */
+ __IO uint32_t RSR; /*!< RCC Reset status register, Address offset: 0xD0 */
+ __IO uint32_t AHB3ENR; /*!< RCC AHB3 peripheral clock register, Address offset: 0xD4 */
+ __IO uint32_t AHB1ENR; /*!< RCC AHB1 peripheral clock register, Address offset: 0xD8 */
+ __IO uint32_t AHB2ENR; /*!< RCC AHB2 peripheral clock register, Address offset: 0xDC */
+ __IO uint32_t AHB4ENR; /*!< RCC AHB4 peripheral clock register, Address offset: 0xE0 */
+ __IO uint32_t APB3ENR; /*!< RCC APB3 peripheral clock register, Address offset: 0xE4 */
+ __IO uint32_t APB1LENR; /*!< RCC APB1 peripheral clock Low Word register, Address offset: 0xE8 */
+ __IO uint32_t APB1HENR; /*!< RCC APB1 peripheral clock High Word register, Address offset: 0xEC */
+ __IO uint32_t APB2ENR; /*!< RCC APB2 peripheral clock register, Address offset: 0xF0 */
+ __IO uint32_t APB4ENR; /*!< RCC APB4 peripheral clock register, Address offset: 0xF4 */
+ uint32_t RESERVED12; /*!< Reserved, Address offset: 0xF8 */
+ __IO uint32_t AHB3LPENR; /*!< RCC AHB3 peripheral sleep clock register, Address offset: 0xFC */
+ __IO uint32_t AHB1LPENR; /*!< RCC AHB1 peripheral sleep clock register, Address offset: 0x100 */
+ __IO uint32_t AHB2LPENR; /*!< RCC AHB2 peripheral sleep clock register, Address offset: 0x104 */
+ __IO uint32_t AHB4LPENR; /*!< RCC AHB4 peripheral sleep clock register, Address offset: 0x108 */
+ __IO uint32_t APB3LPENR; /*!< RCC APB3 peripheral sleep clock register, Address offset: 0x10C */
+ __IO uint32_t APB1LLPENR; /*!< RCC APB1 peripheral sleep clock Low Word register, Address offset: 0x110 */
+ __IO uint32_t APB1HLPENR; /*!< RCC APB1 peripheral sleep clock High Word register, Address offset: 0x114 */
+ __IO uint32_t APB2LPENR; /*!< RCC APB2 peripheral sleep clock register, Address offset: 0x118 */
+ __IO uint32_t APB4LPENR; /*!< RCC APB4 peripheral sleep clock register, Address offset: 0x11C */
+ uint32_t RESERVED13[4]; /*!< Reserved, 0x120-0x12C Address offset: 0x120 */
+
+} RCC_TypeDef;
+
+
+/**
+ * @brief Real-Time Clock
+ */
+typedef struct
+{
+ __IO uint32_t TR; /*!< RTC time register, Address offset: 0x00 */
+ __IO uint32_t DR; /*!< RTC date register, Address offset: 0x04 */
+ __IO uint32_t CR; /*!< RTC control register, Address offset: 0x08 */
+ __IO uint32_t ISR; /*!< RTC initialization and status register, Address offset: 0x0C */
+ __IO uint32_t PRER; /*!< RTC prescaler register, Address offset: 0x10 */
+ __IO uint32_t WUTR; /*!< RTC wakeup timer register, Address offset: 0x14 */
+ uint32_t RESERVED; /*!< Reserved, Address offset: 0x18 */
+ __IO uint32_t ALRMAR; /*!< RTC alarm A register, Address offset: 0x1C */
+ __IO uint32_t ALRMBR; /*!< RTC alarm B register, Address offset: 0x20 */
+ __IO uint32_t WPR; /*!< RTC write protection register, Address offset: 0x24 */
+ __IO uint32_t SSR; /*!< RTC sub second register, Address offset: 0x28 */
+ __IO uint32_t SHIFTR; /*!< RTC shift control register, Address offset: 0x2C */
+ __IO uint32_t TSTR; /*!< RTC time stamp time register, Address offset: 0x30 */
+ __IO uint32_t TSDR; /*!< RTC time stamp date register, Address offset: 0x34 */
+ __IO uint32_t TSSSR; /*!< RTC time-stamp sub second register, Address offset: 0x38 */
+ __IO uint32_t CALR; /*!< RTC calibration register, Address offset: 0x3C */
+ __IO uint32_t TAMPCR; /*!< RTC tamper configuration register, Address offset: 0x40 */
+ __IO uint32_t ALRMASSR; /*!< RTC alarm A sub second register, Address offset: 0x44 */
+ __IO uint32_t ALRMBSSR; /*!< RTC alarm B sub second register, Address offset: 0x48 */
+ __IO uint32_t OR; /*!< RTC option register, Address offset: 0x4C */
+ __IO uint32_t BKP0R; /*!< RTC backup register 0, Address offset: 0x50 */
+ __IO uint32_t BKP1R; /*!< RTC backup register 1, Address offset: 0x54 */
+ __IO uint32_t BKP2R; /*!< RTC backup register 2, Address offset: 0x58 */
+ __IO uint32_t BKP3R; /*!< RTC backup register 3, Address offset: 0x5C */
+ __IO uint32_t BKP4R; /*!< RTC backup register 4, Address offset: 0x60 */
+ __IO uint32_t BKP5R; /*!< RTC backup register 5, Address offset: 0x64 */
+ __IO uint32_t BKP6R; /*!< RTC backup register 6, Address offset: 0x68 */
+ __IO uint32_t BKP7R; /*!< RTC backup register 7, Address offset: 0x6C */
+ __IO uint32_t BKP8R; /*!< RTC backup register 8, Address offset: 0x70 */
+ __IO uint32_t BKP9R; /*!< RTC backup register 9, Address offset: 0x74 */
+ __IO uint32_t BKP10R; /*!< RTC backup register 10, Address offset: 0x78 */
+ __IO uint32_t BKP11R; /*!< RTC backup register 11, Address offset: 0x7C */
+ __IO uint32_t BKP12R; /*!< RTC backup register 12, Address offset: 0x80 */
+ __IO uint32_t BKP13R; /*!< RTC backup register 13, Address offset: 0x84 */
+ __IO uint32_t BKP14R; /*!< RTC backup register 14, Address offset: 0x88 */
+ __IO uint32_t BKP15R; /*!< RTC backup register 15, Address offset: 0x8C */
+ __IO uint32_t BKP16R; /*!< RTC backup register 16, Address offset: 0x90 */
+ __IO uint32_t BKP17R; /*!< RTC backup register 17, Address offset: 0x94 */
+ __IO uint32_t BKP18R; /*!< RTC backup register 18, Address offset: 0x98 */
+ __IO uint32_t BKP19R; /*!< RTC backup register 19, Address offset: 0x9C */
+ __IO uint32_t BKP20R; /*!< RTC backup register 20, Address offset: 0xA0 */
+ __IO uint32_t BKP21R; /*!< RTC backup register 21, Address offset: 0xA4 */
+ __IO uint32_t BKP22R; /*!< RTC backup register 22, Address offset: 0xA8 */
+ __IO uint32_t BKP23R; /*!< RTC backup register 23, Address offset: 0xAC */
+ __IO uint32_t BKP24R; /*!< RTC backup register 24, Address offset: 0xB0 */
+ __IO uint32_t BKP25R; /*!< RTC backup register 25, Address offset: 0xB4 */
+ __IO uint32_t BKP26R; /*!< RTC backup register 26, Address offset: 0xB8 */
+ __IO uint32_t BKP27R; /*!< RTC backup register 27, Address offset: 0xBC */
+ __IO uint32_t BKP28R; /*!< RTC backup register 28, Address offset: 0xC0 */
+ __IO uint32_t BKP29R; /*!< RTC backup register 29, Address offset: 0xC4 */
+ __IO uint32_t BKP30R; /*!< RTC backup register 30, Address offset: 0xC8 */
+ __IO uint32_t BKP31R; /*!< RTC backup register 31, Address offset: 0xCC */
+} RTC_TypeDef;
+
+/**
+ * @brief Serial Audio Interface
+ */
+
+typedef struct
+{
+ __IO uint32_t GCR; /*!< SAI global configuration register, Address offset: 0x00 */
+ uint32_t RESERVED0[16]; /*!< Reserved, 0x04 - 0x43 */
+ __IO uint32_t PDMCR; /*!< SAI PDM control register, Address offset: 0x44 */
+ __IO uint32_t PDMDLY; /*!< SAI PDM delay register, Address offset: 0x48 */
+} SAI_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t CR1; /*!< SAI block x configuration register 1, Address offset: 0x04 */
+ __IO uint32_t CR2; /*!< SAI block x configuration register 2, Address offset: 0x08 */
+ __IO uint32_t FRCR; /*!< SAI block x frame configuration register, Address offset: 0x0C */
+ __IO uint32_t SLOTR; /*!< SAI block x slot register, Address offset: 0x10 */
+ __IO uint32_t IMR; /*!< SAI block x interrupt mask register, Address offset: 0x14 */
+ __IO uint32_t SR; /*!< SAI block x status register, Address offset: 0x18 */
+ __IO uint32_t CLRFR; /*!< SAI block x clear flag register, Address offset: 0x1C */
+ __IO uint32_t DR; /*!< SAI block x data register, Address offset: 0x20 */
+} SAI_Block_TypeDef;
+
+/**
+ * @brief SPDIF-RX Interface
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< Control register, Address offset: 0x00 */
+ __IO uint32_t IMR; /*!< Interrupt mask register, Address offset: 0x04 */
+ __IO uint32_t SR; /*!< Status register, Address offset: 0x08 */
+ __IO uint32_t IFCR; /*!< Interrupt Flag Clear register, Address offset: 0x0C */
+ __IO uint32_t DR; /*!< Data input register, Address offset: 0x10 */
+ __IO uint32_t CSR; /*!< Channel Status register, Address offset: 0x14 */
+ __IO uint32_t DIR; /*!< Debug Information register, Address offset: 0x18 */
+ uint32_t RESERVED2; /*!< Reserved, 0x1A */
+} SPDIFRX_TypeDef;
+
+
+/**
+ * @brief Secure digital input/output Interface
+ */
+
+typedef struct
+{
+ __IO uint32_t POWER; /*!< SDMMC power control register, Address offset: 0x00 */
+ __IO uint32_t CLKCR; /*!< SDMMC clock control register, Address offset: 0x04 */
+ __IO uint32_t ARG; /*!< SDMMC argument register, Address offset: 0x08 */
+ __IO uint32_t CMD; /*!< SDMMC command register, Address offset: 0x0C */
+ __I uint32_t RESPCMD; /*!< SDMMC command response register, Address offset: 0x10 */
+ __I uint32_t RESP1; /*!< SDMMC response 1 register, Address offset: 0x14 */
+ __I uint32_t RESP2; /*!< SDMMC response 2 register, Address offset: 0x18 */
+ __I uint32_t RESP3; /*!< SDMMC response 3 register, Address offset: 0x1C */
+ __I uint32_t RESP4; /*!< SDMMC response 4 register, Address offset: 0x20 */
+ __IO uint32_t DTIMER; /*!< SDMMC data timer register, Address offset: 0x24 */
+ __IO uint32_t DLEN; /*!< SDMMC data length register, Address offset: 0x28 */
+ __IO uint32_t DCTRL; /*!< SDMMC data control register, Address offset: 0x2C */
+ __I uint32_t DCOUNT; /*!< SDMMC data counter register, Address offset: 0x30 */
+ __I uint32_t STA; /*!< SDMMC status register, Address offset: 0x34 */
+ __IO uint32_t ICR; /*!< SDMMC interrupt clear register, Address offset: 0x38 */
+ __IO uint32_t MASK; /*!< SDMMC mask register, Address offset: 0x3C */
+ __IO uint32_t ACKTIME; /*!< SDMMC Acknowledgement timer register, Address offset: 0x40 */
+ uint32_t RESERVED0[3]; /*!< Reserved, 0x44 - 0x4C - 0x4C */
+ __IO uint32_t IDMACTRL; /*!< SDMMC DMA control register, Address offset: 0x50 */
+ __IO uint32_t IDMABSIZE; /*!< SDMMC DMA buffer size register, Address offset: 0x54 */
+ __IO uint32_t IDMABASE0; /*!< SDMMC DMA buffer 0 base address register, Address offset: 0x58 */
+ __IO uint32_t IDMABASE1; /*!< SDMMC DMA buffer 1 base address register, Address offset: 0x5C */
+ uint32_t RESERVED1[8]; /*!< Reserved, 0x60-0x7C */
+ __IO uint32_t FIFO; /*!< SDMMC data FIFO register, Address offset: 0x80 */
+ uint32_t RESERVED2[222]; /*!< Reserved, 0x84-0x3F8 */
+ __IO uint32_t IPVR; /*!< SDMMC data FIFO register, Address offset: 0x3FC */
+} SDMMC_TypeDef;
+
+
+/**
+ * @brief Delay Block DLYB
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< DELAY BLOCK control register, Address offset: 0x00 */
+ __IO uint32_t CFGR; /*!< DELAY BLOCK configuration register, Address offset: 0x04 */
+} DLYB_TypeDef;
+
+/**
+ * @brief HW Semaphore HSEM
+ */
+
+typedef struct
+{
+ __IO uint32_t R[32]; /*!< 2-step write lock and read back registers, Address offset: 00h-7Ch */
+ __IO uint32_t RLR[32]; /*!< 1-step read lock registers, Address offset: 80h-FCh */
+ __IO uint32_t C1IER; /*!< HSEM Interrupt enable register , Address offset: 100h */
+ __IO uint32_t C1ICR; /*!< HSEM Interrupt clear register , Address offset: 104h */
+ __IO uint32_t C1ISR; /*!< HSEM Interrupt Status register , Address offset: 108h */
+ __IO uint32_t C1MISR; /*!< HSEM Interrupt Masked Status register , Address offset: 10Ch */
+ uint32_t Reserved[12]; /* Reserved Address offset: 110h-13Ch */
+ __IO uint32_t CR; /*!< HSEM Semaphore clear register , Address offset: 140h */
+ __IO uint32_t KEYR; /*!< HSEM Semaphore clear key register , Address offset: 144h */
+
+} HSEM_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t IER; /*!< HSEM interrupt enable register , Address offset: 0h */
+ __IO uint32_t ICR; /*!< HSEM interrupt clear register , Address offset: 4h */
+ __IO uint32_t ISR; /*!< HSEM interrupt status register , Address offset: 8h */
+ __IO uint32_t MISR; /*!< HSEM masked interrupt status register , Address offset: Ch */
+} HSEM_Common_TypeDef;
+
+/**
+ * @brief Serial Peripheral Interface
+ */
+
+typedef struct
+{
+ __IO uint32_t CR1; /*!< SPI/I2S Control register 1, Address offset: 0x00 */
+ __IO uint32_t CR2; /*!< SPI Control register 2, Address offset: 0x04 */
+ __IO uint32_t CFG1; /*!< SPI Configuration register 1, Address offset: 0x08 */
+ __IO uint32_t CFG2; /*!< SPI Configuration register 2, Address offset: 0x0C */
+ __IO uint32_t IER; /*!< SPI/I2S Interrupt Enable register, Address offset: 0x10 */
+ __IO uint32_t SR; /*!< SPI/I2S Status register, Address offset: 0x14 */
+ __IO uint32_t IFCR; /*!< SPI/I2S Interrupt/Status flags clear register, Address offset: 0x18 */
+ uint32_t RESERVED0; /*!< Reserved, 0x1C */
+ __IO uint32_t TXDR; /*!< SPI/I2S Transmit data register, Address offset: 0x20 */
+ uint32_t RESERVED1[3]; /*!< Reserved, 0x24-0x2C */
+ __IO uint32_t RXDR; /*!< SPI/I2S Receive data register, Address offset: 0x30 */
+ uint32_t RESERVED2[3]; /*!< Reserved, 0x34-0x3C */
+ __IO uint32_t CRCPOLY; /*!< SPI CRC Polynomial register, Address offset: 0x40 */
+ __IO uint32_t TXCRC; /*!< SPI Transmitter CRC register, Address offset: 0x44 */
+ __IO uint32_t RXCRC; /*!< SPI Receiver CRC register, Address offset: 0x48 */
+ __IO uint32_t UDRDR; /*!< SPI Underrun data register, Address offset: 0x4C */
+ __IO uint32_t I2SCFGR; /*!< I2S Configuration register, Address offset: 0x50 */
+
+} SPI_TypeDef;
+
+/**
+ * @brief DTS
+ */
+typedef struct
+{
+ __IO uint32_t CFGR1; /*!< DTS configuration register, Address offset: 0x00 */
+ uint32_t RESERVED0; /*!< Reserved, Address offset: 0x04 */
+ __IO uint32_t T0VALR1; /*!< DTS T0 Value register, Address offset: 0x08 */
+ uint32_t RESERVED1; /*!< Reserved, Address offset: 0x0C */
+ __IO uint32_t RAMPVALR; /*!< DTS Ramp value register, Address offset: 0x10 */
+ __IO uint32_t ITR1; /*!< DTS Interrupt threshold register, Address offset: 0x14 */
+ uint32_t RESERVED2; /*!< Reserved, Address offset: 0x18 */
+ __IO uint32_t DR; /*!< DTS data register, Address offset: 0x1C */
+ __IO uint32_t SR; /*!< DTS status register Address offset: 0x20 */
+ __IO uint32_t ITENR; /*!< DTS Interrupt enable register, Address offset: 0x24 */
+ __IO uint32_t ICIFR; /*!< DTS Clear Interrupt flag register, Address offset: 0x28 */
+ __IO uint32_t OR; /*!< DTS option register 1, Address offset: 0x2C */
+}
+DTS_TypeDef;
+
+/**
+ * @brief TIM
+ */
+
+typedef struct
+{
+ __IO uint32_t CR1; /*!< TIM control register 1, Address offset: 0x00 */
+ __IO uint32_t CR2; /*!< TIM control register 2, Address offset: 0x04 */
+ __IO uint32_t SMCR; /*!< TIM slave mode control register, Address offset: 0x08 */
+ __IO uint32_t DIER; /*!< TIM DMA/interrupt enable register, Address offset: 0x0C */
+ __IO uint32_t SR; /*!< TIM status register, Address offset: 0x10 */
+ __IO uint32_t EGR; /*!< TIM event generation register, Address offset: 0x14 */
+ __IO uint32_t CCMR1; /*!< TIM capture/compare mode register 1, Address offset: 0x18 */
+ __IO uint32_t CCMR2; /*!< TIM capture/compare mode register 2, Address offset: 0x1C */
+ __IO uint32_t CCER; /*!< TIM capture/compare enable register, Address offset: 0x20 */
+ __IO uint32_t CNT; /*!< TIM counter register, Address offset: 0x24 */
+ __IO uint32_t PSC; /*!< TIM prescaler, Address offset: 0x28 */
+ __IO uint32_t ARR; /*!< TIM auto-reload register, Address offset: 0x2C */
+ __IO uint32_t RCR; /*!< TIM repetition counter register, Address offset: 0x30 */
+ __IO uint32_t CCR1; /*!< TIM capture/compare register 1, Address offset: 0x34 */
+ __IO uint32_t CCR2; /*!< TIM capture/compare register 2, Address offset: 0x38 */
+ __IO uint32_t CCR3; /*!< TIM capture/compare register 3, Address offset: 0x3C */
+ __IO uint32_t CCR4; /*!< TIM capture/compare register 4, Address offset: 0x40 */
+ __IO uint32_t BDTR; /*!< TIM break and dead-time register, Address offset: 0x44 */
+ __IO uint32_t DCR; /*!< TIM DMA control register, Address offset: 0x48 */
+ __IO uint32_t DMAR; /*!< TIM DMA address for full transfer, Address offset: 0x4C */
+ uint32_t RESERVED1; /*!< Reserved, 0x50 */
+ __IO uint32_t CCMR3; /*!< TIM capture/compare mode register 3, Address offset: 0x54 */
+ __IO uint32_t CCR5; /*!< TIM capture/compare register5, Address offset: 0x58 */
+ __IO uint32_t CCR6; /*!< TIM capture/compare register6, Address offset: 0x5C */
+ __IO uint32_t AF1; /*!< TIM alternate function option register 1, Address offset: 0x60 */
+ __IO uint32_t AF2; /*!< TIM alternate function option register 2, Address offset: 0x64 */
+ __IO uint32_t TISEL; /*!< TIM Input Selection register, Address offset: 0x68 */
+} TIM_TypeDef;
+
+/**
+ * @brief LPTIMIMER
+ */
+typedef struct
+{
+ __IO uint32_t ISR; /*!< LPTIM Interrupt and Status register, Address offset: 0x00 */
+ __IO uint32_t ICR; /*!< LPTIM Interrupt Clear register, Address offset: 0x04 */
+ __IO uint32_t IER; /*!< LPTIM Interrupt Enable register, Address offset: 0x08 */
+ __IO uint32_t CFGR; /*!< LPTIM Configuration register, Address offset: 0x0C */
+ __IO uint32_t CR; /*!< LPTIM Control register, Address offset: 0x10 */
+ __IO uint32_t CMP; /*!< LPTIM Compare register, Address offset: 0x14 */
+ __IO uint32_t ARR; /*!< LPTIM Autoreload register, Address offset: 0x18 */
+ __IO uint32_t CNT; /*!< LPTIM Counter register, Address offset: 0x1C */
+ uint32_t RESERVED1; /*!< Reserved, 0x20 */
+ __IO uint32_t CFGR2; /*!< LPTIM Configuration register, Address offset: 0x24 */
+} LPTIM_TypeDef;
+
+/**
+ * @brief Comparator
+ */
+typedef struct
+{
+ __IO uint32_t SR; /*!< Comparator status register, Address offset: 0x00 */
+ __IO uint32_t ICFR; /*!< Comparator interrupt clear flag register, Address offset: 0x04 */
+ __IO uint32_t OR; /*!< Comparator option register, Address offset: 0x08 */
+} COMPOPT_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t CFGR; /*!< Comparator configuration register , Address offset: 0x00 */
+} COMP_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t CFGR; /*!< COMP control and status register, used for bits common to several COMP instances, Address offset: 0x00 */
+} COMP_Common_TypeDef;
+/**
+ * @brief Universal Synchronous Asynchronous Receiver Transmitter
+ */
+
+typedef struct
+{
+ __IO uint32_t CR1; /*!< USART Control register 1, Address offset: 0x00 */
+ __IO uint32_t CR2; /*!< USART Control register 2, Address offset: 0x04 */
+ __IO uint32_t CR3; /*!< USART Control register 3, Address offset: 0x08 */
+ __IO uint32_t BRR; /*!< USART Baud rate register, Address offset: 0x0C */
+ __IO uint32_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x10 */
+ __IO uint32_t RTOR; /*!< USART Receiver Time Out register, Address offset: 0x14 */
+ __IO uint32_t RQR; /*!< USART Request register, Address offset: 0x18 */
+ __IO uint32_t ISR; /*!< USART Interrupt and status register, Address offset: 0x1C */
+ __IO uint32_t ICR; /*!< USART Interrupt flag Clear register, Address offset: 0x20 */
+ __IO uint32_t RDR; /*!< USART Receive Data register, Address offset: 0x24 */
+ __IO uint32_t TDR; /*!< USART Transmit Data register, Address offset: 0x28 */
+ __IO uint32_t PRESC; /*!< USART clock Prescaler register, Address offset: 0x2C */
+} USART_TypeDef;
+
+/**
+ * @brief Single Wire Protocol Master Interface SPWMI
+ */
+typedef struct
+{
+ __IO uint32_t CR; /*!< SWPMI Configuration/Control register, Address offset: 0x00 */
+ __IO uint32_t BRR; /*!< SWPMI bitrate register, Address offset: 0x04 */
+ uint32_t RESERVED1; /*!< Reserved, 0x08 */
+ __IO uint32_t ISR; /*!< SWPMI Interrupt and Status register, Address offset: 0x0C */
+ __IO uint32_t ICR; /*!< SWPMI Interrupt Flag Clear register, Address offset: 0x10 */
+ __IO uint32_t IER; /*!< SWPMI Interrupt Enable register, Address offset: 0x14 */
+ __IO uint32_t RFL; /*!< SWPMI Receive Frame Length register, Address offset: 0x18 */
+ __IO uint32_t TDR; /*!< SWPMI Transmit data register, Address offset: 0x1C */
+ __IO uint32_t RDR; /*!< SWPMI Receive data register, Address offset: 0x20 */
+ __IO uint32_t OR; /*!< SWPMI Option register, Address offset: 0x24 */
+} SWPMI_TypeDef;
+
+/**
+ * @brief Window WATCHDOG
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< WWDG Control register, Address offset: 0x00 */
+ __IO uint32_t CFR; /*!< WWDG Configuration register, Address offset: 0x04 */
+ __IO uint32_t SR; /*!< WWDG Status register, Address offset: 0x08 */
+} WWDG_TypeDef;
+
+
+/**
+ * @brief RAM_ECC_Specific_Registers
+ */
+typedef struct
+{
+ __IO uint32_t CR; /*!< RAMECC monitor configuration register */
+ __IO uint32_t SR; /*!< RAMECC monitor status register */
+ __IO uint32_t FAR; /*!< RAMECC monitor failing address register */
+ __IO uint32_t FDRL; /*!< RAMECC monitor failing data low register */
+ __IO uint32_t FDRH; /*!< RAMECC monitor failing data high register */
+ __IO uint32_t FECR; /*!< RAMECC monitor failing ECC error code register */
+} RAMECC_MonitorTypeDef;
+
+typedef struct
+{
+ __IO uint32_t IER; /*!< RAMECC interrupt enable register */
+} RAMECC_TypeDef;
+/**
+ * @}
+ */
+
+
+
+/**
+ * @brief RNG
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< RNG control register, Address offset: 0x00 */
+ __IO uint32_t SR; /*!< RNG status register, Address offset: 0x04 */
+ __IO uint32_t DR; /*!< RNG data register, Address offset: 0x08 */
+ uint32_t RESERVED;
+ __IO uint32_t HTCR; /*!< RNG health test configuration register, Address offset: 0x10 */
+} RNG_TypeDef;
+
+/**
+ * @brief MDIOS
+ */
+
+typedef struct
+{
+ __IO uint32_t CR;
+ __IO uint32_t WRFR;
+ __IO uint32_t CWRFR;
+ __IO uint32_t RDFR;
+ __IO uint32_t CRDFR;
+ __IO uint32_t SR;
+ __IO uint32_t CLRFR;
+ uint32_t RESERVED[57];
+ __IO uint32_t DINR0;
+ __IO uint32_t DINR1;
+ __IO uint32_t DINR2;
+ __IO uint32_t DINR3;
+ __IO uint32_t DINR4;
+ __IO uint32_t DINR5;
+ __IO uint32_t DINR6;
+ __IO uint32_t DINR7;
+ __IO uint32_t DINR8;
+ __IO uint32_t DINR9;
+ __IO uint32_t DINR10;
+ __IO uint32_t DINR11;
+ __IO uint32_t DINR12;
+ __IO uint32_t DINR13;
+ __IO uint32_t DINR14;
+ __IO uint32_t DINR15;
+ __IO uint32_t DINR16;
+ __IO uint32_t DINR17;
+ __IO uint32_t DINR18;
+ __IO uint32_t DINR19;
+ __IO uint32_t DINR20;
+ __IO uint32_t DINR21;
+ __IO uint32_t DINR22;
+ __IO uint32_t DINR23;
+ __IO uint32_t DINR24;
+ __IO uint32_t DINR25;
+ __IO uint32_t DINR26;
+ __IO uint32_t DINR27;
+ __IO uint32_t DINR28;
+ __IO uint32_t DINR29;
+ __IO uint32_t DINR30;
+ __IO uint32_t DINR31;
+ __IO uint32_t DOUTR0;
+ __IO uint32_t DOUTR1;
+ __IO uint32_t DOUTR2;
+ __IO uint32_t DOUTR3;
+ __IO uint32_t DOUTR4;
+ __IO uint32_t DOUTR5;
+ __IO uint32_t DOUTR6;
+ __IO uint32_t DOUTR7;
+ __IO uint32_t DOUTR8;
+ __IO uint32_t DOUTR9;
+ __IO uint32_t DOUTR10;
+ __IO uint32_t DOUTR11;
+ __IO uint32_t DOUTR12;
+ __IO uint32_t DOUTR13;
+ __IO uint32_t DOUTR14;
+ __IO uint32_t DOUTR15;
+ __IO uint32_t DOUTR16;
+ __IO uint32_t DOUTR17;
+ __IO uint32_t DOUTR18;
+ __IO uint32_t DOUTR19;
+ __IO uint32_t DOUTR20;
+ __IO uint32_t DOUTR21;
+ __IO uint32_t DOUTR22;
+ __IO uint32_t DOUTR23;
+ __IO uint32_t DOUTR24;
+ __IO uint32_t DOUTR25;
+ __IO uint32_t DOUTR26;
+ __IO uint32_t DOUTR27;
+ __IO uint32_t DOUTR28;
+ __IO uint32_t DOUTR29;
+ __IO uint32_t DOUTR30;
+ __IO uint32_t DOUTR31;
+} MDIOS_TypeDef;
+
+
+/**
+ * @brief USB_OTG_Core_Registers
+ */
+typedef struct
+{
+ __IO uint32_t GOTGCTL; /*!< USB_OTG Control and Status Register 000h */
+ __IO uint32_t GOTGINT; /*!< USB_OTG Interrupt Register 004h */
+ __IO uint32_t GAHBCFG; /*!< Core AHB Configuration Register 008h */
+ __IO uint32_t GUSBCFG; /*!< Core USB Configuration Register 00Ch */
+ __IO uint32_t GRSTCTL; /*!< Core Reset Register 010h */
+ __IO uint32_t GINTSTS; /*!< Core Interrupt Register 014h */
+ __IO uint32_t GINTMSK; /*!< Core Interrupt Mask Register 018h */
+ __IO uint32_t GRXSTSR; /*!< Receive Sts Q Read Register 01Ch */
+ __IO uint32_t GRXSTSP; /*!< Receive Sts Q Read & POP Register 020h */
+ __IO uint32_t GRXFSIZ; /*!< Receive FIFO Size Register 024h */
+ __IO uint32_t DIEPTXF0_HNPTXFSIZ; /*!< EP0 / Non Periodic Tx FIFO Size Register 028h */
+ __IO uint32_t HNPTXSTS; /*!< Non Periodic Tx FIFO/Queue Sts reg 02Ch */
+ uint32_t Reserved30[2]; /*!< Reserved 030h */
+ __IO uint32_t GCCFG; /*!< General Purpose IO Register 038h */
+ __IO uint32_t CID; /*!< User ID Register 03Ch */
+ __IO uint32_t GSNPSID; /* USB_OTG core ID 040h*/
+ __IO uint32_t GHWCFG1; /* User HW config1 044h*/
+ __IO uint32_t GHWCFG2; /* User HW config2 048h*/
+ __IO uint32_t GHWCFG3; /*!< User HW config3 04Ch */
+ uint32_t Reserved6; /*!< Reserved 050h */
+ __IO uint32_t GLPMCFG; /*!< LPM Register 054h */
+ __IO uint32_t GPWRDN; /*!< Power Down Register 058h */
+ __IO uint32_t GDFIFOCFG; /*!< DFIFO Software Config Register 05Ch */
+ __IO uint32_t GADPCTL; /*!< ADP Timer, Control and Status Register 60Ch */
+ uint32_t Reserved43[39]; /*!< Reserved 058h-0FFh */
+ __IO uint32_t HPTXFSIZ; /*!< Host Periodic Tx FIFO Size Reg 100h */
+ __IO uint32_t DIEPTXF[0x0F]; /*!< dev Periodic Transmit FIFO */
+} USB_OTG_GlobalTypeDef;
+
+
+/**
+ * @brief USB_OTG_device_Registers
+ */
+typedef struct
+{
+ __IO uint32_t DCFG; /*!< dev Configuration Register 800h */
+ __IO uint32_t DCTL; /*!< dev Control Register 804h */
+ __IO uint32_t DSTS; /*!< dev Status Register (RO) 808h */
+ uint32_t Reserved0C; /*!< Reserved 80Ch */
+ __IO uint32_t DIEPMSK; /*!< dev IN Endpoint Mask 810h */
+ __IO uint32_t DOEPMSK; /*!< dev OUT Endpoint Mask 814h */
+ __IO uint32_t DAINT; /*!< dev All Endpoints Itr Reg 818h */
+ __IO uint32_t DAINTMSK; /*!< dev All Endpoints Itr Mask 81Ch */
+ uint32_t Reserved20; /*!< Reserved 820h */
+ uint32_t Reserved9; /*!< Reserved 824h */
+ __IO uint32_t DVBUSDIS; /*!< dev VBUS discharge Register 828h */
+ __IO uint32_t DVBUSPULSE; /*!< dev VBUS Pulse Register 82Ch */
+ __IO uint32_t DTHRCTL; /*!< dev threshold 830h */
+ __IO uint32_t DIEPEMPMSK; /*!< dev empty msk 834h */
+ __IO uint32_t DEACHINT; /*!< dedicated EP interrupt 838h */
+ __IO uint32_t DEACHMSK; /*!< dedicated EP msk 83Ch */
+ uint32_t Reserved40; /*!< dedicated EP mask 840h */
+ __IO uint32_t DINEP1MSK; /*!< dedicated EP mask 844h */
+ uint32_t Reserved44[15]; /*!< Reserved 844-87Ch */
+ __IO uint32_t DOUTEP1MSK; /*!< dedicated EP msk 884h */
+} USB_OTG_DeviceTypeDef;
+
+
+/**
+ * @brief USB_OTG_IN_Endpoint-Specific_Register
+ */
+typedef struct
+{
+ __IO uint32_t DIEPCTL; /*!< dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h */
+ uint32_t Reserved04; /*!< Reserved 900h + (ep_num * 20h) + 04h */
+ __IO uint32_t DIEPINT; /*!< dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h */
+ uint32_t Reserved0C; /*!< Reserved 900h + (ep_num * 20h) + 0Ch */
+ __IO uint32_t DIEPTSIZ; /*!< IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h */
+ __IO uint32_t DIEPDMA; /*!< IN Endpoint DMA Address Reg 900h + (ep_num * 20h) + 14h */
+ __IO uint32_t DTXFSTS; /*!< IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h */
+ uint32_t Reserved18; /*!< Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch */
+} USB_OTG_INEndpointTypeDef;
+
+
+/**
+ * @brief USB_OTG_OUT_Endpoint-Specific_Registers
+ */
+typedef struct
+{
+ __IO uint32_t DOEPCTL; /*!< dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h */
+ uint32_t Reserved04; /*!< Reserved B00h + (ep_num * 20h) + 04h */
+ __IO uint32_t DOEPINT; /*!< dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h */
+ uint32_t Reserved0C; /*!< Reserved B00h + (ep_num * 20h) + 0Ch */
+ __IO uint32_t DOEPTSIZ; /*!< dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h */
+ __IO uint32_t DOEPDMA; /*!< dev OUT Endpoint DMA Address B00h + (ep_num * 20h) + 14h */
+ uint32_t Reserved18[2]; /*!< Reserved B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch */
+} USB_OTG_OUTEndpointTypeDef;
+
+
+/**
+ * @brief USB_OTG_Host_Mode_Register_Structures
+ */
+typedef struct
+{
+ __IO uint32_t HCFG; /*!< Host Configuration Register 400h */
+ __IO uint32_t HFIR; /*!< Host Frame Interval Register 404h */
+ __IO uint32_t HFNUM; /*!< Host Frame Nbr/Frame Remaining 408h */
+ uint32_t Reserved40C; /*!< Reserved 40Ch */
+ __IO uint32_t HPTXSTS; /*!< Host Periodic Tx FIFO/ Queue Status 410h */
+ __IO uint32_t HAINT; /*!< Host All Channels Interrupt Register 414h */
+ __IO uint32_t HAINTMSK; /*!< Host All Channels Interrupt Mask 418h */
+} USB_OTG_HostTypeDef;
+
+/**
+ * @brief USB_OTG_Host_Channel_Specific_Registers
+ */
+typedef struct
+{
+ __IO uint32_t HCCHAR; /*!< Host Channel Characteristics Register 500h */
+ __IO uint32_t HCSPLT; /*!< Host Channel Split Control Register 504h */
+ __IO uint32_t HCINT; /*!< Host Channel Interrupt Register 508h */
+ __IO uint32_t HCINTMSK; /*!< Host Channel Interrupt Mask Register 50Ch */
+ __IO uint32_t HCTSIZ; /*!< Host Channel Transfer Size Register 510h */
+ __IO uint32_t HCDMA; /*!< Host Channel DMA Address Register 514h */
+ uint32_t Reserved[2]; /*!< Reserved */
+} USB_OTG_HostChannelTypeDef;
+/**
+ * @}
+ */
+
+/**
+ * @brief OCTO Serial Peripheral Interface
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< OCTOSPI Control register, Address offset: 0x000 */
+ uint32_t RESERVED; /*!< Reserved, Address offset: 0x004 */
+ __IO uint32_t DCR1; /*!< OCTOSPI Device Configuration register 1, Address offset: 0x008 */
+ __IO uint32_t DCR2; /*!< OCTOSPI Device Configuration register 2, Address offset: 0x00C */
+ __IO uint32_t DCR3; /*!< OCTOSPI Device Configuration register 3, Address offset: 0x010 */
+ __IO uint32_t DCR4; /*!< OCTOSPI Device Configuration register 4, Address offset: 0x014 */
+ uint32_t RESERVED1[2]; /*!< Reserved, Address offset: 0x018-0x01C */
+ __IO uint32_t SR; /*!< OCTOSPI Status register, Address offset: 0x020 */
+ __IO uint32_t FCR; /*!< OCTOSPI Flag Clear register, Address offset: 0x024 */
+ uint32_t RESERVED2[6]; /*!< Reserved, Address offset: 0x028-0x03C */
+ __IO uint32_t DLR; /*!< OCTOSPI Data Length register, Address offset: 0x040 */
+ uint32_t RESERVED3; /*!< Reserved, Address offset: 0x044 */
+ __IO uint32_t AR; /*!< OCTOSPI Address register, Address offset: 0x048 */
+ uint32_t RESERVED4; /*!< Reserved, Address offset: 0x04C */
+ __IO uint32_t DR; /*!< OCTOSPI Data register, Address offset: 0x050 */
+ uint32_t RESERVED5[11]; /*!< Reserved, Address offset: 0x054-0x07C */
+ __IO uint32_t PSMKR; /*!< OCTOSPI Polling Status Mask register, Address offset: 0x080 */
+ uint32_t RESERVED6; /*!< Reserved, Address offset: 0x084 */
+ __IO uint32_t PSMAR; /*!< OCTOSPI Polling Status Match register, Address offset: 0x088 */
+ uint32_t RESERVED7; /*!< Reserved, Address offset: 0x08C */
+ __IO uint32_t PIR; /*!< OCTOSPI Polling Interval register, Address offset: 0x090 */
+ uint32_t RESERVED8[27]; /*!< Reserved, Address offset: 0x094-0x0FC */
+ __IO uint32_t CCR; /*!< OCTOSPI Communication Configuration register, Address offset: 0x100 */
+ uint32_t RESERVED9; /*!< Reserved, Address offset: 0x104 */
+ __IO uint32_t TCR; /*!< OCTOSPI Timing Configuration register, Address offset: 0x108 */
+ uint32_t RESERVED10; /*!< Reserved, Address offset: 0x10C */
+ __IO uint32_t IR; /*!< OCTOSPI Instruction register, Address offset: 0x110 */
+ uint32_t RESERVED11[3]; /*!< Reserved, Address offset: 0x114-0x11C */
+ __IO uint32_t ABR; /*!< OCTOSPI Alternate Bytes register, Address offset: 0x120 */
+ uint32_t RESERVED12[3]; /*!< Reserved, Address offset: 0x124-0x12C */
+ __IO uint32_t LPTR; /*!< OCTOSPI Low Power Timeout register, Address offset: 0x130 */
+ uint32_t RESERVED13[3]; /*!< Reserved, Address offset: 0x134-0x13C */
+ __IO uint32_t WPCCR; /*!< OCTOSPI Wrap Communication Configuration register, Address offset: 0x140 */
+ uint32_t RESERVED14; /*!< Reserved, Address offset: 0x144 */
+ __IO uint32_t WPTCR; /*!< OCTOSPI Wrap Timing Configuration register, Address offset: 0x148 */
+ uint32_t RESERVED15; /*!< Reserved, Address offset: 0x14C */
+ __IO uint32_t WPIR; /*!< OCTOSPI Wrap Instruction register, Address offset: 0x150 */
+ uint32_t RESERVED16[3]; /*!< Reserved, Address offset: 0x154-0x15C */
+ __IO uint32_t WPABR; /*!< OCTOSPI Wrap Alternate Bytes register, Address offset: 0x160 */
+ uint32_t RESERVED17[7]; /*!< Reserved, Address offset: 0x164-0x17C */
+ __IO uint32_t WCCR; /*!< OCTOSPI Write Communication Configuration register, Address offset: 0x180 */
+ uint32_t RESERVED18; /*!< Reserved, Address offset: 0x184 */
+ __IO uint32_t WTCR; /*!< OCTOSPI Write Timing Configuration register, Address offset: 0x188 */
+ uint32_t RESERVED19; /*!< Reserved, Address offset: 0x18C */
+ __IO uint32_t WIR; /*!< OCTOSPI Write Instruction register, Address offset: 0x190 */
+ uint32_t RESERVED20[3]; /*!< Reserved, Address offset: 0x194-0x19C */
+ __IO uint32_t WABR; /*!< OCTOSPI Write Alternate Bytes register, Address offset: 0x1A0 */
+ uint32_t RESERVED21[23]; /*!< Reserved, Address offset: 0x1A4-0x1FC */
+ __IO uint32_t HLCR; /*!< OCTOSPI Hyperbus Latency Configuration register, Address offset: 0x200 */
+ uint32_t RESERVED22[122]; /*!< Reserved, Address offset: 0x204-0x3EC */
+ __IO uint32_t HWCFGR; /*!< OCTOSPI HW Configuration register, Address offset: 0x3F0 */
+ __IO uint32_t VER; /*!< OCTOSPI Version register, Address offset: 0x3F4 */
+ __IO uint32_t ID; /*!< OCTOSPI Identification register, Address offset: 0x3F8 */
+ __IO uint32_t MID; /*!< OCTOPSI HW Magic ID register, Address offset: 0x3FC */
+} OCTOSPI_TypeDef;
+
+/**
+ * @}
+ */
+/**
+ * @brief OCTO Serial Peripheral Interface IO Manager
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< OCTOSPI IO Manager Control register, Address offset: 0x00 */
+ __IO uint32_t PCR[3]; /*!< OCTOSPI IO Manager Port[1:3] Configuration register, Address offset: 0x04-0x20 */
+} OCTOSPIM_TypeDef;
+
+/**
+ * @}
+ */
+
+/** @addtogroup Peripheral_memory_map
+ * @{
+ */
+#define D1_ITCMRAM_BASE (0x00000000UL) /*!< Base address of : 64KB RAM reserved for CPU execution/instruction accessible over ITCM */
+#define D1_ITCMICP_BASE (0x00100000UL) /*!< Base address of : (up to 128KB) embedded Test FLASH memory accessible over ITCM */
+#define D1_DTCMRAM_BASE (0x20000000UL) /*!< Base address of : 128KB system data RAM accessible over DTCM */
+#define D1_AXIFLASH_BASE (0x08000000UL) /*!< Base address of : (up to 1 MB) embedded FLASH memory accessible over AXI */
+#define D1_AXIICP_BASE (0x1FF00000UL) /*!< Base address of : (up to 128KB) embedded Test FLASH memory accessible over AXI */
+#define D1_AXISRAM1_BASE (0x24000000UL) /*!< Base address of : (up to 128KB) system data RAM1 accessible over over AXI */
+#define D1_AXISRAM2_BASE (0x24020000UL) /*!< Base address of : (up to 192KB) system data RAM2 accessible over over AXI to be shared with ITCM (64K granularity) */
+#define D1_AXISRAM_BASE D1_AXISRAM1_BASE /*!< Base address of : (up to 320KB) system data RAM1/2 accessible over over AXI */
+
+#define D2_AHBSRAM1_BASE (0x30000000UL) /*!< Base address of : (up to 16KB) system data RAM accessible over over AXI->AHB Bridge */
+#define D2_AHBSRAM2_BASE (0x30004000UL) /*!< Base address of : (up to 16KB) system data RAM accessible over over AXI->AHB Bridge */
+#define D2_AHBSRAM_BASE D2_AHBSRAM1_BASE /*!< Base address of : (up to 32KB) system data RAM1/2 accessible over over AXI->AHB Bridge */
+
+#define D3_BKPSRAM_BASE (0x38800000UL) /*!< Base address of : Backup SRAM(4 KB) over AXI->AHB Bridge */
+#define D3_SRAM_BASE (0x38000000UL) /*!< Base address of : Backup SRAM(16 KB) over AXI->AHB Bridge */
+
+#define PERIPH_BASE (0x40000000UL) /*!< Base address of : AHB/APB Peripherals */
+#define OCTOSPI1_BASE (0x90000000UL) /*!< Base address of : OCTOSPI1 memories accessible over AXI */
+#define OCTOSPI2_BASE (0x70000000UL) /*!< Base address of : OCTOSPI2 memories accessible over AXI */
+
+#define FLASH_BANK1_BASE (0x08000000UL) /*!< Base address of : (up to 1 MB) Flash Bank1 accessible over AXI */
+#define FLASH_END (0x080FFFFFUL) /*!< FLASH end address */
+
+
+/* Legacy define */
+#define FLASH_BASE FLASH_BANK1_BASE
+
+/*!< Device electronic signature memory map */
+#define UID_BASE (0x1FF1E800UL) /*!< Unique device ID register base address */
+#define FLASHSIZE_BASE (0x1FF1E880UL) /*!< FLASH Size register base address */
+
+
+/*!< Peripheral memory map */
+#define D2_APB1PERIPH_BASE PERIPH_BASE
+#define D2_APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL)
+#define D2_AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL)
+#define D2_AHB2PERIPH_BASE (PERIPH_BASE + 0x08020000UL)
+
+#define D1_APB1PERIPH_BASE (PERIPH_BASE + 0x10000000UL)
+#define D1_AHB1PERIPH_BASE (PERIPH_BASE + 0x12000000UL)
+
+#define D3_APB1PERIPH_BASE (PERIPH_BASE + 0x18000000UL)
+#define D3_AHB1PERIPH_BASE (PERIPH_BASE + 0x18020000UL)
+
+/*!< Legacy Peripheral memory map */
+#define APB1PERIPH_BASE PERIPH_BASE
+#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL)
+#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL)
+#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000UL)
+
+
+/*!< D1_AHB1PERIPH peripherals */
+
+#define MDMA_BASE (D1_AHB1PERIPH_BASE + 0x0000UL)
+#define DMA2D_BASE (D1_AHB1PERIPH_BASE + 0x1000UL)
+#define FLASH_R_BASE (D1_AHB1PERIPH_BASE + 0x2000UL)
+#define FMC_R_BASE (D1_AHB1PERIPH_BASE + 0x4000UL)
+#define OCTOSPI1_R_BASE (D1_AHB1PERIPH_BASE + 0x5000UL)
+#define DLYB_OCTOSPI1_BASE (D1_AHB1PERIPH_BASE + 0x6000UL)
+#define SDMMC1_BASE (D1_AHB1PERIPH_BASE + 0x7000UL)
+#define DLYB_SDMMC1_BASE (D1_AHB1PERIPH_BASE + 0x8000UL)
+#define RAMECC1_BASE (D1_AHB1PERIPH_BASE + 0x9000UL)
+#define OCTOSPI2_R_BASE (D1_AHB1PERIPH_BASE + 0xA000UL)
+#define DLYB_OCTOSPI2_BASE (D1_AHB1PERIPH_BASE + 0xB000UL)
+#define OCTOSPIM_BASE (D1_AHB1PERIPH_BASE + 0xB400UL)
+
+/*!< D2_AHB1PERIPH peripherals */
+
+#define DMA1_BASE (D2_AHB1PERIPH_BASE + 0x0000UL)
+#define DMA2_BASE (D2_AHB1PERIPH_BASE + 0x0400UL)
+#define DMAMUX1_BASE (D2_AHB1PERIPH_BASE + 0x0800UL)
+#define ADC1_BASE (D2_AHB1PERIPH_BASE + 0x2000UL)
+#define ADC2_BASE (D2_AHB1PERIPH_BASE + 0x2100UL)
+#define ADC12_COMMON_BASE (D2_AHB1PERIPH_BASE + 0x2300UL)
+#define ETH_BASE (D2_AHB1PERIPH_BASE + 0x8000UL)
+#define ETH_MAC_BASE (ETH_BASE)
+
+/*!< USB registers base address */
+#define USB1_OTG_HS_PERIPH_BASE (0x40040000UL)
+#define USB_OTG_GLOBAL_BASE (0x000UL)
+#define USB_OTG_DEVICE_BASE (0x800UL)
+#define USB_OTG_IN_ENDPOINT_BASE (0x900UL)
+#define USB_OTG_OUT_ENDPOINT_BASE (0xB00UL)
+#define USB_OTG_EP_REG_SIZE (0x20UL)
+#define USB_OTG_HOST_BASE (0x400UL)
+#define USB_OTG_HOST_PORT_BASE (0x440UL)
+#define USB_OTG_HOST_CHANNEL_BASE (0x500UL)
+#define USB_OTG_HOST_CHANNEL_SIZE (0x20UL)
+#define USB_OTG_PCGCCTL_BASE (0xE00UL)
+#define USB_OTG_FIFO_BASE (0x1000UL)
+#define USB_OTG_FIFO_SIZE (0x1000UL)
+
+/*!< D2_AHB2PERIPH peripherals */
+
+#define DCMI_BASE (D2_AHB2PERIPH_BASE + 0x0000UL)
+#define PSSI_BASE (D2_AHB2PERIPH_BASE + 0x0400UL)
+#define RNG_BASE (D2_AHB2PERIPH_BASE + 0x1800UL)
+#define SDMMC2_BASE (D2_AHB2PERIPH_BASE + 0x2400UL)
+#define DLYB_SDMMC2_BASE (D2_AHB2PERIPH_BASE + 0x2800UL)
+#define RAMECC2_BASE (D2_AHB2PERIPH_BASE + 0x3000UL)
+#define FMAC_BASE (D2_AHB2PERIPH_BASE + 0x4000UL)
+#define CORDIC_BASE (D2_AHB2PERIPH_BASE + 0x4400UL)
+
+/*!< D3_AHB1PERIPH peripherals */
+#define GPIOA_BASE (D3_AHB1PERIPH_BASE + 0x0000UL)
+#define GPIOB_BASE (D3_AHB1PERIPH_BASE + 0x0400UL)
+#define GPIOC_BASE (D3_AHB1PERIPH_BASE + 0x0800UL)
+#define GPIOD_BASE (D3_AHB1PERIPH_BASE + 0x0C00UL)
+#define GPIOE_BASE (D3_AHB1PERIPH_BASE + 0x1000UL)
+#define GPIOF_BASE (D3_AHB1PERIPH_BASE + 0x1400UL)
+#define GPIOG_BASE (D3_AHB1PERIPH_BASE + 0x1800UL)
+#define GPIOH_BASE (D3_AHB1PERIPH_BASE + 0x1C00UL)
+#define GPIOJ_BASE (D3_AHB1PERIPH_BASE + 0x2400UL)
+#define GPIOK_BASE (D3_AHB1PERIPH_BASE + 0x2800UL)
+#define RCC_BASE (D3_AHB1PERIPH_BASE + 0x4400UL)
+#define PWR_BASE (D3_AHB1PERIPH_BASE + 0x4800UL)
+#define CRC_BASE (D3_AHB1PERIPH_BASE + 0x4C00UL)
+#define BDMA_BASE (D3_AHB1PERIPH_BASE + 0x5400UL)
+#define DMAMUX2_BASE (D3_AHB1PERIPH_BASE + 0x5800UL)
+#define ADC3_BASE (D3_AHB1PERIPH_BASE + 0x6000UL)
+#define ADC3_COMMON_BASE (D3_AHB1PERIPH_BASE + 0x6300UL)
+#define HSEM_BASE (D3_AHB1PERIPH_BASE + 0x6400UL)
+#define RAMECC3_BASE (D3_AHB1PERIPH_BASE + 0x7000UL)
+
+/*!< D1_APB1PERIPH peripherals */
+#define LTDC_BASE (D1_APB1PERIPH_BASE + 0x1000UL)
+#define LTDC_Layer1_BASE (LTDC_BASE + 0x84UL)
+#define LTDC_Layer2_BASE (LTDC_BASE + 0x104UL)
+#define WWDG1_BASE (D1_APB1PERIPH_BASE + 0x3000UL)
+
+/*!< D2_APB1PERIPH peripherals */
+#define TIM2_BASE (D2_APB1PERIPH_BASE + 0x0000UL)
+#define TIM3_BASE (D2_APB1PERIPH_BASE + 0x0400UL)
+#define TIM4_BASE (D2_APB1PERIPH_BASE + 0x0800UL)
+#define TIM5_BASE (D2_APB1PERIPH_BASE + 0x0C00UL)
+#define TIM6_BASE (D2_APB1PERIPH_BASE + 0x1000UL)
+#define TIM7_BASE (D2_APB1PERIPH_BASE + 0x1400UL)
+#define TIM12_BASE (D2_APB1PERIPH_BASE + 0x1800UL)
+#define TIM13_BASE (D2_APB1PERIPH_BASE + 0x1C00UL)
+#define TIM14_BASE (D2_APB1PERIPH_BASE + 0x2000UL)
+#define LPTIM1_BASE (D2_APB1PERIPH_BASE + 0x2400UL)
+
+
+#define SPI2_BASE (D2_APB1PERIPH_BASE + 0x3800UL)
+#define SPI3_BASE (D2_APB1PERIPH_BASE + 0x3C00UL)
+#define SPDIFRX_BASE (D2_APB1PERIPH_BASE + 0x4000UL)
+#define USART2_BASE (D2_APB1PERIPH_BASE + 0x4400UL)
+#define USART3_BASE (D2_APB1PERIPH_BASE + 0x4800UL)
+#define UART4_BASE (D2_APB1PERIPH_BASE + 0x4C00UL)
+#define UART5_BASE (D2_APB1PERIPH_BASE + 0x5000UL)
+#define I2C1_BASE (D2_APB1PERIPH_BASE + 0x5400UL)
+#define I2C2_BASE (D2_APB1PERIPH_BASE + 0x5800UL)
+#define I2C3_BASE (D2_APB1PERIPH_BASE + 0x5C00UL)
+#define I2C5_BASE (D2_APB1PERIPH_BASE + 0x6400UL)
+#define CEC_BASE (D2_APB1PERIPH_BASE + 0x6C00UL)
+#define DAC1_BASE (D2_APB1PERIPH_BASE + 0x7400UL)
+#define UART7_BASE (D2_APB1PERIPH_BASE + 0x7800UL)
+#define UART8_BASE (D2_APB1PERIPH_BASE + 0x7C00UL)
+#define CRS_BASE (D2_APB1PERIPH_BASE + 0x8400UL)
+#define SWPMI1_BASE (D2_APB1PERIPH_BASE + 0x8800UL)
+#define OPAMP_BASE (D2_APB1PERIPH_BASE + 0x9000UL)
+#define OPAMP1_BASE (D2_APB1PERIPH_BASE + 0x9000UL)
+#define OPAMP2_BASE (D2_APB1PERIPH_BASE + 0x9010UL)
+#define MDIOS_BASE (D2_APB1PERIPH_BASE + 0x9400UL)
+#define FDCAN1_BASE (D2_APB1PERIPH_BASE + 0xA000UL)
+#define FDCAN2_BASE (D2_APB1PERIPH_BASE + 0xA400UL)
+#define FDCAN_CCU_BASE (D2_APB1PERIPH_BASE + 0xA800UL)
+#define SRAMCAN_BASE (D2_APB1PERIPH_BASE + 0xAC00UL)
+#define FDCAN3_BASE (D2_APB1PERIPH_BASE + 0xD400UL)
+#define TIM23_BASE (D2_APB1PERIPH_BASE + 0xE000UL)
+#define TIM24_BASE (D2_APB1PERIPH_BASE + 0xE400UL)
+
+/*!< D2_APB2PERIPH peripherals */
+
+#define TIM1_BASE (D2_APB2PERIPH_BASE + 0x0000UL)
+#define TIM8_BASE (D2_APB2PERIPH_BASE + 0x0400UL)
+#define USART1_BASE (D2_APB2PERIPH_BASE + 0x1000UL)
+#define USART6_BASE (D2_APB2PERIPH_BASE + 0x1400UL)
+#define UART9_BASE (D2_APB2PERIPH_BASE + 0x1800UL)
+#define USART10_BASE (D2_APB2PERIPH_BASE + 0x1C00UL)
+#define SPI1_BASE (D2_APB2PERIPH_BASE + 0x3000UL)
+#define SPI4_BASE (D2_APB2PERIPH_BASE + 0x3400UL)
+#define TIM15_BASE (D2_APB2PERIPH_BASE + 0x4000UL)
+#define TIM16_BASE (D2_APB2PERIPH_BASE + 0x4400UL)
+#define TIM17_BASE (D2_APB2PERIPH_BASE + 0x4800UL)
+#define SPI5_BASE (D2_APB2PERIPH_BASE + 0x5000UL)
+#define SAI1_BASE (D2_APB2PERIPH_BASE + 0x5800UL)
+#define SAI1_Block_A_BASE (SAI1_BASE + 0x004UL)
+#define SAI1_Block_B_BASE (SAI1_BASE + 0x024UL)
+#define DFSDM1_BASE (D2_APB2PERIPH_BASE + 0x7800UL)
+#define DFSDM1_Channel0_BASE (DFSDM1_BASE + 0x00UL)
+#define DFSDM1_Channel1_BASE (DFSDM1_BASE + 0x20UL)
+#define DFSDM1_Channel2_BASE (DFSDM1_BASE + 0x40UL)
+#define DFSDM1_Channel3_BASE (DFSDM1_BASE + 0x60UL)
+#define DFSDM1_Channel4_BASE (DFSDM1_BASE + 0x80UL)
+#define DFSDM1_Channel5_BASE (DFSDM1_BASE + 0xA0UL)
+#define DFSDM1_Channel6_BASE (DFSDM1_BASE + 0xC0UL)
+#define DFSDM1_Channel7_BASE (DFSDM1_BASE + 0xE0UL)
+#define DFSDM1_Filter0_BASE (DFSDM1_BASE + 0x100UL)
+#define DFSDM1_Filter1_BASE (DFSDM1_BASE + 0x180UL)
+#define DFSDM1_Filter2_BASE (DFSDM1_BASE + 0x200UL)
+#define DFSDM1_Filter3_BASE (DFSDM1_BASE + 0x280UL)
+
+
+/*!< D3_APB1PERIPH peripherals */
+#define EXTI_BASE (D3_APB1PERIPH_BASE + 0x0000UL)
+#define EXTI_D1_BASE (EXTI_BASE + 0x0080UL)
+#define EXTI_D2_BASE (EXTI_BASE + 0x00C0UL)
+#define SYSCFG_BASE (D3_APB1PERIPH_BASE + 0x0400UL)
+#define LPUART1_BASE (D3_APB1PERIPH_BASE + 0x0C00UL)
+#define SPI6_BASE (D3_APB1PERIPH_BASE + 0x1400UL)
+#define I2C4_BASE (D3_APB1PERIPH_BASE + 0x1C00UL)
+#define LPTIM2_BASE (D3_APB1PERIPH_BASE + 0x2400UL)
+#define LPTIM3_BASE (D3_APB1PERIPH_BASE + 0x2800UL)
+#define LPTIM4_BASE (D3_APB1PERIPH_BASE + 0x2C00UL)
+#define LPTIM5_BASE (D3_APB1PERIPH_BASE + 0x3000UL)
+#define COMP12_BASE (D3_APB1PERIPH_BASE + 0x3800UL)
+#define COMP1_BASE (COMP12_BASE + 0x0CUL)
+#define COMP2_BASE (COMP12_BASE + 0x10UL)
+#define VREFBUF_BASE (D3_APB1PERIPH_BASE + 0x3C00UL)
+#define RTC_BASE (D3_APB1PERIPH_BASE + 0x4000UL)
+#define IWDG1_BASE (D3_APB1PERIPH_BASE + 0x4800UL)
+
+
+#define SAI4_BASE (D3_APB1PERIPH_BASE + 0x5400UL)
+#define SAI4_Block_A_BASE (SAI4_BASE + 0x004UL)
+#define SAI4_Block_B_BASE (SAI4_BASE + 0x024UL)
+
+#define DTS_BASE (D3_APB1PERIPH_BASE + 0x6800UL)
+
+
+
+#define BDMA_Channel0_BASE (BDMA_BASE + 0x0008UL)
+#define BDMA_Channel1_BASE (BDMA_BASE + 0x001CUL)
+#define BDMA_Channel2_BASE (BDMA_BASE + 0x0030UL)
+#define BDMA_Channel3_BASE (BDMA_BASE + 0x0044UL)
+#define BDMA_Channel4_BASE (BDMA_BASE + 0x0058UL)
+#define BDMA_Channel5_BASE (BDMA_BASE + 0x006CUL)
+#define BDMA_Channel6_BASE (BDMA_BASE + 0x0080UL)
+#define BDMA_Channel7_BASE (BDMA_BASE + 0x0094UL)
+
+#define DMAMUX2_Channel0_BASE (DMAMUX2_BASE)
+#define DMAMUX2_Channel1_BASE (DMAMUX2_BASE + 0x0004UL)
+#define DMAMUX2_Channel2_BASE (DMAMUX2_BASE + 0x0008UL)
+#define DMAMUX2_Channel3_BASE (DMAMUX2_BASE + 0x000CUL)
+#define DMAMUX2_Channel4_BASE (DMAMUX2_BASE + 0x0010UL)
+#define DMAMUX2_Channel5_BASE (DMAMUX2_BASE + 0x0014UL)
+#define DMAMUX2_Channel6_BASE (DMAMUX2_BASE + 0x0018UL)
+#define DMAMUX2_Channel7_BASE (DMAMUX2_BASE + 0x001CUL)
+
+#define DMAMUX2_RequestGenerator0_BASE (DMAMUX2_BASE + 0x0100UL)
+#define DMAMUX2_RequestGenerator1_BASE (DMAMUX2_BASE + 0x0104UL)
+#define DMAMUX2_RequestGenerator2_BASE (DMAMUX2_BASE + 0x0108UL)
+#define DMAMUX2_RequestGenerator3_BASE (DMAMUX2_BASE + 0x010CUL)
+#define DMAMUX2_RequestGenerator4_BASE (DMAMUX2_BASE + 0x0110UL)
+#define DMAMUX2_RequestGenerator5_BASE (DMAMUX2_BASE + 0x0114UL)
+#define DMAMUX2_RequestGenerator6_BASE (DMAMUX2_BASE + 0x0118UL)
+#define DMAMUX2_RequestGenerator7_BASE (DMAMUX2_BASE + 0x011CUL)
+
+#define DMAMUX2_ChannelStatus_BASE (DMAMUX2_BASE + 0x0080UL)
+#define DMAMUX2_RequestGenStatus_BASE (DMAMUX2_BASE + 0x0140UL)
+
+#define DMA1_Stream0_BASE (DMA1_BASE + 0x010UL)
+#define DMA1_Stream1_BASE (DMA1_BASE + 0x028UL)
+#define DMA1_Stream2_BASE (DMA1_BASE + 0x040UL)
+#define DMA1_Stream3_BASE (DMA1_BASE + 0x058UL)
+#define DMA1_Stream4_BASE (DMA1_BASE + 0x070UL)
+#define DMA1_Stream5_BASE (DMA1_BASE + 0x088UL)
+#define DMA1_Stream6_BASE (DMA1_BASE + 0x0A0UL)
+#define DMA1_Stream7_BASE (DMA1_BASE + 0x0B8UL)
+
+#define DMA2_Stream0_BASE (DMA2_BASE + 0x010UL)
+#define DMA2_Stream1_BASE (DMA2_BASE + 0x028UL)
+#define DMA2_Stream2_BASE (DMA2_BASE + 0x040UL)
+#define DMA2_Stream3_BASE (DMA2_BASE + 0x058UL)
+#define DMA2_Stream4_BASE (DMA2_BASE + 0x070UL)
+#define DMA2_Stream5_BASE (DMA2_BASE + 0x088UL)
+#define DMA2_Stream6_BASE (DMA2_BASE + 0x0A0UL)
+#define DMA2_Stream7_BASE (DMA2_BASE + 0x0B8UL)
+
+#define DMAMUX1_Channel0_BASE (DMAMUX1_BASE)
+#define DMAMUX1_Channel1_BASE (DMAMUX1_BASE + 0x0004UL)
+#define DMAMUX1_Channel2_BASE (DMAMUX1_BASE + 0x0008UL)
+#define DMAMUX1_Channel3_BASE (DMAMUX1_BASE + 0x000CUL)
+#define DMAMUX1_Channel4_BASE (DMAMUX1_BASE + 0x0010UL)
+#define DMAMUX1_Channel5_BASE (DMAMUX1_BASE + 0x0014UL)
+#define DMAMUX1_Channel6_BASE (DMAMUX1_BASE + 0x0018UL)
+#define DMAMUX1_Channel7_BASE (DMAMUX1_BASE + 0x001CUL)
+#define DMAMUX1_Channel8_BASE (DMAMUX1_BASE + 0x0020UL)
+#define DMAMUX1_Channel9_BASE (DMAMUX1_BASE + 0x0024UL)
+#define DMAMUX1_Channel10_BASE (DMAMUX1_BASE + 0x0028UL)
+#define DMAMUX1_Channel11_BASE (DMAMUX1_BASE + 0x002CUL)
+#define DMAMUX1_Channel12_BASE (DMAMUX1_BASE + 0x0030UL)
+#define DMAMUX1_Channel13_BASE (DMAMUX1_BASE + 0x0034UL)
+#define DMAMUX1_Channel14_BASE (DMAMUX1_BASE + 0x0038UL)
+#define DMAMUX1_Channel15_BASE (DMAMUX1_BASE + 0x003CUL)
+
+#define DMAMUX1_RequestGenerator0_BASE (DMAMUX1_BASE + 0x0100UL)
+#define DMAMUX1_RequestGenerator1_BASE (DMAMUX1_BASE + 0x0104UL)
+#define DMAMUX1_RequestGenerator2_BASE (DMAMUX1_BASE + 0x0108UL)
+#define DMAMUX1_RequestGenerator3_BASE (DMAMUX1_BASE + 0x010CUL)
+#define DMAMUX1_RequestGenerator4_BASE (DMAMUX1_BASE + 0x0110UL)
+#define DMAMUX1_RequestGenerator5_BASE (DMAMUX1_BASE + 0x0114UL)
+#define DMAMUX1_RequestGenerator6_BASE (DMAMUX1_BASE + 0x0118UL)
+#define DMAMUX1_RequestGenerator7_BASE (DMAMUX1_BASE + 0x011CUL)
+
+#define DMAMUX1_ChannelStatus_BASE (DMAMUX1_BASE + 0x0080UL)
+#define DMAMUX1_RequestGenStatus_BASE (DMAMUX1_BASE + 0x0140UL)
+
+/*!< FMC Banks registers base address */
+#define FMC_Bank1_R_BASE (FMC_R_BASE + 0x0000UL)
+#define FMC_Bank1E_R_BASE (FMC_R_BASE + 0x0104UL)
+#define FMC_Bank2_R_BASE (FMC_R_BASE + 0x0060UL)
+#define FMC_Bank3_R_BASE (FMC_R_BASE + 0x0080UL)
+#define FMC_Bank5_6_R_BASE (FMC_R_BASE + 0x0140UL)
+
+/* Debug MCU registers base address */
+#define DBGMCU_BASE (0x5C001000UL)
+
+#define MDMA_Channel0_BASE (MDMA_BASE + 0x00000040UL)
+#define MDMA_Channel1_BASE (MDMA_BASE + 0x00000080UL)
+#define MDMA_Channel2_BASE (MDMA_BASE + 0x000000C0UL)
+#define MDMA_Channel3_BASE (MDMA_BASE + 0x00000100UL)
+#define MDMA_Channel4_BASE (MDMA_BASE + 0x00000140UL)
+#define MDMA_Channel5_BASE (MDMA_BASE + 0x00000180UL)
+#define MDMA_Channel6_BASE (MDMA_BASE + 0x000001C0UL)
+#define MDMA_Channel7_BASE (MDMA_BASE + 0x00000200UL)
+#define MDMA_Channel8_BASE (MDMA_BASE + 0x00000240UL)
+#define MDMA_Channel9_BASE (MDMA_BASE + 0x00000280UL)
+#define MDMA_Channel10_BASE (MDMA_BASE + 0x000002C0UL)
+#define MDMA_Channel11_BASE (MDMA_BASE + 0x00000300UL)
+#define MDMA_Channel12_BASE (MDMA_BASE + 0x00000340UL)
+#define MDMA_Channel13_BASE (MDMA_BASE + 0x00000380UL)
+#define MDMA_Channel14_BASE (MDMA_BASE + 0x000003C0UL)
+#define MDMA_Channel15_BASE (MDMA_BASE + 0x00000400UL)
+
+#define RAMECC1_Monitor1_BASE (RAMECC1_BASE + 0x20UL)
+#define RAMECC1_Monitor2_BASE (RAMECC1_BASE + 0x40UL)
+#define RAMECC1_Monitor3_BASE (RAMECC1_BASE + 0x60UL)
+#define RAMECC1_Monitor4_BASE (RAMECC1_BASE + 0x80UL)
+#define RAMECC1_Monitor5_BASE (RAMECC1_BASE + 0xA0UL)
+#define RAMECC1_Monitor6_BASE (RAMECC1_BASE + 0xC0UL)
+
+#define RAMECC2_Monitor1_BASE (RAMECC2_BASE + 0x20UL)
+#define RAMECC2_Monitor2_BASE (RAMECC2_BASE + 0x40UL)
+#define RAMECC2_Monitor3_BASE (RAMECC2_BASE + 0x60UL)
+
+#define RAMECC3_Monitor1_BASE (RAMECC3_BASE + 0x20UL)
+#define RAMECC3_Monitor2_BASE (RAMECC3_BASE + 0x40UL)
+
+
+/**
+ * @}
+ */
+
+/** @addtogroup Peripheral_declaration
+ * @{
+ */
+#define TIM2 ((TIM_TypeDef *) TIM2_BASE)
+#define TIM3 ((TIM_TypeDef *) TIM3_BASE)
+#define TIM4 ((TIM_TypeDef *) TIM4_BASE)
+#define TIM5 ((TIM_TypeDef *) TIM5_BASE)
+#define TIM6 ((TIM_TypeDef *) TIM6_BASE)
+#define TIM7 ((TIM_TypeDef *) TIM7_BASE)
+#define TIM13 ((TIM_TypeDef *) TIM13_BASE)
+#define TIM14 ((TIM_TypeDef *) TIM14_BASE)
+#define VREFBUF ((VREFBUF_TypeDef *) VREFBUF_BASE)
+#define RTC ((RTC_TypeDef *) RTC_BASE)
+#define WWDG1 ((WWDG_TypeDef *) WWDG1_BASE)
+
+
+#define IWDG1 ((IWDG_TypeDef *) IWDG1_BASE)
+#define SPI2 ((SPI_TypeDef *) SPI2_BASE)
+#define SPI3 ((SPI_TypeDef *) SPI3_BASE)
+#define SPI4 ((SPI_TypeDef *) SPI4_BASE)
+#define SPI5 ((SPI_TypeDef *) SPI5_BASE)
+#define SPI6 ((SPI_TypeDef *) SPI6_BASE)
+#define USART2 ((USART_TypeDef *) USART2_BASE)
+#define USART3 ((USART_TypeDef *) USART3_BASE)
+#define USART6 ((USART_TypeDef *) USART6_BASE)
+#define USART10 ((USART_TypeDef *) USART10_BASE)
+#define UART7 ((USART_TypeDef *) UART7_BASE)
+#define UART8 ((USART_TypeDef *) UART8_BASE)
+#define UART9 ((USART_TypeDef *) UART9_BASE)
+#define CRS ((CRS_TypeDef *) CRS_BASE)
+#define UART4 ((USART_TypeDef *) UART4_BASE)
+#define UART5 ((USART_TypeDef *) UART5_BASE)
+#define I2C1 ((I2C_TypeDef *) I2C1_BASE)
+#define I2C2 ((I2C_TypeDef *) I2C2_BASE)
+#define I2C3 ((I2C_TypeDef *) I2C3_BASE)
+#define I2C4 ((I2C_TypeDef *) I2C4_BASE)
+#define I2C5 ((I2C_TypeDef *) I2C5_BASE)
+#define FDCAN1 ((FDCAN_GlobalTypeDef *) FDCAN1_BASE)
+#define FDCAN2 ((FDCAN_GlobalTypeDef *) FDCAN2_BASE)
+#define FDCAN_CCU ((FDCAN_ClockCalibrationUnit_TypeDef *) FDCAN_CCU_BASE)
+#define FDCAN3 ((FDCAN_GlobalTypeDef *) FDCAN3_BASE)
+#define TIM23 ((TIM_TypeDef *) TIM23_BASE)
+#define TIM24 ((TIM_TypeDef *) TIM24_BASE)
+#define CEC ((CEC_TypeDef *) CEC_BASE)
+#define LPTIM1 ((LPTIM_TypeDef *) LPTIM1_BASE)
+#define PWR ((PWR_TypeDef *) PWR_BASE)
+#define DAC1 ((DAC_TypeDef *) DAC1_BASE)
+#define LPUART1 ((USART_TypeDef *) LPUART1_BASE)
+#define SWPMI1 ((SWPMI_TypeDef *) SWPMI1_BASE)
+#define LPTIM2 ((LPTIM_TypeDef *) LPTIM2_BASE)
+#define LPTIM3 ((LPTIM_TypeDef *) LPTIM3_BASE)
+#define DTS ((DTS_TypeDef *) DTS_BASE)
+#define LPTIM4 ((LPTIM_TypeDef *) LPTIM4_BASE)
+#define LPTIM5 ((LPTIM_TypeDef *) LPTIM5_BASE)
+
+#define SYSCFG ((SYSCFG_TypeDef *) SYSCFG_BASE)
+#define COMP12 ((COMPOPT_TypeDef *) COMP12_BASE)
+#define COMP1 ((COMP_TypeDef *) COMP1_BASE)
+#define COMP2 ((COMP_TypeDef *) COMP2_BASE)
+#define COMP12_COMMON ((COMP_Common_TypeDef *) COMP2_BASE)
+#define OPAMP ((OPAMP_TypeDef *) OPAMP_BASE)
+#define OPAMP1 ((OPAMP_TypeDef *) OPAMP1_BASE)
+#define OPAMP2 ((OPAMP_TypeDef *) OPAMP2_BASE)
+
+
+#define EXTI ((EXTI_TypeDef *) EXTI_BASE)
+#define EXTI_D1 ((EXTI_Core_TypeDef *) EXTI_D1_BASE)
+#define EXTI_D2 ((EXTI_Core_TypeDef *) EXTI_D2_BASE)
+#define TIM1 ((TIM_TypeDef *) TIM1_BASE)
+#define SPI1 ((SPI_TypeDef *) SPI1_BASE)
+#define TIM8 ((TIM_TypeDef *) TIM8_BASE)
+#define USART1 ((USART_TypeDef *) USART1_BASE)
+#define TIM12 ((TIM_TypeDef *) TIM12_BASE)
+#define TIM15 ((TIM_TypeDef *) TIM15_BASE)
+#define TIM16 ((TIM_TypeDef *) TIM16_BASE)
+#define TIM17 ((TIM_TypeDef *) TIM17_BASE)
+#define SAI1 ((SAI_TypeDef *) SAI1_BASE)
+#define SAI1_Block_A ((SAI_Block_TypeDef *)SAI1_Block_A_BASE)
+#define SAI1_Block_B ((SAI_Block_TypeDef *)SAI1_Block_B_BASE)
+#define SAI4 ((SAI_TypeDef *) SAI4_BASE)
+#define SAI4_Block_A ((SAI_Block_TypeDef *)SAI4_Block_A_BASE)
+#define SAI4_Block_B ((SAI_Block_TypeDef *)SAI4_Block_B_BASE)
+
+#define SPDIFRX ((SPDIFRX_TypeDef *) SPDIFRX_BASE)
+#define DFSDM1_Channel0 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel0_BASE)
+#define DFSDM1_Channel1 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel1_BASE)
+#define DFSDM1_Channel2 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel2_BASE)
+#define DFSDM1_Channel3 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel3_BASE)
+#define DFSDM1_Channel4 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel4_BASE)
+#define DFSDM1_Channel5 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel5_BASE)
+#define DFSDM1_Channel6 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel6_BASE)
+#define DFSDM1_Channel7 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel7_BASE)
+#define DFSDM1_Filter0 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter0_BASE)
+#define DFSDM1_Filter1 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter1_BASE)
+#define DFSDM1_Filter2 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter2_BASE)
+#define DFSDM1_Filter3 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter3_BASE)
+#define DMA2D ((DMA2D_TypeDef *) DMA2D_BASE)
+#define DCMI ((DCMI_TypeDef *) DCMI_BASE)
+#define PSSI ((PSSI_TypeDef *) PSSI_BASE)
+#define RCC ((RCC_TypeDef *) RCC_BASE)
+#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE)
+#define CRC ((CRC_TypeDef *) CRC_BASE)
+
+#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
+#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
+#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)
+#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)
+#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)
+#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE)
+#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE)
+#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE)
+#define GPIOJ ((GPIO_TypeDef *) GPIOJ_BASE)
+#define GPIOK ((GPIO_TypeDef *) GPIOK_BASE)
+
+#define ADC1 ((ADC12_TypeDef *) ADC1_BASE)
+#define ADC2 ((ADC12_TypeDef *) ADC2_BASE)
+#define ADC3 ((ADC3_TypeDef *) ADC3_BASE)
+#define ADC3_COMMON ((ADC_Common_TypeDef *) ADC3_COMMON_BASE)
+#define ADC12_COMMON ((ADC_Common_TypeDef *) ADC12_COMMON_BASE)
+
+#define RNG ((RNG_TypeDef *) RNG_BASE)
+#define SDMMC2 ((SDMMC_TypeDef *) SDMMC2_BASE)
+#define DLYB_SDMMC2 ((DLYB_TypeDef *) DLYB_SDMMC2_BASE)
+#define FMAC ((FMAC_TypeDef *) FMAC_BASE)
+#define CORDIC ((CORDIC_TypeDef *) CORDIC_BASE)
+
+#define BDMA ((BDMA_TypeDef *) BDMA_BASE)
+#define BDMA_Channel0 ((BDMA_Channel_TypeDef *) BDMA_Channel0_BASE)
+#define BDMA_Channel1 ((BDMA_Channel_TypeDef *) BDMA_Channel1_BASE)
+#define BDMA_Channel2 ((BDMA_Channel_TypeDef *) BDMA_Channel2_BASE)
+#define BDMA_Channel3 ((BDMA_Channel_TypeDef *) BDMA_Channel3_BASE)
+#define BDMA_Channel4 ((BDMA_Channel_TypeDef *) BDMA_Channel4_BASE)
+#define BDMA_Channel5 ((BDMA_Channel_TypeDef *) BDMA_Channel5_BASE)
+#define BDMA_Channel6 ((BDMA_Channel_TypeDef *) BDMA_Channel6_BASE)
+#define BDMA_Channel7 ((BDMA_Channel_TypeDef *) BDMA_Channel7_BASE)
+
+#define RAMECC1 ((RAMECC_TypeDef *)RAMECC1_BASE)
+#define RAMECC1_Monitor1 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor1_BASE)
+#define RAMECC1_Monitor2 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor2_BASE)
+#define RAMECC1_Monitor3 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor3_BASE)
+#define RAMECC1_Monitor4 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor4_BASE)
+#define RAMECC1_Monitor5 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor5_BASE)
+#define RAMECC1_Monitor6 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor6_BASE)
+
+#define RAMECC2 ((RAMECC_TypeDef *)RAMECC2_BASE)
+#define RAMECC2_Monitor1 ((RAMECC_MonitorTypeDef *)RAMECC2_Monitor1_BASE)
+#define RAMECC2_Monitor2 ((RAMECC_MonitorTypeDef *)RAMECC2_Monitor2_BASE)
+#define RAMECC2_Monitor3 ((RAMECC_MonitorTypeDef *)RAMECC2_Monitor3_BASE)
+
+#define RAMECC3 ((RAMECC_TypeDef *)RAMECC3_BASE)
+#define RAMECC3_Monitor1 ((RAMECC_MonitorTypeDef *)RAMECC3_Monitor1_BASE)
+#define RAMECC3_Monitor2 ((RAMECC_MonitorTypeDef *)RAMECC3_Monitor2_BASE)
+
+#define DMAMUX2 ((DMAMUX_Channel_TypeDef *) DMAMUX2_BASE)
+#define DMAMUX2_Channel0 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel0_BASE)
+#define DMAMUX2_Channel1 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel1_BASE)
+#define DMAMUX2_Channel2 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel2_BASE)
+#define DMAMUX2_Channel3 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel3_BASE)
+#define DMAMUX2_Channel4 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel4_BASE)
+#define DMAMUX2_Channel5 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel5_BASE)
+#define DMAMUX2_Channel6 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel6_BASE)
+#define DMAMUX2_Channel7 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel7_BASE)
+
+
+#define DMAMUX2_RequestGenerator0 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator0_BASE)
+#define DMAMUX2_RequestGenerator1 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator1_BASE)
+#define DMAMUX2_RequestGenerator2 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator2_BASE)
+#define DMAMUX2_RequestGenerator3 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator3_BASE)
+#define DMAMUX2_RequestGenerator4 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator4_BASE)
+#define DMAMUX2_RequestGenerator5 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator5_BASE)
+#define DMAMUX2_RequestGenerator6 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator6_BASE)
+#define DMAMUX2_RequestGenerator7 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator7_BASE)
+
+#define DMAMUX2_ChannelStatus ((DMAMUX_ChannelStatus_TypeDef *) DMAMUX2_ChannelStatus_BASE)
+#define DMAMUX2_RequestGenStatus ((DMAMUX_RequestGenStatus_TypeDef *) DMAMUX2_RequestGenStatus_BASE)
+
+#define DMA2 ((DMA_TypeDef *) DMA2_BASE)
+#define DMA2_Stream0 ((DMA_Stream_TypeDef *) DMA2_Stream0_BASE)
+#define DMA2_Stream1 ((DMA_Stream_TypeDef *) DMA2_Stream1_BASE)
+#define DMA2_Stream2 ((DMA_Stream_TypeDef *) DMA2_Stream2_BASE)
+#define DMA2_Stream3 ((DMA_Stream_TypeDef *) DMA2_Stream3_BASE)
+#define DMA2_Stream4 ((DMA_Stream_TypeDef *) DMA2_Stream4_BASE)
+#define DMA2_Stream5 ((DMA_Stream_TypeDef *) DMA2_Stream5_BASE)
+#define DMA2_Stream6 ((DMA_Stream_TypeDef *) DMA2_Stream6_BASE)
+#define DMA2_Stream7 ((DMA_Stream_TypeDef *) DMA2_Stream7_BASE)
+
+#define DMA1 ((DMA_TypeDef *) DMA1_BASE)
+#define DMA1_Stream0 ((DMA_Stream_TypeDef *) DMA1_Stream0_BASE)
+#define DMA1_Stream1 ((DMA_Stream_TypeDef *) DMA1_Stream1_BASE)
+#define DMA1_Stream2 ((DMA_Stream_TypeDef *) DMA1_Stream2_BASE)
+#define DMA1_Stream3 ((DMA_Stream_TypeDef *) DMA1_Stream3_BASE)
+#define DMA1_Stream4 ((DMA_Stream_TypeDef *) DMA1_Stream4_BASE)
+#define DMA1_Stream5 ((DMA_Stream_TypeDef *) DMA1_Stream5_BASE)
+#define DMA1_Stream6 ((DMA_Stream_TypeDef *) DMA1_Stream6_BASE)
+#define DMA1_Stream7 ((DMA_Stream_TypeDef *) DMA1_Stream7_BASE)
+
+
+#define DMAMUX1 ((DMAMUX_Channel_TypeDef *) DMAMUX1_BASE)
+#define DMAMUX1_Channel0 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel0_BASE)
+#define DMAMUX1_Channel1 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel1_BASE)
+#define DMAMUX1_Channel2 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel2_BASE)
+#define DMAMUX1_Channel3 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel3_BASE)
+#define DMAMUX1_Channel4 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel4_BASE)
+#define DMAMUX1_Channel5 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel5_BASE)
+#define DMAMUX1_Channel6 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel6_BASE)
+#define DMAMUX1_Channel7 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel7_BASE)
+#define DMAMUX1_Channel8 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel8_BASE)
+#define DMAMUX1_Channel9 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel9_BASE)
+#define DMAMUX1_Channel10 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel10_BASE)
+#define DMAMUX1_Channel11 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel11_BASE)
+#define DMAMUX1_Channel12 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel12_BASE)
+#define DMAMUX1_Channel13 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel13_BASE)
+#define DMAMUX1_Channel14 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel14_BASE)
+#define DMAMUX1_Channel15 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel15_BASE)
+
+#define DMAMUX1_RequestGenerator0 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator0_BASE)
+#define DMAMUX1_RequestGenerator1 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator1_BASE)
+#define DMAMUX1_RequestGenerator2 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator2_BASE)
+#define DMAMUX1_RequestGenerator3 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator3_BASE)
+#define DMAMUX1_RequestGenerator4 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator4_BASE)
+#define DMAMUX1_RequestGenerator5 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator5_BASE)
+#define DMAMUX1_RequestGenerator6 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator6_BASE)
+#define DMAMUX1_RequestGenerator7 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator7_BASE)
+
+#define DMAMUX1_ChannelStatus ((DMAMUX_ChannelStatus_TypeDef *) DMAMUX1_ChannelStatus_BASE)
+#define DMAMUX1_RequestGenStatus ((DMAMUX_RequestGenStatus_TypeDef *) DMAMUX1_RequestGenStatus_BASE)
+
+
+#define FMC_Bank1_R ((FMC_Bank1_TypeDef *) FMC_Bank1_R_BASE)
+#define FMC_Bank1E_R ((FMC_Bank1E_TypeDef *) FMC_Bank1E_R_BASE)
+#define FMC_Bank2_R ((FMC_Bank2_TypeDef *) FMC_Bank2_R_BASE)
+#define FMC_Bank3_R ((FMC_Bank3_TypeDef *) FMC_Bank3_R_BASE)
+#define FMC_Bank5_6_R ((FMC_Bank5_6_TypeDef *) FMC_Bank5_6_R_BASE)
+
+#define OCTOSPI1 ((OCTOSPI_TypeDef *) OCTOSPI1_R_BASE)
+#define DLYB_OCTOSPI1 ((DLYB_TypeDef *) DLYB_OCTOSPI1_BASE)
+#define OCTOSPI2 ((OCTOSPI_TypeDef *) OCTOSPI2_R_BASE)
+#define DLYB_OCTOSPI2 ((DLYB_TypeDef *) DLYB_OCTOSPI2_BASE)
+#define OCTOSPIM ((OCTOSPIM_TypeDef *) OCTOSPIM_BASE)
+
+#define SDMMC1 ((SDMMC_TypeDef *) SDMMC1_BASE)
+#define DLYB_SDMMC1 ((DLYB_TypeDef *) DLYB_SDMMC1_BASE)
+
+#define DBGMCU ((DBGMCU_TypeDef *) DBGMCU_BASE)
+
+#define HSEM ((HSEM_TypeDef *) HSEM_BASE)
+#define HSEM_COMMON ((HSEM_Common_TypeDef *) (HSEM_BASE + 0x100UL))
+
+#define LTDC ((LTDC_TypeDef *)LTDC_BASE)
+#define LTDC_Layer1 ((LTDC_Layer_TypeDef *)LTDC_Layer1_BASE)
+#define LTDC_Layer2 ((LTDC_Layer_TypeDef *)LTDC_Layer2_BASE)
+
+#define MDIOS ((MDIOS_TypeDef *) MDIOS_BASE)
+
+#define ETH ((ETH_TypeDef *)ETH_BASE)
+#define MDMA ((MDMA_TypeDef *)MDMA_BASE)
+#define MDMA_Channel0 ((MDMA_Channel_TypeDef *)MDMA_Channel0_BASE)
+#define MDMA_Channel1 ((MDMA_Channel_TypeDef *)MDMA_Channel1_BASE)
+#define MDMA_Channel2 ((MDMA_Channel_TypeDef *)MDMA_Channel2_BASE)
+#define MDMA_Channel3 ((MDMA_Channel_TypeDef *)MDMA_Channel3_BASE)
+#define MDMA_Channel4 ((MDMA_Channel_TypeDef *)MDMA_Channel4_BASE)
+#define MDMA_Channel5 ((MDMA_Channel_TypeDef *)MDMA_Channel5_BASE)
+#define MDMA_Channel6 ((MDMA_Channel_TypeDef *)MDMA_Channel6_BASE)
+#define MDMA_Channel7 ((MDMA_Channel_TypeDef *)MDMA_Channel7_BASE)
+#define MDMA_Channel8 ((MDMA_Channel_TypeDef *)MDMA_Channel8_BASE)
+#define MDMA_Channel9 ((MDMA_Channel_TypeDef *)MDMA_Channel9_BASE)
+#define MDMA_Channel10 ((MDMA_Channel_TypeDef *)MDMA_Channel10_BASE)
+#define MDMA_Channel11 ((MDMA_Channel_TypeDef *)MDMA_Channel11_BASE)
+#define MDMA_Channel12 ((MDMA_Channel_TypeDef *)MDMA_Channel12_BASE)
+#define MDMA_Channel13 ((MDMA_Channel_TypeDef *)MDMA_Channel13_BASE)
+#define MDMA_Channel14 ((MDMA_Channel_TypeDef *)MDMA_Channel14_BASE)
+#define MDMA_Channel15 ((MDMA_Channel_TypeDef *)MDMA_Channel15_BASE)
+
+
+#define USB1_OTG_HS ((USB_OTG_GlobalTypeDef *) USB1_OTG_HS_PERIPH_BASE)
+
+/* Legacy defines */
+#define USB_OTG_HS USB1_OTG_HS
+#define USB_OTG_HS_PERIPH_BASE USB1_OTG_HS_PERIPH_BASE
+
+/**
+ * @}
+ */
+
+/** @addtogroup Exported_constants
+ * @{
+ */
+
+ /** @addtogroup Peripheral_Registers_Bits_Definition
+ * @{
+ */
+
+/******************************************************************************/
+/* Peripheral Registers_Bits_Definition */
+/******************************************************************************/
+
+/******************************************************************************/
+/* */
+/* Analog to Digital Converter */
+/* */
+/******************************************************************************/
+/******************************* ADC VERSION ********************************/
+#define ADC_VER_V5_V90
+/******************** Bit definition for ADC_ISR register ********************/
+#define ADC_ISR_ADRDY_Pos (0U)
+#define ADC_ISR_ADRDY_Msk (0x1UL << ADC_ISR_ADRDY_Pos) /*!< 0x00000001 */
+#define ADC_ISR_ADRDY ADC_ISR_ADRDY_Msk /*!< ADC Ready (ADRDY) flag */
+#define ADC_ISR_EOSMP_Pos (1U)
+#define ADC_ISR_EOSMP_Msk (0x1UL << ADC_ISR_EOSMP_Pos) /*!< 0x00000002 */
+#define ADC_ISR_EOSMP ADC_ISR_EOSMP_Msk /*!< ADC End of Sampling flag */
+#define ADC_ISR_EOC_Pos (2U)
+#define ADC_ISR_EOC_Msk (0x1UL << ADC_ISR_EOC_Pos) /*!< 0x00000004 */
+#define ADC_ISR_EOC ADC_ISR_EOC_Msk /*!< ADC End of Regular Conversion flag */
+#define ADC_ISR_EOS_Pos (3U)
+#define ADC_ISR_EOS_Msk (0x1UL << ADC_ISR_EOS_Pos) /*!< 0x00000008 */
+#define ADC_ISR_EOS ADC_ISR_EOS_Msk /*!< ADC End of Regular sequence of Conversions flag */
+#define ADC_ISR_OVR_Pos (4U)
+#define ADC_ISR_OVR_Msk (0x1UL << ADC_ISR_OVR_Pos) /*!< 0x00000010 */
+#define ADC_ISR_OVR ADC_ISR_OVR_Msk /*!< ADC overrun flag */
+#define ADC_ISR_JEOC_Pos (5U)
+#define ADC_ISR_JEOC_Msk (0x1UL << ADC_ISR_JEOC_Pos) /*!< 0x00000020 */
+#define ADC_ISR_JEOC ADC_ISR_JEOC_Msk /*!< ADC End of Injected Conversion flag */
+#define ADC_ISR_JEOS_Pos (6U)
+#define ADC_ISR_JEOS_Msk (0x1UL << ADC_ISR_JEOS_Pos) /*!< 0x00000040 */
+#define ADC_ISR_JEOS ADC_ISR_JEOS_Msk /*!< ADC End of Injected sequence of Conversions flag */
+#define ADC_ISR_AWD1_Pos (7U)
+#define ADC_ISR_AWD1_Msk (0x1UL << ADC_ISR_AWD1_Pos) /*!< 0x00000080 */
+#define ADC_ISR_AWD1 ADC_ISR_AWD1_Msk /*!< ADC Analog watchdog 1 flag */
+#define ADC_ISR_AWD2_Pos (8U)
+#define ADC_ISR_AWD2_Msk (0x1UL << ADC_ISR_AWD2_Pos) /*!< 0x00000100 */
+#define ADC_ISR_AWD2 ADC_ISR_AWD2_Msk /*!< ADC Analog watchdog 2 flag */
+#define ADC_ISR_AWD3_Pos (9U)
+#define ADC_ISR_AWD3_Msk (0x1UL << ADC_ISR_AWD3_Pos) /*!< 0x00000200 */
+#define ADC_ISR_AWD3 ADC_ISR_AWD3_Msk /*!< ADC Analog watchdog 3 flag */
+#define ADC_ISR_JQOVF_Pos (10U)
+#define ADC_ISR_JQOVF_Msk (0x1UL << ADC_ISR_JQOVF_Pos) /*!< 0x00000400 */
+#define ADC_ISR_JQOVF ADC_ISR_JQOVF_Msk /*!< ADC Injected Context Queue Overflow flag */
+
+/******************** Bit definition for ADC_IER register ********************/
+#define ADC_IER_ADRDYIE_Pos (0U)
+#define ADC_IER_ADRDYIE_Msk (0x1UL << ADC_IER_ADRDYIE_Pos) /*!< 0x00000001 */
+#define ADC_IER_ADRDYIE ADC_IER_ADRDYIE_Msk /*!< ADC Ready (ADRDY) interrupt source */
+#define ADC_IER_EOSMPIE_Pos (1U)
+#define ADC_IER_EOSMPIE_Msk (0x1UL << ADC_IER_EOSMPIE_Pos) /*!< 0x00000002 */
+#define ADC_IER_EOSMPIE ADC_IER_EOSMPIE_Msk /*!< ADC End of Sampling interrupt source */
+#define ADC_IER_EOCIE_Pos (2U)
+#define ADC_IER_EOCIE_Msk (0x1UL << ADC_IER_EOCIE_Pos) /*!< 0x00000004 */
+#define ADC_IER_EOCIE ADC_IER_EOCIE_Msk /*!< ADC End of Regular Conversion interrupt source */
+#define ADC_IER_EOSIE_Pos (3U)
+#define ADC_IER_EOSIE_Msk (0x1UL << ADC_IER_EOSIE_Pos) /*!< 0x00000008 */
+#define ADC_IER_EOSIE ADC_IER_EOSIE_Msk /*!< ADC End of Regular sequence of Conversions interrupt source */
+#define ADC_IER_OVRIE_Pos (4U)
+#define ADC_IER_OVRIE_Msk (0x1UL << ADC_IER_OVRIE_Pos) /*!< 0x00000010 */
+#define ADC_IER_OVRIE ADC_IER_OVRIE_Msk /*!< ADC overrun interrupt source */
+#define ADC_IER_JEOCIE_Pos (5U)
+#define ADC_IER_JEOCIE_Msk (0x1UL << ADC_IER_JEOCIE_Pos) /*!< 0x00000020 */
+#define ADC_IER_JEOCIE ADC_IER_JEOCIE_Msk /*!< ADC End of Injected Conversion interrupt source */
+#define ADC_IER_JEOSIE_Pos (6U)
+#define ADC_IER_JEOSIE_Msk (0x1UL << ADC_IER_JEOSIE_Pos) /*!< 0x00000040 */
+#define ADC_IER_JEOSIE ADC_IER_JEOSIE_Msk /*!< ADC End of Injected sequence of Conversions interrupt source */
+#define ADC_IER_AWD1IE_Pos (7U)
+#define ADC_IER_AWD1IE_Msk (0x1UL << ADC_IER_AWD1IE_Pos) /*!< 0x00000080 */
+#define ADC_IER_AWD1IE ADC_IER_AWD1IE_Msk /*!< ADC Analog watchdog 1 interrupt source */
+#define ADC_IER_AWD2IE_Pos (8U)
+#define ADC_IER_AWD2IE_Msk (0x1UL << ADC_IER_AWD2IE_Pos) /*!< 0x00000100 */
+#define ADC_IER_AWD2IE ADC_IER_AWD2IE_Msk /*!< ADC Analog watchdog 2 interrupt source */
+#define ADC_IER_AWD3IE_Pos (9U)
+#define ADC_IER_AWD3IE_Msk (0x1UL << ADC_IER_AWD3IE_Pos) /*!< 0x00000200 */
+#define ADC_IER_AWD3IE ADC_IER_AWD3IE_Msk /*!< ADC Analog watchdog 3 interrupt source */
+#define ADC_IER_JQOVFIE_Pos (10U)
+#define ADC_IER_JQOVFIE_Msk (0x1UL << ADC_IER_JQOVFIE_Pos) /*!< 0x00000400 */
+#define ADC_IER_JQOVFIE ADC_IER_JQOVFIE_Msk /*!< ADC Injected Context Queue Overflow interrupt source */
+
+/******************** Bit definition for ADC_CR register ********************/
+#define ADC_CR_ADEN_Pos (0U)
+#define ADC_CR_ADEN_Msk (0x1UL << ADC_CR_ADEN_Pos) /*!< 0x00000001 */
+#define ADC_CR_ADEN ADC_CR_ADEN_Msk /*!< ADC Enable control */
+#define ADC_CR_ADDIS_Pos (1U)
+#define ADC_CR_ADDIS_Msk (0x1UL << ADC_CR_ADDIS_Pos) /*!< 0x00000002 */
+#define ADC_CR_ADDIS ADC_CR_ADDIS_Msk /*!< ADC Disable command */
+#define ADC_CR_ADSTART_Pos (2U)
+#define ADC_CR_ADSTART_Msk (0x1UL << ADC_CR_ADSTART_Pos) /*!< 0x00000004 */
+#define ADC_CR_ADSTART ADC_CR_ADSTART_Msk /*!< ADC Start of Regular conversion */
+#define ADC_CR_JADSTART_Pos (3U)
+#define ADC_CR_JADSTART_Msk (0x1UL << ADC_CR_JADSTART_Pos) /*!< 0x00000008 */
+#define ADC_CR_JADSTART ADC_CR_JADSTART_Msk /*!< ADC Start of injected conversion */
+#define ADC_CR_ADSTP_Pos (4U)
+#define ADC_CR_ADSTP_Msk (0x1UL << ADC_CR_ADSTP_Pos) /*!< 0x00000010 */
+#define ADC_CR_ADSTP ADC_CR_ADSTP_Msk /*!< ADC Stop of Regular conversion */
+#define ADC_CR_JADSTP_Pos (5U)
+#define ADC_CR_JADSTP_Msk (0x1UL << ADC_CR_JADSTP_Pos) /*!< 0x00000020 */
+#define ADC_CR_JADSTP ADC_CR_JADSTP_Msk /*!< ADC Stop of injected conversion */
+#define ADC_CR_BOOST_Pos (8U)
+#define ADC_CR_BOOST_Msk (0x3UL << ADC_CR_BOOST_Pos) /*!< 0x00000300 */
+#define ADC_CR_BOOST ADC_CR_BOOST_Msk /*!< ADC Boost Mode configuration */
+#define ADC_CR_BOOST_0 (0x1UL << ADC_CR_BOOST_Pos) /*!< 0x00000100 */
+#define ADC_CR_BOOST_1 (0x2UL << ADC_CR_BOOST_Pos) /*!< 0x00000200 */
+#define ADC_CR_ADCALLIN_Pos (16U)
+#define ADC_CR_ADCALLIN_Msk (0x1UL << ADC_CR_ADCALLIN_Pos) /*!< 0x00010000 */
+#define ADC_CR_ADCALLIN ADC_CR_ADCALLIN_Msk /*!< ADC Linearity calibration */
+#define ADC_CR_LINCALRDYW1_Pos (22U)
+#define ADC_CR_LINCALRDYW1_Msk (0x1UL << ADC_CR_LINCALRDYW1_Pos) /*!< 0x00400000 */
+#define ADC_CR_LINCALRDYW1 ADC_CR_LINCALRDYW1_Msk /*!< ADC Linearity calibration ready Word 1 */
+#define ADC_CR_LINCALRDYW2_Pos (23U)
+#define ADC_CR_LINCALRDYW2_Msk (0x1UL << ADC_CR_LINCALRDYW2_Pos) /*!< 0x00800000 */
+#define ADC_CR_LINCALRDYW2 ADC_CR_LINCALRDYW2_Msk /*!< ADC Linearity calibration ready Word 2 */
+#define ADC_CR_LINCALRDYW3_Pos (24U)
+#define ADC_CR_LINCALRDYW3_Msk (0x1UL << ADC_CR_LINCALRDYW3_Pos) /*!< 0x01000000 */
+#define ADC_CR_LINCALRDYW3 ADC_CR_LINCALRDYW3_Msk /*!< ADC Linearity calibration ready Word 3 */
+#define ADC_CR_LINCALRDYW4_Pos (25U)
+#define ADC_CR_LINCALRDYW4_Msk (0x1UL << ADC_CR_LINCALRDYW4_Pos) /*!< 0x02000000 */
+#define ADC_CR_LINCALRDYW4 ADC_CR_LINCALRDYW4_Msk /*!< ADC Linearity calibration ready Word 4 */
+#define ADC_CR_LINCALRDYW5_Pos (26U)
+#define ADC_CR_LINCALRDYW5_Msk (0x1UL << ADC_CR_LINCALRDYW5_Pos) /*!< 0x04000000 */
+#define ADC_CR_LINCALRDYW5 ADC_CR_LINCALRDYW5_Msk /*!< ADC Linearity calibration ready Word 5 */
+#define ADC_CR_LINCALRDYW6_Pos (27U)
+#define ADC_CR_LINCALRDYW6_Msk (0x1UL << ADC_CR_LINCALRDYW6_Pos) /*!< 0x08000000 */
+#define ADC_CR_LINCALRDYW6 ADC_CR_LINCALRDYW6_Msk /*!< ADC Linearity calibration ready Word 6 */
+#define ADC_CR_ADVREGEN_Pos (28U)
+#define ADC_CR_ADVREGEN_Msk (0x1UL << ADC_CR_ADVREGEN_Pos) /*!< 0x10000000 */
+#define ADC_CR_ADVREGEN ADC_CR_ADVREGEN_Msk /*!< ADC Voltage regulator Enable */
+#define ADC_CR_DEEPPWD_Pos (29U)
+#define ADC_CR_DEEPPWD_Msk (0x1UL << ADC_CR_DEEPPWD_Pos) /*!< 0x20000000 */
+#define ADC_CR_DEEPPWD ADC_CR_DEEPPWD_Msk /*!< ADC Deep power down Enable */
+#define ADC_CR_ADCALDIF_Pos (30U)
+#define ADC_CR_ADCALDIF_Msk (0x1UL << ADC_CR_ADCALDIF_Pos) /*!< 0x40000000 */
+#define ADC_CR_ADCALDIF ADC_CR_ADCALDIF_Msk /*!< ADC Differential Mode for calibration */
+#define ADC_CR_ADCAL_Pos (31U)
+#define ADC_CR_ADCAL_Msk (0x1UL << ADC_CR_ADCAL_Pos) /*!< 0x80000000 */
+#define ADC_CR_ADCAL ADC_CR_ADCAL_Msk /*!< ADC Calibration */
+
+/******************** Bit definition for ADC_CFGR register ********************/
+#define ADC_CFGR_DMNGT_Pos (0U)
+#define ADC_CFGR_DMNGT_Msk (0x3UL << ADC_CFGR_DMNGT_Pos) /*!< 0x00000003 */
+#define ADC_CFGR_DMNGT ADC_CFGR_DMNGT_Msk /*!< ADC Data Management configuration */
+#define ADC_CFGR_DMNGT_0 (0x1UL << ADC_CFGR_DMNGT_Pos) /*!< 0x00000001 */
+#define ADC_CFGR_DMNGT_1 (0x2UL << ADC_CFGR_DMNGT_Pos) /*!< 0x00000002 */
+
+#define ADC_CFGR_RES_Pos (2U)
+#define ADC_CFGR_RES_Msk (0x7UL << ADC_CFGR_RES_Pos) /*!< 0x0000001C */
+#define ADC_CFGR_RES ADC_CFGR_RES_Msk /*!< ADC Data resolution */
+#define ADC_CFGR_RES_0 (0x1UL << ADC_CFGR_RES_Pos) /*!< 0x00000004 */
+#define ADC_CFGR_RES_1 (0x2UL << ADC_CFGR_RES_Pos) /*!< 0x00000008 */
+#define ADC_CFGR_RES_2 (0x4UL << ADC_CFGR_RES_Pos) /*!< 0x00000010 */
+
+#define ADC_CFGR_EXTSEL_Pos (5U)
+#define ADC_CFGR_EXTSEL_Msk (0x1FUL << ADC_CFGR_EXTSEL_Pos) /*!< 0x000003E0 */
+#define ADC_CFGR_EXTSEL ADC_CFGR_EXTSEL_Msk /*!< ADC External trigger selection for regular group */
+#define ADC_CFGR_EXTSEL_0 (0x01UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000020 */
+#define ADC_CFGR_EXTSEL_1 (0x02UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000040 */
+#define ADC_CFGR_EXTSEL_2 (0x04UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000080 */
+#define ADC_CFGR_EXTSEL_3 (0x08UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000100 */
+#define ADC_CFGR_EXTSEL_4 (0x10UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000200 */
+
+#define ADC_CFGR_EXTEN_Pos (10U)
+#define ADC_CFGR_EXTEN_Msk (0x3UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000C00 */
+#define ADC_CFGR_EXTEN ADC_CFGR_EXTEN_Msk /*!< ADC External trigger enable and polarity selection for regular channels */
+#define ADC_CFGR_EXTEN_0 (0x1UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000400 */
+#define ADC_CFGR_EXTEN_1 (0x2UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000800 */
+
+#define ADC_CFGR_OVRMOD_Pos (12U)
+#define ADC_CFGR_OVRMOD_Msk (0x1UL << ADC_CFGR_OVRMOD_Pos) /*!< 0x00001000 */
+#define ADC_CFGR_OVRMOD ADC_CFGR_OVRMOD_Msk /*!< ADC overrun mode */
+#define ADC_CFGR_CONT_Pos (13U)
+#define ADC_CFGR_CONT_Msk (0x1UL << ADC_CFGR_CONT_Pos) /*!< 0x00002000 */
+#define ADC_CFGR_CONT ADC_CFGR_CONT_Msk /*!< ADC Single/continuous conversion mode for regular conversion */
+#define ADC_CFGR_AUTDLY_Pos (14U)
+#define ADC_CFGR_AUTDLY_Msk (0x1UL << ADC_CFGR_AUTDLY_Pos) /*!< 0x00004000 */
+#define ADC_CFGR_AUTDLY ADC_CFGR_AUTDLY_Msk /*!< ADC Delayed conversion mode */
+
+#define ADC_CFGR_DISCEN_Pos (16U)
+#define ADC_CFGR_DISCEN_Msk (0x1UL << ADC_CFGR_DISCEN_Pos) /*!< 0x00010000 */
+#define ADC_CFGR_DISCEN ADC_CFGR_DISCEN_Msk /*!< ADC Discontinuous mode for regular channels */
+
+#define ADC_CFGR_DISCNUM_Pos (17U)
+#define ADC_CFGR_DISCNUM_Msk (0x7UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x000E0000 */
+#define ADC_CFGR_DISCNUM ADC_CFGR_DISCNUM_Msk /*!< ADC Discontinuous mode channel count */
+#define ADC_CFGR_DISCNUM_0 (0x1UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00020000 */
+#define ADC_CFGR_DISCNUM_1 (0x2UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00040000 */
+#define ADC_CFGR_DISCNUM_2 (0x4UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00080000 */
+
+#define ADC_CFGR_JDISCEN_Pos (20U)
+#define ADC_CFGR_JDISCEN_Msk (0x1UL << ADC_CFGR_JDISCEN_Pos) /*!< 0x00100000 */
+#define ADC_CFGR_JDISCEN ADC_CFGR_JDISCEN_Msk /*!< ADC Discontinuous mode on injected channels */
+#define ADC_CFGR_JQM_Pos (21U)
+#define ADC_CFGR_JQM_Msk (0x1UL << ADC_CFGR_JQM_Pos) /*!< 0x00200000 */
+#define ADC_CFGR_JQM ADC_CFGR_JQM_Msk /*!< ADC JSQR Queue mode */
+#define ADC_CFGR_AWD1SGL_Pos (22U)
+#define ADC_CFGR_AWD1SGL_Msk (0x1UL << ADC_CFGR_AWD1SGL_Pos) /*!< 0x00400000 */
+#define ADC_CFGR_AWD1SGL ADC_CFGR_AWD1SGL_Msk /*!< Enable the watchdog 1 on a single channel or on all channels */
+#define ADC_CFGR_AWD1EN_Pos (23U)
+#define ADC_CFGR_AWD1EN_Msk (0x1UL << ADC_CFGR_AWD1EN_Pos) /*!< 0x00800000 */
+#define ADC_CFGR_AWD1EN ADC_CFGR_AWD1EN_Msk /*!< ADC Analog watchdog 1 enable on regular Channels */
+#define ADC_CFGR_JAWD1EN_Pos (24U)
+#define ADC_CFGR_JAWD1EN_Msk (0x1UL << ADC_CFGR_JAWD1EN_Pos) /*!< 0x01000000 */
+#define ADC_CFGR_JAWD1EN ADC_CFGR_JAWD1EN_Msk /*!< ADC Analog watchdog 1 enable on injected Channels */
+#define ADC_CFGR_JAUTO_Pos (25U)
+#define ADC_CFGR_JAUTO_Msk (0x1UL << ADC_CFGR_JAUTO_Pos) /*!< 0x02000000 */
+#define ADC_CFGR_JAUTO ADC_CFGR_JAUTO_Msk /*!< ADC Automatic injected group conversion */
+
+#define ADC_CFGR_AWD1CH_Pos (26U)
+#define ADC_CFGR_AWD1CH_Msk (0x1FUL << ADC_CFGR_AWD1CH_Pos) /*!< 0x7C000000 */
+#define ADC_CFGR_AWD1CH ADC_CFGR_AWD1CH_Msk /*!< ADC Analog watchdog 1 Channel selection */
+#define ADC_CFGR_AWD1CH_0 (0x01UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x04000000 */
+#define ADC_CFGR_AWD1CH_1 (0x02UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x08000000 */
+#define ADC_CFGR_AWD1CH_2 (0x04UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x10000000 */
+#define ADC_CFGR_AWD1CH_3 (0x08UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x20000000 */
+#define ADC_CFGR_AWD1CH_4 (0x10UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x40000000 */
+
+#define ADC_CFGR_JQDIS_Pos (31U)
+#define ADC_CFGR_JQDIS_Msk (0x1UL << ADC_CFGR_JQDIS_Pos) /*!< 0x80000000 */
+#define ADC_CFGR_JQDIS ADC_CFGR_JQDIS_Msk /*!< ADC Injected queue disable */
+
+#define ADC3_CFGR_DMAEN_Pos (0U)
+#define ADC3_CFGR_DMAEN_Msk (0x1UL << ADC3_CFGR_DMAEN_Pos) /*!< 0x00000001 */
+#define ADC3_CFGR_DMAEN ADC3_CFGR_DMAEN_Msk /*!< ADC DMA transfer enable */
+#define ADC3_CFGR_DMACFG_Pos (1U)
+#define ADC3_CFGR_DMACFG_Msk (0x1UL << ADC3_CFGR_DMACFG_Pos) /*!< 0x00000002 */
+#define ADC3_CFGR_DMACFG ADC3_CFGR_DMACFG_Msk /*!< ADC DMA transfer configuration */
+
+#define ADC3_CFGR_RES_Pos (3U)
+#define ADC3_CFGR_RES_Msk (0x3UL << ADC3_CFGR_RES_Pos) /*!< 0x00000018 */
+#define ADC3_CFGR_RES ADC3_CFGR_RES_Msk /*!< ADC data resolution */
+#define ADC3_CFGR_RES_0 (0x1UL << ADC3_CFGR_RES_Pos) /*!< 0x00000008 */
+#define ADC3_CFGR_RES_1 (0x2UL << ADC3_CFGR_RES_Pos) /*!< 0x00000010 */
+
+#define ADC3_CFGR_ALIGN_Pos (15U)
+#define ADC3_CFGR_ALIGN_Msk (0x1UL << ADC3_CFGR_ALIGN_Pos) /*!< 0x00008000 */
+#define ADC3_CFGR_ALIGN ADC3_CFGR_ALIGN_Msk /*!< ADC data alignement */
+/******************** Bit definition for ADC_CFGR2 register ********************/
+#define ADC_CFGR2_ROVSE_Pos (0U)
+#define ADC_CFGR2_ROVSE_Msk (0x1UL << ADC_CFGR2_ROVSE_Pos) /*!< 0x00000001 */
+#define ADC_CFGR2_ROVSE ADC_CFGR2_ROVSE_Msk /*!< ADC Regular group oversampler enable */
+#define ADC_CFGR2_JOVSE_Pos (1U)
+#define ADC_CFGR2_JOVSE_Msk (0x1UL << ADC_CFGR2_JOVSE_Pos) /*!< 0x00000002 */
+#define ADC_CFGR2_JOVSE ADC_CFGR2_JOVSE_Msk /*!< ADC Injected group oversampler enable */
+
+#define ADC_CFGR2_OVSS_Pos (5U)
+#define ADC_CFGR2_OVSS_Msk (0xFUL << ADC_CFGR2_OVSS_Pos) /*!< 0x000001E0 */
+#define ADC_CFGR2_OVSS ADC_CFGR2_OVSS_Msk /*!< ADC Regular Oversampling shift */
+#define ADC_CFGR2_OVSS_0 (0x1UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000020 */
+#define ADC_CFGR2_OVSS_1 (0x2UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000040 */
+#define ADC_CFGR2_OVSS_2 (0x4UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000080 */
+#define ADC_CFGR2_OVSS_3 (0x8UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000100 */
+
+#define ADC_CFGR2_TROVS_Pos (9U)
+#define ADC_CFGR2_TROVS_Msk (0x1UL << ADC_CFGR2_TROVS_Pos) /*!< 0x00000200 */
+#define ADC_CFGR2_TROVS ADC_CFGR2_TROVS_Msk /*!< ADC Triggered regular Oversampling */
+#define ADC_CFGR2_ROVSM_Pos (10U)
+#define ADC_CFGR2_ROVSM_Msk (0x1UL << ADC_CFGR2_ROVSM_Pos) /*!< 0x00000400 */
+#define ADC_CFGR2_ROVSM ADC_CFGR2_ROVSM_Msk /*!< ADC Regular oversampling mode */
+
+#define ADC_CFGR2_RSHIFT1_Pos (11U)
+#define ADC_CFGR2_RSHIFT1_Msk (0x1UL << ADC_CFGR2_RSHIFT1_Pos) /*!< 0x00000800 */
+#define ADC_CFGR2_RSHIFT1 ADC_CFGR2_RSHIFT1_Msk /*!< ADC Right-shift data after Offset 1 correction */
+#define ADC_CFGR2_RSHIFT2_Pos (12U)
+#define ADC_CFGR2_RSHIFT2_Msk (0x1UL << ADC_CFGR2_RSHIFT2_Pos) /*!< 0x00001000 */
+#define ADC_CFGR2_RSHIFT2 ADC_CFGR2_RSHIFT2_Msk /*!< ADC Right-shift data after Offset 2 correction */
+#define ADC_CFGR2_RSHIFT3_Pos (13U)
+#define ADC_CFGR2_RSHIFT3_Msk (0x1UL << ADC_CFGR2_RSHIFT3_Pos) /*!< 0x00002000 */
+#define ADC_CFGR2_RSHIFT3 ADC_CFGR2_RSHIFT3_Msk /*!< ADC Right-shift data after Offset 3 correction */
+#define ADC_CFGR2_RSHIFT4_Pos (14U)
+#define ADC_CFGR2_RSHIFT4_Msk (0x1UL << ADC_CFGR2_RSHIFT4_Pos) /*!< 0x00004000 */
+#define ADC_CFGR2_RSHIFT4 ADC_CFGR2_RSHIFT4_Msk /*!< ADC Right-shift data after Offset 4 correction */
+
+#define ADC_CFGR2_OVSR_Pos (16U)
+#define ADC_CFGR2_OVSR_Msk (0x3FFUL << ADC_CFGR2_OVSR_Pos) /*!< 0x03FF0000 */
+#define ADC_CFGR2_OVSR ADC_CFGR2_OVSR_Msk /*!< ADC oversampling Ratio */
+#define ADC_CFGR2_OVSR_0 (0x001UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00010000 */
+#define ADC_CFGR2_OVSR_1 (0x002UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00020000 */
+#define ADC_CFGR2_OVSR_2 (0x004UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00040000 */
+#define ADC_CFGR2_OVSR_3 (0x008UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00080000 */
+#define ADC_CFGR2_OVSR_4 (0x010UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00100000 */
+#define ADC_CFGR2_OVSR_5 (0x020UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00200000 */
+#define ADC_CFGR2_OVSR_6 (0x040UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00400000 */
+#define ADC_CFGR2_OVSR_7 (0x080UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00800000 */
+#define ADC_CFGR2_OVSR_8 (0x100UL << ADC_CFGR2_OVSR_Pos) /*!< 0x01000000 */
+#define ADC_CFGR2_OVSR_9 (0x200UL << ADC_CFGR2_OVSR_Pos) /*!< 0x02000000 */
+
+#define ADC_CFGR2_LSHIFT_Pos (28U)
+#define ADC_CFGR2_LSHIFT_Msk (0xFUL << ADC_CFGR2_LSHIFT_Pos) /*!< 0xF0000000 */
+#define ADC_CFGR2_LSHIFT ADC_CFGR2_LSHIFT_Msk /*!< ADC Left shift factor */
+#define ADC_CFGR2_LSHIFT_0 (0x1UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x10000000 */
+#define ADC_CFGR2_LSHIFT_1 (0x2UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x20000000 */
+#define ADC_CFGR2_LSHIFT_2 (0x4UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x40000000 */
+#define ADC_CFGR2_LSHIFT_3 (0x8UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x80000000 */
+
+#define ADC3_CFGR2_OVSR_Pos (2U)
+#define ADC3_CFGR2_OVSR_Msk (0x7UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x0000001C */
+#define ADC3_CFGR2_OVSR ADC3_CFGR2_OVSR_Msk /*!< ADC oversampling ratio */
+#define ADC3_CFGR2_OVSR_0 (0x1UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x00000004 */
+#define ADC3_CFGR2_OVSR_1 (0x2UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x00000008 */
+#define ADC3_CFGR2_OVSR_2 (0x4UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x00000010 */
+
+#define ADC3_CFGR2_SWTRIG_Pos (25U)
+#define ADC3_CFGR2_SWTRIG_Msk (0x1UL << ADC3_CFGR2_SWTRIG_Pos) /*!< 0x02000000 */
+#define ADC3_CFGR2_SWTRIG ADC3_CFGR2_SWTRIG_Msk /*!< ADC Software Trigger Bit for Sample time control trigger mode */
+#define ADC3_CFGR2_BULB_Pos (26U)
+#define ADC3_CFGR2_BULB_Msk (0x1UL << ADC3_CFGR2_BULB_Pos) /*!< 0x04000000 */
+#define ADC3_CFGR2_BULB ADC3_CFGR2_BULB_Msk /*!< ADC Bulb sampling mode */
+#define ADC3_CFGR2_SMPTRIG_Pos (27U)
+#define ADC3_CFGR2_SMPTRIG_Msk (0x1UL << ADC3_CFGR2_SMPTRIG_Pos) /*!< 0x08000000 */
+#define ADC3_CFGR2_SMPTRIG ADC3_CFGR2_SMPTRIG_Msk /*!< ADC Sample Time Control Trigger mode */
+/******************** Bit definition for ADC_SMPR1 register ********************/
+#define ADC_SMPR1_SMP0_Pos (0U)
+#define ADC_SMPR1_SMP0_Msk (0x7UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000007 */
+#define ADC_SMPR1_SMP0 ADC_SMPR1_SMP0_Msk /*!< ADC Channel 0 Sampling time selection */
+#define ADC_SMPR1_SMP0_0 (0x1UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000001 */
+#define ADC_SMPR1_SMP0_1 (0x2UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000002 */
+#define ADC_SMPR1_SMP0_2 (0x4UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000004 */
+
+#define ADC_SMPR1_SMP1_Pos (3U)
+#define ADC_SMPR1_SMP1_Msk (0x7UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000038 */
+#define ADC_SMPR1_SMP1 ADC_SMPR1_SMP1_Msk /*!< ADC Channel 1 Sampling time selection */
+#define ADC_SMPR1_SMP1_0 (0x1UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000008 */
+#define ADC_SMPR1_SMP1_1 (0x2UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000010 */
+#define ADC_SMPR1_SMP1_2 (0x4UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000020 */
+
+#define ADC_SMPR1_SMP2_Pos (6U)
+#define ADC_SMPR1_SMP2_Msk (0x7UL << ADC_SMPR1_SMP2_Pos) /*!< 0x000001C0 */
+#define ADC_SMPR1_SMP2 ADC_SMPR1_SMP2_Msk /*!< ADC Channel 2 Sampling time selection */
+#define ADC_SMPR1_SMP2_0 (0x1UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000040 */
+#define ADC_SMPR1_SMP2_1 (0x2UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000080 */
+#define ADC_SMPR1_SMP2_2 (0x4UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000100 */
+
+#define ADC_SMPR1_SMP3_Pos (9U)
+#define ADC_SMPR1_SMP3_Msk (0x7UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000E00 */
+#define ADC_SMPR1_SMP3 ADC_SMPR1_SMP3_Msk /*!< ADC Channel 3 Sampling time selection */
+#define ADC_SMPR1_SMP3_0 (0x1UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000200 */
+#define ADC_SMPR1_SMP3_1 (0x2UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000400 */
+#define ADC_SMPR1_SMP3_2 (0x4UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000800 */
+
+#define ADC_SMPR1_SMP4_Pos (12U)
+#define ADC_SMPR1_SMP4_Msk (0x7UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00007000 */
+#define ADC_SMPR1_SMP4 ADC_SMPR1_SMP4_Msk /*!< ADC Channel 4 Sampling time selection */
+#define ADC_SMPR1_SMP4_0 (0x1UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00001000 */
+#define ADC_SMPR1_SMP4_1 (0x2UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00002000 */
+#define ADC_SMPR1_SMP4_2 (0x4UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00004000 */
+
+#define ADC_SMPR1_SMP5_Pos (15U)
+#define ADC_SMPR1_SMP5_Msk (0x7UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00038000 */
+#define ADC_SMPR1_SMP5 ADC_SMPR1_SMP5_Msk /*!< ADC Channel 5 Sampling time selection */
+#define ADC_SMPR1_SMP5_0 (0x1UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00008000 */
+#define ADC_SMPR1_SMP5_1 (0x2UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00010000 */
+#define ADC_SMPR1_SMP5_2 (0x4UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00020000 */
+
+#define ADC_SMPR1_SMP6_Pos (18U)
+#define ADC_SMPR1_SMP6_Msk (0x7UL << ADC_SMPR1_SMP6_Pos) /*!< 0x001C0000 */
+#define ADC_SMPR1_SMP6 ADC_SMPR1_SMP6_Msk /*!< ADC Channel 6 Sampling time selection */
+#define ADC_SMPR1_SMP6_0 (0x1UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00040000 */
+#define ADC_SMPR1_SMP6_1 (0x2UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00080000 */
+#define ADC_SMPR1_SMP6_2 (0x4UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00100000 */
+
+#define ADC_SMPR1_SMP7_Pos (21U)
+#define ADC_SMPR1_SMP7_Msk (0x7UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00E00000 */
+#define ADC_SMPR1_SMP7 ADC_SMPR1_SMP7_Msk /*!< ADC Channel 7 Sampling time selection */
+#define ADC_SMPR1_SMP7_0 (0x1UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00200000 */
+#define ADC_SMPR1_SMP7_1 (0x2UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00400000 */
+#define ADC_SMPR1_SMP7_2 (0x4UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00800000 */
+
+#define ADC_SMPR1_SMP8_Pos (24U)
+#define ADC_SMPR1_SMP8_Msk (0x7UL << ADC_SMPR1_SMP8_Pos) /*!< 0x07000000 */
+#define ADC_SMPR1_SMP8 ADC_SMPR1_SMP8_Msk /*!< ADC Channel 8 Sampling time selection */
+#define ADC_SMPR1_SMP8_0 (0x1UL << ADC_SMPR1_SMP8_Pos) /*!< 0x01000000 */
+#define ADC_SMPR1_SMP8_1 (0x2UL << ADC_SMPR1_SMP8_Pos) /*!< 0x02000000 */
+#define ADC_SMPR1_SMP8_2 (0x4UL << ADC_SMPR1_SMP8_Pos) /*!< 0x04000000 */
+
+#define ADC_SMPR1_SMP9_Pos (27U)
+#define ADC_SMPR1_SMP9_Msk (0x7UL << ADC_SMPR1_SMP9_Pos) /*!< 0x38000000 */
+#define ADC_SMPR1_SMP9 ADC_SMPR1_SMP9_Msk /*!< ADC Channel 9 Sampling time selection */
+#define ADC_SMPR1_SMP9_0 (0x1UL << ADC_SMPR1_SMP9_Pos) /*!< 0x08000000 */
+#define ADC_SMPR1_SMP9_1 (0x2UL << ADC_SMPR1_SMP9_Pos) /*!< 0x10000000 */
+#define ADC_SMPR1_SMP9_2 (0x4UL << ADC_SMPR1_SMP9_Pos) /*!< 0x20000000 */
+
+/******************** Bit definition for ADC_SMPR2 register ********************/
+#define ADC_SMPR2_SMP10_Pos (0U)
+#define ADC_SMPR2_SMP10_Msk (0x7UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000007 */
+#define ADC_SMPR2_SMP10 ADC_SMPR2_SMP10_Msk /*!< ADC Channel 10 Sampling time selection */
+#define ADC_SMPR2_SMP10_0 (0x1UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000001 */
+#define ADC_SMPR2_SMP10_1 (0x2UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000002 */
+#define ADC_SMPR2_SMP10_2 (0x4UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000004 */
+
+#define ADC_SMPR2_SMP11_Pos (3U)
+#define ADC_SMPR2_SMP11_Msk (0x7UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000038 */
+#define ADC_SMPR2_SMP11 ADC_SMPR2_SMP11_Msk /*!< ADC Channel 11 Sampling time selection */
+#define ADC_SMPR2_SMP11_0 (0x1UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000008 */
+#define ADC_SMPR2_SMP11_1 (0x2UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000010 */
+#define ADC_SMPR2_SMP11_2 (0x4UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000020 */
+
+#define ADC_SMPR2_SMP12_Pos (6U)
+#define ADC_SMPR2_SMP12_Msk (0x7UL << ADC_SMPR2_SMP12_Pos) /*!< 0x000001C0 */
+#define ADC_SMPR2_SMP12 ADC_SMPR2_SMP12_Msk /*!< ADC Channel 12 Sampling time selection */
+#define ADC_SMPR2_SMP12_0 (0x1UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000040 */
+#define ADC_SMPR2_SMP12_1 (0x2UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000080 */
+#define ADC_SMPR2_SMP12_2 (0x4UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000100 */
+
+#define ADC_SMPR2_SMP13_Pos (9U)
+#define ADC_SMPR2_SMP13_Msk (0x7UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000E00 */
+#define ADC_SMPR2_SMP13 ADC_SMPR2_SMP13_Msk /*!< ADC Channel 13 Sampling time selection */
+#define ADC_SMPR2_SMP13_0 (0x1UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000200 */
+#define ADC_SMPR2_SMP13_1 (0x2UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000400 */
+#define ADC_SMPR2_SMP13_2 (0x4UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000800 */
+
+#define ADC_SMPR2_SMP14_Pos (12U)
+#define ADC_SMPR2_SMP14_Msk (0x7UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00007000 */
+#define ADC_SMPR2_SMP14 ADC_SMPR2_SMP14_Msk /*!< ADC Channel 14 Sampling time selection */
+#define ADC_SMPR2_SMP14_0 (0x1UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00001000 */
+#define ADC_SMPR2_SMP14_1 (0x2UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00002000 */
+#define ADC_SMPR2_SMP14_2 (0x4UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00004000 */
+
+#define ADC_SMPR2_SMP15_Pos (15U)
+#define ADC_SMPR2_SMP15_Msk (0x7UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00038000 */
+#define ADC_SMPR2_SMP15 ADC_SMPR2_SMP15_Msk /*!< ADC Channel 15 Sampling time selection */
+#define ADC_SMPR2_SMP15_0 (0x1UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00008000 */
+#define ADC_SMPR2_SMP15_1 (0x2UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00010000 */
+#define ADC_SMPR2_SMP15_2 (0x4UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00020000 */
+
+#define ADC_SMPR2_SMP16_Pos (18U)
+#define ADC_SMPR2_SMP16_Msk (0x7UL << ADC_SMPR2_SMP16_Pos) /*!< 0x001C0000 */
+#define ADC_SMPR2_SMP16 ADC_SMPR2_SMP16_Msk /*!< ADC Channel 16 Sampling time selection */
+#define ADC_SMPR2_SMP16_0 (0x1UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00040000 */
+#define ADC_SMPR2_SMP16_1 (0x2UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00080000 */
+#define ADC_SMPR2_SMP16_2 (0x4UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00100000 */
+
+#define ADC_SMPR2_SMP17_Pos (21U)
+#define ADC_SMPR2_SMP17_Msk (0x7UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00E00000 */
+#define ADC_SMPR2_SMP17 ADC_SMPR2_SMP17_Msk /*!< ADC Channel 17 Sampling time selection */
+#define ADC_SMPR2_SMP17_0 (0x1UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00200000 */
+#define ADC_SMPR2_SMP17_1 (0x2UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00400000 */
+#define ADC_SMPR2_SMP17_2 (0x4UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00800000 */
+
+#define ADC_SMPR2_SMP18_Pos (24U)
+#define ADC_SMPR2_SMP18_Msk (0x7UL << ADC_SMPR2_SMP18_Pos) /*!< 0x07000000 */
+#define ADC_SMPR2_SMP18 ADC_SMPR2_SMP18_Msk /*!< ADC Channel 18 Sampling time selection */
+#define ADC_SMPR2_SMP18_0 (0x1UL << ADC_SMPR2_SMP18_Pos) /*!< 0x01000000 */
+#define ADC_SMPR2_SMP18_1 (0x2UL << ADC_SMPR2_SMP18_Pos) /*!< 0x02000000 */
+#define ADC_SMPR2_SMP18_2 (0x4UL << ADC_SMPR2_SMP18_Pos) /*!< 0x04000000 */
+
+#define ADC_SMPR2_SMP19_Pos (27U)
+#define ADC_SMPR2_SMP19_Msk (0x7UL << ADC_SMPR2_SMP19_Pos) /*!< 0x38000000 */
+#define ADC_SMPR2_SMP19 ADC_SMPR2_SMP19_Msk /*!< ADC Channel 19 Sampling time selection */
+#define ADC_SMPR2_SMP19_0 (0x1UL << ADC_SMPR2_SMP19_Pos) /*!< 0x08000000 */
+#define ADC_SMPR2_SMP19_1 (0x2UL << ADC_SMPR2_SMP19_Pos) /*!< 0x10000000 */
+#define ADC_SMPR2_SMP19_2 (0x4UL << ADC_SMPR2_SMP19_Pos) /*!< 0x20000000 */
+
+/******************** Bit definition for ADC_PCSEL register ********************/
+#define ADC_PCSEL_PCSEL_Pos (0U)
+#define ADC_PCSEL_PCSEL_Msk (0xFFFFFUL << ADC_PCSEL_PCSEL_Pos) /*!< 0x000FFFFF */
+#define ADC_PCSEL_PCSEL ADC_PCSEL_PCSEL_Msk /*!< ADC pre channel selection */
+#define ADC_PCSEL_PCSEL_0 (0x00001UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000001 */
+#define ADC_PCSEL_PCSEL_1 (0x00002UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000002 */
+#define ADC_PCSEL_PCSEL_2 (0x00004UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000004 */
+#define ADC_PCSEL_PCSEL_3 (0x00008UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000008 */
+#define ADC_PCSEL_PCSEL_4 (0x00010UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000010 */
+#define ADC_PCSEL_PCSEL_5 (0x00020UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000020 */
+#define ADC_PCSEL_PCSEL_6 (0x00040UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000040 */
+#define ADC_PCSEL_PCSEL_7 (0x00080UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000080 */
+#define ADC_PCSEL_PCSEL_8 (0x00100UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000100 */
+#define ADC_PCSEL_PCSEL_9 (0x00200UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000200 */
+#define ADC_PCSEL_PCSEL_10 (0x00400UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000400 */
+#define ADC_PCSEL_PCSEL_11 (0x00800UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000800 */
+#define ADC_PCSEL_PCSEL_12 (0x01000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00001000 */
+#define ADC_PCSEL_PCSEL_13 (0x02000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00002000 */
+#define ADC_PCSEL_PCSEL_14 (0x04000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00004000 */
+#define ADC_PCSEL_PCSEL_15 (0x08000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00008000 */
+#define ADC_PCSEL_PCSEL_16 (0x10000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00010000 */
+#define ADC_PCSEL_PCSEL_17 (0x20000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00020000 */
+#define ADC_PCSEL_PCSEL_18 (0x40000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00040000 */
+#define ADC_PCSEL_PCSEL_19 (0x80000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00080000 */
+
+/***************** Bit definition for ADC_LTR1, 2, 3 registers *****************/
+#define ADC_LTR_LT_Pos (0U)
+#define ADC_LTR_LT_Msk (0x3FFFFFFUL << ADC_LTR_LT_Pos) /*!< 0x03FFFFFF */
+#define ADC_LTR_LT ADC_LTR_LT_Msk /*!< ADC Analog watchdog 1, 2 and 3 lower threshold */
+
+/***************** Bit definition for ADC_HTR1, 2, 3 registers ****************/
+#define ADC_HTR_HT_Pos (0U)
+#define ADC_HTR_HT_Msk (0x3FFFFFFUL << ADC_HTR_HT_Pos) /*!< 0x03FFFFFF */
+#define ADC_HTR_HT ADC_HTR_HT_Msk /*!< ADC Analog watchdog 1,2 and 3 higher threshold */
+
+/******************** Bit definition for ADC3_TR1 register *******************/
+#define ADC3_TR1_LT1_Pos (0U)
+#define ADC3_TR1_LT1_Msk (0xFFFUL << ADC3_TR1_LT1_Pos) /*!< 0x00000FFF */
+#define ADC3_TR1_LT1 ADC3_TR1_LT1_Msk /*!< ADC analog watchdog 1 threshold low */
+
+#define ADC3_TR1_AWDFILT_Pos (12U)
+#define ADC3_TR1_AWDFILT_Msk (0x7UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00007000 */
+#define ADC3_TR1_AWDFILT ADC3_TR1_AWDFILT_Msk /*!< ADC analog watchdog filtering parameter */
+#define ADC3_TR1_AWDFILT_0 (0x1UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00001000 */
+#define ADC3_TR1_AWDFILT_1 (0x2UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00002000 */
+#define ADC3_TR1_AWDFILT_2 (0x4UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00004000 */
+
+#define ADC3_TR1_HT1_Pos (16U)
+#define ADC3_TR1_HT1_Msk (0xFFFUL << ADC3_TR1_HT1_Pos) /*!< 0x0FFF0000 */
+#define ADC3_TR1_HT1 ADC3_TR1_HT1_Msk /*!< ADC analog watchdog 1 threshold high */
+
+/******************** Bit definition for ADC3_TR2 register *******************/
+#define ADC3_TR2_LT2_Pos (0U)
+#define ADC3_TR2_LT2_Msk (0xFFUL << ADC3_TR2_LT2_Pos) /*!< 0x000000FF */
+#define ADC3_TR2_LT2 ADC3_TR2_LT2_Msk /*!< ADC analog watchdog 2 threshold low */
+
+#define ADC3_TR2_HT2_Pos (16U)
+#define ADC3_TR2_HT2_Msk (0xFFUL << ADC3_TR2_HT2_Pos) /*!< 0x00FF0000 */
+#define ADC3_TR2_HT2 ADC3_TR2_HT2_Msk /*!< ADC analog watchdog 2 threshold high */
+
+/******************** Bit definition for ADC3_TR3 register *******************/
+#define ADC3_TR3_LT3_Pos (0U)
+#define ADC3_TR3_LT3_Msk (0xFFUL << ADC3_TR3_LT3_Pos) /*!< 0x000000FF */
+#define ADC3_TR3_LT3 ADC3_TR3_LT3_Msk /*!< ADC analog watchdog 3 threshold low */
+
+#define ADC3_TR3_HT3_Pos (16U)
+#define ADC3_TR3_HT3_Msk (0xFFUL << ADC3_TR3_HT3_Pos) /*!< 0x00FF0000 */
+#define ADC3_TR3_HT3 ADC3_TR3_HT3_Msk /*!< ADC analog watchdog 3 threshold high */
+
+/******************** Bit definition for ADC_SQR1 register ********************/
+#define ADC_SQR1_L_Pos (0U)
+#define ADC_SQR1_L_Msk (0xFUL << ADC_SQR1_L_Pos) /*!< 0x0000000F */
+#define ADC_SQR1_L ADC_SQR1_L_Msk /*!< ADC regular channel sequence lenght */
+#define ADC_SQR1_L_0 (0x1UL << ADC_SQR1_L_Pos) /*!< 0x00000001 */
+#define ADC_SQR1_L_1 (0x2UL << ADC_SQR1_L_Pos) /*!< 0x00000002 */
+#define ADC_SQR1_L_2 (0x4UL << ADC_SQR1_L_Pos) /*!< 0x00000004 */
+#define ADC_SQR1_L_3 (0x8UL << ADC_SQR1_L_Pos) /*!< 0x00000008 */
+
+#define ADC_SQR1_SQ1_Pos (6U)
+#define ADC_SQR1_SQ1_Msk (0x1FUL << ADC_SQR1_SQ1_Pos) /*!< 0x000007C0 */
+#define ADC_SQR1_SQ1 ADC_SQR1_SQ1_Msk /*!< ADC 1st conversion in regular sequence */
+#define ADC_SQR1_SQ1_0 (0x01UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000040 */
+#define ADC_SQR1_SQ1_1 (0x02UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000080 */
+#define ADC_SQR1_SQ1_2 (0x04UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000100 */
+#define ADC_SQR1_SQ1_3 (0x08UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000200 */
+#define ADC_SQR1_SQ1_4 (0x10UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000400 */
+
+#define ADC_SQR1_SQ2_Pos (12U)
+#define ADC_SQR1_SQ2_Msk (0x1FUL << ADC_SQR1_SQ2_Pos) /*!< 0x0001F000 */
+#define ADC_SQR1_SQ2 ADC_SQR1_SQ2_Msk /*!< ADC 2nd conversion in regular sequence */
+#define ADC_SQR1_SQ2_0 (0x01UL << ADC_SQR1_SQ2_Pos) /*!< 0x00001000 */
+#define ADC_SQR1_SQ2_1 (0x02UL << ADC_SQR1_SQ2_Pos) /*!< 0x00002000 */
+#define ADC_SQR1_SQ2_2 (0x04UL << ADC_SQR1_SQ2_Pos) /*!< 0x00004000 */
+#define ADC_SQR1_SQ2_3 (0x08UL << ADC_SQR1_SQ2_Pos) /*!< 0x00008000 */
+#define ADC_SQR1_SQ2_4 (0x10UL << ADC_SQR1_SQ2_Pos) /*!< 0x00010000 */
+
+#define ADC_SQR1_SQ3_Pos (18U)
+#define ADC_SQR1_SQ3_Msk (0x1FUL << ADC_SQR1_SQ3_Pos) /*!< 0x007C0000 */
+#define ADC_SQR1_SQ3 ADC_SQR1_SQ3_Msk /*!< ADC 3rd conversion in regular sequence */
+#define ADC_SQR1_SQ3_0 (0x01UL << ADC_SQR1_SQ3_Pos) /*!< 0x00040000 */
+#define ADC_SQR1_SQ3_1 (0x02UL << ADC_SQR1_SQ3_Pos) /*!< 0x00080000 */
+#define ADC_SQR1_SQ3_2 (0x04UL << ADC_SQR1_SQ3_Pos) /*!< 0x00100000 */
+#define ADC_SQR1_SQ3_3 (0x08UL << ADC_SQR1_SQ3_Pos) /*!< 0x00200000 */
+#define ADC_SQR1_SQ3_4 (0x10UL << ADC_SQR1_SQ3_Pos) /*!< 0x00400000 */
+
+#define ADC_SQR1_SQ4_Pos (24U)
+#define ADC_SQR1_SQ4_Msk (0x1FUL << ADC_SQR1_SQ4_Pos) /*!< 0x1F000000 */
+#define ADC_SQR1_SQ4 ADC_SQR1_SQ4_Msk /*!< ADC 4th conversion in regular sequence */
+#define ADC_SQR1_SQ4_0 (0x01UL << ADC_SQR1_SQ4_Pos) /*!< 0x01000000 */
+#define ADC_SQR1_SQ4_1 (0x02UL << ADC_SQR1_SQ4_Pos) /*!< 0x02000000 */
+#define ADC_SQR1_SQ4_2 (0x04UL << ADC_SQR1_SQ4_Pos) /*!< 0x04000000 */
+#define ADC_SQR1_SQ4_3 (0x08UL << ADC_SQR1_SQ4_Pos) /*!< 0x08000000 */
+#define ADC_SQR1_SQ4_4 (0x10UL << ADC_SQR1_SQ4_Pos) /*!< 0x10000000 */
+
+/******************** Bit definition for ADC_SQR2 register ********************/
+#define ADC_SQR2_SQ5_Pos (0U)
+#define ADC_SQR2_SQ5_Msk (0x1FUL << ADC_SQR2_SQ5_Pos) /*!< 0x0000001F */
+#define ADC_SQR2_SQ5 ADC_SQR2_SQ5_Msk /*!< ADC 5th conversion in regular sequence */
+#define ADC_SQR2_SQ5_0 (0x01UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000001 */
+#define ADC_SQR2_SQ5_1 (0x02UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000002 */
+#define ADC_SQR2_SQ5_2 (0x04UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000004 */
+#define ADC_SQR2_SQ5_3 (0x08UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000008 */
+#define ADC_SQR2_SQ5_4 (0x10UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000010 */
+
+#define ADC_SQR2_SQ6_Pos (6U)
+#define ADC_SQR2_SQ6_Msk (0x1FUL << ADC_SQR2_SQ6_Pos) /*!< 0x000007C0 */
+#define ADC_SQR2_SQ6 ADC_SQR2_SQ6_Msk /*!< ADC 6th conversion in regular sequence */
+#define ADC_SQR2_SQ6_0 (0x01UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000040 */
+#define ADC_SQR2_SQ6_1 (0x02UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000080 */
+#define ADC_SQR2_SQ6_2 (0x04UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000100 */
+#define ADC_SQR2_SQ6_3 (0x08UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000200 */
+#define ADC_SQR2_SQ6_4 (0x10UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000400 */
+
+#define ADC_SQR2_SQ7_Pos (12U)
+#define ADC_SQR2_SQ7_Msk (0x1FUL << ADC_SQR2_SQ7_Pos) /*!< 0x0001F000 */
+#define ADC_SQR2_SQ7 ADC_SQR2_SQ7_Msk /*!< ADC 7th conversion in regular sequence */
+#define ADC_SQR2_SQ7_0 (0x01UL << ADC_SQR2_SQ7_Pos) /*!< 0x00001000 */
+#define ADC_SQR2_SQ7_1 (0x02UL << ADC_SQR2_SQ7_Pos) /*!< 0x00002000 */
+#define ADC_SQR2_SQ7_2 (0x04UL << ADC_SQR2_SQ7_Pos) /*!< 0x00004000 */
+#define ADC_SQR2_SQ7_3 (0x08UL << ADC_SQR2_SQ7_Pos) /*!< 0x00008000 */
+#define ADC_SQR2_SQ7_4 (0x10UL << ADC_SQR2_SQ7_Pos) /*!< 0x00010000 */
+
+#define ADC_SQR2_SQ8_Pos (18U)
+#define ADC_SQR2_SQ8_Msk (0x1FUL << ADC_SQR2_SQ8_Pos) /*!< 0x007C0000 */
+#define ADC_SQR2_SQ8 ADC_SQR2_SQ8_Msk /*!< ADC 8th conversion in regular sequence */
+#define ADC_SQR2_SQ8_0 (0x01UL << ADC_SQR2_SQ8_Pos) /*!< 0x00040000 */
+#define ADC_SQR2_SQ8_1 (0x02UL << ADC_SQR2_SQ8_Pos) /*!< 0x00080000 */
+#define ADC_SQR2_SQ8_2 (0x04UL << ADC_SQR2_SQ8_Pos) /*!< 0x00100000 */
+#define ADC_SQR2_SQ8_3 (0x08UL << ADC_SQR2_SQ8_Pos) /*!< 0x00200000 */
+#define ADC_SQR2_SQ8_4 (0x10UL << ADC_SQR2_SQ8_Pos) /*!< 0x00400000 */
+
+#define ADC_SQR2_SQ9_Pos (24U)
+#define ADC_SQR2_SQ9_Msk (0x1FUL << ADC_SQR2_SQ9_Pos) /*!< 0x1F000000 */
+#define ADC_SQR2_SQ9 ADC_SQR2_SQ9_Msk /*!< ADC 9th conversion in regular sequence */
+#define ADC_SQR2_SQ9_0 (0x01UL << ADC_SQR2_SQ9_Pos) /*!< 0x01000000 */
+#define ADC_SQR2_SQ9_1 (0x02UL << ADC_SQR2_SQ9_Pos) /*!< 0x02000000 */
+#define ADC_SQR2_SQ9_2 (0x04UL << ADC_SQR2_SQ9_Pos) /*!< 0x04000000 */
+#define ADC_SQR2_SQ9_3 (0x08UL << ADC_SQR2_SQ9_Pos) /*!< 0x08000000 */
+#define ADC_SQR2_SQ9_4 (0x10UL << ADC_SQR2_SQ9_Pos) /*!< 0x10000000 */
+
+/******************** Bit definition for ADC_SQR3 register ********************/
+#define ADC_SQR3_SQ10_Pos (0U)
+#define ADC_SQR3_SQ10_Msk (0x1FUL << ADC_SQR3_SQ10_Pos) /*!< 0x0000001F */
+#define ADC_SQR3_SQ10 ADC_SQR3_SQ10_Msk /*!< ADC 10th conversion in regular sequence */
+#define ADC_SQR3_SQ10_0 (0x01UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000001 */
+#define ADC_SQR3_SQ10_1 (0x02UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000002 */
+#define ADC_SQR3_SQ10_2 (0x04UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000004 */
+#define ADC_SQR3_SQ10_3 (0x08UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000008 */
+#define ADC_SQR3_SQ10_4 (0x10UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000010 */
+
+#define ADC_SQR3_SQ11_Pos (6U)
+#define ADC_SQR3_SQ11_Msk (0x1FUL << ADC_SQR3_SQ11_Pos) /*!< 0x000007C0 */
+#define ADC_SQR3_SQ11 ADC_SQR3_SQ11_Msk /*!< ADC 11th conversion in regular sequence */
+#define ADC_SQR3_SQ11_0 (0x01UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000040 */
+#define ADC_SQR3_SQ11_1 (0x02UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000080 */
+#define ADC_SQR3_SQ11_2 (0x04UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000100 */
+#define ADC_SQR3_SQ11_3 (0x08UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000200 */
+#define ADC_SQR3_SQ11_4 (0x10UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000400 */
+
+#define ADC_SQR3_SQ12_Pos (12U)
+#define ADC_SQR3_SQ12_Msk (0x1FUL << ADC_SQR3_SQ12_Pos) /*!< 0x0001F000 */
+#define ADC_SQR3_SQ12 ADC_SQR3_SQ12_Msk /*!< ADC 12th conversion in regular sequence */
+#define ADC_SQR3_SQ12_0 (0x01UL << ADC_SQR3_SQ12_Pos) /*!< 0x00001000 */
+#define ADC_SQR3_SQ12_1 (0x02UL << ADC_SQR3_SQ12_Pos) /*!< 0x00002000 */
+#define ADC_SQR3_SQ12_2 (0x04UL << ADC_SQR3_SQ12_Pos) /*!< 0x00004000 */
+#define ADC_SQR3_SQ12_3 (0x08UL << ADC_SQR3_SQ12_Pos) /*!< 0x00008000 */
+#define ADC_SQR3_SQ12_4 (0x10UL << ADC_SQR3_SQ12_Pos) /*!< 0x00010000 */
+
+#define ADC_SQR3_SQ13_Pos (18U)
+#define ADC_SQR3_SQ13_Msk (0x1FUL << ADC_SQR3_SQ13_Pos) /*!< 0x007C0000 */
+#define ADC_SQR3_SQ13 ADC_SQR3_SQ13_Msk /*!< ADC 13th conversion in regular sequence */
+#define ADC_SQR3_SQ13_0 (0x01UL << ADC_SQR3_SQ13_Pos) /*!< 0x00040000 */
+#define ADC_SQR3_SQ13_1 (0x02UL << ADC_SQR3_SQ13_Pos) /*!< 0x00080000 */
+#define ADC_SQR3_SQ13_2 (0x04UL << ADC_SQR3_SQ13_Pos) /*!< 0x00100000 */
+#define ADC_SQR3_SQ13_3 (0x08UL << ADC_SQR3_SQ13_Pos) /*!< 0x00200000 */
+#define ADC_SQR3_SQ13_4 (0x10UL << ADC_SQR3_SQ13_Pos) /*!< 0x00400000 */
+
+#define ADC_SQR3_SQ14_Pos (24U)
+#define ADC_SQR3_SQ14_Msk (0x1FUL << ADC_SQR3_SQ14_Pos) /*!< 0x1F000000 */
+#define ADC_SQR3_SQ14 ADC_SQR3_SQ14_Msk /*!< ADC 14th conversion in regular sequence */
+#define ADC_SQR3_SQ14_0 (0x01UL << ADC_SQR3_SQ14_Pos) /*!< 0x01000000 */
+#define ADC_SQR3_SQ14_1 (0x02UL << ADC_SQR3_SQ14_Pos) /*!< 0x02000000 */
+#define ADC_SQR3_SQ14_2 (0x04UL << ADC_SQR3_SQ14_Pos) /*!< 0x04000000 */
+#define ADC_SQR3_SQ14_3 (0x08UL << ADC_SQR3_SQ14_Pos) /*!< 0x08000000 */
+#define ADC_SQR3_SQ14_4 (0x10UL << ADC_SQR3_SQ14_Pos) /*!< 0x10000000 */
+
+/******************** Bit definition for ADC_SQR4 register ********************/
+#define ADC_SQR4_SQ15_Pos (0U)
+#define ADC_SQR4_SQ15_Msk (0x1FUL << ADC_SQR4_SQ15_Pos) /*!< 0x0000001F */
+#define ADC_SQR4_SQ15 ADC_SQR4_SQ15_Msk /*!< ADC 15th conversion in regular sequence */
+#define ADC_SQR4_SQ15_0 (0x01UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000001 */
+#define ADC_SQR4_SQ15_1 (0x02UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000002 */
+#define ADC_SQR4_SQ15_2 (0x04UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000004 */
+#define ADC_SQR4_SQ15_3 (0x08UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000008 */
+#define ADC_SQR4_SQ15_4 (0x10UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000010 */
+
+#define ADC_SQR4_SQ16_Pos (6U)
+#define ADC_SQR4_SQ16_Msk (0x1FUL << ADC_SQR4_SQ16_Pos) /*!< 0x000007C0 */
+#define ADC_SQR4_SQ16 ADC_SQR4_SQ16_Msk /*!< ADC 16th conversion in regular sequence */
+#define ADC_SQR4_SQ16_0 (0x01UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000040 */
+#define ADC_SQR4_SQ16_1 (0x02UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000080 */
+#define ADC_SQR4_SQ16_2 (0x04UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000100 */
+#define ADC_SQR4_SQ16_3 (0x08UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000200 */
+#define ADC_SQR4_SQ16_4 (0x10UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000400 */
+/******************** Bit definition for ADC_DR register ********************/
+#define ADC_DR_RDATA_Pos (0U)
+#define ADC_DR_RDATA_Msk (0xFFFFFFFFUL << ADC_DR_RDATA_Pos) /*!< 0xFFFFFFFF */
+#define ADC_DR_RDATA ADC_DR_RDATA_Msk /*!< ADC regular Data converted */
+
+/******************** Bit definition for ADC_JSQR register ********************/
+#define ADC_JSQR_JL_Pos (0U)
+#define ADC_JSQR_JL_Msk (0x3UL << ADC_JSQR_JL_Pos) /*!< 0x00000003 */
+#define ADC_JSQR_JL ADC_JSQR_JL_Msk /*!< ADC injected channel sequence length */
+#define ADC_JSQR_JL_0 (0x1UL << ADC_JSQR_JL_Pos) /*!< 0x00000001 */
+#define ADC_JSQR_JL_1 (0x2UL << ADC_JSQR_JL_Pos) /*!< 0x00000002 */
+
+#define ADC_JSQR_JEXTSEL_Pos (2U)
+#define ADC_JSQR_JEXTSEL_Msk (0x1FUL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x0000007C */
+#define ADC_JSQR_JEXTSEL ADC_JSQR_JEXTSEL_Msk /*!< ADC external trigger selection for injected group */
+#define ADC_JSQR_JEXTSEL_0 (0x01UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000004 */
+#define ADC_JSQR_JEXTSEL_1 (0x02UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000008 */
+#define ADC_JSQR_JEXTSEL_2 (0x04UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000010 */
+#define ADC_JSQR_JEXTSEL_3 (0x08UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000020 */
+#define ADC_JSQR_JEXTSEL_4 (0x10UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000040 */
+
+#define ADC_JSQR_JEXTEN_Pos (7U)
+#define ADC_JSQR_JEXTEN_Msk (0x3UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000180 */
+#define ADC_JSQR_JEXTEN ADC_JSQR_JEXTEN_Msk /*!< ADC external trigger enable and polarity selection for injected channels */
+#define ADC_JSQR_JEXTEN_0 (0x1UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000080 */
+#define ADC_JSQR_JEXTEN_1 (0x2UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000100 */
+
+#define ADC_JSQR_JSQ1_Pos (9U)
+#define ADC_JSQR_JSQ1_Msk (0x1FUL << ADC_JSQR_JSQ1_Pos) /*!< 0x00003E00 */
+#define ADC_JSQR_JSQ1 ADC_JSQR_JSQ1_Msk /*!< ADC 1st conversion in injected sequence */
+#define ADC_JSQR_JSQ1_0 (0x01UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000200 */
+#define ADC_JSQR_JSQ1_1 (0x02UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000400 */
+#define ADC_JSQR_JSQ1_2 (0x04UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000800 */
+#define ADC_JSQR_JSQ1_3 (0x08UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00001000 */
+#define ADC_JSQR_JSQ1_4 (0x10UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00002000 */
+
+#define ADC_JSQR_JSQ2_Pos (15U)
+#define ADC_JSQR_JSQ2_Msk (0x1FUL << ADC_JSQR_JSQ2_Pos) /*!< 0x000F8000 */
+#define ADC_JSQR_JSQ2 ADC_JSQR_JSQ2_Msk /*!< ADC 2nd conversion in injected sequence */
+#define ADC_JSQR_JSQ2_0 (0x01UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00008000 */
+#define ADC_JSQR_JSQ2_1 (0x02UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00010000 */
+#define ADC_JSQR_JSQ2_2 (0x04UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00020000 */
+#define ADC_JSQR_JSQ2_3 (0x08UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00040000 */
+#define ADC_JSQR_JSQ2_4 (0x10UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00080000 */
+
+#define ADC_JSQR_JSQ3_Pos (21U)
+#define ADC_JSQR_JSQ3_Msk (0x1FUL << ADC_JSQR_JSQ3_Pos) /*!< 0x03E00000 */
+#define ADC_JSQR_JSQ3 ADC_JSQR_JSQ3_Msk /*!< ADC 3rd conversion in injected sequence */
+#define ADC_JSQR_JSQ3_0 (0x01UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00200000 */
+#define ADC_JSQR_JSQ3_1 (0x02UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00400000 */
+#define ADC_JSQR_JSQ3_2 (0x04UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00800000 */
+#define ADC_JSQR_JSQ3_3 (0x08UL << ADC_JSQR_JSQ3_Pos) /*!< 0x01000000 */
+#define ADC_JSQR_JSQ3_4 (0x10UL << ADC_JSQR_JSQ3_Pos) /*!< 0x02000000 */
+
+#define ADC_JSQR_JSQ4_Pos (27U)
+#define ADC_JSQR_JSQ4_Msk (0x1FUL << ADC_JSQR_JSQ4_Pos) /*!< 0xF8000000 */
+#define ADC_JSQR_JSQ4 ADC_JSQR_JSQ4_Msk /*!< ADC 4th conversion in injected sequence */
+#define ADC_JSQR_JSQ4_0 (0x01UL << ADC_JSQR_JSQ4_Pos) /*!< 0x08000000 */
+#define ADC_JSQR_JSQ4_1 (0x02UL << ADC_JSQR_JSQ4_Pos) /*!< 0x10000000 */
+#define ADC_JSQR_JSQ4_2 (0x04UL << ADC_JSQR_JSQ4_Pos) /*!< 0x20000000 */
+#define ADC_JSQR_JSQ4_3 (0x08UL << ADC_JSQR_JSQ4_Pos) /*!< 0x40000000 */
+#define ADC_JSQR_JSQ4_4 (0x10UL << ADC_JSQR_JSQ4_Pos) /*!< 0x80000000 */
+
+/******************** Bit definition for ADC_OFR1 register ********************/
+#define ADC_OFR1_OFFSET1_Pos (0U)
+#define ADC_OFR1_OFFSET1_Msk (0x3FFFFFFUL << ADC_OFR1_OFFSET1_Pos) /*!< 0x03FFFFFF */
+#define ADC_OFR1_OFFSET1 ADC_OFR1_OFFSET1_Msk /*!< ADC data offset 1 for channel programmed into bits OFFSET1_CH[4:0] */
+#define ADC_OFR1_OFFSET1_0 (0x0000001UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000001 */
+#define ADC_OFR1_OFFSET1_1 (0x0000002UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000002 */
+#define ADC_OFR1_OFFSET1_2 (0x0000004UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000004 */
+#define ADC_OFR1_OFFSET1_3 (0x0000008UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000008 */
+#define ADC_OFR1_OFFSET1_4 (0x0000010UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000010 */
+#define ADC_OFR1_OFFSET1_5 (0x0000020UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000020 */
+#define ADC_OFR1_OFFSET1_6 (0x0000040UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000040 */
+#define ADC_OFR1_OFFSET1_7 (0x0000080UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000080 */
+#define ADC_OFR1_OFFSET1_8 (0x0000100UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000100 */
+#define ADC_OFR1_OFFSET1_9 (0x0000200UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000200 */
+#define ADC_OFR1_OFFSET1_10 (0x0000400UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000400 */
+#define ADC_OFR1_OFFSET1_11 (0x0000800UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000800 */
+#define ADC_OFR1_OFFSET1_12 (0x0001000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00001000 */
+#define ADC_OFR1_OFFSET1_13 (0x0002000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00002000 */
+#define ADC_OFR1_OFFSET1_14 (0x0004000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00004000 */
+#define ADC_OFR1_OFFSET1_15 (0x0008000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00008000 */
+#define ADC_OFR1_OFFSET1_16 (0x0010000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00010000 */
+#define ADC_OFR1_OFFSET1_17 (0x0020000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00020000 */
+#define ADC_OFR1_OFFSET1_18 (0x0040000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00040000 */
+#define ADC_OFR1_OFFSET1_19 (0x0080000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00080000 */
+#define ADC_OFR1_OFFSET1_20 (0x0100000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00100000 */
+#define ADC_OFR1_OFFSET1_21 (0x0200000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00200000 */
+#define ADC_OFR1_OFFSET1_22 (0x0400000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00400000 */
+#define ADC_OFR1_OFFSET1_23 (0x0800000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00800000 */
+#define ADC_OFR1_OFFSET1_24 (0x1000000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x01000000 */
+#define ADC_OFR1_OFFSET1_25 (0x2000000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x02000000 */
+
+#define ADC_OFR1_OFFSET1_CH_Pos (26U)
+#define ADC_OFR1_OFFSET1_CH_Msk (0x1FUL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x7C000000 */
+#define ADC_OFR1_OFFSET1_CH ADC_OFR1_OFFSET1_CH_Msk /*!< ADC Channel selection for the data offset 1 */
+#define ADC_OFR1_OFFSET1_CH_0 (0x01UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x04000000 */
+#define ADC_OFR1_OFFSET1_CH_1 (0x02UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x08000000 */
+#define ADC_OFR1_OFFSET1_CH_2 (0x04UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x10000000 */
+#define ADC_OFR1_OFFSET1_CH_3 (0x08UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x20000000 */
+#define ADC_OFR1_OFFSET1_CH_4 (0x10UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x40000000 */
+
+#define ADC_OFR1_SSATE_Pos (31U)
+#define ADC_OFR1_SSATE_Msk (0x1UL << ADC_OFR1_SSATE_Pos) /*!< 0x80000000 */
+#define ADC_OFR1_SSATE ADC_OFR1_SSATE_Msk /*!< ADC Signed saturation Enable */
+
+#define ADC3_OFR1_OFFSET1_Pos (0U)
+#define ADC3_OFR1_OFFSET1_Msk (0xFFFUL << ADC3_OFR1_OFFSET1_Pos) /*!< 0x00000FFF */
+#define ADC3_OFR1_OFFSET1 ADC3_OFR1_OFFSET1_Msk /*!< ADC data offset 1 for channel programmed into bits OFFSET1_CH[4:0] */
+
+#define ADC3_OFR1_OFFSETPOS_Pos (24U)
+#define ADC3_OFR1_OFFSETPOS_Msk (0x1UL << ADC3_OFR1_OFFSETPOS_Pos) /*!< 0x01000000 */
+#define ADC3_OFR1_OFFSETPOS ADC3_OFR1_OFFSETPOS_Msk /*!< ADC offset number 1 positive */
+#define ADC3_OFR1_SATEN_Pos (25U)
+#define ADC3_OFR1_SATEN_Msk (0x1UL << ADC3_OFR1_SATEN_Pos) /*!< 0x02000000 */
+#define ADC3_OFR1_SATEN ADC3_OFR1_SATEN_Msk /*!< ADC offset number 1 saturation enable */
+
+#define ADC3_OFR1_OFFSET1_EN_Pos (31U)
+#define ADC3_OFR1_OFFSET1_EN_Msk (0x1UL << ADC3_OFR1_OFFSET1_EN_Pos) /*!< 0x80000000 */
+#define ADC3_OFR1_OFFSET1_EN ADC3_OFR1_OFFSET1_EN_Msk /*!< ADC offset number 1 enable */
+
+/******************** Bit definition for ADC_OFR2 register ********************/
+#define ADC_OFR2_OFFSET2_Pos (0U)
+#define ADC_OFR2_OFFSET2_Msk (0x3FFFFFFUL << ADC_OFR2_OFFSET2_Pos) /*!< 0x03FFFFFF */
+#define ADC_OFR2_OFFSET2 ADC_OFR2_OFFSET2_Msk /*!< ADC data offset 2 for channel programmed into bits OFFSET2_CH[4:0] */
+#define ADC_OFR2_OFFSET2_0 (0x0000001UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000001 */
+#define ADC_OFR2_OFFSET2_1 (0x0000002UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000002 */
+#define ADC_OFR2_OFFSET2_2 (0x0000004UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000004 */
+#define ADC_OFR2_OFFSET2_3 (0x0000008UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000008 */
+#define ADC_OFR2_OFFSET2_4 (0x0000010UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000010 */
+#define ADC_OFR2_OFFSET2_5 (0x0000020UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000020 */
+#define ADC_OFR2_OFFSET2_6 (0x0000040UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000040 */
+#define ADC_OFR2_OFFSET2_7 (0x0000080UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000080 */
+#define ADC_OFR2_OFFSET2_8 (0x0000100UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000100 */
+#define ADC_OFR2_OFFSET2_9 (0x0000200UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000200 */
+#define ADC_OFR2_OFFSET2_10 (0x0000400UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000400 */
+#define ADC_OFR2_OFFSET2_11 (0x0000800UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000800 */
+#define ADC_OFR2_OFFSET2_12 (0x0001000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00001000 */
+#define ADC_OFR2_OFFSET2_13 (0x0002000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00002000 */
+#define ADC_OFR2_OFFSET2_14 (0x0004000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00004000 */
+#define ADC_OFR2_OFFSET2_15 (0x0008000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00008000 */
+#define ADC_OFR2_OFFSET2_16 (0x0010000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00010000 */
+#define ADC_OFR2_OFFSET2_17 (0x0020000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00020000 */
+#define ADC_OFR2_OFFSET2_18 (0x0040000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00040000 */
+#define ADC_OFR2_OFFSET2_19 (0x0080000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00080000 */
+#define ADC_OFR2_OFFSET2_20 (0x0100000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00100000 */
+#define ADC_OFR2_OFFSET2_21 (0x0200000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00200000 */
+#define ADC_OFR2_OFFSET2_22 (0x0400000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00400000 */
+#define ADC_OFR2_OFFSET2_23 (0x0800000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00800000 */
+#define ADC_OFR2_OFFSET2_24 (0x1000000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x01000000 */
+#define ADC_OFR2_OFFSET2_25 (0x2000000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x02000000 */
+
+#define ADC_OFR2_OFFSET2_CH_Pos (26U)
+#define ADC_OFR2_OFFSET2_CH_Msk (0x1FUL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x7C000000 */
+#define ADC_OFR2_OFFSET2_CH ADC_OFR2_OFFSET2_CH_Msk /*!< ADC Channel selection for the data offset 2 */
+#define ADC_OFR2_OFFSET2_CH_0 (0x01UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x04000000 */
+#define ADC_OFR2_OFFSET2_CH_1 (0x02UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x08000000 */
+#define ADC_OFR2_OFFSET2_CH_2 (0x04UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x10000000 */
+#define ADC_OFR2_OFFSET2_CH_3 (0x08UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x20000000 */
+#define ADC_OFR2_OFFSET2_CH_4 (0x10UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x40000000 */
+
+#define ADC_OFR2_SSATE_Pos (31U)
+#define ADC_OFR2_SSATE_Msk (0x1UL << ADC_OFR2_SSATE_Pos) /*!< 0x80000000 */
+#define ADC_OFR2_SSATE ADC_OFR2_SSATE_Msk /*!< ADC Signed saturation Enable */
+
+#define ADC3_OFR2_OFFSET2_Pos (0U)
+#define ADC3_OFR2_OFFSET2_Msk (0xFFFUL << ADC3_OFR2_OFFSET2_Pos) /*!< 0x00000FFF */
+#define ADC3_OFR2_OFFSET2 ADC3_OFR2_OFFSET2_Msk /*!< ADC data offset 2 for channel programmed into bits OFFSET1_CH[4:0] */
+
+#define ADC3_OFR2_OFFSETPOS_Pos (24U)
+#define ADC3_OFR2_OFFSETPOS_Msk (0x1UL << ADC3_OFR2_OFFSETPOS_Pos) /*!< 0x01000000 */
+#define ADC3_OFR2_OFFSETPOS ADC3_OFR2_OFFSETPOS_Msk /*!< ADC offset number 2 positive */
+#define ADC3_OFR2_SATEN_Pos (25U)
+#define ADC3_OFR2_SATEN_Msk (0x1UL << ADC3_OFR2_SATEN_Pos) /*!< 0x02000000 */
+#define ADC3_OFR2_SATEN ADC3_OFR2_SATEN_Msk /*!< ADC offset number 2 saturation enable */
+
+#define ADC3_OFR2_OFFSET2_EN_Pos (31U)
+#define ADC3_OFR2_OFFSET2_EN_Msk (0x1UL << ADC3_OFR2_OFFSET2_EN_Pos) /*!< 0x80000000 */
+#define ADC3_OFR2_OFFSET2_EN ADC3_OFR2_OFFSET2_EN_Msk /*!< ADC offset number 2 enable */
+
+/******************** Bit definition for ADC_OFR3 register ********************/
+#define ADC_OFR3_OFFSET3_Pos (0U)
+#define ADC_OFR3_OFFSET3_Msk (0x3FFFFFFUL << ADC_OFR3_OFFSET3_Pos) /*!< 0x03FFFFFF */
+#define ADC_OFR3_OFFSET3 ADC_OFR3_OFFSET3_Msk /*!< ADC data offset 3 for channel programmed into bits OFFSET3_CH[4:0] */
+#define ADC_OFR3_OFFSET3_0 (0x0000001UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000001 */
+#define ADC_OFR3_OFFSET3_1 (0x0000002UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000002 */
+#define ADC_OFR3_OFFSET3_2 (0x0000004UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000004 */
+#define ADC_OFR3_OFFSET3_3 (0x0000008UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000008 */
+#define ADC_OFR3_OFFSET3_4 (0x0000010UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000010 */
+#define ADC_OFR3_OFFSET3_5 (0x0000020UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000020 */
+#define ADC_OFR3_OFFSET3_6 (0x0000040UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000040 */
+#define ADC_OFR3_OFFSET3_7 (0x0000080UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000080 */
+#define ADC_OFR3_OFFSET3_8 (0x0000100UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000100 */
+#define ADC_OFR3_OFFSET3_9 (0x0000200UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000200 */
+#define ADC_OFR3_OFFSET3_10 (0x0000400UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000400 */
+#define ADC_OFR3_OFFSET3_11 (0x0000800UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000800 */
+#define ADC_OFR3_OFFSET3_12 (0x0001000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00001000 */
+#define ADC_OFR3_OFFSET3_13 (0x0002000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00002000 */
+#define ADC_OFR3_OFFSET3_14 (0x0004000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00004000 */
+#define ADC_OFR3_OFFSET3_15 (0x0008000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00008000 */
+#define ADC_OFR3_OFFSET3_16 (0x0010000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00010000 */
+#define ADC_OFR3_OFFSET3_17 (0x0020000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00020000 */
+#define ADC_OFR3_OFFSET3_18 (0x0040000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00040000 */
+#define ADC_OFR3_OFFSET3_19 (0x0080000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00080000 */
+#define ADC_OFR3_OFFSET3_20 (0x0100000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00100000 */
+#define ADC_OFR3_OFFSET3_21 (0x0200000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00200000 */
+#define ADC_OFR3_OFFSET3_22 (0x0400000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00400000 */
+#define ADC_OFR3_OFFSET3_23 (0x0800000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00800000 */
+#define ADC_OFR3_OFFSET3_24 (0x1000000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x01000000 */
+#define ADC_OFR3_OFFSET3_25 (0x2000000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x02000000 */
+
+#define ADC_OFR3_OFFSET3_CH_Pos (26U)
+#define ADC_OFR3_OFFSET3_CH_Msk (0x1FUL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x7C000000 */
+#define ADC_OFR3_OFFSET3_CH ADC_OFR3_OFFSET3_CH_Msk /*!< ADC Channel selection for the data offset 3 */
+#define ADC_OFR3_OFFSET3_CH_0 (0x01UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x04000000 */
+#define ADC_OFR3_OFFSET3_CH_1 (0x02UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x08000000 */
+#define ADC_OFR3_OFFSET3_CH_2 (0x04UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x10000000 */
+#define ADC_OFR3_OFFSET3_CH_3 (0x08UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x20000000 */
+#define ADC_OFR3_OFFSET3_CH_4 (0x10UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x40000000 */
+
+#define ADC_OFR3_SSATE_Pos (31U)
+#define ADC_OFR3_SSATE_Msk (0x1UL << ADC_OFR3_SSATE_Pos) /*!< 0x80000000 */
+#define ADC_OFR3_SSATE ADC_OFR3_SSATE_Msk /*!< ADC Signed saturation Enable */
+
+#define ADC3_OFR3_OFFSET3_Pos (0U)
+#define ADC3_OFR3_OFFSET3_Msk (0xFFFUL << ADC3_OFR3_OFFSET3_Pos) /*!< 0x00000FFF */
+#define ADC3_OFR3_OFFSET3 ADC3_OFR3_OFFSET3_Msk /*!< ADC data offset 3 for channel programmed into bits OFFSET1_CH[4:0] */
+
+#define ADC3_OFR3_OFFSETPOS_Pos (24U)
+#define ADC3_OFR3_OFFSETPOS_Msk (0x1UL << ADC3_OFR3_OFFSETPOS_Pos) /*!< 0x01000000 */
+#define ADC3_OFR3_OFFSETPOS ADC3_OFR3_OFFSETPOS_Msk /*!< ADC offset number 3 positive */
+#define ADC3_OFR3_SATEN_Pos (25U)
+#define ADC3_OFR3_SATEN_Msk (0x1UL << ADC3_OFR3_SATEN_Pos) /*!< 0x02000000 */
+#define ADC3_OFR3_SATEN ADC3_OFR3_SATEN_Msk /*!< ADC offset number 3 saturation enable */
+
+#define ADC3_OFR3_OFFSET3_EN_Pos (31U)
+#define ADC3_OFR3_OFFSET3_EN_Msk (0x1UL << ADC3_OFR3_OFFSET3_EN_Pos) /*!< 0x80000000 */
+#define ADC3_OFR3_OFFSET3_EN ADC3_OFR3_OFFSET3_EN_Msk /*!< ADC offset number 3 enable */
+
+/******************** Bit definition for ADC_OFR4 register ********************/
+#define ADC_OFR4_OFFSET4_Pos (0U)
+#define ADC_OFR4_OFFSET4_Msk (0x3FFFFFFUL << ADC_OFR4_OFFSET4_Pos) /*!< 0x03FFFFFF */
+#define ADC_OFR4_OFFSET4 ADC_OFR4_OFFSET4_Msk /*!< ADC data offset 4 for channel programmed into bits OFFSET4_CH[4:0] */
+#define ADC_OFR4_OFFSET4_0 (0x0000001UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000001 */
+#define ADC_OFR4_OFFSET4_1 (0x0000002UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000002 */
+#define ADC_OFR4_OFFSET4_2 (0x0000004UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000004 */
+#define ADC_OFR4_OFFSET4_3 (0x0000008UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000008 */
+#define ADC_OFR4_OFFSET4_4 (0x0000010UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000010 */
+#define ADC_OFR4_OFFSET4_5 (0x0000020UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000020 */
+#define ADC_OFR4_OFFSET4_6 (0x0000040UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000040 */
+#define ADC_OFR4_OFFSET4_7 (0x0000080UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000080 */
+#define ADC_OFR4_OFFSET4_8 (0x0000100UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000100 */
+#define ADC_OFR4_OFFSET4_9 (0x0000200UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000200 */
+#define ADC_OFR4_OFFSET4_10 (0x0000400UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000400 */
+#define ADC_OFR4_OFFSET4_11 (0x0000800UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000800 */
+#define ADC_OFR4_OFFSET4_12 (0x0001000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00001000 */
+#define ADC_OFR4_OFFSET4_13 (0x0002000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00002000 */
+#define ADC_OFR4_OFFSET4_14 (0x0004000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00004000 */
+#define ADC_OFR4_OFFSET4_15 (0x0008000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00008000 */
+#define ADC_OFR4_OFFSET4_16 (0x0010000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00010000 */
+#define ADC_OFR4_OFFSET4_17 (0x0020000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00020000 */
+#define ADC_OFR4_OFFSET4_18 (0x0040000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00040000 */
+#define ADC_OFR4_OFFSET4_19 (0x0080000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00080000 */
+#define ADC_OFR4_OFFSET4_20 (0x0100000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00100000 */
+#define ADC_OFR4_OFFSET4_21 (0x0200000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00200000 */
+#define ADC_OFR4_OFFSET4_22 (0x0400000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00400000 */
+#define ADC_OFR4_OFFSET4_23 (0x0800000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00800000 */
+#define ADC_OFR4_OFFSET4_24 (0x1000000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x01000000 */
+#define ADC_OFR4_OFFSET4_25 (0x2000000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x02000000 */
+
+#define ADC_OFR4_OFFSET4_CH_Pos (26U)
+#define ADC_OFR4_OFFSET4_CH_Msk (0x1FUL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x7C000000 */
+#define ADC_OFR4_OFFSET4_CH ADC_OFR4_OFFSET4_CH_Msk /*!< ADC Channel selection for the data offset 4 */
+#define ADC_OFR4_OFFSET4_CH_0 (0x01UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x04000000 */
+#define ADC_OFR4_OFFSET4_CH_1 (0x02UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x08000000 */
+#define ADC_OFR4_OFFSET4_CH_2 (0x04UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x10000000 */
+#define ADC_OFR4_OFFSET4_CH_3 (0x08UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x20000000 */
+#define ADC_OFR4_OFFSET4_CH_4 (0x10UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x40000000 */
+
+#define ADC_OFR4_SSATE_Pos (31U)
+#define ADC_OFR4_SSATE_Msk (0x1UL << ADC_OFR4_SSATE_Pos) /*!< 0x80000000 */
+#define ADC_OFR4_SSATE ADC_OFR4_SSATE_Msk /*!< ADC Signed saturation Enable */
+
+#define ADC3_OFR4_OFFSET4_Pos (0U)
+#define ADC3_OFR4_OFFSET4_Msk (0xFFFUL << ADC3_OFR4_OFFSET4_Pos) /*!< 0x00000FFF */
+#define ADC3_OFR4_OFFSET4 ADC3_OFR4_OFFSET4_Msk /*!< ADC data offset 4 for channel programmed into bits OFFSET1_CH[4:0] */
+
+#define ADC3_OFR4_OFFSETPOS_Pos (24U)
+#define ADC3_OFR4_OFFSETPOS_Msk (0x1UL << ADC3_OFR4_OFFSETPOS_Pos) /*!< 0x01000000 */
+#define ADC3_OFR4_OFFSETPOS ADC3_OFR4_OFFSETPOS_Msk /*!< ADC offset number 4 positive */
+#define ADC3_OFR4_SATEN_Pos (25U)
+#define ADC3_OFR4_SATEN_Msk (0x1UL << ADC3_OFR4_SATEN_Pos) /*!< 0x02000000 */
+#define ADC3_OFR4_SATEN ADC3_OFR4_SATEN_Msk /*!< ADC offset number 4 saturation enable */
+
+#define ADC3_OFR4_OFFSET4_EN_Pos (31U)
+#define ADC3_OFR4_OFFSET4_EN_Msk (0x1UL << ADC3_OFR4_OFFSET4_EN_Pos) /*!< 0x80000000 */
+#define ADC3_OFR4_OFFSET4_EN ADC3_OFR4_OFFSET4_EN_Msk /*!< ADC offset number 4 enable */
+
+/******************** Bit definition for ADC_JDR1 register ********************/
+#define ADC_JDR1_JDATA_Pos (0U)
+#define ADC_JDR1_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR1_JDATA_Pos) /*!< 0xFFFFFFFF */
+#define ADC_JDR1_JDATA ADC_JDR1_JDATA_Msk /*!< ADC Injected DATA */
+#define ADC_JDR1_JDATA_0 (0x00000001UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000001 */
+#define ADC_JDR1_JDATA_1 (0x00000002UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000002 */
+#define ADC_JDR1_JDATA_2 (0x00000004UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000004 */
+#define ADC_JDR1_JDATA_3 (0x00000008UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000008 */
+#define ADC_JDR1_JDATA_4 (0x00000010UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000010 */
+#define ADC_JDR1_JDATA_5 (0x00000020UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000020 */
+#define ADC_JDR1_JDATA_6 (0x00000040UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000040 */
+#define ADC_JDR1_JDATA_7 (0x00000080UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000080 */
+#define ADC_JDR1_JDATA_8 (0x00000100UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000100 */
+#define ADC_JDR1_JDATA_9 (0x00000200UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000200 */
+#define ADC_JDR1_JDATA_10 (0x00000400UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000400 */
+#define ADC_JDR1_JDATA_11 (0x00000800UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000800 */
+#define ADC_JDR1_JDATA_12 (0x00001000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00001000 */
+#define ADC_JDR1_JDATA_13 (0x00002000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00002000 */
+#define ADC_JDR1_JDATA_14 (0x00004000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00004000 */
+#define ADC_JDR1_JDATA_15 (0x00008000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00008000 */
+#define ADC_JDR1_JDATA_16 (0x00010000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00010000 */
+#define ADC_JDR1_JDATA_17 (0x00020000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00020000 */
+#define ADC_JDR1_JDATA_18 (0x00040000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00040000 */
+#define ADC_JDR1_JDATA_19 (0x00080000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00080000 */
+#define ADC_JDR1_JDATA_20 (0x00100000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00100000 */
+#define ADC_JDR1_JDATA_21 (0x00200000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00200000 */
+#define ADC_JDR1_JDATA_22 (0x00400000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00400000 */
+#define ADC_JDR1_JDATA_23 (0x00800000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00800000 */
+#define ADC_JDR1_JDATA_24 (0x01000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x01000000 */
+#define ADC_JDR1_JDATA_25 (0x02000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x02000000 */
+#define ADC_JDR1_JDATA_26 (0x04000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x04000000 */
+#define ADC_JDR1_JDATA_27 (0x08000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x08000000 */
+#define ADC_JDR1_JDATA_28 (0x10000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x10000000 */
+#define ADC_JDR1_JDATA_29 (0x20000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x20000000 */
+#define ADC_JDR1_JDATA_30 (0x40000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x40000000 */
+#define ADC_JDR1_JDATA_31 (0x80000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x80000000 */
+
+/******************** Bit definition for ADC_JDR2 register ********************/
+#define ADC_JDR2_JDATA_Pos (0U)
+#define ADC_JDR2_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR2_JDATA_Pos) /*!< 0xFFFFFFFF */
+#define ADC_JDR2_JDATA ADC_JDR2_JDATA_Msk /*!< ADC Injected DATA */
+#define ADC_JDR2_JDATA_0 (0x00000001UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000001 */
+#define ADC_JDR2_JDATA_1 (0x00000002UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000002 */
+#define ADC_JDR2_JDATA_2 (0x00000004UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000004 */
+#define ADC_JDR2_JDATA_3 (0x00000008UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000008 */
+#define ADC_JDR2_JDATA_4 (0x00000010UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000010 */
+#define ADC_JDR2_JDATA_5 (0x00000020UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000020 */
+#define ADC_JDR2_JDATA_6 (0x00000040UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000040 */
+#define ADC_JDR2_JDATA_7 (0x00000080UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000080 */
+#define ADC_JDR2_JDATA_8 (0x00000100UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000100 */
+#define ADC_JDR2_JDATA_9 (0x00000200UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000200 */
+#define ADC_JDR2_JDATA_10 (0x00000400UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000400 */
+#define ADC_JDR2_JDATA_11 (0x00000800UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000800 */
+#define ADC_JDR2_JDATA_12 (0x00001000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00001000 */
+#define ADC_JDR2_JDATA_13 (0x00002000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00002000 */
+#define ADC_JDR2_JDATA_14 (0x00004000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00004000 */
+#define ADC_JDR2_JDATA_15 (0x00008000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00008000 */
+#define ADC_JDR2_JDATA_16 (0x00010000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00010000 */
+#define ADC_JDR2_JDATA_17 (0x00020000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00020000 */
+#define ADC_JDR2_JDATA_18 (0x00040000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00040000 */
+#define ADC_JDR2_JDATA_19 (0x00080000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00080000 */
+#define ADC_JDR2_JDATA_20 (0x00100000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00100000 */
+#define ADC_JDR2_JDATA_21 (0x00200000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00200000 */
+#define ADC_JDR2_JDATA_22 (0x00400000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00400000 */
+#define ADC_JDR2_JDATA_23 (0x00800000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00800000 */
+#define ADC_JDR2_JDATA_24 (0x01000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x01000000 */
+#define ADC_JDR2_JDATA_25 (0x02000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x02000000 */
+#define ADC_JDR2_JDATA_26 (0x04000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x04000000 */
+#define ADC_JDR2_JDATA_27 (0x08000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x08000000 */
+#define ADC_JDR2_JDATA_28 (0x10000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x10000000 */
+#define ADC_JDR2_JDATA_29 (0x20000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x20000000 */
+#define ADC_JDR2_JDATA_30 (0x40000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x40000000 */
+#define ADC_JDR2_JDATA_31 (0x80000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x80000000 */
+
+/******************** Bit definition for ADC_JDR3 register ********************/
+#define ADC_JDR3_JDATA_Pos (0U)
+#define ADC_JDR3_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR3_JDATA_Pos) /*!< 0xFFFFFFFF */
+#define ADC_JDR3_JDATA ADC_JDR3_JDATA_Msk /*!< ADC Injected DATA */
+#define ADC_JDR3_JDATA_0 (0x00000001UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000001 */
+#define ADC_JDR3_JDATA_1 (0x00000002UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000002 */
+#define ADC_JDR3_JDATA_2 (0x00000004UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000004 */
+#define ADC_JDR3_JDATA_3 (0x00000008UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000008 */
+#define ADC_JDR3_JDATA_4 (0x00000010UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000010 */
+#define ADC_JDR3_JDATA_5 (0x00000020UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000020 */
+#define ADC_JDR3_JDATA_6 (0x00000040UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000040 */
+#define ADC_JDR3_JDATA_7 (0x00000080UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000080 */
+#define ADC_JDR3_JDATA_8 (0x00000100UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000100 */
+#define ADC_JDR3_JDATA_9 (0x00000200UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000200 */
+#define ADC_JDR3_JDATA_10 (0x00000400UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000400 */
+#define ADC_JDR3_JDATA_11 (0x00000800UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000800 */
+#define ADC_JDR3_JDATA_12 (0x00001000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00001000 */
+#define ADC_JDR3_JDATA_13 (0x00002000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00002000 */
+#define ADC_JDR3_JDATA_14 (0x00004000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00004000 */
+#define ADC_JDR3_JDATA_15 (0x00008000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00008000 */
+#define ADC_JDR3_JDATA_16 (0x00010000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00010000 */
+#define ADC_JDR3_JDATA_17 (0x00020000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00020000 */
+#define ADC_JDR3_JDATA_18 (0x00040000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00040000 */
+#define ADC_JDR3_JDATA_19 (0x00080000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00080000 */
+#define ADC_JDR3_JDATA_20 (0x00100000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00100000 */
+#define ADC_JDR3_JDATA_21 (0x00200000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00200000 */
+#define ADC_JDR3_JDATA_22 (0x00400000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00400000 */
+#define ADC_JDR3_JDATA_23 (0x00800000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00800000 */
+#define ADC_JDR3_JDATA_24 (0x01000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x01000000 */
+#define ADC_JDR3_JDATA_25 (0x02000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x02000000 */
+#define ADC_JDR3_JDATA_26 (0x04000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x04000000 */
+#define ADC_JDR3_JDATA_27 (0x08000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x08000000 */
+#define ADC_JDR3_JDATA_28 (0x10000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x10000000 */
+#define ADC_JDR3_JDATA_29 (0x20000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x20000000 */
+#define ADC_JDR3_JDATA_30 (0x40000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x40000000 */
+#define ADC_JDR3_JDATA_31 (0x80000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x80000000 */
+
+/******************** Bit definition for ADC_JDR4 register ********************/
+#define ADC_JDR4_JDATA_Pos (0U)
+#define ADC_JDR4_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR4_JDATA_Pos) /*!< 0xFFFFFFFF */
+#define ADC_JDR4_JDATA ADC_JDR4_JDATA_Msk /*!< ADC Injected DATA */
+#define ADC_JDR4_JDATA_0 (0x00000001UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000001 */
+#define ADC_JDR4_JDATA_1 (0x00000002UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000002 */
+#define ADC_JDR4_JDATA_2 (0x00000004UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000004 */
+#define ADC_JDR4_JDATA_3 (0x00000008UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000008 */
+#define ADC_JDR4_JDATA_4 (0x00000010UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000010 */
+#define ADC_JDR4_JDATA_5 (0x00000020UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000020 */
+#define ADC_JDR4_JDATA_6 (0x00000040UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000040 */
+#define ADC_JDR4_JDATA_7 (0x00000080UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000080 */
+#define ADC_JDR4_JDATA_8 (0x00000100UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000100 */
+#define ADC_JDR4_JDATA_9 (0x00000200UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000200 */
+#define ADC_JDR4_JDATA_10 (0x00000400UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000400 */
+#define ADC_JDR4_JDATA_11 (0x00000800UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000800 */
+#define ADC_JDR4_JDATA_12 (0x00001000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00001000 */
+#define ADC_JDR4_JDATA_13 (0x00002000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00002000 */
+#define ADC_JDR4_JDATA_14 (0x00004000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00004000 */
+#define ADC_JDR4_JDATA_15 (0x00008000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00008000 */
+#define ADC_JDR4_JDATA_16 (0x00010000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00010000 */
+#define ADC_JDR4_JDATA_17 (0x00020000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00020000 */
+#define ADC_JDR4_JDATA_18 (0x00040000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00040000 */
+#define ADC_JDR4_JDATA_19 (0x00080000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00080000 */
+#define ADC_JDR4_JDATA_20 (0x00100000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00100000 */
+#define ADC_JDR4_JDATA_21 (0x00200000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00200000 */
+#define ADC_JDR4_JDATA_22 (0x00400000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00400000 */
+#define ADC_JDR4_JDATA_23 (0x00800000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00800000 */
+#define ADC_JDR4_JDATA_24 (0x01000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x01000000 */
+#define ADC_JDR4_JDATA_25 (0x02000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x02000000 */
+#define ADC_JDR4_JDATA_26 (0x04000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x04000000 */
+#define ADC_JDR4_JDATA_27 (0x08000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x08000000 */
+#define ADC_JDR4_JDATA_28 (0x10000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x10000000 */
+#define ADC_JDR4_JDATA_29 (0x20000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x20000000 */
+#define ADC_JDR4_JDATA_30 (0x40000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x40000000 */
+#define ADC_JDR4_JDATA_31 (0x80000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x80000000 */
+
+/******************** Bit definition for ADC_AWD2CR register ********************/
+#define ADC_AWD2CR_AWD2CH_Pos (0U)
+#define ADC_AWD2CR_AWD2CH_Msk (0xFFFFFUL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x000FFFFF */
+#define ADC_AWD2CR_AWD2CH ADC_AWD2CR_AWD2CH_Msk /*!< ADC Analog watchdog 2 channel selection */
+#define ADC_AWD2CR_AWD2CH_0 (0x00001UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000001 */
+#define ADC_AWD2CR_AWD2CH_1 (0x00002UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000002 */
+#define ADC_AWD2CR_AWD2CH_2 (0x00004UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000004 */
+#define ADC_AWD2CR_AWD2CH_3 (0x00008UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000008 */
+#define ADC_AWD2CR_AWD2CH_4 (0x00010UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000010 */
+#define ADC_AWD2CR_AWD2CH_5 (0x00020UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000020 */
+#define ADC_AWD2CR_AWD2CH_6 (0x00040UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000040 */
+#define ADC_AWD2CR_AWD2CH_7 (0x00080UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000080 */
+#define ADC_AWD2CR_AWD2CH_8 (0x00100UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000100 */
+#define ADC_AWD2CR_AWD2CH_9 (0x00200UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000200 */
+#define ADC_AWD2CR_AWD2CH_10 (0x00400UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000400 */
+#define ADC_AWD2CR_AWD2CH_11 (0x00800UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000800 */
+#define ADC_AWD2CR_AWD2CH_12 (0x01000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00001000 */
+#define ADC_AWD2CR_AWD2CH_13 (0x02000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00002000 */
+#define ADC_AWD2CR_AWD2CH_14 (0x04000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00004000 */
+#define ADC_AWD2CR_AWD2CH_15 (0x08000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00008000 */
+#define ADC_AWD2CR_AWD2CH_16 (0x10000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00010000 */
+#define ADC_AWD2CR_AWD2CH_17 (0x20000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00020000 */
+#define ADC_AWD2CR_AWD2CH_18 (0x40000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00040000 */
+#define ADC_AWD2CR_AWD2CH_19 (0x80000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00080000 */
+
+/******************** Bit definition for ADC_AWD3CR register ********************/
+#define ADC_AWD3CR_AWD3CH_Pos (0U)
+#define ADC_AWD3CR_AWD3CH_Msk (0xFFFFFUL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x000FFFFF */
+#define ADC_AWD3CR_AWD3CH ADC_AWD3CR_AWD3CH_Msk /*!< ADC Analog watchdog 2 channel selection */
+#define ADC_AWD3CR_AWD3CH_0 (0x00001UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000001 */
+#define ADC_AWD3CR_AWD3CH_1 (0x00002UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000002 */
+#define ADC_AWD3CR_AWD3CH_2 (0x00004UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000004 */
+#define ADC_AWD3CR_AWD3CH_3 (0x00008UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000008 */
+#define ADC_AWD3CR_AWD3CH_4 (0x00010UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000010 */
+#define ADC_AWD3CR_AWD3CH_5 (0x00020UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000020 */
+#define ADC_AWD3CR_AWD3CH_6 (0x00040UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000040 */
+#define ADC_AWD3CR_AWD3CH_7 (0x00080UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000080 */
+#define ADC_AWD3CR_AWD3CH_8 (0x00100UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000100 */
+#define ADC_AWD3CR_AWD3CH_9 (0x00200UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000200 */
+#define ADC_AWD3CR_AWD3CH_10 (0x00400UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000400 */
+#define ADC_AWD3CR_AWD3CH_11 (0x00800UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000800 */
+#define ADC_AWD3CR_AWD3CH_12 (0x01000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00001000 */
+#define ADC_AWD3CR_AWD3CH_13 (0x02000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00002000 */
+#define ADC_AWD3CR_AWD3CH_14 (0x04000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00004000 */
+#define ADC_AWD3CR_AWD3CH_15 (0x08000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00008000 */
+#define ADC_AWD3CR_AWD3CH_16 (0x10000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00010000 */
+#define ADC_AWD3CR_AWD3CH_17 (0x20000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00020000 */
+#define ADC_AWD3CR_AWD3CH_18 (0x40000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00040000 */
+#define ADC_AWD3CR_AWD3CH_19 (0x80000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00080000 */
+
+/******************** Bit definition for ADC_DIFSEL register ********************/
+#define ADC_DIFSEL_DIFSEL_Pos (0U)
+#define ADC_DIFSEL_DIFSEL_Msk (0xFFFFFUL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x000FFFFF */
+#define ADC_DIFSEL_DIFSEL ADC_DIFSEL_DIFSEL_Msk /*!< ADC differential modes for channels 1 to 18 */
+#define ADC_DIFSEL_DIFSEL_0 (0x00001UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000001 */
+#define ADC_DIFSEL_DIFSEL_1 (0x00002UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000002 */
+#define ADC_DIFSEL_DIFSEL_2 (0x00004UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000004 */
+#define ADC_DIFSEL_DIFSEL_3 (0x00008UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000008 */
+#define ADC_DIFSEL_DIFSEL_4 (0x00010UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000010 */
+#define ADC_DIFSEL_DIFSEL_5 (0x00020UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000020 */
+#define ADC_DIFSEL_DIFSEL_6 (0x00040UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000040 */
+#define ADC_DIFSEL_DIFSEL_7 (0x00080UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000080 */
+#define ADC_DIFSEL_DIFSEL_8 (0x00100UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000100 */
+#define ADC_DIFSEL_DIFSEL_9 (0x00200UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000200 */
+#define ADC_DIFSEL_DIFSEL_10 (0x00400UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000400 */
+#define ADC_DIFSEL_DIFSEL_11 (0x00800UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000800 */
+#define ADC_DIFSEL_DIFSEL_12 (0x01000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00001000 */
+#define ADC_DIFSEL_DIFSEL_13 (0x02000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00002000 */
+#define ADC_DIFSEL_DIFSEL_14 (0x04000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00004000 */
+#define ADC_DIFSEL_DIFSEL_15 (0x08000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00008000 */
+#define ADC_DIFSEL_DIFSEL_16 (0x10000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00010000 */
+#define ADC_DIFSEL_DIFSEL_17 (0x20000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00020000 */
+#define ADC_DIFSEL_DIFSEL_18 (0x40000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00040000 */
+#define ADC_DIFSEL_DIFSEL_19 (0x80000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00080000 */
+
+/******************** Bit definition for ADC_CALFACT register ********************/
+#define ADC_CALFACT_CALFACT_S_Pos (0U)
+#define ADC_CALFACT_CALFACT_S_Msk (0x7FFUL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x000007FF */
+#define ADC_CALFACT_CALFACT_S ADC_CALFACT_CALFACT_S_Msk /*!< ADC calibration factors in single-ended mode */
+#define ADC_CALFACT_CALFACT_S_0 (0x001UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000001 */
+#define ADC_CALFACT_CALFACT_S_1 (0x002UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000002 */
+#define ADC_CALFACT_CALFACT_S_2 (0x004UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000004 */
+#define ADC_CALFACT_CALFACT_S_3 (0x008UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000008 */
+#define ADC_CALFACT_CALFACT_S_4 (0x010UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000010 */
+#define ADC_CALFACT_CALFACT_S_5 (0x020UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000020 */
+#define ADC_CALFACT_CALFACT_S_6 (0x040UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000040 */
+#define ADC_CALFACT_CALFACT_S_7 (0x080UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000080 */
+#define ADC_CALFACT_CALFACT_S_8 (0x100UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000100 */
+#define ADC_CALFACT_CALFACT_S_9 (0x200UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000200 */
+#define ADC_CALFACT_CALFACT_S_10 (0x400UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000400 */
+#define ADC_CALFACT_CALFACT_D_Pos (16U)
+#define ADC_CALFACT_CALFACT_D_Msk (0x7FFUL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x07FF0000 */
+#define ADC_CALFACT_CALFACT_D ADC_CALFACT_CALFACT_D_Msk /*!< ADC calibration factors in differential mode */
+#define ADC_CALFACT_CALFACT_D_0 (0x001UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00010000 */
+#define ADC_CALFACT_CALFACT_D_1 (0x002UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00020000 */
+#define ADC_CALFACT_CALFACT_D_2 (0x004UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00040000 */
+#define ADC_CALFACT_CALFACT_D_3 (0x008UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00080000 */
+#define ADC_CALFACT_CALFACT_D_4 (0x010UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00100000 */
+#define ADC_CALFACT_CALFACT_D_5 (0x020UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00200000 */
+#define ADC_CALFACT_CALFACT_D_6 (0x040UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00400000 */
+#define ADC_CALFACT_CALFACT_D_7 (0x080UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00800000 */
+#define ADC_CALFACT_CALFACT_D_8 (0x100UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x01000000 */
+#define ADC_CALFACT_CALFACT_D_9 (0x200UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x02000000 */
+#define ADC_CALFACT_CALFACT_D_10 (0x400UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x04000000 */
+
+/******************** Bit definition for ADC_CALFACT2 register ********************/
+#define ADC_CALFACT2_LINCALFACT_Pos (0U)
+#define ADC_CALFACT2_LINCALFACT_Msk (0x3FFFFFFFUL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x3FFFFFFF */
+#define ADC_CALFACT2_LINCALFACT ADC_CALFACT2_LINCALFACT_Msk /*!< ADC Linearity calibration factors */
+#define ADC_CALFACT2_LINCALFACT_0 (0x00000001UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000001 */
+#define ADC_CALFACT2_LINCALFACT_1 (0x00000002UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000002 */
+#define ADC_CALFACT2_LINCALFACT_2 (0x00000004UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000004 */
+#define ADC_CALFACT2_LINCALFACT_3 (0x00000008UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000008 */
+#define ADC_CALFACT2_LINCALFACT_4 (0x00000010UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000010 */
+#define ADC_CALFACT2_LINCALFACT_5 (0x00000020UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000020 */
+#define ADC_CALFACT2_LINCALFACT_6 (0x00000040UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000040 */
+#define ADC_CALFACT2_LINCALFACT_7 (0x00000080UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000080 */
+#define ADC_CALFACT2_LINCALFACT_8 (0x00000100UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000100 */
+#define ADC_CALFACT2_LINCALFACT_9 (0x00000200UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000200 */
+#define ADC_CALFACT2_LINCALFACT_10 (0x00000400UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000400 */
+#define ADC_CALFACT2_LINCALFACT_11 (0x00000800UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000800 */
+#define ADC_CALFACT2_LINCALFACT_12 (0x00001000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00001000 */
+#define ADC_CALFACT2_LINCALFACT_13 (0x00002000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00002000 */
+#define ADC_CALFACT2_LINCALFACT_14 (0x00004000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00004000 */
+#define ADC_CALFACT2_LINCALFACT_15 (0x00008000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00008000 */
+#define ADC_CALFACT2_LINCALFACT_16 (0x00010000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00010000 */
+#define ADC_CALFACT2_LINCALFACT_17 (0x00020000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00020000 */
+#define ADC_CALFACT2_LINCALFACT_18 (0x00040000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00040000 */
+#define ADC_CALFACT2_LINCALFACT_19 (0x00080000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00080000 */
+#define ADC_CALFACT2_LINCALFACT_20 (0x00100000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00100000 */
+#define ADC_CALFACT2_LINCALFACT_21 (0x00200000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00200000 */
+#define ADC_CALFACT2_LINCALFACT_22 (0x00400000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00400000 */
+#define ADC_CALFACT2_LINCALFACT_23 (0x00800000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00800000 */
+#define ADC_CALFACT2_LINCALFACT_24 (0x01000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x01000000 */
+#define ADC_CALFACT2_LINCALFACT_25 (0x02000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x02000000 */
+#define ADC_CALFACT2_LINCALFACT_26 (0x04000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x04000000 */
+#define ADC_CALFACT2_LINCALFACT_27 (0x08000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x08000000 */
+#define ADC_CALFACT2_LINCALFACT_28 (0x10000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x10000000 */
+#define ADC_CALFACT2_LINCALFACT_29 (0x20000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x20000000 */
+
+/************************* ADC Common registers *****************************/
+/******************** Bit definition for ADC_CSR register ********************/
+#define ADC_CSR_ADRDY_MST_Pos (0U)
+#define ADC_CSR_ADRDY_MST_Msk (0x1UL << ADC_CSR_ADRDY_MST_Pos) /*!< 0x00000001 */
+#define ADC_CSR_ADRDY_MST ADC_CSR_ADRDY_MST_Msk /*!< Master ADC ready */
+#define ADC_CSR_EOSMP_MST_Pos (1U)
+#define ADC_CSR_EOSMP_MST_Msk (0x1UL << ADC_CSR_EOSMP_MST_Pos) /*!< 0x00000002 */
+#define ADC_CSR_EOSMP_MST ADC_CSR_EOSMP_MST_Msk /*!< End of sampling phase flag of the master ADC */
+#define ADC_CSR_EOC_MST_Pos (2U)
+#define ADC_CSR_EOC_MST_Msk (0x1UL << ADC_CSR_EOC_MST_Pos) /*!< 0x00000004 */
+#define ADC_CSR_EOC_MST ADC_CSR_EOC_MST_Msk /*!< End of regular conversion of the master ADC */
+#define ADC_CSR_EOS_MST_Pos (3U)
+#define ADC_CSR_EOS_MST_Msk (0x1UL << ADC_CSR_EOS_MST_Pos) /*!< 0x00000008 */
+#define ADC_CSR_EOS_MST ADC_CSR_EOS_MST_Msk /*!< End of regular sequence flag of the master ADC */
+#define ADC_CSR_OVR_MST_Pos (4U)
+#define ADC_CSR_OVR_MST_Msk (0x1UL << ADC_CSR_OVR_MST_Pos) /*!< 0x00000010 */
+#define ADC_CSR_OVR_MST ADC_CSR_OVR_MST_Msk /*!< Overrun flag of the master ADC */
+#define ADC_CSR_JEOC_MST_Pos (5U)
+#define ADC_CSR_JEOC_MST_Msk (0x1UL << ADC_CSR_JEOC_MST_Pos) /*!< 0x00000020 */
+#define ADC_CSR_JEOC_MST ADC_CSR_JEOC_MST_Msk /*!< End of injected conversion of the master ADC */
+#define ADC_CSR_JEOS_MST_Pos (6U)
+#define ADC_CSR_JEOS_MST_Msk (0x1UL << ADC_CSR_JEOS_MST_Pos) /*!< 0x00000040 */
+#define ADC_CSR_JEOS_MST ADC_CSR_JEOS_MST_Msk /*!< End of injected sequence flag of the master ADC */
+#define ADC_CSR_AWD1_MST_Pos (7U)
+#define ADC_CSR_AWD1_MST_Msk (0x1UL << ADC_CSR_AWD1_MST_Pos) /*!< 0x00000080 */
+#define ADC_CSR_AWD1_MST ADC_CSR_AWD1_MST_Msk /*!< Analog watchdog 1 flag of the master ADC */
+#define ADC_CSR_AWD2_MST_Pos (8U)
+#define ADC_CSR_AWD2_MST_Msk (0x1UL << ADC_CSR_AWD2_MST_Pos) /*!< 0x00000100 */
+#define ADC_CSR_AWD2_MST ADC_CSR_AWD2_MST_Msk /*!< Analog watchdog 2 flag of the master ADC */
+#define ADC_CSR_AWD3_MST_Pos (9U)
+#define ADC_CSR_AWD3_MST_Msk (0x1UL << ADC_CSR_AWD3_MST_Pos) /*!< 0x00000200 */
+#define ADC_CSR_AWD3_MST ADC_CSR_AWD3_MST_Msk /*!< Analog watchdog 3 flag of the master ADC */
+#define ADC_CSR_JQOVF_MST_Pos (10U)
+#define ADC_CSR_JQOVF_MST_Msk (0x1UL << ADC_CSR_JQOVF_MST_Pos) /*!< 0x00000400 */
+#define ADC_CSR_JQOVF_MST ADC_CSR_JQOVF_MST_Msk /*!< Injected context queue overflow flag of the master ADC */
+#define ADC_CSR_ADRDY_SLV_Pos (16U)
+#define ADC_CSR_ADRDY_SLV_Msk (0x1UL << ADC_CSR_ADRDY_SLV_Pos) /*!< 0x00010000 */
+#define ADC_CSR_ADRDY_SLV ADC_CSR_ADRDY_SLV_Msk /*!< Slave ADC ready */
+#define ADC_CSR_EOSMP_SLV_Pos (17U)
+#define ADC_CSR_EOSMP_SLV_Msk (0x1UL << ADC_CSR_EOSMP_SLV_Pos) /*!< 0x00020000 */
+#define ADC_CSR_EOSMP_SLV ADC_CSR_EOSMP_SLV_Msk /*!< End of sampling phase flag of the slave ADC */
+#define ADC_CSR_EOC_SLV_Pos (18U)
+#define ADC_CSR_EOC_SLV_Msk (0x1UL << ADC_CSR_EOC_SLV_Pos) /*!< 0x00040000 */
+#define ADC_CSR_EOC_SLV ADC_CSR_EOC_SLV_Msk /*!< End of regular conversion of the slave ADC */
+#define ADC_CSR_EOS_SLV_Pos (19U)
+#define ADC_CSR_EOS_SLV_Msk (0x1UL << ADC_CSR_EOS_SLV_Pos) /*!< 0x00080000 */
+#define ADC_CSR_EOS_SLV ADC_CSR_EOS_SLV_Msk /*!< End of regular sequence flag of the slave ADC */
+#define ADC_CSR_OVR_SLV_Pos (20U)
+#define ADC_CSR_OVR_SLV_Msk (0x1UL << ADC_CSR_OVR_SLV_Pos) /*!< 0x00100000 */
+#define ADC_CSR_OVR_SLV ADC_CSR_OVR_SLV_Msk /*!< Overrun flag of the slave ADC */
+#define ADC_CSR_JEOC_SLV_Pos (21U)
+#define ADC_CSR_JEOC_SLV_Msk (0x1UL << ADC_CSR_JEOC_SLV_Pos) /*!< 0x00200000 */
+#define ADC_CSR_JEOC_SLV ADC_CSR_JEOC_SLV_Msk /*!< End of injected conversion of the slave ADC */
+#define ADC_CSR_JEOS_SLV_Pos (22U)
+#define ADC_CSR_JEOS_SLV_Msk (0x1UL << ADC_CSR_JEOS_SLV_Pos) /*!< 0x00400000 */
+#define ADC_CSR_JEOS_SLV ADC_CSR_JEOS_SLV_Msk /*!< End of injected sequence flag of the slave ADC */
+#define ADC_CSR_AWD1_SLV_Pos (23U)
+#define ADC_CSR_AWD1_SLV_Msk (0x1UL << ADC_CSR_AWD1_SLV_Pos) /*!< 0x00800000 */
+#define ADC_CSR_AWD1_SLV ADC_CSR_AWD1_SLV_Msk /*!< Analog watchdog 1 flag of the slave ADC */
+#define ADC_CSR_AWD2_SLV_Pos (24U)
+#define ADC_CSR_AWD2_SLV_Msk (0x1UL << ADC_CSR_AWD2_SLV_Pos) /*!< 0x01000000 */
+#define ADC_CSR_AWD2_SLV ADC_CSR_AWD2_SLV_Msk /*!< Analog watchdog 2 flag of the slave ADC */
+#define ADC_CSR_AWD3_SLV_Pos (25U)
+#define ADC_CSR_AWD3_SLV_Msk (0x1UL << ADC_CSR_AWD3_SLV_Pos) /*!< 0x02000000 */
+#define ADC_CSR_AWD3_SLV ADC_CSR_AWD3_SLV_Msk /*!< Analog watchdog 3 flag of the slave ADC */
+#define ADC_CSR_JQOVF_SLV_Pos (26U)
+#define ADC_CSR_JQOVF_SLV_Msk (0x1UL << ADC_CSR_JQOVF_SLV_Pos) /*!< 0x04000000 */
+#define ADC_CSR_JQOVF_SLV ADC_CSR_JQOVF_SLV_Msk /*!< Injected context queue overflow flag of the slave ADC */
+
+/******************** Bit definition for ADC_CCR register ********************/
+#define ADC_CCR_DUAL_Pos (0U)
+#define ADC_CCR_DUAL_Msk (0x1FUL << ADC_CCR_DUAL_Pos) /*!< 0x0000001F */
+#define ADC_CCR_DUAL ADC_CCR_DUAL_Msk /*!< Dual ADC mode selection */
+#define ADC_CCR_DUAL_0 (0x01UL << ADC_CCR_DUAL_Pos) /*!< 0x00000001 */
+#define ADC_CCR_DUAL_1 (0x02UL << ADC_CCR_DUAL_Pos) /*!< 0x00000002 */
+#define ADC_CCR_DUAL_2 (0x04UL << ADC_CCR_DUAL_Pos) /*!< 0x00000004 */
+#define ADC_CCR_DUAL_3 (0x08UL << ADC_CCR_DUAL_Pos) /*!< 0x00000008 */
+#define ADC_CCR_DUAL_4 (0x10UL << ADC_CCR_DUAL_Pos) /*!< 0x00000010 */
+
+#define ADC_CCR_DELAY_Pos (8U)
+#define ADC_CCR_DELAY_Msk (0xFUL << ADC_CCR_DELAY_Pos) /*!< 0x00000F00 */
+#define ADC_CCR_DELAY ADC_CCR_DELAY_Msk /*!< Delay between 2 sampling phases */
+#define ADC_CCR_DELAY_0 (0x1UL << ADC_CCR_DELAY_Pos) /*!< 0x00000100 */
+#define ADC_CCR_DELAY_1 (0x2UL << ADC_CCR_DELAY_Pos) /*!< 0x00000200 */
+#define ADC_CCR_DELAY_2 (0x4UL << ADC_CCR_DELAY_Pos) /*!< 0x00000400 */
+#define ADC_CCR_DELAY_3 (0x8UL << ADC_CCR_DELAY_Pos) /*!< 0x00000800 */
+
+
+#define ADC_CCR_DAMDF_Pos (14U)
+#define ADC_CCR_DAMDF_Msk (0x3UL << ADC_CCR_DAMDF_Pos) /*!< 0x0000C000 */
+#define ADC_CCR_DAMDF ADC_CCR_DAMDF_Msk /*!< Dual ADC mode Data format */
+#define ADC_CCR_DAMDF_0 (0x1UL << ADC_CCR_DAMDF_Pos) /*!< 0x00004000 */
+#define ADC_CCR_DAMDF_1 (0x2UL << ADC_CCR_DAMDF_Pos) /*!< 0x00008000 */
+
+#define ADC_CCR_CKMODE_Pos (16U)
+#define ADC_CCR_CKMODE_Msk (0x3UL << ADC_CCR_CKMODE_Pos) /*!< 0x00030000 */
+#define ADC_CCR_CKMODE ADC_CCR_CKMODE_Msk /*!< ADC clock mode */
+#define ADC_CCR_CKMODE_0 (0x1UL << ADC_CCR_CKMODE_Pos) /*!< 0x00010000 */
+#define ADC_CCR_CKMODE_1 (0x2UL << ADC_CCR_CKMODE_Pos) /*!< 0x00020000 */
+
+#define ADC_CCR_PRESC_Pos (18U)
+#define ADC_CCR_PRESC_Msk (0xFUL << ADC_CCR_PRESC_Pos) /*!< 0x003C0000 */
+#define ADC_CCR_PRESC ADC_CCR_PRESC_Msk /*!< ADC prescaler */
+#define ADC_CCR_PRESC_0 (0x1UL << ADC_CCR_PRESC_Pos) /*!< 0x00040000 */
+#define ADC_CCR_PRESC_1 (0x2UL << ADC_CCR_PRESC_Pos) /*!< 0x00080000 */
+#define ADC_CCR_PRESC_2 (0x4UL << ADC_CCR_PRESC_Pos) /*!< 0x00100000 */
+#define ADC_CCR_PRESC_3 (0x8UL << ADC_CCR_PRESC_Pos) /*!< 0x00200000 */
+
+#define ADC_CCR_VREFEN_Pos (22U)
+#define ADC_CCR_VREFEN_Msk (0x1UL << ADC_CCR_VREFEN_Pos) /*!< 0x00400000 */
+#define ADC_CCR_VREFEN ADC_CCR_VREFEN_Msk /*!< VREFINT enable */
+#define ADC_CCR_TSEN_Pos (23U)
+#define ADC_CCR_TSEN_Msk (0x1UL << ADC_CCR_TSEN_Pos) /*!< 0x00800000 */
+#define ADC_CCR_TSEN ADC_CCR_TSEN_Msk /*!< Temperature sensor enable */
+#define ADC_CCR_VBATEN_Pos (24U)
+#define ADC_CCR_VBATEN_Msk (0x1UL << ADC_CCR_VBATEN_Pos) /*!< 0x01000000 */
+#define ADC_CCR_VBATEN ADC_CCR_VBATEN_Msk /*!< VBAT enable */
+
+/******************** Bit definition for ADC_CDR register *******************/
+#define ADC_CDR_RDATA_MST_Pos (0U)
+#define ADC_CDR_RDATA_MST_Msk (0xFFFFUL << ADC_CDR_RDATA_MST_Pos) /*!< 0x0000FFFF */
+#define ADC_CDR_RDATA_MST ADC_CDR_RDATA_MST_Msk /*!< ADC multimode master group regular conversion data */
+
+#define ADC_CDR_RDATA_SLV_Pos (16U)
+#define ADC_CDR_RDATA_SLV_Msk (0xFFFFUL << ADC_CDR_RDATA_SLV_Pos) /*!< 0xFFFF0000 */
+#define ADC_CDR_RDATA_SLV ADC_CDR_RDATA_SLV_Msk /*!< ADC multimode slave group regular conversion data */
+
+/******************** Bit definition for ADC_CDR2 register ******************/
+#define ADC_CDR2_RDATA_ALT_Pos (0U)
+#define ADC_CDR2_RDATA_ALT_Msk (0xFFFFFFFFUL << ADC_CDR2_RDATA_ALT_Pos) /*!< 0xFFFFFFFF */
+#define ADC_CDR2_RDATA_ALT ADC_CDR2_RDATA_ALT_Msk /*!< Regular data of the master/slave alternated ADCs */
+
+
+/******************************************************************************/
+/* */
+/* VREFBUF */
+/* */
+/******************************************************************************/
+/******************* Bit definition for VREFBUF_CSR register ****************/
+#define VREFBUF_CSR_ENVR_Pos (0U)
+#define VREFBUF_CSR_ENVR_Msk (0x1UL << VREFBUF_CSR_ENVR_Pos) /*!< 0x00000001 */
+#define VREFBUF_CSR_ENVR VREFBUF_CSR_ENVR_Msk /*!*/
+#define DAC_CR_CEN1_Pos (14U)
+#define DAC_CR_CEN1_Msk (0x1UL << DAC_CR_CEN1_Pos) /*!< 0x00004000 */
+#define DAC_CR_CEN1 DAC_CR_CEN1_Msk /*!*/
+
+#define DAC_CR_EN2_Pos (16U)
+#define DAC_CR_EN2_Msk (0x1UL << DAC_CR_EN2_Pos) /*!< 0x00010000 */
+#define DAC_CR_EN2 DAC_CR_EN2_Msk /*!*/
+#define DAC_CR_CEN2_Pos (30U)
+#define DAC_CR_CEN2_Msk (0x1UL << DAC_CR_CEN2_Pos) /*!< 0x40000000 */
+#define DAC_CR_CEN2 DAC_CR_CEN2_Msk /*!*/
+
+/***************** Bit definition for DAC_SWTRIGR register ******************/
+#define DAC_SWTRIGR_SWTRIG1_Pos (0U)
+#define DAC_SWTRIGR_SWTRIG1_Msk (0x1UL << DAC_SWTRIGR_SWTRIG1_Pos) /*!< 0x00000001 */
+#define DAC_SWTRIGR_SWTRIG1 DAC_SWTRIGR_SWTRIG1_Msk /*!© Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/** @addtogroup CMSIS
+ * @{
+ */
+
+/** @addtogroup stm32h7xx
+ * @{
+ */
+
+#ifndef STM32H7xx_H
+#define STM32H7xx_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif /* __cplusplus */
+
+/** @addtogroup Library_configuration_section
+ * @{
+ */
+
+/**
+ * @brief STM32 Family
+ */
+#if !defined (STM32H7)
+#define STM32H7
+#endif /* STM32H7 */
+
+
+/* Uncomment the line below according to the target STM32H7 device used in your
+ application
+ */
+
+#if !defined (STM32H743xx) && !defined (STM32H753xx) && !defined (STM32H750xx) && !defined (STM32H742xx) && \
+ !defined (STM32H745xx) && !defined (STM32H755xx) && !defined (STM32H747xx) && !defined (STM32H757xx) && \
+ !defined (STM32H7A3xx) && !defined (STM32H7A3xxQ) && !defined (STM32H7B3xx) && !defined (STM32H7B3xxQ) && !defined (STM32H7B0xx) && !defined (STM32H7B0xxQ) && \
+ !defined (STM32H723xx)
+ /* #define STM32H742xx */ /*!< STM32H742VI, STM32H742ZI, STM32H742AI, STM32H742II, STM32H742BI, STM32H742XI Devices */
+ /* #define STM32H743xx */ /*!< STM32H743VI, STM32H743ZI, STM32H743AI, STM32H743II, STM32H743BI, STM32H743XI Devices */
+ /* #define STM32H753xx */ /*!< STM32H753VI, STM32H753ZI, STM32H753AI, STM32H753II, STM32H753BI, STM32H753XI Devices */
+ /* #define STM32H750xx */ /*!< STM32H750V, STM32H750I, STM32H750X Devices */
+ /* #define STM32H747xx */ /*!< STM32H747ZI, STM32H747AI, STM32H747II, STM32H747BI, STM32H747XI Devices */
+ /* #define STM32H757xx */ /*!< STM32H757ZI, STM32H757AI, STM32H757II, STM32H757BI, STM32H757XI Devices */
+ /* #define STM32H745xx */ /*!< STM32H745ZI, STM32H745II, STM32H745BI, STM32H745XI Devices */
+ /* #define STM32H755xx */ /*!< STM32H755ZI, STM32H755II, STM32H755BI, STM32H755XI Devices */
+ /* #define STM32H7B0xx */ /*!< STM32H7B0ABIxQ, STM32H7B0IBTx, STM32H7B0RBTx, STM32H7B0VBTx, STM32H7B0ZBTx, STM32H7B0IBKxQ */
+ /* #define STM32H7A3xx */ /*!< STM32H7A3IIK6, STM32H7A3IIT6, STM32H7A3NIH6, STM32H7A3RIT6, STM32H7A3VIH6, STM32H7A3VIT6, STM32H7A3ZIT6 */
+ /* #define STM32H7A3xxQ */ /*!< STM32H7A3QIY6Q, STM32H7A3IIK6Q, STM32H7A3IIT6Q, STM32H7A3LIH6Q, STM32H7A3VIH6Q, STM32H7A3VIT6Q, STM32H7A3AII6Q, STM32H7A3ZIT6Q */
+ /* #define STM32H7B3xx */ /*!< STM32H7B3IIK6, STM32H7B3IIT6, STM32H7B3NIH6, STM32H7B3RIT6, STM32H7B3VIH6, STM32H7B3VIT6, STM32H7B3ZIT6 */
+ /* #define STM32H7B3xxQ */ /*!< STM32H7B3QIY6Q, STM32H7B3IIK6Q, STM32H7B3IIT6Q, STM32H7B3LIH6Q, STM32H7B3VIH6Q, STM32H7B3VIT6Q, STM32H7B3AII6Q, STM32H7B3ZIT6Q */
+ /* #define STM32H723xx */
+#endif
+
+/* Tip: To avoid modifying this file each time you need to switch between these
+ devices, you can define the device in your toolchain compiler preprocessor.
+ */
+
+#if defined(DUAL_CORE) && !defined(CORE_CM4) && !defined(CORE_CM7)
+ #error "Dual core device, please select CORE_CM4 or CORE_CM7"
+#endif
+
+#if !defined (USE_HAL_DRIVER)
+/**
+ * @brief Comment the line below if you will not use the peripherals drivers.
+ In this case, these drivers will not be included and the application code will
+ be based on direct access to peripherals registers
+ */
+ /*#define USE_HAL_DRIVER */
+#endif /* USE_HAL_DRIVER */
+
+/**
+ * @brief CMSIS Device version number V1.7.0
+ */
+#define __STM32H7xx_CMSIS_DEVICE_VERSION_MAIN (0x01) /*!< [31:24] main version */
+#define __STM32H7xx_CMSIS_DEVICE_VERSION_SUB1 (0x07) /*!< [23:16] sub1 version */
+#define __STM32H7xx_CMSIS_DEVICE_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */
+#define __STM32H7xx_CMSIS_DEVICE_VERSION_RC (0x00) /*!< [7:0] release candidate */
+#define __STM32H7xx_CMSIS_DEVICE_VERSION ((__CMSIS_DEVICE_VERSION_MAIN << 24)\
+ |(__CMSIS_DEVICE_HAL_VERSION_SUB1 << 16)\
+ |(__CMSIS_DEVICE_HAL_VERSION_SUB2 << 8 )\
+ |(__CMSIS_DEVICE_HAL_VERSION_RC))
+
+/**
+ * @}
+ */
+
+/** @addtogroup Device_Included
+ * @{
+ */
+
+#if defined(STM32H743xx)
+ #include "stm32h743xx.h"
+#elif defined(STM32H753xx)
+ #include "stm32h753xx.h"
+#elif defined(STM32H750xx)
+ #include "stm32h750xx.h"
+#elif defined(STM32H742xx)
+ #include "stm32h742xx.h"
+#elif defined(STM32H745xx)
+ #include "stm32h745xx.h"
+#elif defined(STM32H755xx)
+ #include "stm32h755xx.h"
+#elif defined(STM32H747xx)
+ #include "stm32h747xx.h"
+#elif defined(STM32H757xx)
+ #include "stm32h757xx.h"
+#elif defined(STM32H7B0xx)
+ #include "stm32h7b0xx.h"
+#elif defined(STM32H7B0xxQ)
+ #include "stm32h7b0xxq.h"
+#elif defined(STM32H7A3xx)
+ #include "stm32h7a3xx.h"
+#elif defined(STM32H7B3xx)
+ #include "stm32h7b3xx.h"
+#elif defined(STM32H7A3xxQ)
+ #include "stm32h7a3xxq.h"
+#elif defined(STM32H7B3xxQ)
+ #include "stm32h7b3xxq.h"
+#elif defined(STM32H723xx)
+ #include "stm32h723xx.h"
+#else
+ #error "Please select first the target STM32H7xx device used in your application (in stm32h7xx.h file)"
+#endif
+
+/**
+ * @}
+ */
+
+/** @addtogroup Exported_types
+ * @{
+ */
+typedef enum
+{
+ RESET = 0,
+ SET = !RESET
+} FlagStatus, ITStatus;
+
+typedef enum
+{
+ DISABLE = 0,
+ ENABLE = !DISABLE
+} FunctionalState;
+#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))
+
+typedef enum
+{
+ ERROR = 0,
+ SUCCESS = !ERROR
+} ErrorStatus;
+
+/**
+ * @}
+ */
+
+
+/** @addtogroup Exported_macros
+ * @{
+ */
+#define SET_BIT(REG, BIT) ((REG) |= (BIT))
+
+#define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT))
+
+#define READ_BIT(REG, BIT) ((REG) & (BIT))
+
+#define CLEAR_REG(REG) ((REG) = (0x0))
+
+#define WRITE_REG(REG, VAL) ((REG) = (VAL))
+
+#define READ_REG(REG) ((REG))
+
+#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))
+
+#define POSITION_VAL(VAL) (__CLZ(__RBIT(VAL)))
+
+
+/**
+ * @}
+ */
+
+#if defined (USE_HAL_DRIVER)
+ #include "stm32h7xx_hal.h"
+#endif /* USE_HAL_DRIVER */
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* STM32H7xx_H */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ChibiOS_20.3.2/os/common/ext/ST/STM32H7xx/system_stm32h7xx.h b/ChibiOS_20.3.2/os/common/ext/ST/STM32H7xx/system_stm32h7xx.h
new file mode 100644
index 0000000..dd75af6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ST/STM32H7xx/system_stm32h7xx.h
@@ -0,0 +1,105 @@
+/**
+ ******************************************************************************
+ * @file system_stm32h7xx.h
+ * @author MCD Application Team
+ * @brief CMSIS Cortex-Mx Device System Source File for STM32H7xx devices.
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+/** @addtogroup CMSIS
+ * @{
+ */
+
+/** @addtogroup stm32h7xx_system
+ * @{
+ */
+
+/**
+ * @brief Define to prevent recursive inclusion
+ */
+#ifndef SYSTEM_STM32H7XX_H
+#define SYSTEM_STM32H7XX_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/** @addtogroup STM32H7xx_System_Includes
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @addtogroup STM32H7xx_System_Exported_types
+ * @{
+ */
+ /* This variable is updated in three ways:
+ 1) by calling CMSIS function SystemCoreClockUpdate()
+ 2) by calling HAL API function HAL_RCC_GetSysClockFreq()
+ 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
+ Note: If you use this function to configure the system clock; then there
+ is no need to call the 2 first functions listed above, since SystemCoreClock
+ variable is updated automatically.
+ */
+extern uint32_t SystemCoreClock; /*!< System Domain1 Clock Frequency */
+extern uint32_t SystemD2Clock; /*!< System Domain2 Clock Frequency */
+extern const uint8_t D1CorePrescTable[16] ; /*!< D1CorePrescTable prescalers table values */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32H7xx_System_Exported_Constants
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32H7xx_System_Exported_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32H7xx_System_Exported_Functions
+ * @{
+ */
+
+extern void SystemInit(void);
+extern void SystemCoreClockUpdate(void);
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SYSTEM_STM32H7XX_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ChibiOS_20.3.2/os/common/ext/ST/STM32L4xx/stm32l476xx.h b/ChibiOS_20.3.2/os/common/ext/ST/STM32L4xx/stm32l476xx.h
new file mode 100644
index 0000000..4f2b2a1
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ST/STM32L4xx/stm32l476xx.h
@@ -0,0 +1,18537 @@
+/**
+ ******************************************************************************
+ * @file stm32l476xx.h
+ * @author MCD Application Team
+ * @brief CMSIS STM32L476xx Device Peripheral Access Layer Header File.
+ *
+ * This file contains:
+ * - Data structures and the address mapping for all peripherals
+ * - Peripheral's registers declarations and bits definition
+ * - Macros to access peripheral’s registers hardware
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT(c) 2017 STMicroelectronics
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/** @addtogroup CMSIS_Device
+ * @{
+ */
+
+/** @addtogroup stm32l476xx
+ * @{
+ */
+
+#ifndef __STM32L476xx_H
+#define __STM32L476xx_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif /* __cplusplus */
+
+/** @addtogroup Configuration_section_for_CMSIS
+ * @{
+ */
+
+/**
+ * @brief Configuration of the Cortex-M4 Processor and Core Peripherals
+ */
+#define __CM4_REV 0x0001 /*!< Cortex-M4 revision r0p1 */
+#define __MPU_PRESENT 1 /*!< STM32L4XX provides an MPU */
+#define __NVIC_PRIO_BITS 4 /*!< STM32L4XX uses 4 Bits for the Priority Levels */
+#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */
+#define __FPU_PRESENT 1 /*!< FPU present */
+
+/**
+ * @}
+ */
+
+/** @addtogroup Peripheral_interrupt_number_definition
+ * @{
+ */
+
+/**
+ * @brief STM32L4XX Interrupt Number Definition, according to the selected device
+ * in @ref Library_configuration_section
+ */
+typedef enum
+{
+/****** Cortex-M4 Processor Exceptions Numbers ****************************************************************/
+ NonMaskableInt_IRQn = -14, /*!< 2 Cortex-M4 Non Maskable Interrupt */
+ HardFault_IRQn = -13, /*!< 3 Cortex-M4 Hard Fault Interrupt */
+ MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 Memory Management Interrupt */
+ BusFault_IRQn = -11, /*!< 5 Cortex-M4 Bus Fault Interrupt */
+ UsageFault_IRQn = -10, /*!< 6 Cortex-M4 Usage Fault Interrupt */
+ SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV Call Interrupt */
+ DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 Debug Monitor Interrupt */
+ PendSV_IRQn = -2, /*!< 14 Cortex-M4 Pend SV Interrupt */
+ SysTick_IRQn = -1, /*!< 15 Cortex-M4 System Tick Interrupt */
+/****** STM32 specific Interrupt Numbers **********************************************************************/
+ WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */
+ PVD_PVM_IRQn = 1, /*!< PVD/PVM1/PVM2/PVM3/PVM4 through EXTI Line detection Interrupts */
+ TAMP_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts through the EXTI line */
+ RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI line */
+ FLASH_IRQn = 4, /*!< FLASH global Interrupt */
+ RCC_IRQn = 5, /*!< RCC global Interrupt */
+ EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */
+ EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */
+ EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */
+ EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */
+ EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */
+ DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */
+ DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */
+ DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */
+ DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */
+ DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */
+ DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */
+ DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */
+ ADC1_2_IRQn = 18, /*!< ADC1, ADC2 SAR global Interrupts */
+ CAN1_TX_IRQn = 19, /*!< CAN1 TX Interrupt */
+ CAN1_RX0_IRQn = 20, /*!< CAN1 RX0 Interrupt */
+ CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */
+ CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */
+ EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */
+ TIM1_BRK_TIM15_IRQn = 24, /*!< TIM1 Break interrupt and TIM15 global interrupt */
+ TIM1_UP_TIM16_IRQn = 25, /*!< TIM1 Update Interrupt and TIM16 global interrupt */
+ TIM1_TRG_COM_TIM17_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt and TIM17 global interrupt */
+ TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */
+ TIM2_IRQn = 28, /*!< TIM2 global Interrupt */
+ TIM3_IRQn = 29, /*!< TIM3 global Interrupt */
+ TIM4_IRQn = 30, /*!< TIM4 global Interrupt */
+ I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */
+ I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */
+ I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */
+ I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */
+ SPI1_IRQn = 35, /*!< SPI1 global Interrupt */
+ SPI2_IRQn = 36, /*!< SPI2 global Interrupt */
+ USART1_IRQn = 37, /*!< USART1 global Interrupt */
+ USART2_IRQn = 38, /*!< USART2 global Interrupt */
+ USART3_IRQn = 39, /*!< USART3 global Interrupt */
+ EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */
+ RTC_Alarm_IRQn = 41, /*!< RTC Alarm (A and B) through EXTI Line Interrupt */
+ DFSDM1_FLT3_IRQn = 42, /*!< DFSDM1 Filter 3 global Interrupt */
+ TIM8_BRK_IRQn = 43, /*!< TIM8 Break Interrupt */
+ TIM8_UP_IRQn = 44, /*!< TIM8 Update Interrupt */
+ TIM8_TRG_COM_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt */
+ TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */
+ ADC3_IRQn = 47, /*!< ADC3 global Interrupt */
+ FMC_IRQn = 48, /*!< FMC global Interrupt */
+ SDMMC1_IRQn = 49, /*!< SDMMC1 global Interrupt */
+ TIM5_IRQn = 50, /*!< TIM5 global Interrupt */
+ SPI3_IRQn = 51, /*!< SPI3 global Interrupt */
+ UART4_IRQn = 52, /*!< UART4 global Interrupt */
+ UART5_IRQn = 53, /*!< UART5 global Interrupt */
+ TIM6_DAC_IRQn = 54, /*!< TIM6 global and DAC1&2 underrun error interrupts */
+ TIM7_IRQn = 55, /*!< TIM7 global interrupt */
+ DMA2_Channel1_IRQn = 56, /*!< DMA2 Channel 1 global Interrupt */
+ DMA2_Channel2_IRQn = 57, /*!< DMA2 Channel 2 global Interrupt */
+ DMA2_Channel3_IRQn = 58, /*!< DMA2 Channel 3 global Interrupt */
+ DMA2_Channel4_IRQn = 59, /*!< DMA2 Channel 4 global Interrupt */
+ DMA2_Channel5_IRQn = 60, /*!< DMA2 Channel 5 global Interrupt */
+ DFSDM1_FLT0_IRQn = 61, /*!< DFSDM1 Filter 0 global Interrupt */
+ DFSDM1_FLT1_IRQn = 62, /*!< DFSDM1 Filter 1 global Interrupt */
+ DFSDM1_FLT2_IRQn = 63, /*!< DFSDM1 Filter 2 global Interrupt */
+ COMP_IRQn = 64, /*!< COMP1 and COMP2 Interrupts */
+ LPTIM1_IRQn = 65, /*!< LP TIM1 interrupt */
+ LPTIM2_IRQn = 66, /*!< LP TIM2 interrupt */
+ OTG_FS_IRQn = 67, /*!< USB OTG FS global Interrupt */
+ DMA2_Channel6_IRQn = 68, /*!< DMA2 Channel 6 global interrupt */
+ DMA2_Channel7_IRQn = 69, /*!< DMA2 Channel 7 global interrupt */
+ LPUART1_IRQn = 70, /*!< LP UART1 interrupt */
+ QUADSPI_IRQn = 71, /*!< Quad SPI global interrupt */
+ I2C3_EV_IRQn = 72, /*!< I2C3 event interrupt */
+ I2C3_ER_IRQn = 73, /*!< I2C3 error interrupt */
+ SAI1_IRQn = 74, /*!< Serial Audio Interface 1 global interrupt */
+ SAI2_IRQn = 75, /*!< Serial Audio Interface 2 global interrupt */
+ SWPMI1_IRQn = 76, /*!< Serial Wire Interface 1 global interrupt */
+ TSC_IRQn = 77, /*!< Touch Sense Controller global interrupt */
+ LCD_IRQn = 78, /*!< LCD global interrupt */
+ RNG_IRQn = 80, /*!< RNG global interrupt */
+ FPU_IRQn = 81 /*!< FPU global interrupt */
+} IRQn_Type;
+
+/**
+ * @}
+ */
+
+#include "core_cm4.h" /* Cortex-M4 processor and core peripherals */
+#include "system_stm32l4xx.h"
+#include
+
+/** @addtogroup Peripheral_registers_structures
+ * @{
+ */
+
+/**
+ * @brief Analog to Digital Converter
+ */
+
+typedef struct
+{
+ __IO uint32_t ISR; /*!< ADC interrupt and status register, Address offset: 0x00 */
+ __IO uint32_t IER; /*!< ADC interrupt enable register, Address offset: 0x04 */
+ __IO uint32_t CR; /*!< ADC control register, Address offset: 0x08 */
+ __IO uint32_t CFGR; /*!< ADC configuration register 1, Address offset: 0x0C */
+ __IO uint32_t CFGR2; /*!< ADC configuration register 2, Address offset: 0x10 */
+ __IO uint32_t SMPR1; /*!< ADC sampling time register 1, Address offset: 0x14 */
+ __IO uint32_t SMPR2; /*!< ADC sampling time register 2, Address offset: 0x18 */
+ uint32_t RESERVED1; /*!< Reserved, 0x1C */
+ __IO uint32_t TR1; /*!< ADC analog watchdog 1 threshold register, Address offset: 0x20 */
+ __IO uint32_t TR2; /*!< ADC analog watchdog 2 threshold register, Address offset: 0x24 */
+ __IO uint32_t TR3; /*!< ADC analog watchdog 3 threshold register, Address offset: 0x28 */
+ uint32_t RESERVED2; /*!< Reserved, 0x2C */
+ __IO uint32_t SQR1; /*!< ADC group regular sequencer register 1, Address offset: 0x30 */
+ __IO uint32_t SQR2; /*!< ADC group regular sequencer register 2, Address offset: 0x34 */
+ __IO uint32_t SQR3; /*!< ADC group regular sequencer register 3, Address offset: 0x38 */
+ __IO uint32_t SQR4; /*!< ADC group regular sequencer register 4, Address offset: 0x3C */
+ __IO uint32_t DR; /*!< ADC group regular data register, Address offset: 0x40 */
+ uint32_t RESERVED3; /*!< Reserved, 0x44 */
+ uint32_t RESERVED4; /*!< Reserved, 0x48 */
+ __IO uint32_t JSQR; /*!< ADC group injected sequencer register, Address offset: 0x4C */
+ uint32_t RESERVED5[4]; /*!< Reserved, 0x50 - 0x5C */
+ __IO uint32_t OFR1; /*!< ADC offset register 1, Address offset: 0x60 */
+ __IO uint32_t OFR2; /*!< ADC offset register 2, Address offset: 0x64 */
+ __IO uint32_t OFR3; /*!< ADC offset register 3, Address offset: 0x68 */
+ __IO uint32_t OFR4; /*!< ADC offset register 4, Address offset: 0x6C */
+ uint32_t RESERVED6[4]; /*!< Reserved, 0x70 - 0x7C */
+ __IO uint32_t JDR1; /*!< ADC group injected rank 1 data register, Address offset: 0x80 */
+ __IO uint32_t JDR2; /*!< ADC group injected rank 2 data register, Address offset: 0x84 */
+ __IO uint32_t JDR3; /*!< ADC group injected rank 3 data register, Address offset: 0x88 */
+ __IO uint32_t JDR4; /*!< ADC group injected rank 4 data register, Address offset: 0x8C */
+ uint32_t RESERVED7[4]; /*!< Reserved, 0x090 - 0x09C */
+ __IO uint32_t AWD2CR; /*!< ADC analog watchdog 1 configuration register, Address offset: 0xA0 */
+ __IO uint32_t AWD3CR; /*!< ADC analog watchdog 3 Configuration Register, Address offset: 0xA4 */
+ uint32_t RESERVED8; /*!< Reserved, 0x0A8 */
+ uint32_t RESERVED9; /*!< Reserved, 0x0AC */
+ __IO uint32_t DIFSEL; /*!< ADC differential mode selection register, Address offset: 0xB0 */
+ __IO uint32_t CALFACT; /*!< ADC calibration factors, Address offset: 0xB4 */
+
+} ADC_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t CSR; /*!< ADC common status register, Address offset: ADC1 base address + 0x300 */
+ uint32_t RESERVED; /*!< Reserved, Address offset: ADC1 base address + 0x304 */
+ __IO uint32_t CCR; /*!< ADC common configuration register, Address offset: ADC1 base address + 0x308 */
+ __IO uint32_t CDR; /*!< ADC common group regular data register Address offset: ADC1 base address + 0x30C */
+} ADC_Common_TypeDef;
+
+
+/**
+ * @brief Controller Area Network TxMailBox
+ */
+
+typedef struct
+{
+ __IO uint32_t TIR; /*!< CAN TX mailbox identifier register */
+ __IO uint32_t TDTR; /*!< CAN mailbox data length control and time stamp register */
+ __IO uint32_t TDLR; /*!< CAN mailbox data low register */
+ __IO uint32_t TDHR; /*!< CAN mailbox data high register */
+} CAN_TxMailBox_TypeDef;
+
+/**
+ * @brief Controller Area Network FIFOMailBox
+ */
+
+typedef struct
+{
+ __IO uint32_t RIR; /*!< CAN receive FIFO mailbox identifier register */
+ __IO uint32_t RDTR; /*!< CAN receive FIFO mailbox data length control and time stamp register */
+ __IO uint32_t RDLR; /*!< CAN receive FIFO mailbox data low register */
+ __IO uint32_t RDHR; /*!< CAN receive FIFO mailbox data high register */
+} CAN_FIFOMailBox_TypeDef;
+
+/**
+ * @brief Controller Area Network FilterRegister
+ */
+
+typedef struct
+{
+ __IO uint32_t FR1; /*!< CAN Filter bank register 1 */
+ __IO uint32_t FR2; /*!< CAN Filter bank register 1 */
+} CAN_FilterRegister_TypeDef;
+
+/**
+ * @brief Controller Area Network
+ */
+
+typedef struct
+{
+ __IO uint32_t MCR; /*!< CAN master control register, Address offset: 0x00 */
+ __IO uint32_t MSR; /*!< CAN master status register, Address offset: 0x04 */
+ __IO uint32_t TSR; /*!< CAN transmit status register, Address offset: 0x08 */
+ __IO uint32_t RF0R; /*!< CAN receive FIFO 0 register, Address offset: 0x0C */
+ __IO uint32_t RF1R; /*!< CAN receive FIFO 1 register, Address offset: 0x10 */
+ __IO uint32_t IER; /*!< CAN interrupt enable register, Address offset: 0x14 */
+ __IO uint32_t ESR; /*!< CAN error status register, Address offset: 0x18 */
+ __IO uint32_t BTR; /*!< CAN bit timing register, Address offset: 0x1C */
+ uint32_t RESERVED0[88]; /*!< Reserved, 0x020 - 0x17F */
+ CAN_TxMailBox_TypeDef sTxMailBox[3]; /*!< CAN Tx MailBox, Address offset: 0x180 - 0x1AC */
+ CAN_FIFOMailBox_TypeDef sFIFOMailBox[2]; /*!< CAN FIFO MailBox, Address offset: 0x1B0 - 0x1CC */
+ uint32_t RESERVED1[12]; /*!< Reserved, 0x1D0 - 0x1FF */
+ __IO uint32_t FMR; /*!< CAN filter master register, Address offset: 0x200 */
+ __IO uint32_t FM1R; /*!< CAN filter mode register, Address offset: 0x204 */
+ uint32_t RESERVED2; /*!< Reserved, 0x208 */
+ __IO uint32_t FS1R; /*!< CAN filter scale register, Address offset: 0x20C */
+ uint32_t RESERVED3; /*!< Reserved, 0x210 */
+ __IO uint32_t FFA1R; /*!< CAN filter FIFO assignment register, Address offset: 0x214 */
+ uint32_t RESERVED4; /*!< Reserved, 0x218 */
+ __IO uint32_t FA1R; /*!< CAN filter activation register, Address offset: 0x21C */
+ uint32_t RESERVED5[8]; /*!< Reserved, 0x220-0x23F */
+ CAN_FilterRegister_TypeDef sFilterRegister[28]; /*!< CAN Filter Register, Address offset: 0x240-0x31C */
+} CAN_TypeDef;
+
+
+/**
+ * @brief Comparator
+ */
+
+typedef struct
+{
+ __IO uint32_t CSR; /*!< COMP control and status register, Address offset: 0x00 */
+} COMP_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t CSR; /*!< COMP control and status register, used for bits common to several COMP instances, Address offset: 0x00 */
+} COMP_Common_TypeDef;
+
+/**
+ * @brief CRC calculation unit
+ */
+
+typedef struct
+{
+ __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */
+ __IO uint8_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */
+ uint8_t RESERVED0; /*!< Reserved, 0x05 */
+ uint16_t RESERVED1; /*!< Reserved, 0x06 */
+ __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */
+ uint32_t RESERVED2; /*!< Reserved, 0x0C */
+ __IO uint32_t INIT; /*!< Initial CRC value register, Address offset: 0x10 */
+ __IO uint32_t POL; /*!< CRC polynomial register, Address offset: 0x14 */
+} CRC_TypeDef;
+
+/**
+ * @brief Digital to Analog Converter
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< DAC control register, Address offset: 0x00 */
+ __IO uint32_t SWTRIGR; /*!< DAC software trigger register, Address offset: 0x04 */
+ __IO uint32_t DHR12R1; /*!< DAC channel1 12-bit right-aligned data holding register, Address offset: 0x08 */
+ __IO uint32_t DHR12L1; /*!< DAC channel1 12-bit left aligned data holding register, Address offset: 0x0C */
+ __IO uint32_t DHR8R1; /*!< DAC channel1 8-bit right aligned data holding register, Address offset: 0x10 */
+ __IO uint32_t DHR12R2; /*!< DAC channel2 12-bit right aligned data holding register, Address offset: 0x14 */
+ __IO uint32_t DHR12L2; /*!< DAC channel2 12-bit left aligned data holding register, Address offset: 0x18 */
+ __IO uint32_t DHR8R2; /*!< DAC channel2 8-bit right-aligned data holding register, Address offset: 0x1C */
+ __IO uint32_t DHR12RD; /*!< Dual DAC 12-bit right-aligned data holding register, Address offset: 0x20 */
+ __IO uint32_t DHR12LD; /*!< DUAL DAC 12-bit left aligned data holding register, Address offset: 0x24 */
+ __IO uint32_t DHR8RD; /*!< DUAL DAC 8-bit right aligned data holding register, Address offset: 0x28 */
+ __IO uint32_t DOR1; /*!< DAC channel1 data output register, Address offset: 0x2C */
+ __IO uint32_t DOR2; /*!< DAC channel2 data output register, Address offset: 0x30 */
+ __IO uint32_t SR; /*!< DAC status register, Address offset: 0x34 */
+ __IO uint32_t CCR; /*!< DAC calibration control register, Address offset: 0x38 */
+ __IO uint32_t MCR; /*!< DAC mode control register, Address offset: 0x3C */
+ __IO uint32_t SHSR1; /*!< DAC Sample and Hold sample time register 1, Address offset: 0x40 */
+ __IO uint32_t SHSR2; /*!< DAC Sample and Hold sample time register 2, Address offset: 0x44 */
+ __IO uint32_t SHHR; /*!< DAC Sample and Hold hold time register, Address offset: 0x48 */
+ __IO uint32_t SHRR; /*!< DAC Sample and Hold refresh time register, Address offset: 0x4C */
+} DAC_TypeDef;
+
+/**
+ * @brief DFSDM module registers
+ */
+typedef struct
+{
+ __IO uint32_t FLTCR1; /*!< DFSDM control register1, Address offset: 0x100 */
+ __IO uint32_t FLTCR2; /*!< DFSDM control register2, Address offset: 0x104 */
+ __IO uint32_t FLTISR; /*!< DFSDM interrupt and status register, Address offset: 0x108 */
+ __IO uint32_t FLTICR; /*!< DFSDM interrupt flag clear register, Address offset: 0x10C */
+ __IO uint32_t FLTJCHGR; /*!< DFSDM injected channel group selection register, Address offset: 0x110 */
+ __IO uint32_t FLTFCR; /*!< DFSDM filter control register, Address offset: 0x114 */
+ __IO uint32_t FLTJDATAR; /*!< DFSDM data register for injected group, Address offset: 0x118 */
+ __IO uint32_t FLTRDATAR; /*!< DFSDM data register for regular group, Address offset: 0x11C */
+ __IO uint32_t FLTAWHTR; /*!< DFSDM analog watchdog high threshold register, Address offset: 0x120 */
+ __IO uint32_t FLTAWLTR; /*!< DFSDM analog watchdog low threshold register, Address offset: 0x124 */
+ __IO uint32_t FLTAWSR; /*!< DFSDM analog watchdog status register Address offset: 0x128 */
+ __IO uint32_t FLTAWCFR; /*!< DFSDM analog watchdog clear flag register Address offset: 0x12C */
+ __IO uint32_t FLTEXMAX; /*!< DFSDM extreme detector maximum register, Address offset: 0x130 */
+ __IO uint32_t FLTEXMIN; /*!< DFSDM extreme detector minimum register Address offset: 0x134 */
+ __IO uint32_t FLTCNVTIMR; /*!< DFSDM conversion timer, Address offset: 0x138 */
+} DFSDM_Filter_TypeDef;
+
+/**
+ * @brief DFSDM channel configuration registers
+ */
+typedef struct
+{
+ __IO uint32_t CHCFGR1; /*!< DFSDM channel configuration register1, Address offset: 0x00 */
+ __IO uint32_t CHCFGR2; /*!< DFSDM channel configuration register2, Address offset: 0x04 */
+ __IO uint32_t CHAWSCDR; /*!< DFSDM channel analog watchdog and
+ short circuit detector register, Address offset: 0x08 */
+ __IO uint32_t CHWDATAR; /*!< DFSDM channel watchdog filter data register, Address offset: 0x0C */
+ __IO uint32_t CHDATINR; /*!< DFSDM channel data input register, Address offset: 0x10 */
+} DFSDM_Channel_TypeDef;
+
+/**
+ * @brief Debug MCU
+ */
+
+typedef struct
+{
+ __IO uint32_t IDCODE; /*!< MCU device ID code, Address offset: 0x00 */
+ __IO uint32_t CR; /*!< Debug MCU configuration register, Address offset: 0x04 */
+ __IO uint32_t APB1FZR1; /*!< Debug MCU APB1 freeze register 1, Address offset: 0x08 */
+ __IO uint32_t APB1FZR2; /*!< Debug MCU APB1 freeze register 2, Address offset: 0x0C */
+ __IO uint32_t APB2FZ; /*!< Debug MCU APB2 freeze register, Address offset: 0x10 */
+} DBGMCU_TypeDef;
+
+
+/**
+ * @brief DMA Controller
+ */
+
+typedef struct
+{
+ __IO uint32_t CCR; /*!< DMA channel x configuration register */
+ __IO uint32_t CNDTR; /*!< DMA channel x number of data register */
+ __IO uint32_t CPAR; /*!< DMA channel x peripheral address register */
+ __IO uint32_t CMAR; /*!< DMA channel x memory address register */
+} DMA_Channel_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t ISR; /*!< DMA interrupt status register, Address offset: 0x00 */
+ __IO uint32_t IFCR; /*!< DMA interrupt flag clear register, Address offset: 0x04 */
+} DMA_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t CSELR; /*!< DMA channel selection register */
+} DMA_Request_TypeDef;
+
+/* Legacy define */
+#define DMA_request_TypeDef DMA_Request_TypeDef
+
+
+/**
+ * @brief External Interrupt/Event Controller
+ */
+
+typedef struct
+{
+ __IO uint32_t IMR1; /*!< EXTI Interrupt mask register 1, Address offset: 0x00 */
+ __IO uint32_t EMR1; /*!< EXTI Event mask register 1, Address offset: 0x04 */
+ __IO uint32_t RTSR1; /*!< EXTI Rising trigger selection register 1, Address offset: 0x08 */
+ __IO uint32_t FTSR1; /*!< EXTI Falling trigger selection register 1, Address offset: 0x0C */
+ __IO uint32_t SWIER1; /*!< EXTI Software interrupt event register 1, Address offset: 0x10 */
+ __IO uint32_t PR1; /*!< EXTI Pending register 1, Address offset: 0x14 */
+ uint32_t RESERVED1; /*!< Reserved, 0x18 */
+ uint32_t RESERVED2; /*!< Reserved, 0x1C */
+ __IO uint32_t IMR2; /*!< EXTI Interrupt mask register 2, Address offset: 0x20 */
+ __IO uint32_t EMR2; /*!< EXTI Event mask register 2, Address offset: 0x24 */
+ __IO uint32_t RTSR2; /*!< EXTI Rising trigger selection register 2, Address offset: 0x28 */
+ __IO uint32_t FTSR2; /*!< EXTI Falling trigger selection register 2, Address offset: 0x2C */
+ __IO uint32_t SWIER2; /*!< EXTI Software interrupt event register 2, Address offset: 0x30 */
+ __IO uint32_t PR2; /*!< EXTI Pending register 2, Address offset: 0x34 */
+} EXTI_TypeDef;
+
+
+/**
+ * @brief Firewall
+ */
+
+typedef struct
+{
+ __IO uint32_t CSSA; /*!< Code Segment Start Address register, Address offset: 0x00 */
+ __IO uint32_t CSL; /*!< Code Segment Length register, Address offset: 0x04 */
+ __IO uint32_t NVDSSA; /*!< NON volatile data Segment Start Address register, Address offset: 0x08 */
+ __IO uint32_t NVDSL; /*!< NON volatile data Segment Length register, Address offset: 0x0C */
+ __IO uint32_t VDSSA ; /*!< Volatile data Segment Start Address register, Address offset: 0x10 */
+ __IO uint32_t VDSL ; /*!< Volatile data Segment Length register, Address offset: 0x14 */
+ uint32_t RESERVED1; /*!< Reserved1, Address offset: 0x18 */
+ uint32_t RESERVED2; /*!< Reserved2, Address offset: 0x1C */
+ __IO uint32_t CR ; /*!< Configuration register, Address offset: 0x20 */
+} FIREWALL_TypeDef;
+
+
+/**
+ * @brief FLASH Registers
+ */
+
+typedef struct
+{
+ __IO uint32_t ACR; /*!< FLASH access control register, Address offset: 0x00 */
+ __IO uint32_t PDKEYR; /*!< FLASH power down key register, Address offset: 0x04 */
+ __IO uint32_t KEYR; /*!< FLASH key register, Address offset: 0x08 */
+ __IO uint32_t OPTKEYR; /*!< FLASH option key register, Address offset: 0x0C */
+ __IO uint32_t SR; /*!< FLASH status register, Address offset: 0x10 */
+ __IO uint32_t CR; /*!< FLASH control register, Address offset: 0x14 */
+ __IO uint32_t ECCR; /*!< FLASH ECC register, Address offset: 0x18 */
+ __IO uint32_t RESERVED1; /*!< Reserved1, Address offset: 0x1C */
+ __IO uint32_t OPTR; /*!< FLASH option register, Address offset: 0x20 */
+ __IO uint32_t PCROP1SR; /*!< FLASH bank1 PCROP start address register, Address offset: 0x24 */
+ __IO uint32_t PCROP1ER; /*!< FLASH bank1 PCROP end address register, Address offset: 0x28 */
+ __IO uint32_t WRP1AR; /*!< FLASH bank1 WRP area A address register, Address offset: 0x2C */
+ __IO uint32_t WRP1BR; /*!< FLASH bank1 WRP area B address register, Address offset: 0x30 */
+ uint32_t RESERVED2[4]; /*!< Reserved2, Address offset: 0x34-0x40 */
+ __IO uint32_t PCROP2SR; /*!< FLASH bank2 PCROP start address register, Address offset: 0x44 */
+ __IO uint32_t PCROP2ER; /*!< FLASH bank2 PCROP end address register, Address offset: 0x48 */
+ __IO uint32_t WRP2AR; /*!< FLASH bank2 WRP area A address register, Address offset: 0x4C */
+ __IO uint32_t WRP2BR; /*!< FLASH bank2 WRP area B address register, Address offset: 0x50 */
+} FLASH_TypeDef;
+
+
+/**
+ * @brief Flexible Memory Controller
+ */
+
+typedef struct
+{
+ __IO uint32_t BTCR[8]; /*!< NOR/PSRAM chip-select control register(BCR) and chip-select timing register(BTR), Address offset: 0x00-1C */
+} FMC_Bank1_TypeDef;
+
+/**
+ * @brief Flexible Memory Controller Bank1E
+ */
+
+typedef struct
+{
+ __IO uint32_t BWTR[7]; /*!< NOR/PSRAM write timing registers, Address offset: 0x104-0x11C */
+} FMC_Bank1E_TypeDef;
+
+/**
+ * @brief Flexible Memory Controller Bank3
+ */
+
+typedef struct
+{
+ __IO uint32_t PCR; /*!< NAND Flash control register, Address offset: 0x80 */
+ __IO uint32_t SR; /*!< NAND Flash FIFO status and interrupt register, Address offset: 0x84 */
+ __IO uint32_t PMEM; /*!< NAND Flash Common memory space timing register, Address offset: 0x88 */
+ __IO uint32_t PATT; /*!< NAND Flash Attribute memory space timing register, Address offset: 0x8C */
+ uint32_t RESERVED0; /*!< Reserved, 0x90 */
+ __IO uint32_t ECCR; /*!< NAND Flash ECC result registers, Address offset: 0x94 */
+} FMC_Bank3_TypeDef;
+
+/**
+ * @brief General Purpose I/O
+ */
+
+typedef struct
+{
+ __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */
+ __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */
+ __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */
+ __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */
+ __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */
+ __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */
+ __IO uint32_t BSRR; /*!< GPIO port bit set/reset register, Address offset: 0x18 */
+ __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */
+ __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */
+ __IO uint32_t BRR; /*!< GPIO Bit Reset register, Address offset: 0x28 */
+ __IO uint32_t ASCR; /*!< GPIO analog switch control register, Address offset: 0x2C */
+
+} GPIO_TypeDef;
+
+
+/**
+ * @brief Inter-integrated Circuit Interface
+ */
+
+typedef struct
+{
+ __IO uint32_t CR1; /*!< I2C Control register 1, Address offset: 0x00 */
+ __IO uint32_t CR2; /*!< I2C Control register 2, Address offset: 0x04 */
+ __IO uint32_t OAR1; /*!< I2C Own address 1 register, Address offset: 0x08 */
+ __IO uint32_t OAR2; /*!< I2C Own address 2 register, Address offset: 0x0C */
+ __IO uint32_t TIMINGR; /*!< I2C Timing register, Address offset: 0x10 */
+ __IO uint32_t TIMEOUTR; /*!< I2C Timeout register, Address offset: 0x14 */
+ __IO uint32_t ISR; /*!< I2C Interrupt and status register, Address offset: 0x18 */
+ __IO uint32_t ICR; /*!< I2C Interrupt clear register, Address offset: 0x1C */
+ __IO uint32_t PECR; /*!< I2C PEC register, Address offset: 0x20 */
+ __IO uint32_t RXDR; /*!< I2C Receive data register, Address offset: 0x24 */
+ __IO uint32_t TXDR; /*!< I2C Transmit data register, Address offset: 0x28 */
+} I2C_TypeDef;
+
+/**
+ * @brief Independent WATCHDOG
+ */
+
+typedef struct
+{
+ __IO uint32_t KR; /*!< IWDG Key register, Address offset: 0x00 */
+ __IO uint32_t PR; /*!< IWDG Prescaler register, Address offset: 0x04 */
+ __IO uint32_t RLR; /*!< IWDG Reload register, Address offset: 0x08 */
+ __IO uint32_t SR; /*!< IWDG Status register, Address offset: 0x0C */
+ __IO uint32_t WINR; /*!< IWDG Window register, Address offset: 0x10 */
+} IWDG_TypeDef;
+
+/**
+ * @brief LCD
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< LCD control register, Address offset: 0x00 */
+ __IO uint32_t FCR; /*!< LCD frame control register, Address offset: 0x04 */
+ __IO uint32_t SR; /*!< LCD status register, Address offset: 0x08 */
+ __IO uint32_t CLR; /*!< LCD clear register, Address offset: 0x0C */
+ uint32_t RESERVED; /*!< Reserved, Address offset: 0x10 */
+ __IO uint32_t RAM[16]; /*!< LCD display memory, Address offset: 0x14-0x50 */
+} LCD_TypeDef;
+
+/**
+ * @brief LPTIMER
+ */
+typedef struct
+{
+ __IO uint32_t ISR; /*!< LPTIM Interrupt and Status register, Address offset: 0x00 */
+ __IO uint32_t ICR; /*!< LPTIM Interrupt Clear register, Address offset: 0x04 */
+ __IO uint32_t IER; /*!< LPTIM Interrupt Enable register, Address offset: 0x08 */
+ __IO uint32_t CFGR; /*!< LPTIM Configuration register, Address offset: 0x0C */
+ __IO uint32_t CR; /*!< LPTIM Control register, Address offset: 0x10 */
+ __IO uint32_t CMP; /*!< LPTIM Compare register, Address offset: 0x14 */
+ __IO uint32_t ARR; /*!< LPTIM Autoreload register, Address offset: 0x18 */
+ __IO uint32_t CNT; /*!< LPTIM Counter register, Address offset: 0x1C */
+ __IO uint32_t OR; /*!< LPTIM Option register, Address offset: 0x20 */
+} LPTIM_TypeDef;
+
+/**
+ * @brief Operational Amplifier (OPAMP)
+ */
+
+typedef struct
+{
+ __IO uint32_t CSR; /*!< OPAMP control/status register, Address offset: 0x00 */
+ __IO uint32_t OTR; /*!< OPAMP offset trimming register for normal mode, Address offset: 0x04 */
+ __IO uint32_t LPOTR; /*!< OPAMP offset trimming register for low power mode, Address offset: 0x08 */
+} OPAMP_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t CSR; /*!< OPAMP control/status register, used for bits common to several OPAMP instances, Address offset: 0x00 */
+} OPAMP_Common_TypeDef;
+
+/**
+ * @brief Power Control
+ */
+
+typedef struct
+{
+ __IO uint32_t CR1; /*!< PWR power control register 1, Address offset: 0x00 */
+ __IO uint32_t CR2; /*!< PWR power control register 2, Address offset: 0x04 */
+ __IO uint32_t CR3; /*!< PWR power control register 3, Address offset: 0x08 */
+ __IO uint32_t CR4; /*!< PWR power control register 4, Address offset: 0x0C */
+ __IO uint32_t SR1; /*!< PWR power status register 1, Address offset: 0x10 */
+ __IO uint32_t SR2; /*!< PWR power status register 2, Address offset: 0x14 */
+ __IO uint32_t SCR; /*!< PWR power status reset register, Address offset: 0x18 */
+ uint32_t RESERVED; /*!< Reserved, Address offset: 0x1C */
+ __IO uint32_t PUCRA; /*!< Pull_up control register of portA, Address offset: 0x20 */
+ __IO uint32_t PDCRA; /*!< Pull_Down control register of portA, Address offset: 0x24 */
+ __IO uint32_t PUCRB; /*!< Pull_up control register of portB, Address offset: 0x28 */
+ __IO uint32_t PDCRB; /*!< Pull_Down control register of portB, Address offset: 0x2C */
+ __IO uint32_t PUCRC; /*!< Pull_up control register of portC, Address offset: 0x30 */
+ __IO uint32_t PDCRC; /*!< Pull_Down control register of portC, Address offset: 0x34 */
+ __IO uint32_t PUCRD; /*!< Pull_up control register of portD, Address offset: 0x38 */
+ __IO uint32_t PDCRD; /*!< Pull_Down control register of portD, Address offset: 0x3C */
+ __IO uint32_t PUCRE; /*!< Pull_up control register of portE, Address offset: 0x40 */
+ __IO uint32_t PDCRE; /*!< Pull_Down control register of portE, Address offset: 0x44 */
+ __IO uint32_t PUCRF; /*!< Pull_up control register of portF, Address offset: 0x48 */
+ __IO uint32_t PDCRF; /*!< Pull_Down control register of portF, Address offset: 0x4C */
+ __IO uint32_t PUCRG; /*!< Pull_up control register of portG, Address offset: 0x50 */
+ __IO uint32_t PDCRG; /*!< Pull_Down control register of portG, Address offset: 0x54 */
+ __IO uint32_t PUCRH; /*!< Pull_up control register of portH, Address offset: 0x58 */
+ __IO uint32_t PDCRH; /*!< Pull_Down control register of portH, Address offset: 0x5C */
+} PWR_TypeDef;
+
+
+/**
+ * @brief QUAD Serial Peripheral Interface
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< QUADSPI Control register, Address offset: 0x00 */
+ __IO uint32_t DCR; /*!< QUADSPI Device Configuration register, Address offset: 0x04 */
+ __IO uint32_t SR; /*!< QUADSPI Status register, Address offset: 0x08 */
+ __IO uint32_t FCR; /*!< QUADSPI Flag Clear register, Address offset: 0x0C */
+ __IO uint32_t DLR; /*!< QUADSPI Data Length register, Address offset: 0x10 */
+ __IO uint32_t CCR; /*!< QUADSPI Communication Configuration register, Address offset: 0x14 */
+ __IO uint32_t AR; /*!< QUADSPI Address register, Address offset: 0x18 */
+ __IO uint32_t ABR; /*!< QUADSPI Alternate Bytes register, Address offset: 0x1C */
+ __IO uint32_t DR; /*!< QUADSPI Data register, Address offset: 0x20 */
+ __IO uint32_t PSMKR; /*!< QUADSPI Polling Status Mask register, Address offset: 0x24 */
+ __IO uint32_t PSMAR; /*!< QUADSPI Polling Status Match register, Address offset: 0x28 */
+ __IO uint32_t PIR; /*!< QUADSPI Polling Interval register, Address offset: 0x2C */
+ __IO uint32_t LPTR; /*!< QUADSPI Low Power Timeout register, Address offset: 0x30 */
+} QUADSPI_TypeDef;
+
+
+/**
+ * @brief Reset and Clock Control
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< RCC clock control register, Address offset: 0x00 */
+ __IO uint32_t ICSCR; /*!< RCC internal clock sources calibration register, Address offset: 0x04 */
+ __IO uint32_t CFGR; /*!< RCC clock configuration register, Address offset: 0x08 */
+ __IO uint32_t PLLCFGR; /*!< RCC system PLL configuration register, Address offset: 0x0C */
+ __IO uint32_t PLLSAI1CFGR; /*!< RCC PLL SAI1 configuration register, Address offset: 0x10 */
+ __IO uint32_t PLLSAI2CFGR; /*!< RCC PLL SAI2 configuration register, Address offset: 0x14 */
+ __IO uint32_t CIER; /*!< RCC clock interrupt enable register, Address offset: 0x18 */
+ __IO uint32_t CIFR; /*!< RCC clock interrupt flag register, Address offset: 0x1C */
+ __IO uint32_t CICR; /*!< RCC clock interrupt clear register, Address offset: 0x20 */
+ uint32_t RESERVED0; /*!< Reserved, Address offset: 0x24 */
+ __IO uint32_t AHB1RSTR; /*!< RCC AHB1 peripheral reset register, Address offset: 0x28 */
+ __IO uint32_t AHB2RSTR; /*!< RCC AHB2 peripheral reset register, Address offset: 0x2C */
+ __IO uint32_t AHB3RSTR; /*!< RCC AHB3 peripheral reset register, Address offset: 0x30 */
+ uint32_t RESERVED1; /*!< Reserved, Address offset: 0x34 */
+ __IO uint32_t APB1RSTR1; /*!< RCC APB1 peripheral reset register 1, Address offset: 0x38 */
+ __IO uint32_t APB1RSTR2; /*!< RCC APB1 peripheral reset register 2, Address offset: 0x3C */
+ __IO uint32_t APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x40 */
+ uint32_t RESERVED2; /*!< Reserved, Address offset: 0x44 */
+ __IO uint32_t AHB1ENR; /*!< RCC AHB1 peripheral clocks enable register, Address offset: 0x48 */
+ __IO uint32_t AHB2ENR; /*!< RCC AHB2 peripheral clocks enable register, Address offset: 0x4C */
+ __IO uint32_t AHB3ENR; /*!< RCC AHB3 peripheral clocks enable register, Address offset: 0x50 */
+ uint32_t RESERVED3; /*!< Reserved, Address offset: 0x54 */
+ __IO uint32_t APB1ENR1; /*!< RCC APB1 peripheral clocks enable register 1, Address offset: 0x58 */
+ __IO uint32_t APB1ENR2; /*!< RCC APB1 peripheral clocks enable register 2, Address offset: 0x5C */
+ __IO uint32_t APB2ENR; /*!< RCC APB2 peripheral clocks enable register, Address offset: 0x60 */
+ uint32_t RESERVED4; /*!< Reserved, Address offset: 0x64 */
+ __IO uint32_t AHB1SMENR; /*!< RCC AHB1 peripheral clocks enable in sleep and stop modes register, Address offset: 0x68 */
+ __IO uint32_t AHB2SMENR; /*!< RCC AHB2 peripheral clocks enable in sleep and stop modes register, Address offset: 0x6C */
+ __IO uint32_t AHB3SMENR; /*!< RCC AHB3 peripheral clocks enable in sleep and stop modes register, Address offset: 0x70 */
+ uint32_t RESERVED5; /*!< Reserved, Address offset: 0x74 */
+ __IO uint32_t APB1SMENR1; /*!< RCC APB1 peripheral clocks enable in sleep mode and stop modes register 1, Address offset: 0x78 */
+ __IO uint32_t APB1SMENR2; /*!< RCC APB1 peripheral clocks enable in sleep mode and stop modes register 2, Address offset: 0x7C */
+ __IO uint32_t APB2SMENR; /*!< RCC APB2 peripheral clocks enable in sleep mode and stop modes register, Address offset: 0x80 */
+ uint32_t RESERVED6; /*!< Reserved, Address offset: 0x84 */
+ __IO uint32_t CCIPR; /*!< RCC peripherals independent clock configuration register, Address offset: 0x88 */
+ uint32_t RESERVED7; /*!< Reserved, Address offset: 0x8C */
+ __IO uint32_t BDCR; /*!< RCC backup domain control register, Address offset: 0x90 */
+ __IO uint32_t CSR; /*!< RCC clock control & status register, Address offset: 0x94 */
+} RCC_TypeDef;
+
+/**
+ * @brief Real-Time Clock
+ */
+
+typedef struct
+{
+ __IO uint32_t TR; /*!< RTC time register, Address offset: 0x00 */
+ __IO uint32_t DR; /*!< RTC date register, Address offset: 0x04 */
+ __IO uint32_t CR; /*!< RTC control register, Address offset: 0x08 */
+ __IO uint32_t ISR; /*!< RTC initialization and status register, Address offset: 0x0C */
+ __IO uint32_t PRER; /*!< RTC prescaler register, Address offset: 0x10 */
+ __IO uint32_t WUTR; /*!< RTC wakeup timer register, Address offset: 0x14 */
+ uint32_t reserved; /*!< Reserved */
+ __IO uint32_t ALRMAR; /*!< RTC alarm A register, Address offset: 0x1C */
+ __IO uint32_t ALRMBR; /*!< RTC alarm B register, Address offset: 0x20 */
+ __IO uint32_t WPR; /*!< RTC write protection register, Address offset: 0x24 */
+ __IO uint32_t SSR; /*!< RTC sub second register, Address offset: 0x28 */
+ __IO uint32_t SHIFTR; /*!< RTC shift control register, Address offset: 0x2C */
+ __IO uint32_t TSTR; /*!< RTC time stamp time register, Address offset: 0x30 */
+ __IO uint32_t TSDR; /*!< RTC time stamp date register, Address offset: 0x34 */
+ __IO uint32_t TSSSR; /*!< RTC time-stamp sub second register, Address offset: 0x38 */
+ __IO uint32_t CALR; /*!< RTC calibration register, Address offset: 0x3C */
+ __IO uint32_t TAMPCR; /*!< RTC tamper configuration register, Address offset: 0x40 */
+ __IO uint32_t ALRMASSR; /*!< RTC alarm A sub second register, Address offset: 0x44 */
+ __IO uint32_t ALRMBSSR; /*!< RTC alarm B sub second register, Address offset: 0x48 */
+ __IO uint32_t OR; /*!< RTC option register, Address offset: 0x4C */
+ __IO uint32_t BKP0R; /*!< RTC backup register 0, Address offset: 0x50 */
+ __IO uint32_t BKP1R; /*!< RTC backup register 1, Address offset: 0x54 */
+ __IO uint32_t BKP2R; /*!< RTC backup register 2, Address offset: 0x58 */
+ __IO uint32_t BKP3R; /*!< RTC backup register 3, Address offset: 0x5C */
+ __IO uint32_t BKP4R; /*!< RTC backup register 4, Address offset: 0x60 */
+ __IO uint32_t BKP5R; /*!< RTC backup register 5, Address offset: 0x64 */
+ __IO uint32_t BKP6R; /*!< RTC backup register 6, Address offset: 0x68 */
+ __IO uint32_t BKP7R; /*!< RTC backup register 7, Address offset: 0x6C */
+ __IO uint32_t BKP8R; /*!< RTC backup register 8, Address offset: 0x70 */
+ __IO uint32_t BKP9R; /*!< RTC backup register 9, Address offset: 0x74 */
+ __IO uint32_t BKP10R; /*!< RTC backup register 10, Address offset: 0x78 */
+ __IO uint32_t BKP11R; /*!< RTC backup register 11, Address offset: 0x7C */
+ __IO uint32_t BKP12R; /*!< RTC backup register 12, Address offset: 0x80 */
+ __IO uint32_t BKP13R; /*!< RTC backup register 13, Address offset: 0x84 */
+ __IO uint32_t BKP14R; /*!< RTC backup register 14, Address offset: 0x88 */
+ __IO uint32_t BKP15R; /*!< RTC backup register 15, Address offset: 0x8C */
+ __IO uint32_t BKP16R; /*!< RTC backup register 16, Address offset: 0x90 */
+ __IO uint32_t BKP17R; /*!< RTC backup register 17, Address offset: 0x94 */
+ __IO uint32_t BKP18R; /*!< RTC backup register 18, Address offset: 0x98 */
+ __IO uint32_t BKP19R; /*!< RTC backup register 19, Address offset: 0x9C */
+ __IO uint32_t BKP20R; /*!< RTC backup register 20, Address offset: 0xA0 */
+ __IO uint32_t BKP21R; /*!< RTC backup register 21, Address offset: 0xA4 */
+ __IO uint32_t BKP22R; /*!< RTC backup register 22, Address offset: 0xA8 */
+ __IO uint32_t BKP23R; /*!< RTC backup register 23, Address offset: 0xAC */
+ __IO uint32_t BKP24R; /*!< RTC backup register 24, Address offset: 0xB0 */
+ __IO uint32_t BKP25R; /*!< RTC backup register 25, Address offset: 0xB4 */
+ __IO uint32_t BKP26R; /*!< RTC backup register 26, Address offset: 0xB8 */
+ __IO uint32_t BKP27R; /*!< RTC backup register 27, Address offset: 0xBC */
+ __IO uint32_t BKP28R; /*!< RTC backup register 28, Address offset: 0xC0 */
+ __IO uint32_t BKP29R; /*!< RTC backup register 29, Address offset: 0xC4 */
+ __IO uint32_t BKP30R; /*!< RTC backup register 30, Address offset: 0xC8 */
+ __IO uint32_t BKP31R; /*!< RTC backup register 31, Address offset: 0xCC */
+} RTC_TypeDef;
+
+
+/**
+ * @brief Serial Audio Interface
+ */
+
+typedef struct
+{
+ __IO uint32_t GCR; /*!< SAI global configuration register, Address offset: 0x00 */
+} SAI_TypeDef;
+
+typedef struct
+{
+ __IO uint32_t CR1; /*!< SAI block x configuration register 1, Address offset: 0x04 */
+ __IO uint32_t CR2; /*!< SAI block x configuration register 2, Address offset: 0x08 */
+ __IO uint32_t FRCR; /*!< SAI block x frame configuration register, Address offset: 0x0C */
+ __IO uint32_t SLOTR; /*!< SAI block x slot register, Address offset: 0x10 */
+ __IO uint32_t IMR; /*!< SAI block x interrupt mask register, Address offset: 0x14 */
+ __IO uint32_t SR; /*!< SAI block x status register, Address offset: 0x18 */
+ __IO uint32_t CLRFR; /*!< SAI block x clear flag register, Address offset: 0x1C */
+ __IO uint32_t DR; /*!< SAI block x data register, Address offset: 0x20 */
+} SAI_Block_TypeDef;
+
+
+/**
+ * @brief Secure digital input/output Interface
+ */
+
+typedef struct
+{
+ __IO uint32_t POWER; /*!< SDMMC power control register, Address offset: 0x00 */
+ __IO uint32_t CLKCR; /*!< SDMMC clock control register, Address offset: 0x04 */
+ __IO uint32_t ARG; /*!< SDMMC argument register, Address offset: 0x08 */
+ __IO uint32_t CMD; /*!< SDMMC command register, Address offset: 0x0C */
+ __I uint32_t RESPCMD; /*!< SDMMC command response register, Address offset: 0x10 */
+ __I uint32_t RESP1; /*!< SDMMC response 1 register, Address offset: 0x14 */
+ __I uint32_t RESP2; /*!< SDMMC response 2 register, Address offset: 0x18 */
+ __I uint32_t RESP3; /*!< SDMMC response 3 register, Address offset: 0x1C */
+ __I uint32_t RESP4; /*!< SDMMC response 4 register, Address offset: 0x20 */
+ __IO uint32_t DTIMER; /*!< SDMMC data timer register, Address offset: 0x24 */
+ __IO uint32_t DLEN; /*!< SDMMC data length register, Address offset: 0x28 */
+ __IO uint32_t DCTRL; /*!< SDMMC data control register, Address offset: 0x2C */
+ __I uint32_t DCOUNT; /*!< SDMMC data counter register, Address offset: 0x30 */
+ __I uint32_t STA; /*!< SDMMC status register, Address offset: 0x34 */
+ __IO uint32_t ICR; /*!< SDMMC interrupt clear register, Address offset: 0x38 */
+ __IO uint32_t MASK; /*!< SDMMC mask register, Address offset: 0x3C */
+ uint32_t RESERVED0[2]; /*!< Reserved, 0x40-0x44 */
+ __I uint32_t FIFOCNT; /*!< SDMMC FIFO counter register, Address offset: 0x48 */
+ uint32_t RESERVED1[13]; /*!< Reserved, 0x4C-0x7C */
+ __IO uint32_t FIFO; /*!< SDMMC data FIFO register, Address offset: 0x80 */
+} SDMMC_TypeDef;
+
+
+/**
+ * @brief Serial Peripheral Interface
+ */
+
+typedef struct
+{
+ __IO uint32_t CR1; /*!< SPI Control register 1, Address offset: 0x00 */
+ __IO uint32_t CR2; /*!< SPI Control register 2, Address offset: 0x04 */
+ __IO uint32_t SR; /*!< SPI Status register, Address offset: 0x08 */
+ __IO uint32_t DR; /*!< SPI data register, Address offset: 0x0C */
+ __IO uint32_t CRCPR; /*!< SPI CRC polynomial register, Address offset: 0x10 */
+ __IO uint32_t RXCRCR; /*!< SPI Rx CRC register, Address offset: 0x14 */
+ __IO uint32_t TXCRCR; /*!< SPI Tx CRC register, Address offset: 0x18 */
+} SPI_TypeDef;
+
+
+/**
+ * @brief Single Wire Protocol Master Interface SPWMI
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< SWPMI Configuration/Control register, Address offset: 0x00 */
+ __IO uint32_t BRR; /*!< SWPMI bitrate register, Address offset: 0x04 */
+ uint32_t RESERVED1; /*!< Reserved, 0x08 */
+ __IO uint32_t ISR; /*!< SWPMI Interrupt and Status register, Address offset: 0x0C */
+ __IO uint32_t ICR; /*!< SWPMI Interrupt Flag Clear register, Address offset: 0x10 */
+ __IO uint32_t IER; /*!< SWPMI Interrupt Enable register, Address offset: 0x14 */
+ __IO uint32_t RFL; /*!< SWPMI Receive Frame Length register, Address offset: 0x18 */
+ __IO uint32_t TDR; /*!< SWPMI Transmit data register, Address offset: 0x1C */
+ __IO uint32_t RDR; /*!< SWPMI Receive data register, Address offset: 0x20 */
+ __IO uint32_t OR; /*!< SWPMI Option register, Address offset: 0x24 */
+} SWPMI_TypeDef;
+
+
+/**
+ * @brief System configuration controller
+ */
+
+typedef struct
+{
+ __IO uint32_t MEMRMP; /*!< SYSCFG memory remap register, Address offset: 0x00 */
+ __IO uint32_t CFGR1; /*!< SYSCFG configuration register 1, Address offset: 0x04 */
+ __IO uint32_t EXTICR[4]; /*!< SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14 */
+ __IO uint32_t SCSR; /*!< SYSCFG SRAM2 control and status register, Address offset: 0x18 */
+ __IO uint32_t CFGR2; /*!< SYSCFG configuration register 2, Address offset: 0x1C */
+ __IO uint32_t SWPR; /*!< SYSCFG SRAM2 write protection register, Address offset: 0x20 */
+ __IO uint32_t SKR; /*!< SYSCFG SRAM2 key register, Address offset: 0x24 */
+} SYSCFG_TypeDef;
+
+
+/**
+ * @brief TIM
+ */
+
+typedef struct
+{
+ __IO uint32_t CR1; /*!< TIM control register 1, Address offset: 0x00 */
+ __IO uint32_t CR2; /*!< TIM control register 2, Address offset: 0x04 */
+ __IO uint32_t SMCR; /*!< TIM slave mode control register, Address offset: 0x08 */
+ __IO uint32_t DIER; /*!< TIM DMA/interrupt enable register, Address offset: 0x0C */
+ __IO uint32_t SR; /*!< TIM status register, Address offset: 0x10 */
+ __IO uint32_t EGR; /*!< TIM event generation register, Address offset: 0x14 */
+ __IO uint32_t CCMR1; /*!< TIM capture/compare mode register 1, Address offset: 0x18 */
+ __IO uint32_t CCMR2; /*!< TIM capture/compare mode register 2, Address offset: 0x1C */
+ __IO uint32_t CCER; /*!< TIM capture/compare enable register, Address offset: 0x20 */
+ __IO uint32_t CNT; /*!< TIM counter register, Address offset: 0x24 */
+ __IO uint32_t PSC; /*!< TIM prescaler, Address offset: 0x28 */
+ __IO uint32_t ARR; /*!< TIM auto-reload register, Address offset: 0x2C */
+ __IO uint32_t RCR; /*!< TIM repetition counter register, Address offset: 0x30 */
+ __IO uint32_t CCR1; /*!< TIM capture/compare register 1, Address offset: 0x34 */
+ __IO uint32_t CCR2; /*!< TIM capture/compare register 2, Address offset: 0x38 */
+ __IO uint32_t CCR3; /*!< TIM capture/compare register 3, Address offset: 0x3C */
+ __IO uint32_t CCR4; /*!< TIM capture/compare register 4, Address offset: 0x40 */
+ __IO uint32_t BDTR; /*!< TIM break and dead-time register, Address offset: 0x44 */
+ __IO uint32_t DCR; /*!< TIM DMA control register, Address offset: 0x48 */
+ __IO uint32_t DMAR; /*!< TIM DMA address for full transfer, Address offset: 0x4C */
+ __IO uint32_t OR1; /*!< TIM option register 1, Address offset: 0x50 */
+ __IO uint32_t CCMR3; /*!< TIM capture/compare mode register 3, Address offset: 0x54 */
+ __IO uint32_t CCR5; /*!< TIM capture/compare register5, Address offset: 0x58 */
+ __IO uint32_t CCR6; /*!< TIM capture/compare register6, Address offset: 0x5C */
+ __IO uint32_t OR2; /*!< TIM option register 2, Address offset: 0x60 */
+ __IO uint32_t OR3; /*!< TIM option register 3, Address offset: 0x64 */
+} TIM_TypeDef;
+
+
+/**
+ * @brief Touch Sensing Controller (TSC)
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< TSC control register, Address offset: 0x00 */
+ __IO uint32_t IER; /*!< TSC interrupt enable register, Address offset: 0x04 */
+ __IO uint32_t ICR; /*!< TSC interrupt clear register, Address offset: 0x08 */
+ __IO uint32_t ISR; /*!< TSC interrupt status register, Address offset: 0x0C */
+ __IO uint32_t IOHCR; /*!< TSC I/O hysteresis control register, Address offset: 0x10 */
+ uint32_t RESERVED1; /*!< Reserved, Address offset: 0x14 */
+ __IO uint32_t IOASCR; /*!< TSC I/O analog switch control register, Address offset: 0x18 */
+ uint32_t RESERVED2; /*!< Reserved, Address offset: 0x1C */
+ __IO uint32_t IOSCR; /*!< TSC I/O sampling control register, Address offset: 0x20 */
+ uint32_t RESERVED3; /*!< Reserved, Address offset: 0x24 */
+ __IO uint32_t IOCCR; /*!< TSC I/O channel control register, Address offset: 0x28 */
+ uint32_t RESERVED4; /*!< Reserved, Address offset: 0x2C */
+ __IO uint32_t IOGCSR; /*!< TSC I/O group control status register, Address offset: 0x30 */
+ __IO uint32_t IOGXCR[8]; /*!< TSC I/O group x counter register, Address offset: 0x34-50 */
+} TSC_TypeDef;
+
+/**
+ * @brief Universal Synchronous Asynchronous Receiver Transmitter
+ */
+
+typedef struct
+{
+ __IO uint32_t CR1; /*!< USART Control register 1, Address offset: 0x00 */
+ __IO uint32_t CR2; /*!< USART Control register 2, Address offset: 0x04 */
+ __IO uint32_t CR3; /*!< USART Control register 3, Address offset: 0x08 */
+ __IO uint32_t BRR; /*!< USART Baud rate register, Address offset: 0x0C */
+ __IO uint16_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x10 */
+ uint16_t RESERVED2; /*!< Reserved, 0x12 */
+ __IO uint32_t RTOR; /*!< USART Receiver Time Out register, Address offset: 0x14 */
+ __IO uint16_t RQR; /*!< USART Request register, Address offset: 0x18 */
+ uint16_t RESERVED3; /*!< Reserved, 0x1A */
+ __IO uint32_t ISR; /*!< USART Interrupt and status register, Address offset: 0x1C */
+ __IO uint32_t ICR; /*!< USART Interrupt flag Clear register, Address offset: 0x20 */
+ __IO uint16_t RDR; /*!< USART Receive Data register, Address offset: 0x24 */
+ uint16_t RESERVED4; /*!< Reserved, 0x26 */
+ __IO uint16_t TDR; /*!< USART Transmit Data register, Address offset: 0x28 */
+ uint16_t RESERVED5; /*!< Reserved, 0x2A */
+} USART_TypeDef;
+
+/**
+ * @brief VREFBUF
+ */
+
+typedef struct
+{
+ __IO uint32_t CSR; /*!< VREFBUF control and status register, Address offset: 0x00 */
+ __IO uint32_t CCR; /*!< VREFBUF calibration and control register, Address offset: 0x04 */
+} VREFBUF_TypeDef;
+
+/**
+ * @brief Window WATCHDOG
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< WWDG Control register, Address offset: 0x00 */
+ __IO uint32_t CFR; /*!< WWDG Configuration register, Address offset: 0x04 */
+ __IO uint32_t SR; /*!< WWDG Status register, Address offset: 0x08 */
+} WWDG_TypeDef;
+
+/**
+ * @brief RNG
+ */
+
+typedef struct
+{
+ __IO uint32_t CR; /*!< RNG control register, Address offset: 0x00 */
+ __IO uint32_t SR; /*!< RNG status register, Address offset: 0x04 */
+ __IO uint32_t DR; /*!< RNG data register, Address offset: 0x08 */
+} RNG_TypeDef;
+
+/**
+ * @brief USB_OTG_Core_register
+ */
+typedef struct
+{
+ __IO uint32_t GOTGCTL; /*!< USB_OTG Control and Status Register 000h*/
+ __IO uint32_t GOTGINT; /*!< USB_OTG Interrupt Register 004h*/
+ __IO uint32_t GAHBCFG; /*!< Core AHB Configuration Register 008h*/
+ __IO uint32_t GUSBCFG; /*!< Core USB Configuration Register 00Ch*/
+ __IO uint32_t GRSTCTL; /*!< Core Reset Register 010h*/
+ __IO uint32_t GINTSTS; /*!< Core Interrupt Register 014h*/
+ __IO uint32_t GINTMSK; /*!< Core Interrupt Mask Register 018h*/
+ __IO uint32_t GRXSTSR; /*!< Receive Sts Q Read Register 01Ch*/
+ __IO uint32_t GRXSTSP; /*!< Receive Sts Q Read & POP Register 020h*/
+ __IO uint32_t GRXFSIZ; /* Receive FIFO Size Register 024h*/
+ __IO uint32_t DIEPTXF0_HNPTXFSIZ; /*!< EP0 / Non Periodic Tx FIFO Size Register 028h*/
+ __IO uint32_t HNPTXSTS; /*!< Non Periodic Tx FIFO/Queue Sts reg 02Ch*/
+ uint32_t Reserved30[2]; /* Reserved 030h*/
+ __IO uint32_t GCCFG; /* General Purpose IO Register 038h*/
+ __IO uint32_t CID; /* User ID Register 03Ch*/
+ __IO uint32_t GSNPSID; /* USB_OTG core ID 040h*/
+ __IO uint32_t GHWCFG1; /* User HW config1 044h*/
+ __IO uint32_t GHWCFG2; /* User HW config2 048h*/
+ __IO uint32_t GHWCFG3; /* User HW config3 04Ch*/
+ uint32_t Reserved6; /* Reserved 050h*/
+ __IO uint32_t GLPMCFG; /* LPM Register 054h*/
+ __IO uint32_t GPWRDN; /* Power Down Register 058h*/
+ __IO uint32_t GDFIFOCFG; /* DFIFO Software Config Register 05Ch*/
+ __IO uint32_t GADPCTL; /* ADP Timer, Control and Status Register 60Ch*/
+ uint32_t Reserved43[39]; /* Reserved 058h-0FFh*/
+ __IO uint32_t HPTXFSIZ; /* Host Periodic Tx FIFO Size Reg 100h*/
+ __IO uint32_t DIEPTXF[0x0F]; /* dev Periodic Transmit FIFO */
+} USB_OTG_GlobalTypeDef;
+
+/**
+ * @brief USB_OTG_device_Registers
+ */
+typedef struct
+{
+ __IO uint32_t DCFG; /* dev Configuration Register 800h*/
+ __IO uint32_t DCTL; /* dev Control Register 804h*/
+ __IO uint32_t DSTS; /* dev Status Register (RO) 808h*/
+ uint32_t Reserved0C; /* Reserved 80Ch*/
+ __IO uint32_t DIEPMSK; /* dev IN Endpoint Mask 810h*/
+ __IO uint32_t DOEPMSK; /* dev OUT Endpoint Mask 814h*/
+ __IO uint32_t DAINT; /* dev All Endpoints Itr Reg 818h*/
+ __IO uint32_t DAINTMSK; /* dev All Endpoints Itr Mask 81Ch*/
+ uint32_t Reserved20; /* Reserved 820h*/
+ uint32_t Reserved9; /* Reserved 824h*/
+ __IO uint32_t DVBUSDIS; /* dev VBUS discharge Register 828h*/
+ __IO uint32_t DVBUSPULSE; /* dev VBUS Pulse Register 82Ch*/
+ __IO uint32_t DTHRCTL; /* dev thr 830h*/
+ __IO uint32_t DIEPEMPMSK; /* dev empty msk 834h*/
+ __IO uint32_t DEACHINT; /* dedicated EP interrupt 838h*/
+ __IO uint32_t DEACHMSK; /* dedicated EP msk 83Ch*/
+ uint32_t Reserved40; /* dedicated EP mask 840h*/
+ __IO uint32_t DINEP1MSK; /* dedicated EP mask 844h*/
+ uint32_t Reserved44[15]; /* Reserved 844-87Ch*/
+ __IO uint32_t DOUTEP1MSK; /* dedicated EP msk 884h*/
+} USB_OTG_DeviceTypeDef;
+
+/**
+ * @brief USB_OTG_IN_Endpoint-Specific_Register
+ */
+typedef struct
+{
+ __IO uint32_t DIEPCTL; /* dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h*/
+ uint32_t Reserved04; /* Reserved 900h + (ep_num * 20h) + 04h*/
+ __IO uint32_t DIEPINT; /* dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h*/
+ uint32_t Reserved0C; /* Reserved 900h + (ep_num * 20h) + 0Ch*/
+ __IO uint32_t DIEPTSIZ; /* IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h*/
+ __IO uint32_t DIEPDMA; /* IN Endpoint DMA Address Reg 900h + (ep_num * 20h) + 14h*/
+ __IO uint32_t DTXFSTS; /*IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h*/
+ uint32_t Reserved18; /* Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch*/
+} USB_OTG_INEndpointTypeDef;
+
+/**
+ * @brief USB_OTG_OUT_Endpoint-Specific_Registers
+ */
+typedef struct
+{
+ __IO uint32_t DOEPCTL; /* dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h*/
+ uint32_t Reserved04; /* Reserved B00h + (ep_num * 20h) + 04h*/
+ __IO uint32_t DOEPINT; /* dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h*/
+ uint32_t Reserved0C; /* Reserved B00h + (ep_num * 20h) + 0Ch*/
+ __IO uint32_t DOEPTSIZ; /* dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h*/
+ __IO uint32_t DOEPDMA; /* dev OUT Endpoint DMA Address B00h + (ep_num * 20h) + 14h*/
+ uint32_t Reserved18[2]; /* Reserved B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch*/
+} USB_OTG_OUTEndpointTypeDef;
+
+/**
+ * @brief USB_OTG_Host_Mode_Register_Structures
+ */
+typedef struct
+{
+ __IO uint32_t HCFG; /* Host Configuration Register 400h*/
+ __IO uint32_t HFIR; /* Host Frame Interval Register 404h*/
+ __IO uint32_t HFNUM; /* Host Frame Nbr/Frame Remaining 408h*/
+ uint32_t Reserved40C; /* Reserved 40Ch*/
+ __IO uint32_t HPTXSTS; /* Host Periodic Tx FIFO/ Queue Status 410h*/
+ __IO uint32_t HAINT; /* Host All Channels Interrupt Register 414h*/
+ __IO uint32_t HAINTMSK; /* Host All Channels Interrupt Mask 418h*/
+} USB_OTG_HostTypeDef;
+
+/**
+ * @brief USB_OTG_Host_Channel_Specific_Registers
+ */
+typedef struct
+{
+ __IO uint32_t HCCHAR;
+ __IO uint32_t HCSPLT;
+ __IO uint32_t HCINT;
+ __IO uint32_t HCINTMSK;
+ __IO uint32_t HCTSIZ;
+ __IO uint32_t HCDMA;
+ uint32_t Reserved[2];
+} USB_OTG_HostChannelTypeDef;
+
+/**
+ * @}
+ */
+
+/** @addtogroup Peripheral_memory_map
+ * @{
+ */
+#define FLASH_BASE ((uint32_t)0x08000000U) /*!< FLASH(up to 1 MB) base address */
+#define SRAM1_BASE ((uint32_t)0x20000000U) /*!< SRAM1(up to 96 KB) base address */
+#define SRAM2_BASE ((uint32_t)0x10000000U) /*!< SRAM2(32 KB) base address */
+#define PERIPH_BASE ((uint32_t)0x40000000U) /*!< Peripheral base address */
+#define FMC_BASE ((uint32_t)0x60000000U) /*!< FMC base address */
+#define QSPI_BASE ((uint32_t)0x90000000U) /*!< QUADSPI memories accessible over AHB base address */
+
+#define FMC_R_BASE ((uint32_t)0xA0000000U) /*!< FMC control registers base address */
+#define QSPI_R_BASE ((uint32_t)0xA0001000U) /*!< QUADSPI control registers base address */
+#define SRAM1_BB_BASE ((uint32_t)0x22000000U) /*!< SRAM1(96 KB) base address in the bit-band region */
+#define PERIPH_BB_BASE ((uint32_t)0x42000000U) /*!< Peripheral base address in the bit-band region */
+
+/* Legacy defines */
+#define SRAM_BASE SRAM1_BASE
+#define SRAM_BB_BASE SRAM1_BB_BASE
+
+#define SRAM1_SIZE_MAX ((uint32_t)0x00018000U) /*!< maximum SRAM1 size (up to 96 KBytes) */
+#define SRAM2_SIZE ((uint32_t)0x00008000U) /*!< SRAM2 size (32 KBytes) */
+
+/*!< Peripheral memory map */
+#define APB1PERIPH_BASE PERIPH_BASE
+#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000U)
+#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000U)
+#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000U)
+
+#define FMC_BANK1 FMC_BASE
+#define FMC_BANK1_1 FMC_BANK1
+#define FMC_BANK1_2 (FMC_BANK1 + 0x04000000U)
+#define FMC_BANK1_3 (FMC_BANK1 + 0x08000000U)
+#define FMC_BANK1_4 (FMC_BANK1 + 0x0C000000U)
+#define FMC_BANK3 (FMC_BASE + 0x20000000U)
+
+/*!< APB1 peripherals */
+#define TIM2_BASE (APB1PERIPH_BASE + 0x0000U)
+#define TIM3_BASE (APB1PERIPH_BASE + 0x0400U)
+#define TIM4_BASE (APB1PERIPH_BASE + 0x0800U)
+#define TIM5_BASE (APB1PERIPH_BASE + 0x0C00U)
+#define TIM6_BASE (APB1PERIPH_BASE + 0x1000U)
+#define TIM7_BASE (APB1PERIPH_BASE + 0x1400U)
+#define LCD_BASE (APB1PERIPH_BASE + 0x2400U)
+#define RTC_BASE (APB1PERIPH_BASE + 0x2800U)
+#define WWDG_BASE (APB1PERIPH_BASE + 0x2C00U)
+#define IWDG_BASE (APB1PERIPH_BASE + 0x3000U)
+#define SPI2_BASE (APB1PERIPH_BASE + 0x3800U)
+#define SPI3_BASE (APB1PERIPH_BASE + 0x3C00U)
+#define USART2_BASE (APB1PERIPH_BASE + 0x4400U)
+#define USART3_BASE (APB1PERIPH_BASE + 0x4800U)
+#define UART4_BASE (APB1PERIPH_BASE + 0x4C00U)
+#define UART5_BASE (APB1PERIPH_BASE + 0x5000U)
+#define I2C1_BASE (APB1PERIPH_BASE + 0x5400U)
+#define I2C2_BASE (APB1PERIPH_BASE + 0x5800U)
+#define I2C3_BASE (APB1PERIPH_BASE + 0x5C00U)
+#define CAN1_BASE (APB1PERIPH_BASE + 0x6400U)
+#define PWR_BASE (APB1PERIPH_BASE + 0x7000U)
+#define DAC_BASE (APB1PERIPH_BASE + 0x7400U)
+#define DAC1_BASE (APB1PERIPH_BASE + 0x7400U)
+#define OPAMP_BASE (APB1PERIPH_BASE + 0x7800U)
+#define OPAMP1_BASE (APB1PERIPH_BASE + 0x7800U)
+#define OPAMP2_BASE (APB1PERIPH_BASE + 0x7810U)
+#define LPTIM1_BASE (APB1PERIPH_BASE + 0x7C00U)
+#define LPUART1_BASE (APB1PERIPH_BASE + 0x8000U)
+#define SWPMI1_BASE (APB1PERIPH_BASE + 0x8800U)
+#define LPTIM2_BASE (APB1PERIPH_BASE + 0x9400U)
+
+
+/*!< APB2 peripherals */
+#define SYSCFG_BASE (APB2PERIPH_BASE + 0x0000U)
+#define VREFBUF_BASE (APB2PERIPH_BASE + 0x0030U)
+#define COMP1_BASE (APB2PERIPH_BASE + 0x0200U)
+#define COMP2_BASE (APB2PERIPH_BASE + 0x0204U)
+#define EXTI_BASE (APB2PERIPH_BASE + 0x0400U)
+#define FIREWALL_BASE (APB2PERIPH_BASE + 0x1C00U)
+#define SDMMC1_BASE (APB2PERIPH_BASE + 0x2800U)
+#define TIM1_BASE (APB2PERIPH_BASE + 0x2C00U)
+#define SPI1_BASE (APB2PERIPH_BASE + 0x3000U)
+#define TIM8_BASE (APB2PERIPH_BASE + 0x3400U)
+#define USART1_BASE (APB2PERIPH_BASE + 0x3800U)
+#define TIM15_BASE (APB2PERIPH_BASE + 0x4000U)
+#define TIM16_BASE (APB2PERIPH_BASE + 0x4400U)
+#define TIM17_BASE (APB2PERIPH_BASE + 0x4800U)
+#define SAI1_BASE (APB2PERIPH_BASE + 0x5400U)
+#define SAI1_Block_A_BASE (SAI1_BASE + 0x004)
+#define SAI1_Block_B_BASE (SAI1_BASE + 0x024)
+#define SAI2_BASE (APB2PERIPH_BASE + 0x5800U)
+#define SAI2_Block_A_BASE (SAI2_BASE + 0x004)
+#define SAI2_Block_B_BASE (SAI2_BASE + 0x024)
+#define DFSDM1_BASE (APB2PERIPH_BASE + 0x6000U)
+#define DFSDM1_Channel0_BASE (DFSDM1_BASE + 0x00)
+#define DFSDM1_Channel1_BASE (DFSDM1_BASE + 0x20)
+#define DFSDM1_Channel2_BASE (DFSDM1_BASE + 0x40)
+#define DFSDM1_Channel3_BASE (DFSDM1_BASE + 0x60)
+#define DFSDM1_Channel4_BASE (DFSDM1_BASE + 0x80)
+#define DFSDM1_Channel5_BASE (DFSDM1_BASE + 0xA0)
+#define DFSDM1_Channel6_BASE (DFSDM1_BASE + 0xC0)
+#define DFSDM1_Channel7_BASE (DFSDM1_BASE + 0xE0)
+#define DFSDM1_Filter0_BASE (DFSDM1_BASE + 0x100)
+#define DFSDM1_Filter1_BASE (DFSDM1_BASE + 0x180)
+#define DFSDM1_Filter2_BASE (DFSDM1_BASE + 0x200)
+#define DFSDM1_Filter3_BASE (DFSDM1_BASE + 0x280)
+
+/*!< AHB1 peripherals */
+#define DMA1_BASE (AHB1PERIPH_BASE)
+#define DMA2_BASE (AHB1PERIPH_BASE + 0x0400U)
+#define RCC_BASE (AHB1PERIPH_BASE + 0x1000U)
+#define FLASH_R_BASE (AHB1PERIPH_BASE + 0x2000U)
+#define CRC_BASE (AHB1PERIPH_BASE + 0x3000U)
+#define TSC_BASE (AHB1PERIPH_BASE + 0x4000U)
+
+
+#define DMA1_Channel1_BASE (DMA1_BASE + 0x0008U)
+#define DMA1_Channel2_BASE (DMA1_BASE + 0x001CU)
+#define DMA1_Channel3_BASE (DMA1_BASE + 0x0030U)
+#define DMA1_Channel4_BASE (DMA1_BASE + 0x0044U)
+#define DMA1_Channel5_BASE (DMA1_BASE + 0x0058U)
+#define DMA1_Channel6_BASE (DMA1_BASE + 0x006CU)
+#define DMA1_Channel7_BASE (DMA1_BASE + 0x0080U)
+#define DMA1_CSELR_BASE (DMA1_BASE + 0x00A8U)
+
+
+#define DMA2_Channel1_BASE (DMA2_BASE + 0x0008U)
+#define DMA2_Channel2_BASE (DMA2_BASE + 0x001CU)
+#define DMA2_Channel3_BASE (DMA2_BASE + 0x0030U)
+#define DMA2_Channel4_BASE (DMA2_BASE + 0x0044U)
+#define DMA2_Channel5_BASE (DMA2_BASE + 0x0058U)
+#define DMA2_Channel6_BASE (DMA2_BASE + 0x006CU)
+#define DMA2_Channel7_BASE (DMA2_BASE + 0x0080U)
+#define DMA2_CSELR_BASE (DMA2_BASE + 0x00A8U)
+
+
+/*!< AHB2 peripherals */
+#define GPIOA_BASE (AHB2PERIPH_BASE + 0x0000U)
+#define GPIOB_BASE (AHB2PERIPH_BASE + 0x0400U)
+#define GPIOC_BASE (AHB2PERIPH_BASE + 0x0800U)
+#define GPIOD_BASE (AHB2PERIPH_BASE + 0x0C00U)
+#define GPIOE_BASE (AHB2PERIPH_BASE + 0x1000U)
+#define GPIOF_BASE (AHB2PERIPH_BASE + 0x1400U)
+#define GPIOG_BASE (AHB2PERIPH_BASE + 0x1800U)
+#define GPIOH_BASE (AHB2PERIPH_BASE + 0x1C00U)
+
+#define USBOTG_BASE (AHB2PERIPH_BASE + 0x08000000U)
+
+#define ADC1_BASE (AHB2PERIPH_BASE + 0x08040000U)
+#define ADC2_BASE (AHB2PERIPH_BASE + 0x08040100U)
+#define ADC3_BASE (AHB2PERIPH_BASE + 0x08040200U)
+#define ADC123_COMMON_BASE (AHB2PERIPH_BASE + 0x08040300U)
+
+
+#define RNG_BASE (AHB2PERIPH_BASE + 0x08060800U)
+
+
+/*!< FMC Banks registers base address */
+#define FMC_Bank1_R_BASE (FMC_R_BASE + 0x0000U)
+#define FMC_Bank1E_R_BASE (FMC_R_BASE + 0x0104U)
+#define FMC_Bank3_R_BASE (FMC_R_BASE + 0x0080U)
+
+/* Debug MCU registers base address */
+#define DBGMCU_BASE ((uint32_t)0xE0042000U)
+
+/*!< USB registers base address */
+#define USB_OTG_FS_PERIPH_BASE ((uint32_t)0x50000000U)
+
+#define USB_OTG_GLOBAL_BASE ((uint32_t)0x00000000U)
+#define USB_OTG_DEVICE_BASE ((uint32_t)0x00000800U)
+#define USB_OTG_IN_ENDPOINT_BASE ((uint32_t)0x00000900U)
+#define USB_OTG_OUT_ENDPOINT_BASE ((uint32_t)0x00000B00U)
+#define USB_OTG_EP_REG_SIZE ((uint32_t)0x00000020U)
+#define USB_OTG_HOST_BASE ((uint32_t)0x00000400U)
+#define USB_OTG_HOST_PORT_BASE ((uint32_t)0x00000440U)
+#define USB_OTG_HOST_CHANNEL_BASE ((uint32_t)0x00000500U)
+#define USB_OTG_HOST_CHANNEL_SIZE ((uint32_t)0x00000020U)
+#define USB_OTG_PCGCCTL_BASE ((uint32_t)0x00000E00U)
+#define USB_OTG_FIFO_BASE ((uint32_t)0x00001000U)
+#define USB_OTG_FIFO_SIZE ((uint32_t)0x00001000U)
+
+
+#define PACKAGE_BASE ((uint32_t)0x1FFF7500U) /*!< Package data register base address */
+#define UID_BASE ((uint32_t)0x1FFF7590U) /*!< Unique device ID register base address */
+#define FLASHSIZE_BASE ((uint32_t)0x1FFF75E0U) /*!< Flash size data register base address */
+/**
+ * @}
+ */
+
+/** @addtogroup Peripheral_declaration
+ * @{
+ */
+#define TIM2 ((TIM_TypeDef *) TIM2_BASE)
+#define TIM3 ((TIM_TypeDef *) TIM3_BASE)
+#define TIM4 ((TIM_TypeDef *) TIM4_BASE)
+#define TIM5 ((TIM_TypeDef *) TIM5_BASE)
+#define TIM6 ((TIM_TypeDef *) TIM6_BASE)
+#define TIM7 ((TIM_TypeDef *) TIM7_BASE)
+#define LCD ((LCD_TypeDef *) LCD_BASE)
+#define RTC ((RTC_TypeDef *) RTC_BASE)
+#define WWDG ((WWDG_TypeDef *) WWDG_BASE)
+#define IWDG ((IWDG_TypeDef *) IWDG_BASE)
+#define SPI2 ((SPI_TypeDef *) SPI2_BASE)
+#define SPI3 ((SPI_TypeDef *) SPI3_BASE)
+#define USART2 ((USART_TypeDef *) USART2_BASE)
+#define USART3 ((USART_TypeDef *) USART3_BASE)
+#define UART4 ((USART_TypeDef *) UART4_BASE)
+#define UART5 ((USART_TypeDef *) UART5_BASE)
+#define I2C1 ((I2C_TypeDef *) I2C1_BASE)
+#define I2C2 ((I2C_TypeDef *) I2C2_BASE)
+#define I2C3 ((I2C_TypeDef *) I2C3_BASE)
+#define CAN ((CAN_TypeDef *) CAN1_BASE)
+#define CAN1 ((CAN_TypeDef *) CAN1_BASE)
+#define PWR ((PWR_TypeDef *) PWR_BASE)
+#define DAC ((DAC_TypeDef *) DAC1_BASE)
+#define DAC1 ((DAC_TypeDef *) DAC1_BASE)
+#define OPAMP ((OPAMP_TypeDef *) OPAMP_BASE)
+#define OPAMP1 ((OPAMP_TypeDef *) OPAMP1_BASE)
+#define OPAMP2 ((OPAMP_TypeDef *) OPAMP2_BASE)
+#define OPAMP12_COMMON ((OPAMP_Common_TypeDef *) OPAMP1_BASE)
+#define LPTIM1 ((LPTIM_TypeDef *) LPTIM1_BASE)
+#define LPUART1 ((USART_TypeDef *) LPUART1_BASE)
+#define SWPMI1 ((SWPMI_TypeDef *) SWPMI1_BASE)
+#define LPTIM2 ((LPTIM_TypeDef *) LPTIM2_BASE)
+
+#define SYSCFG ((SYSCFG_TypeDef *) SYSCFG_BASE)
+#define VREFBUF ((VREFBUF_TypeDef *) VREFBUF_BASE)
+#define COMP1 ((COMP_TypeDef *) COMP1_BASE)
+#define COMP2 ((COMP_TypeDef *) COMP2_BASE)
+#define COMP12_COMMON ((COMP_Common_TypeDef *) COMP2_BASE)
+#define EXTI ((EXTI_TypeDef *) EXTI_BASE)
+#define FIREWALL ((FIREWALL_TypeDef *) FIREWALL_BASE)
+#define SDMMC1 ((SDMMC_TypeDef *) SDMMC1_BASE)
+#define TIM1 ((TIM_TypeDef *) TIM1_BASE)
+#define SPI1 ((SPI_TypeDef *) SPI1_BASE)
+#define TIM8 ((TIM_TypeDef *) TIM8_BASE)
+#define USART1 ((USART_TypeDef *) USART1_BASE)
+#define TIM15 ((TIM_TypeDef *) TIM15_BASE)
+#define TIM16 ((TIM_TypeDef *) TIM16_BASE)
+#define TIM17 ((TIM_TypeDef *) TIM17_BASE)
+#define SAI1 ((SAI_TypeDef *) SAI1_BASE)
+#define SAI1_Block_A ((SAI_Block_TypeDef *)SAI1_Block_A_BASE)
+#define SAI1_Block_B ((SAI_Block_TypeDef *)SAI1_Block_B_BASE)
+#define SAI2 ((SAI_TypeDef *) SAI2_BASE)
+#define SAI2_Block_A ((SAI_Block_TypeDef *)SAI2_Block_A_BASE)
+#define SAI2_Block_B ((SAI_Block_TypeDef *)SAI2_Block_B_BASE)
+#define DFSDM1_Channel0 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel0_BASE)
+#define DFSDM1_Channel1 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel1_BASE)
+#define DFSDM1_Channel2 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel2_BASE)
+#define DFSDM1_Channel3 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel3_BASE)
+#define DFSDM1_Channel4 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel4_BASE)
+#define DFSDM1_Channel5 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel5_BASE)
+#define DFSDM1_Channel6 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel6_BASE)
+#define DFSDM1_Channel7 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel7_BASE)
+#define DFSDM1_Filter0 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter0_BASE)
+#define DFSDM1_Filter1 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter1_BASE)
+#define DFSDM1_Filter2 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter2_BASE)
+#define DFSDM1_Filter3 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter3_BASE)
+/* Aliases to keep compatibility after DFSDM renaming */
+#define DFSDM_Channel0 DFSDM1_Channel0
+#define DFSDM_Channel1 DFSDM1_Channel1
+#define DFSDM_Channel2 DFSDM1_Channel2
+#define DFSDM_Channel3 DFSDM1_Channel3
+#define DFSDM_Channel4 DFSDM1_Channel4
+#define DFSDM_Channel5 DFSDM1_Channel5
+#define DFSDM_Channel6 DFSDM1_Channel6
+#define DFSDM_Channel7 DFSDM1_Channel7
+#define DFSDM_Filter0 DFSDM1_Filter0
+#define DFSDM_Filter1 DFSDM1_Filter1
+#define DFSDM_Filter2 DFSDM1_Filter2
+#define DFSDM_Filter3 DFSDM1_Filter3
+#define DMA1 ((DMA_TypeDef *) DMA1_BASE)
+#define DMA2 ((DMA_TypeDef *) DMA2_BASE)
+#define RCC ((RCC_TypeDef *) RCC_BASE)
+#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE)
+#define CRC ((CRC_TypeDef *) CRC_BASE)
+#define TSC ((TSC_TypeDef *) TSC_BASE)
+
+#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
+#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
+#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)
+#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)
+#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)
+#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE)
+#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE)
+#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE)
+#define ADC1 ((ADC_TypeDef *) ADC1_BASE)
+#define ADC2 ((ADC_TypeDef *) ADC2_BASE)
+#define ADC3 ((ADC_TypeDef *) ADC3_BASE)
+#define ADC123_COMMON ((ADC_Common_TypeDef *) ADC123_COMMON_BASE)
+#define RNG ((RNG_TypeDef *) RNG_BASE)
+
+
+#define DMA1_Channel1 ((DMA_Channel_TypeDef *) DMA1_Channel1_BASE)
+#define DMA1_Channel2 ((DMA_Channel_TypeDef *) DMA1_Channel2_BASE)
+#define DMA1_Channel3 ((DMA_Channel_TypeDef *) DMA1_Channel3_BASE)
+#define DMA1_Channel4 ((DMA_Channel_TypeDef *) DMA1_Channel4_BASE)
+#define DMA1_Channel5 ((DMA_Channel_TypeDef *) DMA1_Channel5_BASE)
+#define DMA1_Channel6 ((DMA_Channel_TypeDef *) DMA1_Channel6_BASE)
+#define DMA1_Channel7 ((DMA_Channel_TypeDef *) DMA1_Channel7_BASE)
+#define DMA1_CSELR ((DMA_Request_TypeDef *) DMA1_CSELR_BASE)
+
+
+#define DMA2_Channel1 ((DMA_Channel_TypeDef *) DMA2_Channel1_BASE)
+#define DMA2_Channel2 ((DMA_Channel_TypeDef *) DMA2_Channel2_BASE)
+#define DMA2_Channel3 ((DMA_Channel_TypeDef *) DMA2_Channel3_BASE)
+#define DMA2_Channel4 ((DMA_Channel_TypeDef *) DMA2_Channel4_BASE)
+#define DMA2_Channel5 ((DMA_Channel_TypeDef *) DMA2_Channel5_BASE)
+#define DMA2_Channel6 ((DMA_Channel_TypeDef *) DMA2_Channel6_BASE)
+#define DMA2_Channel7 ((DMA_Channel_TypeDef *) DMA2_Channel7_BASE)
+#define DMA2_CSELR ((DMA_Request_TypeDef *) DMA2_CSELR_BASE)
+
+
+#define FMC_Bank1_R ((FMC_Bank1_TypeDef *) FMC_Bank1_R_BASE)
+#define FMC_Bank1E_R ((FMC_Bank1E_TypeDef *) FMC_Bank1E_R_BASE)
+#define FMC_Bank3_R ((FMC_Bank3_TypeDef *) FMC_Bank3_R_BASE)
+
+#define QUADSPI ((QUADSPI_TypeDef *) QSPI_R_BASE)
+
+#define DBGMCU ((DBGMCU_TypeDef *) DBGMCU_BASE)
+
+#define USB_OTG_FS ((USB_OTG_GlobalTypeDef *) USB_OTG_FS_PERIPH_BASE)
+/**
+ * @}
+ */
+
+/** @addtogroup Exported_constants
+ * @{
+ */
+
+/** @addtogroup Peripheral_Registers_Bits_Definition
+ * @{
+ */
+
+/******************************************************************************/
+/* Peripheral Registers_Bits_Definition */
+/******************************************************************************/
+
+/******************************************************************************/
+/* */
+/* Analog to Digital Converter */
+/* */
+/******************************************************************************/
+
+/*
+ * @brief Specific device feature definitions (not present on all devices in the STM32L4 serie)
+ */
+#define ADC_MULTIMODE_SUPPORT /*!< ADC feature available only on specific devices: multimode available on devices with several ADC instances */
+
+/******************** Bit definition for ADC_ISR register *******************/
+#define ADC_ISR_ADRDY_Pos (0U)
+#define ADC_ISR_ADRDY_Msk (0x1U << ADC_ISR_ADRDY_Pos) /*!< 0x00000001 */
+#define ADC_ISR_ADRDY ADC_ISR_ADRDY_Msk /*!< ADC ready flag */
+#define ADC_ISR_EOSMP_Pos (1U)
+#define ADC_ISR_EOSMP_Msk (0x1U << ADC_ISR_EOSMP_Pos) /*!< 0x00000002 */
+#define ADC_ISR_EOSMP ADC_ISR_EOSMP_Msk /*!< ADC group regular end of sampling flag */
+#define ADC_ISR_EOC_Pos (2U)
+#define ADC_ISR_EOC_Msk (0x1U << ADC_ISR_EOC_Pos) /*!< 0x00000004 */
+#define ADC_ISR_EOC ADC_ISR_EOC_Msk /*!< ADC group regular end of unitary conversion flag */
+#define ADC_ISR_EOS_Pos (3U)
+#define ADC_ISR_EOS_Msk (0x1U << ADC_ISR_EOS_Pos) /*!< 0x00000008 */
+#define ADC_ISR_EOS ADC_ISR_EOS_Msk /*!< ADC group regular end of sequence conversions flag */
+#define ADC_ISR_OVR_Pos (4U)
+#define ADC_ISR_OVR_Msk (0x1U << ADC_ISR_OVR_Pos) /*!< 0x00000010 */
+#define ADC_ISR_OVR ADC_ISR_OVR_Msk /*!< ADC group regular overrun flag */
+#define ADC_ISR_JEOC_Pos (5U)
+#define ADC_ISR_JEOC_Msk (0x1U << ADC_ISR_JEOC_Pos) /*!< 0x00000020 */
+#define ADC_ISR_JEOC ADC_ISR_JEOC_Msk /*!< ADC group injected end of unitary conversion flag */
+#define ADC_ISR_JEOS_Pos (6U)
+#define ADC_ISR_JEOS_Msk (0x1U << ADC_ISR_JEOS_Pos) /*!< 0x00000040 */
+#define ADC_ISR_JEOS ADC_ISR_JEOS_Msk /*!< ADC group injected end of sequence conversions flag */
+#define ADC_ISR_AWD1_Pos (7U)
+#define ADC_ISR_AWD1_Msk (0x1U << ADC_ISR_AWD1_Pos) /*!< 0x00000080 */
+#define ADC_ISR_AWD1 ADC_ISR_AWD1_Msk /*!< ADC analog watchdog 1 flag */
+#define ADC_ISR_AWD2_Pos (8U)
+#define ADC_ISR_AWD2_Msk (0x1U << ADC_ISR_AWD2_Pos) /*!< 0x00000100 */
+#define ADC_ISR_AWD2 ADC_ISR_AWD2_Msk /*!< ADC analog watchdog 2 flag */
+#define ADC_ISR_AWD3_Pos (9U)
+#define ADC_ISR_AWD3_Msk (0x1U << ADC_ISR_AWD3_Pos) /*!< 0x00000200 */
+#define ADC_ISR_AWD3 ADC_ISR_AWD3_Msk /*!< ADC analog watchdog 3 flag */
+#define ADC_ISR_JQOVF_Pos (10U)
+#define ADC_ISR_JQOVF_Msk (0x1U << ADC_ISR_JQOVF_Pos) /*!< 0x00000400 */
+#define ADC_ISR_JQOVF ADC_ISR_JQOVF_Msk /*!< ADC group injected contexts queue overflow flag */
+
+/******************** Bit definition for ADC_IER register *******************/
+#define ADC_IER_ADRDYIE_Pos (0U)
+#define ADC_IER_ADRDYIE_Msk (0x1U << ADC_IER_ADRDYIE_Pos) /*!< 0x00000001 */
+#define ADC_IER_ADRDYIE ADC_IER_ADRDYIE_Msk /*!< ADC ready interrupt */
+#define ADC_IER_EOSMPIE_Pos (1U)
+#define ADC_IER_EOSMPIE_Msk (0x1U << ADC_IER_EOSMPIE_Pos) /*!< 0x00000002 */
+#define ADC_IER_EOSMPIE ADC_IER_EOSMPIE_Msk /*!< ADC group regular end of sampling interrupt */
+#define ADC_IER_EOCIE_Pos (2U)
+#define ADC_IER_EOCIE_Msk (0x1U << ADC_IER_EOCIE_Pos) /*!< 0x00000004 */
+#define ADC_IER_EOCIE ADC_IER_EOCIE_Msk /*!< ADC group regular end of unitary conversion interrupt */
+#define ADC_IER_EOSIE_Pos (3U)
+#define ADC_IER_EOSIE_Msk (0x1U << ADC_IER_EOSIE_Pos) /*!< 0x00000008 */
+#define ADC_IER_EOSIE ADC_IER_EOSIE_Msk /*!< ADC group regular end of sequence conversions interrupt */
+#define ADC_IER_OVRIE_Pos (4U)
+#define ADC_IER_OVRIE_Msk (0x1U << ADC_IER_OVRIE_Pos) /*!< 0x00000010 */
+#define ADC_IER_OVRIE ADC_IER_OVRIE_Msk /*!< ADC group regular overrun interrupt */
+#define ADC_IER_JEOCIE_Pos (5U)
+#define ADC_IER_JEOCIE_Msk (0x1U << ADC_IER_JEOCIE_Pos) /*!< 0x00000020 */
+#define ADC_IER_JEOCIE ADC_IER_JEOCIE_Msk /*!< ADC group injected end of unitary conversion interrupt */
+#define ADC_IER_JEOSIE_Pos (6U)
+#define ADC_IER_JEOSIE_Msk (0x1U << ADC_IER_JEOSIE_Pos) /*!< 0x00000040 */
+#define ADC_IER_JEOSIE ADC_IER_JEOSIE_Msk /*!< ADC group injected end of sequence conversions interrupt */
+#define ADC_IER_AWD1IE_Pos (7U)
+#define ADC_IER_AWD1IE_Msk (0x1U << ADC_IER_AWD1IE_Pos) /*!< 0x00000080 */
+#define ADC_IER_AWD1IE ADC_IER_AWD1IE_Msk /*!< ADC analog watchdog 1 interrupt */
+#define ADC_IER_AWD2IE_Pos (8U)
+#define ADC_IER_AWD2IE_Msk (0x1U << ADC_IER_AWD2IE_Pos) /*!< 0x00000100 */
+#define ADC_IER_AWD2IE ADC_IER_AWD2IE_Msk /*!< ADC analog watchdog 2 interrupt */
+#define ADC_IER_AWD3IE_Pos (9U)
+#define ADC_IER_AWD3IE_Msk (0x1U << ADC_IER_AWD3IE_Pos) /*!< 0x00000200 */
+#define ADC_IER_AWD3IE ADC_IER_AWD3IE_Msk /*!< ADC analog watchdog 3 interrupt */
+#define ADC_IER_JQOVFIE_Pos (10U)
+#define ADC_IER_JQOVFIE_Msk (0x1U << ADC_IER_JQOVFIE_Pos) /*!< 0x00000400 */
+#define ADC_IER_JQOVFIE ADC_IER_JQOVFIE_Msk /*!< ADC group injected contexts queue overflow interrupt */
+
+/* Legacy defines */
+#define ADC_IER_ADRDY (ADC_IER_ADRDYIE)
+#define ADC_IER_EOSMP (ADC_IER_EOSMPIE)
+#define ADC_IER_EOC (ADC_IER_EOCIE)
+#define ADC_IER_EOS (ADC_IER_EOSIE)
+#define ADC_IER_OVR (ADC_IER_OVRIE)
+#define ADC_IER_JEOC (ADC_IER_JEOCIE)
+#define ADC_IER_JEOS (ADC_IER_JEOSIE)
+#define ADC_IER_AWD1 (ADC_IER_AWD1IE)
+#define ADC_IER_AWD2 (ADC_IER_AWD2IE)
+#define ADC_IER_AWD3 (ADC_IER_AWD3IE)
+#define ADC_IER_JQOVF (ADC_IER_JQOVFIE)
+
+/******************** Bit definition for ADC_CR register ********************/
+#define ADC_CR_ADEN_Pos (0U)
+#define ADC_CR_ADEN_Msk (0x1U << ADC_CR_ADEN_Pos) /*!< 0x00000001 */
+#define ADC_CR_ADEN ADC_CR_ADEN_Msk /*!< ADC enable */
+#define ADC_CR_ADDIS_Pos (1U)
+#define ADC_CR_ADDIS_Msk (0x1U << ADC_CR_ADDIS_Pos) /*!< 0x00000002 */
+#define ADC_CR_ADDIS ADC_CR_ADDIS_Msk /*!< ADC disable */
+#define ADC_CR_ADSTART_Pos (2U)
+#define ADC_CR_ADSTART_Msk (0x1U << ADC_CR_ADSTART_Pos) /*!< 0x00000004 */
+#define ADC_CR_ADSTART ADC_CR_ADSTART_Msk /*!< ADC group regular conversion start */
+#define ADC_CR_JADSTART_Pos (3U)
+#define ADC_CR_JADSTART_Msk (0x1U << ADC_CR_JADSTART_Pos) /*!< 0x00000008 */
+#define ADC_CR_JADSTART ADC_CR_JADSTART_Msk /*!< ADC group injected conversion start */
+#define ADC_CR_ADSTP_Pos (4U)
+#define ADC_CR_ADSTP_Msk (0x1U << ADC_CR_ADSTP_Pos) /*!< 0x00000010 */
+#define ADC_CR_ADSTP ADC_CR_ADSTP_Msk /*!< ADC group regular conversion stop */
+#define ADC_CR_JADSTP_Pos (5U)
+#define ADC_CR_JADSTP_Msk (0x1U << ADC_CR_JADSTP_Pos) /*!< 0x00000020 */
+#define ADC_CR_JADSTP ADC_CR_JADSTP_Msk /*!< ADC group injected conversion stop */
+#define ADC_CR_ADVREGEN_Pos (28U)
+#define ADC_CR_ADVREGEN_Msk (0x1U << ADC_CR_ADVREGEN_Pos) /*!< 0x10000000 */
+#define ADC_CR_ADVREGEN ADC_CR_ADVREGEN_Msk /*!< ADC voltage regulator enable */
+#define ADC_CR_DEEPPWD_Pos (29U)
+#define ADC_CR_DEEPPWD_Msk (0x1U << ADC_CR_DEEPPWD_Pos) /*!< 0x20000000 */
+#define ADC_CR_DEEPPWD ADC_CR_DEEPPWD_Msk /*!< ADC deep power down enable */
+#define ADC_CR_ADCALDIF_Pos (30U)
+#define ADC_CR_ADCALDIF_Msk (0x1U << ADC_CR_ADCALDIF_Pos) /*!< 0x40000000 */
+#define ADC_CR_ADCALDIF ADC_CR_ADCALDIF_Msk /*!< ADC differential mode for calibration */
+#define ADC_CR_ADCAL_Pos (31U)
+#define ADC_CR_ADCAL_Msk (0x1U << ADC_CR_ADCAL_Pos) /*!< 0x80000000 */
+#define ADC_CR_ADCAL ADC_CR_ADCAL_Msk /*!< ADC calibration */
+
+/******************** Bit definition for ADC_CFGR register ******************/
+#define ADC_CFGR_DMAEN_Pos (0U)
+#define ADC_CFGR_DMAEN_Msk (0x1U << ADC_CFGR_DMAEN_Pos) /*!< 0x00000001 */
+#define ADC_CFGR_DMAEN ADC_CFGR_DMAEN_Msk /*!< ADC DMA transfer enable */
+#define ADC_CFGR_DMACFG_Pos (1U)
+#define ADC_CFGR_DMACFG_Msk (0x1U << ADC_CFGR_DMACFG_Pos) /*!< 0x00000002 */
+#define ADC_CFGR_DMACFG ADC_CFGR_DMACFG_Msk /*!< ADC DMA transfer configuration */
+
+#define ADC_CFGR_RES_Pos (3U)
+#define ADC_CFGR_RES_Msk (0x3U << ADC_CFGR_RES_Pos) /*!< 0x00000018 */
+#define ADC_CFGR_RES ADC_CFGR_RES_Msk /*!< ADC data resolution */
+#define ADC_CFGR_RES_0 (0x1U << ADC_CFGR_RES_Pos) /*!< 0x00000008 */
+#define ADC_CFGR_RES_1 (0x2U << ADC_CFGR_RES_Pos) /*!< 0x00000010 */
+
+#define ADC_CFGR_ALIGN_Pos (5U)
+#define ADC_CFGR_ALIGN_Msk (0x1U << ADC_CFGR_ALIGN_Pos) /*!< 0x00000020 */
+#define ADC_CFGR_ALIGN ADC_CFGR_ALIGN_Msk /*!< ADC data alignement */
+
+#define ADC_CFGR_EXTSEL_Pos (6U)
+#define ADC_CFGR_EXTSEL_Msk (0xFU << ADC_CFGR_EXTSEL_Pos) /*!< 0x000003C0 */
+#define ADC_CFGR_EXTSEL ADC_CFGR_EXTSEL_Msk /*!< ADC group regular external trigger source */
+#define ADC_CFGR_EXTSEL_0 (0x1U << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000040 */
+#define ADC_CFGR_EXTSEL_1 (0x2U << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000080 */
+#define ADC_CFGR_EXTSEL_2 (0x4U << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000100 */
+#define ADC_CFGR_EXTSEL_3 (0x8U << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000200 */
+
+#define ADC_CFGR_EXTEN_Pos (10U)
+#define ADC_CFGR_EXTEN_Msk (0x3U << ADC_CFGR_EXTEN_Pos) /*!< 0x00000C00 */
+#define ADC_CFGR_EXTEN ADC_CFGR_EXTEN_Msk /*!< ADC group regular external trigger polarity */
+#define ADC_CFGR_EXTEN_0 (0x1U << ADC_CFGR_EXTEN_Pos) /*!< 0x00000400 */
+#define ADC_CFGR_EXTEN_1 (0x2U << ADC_CFGR_EXTEN_Pos) /*!< 0x00000800 */
+
+#define ADC_CFGR_OVRMOD_Pos (12U)
+#define ADC_CFGR_OVRMOD_Msk (0x1U << ADC_CFGR_OVRMOD_Pos) /*!< 0x00001000 */
+#define ADC_CFGR_OVRMOD ADC_CFGR_OVRMOD_Msk /*!< ADC group regular overrun configuration */
+#define ADC_CFGR_CONT_Pos (13U)
+#define ADC_CFGR_CONT_Msk (0x1U << ADC_CFGR_CONT_Pos) /*!< 0x00002000 */
+#define ADC_CFGR_CONT ADC_CFGR_CONT_Msk /*!< ADC group regular continuous conversion mode */
+#define ADC_CFGR_AUTDLY_Pos (14U)
+#define ADC_CFGR_AUTDLY_Msk (0x1U << ADC_CFGR_AUTDLY_Pos) /*!< 0x00004000 */
+#define ADC_CFGR_AUTDLY ADC_CFGR_AUTDLY_Msk /*!< ADC low power auto wait */
+
+#define ADC_CFGR_DISCEN_Pos (16U)
+#define ADC_CFGR_DISCEN_Msk (0x1U << ADC_CFGR_DISCEN_Pos) /*!< 0x00010000 */
+#define ADC_CFGR_DISCEN ADC_CFGR_DISCEN_Msk /*!< ADC group regular sequencer discontinuous mode */
+
+#define ADC_CFGR_DISCNUM_Pos (17U)
+#define ADC_CFGR_DISCNUM_Msk (0x7U << ADC_CFGR_DISCNUM_Pos) /*!< 0x000E0000 */
+#define ADC_CFGR_DISCNUM ADC_CFGR_DISCNUM_Msk /*!< ADC group regular sequencer discontinuous number of ranks */
+#define ADC_CFGR_DISCNUM_0 (0x1U << ADC_CFGR_DISCNUM_Pos) /*!< 0x00020000 */
+#define ADC_CFGR_DISCNUM_1 (0x2U << ADC_CFGR_DISCNUM_Pos) /*!< 0x00040000 */
+#define ADC_CFGR_DISCNUM_2 (0x4U << ADC_CFGR_DISCNUM_Pos) /*!< 0x00080000 */
+
+#define ADC_CFGR_JDISCEN_Pos (20U)
+#define ADC_CFGR_JDISCEN_Msk (0x1U << ADC_CFGR_JDISCEN_Pos) /*!< 0x00100000 */
+#define ADC_CFGR_JDISCEN ADC_CFGR_JDISCEN_Msk /*!< ADC group injected sequencer discontinuous mode */
+#define ADC_CFGR_JQM_Pos (21U)
+#define ADC_CFGR_JQM_Msk (0x1U << ADC_CFGR_JQM_Pos) /*!< 0x00200000 */
+#define ADC_CFGR_JQM ADC_CFGR_JQM_Msk /*!< ADC group injected contexts queue mode */
+#define ADC_CFGR_AWD1SGL_Pos (22U)
+#define ADC_CFGR_AWD1SGL_Msk (0x1U << ADC_CFGR_AWD1SGL_Pos) /*!< 0x00400000 */
+#define ADC_CFGR_AWD1SGL ADC_CFGR_AWD1SGL_Msk /*!< ADC analog watchdog 1 monitoring a single channel or all channels */
+#define ADC_CFGR_AWD1EN_Pos (23U)
+#define ADC_CFGR_AWD1EN_Msk (0x1U << ADC_CFGR_AWD1EN_Pos) /*!< 0x00800000 */
+#define ADC_CFGR_AWD1EN ADC_CFGR_AWD1EN_Msk /*!< ADC analog watchdog 1 enable on scope ADC group regular */
+#define ADC_CFGR_JAWD1EN_Pos (24U)
+#define ADC_CFGR_JAWD1EN_Msk (0x1U << ADC_CFGR_JAWD1EN_Pos) /*!< 0x01000000 */
+#define ADC_CFGR_JAWD1EN ADC_CFGR_JAWD1EN_Msk /*!< ADC analog watchdog 1 enable on scope ADC group injected */
+#define ADC_CFGR_JAUTO_Pos (25U)
+#define ADC_CFGR_JAUTO_Msk (0x1U << ADC_CFGR_JAUTO_Pos) /*!< 0x02000000 */
+#define ADC_CFGR_JAUTO ADC_CFGR_JAUTO_Msk /*!< ADC group injected automatic trigger mode */
+
+#define ADC_CFGR_AWD1CH_Pos (26U)
+#define ADC_CFGR_AWD1CH_Msk (0x1FU << ADC_CFGR_AWD1CH_Pos) /*!< 0x7C000000 */
+#define ADC_CFGR_AWD1CH ADC_CFGR_AWD1CH_Msk /*!< ADC analog watchdog 1 monitored channel selection */
+#define ADC_CFGR_AWD1CH_0 (0x01U << ADC_CFGR_AWD1CH_Pos) /*!< 0x04000000 */
+#define ADC_CFGR_AWD1CH_1 (0x02U << ADC_CFGR_AWD1CH_Pos) /*!< 0x08000000 */
+#define ADC_CFGR_AWD1CH_2 (0x04U << ADC_CFGR_AWD1CH_Pos) /*!< 0x10000000 */
+#define ADC_CFGR_AWD1CH_3 (0x08U << ADC_CFGR_AWD1CH_Pos) /*!< 0x20000000 */
+#define ADC_CFGR_AWD1CH_4 (0x10U << ADC_CFGR_AWD1CH_Pos) /*!< 0x40000000 */
+
+#define ADC_CFGR_JQDIS_Pos (31U)
+#define ADC_CFGR_JQDIS_Msk (0x1U << ADC_CFGR_JQDIS_Pos) /*!< 0x80000000 */
+#define ADC_CFGR_JQDIS ADC_CFGR_JQDIS_Msk /*!< ADC group injected contexts queue disable */
+
+/******************** Bit definition for ADC_CFGR2 register *****************/
+#define ADC_CFGR2_ROVSE_Pos (0U)
+#define ADC_CFGR2_ROVSE_Msk (0x1U << ADC_CFGR2_ROVSE_Pos) /*!< 0x00000001 */
+#define ADC_CFGR2_ROVSE ADC_CFGR2_ROVSE_Msk /*!< ADC oversampler enable on scope ADC group regular */
+#define ADC_CFGR2_JOVSE_Pos (1U)
+#define ADC_CFGR2_JOVSE_Msk (0x1U << ADC_CFGR2_JOVSE_Pos) /*!< 0x00000002 */
+#define ADC_CFGR2_JOVSE ADC_CFGR2_JOVSE_Msk /*!< ADC oversampler enable on scope ADC group injected */
+
+#define ADC_CFGR2_OVSR_Pos (2U)
+#define ADC_CFGR2_OVSR_Msk (0x7U << ADC_CFGR2_OVSR_Pos) /*!< 0x0000001C */
+#define ADC_CFGR2_OVSR ADC_CFGR2_OVSR_Msk /*!< ADC oversampling ratio */
+#define ADC_CFGR2_OVSR_0 (0x1U << ADC_CFGR2_OVSR_Pos) /*!< 0x00000004 */
+#define ADC_CFGR2_OVSR_1 (0x2U << ADC_CFGR2_OVSR_Pos) /*!< 0x00000008 */
+#define ADC_CFGR2_OVSR_2 (0x4U << ADC_CFGR2_OVSR_Pos) /*!< 0x00000010 */
+
+#define ADC_CFGR2_OVSS_Pos (5U)
+#define ADC_CFGR2_OVSS_Msk (0xFU << ADC_CFGR2_OVSS_Pos) /*!< 0x000001E0 */
+#define ADC_CFGR2_OVSS ADC_CFGR2_OVSS_Msk /*!< ADC oversampling shift */
+#define ADC_CFGR2_OVSS_0 (0x1U << ADC_CFGR2_OVSS_Pos) /*!< 0x00000020 */
+#define ADC_CFGR2_OVSS_1 (0x2U << ADC_CFGR2_OVSS_Pos) /*!< 0x00000040 */
+#define ADC_CFGR2_OVSS_2 (0x4U << ADC_CFGR2_OVSS_Pos) /*!< 0x00000080 */
+#define ADC_CFGR2_OVSS_3 (0x8U << ADC_CFGR2_OVSS_Pos) /*!< 0x00000100 */
+
+#define ADC_CFGR2_TROVS_Pos (9U)
+#define ADC_CFGR2_TROVS_Msk (0x1U << ADC_CFGR2_TROVS_Pos) /*!< 0x00000200 */
+#define ADC_CFGR2_TROVS ADC_CFGR2_TROVS_Msk /*!< ADC oversampling discontinuous mode (triggered mode) for ADC group regular */
+#define ADC_CFGR2_ROVSM_Pos (10U)
+#define ADC_CFGR2_ROVSM_Msk (0x1U << ADC_CFGR2_ROVSM_Pos) /*!< 0x00000400 */
+#define ADC_CFGR2_ROVSM ADC_CFGR2_ROVSM_Msk /*!< ADC oversampling mode managing interlaced conversions of ADC group regular and group injected */
+
+/******************** Bit definition for ADC_SMPR1 register *****************/
+#define ADC_SMPR1_SMP0_Pos (0U)
+#define ADC_SMPR1_SMP0_Msk (0x7U << ADC_SMPR1_SMP0_Pos) /*!< 0x00000007 */
+#define ADC_SMPR1_SMP0 ADC_SMPR1_SMP0_Msk /*!< ADC channel 0 sampling time selection */
+#define ADC_SMPR1_SMP0_0 (0x1U << ADC_SMPR1_SMP0_Pos) /*!< 0x00000001 */
+#define ADC_SMPR1_SMP0_1 (0x2U << ADC_SMPR1_SMP0_Pos) /*!< 0x00000002 */
+#define ADC_SMPR1_SMP0_2 (0x4U << ADC_SMPR1_SMP0_Pos) /*!< 0x00000004 */
+
+#define ADC_SMPR1_SMP1_Pos (3U)
+#define ADC_SMPR1_SMP1_Msk (0x7U << ADC_SMPR1_SMP1_Pos) /*!< 0x00000038 */
+#define ADC_SMPR1_SMP1 ADC_SMPR1_SMP1_Msk /*!< ADC channel 1 sampling time selection */
+#define ADC_SMPR1_SMP1_0 (0x1U << ADC_SMPR1_SMP1_Pos) /*!< 0x00000008 */
+#define ADC_SMPR1_SMP1_1 (0x2U << ADC_SMPR1_SMP1_Pos) /*!< 0x00000010 */
+#define ADC_SMPR1_SMP1_2 (0x4U << ADC_SMPR1_SMP1_Pos) /*!< 0x00000020 */
+
+#define ADC_SMPR1_SMP2_Pos (6U)
+#define ADC_SMPR1_SMP2_Msk (0x7U << ADC_SMPR1_SMP2_Pos) /*!< 0x000001C0 */
+#define ADC_SMPR1_SMP2 ADC_SMPR1_SMP2_Msk /*!< ADC channel 2 sampling time selection */
+#define ADC_SMPR1_SMP2_0 (0x1U << ADC_SMPR1_SMP2_Pos) /*!< 0x00000040 */
+#define ADC_SMPR1_SMP2_1 (0x2U << ADC_SMPR1_SMP2_Pos) /*!< 0x00000080 */
+#define ADC_SMPR1_SMP2_2 (0x4U << ADC_SMPR1_SMP2_Pos) /*!< 0x00000100 */
+
+#define ADC_SMPR1_SMP3_Pos (9U)
+#define ADC_SMPR1_SMP3_Msk (0x7U << ADC_SMPR1_SMP3_Pos) /*!< 0x00000E00 */
+#define ADC_SMPR1_SMP3 ADC_SMPR1_SMP3_Msk /*!< ADC channel 3 sampling time selection */
+#define ADC_SMPR1_SMP3_0 (0x1U << ADC_SMPR1_SMP3_Pos) /*!< 0x00000200 */
+#define ADC_SMPR1_SMP3_1 (0x2U << ADC_SMPR1_SMP3_Pos) /*!< 0x00000400 */
+#define ADC_SMPR1_SMP3_2 (0x4U << ADC_SMPR1_SMP3_Pos) /*!< 0x00000800 */
+
+#define ADC_SMPR1_SMP4_Pos (12U)
+#define ADC_SMPR1_SMP4_Msk (0x7U << ADC_SMPR1_SMP4_Pos) /*!< 0x00007000 */
+#define ADC_SMPR1_SMP4 ADC_SMPR1_SMP4_Msk /*!< ADC channel 4 sampling time selection */
+#define ADC_SMPR1_SMP4_0 (0x1U << ADC_SMPR1_SMP4_Pos) /*!< 0x00001000 */
+#define ADC_SMPR1_SMP4_1 (0x2U << ADC_SMPR1_SMP4_Pos) /*!< 0x00002000 */
+#define ADC_SMPR1_SMP4_2 (0x4U << ADC_SMPR1_SMP4_Pos) /*!< 0x00004000 */
+
+#define ADC_SMPR1_SMP5_Pos (15U)
+#define ADC_SMPR1_SMP5_Msk (0x7U << ADC_SMPR1_SMP5_Pos) /*!< 0x00038000 */
+#define ADC_SMPR1_SMP5 ADC_SMPR1_SMP5_Msk /*!< ADC channel 5 sampling time selection */
+#define ADC_SMPR1_SMP5_0 (0x1U << ADC_SMPR1_SMP5_Pos) /*!< 0x00008000 */
+#define ADC_SMPR1_SMP5_1 (0x2U << ADC_SMPR1_SMP5_Pos) /*!< 0x00010000 */
+#define ADC_SMPR1_SMP5_2 (0x4U << ADC_SMPR1_SMP5_Pos) /*!< 0x00020000 */
+
+#define ADC_SMPR1_SMP6_Pos (18U)
+#define ADC_SMPR1_SMP6_Msk (0x7U << ADC_SMPR1_SMP6_Pos) /*!< 0x001C0000 */
+#define ADC_SMPR1_SMP6 ADC_SMPR1_SMP6_Msk /*!< ADC channel 6 sampling time selection */
+#define ADC_SMPR1_SMP6_0 (0x1U << ADC_SMPR1_SMP6_Pos) /*!< 0x00040000 */
+#define ADC_SMPR1_SMP6_1 (0x2U << ADC_SMPR1_SMP6_Pos) /*!< 0x00080000 */
+#define ADC_SMPR1_SMP6_2 (0x4U << ADC_SMPR1_SMP6_Pos) /*!< 0x00100000 */
+
+#define ADC_SMPR1_SMP7_Pos (21U)
+#define ADC_SMPR1_SMP7_Msk (0x7U << ADC_SMPR1_SMP7_Pos) /*!< 0x00E00000 */
+#define ADC_SMPR1_SMP7 ADC_SMPR1_SMP7_Msk /*!< ADC channel 7 sampling time selection */
+#define ADC_SMPR1_SMP7_0 (0x1U << ADC_SMPR1_SMP7_Pos) /*!< 0x00200000 */
+#define ADC_SMPR1_SMP7_1 (0x2U << ADC_SMPR1_SMP7_Pos) /*!< 0x00400000 */
+#define ADC_SMPR1_SMP7_2 (0x4U << ADC_SMPR1_SMP7_Pos) /*!< 0x00800000 */
+
+#define ADC_SMPR1_SMP8_Pos (24U)
+#define ADC_SMPR1_SMP8_Msk (0x7U << ADC_SMPR1_SMP8_Pos) /*!< 0x07000000 */
+#define ADC_SMPR1_SMP8 ADC_SMPR1_SMP8_Msk /*!< ADC channel 8 sampling time selection */
+#define ADC_SMPR1_SMP8_0 (0x1U << ADC_SMPR1_SMP8_Pos) /*!< 0x01000000 */
+#define ADC_SMPR1_SMP8_1 (0x2U << ADC_SMPR1_SMP8_Pos) /*!< 0x02000000 */
+#define ADC_SMPR1_SMP8_2 (0x4U << ADC_SMPR1_SMP8_Pos) /*!< 0x04000000 */
+
+#define ADC_SMPR1_SMP9_Pos (27U)
+#define ADC_SMPR1_SMP9_Msk (0x7U << ADC_SMPR1_SMP9_Pos) /*!< 0x38000000 */
+#define ADC_SMPR1_SMP9 ADC_SMPR1_SMP9_Msk /*!< ADC channel 9 sampling time selection */
+#define ADC_SMPR1_SMP9_0 (0x1U << ADC_SMPR1_SMP9_Pos) /*!< 0x08000000 */
+#define ADC_SMPR1_SMP9_1 (0x2U << ADC_SMPR1_SMP9_Pos) /*!< 0x10000000 */
+#define ADC_SMPR1_SMP9_2 (0x4U << ADC_SMPR1_SMP9_Pos) /*!< 0x20000000 */
+
+/******************** Bit definition for ADC_SMPR2 register *****************/
+#define ADC_SMPR2_SMP10_Pos (0U)
+#define ADC_SMPR2_SMP10_Msk (0x7U << ADC_SMPR2_SMP10_Pos) /*!< 0x00000007 */
+#define ADC_SMPR2_SMP10 ADC_SMPR2_SMP10_Msk /*!< ADC channel 10 sampling time selection */
+#define ADC_SMPR2_SMP10_0 (0x1U << ADC_SMPR2_SMP10_Pos) /*!< 0x00000001 */
+#define ADC_SMPR2_SMP10_1 (0x2U << ADC_SMPR2_SMP10_Pos) /*!< 0x00000002 */
+#define ADC_SMPR2_SMP10_2 (0x4U << ADC_SMPR2_SMP10_Pos) /*!< 0x00000004 */
+
+#define ADC_SMPR2_SMP11_Pos (3U)
+#define ADC_SMPR2_SMP11_Msk (0x7U << ADC_SMPR2_SMP11_Pos) /*!< 0x00000038 */
+#define ADC_SMPR2_SMP11 ADC_SMPR2_SMP11_Msk /*!< ADC channel 11 sampling time selection */
+#define ADC_SMPR2_SMP11_0 (0x1U << ADC_SMPR2_SMP11_Pos) /*!< 0x00000008 */
+#define ADC_SMPR2_SMP11_1 (0x2U << ADC_SMPR2_SMP11_Pos) /*!< 0x00000010 */
+#define ADC_SMPR2_SMP11_2 (0x4U << ADC_SMPR2_SMP11_Pos) /*!< 0x00000020 */
+
+#define ADC_SMPR2_SMP12_Pos (6U)
+#define ADC_SMPR2_SMP12_Msk (0x7U << ADC_SMPR2_SMP12_Pos) /*!< 0x000001C0 */
+#define ADC_SMPR2_SMP12 ADC_SMPR2_SMP12_Msk /*!< ADC channel 12 sampling time selection */
+#define ADC_SMPR2_SMP12_0 (0x1U << ADC_SMPR2_SMP12_Pos) /*!< 0x00000040 */
+#define ADC_SMPR2_SMP12_1 (0x2U << ADC_SMPR2_SMP12_Pos) /*!< 0x00000080 */
+#define ADC_SMPR2_SMP12_2 (0x4U << ADC_SMPR2_SMP12_Pos) /*!< 0x00000100 */
+
+#define ADC_SMPR2_SMP13_Pos (9U)
+#define ADC_SMPR2_SMP13_Msk (0x7U << ADC_SMPR2_SMP13_Pos) /*!< 0x00000E00 */
+#define ADC_SMPR2_SMP13 ADC_SMPR2_SMP13_Msk /*!< ADC channel 13 sampling time selection */
+#define ADC_SMPR2_SMP13_0 (0x1U << ADC_SMPR2_SMP13_Pos) /*!< 0x00000200 */
+#define ADC_SMPR2_SMP13_1 (0x2U << ADC_SMPR2_SMP13_Pos) /*!< 0x00000400 */
+#define ADC_SMPR2_SMP13_2 (0x4U << ADC_SMPR2_SMP13_Pos) /*!< 0x00000800 */
+
+#define ADC_SMPR2_SMP14_Pos (12U)
+#define ADC_SMPR2_SMP14_Msk (0x7U << ADC_SMPR2_SMP14_Pos) /*!< 0x00007000 */
+#define ADC_SMPR2_SMP14 ADC_SMPR2_SMP14_Msk /*!< ADC channel 14 sampling time selection */
+#define ADC_SMPR2_SMP14_0 (0x1U << ADC_SMPR2_SMP14_Pos) /*!< 0x00001000 */
+#define ADC_SMPR2_SMP14_1 (0x2U << ADC_SMPR2_SMP14_Pos) /*!< 0x00002000 */
+#define ADC_SMPR2_SMP14_2 (0x4U << ADC_SMPR2_SMP14_Pos) /*!< 0x00004000 */
+
+#define ADC_SMPR2_SMP15_Pos (15U)
+#define ADC_SMPR2_SMP15_Msk (0x7U << ADC_SMPR2_SMP15_Pos) /*!< 0x00038000 */
+#define ADC_SMPR2_SMP15 ADC_SMPR2_SMP15_Msk /*!< ADC channel 15 sampling time selection */
+#define ADC_SMPR2_SMP15_0 (0x1U << ADC_SMPR2_SMP15_Pos) /*!< 0x00008000 */
+#define ADC_SMPR2_SMP15_1 (0x2U << ADC_SMPR2_SMP15_Pos) /*!< 0x00010000 */
+#define ADC_SMPR2_SMP15_2 (0x4U << ADC_SMPR2_SMP15_Pos) /*!< 0x00020000 */
+
+#define ADC_SMPR2_SMP16_Pos (18U)
+#define ADC_SMPR2_SMP16_Msk (0x7U << ADC_SMPR2_SMP16_Pos) /*!< 0x001C0000 */
+#define ADC_SMPR2_SMP16 ADC_SMPR2_SMP16_Msk /*!< ADC channel 16 sampling time selection */
+#define ADC_SMPR2_SMP16_0 (0x1U << ADC_SMPR2_SMP16_Pos) /*!< 0x00040000 */
+#define ADC_SMPR2_SMP16_1 (0x2U << ADC_SMPR2_SMP16_Pos) /*!< 0x00080000 */
+#define ADC_SMPR2_SMP16_2 (0x4U << ADC_SMPR2_SMP16_Pos) /*!< 0x00100000 */
+
+#define ADC_SMPR2_SMP17_Pos (21U)
+#define ADC_SMPR2_SMP17_Msk (0x7U << ADC_SMPR2_SMP17_Pos) /*!< 0x00E00000 */
+#define ADC_SMPR2_SMP17 ADC_SMPR2_SMP17_Msk /*!< ADC channel 17 sampling time selection */
+#define ADC_SMPR2_SMP17_0 (0x1U << ADC_SMPR2_SMP17_Pos) /*!< 0x00200000 */
+#define ADC_SMPR2_SMP17_1 (0x2U << ADC_SMPR2_SMP17_Pos) /*!< 0x00400000 */
+#define ADC_SMPR2_SMP17_2 (0x4U << ADC_SMPR2_SMP17_Pos) /*!< 0x00800000 */
+
+#define ADC_SMPR2_SMP18_Pos (24U)
+#define ADC_SMPR2_SMP18_Msk (0x7U << ADC_SMPR2_SMP18_Pos) /*!< 0x07000000 */
+#define ADC_SMPR2_SMP18 ADC_SMPR2_SMP18_Msk /*!< ADC channel 18 sampling time selection */
+#define ADC_SMPR2_SMP18_0 (0x1U << ADC_SMPR2_SMP18_Pos) /*!< 0x01000000 */
+#define ADC_SMPR2_SMP18_1 (0x2U << ADC_SMPR2_SMP18_Pos) /*!< 0x02000000 */
+#define ADC_SMPR2_SMP18_2 (0x4U << ADC_SMPR2_SMP18_Pos) /*!< 0x04000000 */
+
+/******************** Bit definition for ADC_TR1 register *******************/
+#define ADC_TR1_LT1_Pos (0U)
+#define ADC_TR1_LT1_Msk (0xFFFU << ADC_TR1_LT1_Pos) /*!< 0x00000FFF */
+#define ADC_TR1_LT1 ADC_TR1_LT1_Msk /*!< ADC analog watchdog 1 threshold low */
+#define ADC_TR1_LT1_0 (0x001U << ADC_TR1_LT1_Pos) /*!< 0x00000001 */
+#define ADC_TR1_LT1_1 (0x002U << ADC_TR1_LT1_Pos) /*!< 0x00000002 */
+#define ADC_TR1_LT1_2 (0x004U << ADC_TR1_LT1_Pos) /*!< 0x00000004 */
+#define ADC_TR1_LT1_3 (0x008U << ADC_TR1_LT1_Pos) /*!< 0x00000008 */
+#define ADC_TR1_LT1_4 (0x010U << ADC_TR1_LT1_Pos) /*!< 0x00000010 */
+#define ADC_TR1_LT1_5 (0x020U << ADC_TR1_LT1_Pos) /*!< 0x00000020 */
+#define ADC_TR1_LT1_6 (0x040U << ADC_TR1_LT1_Pos) /*!< 0x00000040 */
+#define ADC_TR1_LT1_7 (0x080U << ADC_TR1_LT1_Pos) /*!< 0x00000080 */
+#define ADC_TR1_LT1_8 (0x100U << ADC_TR1_LT1_Pos) /*!< 0x00000100 */
+#define ADC_TR1_LT1_9 (0x200U << ADC_TR1_LT1_Pos) /*!< 0x00000200 */
+#define ADC_TR1_LT1_10 (0x400U << ADC_TR1_LT1_Pos) /*!< 0x00000400 */
+#define ADC_TR1_LT1_11 (0x800U << ADC_TR1_LT1_Pos) /*!< 0x00000800 */
+
+#define ADC_TR1_HT1_Pos (16U)
+#define ADC_TR1_HT1_Msk (0xFFFU << ADC_TR1_HT1_Pos) /*!< 0x0FFF0000 */
+#define ADC_TR1_HT1 ADC_TR1_HT1_Msk /*!< ADC Analog watchdog 1 threshold high */
+#define ADC_TR1_HT1_0 (0x001U << ADC_TR1_HT1_Pos) /*!< 0x00010000 */
+#define ADC_TR1_HT1_1 (0x002U << ADC_TR1_HT1_Pos) /*!< 0x00020000 */
+#define ADC_TR1_HT1_2 (0x004U << ADC_TR1_HT1_Pos) /*!< 0x00040000 */
+#define ADC_TR1_HT1_3 (0x008U << ADC_TR1_HT1_Pos) /*!< 0x00080000 */
+#define ADC_TR1_HT1_4 (0x010U << ADC_TR1_HT1_Pos) /*!< 0x00100000 */
+#define ADC_TR1_HT1_5 (0x020U << ADC_TR1_HT1_Pos) /*!< 0x00200000 */
+#define ADC_TR1_HT1_6 (0x040U << ADC_TR1_HT1_Pos) /*!< 0x00400000 */
+#define ADC_TR1_HT1_7 (0x080U << ADC_TR1_HT1_Pos) /*!< 0x00800000 */
+#define ADC_TR1_HT1_8 (0x100U << ADC_TR1_HT1_Pos) /*!< 0x01000000 */
+#define ADC_TR1_HT1_9 (0x200U << ADC_TR1_HT1_Pos) /*!< 0x02000000 */
+#define ADC_TR1_HT1_10 (0x400U << ADC_TR1_HT1_Pos) /*!< 0x04000000 */
+#define ADC_TR1_HT1_11 (0x800U << ADC_TR1_HT1_Pos) /*!< 0x08000000 */
+
+/******************** Bit definition for ADC_TR2 register *******************/
+#define ADC_TR2_LT2_Pos (0U)
+#define ADC_TR2_LT2_Msk (0xFFU << ADC_TR2_LT2_Pos) /*!< 0x000000FF */
+#define ADC_TR2_LT2 ADC_TR2_LT2_Msk /*!< ADC analog watchdog 2 threshold low */
+#define ADC_TR2_LT2_0 (0x01U << ADC_TR2_LT2_Pos) /*!< 0x00000001 */
+#define ADC_TR2_LT2_1 (0x02U << ADC_TR2_LT2_Pos) /*!< 0x00000002 */
+#define ADC_TR2_LT2_2 (0x04U << ADC_TR2_LT2_Pos) /*!< 0x00000004 */
+#define ADC_TR2_LT2_3 (0x08U << ADC_TR2_LT2_Pos) /*!< 0x00000008 */
+#define ADC_TR2_LT2_4 (0x10U << ADC_TR2_LT2_Pos) /*!< 0x00000010 */
+#define ADC_TR2_LT2_5 (0x20U << ADC_TR2_LT2_Pos) /*!< 0x00000020 */
+#define ADC_TR2_LT2_6 (0x40U << ADC_TR2_LT2_Pos) /*!< 0x00000040 */
+#define ADC_TR2_LT2_7 (0x80U << ADC_TR2_LT2_Pos) /*!< 0x00000080 */
+
+#define ADC_TR2_HT2_Pos (16U)
+#define ADC_TR2_HT2_Msk (0xFFU << ADC_TR2_HT2_Pos) /*!< 0x00FF0000 */
+#define ADC_TR2_HT2 ADC_TR2_HT2_Msk /*!< ADC analog watchdog 2 threshold high */
+#define ADC_TR2_HT2_0 (0x01U << ADC_TR2_HT2_Pos) /*!< 0x00010000 */
+#define ADC_TR2_HT2_1 (0x02U << ADC_TR2_HT2_Pos) /*!< 0x00020000 */
+#define ADC_TR2_HT2_2 (0x04U << ADC_TR2_HT2_Pos) /*!< 0x00040000 */
+#define ADC_TR2_HT2_3 (0x08U << ADC_TR2_HT2_Pos) /*!< 0x00080000 */
+#define ADC_TR2_HT2_4 (0x10U << ADC_TR2_HT2_Pos) /*!< 0x00100000 */
+#define ADC_TR2_HT2_5 (0x20U << ADC_TR2_HT2_Pos) /*!< 0x00200000 */
+#define ADC_TR2_HT2_6 (0x40U << ADC_TR2_HT2_Pos) /*!< 0x00400000 */
+#define ADC_TR2_HT2_7 (0x80U << ADC_TR2_HT2_Pos) /*!< 0x00800000 */
+
+/******************** Bit definition for ADC_TR3 register *******************/
+#define ADC_TR3_LT3_Pos (0U)
+#define ADC_TR3_LT3_Msk (0xFFU << ADC_TR3_LT3_Pos) /*!< 0x000000FF */
+#define ADC_TR3_LT3 ADC_TR3_LT3_Msk /*!< ADC analog watchdog 3 threshold low */
+#define ADC_TR3_LT3_0 (0x01U << ADC_TR3_LT3_Pos) /*!< 0x00000001 */
+#define ADC_TR3_LT3_1 (0x02U << ADC_TR3_LT3_Pos) /*!< 0x00000002 */
+#define ADC_TR3_LT3_2 (0x04U << ADC_TR3_LT3_Pos) /*!< 0x00000004 */
+#define ADC_TR3_LT3_3 (0x08U << ADC_TR3_LT3_Pos) /*!< 0x00000008 */
+#define ADC_TR3_LT3_4 (0x10U << ADC_TR3_LT3_Pos) /*!< 0x00000010 */
+#define ADC_TR3_LT3_5 (0x20U << ADC_TR3_LT3_Pos) /*!< 0x00000020 */
+#define ADC_TR3_LT3_6 (0x40U << ADC_TR3_LT3_Pos) /*!< 0x00000040 */
+#define ADC_TR3_LT3_7 (0x80U << ADC_TR3_LT3_Pos) /*!< 0x00000080 */
+
+#define ADC_TR3_HT3_Pos (16U)
+#define ADC_TR3_HT3_Msk (0xFFU << ADC_TR3_HT3_Pos) /*!< 0x00FF0000 */
+#define ADC_TR3_HT3 ADC_TR3_HT3_Msk /*!< ADC analog watchdog 3 threshold high */
+#define ADC_TR3_HT3_0 (0x01U << ADC_TR3_HT3_Pos) /*!< 0x00010000 */
+#define ADC_TR3_HT3_1 (0x02U << ADC_TR3_HT3_Pos) /*!< 0x00020000 */
+#define ADC_TR3_HT3_2 (0x04U << ADC_TR3_HT3_Pos) /*!< 0x00040000 */
+#define ADC_TR3_HT3_3 (0x08U << ADC_TR3_HT3_Pos) /*!< 0x00080000 */
+#define ADC_TR3_HT3_4 (0x10U << ADC_TR3_HT3_Pos) /*!< 0x00100000 */
+#define ADC_TR3_HT3_5 (0x20U << ADC_TR3_HT3_Pos) /*!< 0x00200000 */
+#define ADC_TR3_HT3_6 (0x40U << ADC_TR3_HT3_Pos) /*!< 0x00400000 */
+#define ADC_TR3_HT3_7 (0x80U << ADC_TR3_HT3_Pos) /*!< 0x00800000 */
+
+/******************** Bit definition for ADC_SQR1 register ******************/
+#define ADC_SQR1_L_Pos (0U)
+#define ADC_SQR1_L_Msk (0xFU << ADC_SQR1_L_Pos) /*!< 0x0000000F */
+#define ADC_SQR1_L ADC_SQR1_L_Msk /*!< ADC group regular sequencer scan length */
+#define ADC_SQR1_L_0 (0x1U << ADC_SQR1_L_Pos) /*!< 0x00000001 */
+#define ADC_SQR1_L_1 (0x2U << ADC_SQR1_L_Pos) /*!< 0x00000002 */
+#define ADC_SQR1_L_2 (0x4U << ADC_SQR1_L_Pos) /*!< 0x00000004 */
+#define ADC_SQR1_L_3 (0x8U << ADC_SQR1_L_Pos) /*!< 0x00000008 */
+
+#define ADC_SQR1_SQ1_Pos (6U)
+#define ADC_SQR1_SQ1_Msk (0x1FU << ADC_SQR1_SQ1_Pos) /*!< 0x000007C0 */
+#define ADC_SQR1_SQ1 ADC_SQR1_SQ1_Msk /*!< ADC group regular sequencer rank 1 */
+#define ADC_SQR1_SQ1_0 (0x01U << ADC_SQR1_SQ1_Pos) /*!< 0x00000040 */
+#define ADC_SQR1_SQ1_1 (0x02U << ADC_SQR1_SQ1_Pos) /*!< 0x00000080 */
+#define ADC_SQR1_SQ1_2 (0x04U << ADC_SQR1_SQ1_Pos) /*!< 0x00000100 */
+#define ADC_SQR1_SQ1_3 (0x08U << ADC_SQR1_SQ1_Pos) /*!< 0x00000200 */
+#define ADC_SQR1_SQ1_4 (0x10U << ADC_SQR1_SQ1_Pos) /*!< 0x00000400 */
+
+#define ADC_SQR1_SQ2_Pos (12U)
+#define ADC_SQR1_SQ2_Msk (0x1FU << ADC_SQR1_SQ2_Pos) /*!< 0x0001F000 */
+#define ADC_SQR1_SQ2 ADC_SQR1_SQ2_Msk /*!< ADC group regular sequencer rank 2 */
+#define ADC_SQR1_SQ2_0 (0x01U << ADC_SQR1_SQ2_Pos) /*!< 0x00001000 */
+#define ADC_SQR1_SQ2_1 (0x02U << ADC_SQR1_SQ2_Pos) /*!< 0x00002000 */
+#define ADC_SQR1_SQ2_2 (0x04U << ADC_SQR1_SQ2_Pos) /*!< 0x00004000 */
+#define ADC_SQR1_SQ2_3 (0x08U << ADC_SQR1_SQ2_Pos) /*!< 0x00008000 */
+#define ADC_SQR1_SQ2_4 (0x10U << ADC_SQR1_SQ2_Pos) /*!< 0x00010000 */
+
+#define ADC_SQR1_SQ3_Pos (18U)
+#define ADC_SQR1_SQ3_Msk (0x1FU << ADC_SQR1_SQ3_Pos) /*!< 0x007C0000 */
+#define ADC_SQR1_SQ3 ADC_SQR1_SQ3_Msk /*!< ADC group regular sequencer rank 3 */
+#define ADC_SQR1_SQ3_0 (0x01U << ADC_SQR1_SQ3_Pos) /*!< 0x00040000 */
+#define ADC_SQR1_SQ3_1 (0x02U << ADC_SQR1_SQ3_Pos) /*!< 0x00080000 */
+#define ADC_SQR1_SQ3_2 (0x04U << ADC_SQR1_SQ3_Pos) /*!< 0x00100000 */
+#define ADC_SQR1_SQ3_3 (0x08U << ADC_SQR1_SQ3_Pos) /*!< 0x00200000 */
+#define ADC_SQR1_SQ3_4 (0x10U << ADC_SQR1_SQ3_Pos) /*!< 0x00400000 */
+
+#define ADC_SQR1_SQ4_Pos (24U)
+#define ADC_SQR1_SQ4_Msk (0x1FU << ADC_SQR1_SQ4_Pos) /*!< 0x1F000000 */
+#define ADC_SQR1_SQ4 ADC_SQR1_SQ4_Msk /*!< ADC group regular sequencer rank 4 */
+#define ADC_SQR1_SQ4_0 (0x01U << ADC_SQR1_SQ4_Pos) /*!< 0x01000000 */
+#define ADC_SQR1_SQ4_1 (0x02U << ADC_SQR1_SQ4_Pos) /*!< 0x02000000 */
+#define ADC_SQR1_SQ4_2 (0x04U << ADC_SQR1_SQ4_Pos) /*!< 0x04000000 */
+#define ADC_SQR1_SQ4_3 (0x08U << ADC_SQR1_SQ4_Pos) /*!< 0x08000000 */
+#define ADC_SQR1_SQ4_4 (0x10U << ADC_SQR1_SQ4_Pos) /*!< 0x10000000 */
+
+/******************** Bit definition for ADC_SQR2 register ******************/
+#define ADC_SQR2_SQ5_Pos (0U)
+#define ADC_SQR2_SQ5_Msk (0x1FU << ADC_SQR2_SQ5_Pos) /*!< 0x0000001F */
+#define ADC_SQR2_SQ5 ADC_SQR2_SQ5_Msk /*!< ADC group regular sequencer rank 5 */
+#define ADC_SQR2_SQ5_0 (0x01U << ADC_SQR2_SQ5_Pos) /*!< 0x00000001 */
+#define ADC_SQR2_SQ5_1 (0x02U << ADC_SQR2_SQ5_Pos) /*!< 0x00000002 */
+#define ADC_SQR2_SQ5_2 (0x04U << ADC_SQR2_SQ5_Pos) /*!< 0x00000004 */
+#define ADC_SQR2_SQ5_3 (0x08U << ADC_SQR2_SQ5_Pos) /*!< 0x00000008 */
+#define ADC_SQR2_SQ5_4 (0x10U << ADC_SQR2_SQ5_Pos) /*!< 0x00000010 */
+
+#define ADC_SQR2_SQ6_Pos (6U)
+#define ADC_SQR2_SQ6_Msk (0x1FU << ADC_SQR2_SQ6_Pos) /*!< 0x000007C0 */
+#define ADC_SQR2_SQ6 ADC_SQR2_SQ6_Msk /*!< ADC group regular sequencer rank 6 */
+#define ADC_SQR2_SQ6_0 (0x01U << ADC_SQR2_SQ6_Pos) /*!< 0x00000040 */
+#define ADC_SQR2_SQ6_1 (0x02U << ADC_SQR2_SQ6_Pos) /*!< 0x00000080 */
+#define ADC_SQR2_SQ6_2 (0x04U << ADC_SQR2_SQ6_Pos) /*!< 0x00000100 */
+#define ADC_SQR2_SQ6_3 (0x08U << ADC_SQR2_SQ6_Pos) /*!< 0x00000200 */
+#define ADC_SQR2_SQ6_4 (0x10U << ADC_SQR2_SQ6_Pos) /*!< 0x00000400 */
+
+#define ADC_SQR2_SQ7_Pos (12U)
+#define ADC_SQR2_SQ7_Msk (0x1FU << ADC_SQR2_SQ7_Pos) /*!< 0x0001F000 */
+#define ADC_SQR2_SQ7 ADC_SQR2_SQ7_Msk /*!< ADC group regular sequencer rank 7 */
+#define ADC_SQR2_SQ7_0 (0x01U << ADC_SQR2_SQ7_Pos) /*!< 0x00001000 */
+#define ADC_SQR2_SQ7_1 (0x02U << ADC_SQR2_SQ7_Pos) /*!< 0x00002000 */
+#define ADC_SQR2_SQ7_2 (0x04U << ADC_SQR2_SQ7_Pos) /*!< 0x00004000 */
+#define ADC_SQR2_SQ7_3 (0x08U << ADC_SQR2_SQ7_Pos) /*!< 0x00008000 */
+#define ADC_SQR2_SQ7_4 (0x10U << ADC_SQR2_SQ7_Pos) /*!< 0x00010000 */
+
+#define ADC_SQR2_SQ8_Pos (18U)
+#define ADC_SQR2_SQ8_Msk (0x1FU << ADC_SQR2_SQ8_Pos) /*!< 0x007C0000 */
+#define ADC_SQR2_SQ8 ADC_SQR2_SQ8_Msk /*!< ADC group regular sequencer rank 8 */
+#define ADC_SQR2_SQ8_0 (0x01U << ADC_SQR2_SQ8_Pos) /*!< 0x00040000 */
+#define ADC_SQR2_SQ8_1 (0x02U << ADC_SQR2_SQ8_Pos) /*!< 0x00080000 */
+#define ADC_SQR2_SQ8_2 (0x04U << ADC_SQR2_SQ8_Pos) /*!< 0x00100000 */
+#define ADC_SQR2_SQ8_3 (0x08U << ADC_SQR2_SQ8_Pos) /*!< 0x00200000 */
+#define ADC_SQR2_SQ8_4 (0x10U << ADC_SQR2_SQ8_Pos) /*!< 0x00400000 */
+
+#define ADC_SQR2_SQ9_Pos (24U)
+#define ADC_SQR2_SQ9_Msk (0x1FU << ADC_SQR2_SQ9_Pos) /*!< 0x1F000000 */
+#define ADC_SQR2_SQ9 ADC_SQR2_SQ9_Msk /*!< ADC group regular sequencer rank 9 */
+#define ADC_SQR2_SQ9_0 (0x01U << ADC_SQR2_SQ9_Pos) /*!< 0x01000000 */
+#define ADC_SQR2_SQ9_1 (0x02U << ADC_SQR2_SQ9_Pos) /*!< 0x02000000 */
+#define ADC_SQR2_SQ9_2 (0x04U << ADC_SQR2_SQ9_Pos) /*!< 0x04000000 */
+#define ADC_SQR2_SQ9_3 (0x08U << ADC_SQR2_SQ9_Pos) /*!< 0x08000000 */
+#define ADC_SQR2_SQ9_4 (0x10U << ADC_SQR2_SQ9_Pos) /*!< 0x10000000 */
+
+/******************** Bit definition for ADC_SQR3 register ******************/
+#define ADC_SQR3_SQ10_Pos (0U)
+#define ADC_SQR3_SQ10_Msk (0x1FU << ADC_SQR3_SQ10_Pos) /*!< 0x0000001F */
+#define ADC_SQR3_SQ10 ADC_SQR3_SQ10_Msk /*!< ADC group regular sequencer rank 10 */
+#define ADC_SQR3_SQ10_0 (0x01U << ADC_SQR3_SQ10_Pos) /*!< 0x00000001 */
+#define ADC_SQR3_SQ10_1 (0x02U << ADC_SQR3_SQ10_Pos) /*!< 0x00000002 */
+#define ADC_SQR3_SQ10_2 (0x04U << ADC_SQR3_SQ10_Pos) /*!< 0x00000004 */
+#define ADC_SQR3_SQ10_3 (0x08U << ADC_SQR3_SQ10_Pos) /*!< 0x00000008 */
+#define ADC_SQR3_SQ10_4 (0x10U << ADC_SQR3_SQ10_Pos) /*!< 0x00000010 */
+
+#define ADC_SQR3_SQ11_Pos (6U)
+#define ADC_SQR3_SQ11_Msk (0x1FU << ADC_SQR3_SQ11_Pos) /*!< 0x000007C0 */
+#define ADC_SQR3_SQ11 ADC_SQR3_SQ11_Msk /*!< ADC group regular sequencer rank 11 */
+#define ADC_SQR3_SQ11_0 (0x01U << ADC_SQR3_SQ11_Pos) /*!< 0x00000040 */
+#define ADC_SQR3_SQ11_1 (0x02U << ADC_SQR3_SQ11_Pos) /*!< 0x00000080 */
+#define ADC_SQR3_SQ11_2 (0x04U << ADC_SQR3_SQ11_Pos) /*!< 0x00000100 */
+#define ADC_SQR3_SQ11_3 (0x08U << ADC_SQR3_SQ11_Pos) /*!< 0x00000200 */
+#define ADC_SQR3_SQ11_4 (0x10U << ADC_SQR3_SQ11_Pos) /*!< 0x00000400 */
+
+#define ADC_SQR3_SQ12_Pos (12U)
+#define ADC_SQR3_SQ12_Msk (0x1FU << ADC_SQR3_SQ12_Pos) /*!< 0x0001F000 */
+#define ADC_SQR3_SQ12 ADC_SQR3_SQ12_Msk /*!< ADC group regular sequencer rank 12 */
+#define ADC_SQR3_SQ12_0 (0x01U << ADC_SQR3_SQ12_Pos) /*!< 0x00001000 */
+#define ADC_SQR3_SQ12_1 (0x02U << ADC_SQR3_SQ12_Pos) /*!< 0x00002000 */
+#define ADC_SQR3_SQ12_2 (0x04U << ADC_SQR3_SQ12_Pos) /*!< 0x00004000 */
+#define ADC_SQR3_SQ12_3 (0x08U << ADC_SQR3_SQ12_Pos) /*!< 0x00008000 */
+#define ADC_SQR3_SQ12_4 (0x10U << ADC_SQR3_SQ12_Pos) /*!< 0x00010000 */
+
+#define ADC_SQR3_SQ13_Pos (18U)
+#define ADC_SQR3_SQ13_Msk (0x1FU << ADC_SQR3_SQ13_Pos) /*!< 0x007C0000 */
+#define ADC_SQR3_SQ13 ADC_SQR3_SQ13_Msk /*!< ADC group regular sequencer rank 13 */
+#define ADC_SQR3_SQ13_0 (0x01U << ADC_SQR3_SQ13_Pos) /*!< 0x00040000 */
+#define ADC_SQR3_SQ13_1 (0x02U << ADC_SQR3_SQ13_Pos) /*!< 0x00080000 */
+#define ADC_SQR3_SQ13_2 (0x04U << ADC_SQR3_SQ13_Pos) /*!< 0x00100000 */
+#define ADC_SQR3_SQ13_3 (0x08U << ADC_SQR3_SQ13_Pos) /*!< 0x00200000 */
+#define ADC_SQR3_SQ13_4 (0x10U << ADC_SQR3_SQ13_Pos) /*!< 0x00400000 */
+
+#define ADC_SQR3_SQ14_Pos (24U)
+#define ADC_SQR3_SQ14_Msk (0x1FU << ADC_SQR3_SQ14_Pos) /*!< 0x1F000000 */
+#define ADC_SQR3_SQ14 ADC_SQR3_SQ14_Msk /*!< ADC group regular sequencer rank 14 */
+#define ADC_SQR3_SQ14_0 (0x01U << ADC_SQR3_SQ14_Pos) /*!< 0x01000000 */
+#define ADC_SQR3_SQ14_1 (0x02U << ADC_SQR3_SQ14_Pos) /*!< 0x02000000 */
+#define ADC_SQR3_SQ14_2 (0x04U << ADC_SQR3_SQ14_Pos) /*!< 0x04000000 */
+#define ADC_SQR3_SQ14_3 (0x08U << ADC_SQR3_SQ14_Pos) /*!< 0x08000000 */
+#define ADC_SQR3_SQ14_4 (0x10U << ADC_SQR3_SQ14_Pos) /*!< 0x10000000 */
+
+/******************** Bit definition for ADC_SQR4 register ******************/
+#define ADC_SQR4_SQ15_Pos (0U)
+#define ADC_SQR4_SQ15_Msk (0x1FU << ADC_SQR4_SQ15_Pos) /*!< 0x0000001F */
+#define ADC_SQR4_SQ15 ADC_SQR4_SQ15_Msk /*!< ADC group regular sequencer rank 15 */
+#define ADC_SQR4_SQ15_0 (0x01U << ADC_SQR4_SQ15_Pos) /*!< 0x00000001 */
+#define ADC_SQR4_SQ15_1 (0x02U << ADC_SQR4_SQ15_Pos) /*!< 0x00000002 */
+#define ADC_SQR4_SQ15_2 (0x04U << ADC_SQR4_SQ15_Pos) /*!< 0x00000004 */
+#define ADC_SQR4_SQ15_3 (0x08U << ADC_SQR4_SQ15_Pos) /*!< 0x00000008 */
+#define ADC_SQR4_SQ15_4 (0x10U << ADC_SQR4_SQ15_Pos) /*!< 0x00000010 */
+
+#define ADC_SQR4_SQ16_Pos (6U)
+#define ADC_SQR4_SQ16_Msk (0x1FU << ADC_SQR4_SQ16_Pos) /*!< 0x000007C0 */
+#define ADC_SQR4_SQ16 ADC_SQR4_SQ16_Msk /*!< ADC group regular sequencer rank 16 */
+#define ADC_SQR4_SQ16_0 (0x01U << ADC_SQR4_SQ16_Pos) /*!< 0x00000040 */
+#define ADC_SQR4_SQ16_1 (0x02U << ADC_SQR4_SQ16_Pos) /*!< 0x00000080 */
+#define ADC_SQR4_SQ16_2 (0x04U << ADC_SQR4_SQ16_Pos) /*!< 0x00000100 */
+#define ADC_SQR4_SQ16_3 (0x08U << ADC_SQR4_SQ16_Pos) /*!< 0x00000200 */
+#define ADC_SQR4_SQ16_4 (0x10U << ADC_SQR4_SQ16_Pos) /*!< 0x00000400 */
+
+/******************** Bit definition for ADC_DR register ********************/
+#define ADC_DR_RDATA_Pos (0U)
+#define ADC_DR_RDATA_Msk (0xFFFFU << ADC_DR_RDATA_Pos) /*!< 0x0000FFFF */
+#define ADC_DR_RDATA ADC_DR_RDATA_Msk /*!< ADC group regular conversion data */
+#define ADC_DR_RDATA_0 (0x0001U << ADC_DR_RDATA_Pos) /*!< 0x00000001 */
+#define ADC_DR_RDATA_1 (0x0002U << ADC_DR_RDATA_Pos) /*!< 0x00000002 */
+#define ADC_DR_RDATA_2 (0x0004U << ADC_DR_RDATA_Pos) /*!< 0x00000004 */
+#define ADC_DR_RDATA_3 (0x0008U << ADC_DR_RDATA_Pos) /*!< 0x00000008 */
+#define ADC_DR_RDATA_4 (0x0010U << ADC_DR_RDATA_Pos) /*!< 0x00000010 */
+#define ADC_DR_RDATA_5 (0x0020U << ADC_DR_RDATA_Pos) /*!< 0x00000020 */
+#define ADC_DR_RDATA_6 (0x0040U << ADC_DR_RDATA_Pos) /*!< 0x00000040 */
+#define ADC_DR_RDATA_7 (0x0080U << ADC_DR_RDATA_Pos) /*!< 0x00000080 */
+#define ADC_DR_RDATA_8 (0x0100U << ADC_DR_RDATA_Pos) /*!< 0x00000100 */
+#define ADC_DR_RDATA_9 (0x0200U << ADC_DR_RDATA_Pos) /*!< 0x00000200 */
+#define ADC_DR_RDATA_10 (0x0400U << ADC_DR_RDATA_Pos) /*!< 0x00000400 */
+#define ADC_DR_RDATA_11 (0x0800U << ADC_DR_RDATA_Pos) /*!< 0x00000800 */
+#define ADC_DR_RDATA_12 (0x1000U << ADC_DR_RDATA_Pos) /*!< 0x00001000 */
+#define ADC_DR_RDATA_13 (0x2000U << ADC_DR_RDATA_Pos) /*!< 0x00002000 */
+#define ADC_DR_RDATA_14 (0x4000U << ADC_DR_RDATA_Pos) /*!< 0x00004000 */
+#define ADC_DR_RDATA_15 (0x8000U << ADC_DR_RDATA_Pos) /*!< 0x00008000 */
+
+/******************** Bit definition for ADC_JSQR register ******************/
+#define ADC_JSQR_JL_Pos (0U)
+#define ADC_JSQR_JL_Msk (0x3U << ADC_JSQR_JL_Pos) /*!< 0x00000003 */
+#define ADC_JSQR_JL ADC_JSQR_JL_Msk /*!< ADC group injected sequencer scan length */
+#define ADC_JSQR_JL_0 (0x1U << ADC_JSQR_JL_Pos) /*!< 0x00000001 */
+#define ADC_JSQR_JL_1 (0x2U << ADC_JSQR_JL_Pos) /*!< 0x00000002 */
+
+#define ADC_JSQR_JEXTSEL_Pos (2U)
+#define ADC_JSQR_JEXTSEL_Msk (0xFU << ADC_JSQR_JEXTSEL_Pos) /*!< 0x0000003C */
+#define ADC_JSQR_JEXTSEL ADC_JSQR_JEXTSEL_Msk /*!< ADC group injected external trigger source */
+#define ADC_JSQR_JEXTSEL_0 (0x1U << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000004 */
+#define ADC_JSQR_JEXTSEL_1 (0x2U << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000008 */
+#define ADC_JSQR_JEXTSEL_2 (0x4U << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000010 */
+#define ADC_JSQR_JEXTSEL_3 (0x8U << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000020 */
+
+#define ADC_JSQR_JEXTEN_Pos (6U)
+#define ADC_JSQR_JEXTEN_Msk (0x3U << ADC_JSQR_JEXTEN_Pos) /*!< 0x000000C0 */
+#define ADC_JSQR_JEXTEN ADC_JSQR_JEXTEN_Msk /*!< ADC group injected external trigger polarity */
+#define ADC_JSQR_JEXTEN_0 (0x1U << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000040 */
+#define ADC_JSQR_JEXTEN_1 (0x2U << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000080 */
+
+#define ADC_JSQR_JSQ1_Pos (8U)
+#define ADC_JSQR_JSQ1_Msk (0x1FU << ADC_JSQR_JSQ1_Pos) /*!< 0x00001F00 */
+#define ADC_JSQR_JSQ1 ADC_JSQR_JSQ1_Msk /*!< ADC group injected sequencer rank 1 */
+#define ADC_JSQR_JSQ1_0 (0x01U << ADC_JSQR_JSQ1_Pos) /*!< 0x00000100 */
+#define ADC_JSQR_JSQ1_1 (0x02U << ADC_JSQR_JSQ1_Pos) /*!< 0x00000200 */
+#define ADC_JSQR_JSQ1_2 (0x04U << ADC_JSQR_JSQ1_Pos) /*!< 0x00000400 */
+#define ADC_JSQR_JSQ1_3 (0x08U << ADC_JSQR_JSQ1_Pos) /*!< 0x00000800 */
+#define ADC_JSQR_JSQ1_4 (0x10U << ADC_JSQR_JSQ1_Pos) /*!< 0x00001000 */
+
+#define ADC_JSQR_JSQ2_Pos (14U)
+#define ADC_JSQR_JSQ2_Msk (0x1FU << ADC_JSQR_JSQ2_Pos) /*!< 0x0007C000 */
+#define ADC_JSQR_JSQ2 ADC_JSQR_JSQ2_Msk /*!< ADC group injected sequencer rank 2 */
+#define ADC_JSQR_JSQ2_0 (0x01U << ADC_JSQR_JSQ2_Pos) /*!< 0x00004000 */
+#define ADC_JSQR_JSQ2_1 (0x02U << ADC_JSQR_JSQ2_Pos) /*!< 0x00008000 */
+#define ADC_JSQR_JSQ2_2 (0x04U << ADC_JSQR_JSQ2_Pos) /*!< 0x00010000 */
+#define ADC_JSQR_JSQ2_3 (0x08U << ADC_JSQR_JSQ2_Pos) /*!< 0x00020000 */
+#define ADC_JSQR_JSQ2_4 (0x10U << ADC_JSQR_JSQ2_Pos) /*!< 0x00040000 */
+
+#define ADC_JSQR_JSQ3_Pos (20U)
+#define ADC_JSQR_JSQ3_Msk (0x1FU << ADC_JSQR_JSQ3_Pos) /*!< 0x01F00000 */
+#define ADC_JSQR_JSQ3 ADC_JSQR_JSQ3_Msk /*!< ADC group injected sequencer rank 3 */
+#define ADC_JSQR_JSQ3_0 (0x01U << ADC_JSQR_JSQ3_Pos) /*!< 0x00100000 */
+#define ADC_JSQR_JSQ3_1 (0x02U << ADC_JSQR_JSQ3_Pos) /*!< 0x00200000 */
+#define ADC_JSQR_JSQ3_2 (0x04U << ADC_JSQR_JSQ3_Pos) /*!< 0x00400000 */
+#define ADC_JSQR_JSQ3_3 (0x08U << ADC_JSQR_JSQ3_Pos) /*!< 0x00800000 */
+#define ADC_JSQR_JSQ3_4 (0x10U << ADC_JSQR_JSQ3_Pos) /*!< 0x01000000 */
+
+#define ADC_JSQR_JSQ4_Pos (26U)
+#define ADC_JSQR_JSQ4_Msk (0x1FU << ADC_JSQR_JSQ4_Pos) /*!< 0x7C000000 */
+#define ADC_JSQR_JSQ4 ADC_JSQR_JSQ4_Msk /*!< ADC group injected sequencer rank 4 */
+#define ADC_JSQR_JSQ4_0 (0x01U << ADC_JSQR_JSQ4_Pos) /*!< 0x04000000 */
+#define ADC_JSQR_JSQ4_1 (0x02U << ADC_JSQR_JSQ4_Pos) /*!< 0x08000000 */
+#define ADC_JSQR_JSQ4_2 (0x04U << ADC_JSQR_JSQ4_Pos) /*!< 0x10000000 */
+#define ADC_JSQR_JSQ4_3 (0x08U << ADC_JSQR_JSQ4_Pos) /*!< 0x20000000 */
+#define ADC_JSQR_JSQ4_4 (0x10U << ADC_JSQR_JSQ4_Pos) /*!< 0x40000000 */
+
+/******************** Bit definition for ADC_OFR1 register ******************/
+#define ADC_OFR1_OFFSET1_Pos (0U)
+#define ADC_OFR1_OFFSET1_Msk (0xFFFU << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000FFF */
+#define ADC_OFR1_OFFSET1 ADC_OFR1_OFFSET1_Msk /*!< ADC offset number 1 offset level */
+#define ADC_OFR1_OFFSET1_0 (0x001U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000001 */
+#define ADC_OFR1_OFFSET1_1 (0x002U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000002 */
+#define ADC_OFR1_OFFSET1_2 (0x004U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000004 */
+#define ADC_OFR1_OFFSET1_3 (0x008U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000008 */
+#define ADC_OFR1_OFFSET1_4 (0x010U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000010 */
+#define ADC_OFR1_OFFSET1_5 (0x020U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000020 */
+#define ADC_OFR1_OFFSET1_6 (0x040U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000040 */
+#define ADC_OFR1_OFFSET1_7 (0x080U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000080 */
+#define ADC_OFR1_OFFSET1_8 (0x100U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000100 */
+#define ADC_OFR1_OFFSET1_9 (0x200U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000200 */
+#define ADC_OFR1_OFFSET1_10 (0x400U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000400 */
+#define ADC_OFR1_OFFSET1_11 (0x800U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000800 */
+
+#define ADC_OFR1_OFFSET1_CH_Pos (26U)
+#define ADC_OFR1_OFFSET1_CH_Msk (0x1FU << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x7C000000 */
+#define ADC_OFR1_OFFSET1_CH ADC_OFR1_OFFSET1_CH_Msk /*!< ADC offset number 1 channel selection */
+#define ADC_OFR1_OFFSET1_CH_0 (0x01U << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x04000000 */
+#define ADC_OFR1_OFFSET1_CH_1 (0x02U << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x08000000 */
+#define ADC_OFR1_OFFSET1_CH_2 (0x04U << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x10000000 */
+#define ADC_OFR1_OFFSET1_CH_3 (0x08U << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x20000000 */
+#define ADC_OFR1_OFFSET1_CH_4 (0x10U << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x40000000 */
+
+#define ADC_OFR1_OFFSET1_EN_Pos (31U)
+#define ADC_OFR1_OFFSET1_EN_Msk (0x1U << ADC_OFR1_OFFSET1_EN_Pos) /*!< 0x80000000 */
+#define ADC_OFR1_OFFSET1_EN ADC_OFR1_OFFSET1_EN_Msk /*!< ADC offset number 1 enable */
+
+/******************** Bit definition for ADC_OFR2 register ******************/
+#define ADC_OFR2_OFFSET2_Pos (0U)
+#define ADC_OFR2_OFFSET2_Msk (0xFFFU << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000FFF */
+#define ADC_OFR2_OFFSET2 ADC_OFR2_OFFSET2_Msk /*!< ADC offset number 2 offset level */
+#define ADC_OFR2_OFFSET2_0 (0x001U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000001 */
+#define ADC_OFR2_OFFSET2_1 (0x002U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000002 */
+#define ADC_OFR2_OFFSET2_2 (0x004U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000004 */
+#define ADC_OFR2_OFFSET2_3 (0x008U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000008 */
+#define ADC_OFR2_OFFSET2_4 (0x010U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000010 */
+#define ADC_OFR2_OFFSET2_5 (0x020U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000020 */
+#define ADC_OFR2_OFFSET2_6 (0x040U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000040 */
+#define ADC_OFR2_OFFSET2_7 (0x080U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000080 */
+#define ADC_OFR2_OFFSET2_8 (0x100U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000100 */
+#define ADC_OFR2_OFFSET2_9 (0x200U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000200 */
+#define ADC_OFR2_OFFSET2_10 (0x400U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000400 */
+#define ADC_OFR2_OFFSET2_11 (0x800U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000800 */
+
+#define ADC_OFR2_OFFSET2_CH_Pos (26U)
+#define ADC_OFR2_OFFSET2_CH_Msk (0x1FU << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x7C000000 */
+#define ADC_OFR2_OFFSET2_CH ADC_OFR2_OFFSET2_CH_Msk /*!< ADC offset number 2 channel selection */
+#define ADC_OFR2_OFFSET2_CH_0 (0x01U << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x04000000 */
+#define ADC_OFR2_OFFSET2_CH_1 (0x02U << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x08000000 */
+#define ADC_OFR2_OFFSET2_CH_2 (0x04U << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x10000000 */
+#define ADC_OFR2_OFFSET2_CH_3 (0x08U << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x20000000 */
+#define ADC_OFR2_OFFSET2_CH_4 (0x10U << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x40000000 */
+
+#define ADC_OFR2_OFFSET2_EN_Pos (31U)
+#define ADC_OFR2_OFFSET2_EN_Msk (0x1U << ADC_OFR2_OFFSET2_EN_Pos) /*!< 0x80000000 */
+#define ADC_OFR2_OFFSET2_EN ADC_OFR2_OFFSET2_EN_Msk /*!< ADC offset number 2 enable */
+
+/******************** Bit definition for ADC_OFR3 register ******************/
+#define ADC_OFR3_OFFSET3_Pos (0U)
+#define ADC_OFR3_OFFSET3_Msk (0xFFFU << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000FFF */
+#define ADC_OFR3_OFFSET3 ADC_OFR3_OFFSET3_Msk /*!< ADC offset number 3 offset level */
+#define ADC_OFR3_OFFSET3_0 (0x001U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000001 */
+#define ADC_OFR3_OFFSET3_1 (0x002U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000002 */
+#define ADC_OFR3_OFFSET3_2 (0x004U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000004 */
+#define ADC_OFR3_OFFSET3_3 (0x008U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000008 */
+#define ADC_OFR3_OFFSET3_4 (0x010U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000010 */
+#define ADC_OFR3_OFFSET3_5 (0x020U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000020 */
+#define ADC_OFR3_OFFSET3_6 (0x040U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000040 */
+#define ADC_OFR3_OFFSET3_7 (0x080U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000080 */
+#define ADC_OFR3_OFFSET3_8 (0x100U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000100 */
+#define ADC_OFR3_OFFSET3_9 (0x200U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000200 */
+#define ADC_OFR3_OFFSET3_10 (0x400U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000400 */
+#define ADC_OFR3_OFFSET3_11 (0x800U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000800 */
+
+#define ADC_OFR3_OFFSET3_CH_Pos (26U)
+#define ADC_OFR3_OFFSET3_CH_Msk (0x1FU << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x7C000000 */
+#define ADC_OFR3_OFFSET3_CH ADC_OFR3_OFFSET3_CH_Msk /*!< ADC offset number 3 channel selection */
+#define ADC_OFR3_OFFSET3_CH_0 (0x01U << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x04000000 */
+#define ADC_OFR3_OFFSET3_CH_1 (0x02U << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x08000000 */
+#define ADC_OFR3_OFFSET3_CH_2 (0x04U << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x10000000 */
+#define ADC_OFR3_OFFSET3_CH_3 (0x08U << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x20000000 */
+#define ADC_OFR3_OFFSET3_CH_4 (0x10U << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x40000000 */
+
+#define ADC_OFR3_OFFSET3_EN_Pos (31U)
+#define ADC_OFR3_OFFSET3_EN_Msk (0x1U << ADC_OFR3_OFFSET3_EN_Pos) /*!< 0x80000000 */
+#define ADC_OFR3_OFFSET3_EN ADC_OFR3_OFFSET3_EN_Msk /*!< ADC offset number 3 enable */
+
+/******************** Bit definition for ADC_OFR4 register ******************/
+#define ADC_OFR4_OFFSET4_Pos (0U)
+#define ADC_OFR4_OFFSET4_Msk (0xFFFU << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000FFF */
+#define ADC_OFR4_OFFSET4 ADC_OFR4_OFFSET4_Msk /*!< ADC offset number 4 offset level */
+#define ADC_OFR4_OFFSET4_0 (0x001U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000001 */
+#define ADC_OFR4_OFFSET4_1 (0x002U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000002 */
+#define ADC_OFR4_OFFSET4_2 (0x004U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000004 */
+#define ADC_OFR4_OFFSET4_3 (0x008U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000008 */
+#define ADC_OFR4_OFFSET4_4 (0x010U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000010 */
+#define ADC_OFR4_OFFSET4_5 (0x020U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000020 */
+#define ADC_OFR4_OFFSET4_6 (0x040U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000040 */
+#define ADC_OFR4_OFFSET4_7 (0x080U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000080 */
+#define ADC_OFR4_OFFSET4_8 (0x100U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000100 */
+#define ADC_OFR4_OFFSET4_9 (0x200U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000200 */
+#define ADC_OFR4_OFFSET4_10 (0x400U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000400 */
+#define ADC_OFR4_OFFSET4_11 (0x800U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000800 */
+
+#define ADC_OFR4_OFFSET4_CH_Pos (26U)
+#define ADC_OFR4_OFFSET4_CH_Msk (0x1FU << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x7C000000 */
+#define ADC_OFR4_OFFSET4_CH ADC_OFR4_OFFSET4_CH_Msk /*!< ADC offset number 4 channel selection */
+#define ADC_OFR4_OFFSET4_CH_0 (0x01U << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x04000000 */
+#define ADC_OFR4_OFFSET4_CH_1 (0x02U << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x08000000 */
+#define ADC_OFR4_OFFSET4_CH_2 (0x04U << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x10000000 */
+#define ADC_OFR4_OFFSET4_CH_3 (0x08U << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x20000000 */
+#define ADC_OFR4_OFFSET4_CH_4 (0x10U << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x40000000 */
+
+#define ADC_OFR4_OFFSET4_EN_Pos (31U)
+#define ADC_OFR4_OFFSET4_EN_Msk (0x1U << ADC_OFR4_OFFSET4_EN_Pos) /*!< 0x80000000 */
+#define ADC_OFR4_OFFSET4_EN ADC_OFR4_OFFSET4_EN_Msk /*!< ADC offset number 4 enable */
+
+/******************** Bit definition for ADC_JDR1 register ******************/
+#define ADC_JDR1_JDATA_Pos (0U)
+#define ADC_JDR1_JDATA_Msk (0xFFFFU << ADC_JDR1_JDATA_Pos) /*!< 0x0000FFFF */
+#define ADC_JDR1_JDATA ADC_JDR1_JDATA_Msk /*!< ADC group injected sequencer rank 1 conversion data */
+#define ADC_JDR1_JDATA_0 (0x0001U << ADC_JDR1_JDATA_Pos) /*!< 0x00000001 */
+#define ADC_JDR1_JDATA_1 (0x0002U << ADC_JDR1_JDATA_Pos) /*!< 0x00000002 */
+#define ADC_JDR1_JDATA_2 (0x0004U << ADC_JDR1_JDATA_Pos) /*!< 0x00000004 */
+#define ADC_JDR1_JDATA_3 (0x0008U << ADC_JDR1_JDATA_Pos) /*!< 0x00000008 */
+#define ADC_JDR1_JDATA_4 (0x0010U << ADC_JDR1_JDATA_Pos) /*!< 0x00000010 */
+#define ADC_JDR1_JDATA_5 (0x0020U << ADC_JDR1_JDATA_Pos) /*!< 0x00000020 */
+#define ADC_JDR1_JDATA_6 (0x0040U << ADC_JDR1_JDATA_Pos) /*!< 0x00000040 */
+#define ADC_JDR1_JDATA_7 (0x0080U << ADC_JDR1_JDATA_Pos) /*!< 0x00000080 */
+#define ADC_JDR1_JDATA_8 (0x0100U << ADC_JDR1_JDATA_Pos) /*!< 0x00000100 */
+#define ADC_JDR1_JDATA_9 (0x0200U << ADC_JDR1_JDATA_Pos) /*!< 0x00000200 */
+#define ADC_JDR1_JDATA_10 (0x0400U << ADC_JDR1_JDATA_Pos) /*!< 0x00000400 */
+#define ADC_JDR1_JDATA_11 (0x0800U << ADC_JDR1_JDATA_Pos) /*!< 0x00000800 */
+#define ADC_JDR1_JDATA_12 (0x1000U << ADC_JDR1_JDATA_Pos) /*!< 0x00001000 */
+#define ADC_JDR1_JDATA_13 (0x2000U << ADC_JDR1_JDATA_Pos) /*!< 0x00002000 */
+#define ADC_JDR1_JDATA_14 (0x4000U << ADC_JDR1_JDATA_Pos) /*!< 0x00004000 */
+#define ADC_JDR1_JDATA_15 (0x8000U << ADC_JDR1_JDATA_Pos) /*!< 0x00008000 */
+
+/******************** Bit definition for ADC_JDR2 register ******************/
+#define ADC_JDR2_JDATA_Pos (0U)
+#define ADC_JDR2_JDATA_Msk (0xFFFFU << ADC_JDR2_JDATA_Pos) /*!< 0x0000FFFF */
+#define ADC_JDR2_JDATA ADC_JDR2_JDATA_Msk /*!< ADC group injected sequencer rank 2 conversion data */
+#define ADC_JDR2_JDATA_0 (0x0001U << ADC_JDR2_JDATA_Pos) /*!< 0x00000001 */
+#define ADC_JDR2_JDATA_1 (0x0002U << ADC_JDR2_JDATA_Pos) /*!< 0x00000002 */
+#define ADC_JDR2_JDATA_2 (0x0004U << ADC_JDR2_JDATA_Pos) /*!< 0x00000004 */
+#define ADC_JDR2_JDATA_3 (0x0008U << ADC_JDR2_JDATA_Pos) /*!< 0x00000008 */
+#define ADC_JDR2_JDATA_4 (0x0010U << ADC_JDR2_JDATA_Pos) /*!< 0x00000010 */
+#define ADC_JDR2_JDATA_5 (0x0020U << ADC_JDR2_JDATA_Pos) /*!< 0x00000020 */
+#define ADC_JDR2_JDATA_6 (0x0040U << ADC_JDR2_JDATA_Pos) /*!< 0x00000040 */
+#define ADC_JDR2_JDATA_7 (0x0080U << ADC_JDR2_JDATA_Pos) /*!< 0x00000080 */
+#define ADC_JDR2_JDATA_8 (0x0100U << ADC_JDR2_JDATA_Pos) /*!< 0x00000100 */
+#define ADC_JDR2_JDATA_9 (0x0200U << ADC_JDR2_JDATA_Pos) /*!< 0x00000200 */
+#define ADC_JDR2_JDATA_10 (0x0400U << ADC_JDR2_JDATA_Pos) /*!< 0x00000400 */
+#define ADC_JDR2_JDATA_11 (0x0800U << ADC_JDR2_JDATA_Pos) /*!< 0x00000800 */
+#define ADC_JDR2_JDATA_12 (0x1000U << ADC_JDR2_JDATA_Pos) /*!< 0x00001000 */
+#define ADC_JDR2_JDATA_13 (0x2000U << ADC_JDR2_JDATA_Pos) /*!< 0x00002000 */
+#define ADC_JDR2_JDATA_14 (0x4000U << ADC_JDR2_JDATA_Pos) /*!< 0x00004000 */
+#define ADC_JDR2_JDATA_15 (0x8000U << ADC_JDR2_JDATA_Pos) /*!< 0x00008000 */
+
+/******************** Bit definition for ADC_JDR3 register ******************/
+#define ADC_JDR3_JDATA_Pos (0U)
+#define ADC_JDR3_JDATA_Msk (0xFFFFU << ADC_JDR3_JDATA_Pos) /*!< 0x0000FFFF */
+#define ADC_JDR3_JDATA ADC_JDR3_JDATA_Msk /*!< ADC group injected sequencer rank 3 conversion data */
+#define ADC_JDR3_JDATA_0 (0x0001U << ADC_JDR3_JDATA_Pos) /*!< 0x00000001 */
+#define ADC_JDR3_JDATA_1 (0x0002U << ADC_JDR3_JDATA_Pos) /*!< 0x00000002 */
+#define ADC_JDR3_JDATA_2 (0x0004U << ADC_JDR3_JDATA_Pos) /*!< 0x00000004 */
+#define ADC_JDR3_JDATA_3 (0x0008U << ADC_JDR3_JDATA_Pos) /*!< 0x00000008 */
+#define ADC_JDR3_JDATA_4 (0x0010U << ADC_JDR3_JDATA_Pos) /*!< 0x00000010 */
+#define ADC_JDR3_JDATA_5 (0x0020U << ADC_JDR3_JDATA_Pos) /*!< 0x00000020 */
+#define ADC_JDR3_JDATA_6 (0x0040U << ADC_JDR3_JDATA_Pos) /*!< 0x00000040 */
+#define ADC_JDR3_JDATA_7 (0x0080U << ADC_JDR3_JDATA_Pos) /*!< 0x00000080 */
+#define ADC_JDR3_JDATA_8 (0x0100U << ADC_JDR3_JDATA_Pos) /*!< 0x00000100 */
+#define ADC_JDR3_JDATA_9 (0x0200U << ADC_JDR3_JDATA_Pos) /*!< 0x00000200 */
+#define ADC_JDR3_JDATA_10 (0x0400U << ADC_JDR3_JDATA_Pos) /*!< 0x00000400 */
+#define ADC_JDR3_JDATA_11 (0x0800U << ADC_JDR3_JDATA_Pos) /*!< 0x00000800 */
+#define ADC_JDR3_JDATA_12 (0x1000U << ADC_JDR3_JDATA_Pos) /*!< 0x00001000 */
+#define ADC_JDR3_JDATA_13 (0x2000U << ADC_JDR3_JDATA_Pos) /*!< 0x00002000 */
+#define ADC_JDR3_JDATA_14 (0x4000U << ADC_JDR3_JDATA_Pos) /*!< 0x00004000 */
+#define ADC_JDR3_JDATA_15 (0x8000U << ADC_JDR3_JDATA_Pos) /*!< 0x00008000 */
+
+/******************** Bit definition for ADC_JDR4 register ******************/
+#define ADC_JDR4_JDATA_Pos (0U)
+#define ADC_JDR4_JDATA_Msk (0xFFFFU << ADC_JDR4_JDATA_Pos) /*!< 0x0000FFFF */
+#define ADC_JDR4_JDATA ADC_JDR4_JDATA_Msk /*!< ADC group injected sequencer rank 4 conversion data */
+#define ADC_JDR4_JDATA_0 (0x0001U << ADC_JDR4_JDATA_Pos) /*!< 0x00000001 */
+#define ADC_JDR4_JDATA_1 (0x0002U << ADC_JDR4_JDATA_Pos) /*!< 0x00000002 */
+#define ADC_JDR4_JDATA_2 (0x0004U << ADC_JDR4_JDATA_Pos) /*!< 0x00000004 */
+#define ADC_JDR4_JDATA_3 (0x0008U << ADC_JDR4_JDATA_Pos) /*!< 0x00000008 */
+#define ADC_JDR4_JDATA_4 (0x0010U << ADC_JDR4_JDATA_Pos) /*!< 0x00000010 */
+#define ADC_JDR4_JDATA_5 (0x0020U << ADC_JDR4_JDATA_Pos) /*!< 0x00000020 */
+#define ADC_JDR4_JDATA_6 (0x0040U << ADC_JDR4_JDATA_Pos) /*!< 0x00000040 */
+#define ADC_JDR4_JDATA_7 (0x0080U << ADC_JDR4_JDATA_Pos) /*!< 0x00000080 */
+#define ADC_JDR4_JDATA_8 (0x0100U << ADC_JDR4_JDATA_Pos) /*!< 0x00000100 */
+#define ADC_JDR4_JDATA_9 (0x0200U << ADC_JDR4_JDATA_Pos) /*!< 0x00000200 */
+#define ADC_JDR4_JDATA_10 (0x0400U << ADC_JDR4_JDATA_Pos) /*!< 0x00000400 */
+#define ADC_JDR4_JDATA_11 (0x0800U << ADC_JDR4_JDATA_Pos) /*!< 0x00000800 */
+#define ADC_JDR4_JDATA_12 (0x1000U << ADC_JDR4_JDATA_Pos) /*!< 0x00001000 */
+#define ADC_JDR4_JDATA_13 (0x2000U << ADC_JDR4_JDATA_Pos) /*!< 0x00002000 */
+#define ADC_JDR4_JDATA_14 (0x4000U << ADC_JDR4_JDATA_Pos) /*!< 0x00004000 */
+#define ADC_JDR4_JDATA_15 (0x8000U << ADC_JDR4_JDATA_Pos) /*!< 0x00008000 */
+
+/******************** Bit definition for ADC_AWD2CR register ****************/
+#define ADC_AWD2CR_AWD2CH_Pos (0U)
+#define ADC_AWD2CR_AWD2CH_Msk (0x7FFFFU << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x0007FFFF */
+#define ADC_AWD2CR_AWD2CH ADC_AWD2CR_AWD2CH_Msk /*!< ADC analog watchdog 2 monitored channel selection */
+#define ADC_AWD2CR_AWD2CH_0 (0x00001U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000001 */
+#define ADC_AWD2CR_AWD2CH_1 (0x00002U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000002 */
+#define ADC_AWD2CR_AWD2CH_2 (0x00004U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000004 */
+#define ADC_AWD2CR_AWD2CH_3 (0x00008U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000008 */
+#define ADC_AWD2CR_AWD2CH_4 (0x00010U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000010 */
+#define ADC_AWD2CR_AWD2CH_5 (0x00020U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000020 */
+#define ADC_AWD2CR_AWD2CH_6 (0x00040U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000040 */
+#define ADC_AWD2CR_AWD2CH_7 (0x00080U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000080 */
+#define ADC_AWD2CR_AWD2CH_8 (0x00100U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000100 */
+#define ADC_AWD2CR_AWD2CH_9 (0x00200U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000200 */
+#define ADC_AWD2CR_AWD2CH_10 (0x00400U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000400 */
+#define ADC_AWD2CR_AWD2CH_11 (0x00800U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000800 */
+#define ADC_AWD2CR_AWD2CH_12 (0x01000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00001000 */
+#define ADC_AWD2CR_AWD2CH_13 (0x02000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00002000 */
+#define ADC_AWD2CR_AWD2CH_14 (0x04000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00004000 */
+#define ADC_AWD2CR_AWD2CH_15 (0x08000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00008000 */
+#define ADC_AWD2CR_AWD2CH_16 (0x10000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00010000 */
+#define ADC_AWD2CR_AWD2CH_17 (0x20000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00020000 */
+#define ADC_AWD2CR_AWD2CH_18 (0x40000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00040000 */
+
+/******************** Bit definition for ADC_AWD3CR register ****************/
+#define ADC_AWD3CR_AWD3CH_Pos (0U)
+#define ADC_AWD3CR_AWD3CH_Msk (0x7FFFFU << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x0007FFFF */
+#define ADC_AWD3CR_AWD3CH ADC_AWD3CR_AWD3CH_Msk /*!< ADC analog watchdog 3 monitored channel selection */
+#define ADC_AWD3CR_AWD3CH_0 (0x00001U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000001 */
+#define ADC_AWD3CR_AWD3CH_1 (0x00002U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000002 */
+#define ADC_AWD3CR_AWD3CH_2 (0x00004U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000004 */
+#define ADC_AWD3CR_AWD3CH_3 (0x00008U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000008 */
+#define ADC_AWD3CR_AWD3CH_4 (0x00010U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000010 */
+#define ADC_AWD3CR_AWD3CH_5 (0x00020U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000020 */
+#define ADC_AWD3CR_AWD3CH_6 (0x00040U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000040 */
+#define ADC_AWD3CR_AWD3CH_7 (0x00080U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000080 */
+#define ADC_AWD3CR_AWD3CH_8 (0x00100U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000100 */
+#define ADC_AWD3CR_AWD3CH_9 (0x00200U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000200 */
+#define ADC_AWD3CR_AWD3CH_10 (0x00400U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000400 */
+#define ADC_AWD3CR_AWD3CH_11 (0x00800U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000800 */
+#define ADC_AWD3CR_AWD3CH_12 (0x01000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00001000 */
+#define ADC_AWD3CR_AWD3CH_13 (0x02000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00002000 */
+#define ADC_AWD3CR_AWD3CH_14 (0x04000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00004000 */
+#define ADC_AWD3CR_AWD3CH_15 (0x08000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00008000 */
+#define ADC_AWD3CR_AWD3CH_16 (0x10000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00010000 */
+#define ADC_AWD3CR_AWD3CH_17 (0x20000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00020000 */
+#define ADC_AWD3CR_AWD3CH_18 (0x40000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00040000 */
+
+/******************** Bit definition for ADC_DIFSEL register ****************/
+#define ADC_DIFSEL_DIFSEL_Pos (0U)
+#define ADC_DIFSEL_DIFSEL_Msk (0x7FFFFU << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x0007FFFF */
+#define ADC_DIFSEL_DIFSEL ADC_DIFSEL_DIFSEL_Msk /*!< ADC channel differential or single-ended mode */
+#define ADC_DIFSEL_DIFSEL_0 (0x00001U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000001 */
+#define ADC_DIFSEL_DIFSEL_1 (0x00002U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000002 */
+#define ADC_DIFSEL_DIFSEL_2 (0x00004U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000004 */
+#define ADC_DIFSEL_DIFSEL_3 (0x00008U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000008 */
+#define ADC_DIFSEL_DIFSEL_4 (0x00010U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000010 */
+#define ADC_DIFSEL_DIFSEL_5 (0x00020U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000020 */
+#define ADC_DIFSEL_DIFSEL_6 (0x00040U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000040 */
+#define ADC_DIFSEL_DIFSEL_7 (0x00080U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000080 */
+#define ADC_DIFSEL_DIFSEL_8 (0x00100U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000100 */
+#define ADC_DIFSEL_DIFSEL_9 (0x00200U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000200 */
+#define ADC_DIFSEL_DIFSEL_10 (0x00400U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000400 */
+#define ADC_DIFSEL_DIFSEL_11 (0x00800U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000800 */
+#define ADC_DIFSEL_DIFSEL_12 (0x01000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00001000 */
+#define ADC_DIFSEL_DIFSEL_13 (0x02000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00002000 */
+#define ADC_DIFSEL_DIFSEL_14 (0x04000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00004000 */
+#define ADC_DIFSEL_DIFSEL_15 (0x08000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00008000 */
+#define ADC_DIFSEL_DIFSEL_16 (0x10000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00010000 */
+#define ADC_DIFSEL_DIFSEL_17 (0x20000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00020000 */
+#define ADC_DIFSEL_DIFSEL_18 (0x40000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00040000 */
+
+/******************** Bit definition for ADC_CALFACT register ***************/
+#define ADC_CALFACT_CALFACT_S_Pos (0U)
+#define ADC_CALFACT_CALFACT_S_Msk (0x7FU << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x0000007F */
+#define ADC_CALFACT_CALFACT_S ADC_CALFACT_CALFACT_S_Msk /*!< ADC calibration factor in single-ended mode */
+#define ADC_CALFACT_CALFACT_S_0 (0x01U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000001 */
+#define ADC_CALFACT_CALFACT_S_1 (0x02U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000002 */
+#define ADC_CALFACT_CALFACT_S_2 (0x04U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000004 */
+#define ADC_CALFACT_CALFACT_S_3 (0x08U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000008 */
+#define ADC_CALFACT_CALFACT_S_4 (0x10U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000010 */
+#define ADC_CALFACT_CALFACT_S_5 (0x20U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000020 */
+#define ADC_CALFACT_CALFACT_S_6 (0x40U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000040 */
+
+#define ADC_CALFACT_CALFACT_D_Pos (16U)
+#define ADC_CALFACT_CALFACT_D_Msk (0x7FU << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x007F0000 */
+#define ADC_CALFACT_CALFACT_D ADC_CALFACT_CALFACT_D_Msk /*!< ADC calibration factor in differential mode */
+#define ADC_CALFACT_CALFACT_D_0 (0x01U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00010000 */
+#define ADC_CALFACT_CALFACT_D_1 (0x02U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00020000 */
+#define ADC_CALFACT_CALFACT_D_2 (0x04U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00040000 */
+#define ADC_CALFACT_CALFACT_D_3 (0x08U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00080000 */
+#define ADC_CALFACT_CALFACT_D_4 (0x10U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00100000 */
+#define ADC_CALFACT_CALFACT_D_5 (0x20U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00200000 */
+#define ADC_CALFACT_CALFACT_D_6 (0x40U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00400000 */
+
+/************************* ADC Common registers *****************************/
+/******************** Bit definition for ADC_CSR register *******************/
+#define ADC_CSR_ADRDY_MST_Pos (0U)
+#define ADC_CSR_ADRDY_MST_Msk (0x1U << ADC_CSR_ADRDY_MST_Pos) /*!< 0x00000001 */
+#define ADC_CSR_ADRDY_MST ADC_CSR_ADRDY_MST_Msk /*!< ADC multimode master ready flag */
+#define ADC_CSR_EOSMP_MST_Pos (1U)
+#define ADC_CSR_EOSMP_MST_Msk (0x1U << ADC_CSR_EOSMP_MST_Pos) /*!< 0x00000002 */
+#define ADC_CSR_EOSMP_MST ADC_CSR_EOSMP_MST_Msk /*!< ADC multimode master group regular end of sampling flag */
+#define ADC_CSR_EOC_MST_Pos (2U)
+#define ADC_CSR_EOC_MST_Msk (0x1U << ADC_CSR_EOC_MST_Pos) /*!< 0x00000004 */
+#define ADC_CSR_EOC_MST ADC_CSR_EOC_MST_Msk /*!< ADC multimode master group regular end of unitary conversion flag */
+#define ADC_CSR_EOS_MST_Pos (3U)
+#define ADC_CSR_EOS_MST_Msk (0x1U << ADC_CSR_EOS_MST_Pos) /*!< 0x00000008 */
+#define ADC_CSR_EOS_MST ADC_CSR_EOS_MST_Msk /*!< ADC multimode master group regular end of sequence conversions flag */
+#define ADC_CSR_OVR_MST_Pos (4U)
+#define ADC_CSR_OVR_MST_Msk (0x1U << ADC_CSR_OVR_MST_Pos) /*!< 0x00000010 */
+#define ADC_CSR_OVR_MST ADC_CSR_OVR_MST_Msk /*!< ADC multimode master group regular overrun flag */
+#define ADC_CSR_JEOC_MST_Pos (5U)
+#define ADC_CSR_JEOC_MST_Msk (0x1U << ADC_CSR_JEOC_MST_Pos) /*!< 0x00000020 */
+#define ADC_CSR_JEOC_MST ADC_CSR_JEOC_MST_Msk /*!< ADC multimode master group injected end of unitary conversion flag */
+#define ADC_CSR_JEOS_MST_Pos (6U)
+#define ADC_CSR_JEOS_MST_Msk (0x1U << ADC_CSR_JEOS_MST_Pos) /*!< 0x00000040 */
+#define ADC_CSR_JEOS_MST ADC_CSR_JEOS_MST_Msk /*!< ADC multimode master group injected end of sequence conversions flag */
+#define ADC_CSR_AWD1_MST_Pos (7U)
+#define ADC_CSR_AWD1_MST_Msk (0x1U << ADC_CSR_AWD1_MST_Pos) /*!< 0x00000080 */
+#define ADC_CSR_AWD1_MST ADC_CSR_AWD1_MST_Msk /*!< ADC multimode master analog watchdog 1 flag */
+#define ADC_CSR_AWD2_MST_Pos (8U)
+#define ADC_CSR_AWD2_MST_Msk (0x1U << ADC_CSR_AWD2_MST_Pos) /*!< 0x00000100 */
+#define ADC_CSR_AWD2_MST ADC_CSR_AWD2_MST_Msk /*!< ADC multimode master analog watchdog 2 flag */
+#define ADC_CSR_AWD3_MST_Pos (9U)
+#define ADC_CSR_AWD3_MST_Msk (0x1U << ADC_CSR_AWD3_MST_Pos) /*!< 0x00000200 */
+#define ADC_CSR_AWD3_MST ADC_CSR_AWD3_MST_Msk /*!< ADC multimode master analog watchdog 3 flag */
+#define ADC_CSR_JQOVF_MST_Pos (10U)
+#define ADC_CSR_JQOVF_MST_Msk (0x1U << ADC_CSR_JQOVF_MST_Pos) /*!< 0x00000400 */
+#define ADC_CSR_JQOVF_MST ADC_CSR_JQOVF_MST_Msk /*!< ADC multimode master group injected contexts queue overflow flag */
+
+#define ADC_CSR_ADRDY_SLV_Pos (16U)
+#define ADC_CSR_ADRDY_SLV_Msk (0x1U << ADC_CSR_ADRDY_SLV_Pos) /*!< 0x00010000 */
+#define ADC_CSR_ADRDY_SLV ADC_CSR_ADRDY_SLV_Msk /*!< ADC multimode slave ready flag */
+#define ADC_CSR_EOSMP_SLV_Pos (17U)
+#define ADC_CSR_EOSMP_SLV_Msk (0x1U << ADC_CSR_EOSMP_SLV_Pos) /*!< 0x00020000 */
+#define ADC_CSR_EOSMP_SLV ADC_CSR_EOSMP_SLV_Msk /*!< ADC multimode slave group regular end of sampling flag */
+#define ADC_CSR_EOC_SLV_Pos (18U)
+#define ADC_CSR_EOC_SLV_Msk (0x1U << ADC_CSR_EOC_SLV_Pos) /*!< 0x00040000 */
+#define ADC_CSR_EOC_SLV ADC_CSR_EOC_SLV_Msk /*!< ADC multimode slave group regular end of unitary conversion flag */
+#define ADC_CSR_EOS_SLV_Pos (19U)
+#define ADC_CSR_EOS_SLV_Msk (0x1U << ADC_CSR_EOS_SLV_Pos) /*!< 0x00080000 */
+#define ADC_CSR_EOS_SLV ADC_CSR_EOS_SLV_Msk /*!< ADC multimode slave group regular end of sequence conversions flag */
+#define ADC_CSR_OVR_SLV_Pos (20U)
+#define ADC_CSR_OVR_SLV_Msk (0x1U << ADC_CSR_OVR_SLV_Pos) /*!< 0x00100000 */
+#define ADC_CSR_OVR_SLV ADC_CSR_OVR_SLV_Msk /*!< ADC multimode slave group regular overrun flag */
+#define ADC_CSR_JEOC_SLV_Pos (21U)
+#define ADC_CSR_JEOC_SLV_Msk (0x1U << ADC_CSR_JEOC_SLV_Pos) /*!< 0x00200000 */
+#define ADC_CSR_JEOC_SLV ADC_CSR_JEOC_SLV_Msk /*!< ADC multimode slave group injected end of unitary conversion flag */
+#define ADC_CSR_JEOS_SLV_Pos (22U)
+#define ADC_CSR_JEOS_SLV_Msk (0x1U << ADC_CSR_JEOS_SLV_Pos) /*!< 0x00400000 */
+#define ADC_CSR_JEOS_SLV ADC_CSR_JEOS_SLV_Msk /*!< ADC multimode slave group injected end of sequence conversions flag */
+#define ADC_CSR_AWD1_SLV_Pos (23U)
+#define ADC_CSR_AWD1_SLV_Msk (0x1U << ADC_CSR_AWD1_SLV_Pos) /*!< 0x00800000 */
+#define ADC_CSR_AWD1_SLV ADC_CSR_AWD1_SLV_Msk /*!< ADC multimode slave analog watchdog 1 flag */
+#define ADC_CSR_AWD2_SLV_Pos (24U)
+#define ADC_CSR_AWD2_SLV_Msk (0x1U << ADC_CSR_AWD2_SLV_Pos) /*!< 0x01000000 */
+#define ADC_CSR_AWD2_SLV ADC_CSR_AWD2_SLV_Msk /*!< ADC multimode slave analog watchdog 2 flag */
+#define ADC_CSR_AWD3_SLV_Pos (25U)
+#define ADC_CSR_AWD3_SLV_Msk (0x1U << ADC_CSR_AWD3_SLV_Pos) /*!< 0x02000000 */
+#define ADC_CSR_AWD3_SLV ADC_CSR_AWD3_SLV_Msk /*!< ADC multimode slave analog watchdog 3 flag */
+#define ADC_CSR_JQOVF_SLV_Pos (26U)
+#define ADC_CSR_JQOVF_SLV_Msk (0x1U << ADC_CSR_JQOVF_SLV_Pos) /*!< 0x04000000 */
+#define ADC_CSR_JQOVF_SLV ADC_CSR_JQOVF_SLV_Msk /*!< ADC multimode slave group injected contexts queue overflow flag */
+
+/******************** Bit definition for ADC_CCR register *******************/
+#define ADC_CCR_DUAL_Pos (0U)
+#define ADC_CCR_DUAL_Msk (0x1FU << ADC_CCR_DUAL_Pos) /*!< 0x0000001F */
+#define ADC_CCR_DUAL ADC_CCR_DUAL_Msk /*!< ADC multimode mode selection */
+#define ADC_CCR_DUAL_0 (0x01U << ADC_CCR_DUAL_Pos) /*!< 0x00000001 */
+#define ADC_CCR_DUAL_1 (0x02U << ADC_CCR_DUAL_Pos) /*!< 0x00000002 */
+#define ADC_CCR_DUAL_2 (0x04U << ADC_CCR_DUAL_Pos) /*!< 0x00000004 */
+#define ADC_CCR_DUAL_3 (0x08U << ADC_CCR_DUAL_Pos) /*!< 0x00000008 */
+#define ADC_CCR_DUAL_4 (0x10U << ADC_CCR_DUAL_Pos) /*!< 0x00000010 */
+
+#define ADC_CCR_DELAY_Pos (8U)
+#define ADC_CCR_DELAY_Msk (0xFU << ADC_CCR_DELAY_Pos) /*!< 0x00000F00 */
+#define ADC_CCR_DELAY ADC_CCR_DELAY_Msk /*!< ADC multimode delay between 2 sampling phases */
+#define ADC_CCR_DELAY_0 (0x1U << ADC_CCR_DELAY_Pos) /*!< 0x00000100 */
+#define ADC_CCR_DELAY_1 (0x2U << ADC_CCR_DELAY_Pos) /*!< 0x00000200 */
+#define ADC_CCR_DELAY_2 (0x4U << ADC_CCR_DELAY_Pos) /*!< 0x00000400 */
+#define ADC_CCR_DELAY_3 (0x8U << ADC_CCR_DELAY_Pos) /*!< 0x00000800 */
+
+#define ADC_CCR_DMACFG_Pos (13U)
+#define ADC_CCR_DMACFG_Msk (0x1U << ADC_CCR_DMACFG_Pos) /*!< 0x00002000 */
+#define ADC_CCR_DMACFG ADC_CCR_DMACFG_Msk /*!< ADC multimode DMA transfer configuration */
+
+#define ADC_CCR_MDMA_Pos (14U)
+#define ADC_CCR_MDMA_Msk (0x3U << ADC_CCR_MDMA_Pos) /*!< 0x0000C000 */
+#define ADC_CCR_MDMA ADC_CCR_MDMA_Msk /*!< ADC multimode DMA transfer enable */
+#define ADC_CCR_MDMA_0 (0x1U << ADC_CCR_MDMA_Pos) /*!< 0x00004000 */
+#define ADC_CCR_MDMA_1 (0x2U << ADC_CCR_MDMA_Pos) /*!< 0x00008000 */
+
+#define ADC_CCR_CKMODE_Pos (16U)
+#define ADC_CCR_CKMODE_Msk (0x3U << ADC_CCR_CKMODE_Pos) /*!< 0x00030000 */
+#define ADC_CCR_CKMODE ADC_CCR_CKMODE_Msk /*!< ADC common clock source and prescaler (prescaler only for clock source synchronous) */
+#define ADC_CCR_CKMODE_0 (0x1U << ADC_CCR_CKMODE_Pos) /*!< 0x00010000 */
+#define ADC_CCR_CKMODE_1 (0x2U << ADC_CCR_CKMODE_Pos) /*!< 0x00020000 */
+
+#define ADC_CCR_PRESC_Pos (18U)
+#define ADC_CCR_PRESC_Msk (0xFU << ADC_CCR_PRESC_Pos) /*!< 0x003C0000 */
+#define ADC_CCR_PRESC ADC_CCR_PRESC_Msk /*!< ADC common clock prescaler, only for clock source asynchronous */
+#define ADC_CCR_PRESC_0 (0x1U << ADC_CCR_PRESC_Pos) /*!< 0x00040000 */
+#define ADC_CCR_PRESC_1 (0x2U << ADC_CCR_PRESC_Pos) /*!< 0x00080000 */
+#define ADC_CCR_PRESC_2 (0x4U << ADC_CCR_PRESC_Pos) /*!< 0x00100000 */
+#define ADC_CCR_PRESC_3 (0x8U << ADC_CCR_PRESC_Pos) /*!< 0x00200000 */
+
+#define ADC_CCR_VREFEN_Pos (22U)
+#define ADC_CCR_VREFEN_Msk (0x1U << ADC_CCR_VREFEN_Pos) /*!< 0x00400000 */
+#define ADC_CCR_VREFEN ADC_CCR_VREFEN_Msk /*!< ADC internal path to VrefInt enable */
+#define ADC_CCR_TSEN_Pos (23U)
+#define ADC_CCR_TSEN_Msk (0x1U << ADC_CCR_TSEN_Pos) /*!< 0x00800000 */
+#define ADC_CCR_TSEN ADC_CCR_TSEN_Msk /*!< ADC internal path to temperature sensor enable */
+#define ADC_CCR_VBATEN_Pos (24U)
+#define ADC_CCR_VBATEN_Msk (0x1U << ADC_CCR_VBATEN_Pos) /*!< 0x01000000 */
+#define ADC_CCR_VBATEN ADC_CCR_VBATEN_Msk /*!< ADC internal path to battery voltage enable */
+
+/******************** Bit definition for ADC_CDR register *******************/
+#define ADC_CDR_RDATA_MST_Pos (0U)
+#define ADC_CDR_RDATA_MST_Msk (0xFFFFU << ADC_CDR_RDATA_MST_Pos) /*!< 0x0000FFFF */
+#define ADC_CDR_RDATA_MST ADC_CDR_RDATA_MST_Msk /*!< ADC multimode master group regular conversion data */
+#define ADC_CDR_RDATA_MST_0 (0x0001U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000001 */
+#define ADC_CDR_RDATA_MST_1 (0x0002U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000002 */
+#define ADC_CDR_RDATA_MST_2 (0x0004U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000004 */
+#define ADC_CDR_RDATA_MST_3 (0x0008U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000008 */
+#define ADC_CDR_RDATA_MST_4 (0x0010U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000010 */
+#define ADC_CDR_RDATA_MST_5 (0x0020U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000020 */
+#define ADC_CDR_RDATA_MST_6 (0x0040U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000040 */
+#define ADC_CDR_RDATA_MST_7 (0x0080U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000080 */
+#define ADC_CDR_RDATA_MST_8 (0x0100U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000100 */
+#define ADC_CDR_RDATA_MST_9 (0x0200U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000200 */
+#define ADC_CDR_RDATA_MST_10 (0x0400U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000400 */
+#define ADC_CDR_RDATA_MST_11 (0x0800U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000800 */
+#define ADC_CDR_RDATA_MST_12 (0x1000U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00001000 */
+#define ADC_CDR_RDATA_MST_13 (0x2000U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00002000 */
+#define ADC_CDR_RDATA_MST_14 (0x4000U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00004000 */
+#define ADC_CDR_RDATA_MST_15 (0x8000U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00008000 */
+
+#define ADC_CDR_RDATA_SLV_Pos (16U)
+#define ADC_CDR_RDATA_SLV_Msk (0xFFFFU << ADC_CDR_RDATA_SLV_Pos) /*!< 0xFFFF0000 */
+#define ADC_CDR_RDATA_SLV ADC_CDR_RDATA_SLV_Msk /*!< ADC multimode slave group regular conversion data */
+#define ADC_CDR_RDATA_SLV_0 (0x0001U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00010000 */
+#define ADC_CDR_RDATA_SLV_1 (0x0002U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00020000 */
+#define ADC_CDR_RDATA_SLV_2 (0x0004U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00040000 */
+#define ADC_CDR_RDATA_SLV_3 (0x0008U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00080000 */
+#define ADC_CDR_RDATA_SLV_4 (0x0010U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00100000 */
+#define ADC_CDR_RDATA_SLV_5 (0x0020U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00200000 */
+#define ADC_CDR_RDATA_SLV_6 (0x0040U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00400000 */
+#define ADC_CDR_RDATA_SLV_7 (0x0080U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00800000 */
+#define ADC_CDR_RDATA_SLV_8 (0x0100U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x01000000 */
+#define ADC_CDR_RDATA_SLV_9 (0x0200U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x02000000 */
+#define ADC_CDR_RDATA_SLV_10 (0x0400U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x04000000 */
+#define ADC_CDR_RDATA_SLV_11 (0x0800U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x08000000 */
+#define ADC_CDR_RDATA_SLV_12 (0x1000U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x10000000 */
+#define ADC_CDR_RDATA_SLV_13 (0x2000U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x20000000 */
+#define ADC_CDR_RDATA_SLV_14 (0x4000U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x40000000 */
+#define ADC_CDR_RDATA_SLV_15 (0x8000U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x80000000 */
+
+/******************************************************************************/
+/* */
+/* Controller Area Network */
+/* */
+/******************************************************************************/
+/*!*/
+#define DAC_CR_CEN1_Pos (14U)
+#define DAC_CR_CEN1_Msk (0x1U << DAC_CR_CEN1_Pos) /*!< 0x00004000 */
+#define DAC_CR_CEN1 DAC_CR_CEN1_Msk /*!*/
+
+#define DAC_CR_EN2_Pos (16U)
+#define DAC_CR_EN2_Msk (0x1U << DAC_CR_EN2_Pos) /*!< 0x00010000 */
+#define DAC_CR_EN2 DAC_CR_EN2_Msk /*!*/
+#define DAC_CR_CEN2_Pos (30U)
+#define DAC_CR_CEN2_Msk (0x1U << DAC_CR_CEN2_Pos) /*!< 0x40000000 */
+#define DAC_CR_CEN2 DAC_CR_CEN2_Msk /*!*/
+
+/***************** Bit definition for DAC_SWTRIGR register ******************/
+#define DAC_SWTRIGR_SWTRIG1_Pos (0U)
+#define DAC_SWTRIGR_SWTRIG1_Msk (0x1U << DAC_SWTRIGR_SWTRIG1_Pos) /*!< 0x00000001 */
+#define DAC_SWTRIGR_SWTRIG1 DAC_SWTRIGR_SWTRIG1_Msk /*!© COPYRIGHT(c) 2017 STMicroelectronics
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/** @addtogroup CMSIS
+ * @{
+ */
+
+/** @addtogroup stm32l4xx
+ * @{
+ */
+
+#ifndef __STM32L4xx_H
+#define __STM32L4xx_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif /* __cplusplus */
+
+/** @addtogroup Library_configuration_section
+ * @{
+ */
+
+/**
+ * @brief STM32 Family
+ */
+#if !defined (STM32L4)
+#define STM32L4
+#endif /* STM32L4 */
+
+/* Uncomment the line below according to the target STM32L4 device used in your
+ application
+ */
+
+#if !defined (STM32L431xx) && !defined (STM32L432xx) && !defined (STM32L433xx) && !defined (STM32L442xx) && !defined (STM32L443xx) && \
+ !defined (STM32L451xx) && !defined (STM32L452xx) && !defined (STM32L462xx) && \
+ !defined (STM32L471xx) && !defined (STM32L475xx) && !defined (STM32L476xx) && !defined (STM32L485xx) && !defined (STM32L486xx) && \
+ !defined (STM32L496xx) && !defined (STM32L4A6xx) && \
+ !defined (STM32L4R5xx) && !defined (STM32L4R7xx) && !defined (STM32L4R9xx) && !defined (STM32L4S5xx) && !defined (STM32L4S7xx) && !defined (STM32L4S9xx)
+ /* #define STM32L431xx */ /*!< STM32L431xx Devices */
+ /* #define STM32L432xx */ /*!< STM32L432xx Devices */
+ /* #define STM32L433xx */ /*!< STM32L433xx Devices */
+ /* #define STM32L442xx */ /*!< STM32L442xx Devices */
+ /* #define STM32L443xx */ /*!< STM32L443xx Devices */
+ /* #define STM32L451xx */ /*!< STM32L451xx Devices */
+ /* #define STM32L452xx */ /*!< STM32L452xx Devices */
+ /* #define STM32L462xx */ /*!< STM32L462xx Devices */
+ /* #define STM32L471xx */ /*!< STM32L471xx Devices */
+ /* #define STM32L475xx */ /*!< STM32L475xx Devices */
+ /* #define STM32L476xx */ /*!< STM32L476xx Devices */
+ /* #define STM32L485xx */ /*!< STM32L485xx Devices */
+ /* #define STM32L486xx */ /*!< STM32L486xx Devices */
+ /* #define STM32L496xx */ /*!< STM32L496xx Devices */
+ /* #define STM32L4A6xx */ /*!< STM32L4A6xx Devices */
+ /* #define STM32L4R5xx */ /*!< STM32L4R5xx Devices */
+ /* #define STM32L4R7xx */ /*!< STM32L4R7xx Devices */
+ /* #define STM32L4R9xx */ /*!< STM32L4R9xx Devices */
+ /* #define STM32L4S5xx */ /*!< STM32L4S5xx Devices */
+ /* #define STM32L4S7xx */ /*!< STM32L4S7xx Devices */
+ /* #define STM32L4S9xx */ /*!< STM32L4S9xx Devices */
+#endif
+
+/* Tip: To avoid modifying this file each time you need to switch between these
+ devices, you can define the device in your toolchain compiler preprocessor.
+ */
+#if !defined (USE_HAL_DRIVER)
+/**
+ * @brief Comment the line below if you will not use the peripherals drivers.
+ In this case, these drivers will not be included and the application code will
+ be based on direct access to peripherals registers
+ */
+ /*#define USE_HAL_DRIVER */
+#endif /* USE_HAL_DRIVER */
+
+/**
+ * @brief CMSIS Device version number
+ */
+#define __STM32L4_CMSIS_VERSION_MAIN (0x01) /*!< [31:24] main version */
+#define __STM32L4_CMSIS_VERSION_SUB1 (0x04) /*!< [23:16] sub1 version */
+#define __STM32L4_CMSIS_VERSION_SUB2 (0x02) /*!< [15:8] sub2 version */
+#define __STM32L4_CMSIS_VERSION_RC (0x00) /*!< [7:0] release candidate */
+#define __STM32L4_CMSIS_VERSION ((__STM32L4_CMSIS_VERSION_MAIN << 24)\
+ |(__STM32L4_CMSIS_VERSION_SUB1 << 16)\
+ |(__STM32L4_CMSIS_VERSION_SUB2 << 8 )\
+ |(__STM32L4_CMSIS_VERSION_RC))
+
+/**
+ * @}
+ */
+
+/** @addtogroup Device_Included
+ * @{
+ */
+
+#if defined(STM32L431xx)
+ #include "stm32l431xx.h"
+#elif defined(STM32L432xx)
+ #include "stm32l432xx.h"
+#elif defined(STM32L433xx)
+ #include "stm32l433xx.h"
+#elif defined(STM32L442xx)
+ #include "stm32l442xx.h"
+#elif defined(STM32L443xx)
+ #include "stm32l443xx.h"
+#elif defined(STM32L451xx)
+ #include "stm32l451xx.h"
+#elif defined(STM32L452xx)
+ #include "stm32l452xx.h"
+#elif defined(STM32L462xx)
+ #include "stm32l462xx.h"
+#elif defined(STM32L471xx)
+ #include "stm32l471xx.h"
+#elif defined(STM32L475xx)
+ #include "stm32l475xx.h"
+#elif defined(STM32L476xx)
+ #include "stm32l476xx.h"
+#elif defined(STM32L485xx)
+ #include "stm32l485xx.h"
+#elif defined(STM32L486xx)
+ #include "stm32l486xx.h"
+#elif defined(STM32L496xx)
+ #include "stm32l496xx.h"
+#elif defined(STM32L4A6xx)
+ #include "stm32l4a6xx.h"
+#elif defined(STM32L4R5xx)
+ #include "stm32l4r5xx.h"
+#elif defined(STM32L4R7xx)
+ #include "stm32l4r7xx.h"
+#elif defined(STM32L4R9xx)
+ #include "stm32l4r9xx.h"
+#elif defined(STM32L4S5xx)
+ #include "stm32l4s5xx.h"
+#elif defined(STM32L4S7xx)
+ #include "stm32l4s7xx.h"
+#elif defined(STM32L4S9xx)
+ #include "stm32l4s9xx.h"
+#else
+ #error "Please select first the target STM32L4xx device used in your application (in stm32l4xx.h file)"
+#endif
+
+/**
+ * @}
+ */
+
+/** @addtogroup Exported_types
+ * @{
+ */
+typedef enum
+{
+ RESET = 0,
+ SET = !RESET
+} FlagStatus, ITStatus;
+
+typedef enum
+{
+ DISABLE = 0,
+ ENABLE = !DISABLE
+} FunctionalState;
+#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))
+
+typedef enum
+{
+ ERROR = 0,
+ SUCCESS = !ERROR
+} ErrorStatus;
+
+/**
+ * @}
+ */
+
+
+/** @addtogroup Exported_macros
+ * @{
+ */
+#define SET_BIT(REG, BIT) ((REG) |= (BIT))
+
+#define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT))
+
+#define READ_BIT(REG, BIT) ((REG) & (BIT))
+
+#define CLEAR_REG(REG) ((REG) = (0x0))
+
+#define WRITE_REG(REG, VAL) ((REG) = (VAL))
+
+#define READ_REG(REG) ((REG))
+
+#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))
+
+#define POSITION_VAL(VAL) (__CLZ(__RBIT(VAL)))
+
+
+/**
+ * @}
+ */
+
+#if defined (USE_HAL_DRIVER)
+ #include "stm32l4xx_hal.h"
+#endif /* USE_HAL_DRIVER */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __STM32L4xx_H */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ChibiOS_20.3.2/os/common/ext/ST/STM32L4xx/system_stm32l4xx.h b/ChibiOS_20.3.2/os/common/ext/ST/STM32L4xx/system_stm32l4xx.h
new file mode 100644
index 0000000..96826be
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/ST/STM32L4xx/system_stm32l4xx.h
@@ -0,0 +1,123 @@
+/**
+ ******************************************************************************
+ * @file system_stm32l4xx.h
+ * @author MCD Application Team
+ * @brief CMSIS Cortex-M4 Device System Source File for STM32L4xx devices.
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT(c) 2017 STMicroelectronics
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/** @addtogroup CMSIS
+ * @{
+ */
+
+/** @addtogroup stm32l4xx_system
+ * @{
+ */
+
+/**
+ * @brief Define to prevent recursive inclusion
+ */
+#ifndef __SYSTEM_STM32L4XX_H
+#define __SYSTEM_STM32L4XX_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/** @addtogroup STM32L4xx_System_Includes
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @addtogroup STM32L4xx_System_Exported_Variables
+ * @{
+ */
+ /* The SystemCoreClock variable is updated in three ways:
+ 1) by calling CMSIS function SystemCoreClockUpdate()
+ 2) by calling HAL API function HAL_RCC_GetSysClockFreq()
+ 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
+ Note: If you use this function to configure the system clock; then there
+ is no need to call the 2 first functions listed above, since SystemCoreClock
+ variable is updated automatically.
+ */
+extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
+
+extern const uint8_t AHBPrescTable[16]; /*!< AHB prescalers table values */
+extern const uint8_t APBPrescTable[8]; /*!< APB prescalers table values */
+extern const uint32_t MSIRangeTable[12]; /*!< MSI ranges table values */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32L4xx_System_Exported_Constants
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32L4xx_System_Exported_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32L4xx_System_Exported_Functions
+ * @{
+ */
+
+extern void SystemInit(void);
+extern void SystemCoreClockUpdate(void);
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__SYSTEM_STM32L4XX_H */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ChibiOS_20.3.2/os/common/ext/readme.txt b/ChibiOS_20.3.2/os/common/ext/readme.txt
new file mode 100644
index 0000000..38d5d44
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ext/readme.txt
@@ -0,0 +1,7 @@
+All the code contained under ./os/common/ext is not part of the ChibiOS
+project and supplied as-is without any additional warranty by ChibiOS.
+For ownership and copyright statements see the license details inside the
+code.
+
+Some modules may contain changes from the ChibiOS team in order to increase
+compatibility or usability with ChibiOS itself.
diff --git a/ChibiOS_20.3.2/os/common/portability/CW/ccportab.h b/ChibiOS_20.3.2/os/common/portability/CW/ccportab.h
new file mode 100644
index 0000000..f94f76a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/portability/CW/ccportab.h
@@ -0,0 +1,129 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file CW/ccportab.h
+ * @brief Compiler portability layer.
+ *
+ * @defgroup CC_PORTAB Compiler portability.
+ * @{
+ */
+
+#ifndef CCPORTAB_H
+#define CCPORTAB_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @name Compiler abstraction macros
+ * @{
+ */
+/**
+ * @brief Allocates a variable or function to a specific section.
+ * @note If the compiler does not support such a feature then this macro
+ * must not be defined or it could originate errors.
+ */
+#define CC_SECTION(s) __declspec (section s)
+
+/**
+ * @brief Marks a function or variable as a weak symbol.
+ * @note If the compiler does not support such a feature then this macro
+ * must not be defined or it could originate errors.
+ */
+//#define CC_WEAK __attribute__((weak))
+
+/**
+ * @brief Marks a function or variable as used.
+ * @details The compiler or linker shall not remove the marked function or
+ * variable regardless if it is referred or not in the code.
+ * @note If the compiler does not support such a feature then this macro
+ * must not be defined or it could originate errors.
+ */
+#define CC_USED __attribute__((used))
+
+/**
+ * @brief Enforces alignment of the variable or function declared afterward.
+ * @note If the compiler does not support such a feature then this macro
+ * must not be defined or it could originate errors.
+ */
+//#define CC_ALIGN(n) __attribute__((aligned(n)))
+
+/**
+ * @brief Enforces packing of the structure declared afterward.
+ * @note If the compiler does not support such a feature then this macro
+ * must not be defined or it could originate errors.
+ */
+//#define CC_PACK __attribute__((packed))
+
+/**
+ * @brief Marks a function as not inlineable.
+ * @note Can be implemented as an empty macro if not supported by the
+ * compiler.
+ */
+#define CC_NO_INLINE __declspec(never_inline)
+
+/**
+ * @brief Enforces a function inline.
+ * @note Can be implemented as an empty macro if not supported by the
+ * compiler.
+ */
+#define CC_FORCE_INLINE //__attribute__((always_inline))
+
+/**
+ * @brief Marks a function as non-returning.
+ * @note Can be implemented as an empty macro if not supported by the
+ * compiler.
+ */
+#define CC_NO_RETURN //__attribute__((noreturn))
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* CCPORTAB_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/portability/GCC/ccportab.h b/ChibiOS_20.3.2/os/common/portability/GCC/ccportab.h
new file mode 100644
index 0000000..8936a9e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/portability/GCC/ccportab.h
@@ -0,0 +1,129 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file GCC/ccportab.h
+ * @brief Compiler portability layer.
+ *
+ * @defgroup CC_PORTAB Compiler portability.
+ * @{
+ */
+
+#ifndef CCPORTAB_H
+#define CCPORTAB_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @name Compiler abstraction macros
+ * @{
+ */
+/**
+ * @brief Allocates a variable or function to a specific section.
+ * @note If the compiler does not support such a feature then this macro
+ * must not be defined or it could originate errors.
+ */
+#define CC_SECTION(s) __attribute__((section(s)))
+
+/**
+ * @brief Marks a function or variable as a weak symbol.
+ * @note If the compiler does not support such a feature then this macro
+ * must not be defined or it could originate errors.
+ */
+#define CC_WEAK __attribute__((weak))
+
+/**
+ * @brief Marks a function or variable as used.
+ * @details The compiler or linker shall not remove the marked function or
+ * variable regardless if it is referred or not in the code.
+ * @note If the compiler does not support such a feature then this macro
+ * must not be defined or it could originate errors.
+ */
+#define CC_USED __attribute__((used))
+
+/**
+ * @brief Enforces alignment of the variable or function declared afterward.
+ * @note If the compiler does not support such a feature then this macro
+ * must not be defined or it could originate errors.
+ */
+#define CC_ALIGN(n) __attribute__((aligned(n)))
+
+/**
+ * @brief Enforces packing of the structure declared afterward.
+ * @note If the compiler does not support such a feature then this macro
+ * must not be defined or it could originate errors.
+ */
+#define CC_PACK __attribute__((packed))
+
+/**
+ * @brief Marks a function as not inlineable.
+ * @note Can be implemented as an empty macro if not supported by the
+ * compiler.
+ */
+#define CC_NO_INLINE __attribute__((noinline))
+
+/**
+ * @brief Enforces a function inline.
+ * @note Can be implemented as an empty macro if not supported by the
+ * compiler.
+ */
+#define CC_FORCE_INLINE __attribute__((always_inline))
+
+/**
+ * @brief Marks a function as non-returning.
+ * @note Can be implemented as an empty macro if not supported by the
+ * compiler.
+ */
+#define CC_NO_RETURN __attribute__((noreturn))
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* CCPORTAB_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/portability/GHS/ccportab.h b/ChibiOS_20.3.2/os/common/portability/GHS/ccportab.h
new file mode 100644
index 0000000..4372152
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/portability/GHS/ccportab.h
@@ -0,0 +1,129 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file GHS/ccportab.h
+ * @brief Compiler portability layer.
+ *
+ * @defgroup CC_PORTAB Compiler portability.
+ * @{
+ */
+
+#ifndef CCPORTAB_H
+#define CCPORTAB_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @name Compiler abstraction macros
+ * @{
+ */
+/**
+ * @brief Allocates a variable or function to a specific section.
+ * @note If the compiler does not support such a feature then this macro
+ * must not be defined or it could originate errors.
+ */
+#define CC_SECTION(s) __attribute__((section(s)))
+
+/**
+ * @brief Marks a function or variable as a weak symbol.
+ * @note If the compiler does not support such a feature then this macro
+ * must not be defined or it could originate errors.
+ */
+#define CC_WEAK __attribute__((weak))
+
+/**
+ * @brief Marks a function or variable as used.
+ * @details The compiler or linker shall not remove the marked function or
+ * variable regardless if it is referred or not in the code.
+ * @note If the compiler does not support such a feature then this macro
+ * must not be defined or it could originate errors.
+ */
+#define CC_USED __attribute__((used))
+
+/**
+ * @brief Enforces alignment of the variable or function declared afterward.
+ * @note If the compiler does not support such a feature then this macro
+ * must not be defined or it could originate errors.
+ */
+#define CC_ALIGN(n) __attribute__((aligned(n)))
+
+/**
+ * @brief Enforces packing of the structure declared afterward.
+ * @note If the compiler does not support such a feature then this macro
+ * must not be defined or it could originate errors.
+ */
+#define CC_PACK __attribute__((packed))
+
+/**
+ * @brief Marks a function as not inlineable.
+ * @note Can be implemented as an empty macro if not supported by the
+ * compiler.
+ */
+#define CC_NO_INLINE __noinline
+
+/**
+ * @brief Enforces a function inline.
+ * @note Can be implemented as an empty macro if not supported by the
+ * compiler.
+ */
+#define CC_FORCE_INLINE
+
+/**
+ * @brief Marks a function as non-returning.
+ * @note Can be implemented as an empty macro if not supported by the
+ * compiler.
+ */
+#define CC_NO_RETURN __attribute__((noreturn))
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* CCPORTAB_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARM/chcore.c b/ChibiOS_20.3.2/os/common/ports/ARM/chcore.c
new file mode 100644
index 0000000..38ecba6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARM/chcore.c
@@ -0,0 +1,54 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file ARM/chcore.c
+ * @brief ARM port code.
+ *
+ * @addtogroup ARM_CORE
+ * @{
+ */
+
+#include "ch.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARM/chcore.h b/ChibiOS_20.3.2/os/common/ports/ARM/chcore.h
new file mode 100644
index 0000000..35797de
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARM/chcore.h
@@ -0,0 +1,607 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file ARM/chcore.h
+ * @brief ARM7/9 architecture port macros and structures.
+ *
+ * @addtogroup ARM_CORE
+ * @{
+ */
+
+#ifndef CHCORE_H
+#define CHCORE_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Port Capabilities and Constants
+ * @{
+ */
+/**
+ * @brief This port supports a realtime counter.
+ */
+#define PORT_SUPPORTS_RT TRUE
+
+/**
+ * @brief Natural alignment constant.
+ * @note It is the minimum alignment for pointer-size variables.
+ */
+#define PORT_NATURAL_ALIGN sizeof (void *)
+
+/**
+ * @brief Stack alignment constant.
+ * @note It is the alignment required for the stack pointer.
+ */
+#define PORT_STACK_ALIGN sizeof (stkalign_t)
+
+/**
+ * @brief Working Areas alignment constant.
+ * @note It is the alignment to be enforced for thread working areas.
+ */
+#define PORT_WORKING_AREA_ALIGN sizeof (stkalign_t)
+/** @} */
+
+/**
+ * @name Architecture and Compiler
+ * @{
+ */
+/**
+ * @brief Macro defining a generic ARM architecture.
+ */
+#define PORT_ARCHITECTURE_ARM
+
+/* The following code is not processed when the file is included from an
+ asm module because those intrinsic macros are not necessarily defined
+ by the assembler too.*/
+#if !defined(_FROM_ASM_)
+
+/**
+ * @brief Compiler name and version.
+ */
+#if defined(__GNUC__) || defined(__DOXYGEN__)
+#define PORT_COMPILER_NAME "GCC " __VERSION__
+
+#else
+#error "unsupported compiler"
+#endif
+
+#endif /* !defined(_FROM_ASM_) */
+/** @} */
+
+/**
+ * @name ARM variants
+ * @{
+ */
+#define ARM_CORE_ARM7TDMI 7
+#define ARM_CORE_ARM9 9
+#define ARM_CORE_CORTEX_A5 105
+#define ARM_CORE_CORTEX_A7 107
+#define ARM_CORE_CORTEX_A8 108
+#define ARM_CORE_CORTEX_A9 109
+/** @} */
+
+/* Inclusion of the ARM implementation specific parameters.*/
+#include "armparams.h"
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables an alternative timer implementation.
+ * @details Usually the port uses a timer interface defined in the file
+ * @p chcore_timer.h, if this option is enabled then the file
+ * @p chcore_timer_alt.h is included instead.
+ */
+#if !defined(PORT_USE_ALT_TIMER)
+#define PORT_USE_ALT_TIMER FALSE
+#endif
+
+/**
+ * @brief Stack size for the system idle thread.
+ * @details This size depends on the idle thread implementation, usually
+ * the idle thread should take no more space than those reserved
+ * by @p PORT_INT_REQUIRED_STACK.
+ * @note In this port it is set to 32 because the idle thread does have
+ * a stack frame when compiling without optimizations. You may
+ * reduce this value to zero when compiling with optimizations.
+ */
+#if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__)
+#define PORT_IDLE_THREAD_STACK_SIZE 32
+#endif
+
+/**
+ * @brief Per-thread stack overhead for interrupts servicing.
+ * @details This constant is used in the calculation of the correct working
+ * area size.
+ */
+#if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__)
+#define PORT_INT_REQUIRED_STACK 32
+#endif
+
+/**
+ * @brief If enabled allows the idle thread to enter a low power mode.
+ */
+#ifndef ARM_ENABLE_WFI_IDLE
+#define ARM_ENABLE_WFI_IDLE FALSE
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if ARM_CORE < 100
+#define ARM_CORE_CLASSIC 1
+#define ARM_CORE_CORTEX_A 0
+#elif ARM_CORE < 200
+#define ARM_CORE_CLASSIC 0
+#define ARM_CORE_CORTEX_A 1
+#else
+#endif
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/* ARM core check.*/
+#if (ARM_CORE == ARM_CORE_ARM7TDMI) || defined(__DOXYGEN__)
+#define PORT_ARCHITECTURE_ARM_ARM7
+#define PORT_ARCHITECTURE_NAME "ARMv4T"
+#define PORT_CORE_VARIANT_NAME "ARM7"
+
+#elif ARM_CORE == ARM_CORE_ARM9
+#define PORT_ARCHITECTURE_ARM_ARM9
+#define PORT_ARCHITECTURE_NAME "ARMv5T"
+#define PORT_CORE_VARIANT_NAME "ARM9"
+
+#elif ARM_CORE == ARM_CORE_CORTEX_A5
+#define PORT_ARCHITECTURE_ARM_CORTEXA5
+#define PORT_ARCHITECTURE_NAME "ARMv7"
+#define PORT_CORE_VARIANT_NAME "ARM Cortex-A5"
+
+#elif ARM_CORE == ARM_CORE_CORTEX_A7
+#define PORT_ARCHITECTURE_ARM_CORTEXA5
+#define PORT_ARCHITECTURE_NAME "ARMv7"
+#define PORT_CORE_VARIANT_NAME "ARM Cortex-A7"
+
+#elif ARM_CORE == ARM_CORE_CORTEX_A8
+#define PORT_ARCHITECTURE_ARM_CORTEXA8
+#define PORT_ARCHITECTURE_NAME "ARMv7"
+#define PORT_CORE_VARIANT_NAME "ARM Cortex-A8"
+
+#elif ARM_CORE == ARM_CORE_CORTEX_A9
+#define PORT_ARCHITECTURE_ARM_CORTEXA9
+#define PORT_ARCHITECTURE_NAME "ARMv7"
+#define PORT_CORE_VARIANT_NAME "ARM Cortex-A9"
+
+#else
+#error "unknown or unsupported ARM core"
+#endif
+
+#if defined(THUMB_PRESENT)
+#if defined(THUMB_NO_INTERWORKING)
+#define PORT_INFO "Pure THUMB mode"
+#else
+#define PORT_INFO "Interworking mode"
+#endif
+#else
+#define PORT_INFO "Pure ARM mode"
+#endif
+
+#endif /* !defined(_FROM_ASM_) */
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/**
+ * @brief Type of stack and memory alignment enforcement.
+ * @note In this architecture the stack alignment is enforced to 64 bits.
+ */
+typedef uint64_t stkalign_t;
+
+/**
+ * @brief Generic ARM register.
+ */
+typedef void *regarm_t;
+
+/**
+ * @brief Interrupt saved context.
+ * @details This structure represents the stack frame saved during an
+ * interrupt handler.
+ */
+struct port_extctx {
+ regarm_t spsr_irq;
+ regarm_t lr_irq;
+ regarm_t r0;
+ regarm_t r1;
+ regarm_t r2;
+ regarm_t r3;
+ regarm_t r12;
+ regarm_t lr_usr;
+};
+
+/**
+ * @brief System saved context.
+ * @details This structure represents the inner stack frame during a context
+ * switch.
+ */
+struct port_intctx {
+ regarm_t r4;
+ regarm_t r5;
+ regarm_t r6;
+ regarm_t r7;
+ regarm_t r8;
+ regarm_t r9;
+ regarm_t r10;
+ regarm_t r11;
+ regarm_t lr;
+};
+
+/**
+ * @brief Platform dependent part of the @p thread_t structure.
+ * @details In this port the structure just holds a pointer to the
+ * @p port_intctx structure representing the stack pointer
+ * at context switch time.
+ */
+struct port_context {
+ struct port_intctx *sp;
+};
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Platform dependent part of the @p chThdCreateI() API.
+ * @details This code usually setup the context switching frame represented
+ * by an @p port_intctx structure.
+ */
+#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \
+ (tp)->ctx.sp = (struct port_intctx *)((uint8_t *)(wtop) - \
+ sizeof (struct port_intctx)); \
+ (tp)->ctx.sp->r4 = (regarm_t)(pf); \
+ (tp)->ctx.sp->r5 = (regarm_t)(arg); \
+ (tp)->ctx.sp->lr = (regarm_t)(_port_thread_start); \
+}
+
+/**
+ * @brief Computes the thread working area global size.
+ * @note There is no need to perform alignments in this macro.
+ */
+#define PORT_WA_SIZE(n) (sizeof(struct port_intctx) + \
+ sizeof(struct port_extctx) + \
+ ((size_t)(n)) + ((size_t)(PORT_INT_REQUIRED_STACK)))
+
+/**
+ * @brief Static working area allocation.
+ * @details This macro is used to allocate a static thread working area
+ * aligned as both position and size.
+ *
+ * @param[in] s the name to be assigned to the stack array
+ * @param[in] n the stack size to be assigned to the thread
+ */
+#define PORT_WORKING_AREA(s, n) \
+ stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)]
+
+/**
+ * @brief Priority level verification macro.
+ * @todo Add the required parameters to armparams.h.
+ */
+#define PORT_IRQ_IS_VALID_PRIORITY(n) false
+
+/**
+ * @brief IRQ prologue code.
+ * @details This macro must be inserted at the start of all IRQ handlers
+ * enabled to invoke system APIs.
+ */
+#define PORT_IRQ_PROLOGUE()
+
+/**
+ * @brief IRQ epilogue code.
+ * @details This macro must be inserted at the end of all IRQ handlers
+ * enabled to invoke system APIs.
+ */
+#define PORT_IRQ_EPILOGUE() return chSchIsPreemptionRequired()
+
+/**
+ * @brief IRQ handler function declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ */
+#ifdef __cplusplus
+#define PORT_IRQ_HANDLER(id) extern "C" bool id(void)
+#else
+#define PORT_IRQ_HANDLER(id) bool id(void)
+#endif
+
+/**
+ * @brief Fast IRQ handler function declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ */
+#define PORT_FAST_IRQ_HANDLER(id) \
+ __attribute__((interrupt("FIQ"))) void id(void)
+
+/**
+ * @brief Performs a context switch between two threads.
+ * @details This is the most critical code in any port, this function
+ * is responsible for the context switch between 2 threads.
+ * @note The implementation of this code affects directly the context
+ * switch performance so optimize here as much as you can.
+ * @note Implemented as inlined code for performance reasons.
+ *
+ * @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread to be switched out
+ */
+#if defined(THUMB)
+
+#if CH_DBG_ENABLE_STACK_CHECK == TRUE
+#define port_switch(ntp, otp) { \
+ register struct port_intctx *r13 asm ("r13"); \
+ if ((stkalign_t *)(r13 - 1) < otp->wabase) \
+ chSysHalt("stack overflow"); \
+ _port_switch_thumb(ntp, otp); \
+}
+#else
+#define port_switch(ntp, otp) _port_switch_thumb(ntp, otp)
+#endif
+
+#else /* !defined(THUMB) */
+
+#if CH_DBG_ENABLE_STACK_CHECK == TRUE
+#define port_switch(ntp, otp) { \
+ register struct port_intctx *r13 asm ("r13"); \
+ if ((stkalign_t *)(r13 - 1) < otp->wabase) \
+ chSysHalt("stack overflow"); \
+ _port_switch_arm(ntp, otp); \
+}
+#else
+#define port_switch(ntp, otp) _port_switch_arm(ntp, otp)
+#endif
+
+#endif /* !defined(THUMB) */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if defined(THUMB_PRESENT)
+ syssts_t _port_get_cpsr(void);
+#endif
+#if defined(THUMB)
+ void _port_switch_thumb(thread_t *ntp, thread_t *otp);
+#else
+ void _port_switch_arm(thread_t *ntp, thread_t *otp);
+#endif
+ void _port_thread_start(void);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Port-related initialization code.
+ */
+static inline void port_init(void) {
+
+}
+
+/**
+ * @brief Returns a word encoding the current interrupts status.
+ *
+ * @return The interrupts status.
+ */
+static inline syssts_t port_get_irq_status(void) {
+ syssts_t sts;
+
+#if defined(THUMB)
+ sts = _port_get_cpsr();
+#else
+ __asm volatile ("mrs %[p0], CPSR" : [p0] "=r" (sts) :);
+#endif
+ /*lint -save -e530 [9.1] Asm instruction not seen by lint.*/
+ return sts;
+ /*lint -restore*/
+}
+
+/**
+ * @brief Checks the interrupt status.
+ *
+ * @param[in] sts the interrupt status word
+ *
+ * @return The interrupt status.
+ * @retval false the word specified a disabled interrupts status.
+ * @retval true the word specified an enabled interrupts status.
+ */
+static inline bool port_irq_enabled(syssts_t sts) {
+
+ return (sts & (syssts_t)0x80) == (syssts_t)0;
+}
+
+/**
+ * @brief Determines the current execution context.
+ *
+ * @return The execution context.
+ * @retval false not running in ISR mode.
+ * @retval true running in ISR mode.
+ */
+static inline bool port_is_isr_context(void) {
+ syssts_t sts;
+
+#if defined(THUMB)
+ sts = _port_get_cpsr();
+#else
+ __asm volatile ("mrs %[p0], CPSR" : [p0] "=r" (sts) :);
+#endif
+
+ /*lint -save -e530 [9.1] Asm instruction not seen by lint.*/
+ return (sts & (syssts_t)0x1F) == (syssts_t)0x12;
+ /*lint -restore*/
+}
+
+/**
+ * @brief Kernel-lock action.
+ * @details In this port it disables the IRQ sources and keeps FIQ sources
+ * enabled.
+ */
+static inline void port_lock(void) {
+
+#if defined(THUMB)
+ __asm volatile ("bl _port_lock_thumb" : : : "r3", "lr", "memory");
+#else
+ __asm volatile ("msr CPSR_c, #0x9F" : : : "memory");
+#endif
+}
+
+/**
+ * @brief Kernel-unlock action.
+ * @details In this port it enables both the IRQ and FIQ sources.
+ */
+static inline void port_unlock(void) {
+
+#if defined(THUMB)
+ __asm volatile ("bl _port_unlock_thumb" : : : "r3", "lr", "memory");
+#else
+ __asm volatile ("msr CPSR_c, #0x1F" : : : "memory");
+#endif
+}
+
+/**
+ * @brief Kernel-lock action from an interrupt handler.
+ * @note Empty in this port.
+ */
+static inline void port_lock_from_isr(void) {
+
+}
+
+/**
+ * @brief Kernel-unlock action from an interrupt handler.
+ * @note Empty in this port.
+ */
+static inline void port_unlock_from_isr(void) {
+
+}
+
+/**
+ * @brief Disables all the interrupt sources.
+ * @details In this port it disables both the IRQ and FIQ sources.
+ * @note Implements a workaround for spurious interrupts taken from the NXP
+ * LPC214x datasheet.
+ */
+static inline void port_disable(void) {
+
+#if defined(THUMB)
+ __asm volatile ("bl _port_disable_thumb" : : : "r3", "lr", "memory");
+#else
+ __asm volatile ("mrs r3, CPSR \n\t"
+ "orr r3, #0x80 \n\t"
+ "msr CPSR_c, r3 \n\t"
+ "orr r3, #0x40 \n\t"
+ "msr CPSR_c, r3" : : : "r3", "memory");
+#endif
+}
+
+/**
+ * @brief Disables the interrupt sources below kernel-level priority.
+ * @note Interrupt sources above kernel level remains enabled.
+ * @note In this port it disables the IRQ sources and enables the
+ * FIQ sources.
+ */
+static inline void port_suspend(void) {
+
+#if defined(THUMB)
+ __asm volatile ("bl _port_suspend_thumb" : : : "r3", "lr", "memory");
+#else
+ __asm volatile ("msr CPSR_c, #0x9F" : : : "memory");
+#endif
+}
+
+/**
+ * @brief Enables all the interrupt sources.
+ * @note In this port it enables both the IRQ and FIQ sources.
+ */
+static inline void port_enable(void) {
+
+#if defined(THUMB)
+ __asm volatile ("bl _port_enable_thumb" : : : "r3", "lr", "memory");
+#else
+ __asm volatile ("msr CPSR_c, #0x1F" : : : "memory");
+#endif
+}
+
+/**
+ * @brief Returns the current value of the realtime counter.
+ *
+ * @return The realtime counter value.
+ */
+static inline rtcnt_t port_rt_get_counter_value(void) {
+
+#if ARM_CORE_CORTEX_A
+ rtcnt_t cyc;
+
+ __asm volatile("mrc p15, 0, %[p0], c9, c13, 0" : [p0] "=r" (cyc) :);
+
+ return cyc;
+#else
+ return 0;
+#endif
+}
+
+/**
+ * @brief Enters an architecture-dependent IRQ-waiting mode.
+ * @details The function is meant to return when an interrupt becomes pending.
+ * The simplest implementation is an empty function or macro but this
+ * would not take advantage of architecture-specific power saving
+ * modes.
+ * @note Implemented as an inlined @p WFI instruction.
+ */
+static inline void port_wait_for_interrupt(void) {
+
+#if ARM_ENABLE_WFI_IDLE == TRUE
+ ARM_WFI_IMPL;
+#endif
+}
+
+#if CH_CFG_ST_TIMEDELTA > 0
+#if PORT_USE_ALT_TIMER == FALSE
+#include "chcore_timer.h"
+#else /* PORT_USE_ALT_TIMER */
+#include "chcore_timer_alt.h"
+#endif /* PORT_USE_ALT_TIMER */
+#endif /* CH_CFG_ST_TIMEDELTA > 0 */
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CHCORE_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARM/chcore_timer.h b/ChibiOS_20.3.2/os/common/ports/ARM/chcore_timer.h
new file mode 100644
index 0000000..e19ac8e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARM/chcore_timer.h
@@ -0,0 +1,126 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file chcore_timer.h
+ * @brief System timer header file.
+ *
+ * @addtogroup ARM_TIMER
+ * @{
+ */
+
+#ifndef CHCORE_TIMER_H
+#define CHCORE_TIMER_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Starts the alarm.
+ * @note Makes sure that no spurious alarms are triggered after
+ * this call.
+ *
+ * @param[in] time the time to be set for the first alarm
+ *
+ * @notapi
+ */
+static inline void port_timer_start_alarm(systime_t time) {
+ void stStartAlarm(systime_t time);
+
+ stStartAlarm(time);
+}
+
+/**
+ * @brief Stops the alarm interrupt.
+ *
+ * @notapi
+ */
+static inline void port_timer_stop_alarm(void) {
+ void stStopAlarm(void);
+
+ stStopAlarm();
+}
+
+/**
+ * @brief Sets the alarm time.
+ *
+ * @param[in] time the time to be set for the next alarm
+ *
+ * @notapi
+ */
+static inline void port_timer_set_alarm(systime_t time) {
+ void stSetAlarm(systime_t time);
+
+ stSetAlarm(time);
+}
+
+/**
+ * @brief Returns the system time.
+ *
+ * @return The system time.
+ *
+ * @notapi
+ */
+static inline systime_t port_timer_get_time(void) {
+ systime_t stGetCounter(void);
+
+ return stGetCounter();
+}
+
+/**
+ * @brief Returns the current alarm time.
+ *
+ * @return The currently set alarm time.
+ *
+ * @notapi
+ */
+static inline systime_t port_timer_get_alarm(void) {
+ systime_t stGetAlarm(void);
+
+ return stGetAlarm();
+}
+
+#endif /* CHCORE_TIMER_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARM/compilers/GCC/chcoreasm.S b/ChibiOS_20.3.2/os/common/ports/ARM/compilers/GCC/chcoreasm.S
new file mode 100644
index 0000000..f4f435d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARM/compilers/GCC/chcoreasm.S
@@ -0,0 +1,167 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file ARM/compilers/GCC/chcoreasm.S
+ * @brief ARM architecture port low level code.
+ *
+ * @addtogroup ARM_CORE
+ * @{
+ */
+
+#define _FROM_ASM_
+#include "chlicense.h"
+#include "chconf.h"
+#include "armparams.h"
+
+#define FALSE 0
+#define TRUE 1
+
+#if !defined(__DOXYGEN__)
+
+/*
+ * RTOS-specific context offset.
+ */
+#if defined(_CHIBIOS_RT_CONF_)
+#define CONTEXT_OFFSET 12
+#elif defined(_CHIBIOS_NIL_CONF_)
+#define CONTEXT_OFFSET 0
+#else
+#error "invalid chconf.h"
+#endif
+
+ .set MODE_USR, 0x10
+ .set MODE_FIQ, 0x11
+ .set MODE_IRQ, 0x12
+ .set MODE_SVC, 0x13
+ .set MODE_ABT, 0x17
+ .set MODE_UND, 0x1B
+ .set MODE_SYS, 0x1F
+
+ .equ I_BIT, 0x80
+ .equ F_BIT, 0x40
+
+ .text
+
+
+ .balign 16
+
+ .code 32
+ .global _port_switch_arm
+_port_switch_arm:
+ stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}
+ str sp, [r1, #12]
+ ldr sp, [r0, #12]
+ ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}
+
+/*
+ * Common IRQ code. It expects a macro ARM_IRQ_VECTOR_REG with the address
+ * of a register holding the address of the ISR to be invoked, the ISR
+ * then returns in the common epilogue code where the context switch will
+ * be performed, if required.
+ * System stack frame structure after a context switch in the
+ * interrupt handler:
+ *
+ * High +------------+
+ * | LR_USR | -+
+ * | r12 | |
+ * | r3 | |
+ * | r2 | | External context: IRQ handler frame
+ * | r1 | |
+ * | r0 | |
+ * | LR_IRQ | | (user code return address)
+ * | PSR_USR | -+ (user code status)
+ * | .... | <- chSchDoReschedule() stack frame, optimize it for space
+ * | LR | -+ (system code return address)
+ * | r11 | |
+ * | r10 | |
+ * | r9 | |
+ * | r8 | | Internal context: chSysSwitch() frame
+ * | r7 | |
+ * | r6 | |
+ * | r5 | |
+ * SP-> | r4 | -+
+ * Low +------------+
+ */
+ .balign 16
+ .code 32
+ .global Irq_Handler
+Irq_Handler:
+ stmfd sp!, {r0-r3, r12, lr}
+ ldr r0, =ARM_IRQ_VECTOR_REG
+ ldr r0, [r0]
+ ldr lr, =_irq_ret_arm // ISR return point.
+ bx r0 // Calling the ISR.
+_irq_ret_arm:
+ cmp r0, #0
+ ldmfd sp!, {r0-r3, r12, lr}
+ subeqs pc, lr, #4 // No reschedule, returns.
+
+ // Now the frame is created in the system stack, the IRQ
+ // stack is empty.
+ msr CPSR_c, #MODE_SYS | I_BIT
+ stmfd sp!, {r0-r3, r12, lr}
+ msr CPSR_c, #MODE_IRQ | I_BIT
+ mrs r0, SPSR
+ mov r1, lr
+ msr CPSR_c, #MODE_SYS | I_BIT
+ stmfd sp!, {r0, r1} // Push R0=SPSR, R1=LR_IRQ.
+
+ // Context switch.
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_lock
+#endif
+ bl chSchDoReschedule
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_unlock
+#endif
+
+ // Re-establish the IRQ conditions again.
+ ldmfd sp!, {r0, r1} // Pop R0=SPSR, R1=LR_IRQ.
+ msr CPSR_c, #MODE_IRQ | I_BIT
+ msr SPSR_fsxc, r0
+ mov lr, r1
+ msr CPSR_c, #MODE_SYS | I_BIT
+ ldmfd sp!, {r0-r3, r12, lr}
+ msr CPSR_c, #MODE_IRQ | I_BIT
+ subs pc, lr, #4
+
+/*
+ * Threads trampoline code.
+ * NOTE: The threads always start in ARM mode and then switches to the
+ * thread-function mode.
+ */
+ .balign 16
+ .code 32
+ .globl _port_thread_start
+_port_thread_start:
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_unlock
+#endif
+ msr CPSR_c, #MODE_SYS
+ mov r0, r5
+ mov lr, pc
+ bx r4
+ mov r0, #0 /* MSG_OK */
+ bl chThdExit
+_zombies: b _zombies
+
+#endif /* !defined(__DOXYGEN__) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARM/compilers/GCC/chtypes.h b/ChibiOS_20.3.2/os/common/ports/ARM/compilers/GCC/chtypes.h
new file mode 100644
index 0000000..0481016
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARM/compilers/GCC/chtypes.h
@@ -0,0 +1,115 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file ARM/compilers/GCC/chtypes.h
+ * @brief ARM port system types.
+ *
+ * @addtogroup ARM_GCC_CORE
+ * @{
+ */
+
+#ifndef CHTYPES_H
+#define CHTYPES_H
+
+#include
+#include
+#include
+
+/**
+ * @name Common constants
+ */
+/**
+ * @brief Generic 'false' boolean constant.
+ */
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+/**
+ * @brief Generic 'true' boolean constant.
+ */
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+/** @} */
+
+/**
+ * @name Kernel types
+ * @{
+ */
+typedef uint32_t rtcnt_t; /**< Realtime counter. */
+typedef uint64_t rttime_t; /**< Realtime accumulator. */
+typedef uint32_t syssts_t; /**< System status word. */
+typedef uint8_t tmode_t; /**< Thread flags. */
+typedef uint8_t tstate_t; /**< Thread state. */
+typedef uint8_t trefs_t; /**< Thread references counter. */
+typedef uint8_t tslices_t; /**< Thread time slices counter.*/
+typedef uint32_t tprio_t; /**< Thread priority. */
+typedef int32_t msg_t; /**< Inter-thread message. */
+typedef int32_t eventid_t; /**< Numeric event identifier. */
+typedef uint32_t eventmask_t; /**< Mask of event identifiers. */
+typedef uint32_t eventflags_t; /**< Mask of event flags. */
+typedef int32_t cnt_t; /**< Generic signed counter. */
+typedef uint32_t ucnt_t; /**< Generic unsigned counter. */
+/** @} */
+
+/**
+ * @brief ROM constant modifier.
+ * @note It is set to use the "const" keyword in this port.
+ */
+#define ROMCONST const
+
+/**
+ * @brief Makes functions not inlineable.
+ * @note If the compiler does not support such attribute then some
+ * time-dependent services could be degraded.
+ */
+#define NOINLINE __attribute__((noinline))
+
+/**
+ * @brief Optimized thread function declaration macro.
+ */
+#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg)
+
+/**
+ * @brief Packed variable specifier.
+ */
+#define PACKED_VAR __attribute__((packed))
+
+/**
+ * @brief Memory alignment enforcement for variables.
+ */
+#define ALIGNED_VAR(n) __attribute__((aligned(n)))
+
+/**
+ * @brief Size of a pointer.
+ * @note To be used where the sizeof operator cannot be used, preprocessor
+ * expressions for example.
+ */
+#define SIZEOF_PTR 4
+
+/**
+ * @brief True if alignment is low-high in current architecture.
+ */
+#define REVERSE_ORDER 1
+
+#endif /* CHTYPES_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARM/compilers/GCC/mk/port_generic.mk b/ChibiOS_20.3.2/os/common/ports/ARM/compilers/GCC/mk/port_generic.mk
new file mode 100644
index 0000000..71f269b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARM/compilers/GCC/mk/port_generic.mk
@@ -0,0 +1,12 @@
+# List of the ChibiOS/RT ARM generic port files.
+PORTSRC = ${CHIBIOS}/os/common/ports/ARM/chcore.c
+
+PORTASM = $(CHIBIOS)/os/common/ports/ARM/compilers/GCC/chcoreasm.S
+
+PORTINC = ${CHIBIOS}/os/common/ports/ARM \
+ ${CHIBIOS}/os/common/ports/ARM/compilers/GCC
+
+# Shared variables
+ALLXASMSRC += $(PORTASM)
+ALLCSRC += $(PORTSRC)
+ALLINC += $(PORTINC)
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore.c b/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore.c
new file mode 100644
index 0000000..06a0ca8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore.c
@@ -0,0 +1,54 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file ARMCMx/chcore.c
+ * @brief ARM Cortex-Mx port code.
+ *
+ * @addtogroup ARMCMx_CORE
+ * @{
+ */
+
+#include "ch.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore.h b/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore.h
new file mode 100644
index 0000000..b6873ee
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore.h
@@ -0,0 +1,208 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file ARMCMx/chcore.h
+ * @brief ARM Cortex-Mx port macros and structures.
+ *
+ * @addtogroup ARMCMx_CORE
+ * @{
+ */
+
+#ifndef CHCORE_H
+#define CHCORE_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Architecture and Compiler
+ * @{
+ */
+/**
+ * @brief Macro defining a generic ARM architecture.
+ */
+#define PORT_ARCHITECTURE_ARM
+
+/* The following code is not processed when the file is included from an
+ asm module because those intrinsic macros are not necessarily defined
+ by the assembler too.*/
+#if !defined(_FROM_ASM_)
+
+/**
+ * @brief Compiler name and version.
+ */
+#if defined(__GNUC__) || defined(__DOXYGEN__)
+#define PORT_COMPILER_NAME "GCC " __VERSION__
+
+#elif defined(__ICCARM__)
+#define PORT_COMPILER_NAME "IAR"
+
+#elif defined(__CC_ARM)
+#define PORT_COMPILER_NAME "RVCT"
+
+#else
+#error "unsupported compiler"
+#endif
+
+#endif /* !defined(_FROM_ASM_) */
+
+/** @} */
+
+/* Inclusion of the Cortex-Mx implementation specific parameters.*/
+#include "cmparams.h"
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables an alternative timer implementation.
+ * @details Usually the port uses a timer interface defined in the file
+ * @p chcore_timer.h, if this option is enabled then the file
+ * @p chcore_timer_alt.h is included instead.
+ */
+#if !defined(PORT_USE_ALT_TIMER)
+#define PORT_USE_ALT_TIMER FALSE
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/**
+ * @brief Type of stack and memory alignment enforcement.
+ * @note In this architecture the stack alignment is enforced to 64 bits,
+ * 32 bits alignment is supported by hardware but deprecated by ARM,
+ * the implementation choice is to not offer the option.
+ */
+typedef uint64_t stkalign_t;
+
+/* The following declarations are there just for Doxygen documentation, the
+ real declarations are inside the sub-headers being specific for the
+ sub-architectures.*/
+#if defined(__DOXYGEN__)
+/**
+ * @brief Interrupt saved context.
+ * @details This structure represents the stack frame saved during a
+ * preemption-capable interrupt handler.
+ * @note It is implemented to match the Cortex-Mx exception context.
+ */
+struct port_extctx {};
+
+/**
+ * @brief System saved context.
+ * @details This structure represents the inner stack frame during a context
+ * switch.
+ */
+struct port_intctx {};
+
+/**
+ * @brief Platform dependent part of the @p thread_t structure.
+ * @details In this port the structure just holds a pointer to the
+ * @p port_intctx structure representing the stack pointer
+ * at context switch time.
+ */
+struct port_context {};
+#endif /* defined(__DOXYGEN__) */
+
+#endif /* !defined(_FROM_ASM_) */
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Total priority levels.
+ */
+#define CORTEX_PRIORITY_LEVELS (1U << CORTEX_PRIORITY_BITS)
+
+/**
+ * @brief Minimum priority level.
+ * @details This minimum priority level is calculated from the number of
+ * priority bits supported by the specific Cortex-Mx implementation.
+ */
+#define CORTEX_MINIMUM_PRIORITY (CORTEX_PRIORITY_LEVELS - 1)
+
+/**
+ * @brief Maximum priority level.
+ * @details The maximum allowed priority level is always zero.
+ */
+#define CORTEX_MAXIMUM_PRIORITY 0U
+
+/**
+ * @brief Priority level to priority mask conversion macro.
+ */
+#define CORTEX_PRIO_MASK(n) \
+ ((n) << (8U - (unsigned)CORTEX_PRIORITY_BITS))
+
+/**
+ * @brief Priority level verification macro.
+ */
+#define PORT_IRQ_IS_VALID_PRIORITY(n) \
+ (((n) >= 0U) && ((n) < CORTEX_PRIORITY_LEVELS))
+
+/**
+ * @brief Priority level verification macro.
+ */
+#define PORT_IRQ_IS_VALID_KERNEL_PRIORITY(n) \
+ (((n) >= CORTEX_MAX_KERNEL_PRIORITY) && ((n) < CORTEX_PRIORITY_LEVELS))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/* Includes the sub-architecture-specific part.*/
+#if (CORTEX_MODEL == 0) || (CORTEX_MODEL == 1)
+#include "chcore_v6m.h"
+#elif (CORTEX_MODEL == 3) || (CORTEX_MODEL == 4) || (CORTEX_MODEL == 7)
+#include "mpu.h"
+#include "chcore_v7m.h"
+#else
+#error "unknown Cortex-M variant"
+#endif
+
+#if !defined(_FROM_ASM_)
+
+#if CH_CFG_ST_TIMEDELTA > 0
+#if PORT_USE_ALT_TIMER == FALSE
+#include "chcore_timer.h"
+#else /* PORT_USE_ALT_TIMER != FALSE */
+#include "chcore_timer_alt.h"
+#endif /* PORT_USE_ALT_TIMER != FALSE */
+#endif /* CH_CFG_ST_TIMEDELTA > 0 */
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CHCORE_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore_timer.h b/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore_timer.h
new file mode 100644
index 0000000..80a76f9
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore_timer.h
@@ -0,0 +1,133 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file chcore_timer.h
+ * @brief System timer header file.
+ *
+ * @addtogroup ARMCMx_TIMER
+ * @{
+ */
+
+#ifndef CHCORE_TIMER_H
+#define CHCORE_TIMER_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void stStartAlarm(systime_t time);
+ void stStopAlarm(void);
+ void stSetAlarm(systime_t time);
+ systime_t stGetCounter(void);
+ systime_t stGetAlarm(void);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Starts the alarm.
+ * @note Makes sure that no spurious alarms are triggered after
+ * this call.
+ *
+ * @param[in] time the time to be set for the first alarm
+ *
+ * @notapi
+ */
+static inline void port_timer_start_alarm(systime_t time) {
+
+ stStartAlarm(time);
+}
+
+/**
+ * @brief Stops the alarm interrupt.
+ *
+ * @notapi
+ */
+static inline void port_timer_stop_alarm(void) {
+
+ stStopAlarm();
+}
+
+/**
+ * @brief Sets the alarm time.
+ *
+ * @param[in] time the time to be set for the next alarm
+ *
+ * @notapi
+ */
+static inline void port_timer_set_alarm(systime_t time) {
+
+ stSetAlarm(time);
+}
+
+/**
+ * @brief Returns the system time.
+ *
+ * @return The system time.
+ *
+ * @notapi
+ */
+static inline systime_t port_timer_get_time(void) {
+
+ return stGetCounter();
+}
+
+/**
+ * @brief Returns the current alarm time.
+ *
+ * @return The currently set alarm time.
+ *
+ * @notapi
+ */
+static inline systime_t port_timer_get_alarm(void) {
+
+ return stGetAlarm();
+}
+
+#endif /* CHCORE_TIMER_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore_v6m.c b/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore_v6m.c
new file mode 100644
index 0000000..6847a15
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore_v6m.c
@@ -0,0 +1,155 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file chcore_v6m.c
+ * @brief ARMv6-M architecture port code.
+ *
+ * @addtogroup ARMCMx_V6M_CORE
+ * @{
+ */
+
+#include "ch.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module interrupt handlers. */
+/*===========================================================================*/
+
+#if (CORTEX_ALTERNATE_SWITCH == FALSE) || defined(__DOXYGEN__)
+/**
+ * @brief NMI vector.
+ * @details The NMI vector is used for exception mode re-entering after a
+ * context switch.
+ */
+/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/
+void NMI_Handler(void) {
+/*lint -restore*/
+
+ /* The port_extctx structure is pointed by the PSP register.*/
+ struct port_extctx *ctxp = (struct port_extctx *)__get_PSP();
+
+ /* Discarding the current exception context and positioning the stack to
+ point to the real one.*/
+ ctxp++;
+
+ /* Writing back the modified PSP value.*/
+ __set_PSP((uint32_t)ctxp);
+
+ /* Restoring the normal interrupts status.*/
+ port_unlock_from_isr();
+}
+#endif /* !CORTEX_ALTERNATE_SWITCH */
+
+#if (CORTEX_ALTERNATE_SWITCH == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief PendSV vector.
+ * @details The PendSV vector is used for exception mode re-entering after a
+ * context switch.
+ */
+/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/
+void PendSV_Handler(void) {
+/*lint -restore*/
+
+ /* The port_extctx structure is pointed by the PSP register.*/
+ struct port_extctx *ctxp = (struct port_extctx *)__get_PSP();
+
+ /* Discarding the current exception context and positioning the stack to
+ point to the real one.*/
+ ctxp++;
+
+ /* Writing back the modified PSP value.*/
+ __set_PSP((uint32_t)ctxp);
+}
+#endif /* CORTEX_ALTERNATE_SWITCH */
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Port-related initialization code.
+ */
+void port_init(void) {
+
+ NVIC_SetPriority(PendSV_IRQn, CORTEX_PRIORITY_PENDSV);
+}
+
+/**
+ * @brief IRQ epilogue code.
+ *
+ * @param[in] lr value of the @p LR register on ISR entry
+ */
+void _port_irq_epilogue(uint32_t lr) {
+
+ if (lr != 0xFFFFFFF1U) {
+ struct port_extctx *ectxp;
+
+ port_lock_from_isr();
+
+ /* The extctx structure is pointed by the PSP register.*/
+ ectxp = (struct port_extctx *)__get_PSP();
+
+ /* Adding an artificial exception return context, there is no need to
+ populate it fully.*/
+ ectxp--;
+
+ /* Writing back the modified PSP value.*/
+ __set_PSP((uint32_t)ectxp);
+
+ /* Setting up a fake XPSR register value.*/
+ ectxp->xpsr = 0x01000000U;
+
+ /* The exit sequence is different depending on if a preemption is
+ required or not.*/
+ if (chSchIsPreemptionRequired()) {
+ /* Preemption is required we need to enforce a context switch.*/
+ ectxp->pc = (uint32_t)_port_switch_from_isr;
+ }
+ else {
+ /* Preemption not required, we just need to exit the exception
+ atomically.*/
+ ectxp->pc = (uint32_t)_port_exit_from_isr;
+ }
+
+ /* Note, returning without unlocking is intentional, this is done in
+ order to keep the rest of the context switch atomic.*/
+ }
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore_v6m.h b/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore_v6m.h
new file mode 100644
index 0000000..371397e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore_v6m.h
@@ -0,0 +1,466 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file chcore_v6m.h
+ * @brief ARMv6-M architecture port macros and structures.
+ *
+ * @addtogroup ARMCMx_V6M_CORE
+ * @{
+ */
+
+#ifndef CHCORE_V6M_H
+#define CHCORE_V6M_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Port Capabilities and Constants
+ * @{
+ */
+/**
+ * @brief This port supports a realtime counter.
+ */
+#define PORT_SUPPORTS_RT FALSE
+
+/**
+ * @brief Natural alignment constant.
+ * @note It is the minimum alignment for pointer-size variables.
+ */
+#define PORT_NATURAL_ALIGN sizeof (void *)
+
+/**
+ * @brief Stack alignment constant.
+ * @note It is the alignment required for the stack pointer.
+ */
+#define PORT_STACK_ALIGN sizeof (stkalign_t)
+
+/**
+ * @brief Working Areas alignment constant.
+ * @note It is the alignment to be enforced for thread working areas.
+ */
+#define PORT_WORKING_AREA_ALIGN PORT_STACK_ALIGN
+/** @} */
+
+/**
+ * @brief PendSV priority level.
+ * @note This priority is enforced to be equal to @p 0,
+ * this handler always has the highest priority that cannot preempt
+ * the kernel.
+ */
+#define CORTEX_PRIORITY_PENDSV 0
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Stack size for the system idle thread.
+ * @details This size depends on the idle thread implementation, usually
+ * the idle thread should take no more space than those reserved
+ * by @p PORT_INT_REQUIRED_STACK.
+ * @note In this port it is set to 16 because the idle thread does have
+ * a stack frame when compiling without optimizations. You may
+ * reduce this value to zero when compiling with optimizations.
+ */
+#if !defined(PORT_IDLE_THREAD_STACK_SIZE)
+#define PORT_IDLE_THREAD_STACK_SIZE 16
+#endif
+
+/**
+ * @brief Per-thread stack overhead for interrupts servicing.
+ * @details This constant is used in the calculation of the correct working
+ * area size.
+ * @note In this port this value is conservatively set to 64 because the
+ * function @p chSchDoReschedule() can have a stack frame, especially
+ * with compiler optimizations disabled. The value can be reduced
+ * when compiler optimizations are enabled.
+ */
+#if !defined(PORT_INT_REQUIRED_STACK)
+#define PORT_INT_REQUIRED_STACK 64
+#endif
+
+/**
+ * @brief Enables the use of the WFI instruction in the idle thread loop.
+ */
+#if !defined(CORTEX_ENABLE_WFI_IDLE)
+#define CORTEX_ENABLE_WFI_IDLE FALSE
+#endif
+
+/**
+ * @brief Alternate preemption method.
+ * @details Activating this option will make the Kernel use the PendSV
+ * handler for preemption instead of the NMI handler.
+ */
+#ifndef CORTEX_ALTERNATE_SWITCH
+#define CORTEX_ALTERNATE_SWITCH FALSE
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !defined(CH_CUSTOMER_LIC_PORT_CM0)
+#error "CH_CUSTOMER_LIC_PORT_CM0 not defined"
+#endif
+
+#if CH_CUSTOMER_LIC_PORT_CM0 == FALSE
+#error "ChibiOS Cortex-M0 port not licensed"
+#endif
+
+/* Handling a GCC problem impacting ARMv6-M.*/
+#if defined(__GNUC__) && !defined(PORT_IGNORE_GCC_VERSION_CHECK)
+#if ( __GNUC__ > 5 ) && ( __GNUC__ < 10 )
+#define GCC_VERSION ( __GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ )
+#if ( __GNUC__ == 7 ) && ( GCC_VERSION >= 70500 )
+#elif ( __GNUC__ == 8 ) && ( GCC_VERSION >= 80400 )
+#elif ( __GNUC__ == 9 ) && ( GCC_VERSION >= 90300 )
+#else
+#warning "This compiler has a know problem with Cortex-M0, see GCC bugs: 88167, 88656."
+#endif
+#endif
+#endif
+
+/**
+ * @name Architecture and Compiler
+ * @{
+ */
+#if ((CORTEX_MODEL == 0) && !defined(__CORE_CM0PLUS_H_DEPENDANT)) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief Macro defining the specific ARM architecture.
+ */
+#define PORT_ARCHITECTURE_ARM_v6M
+
+/**
+ * @brief Name of the implemented architecture.
+ */
+#define PORT_ARCHITECTURE_NAME "ARMv6-M"
+
+/**
+ * @brief Name of the architecture variant.
+ */
+#define PORT_CORE_VARIANT_NAME "Cortex-M0"
+
+#elif (CORTEX_MODEL == 0) && defined(__CORE_CM0PLUS_H_DEPENDANT)
+#define PORT_ARCHITECTURE_ARM_v6M
+#define PORT_ARCHITECTURE_NAME "ARMv6-M"
+#define PORT_CORE_VARIANT_NAME "Cortex-M0+"
+#endif
+
+/**
+ * @brief Port-specific information string.
+ */
+#if (CORTEX_ALTERNATE_SWITCH == FALSE) || defined(__DOXYGEN__)
+#define PORT_INFO "Preemption through NMI"
+#else
+#define PORT_INFO "Preemption through PendSV"
+#endif
+/** @} */
+
+/**
+ * @brief Maximum usable priority for normal ISRs.
+ */
+#if (CORTEX_ALTERNATE_SWITCH == TRUE) || defined(__DOXYGEN__)
+#define CORTEX_MAX_KERNEL_PRIORITY 1
+#else
+#define CORTEX_MAX_KERNEL_PRIORITY 0
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+#if !defined(_FROM_ASM_)
+
+ /* The documentation of the following declarations is in chconf.h in order
+ to not have duplicated structure names into the documentation.*/
+#if !defined(__DOXYGEN__)
+struct port_extctx {
+ uint32_t r0;
+ uint32_t r1;
+ uint32_t r2;
+ uint32_t r3;
+ uint32_t r12;
+ uint32_t lr_thd;
+ uint32_t pc;
+ uint32_t xpsr;
+};
+
+struct port_intctx {
+ uint32_t r8;
+ uint32_t r9;
+ uint32_t r10;
+ uint32_t r11;
+ uint32_t r4;
+ uint32_t r5;
+ uint32_t r6;
+ uint32_t r7;
+ uint32_t lr;
+};
+
+struct port_context {
+ struct port_intctx *sp;
+};
+#endif /* !defined(__DOXYGEN__) */
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Platform dependent part of the @p chThdCreateI() API.
+ * @details This code usually setup the context switching frame represented
+ * by an @p port_intctx structure.
+ */
+#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \
+ (tp)->ctx.sp = (struct port_intctx *)((uint8_t *)(wtop) - \
+ sizeof (struct port_intctx)); \
+ (tp)->ctx.sp->r4 = (uint32_t)(pf); \
+ (tp)->ctx.sp->r5 = (uint32_t)(arg); \
+ (tp)->ctx.sp->lr = (uint32_t)_port_thread_start; \
+}
+
+/**
+ * @brief Computes the thread working area global size.
+ * @note There is no need to perform alignments in this macro.
+ */
+#define PORT_WA_SIZE(n) (sizeof (struct port_intctx) + \
+ sizeof (struct port_extctx) + \
+ ((size_t)(n)) + ((size_t)(PORT_INT_REQUIRED_STACK)))
+
+/**
+ * @brief Static working area allocation.
+ * @details This macro is used to allocate a static thread working area
+ * aligned as both position and size.
+ *
+ * @param[in] s the name to be assigned to the stack array
+ * @param[in] n the stack size to be assigned to the thread
+ */
+#define PORT_WORKING_AREA(s, n) \
+ stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)]
+
+/**
+ * @brief IRQ prologue code.
+ * @details This macro must be inserted at the start of all IRQ handlers
+ * enabled to invoke system APIs.
+ */
+#if defined(__GNUC__) || defined(__DOXYGEN__)
+#define PORT_IRQ_PROLOGUE() \
+ uint32_t _saved_lr = (uint32_t)__builtin_return_address(0)
+#elif defined(__ICCARM__)
+#define PORT_IRQ_PROLOGUE() \
+ uint32_t _saved_lr = (uint32_t)__get_LR()
+#elif defined(__CC_ARM)
+#define PORT_IRQ_PROLOGUE() \
+ uint32_t _saved_lr = (uint32_t)__return_address()
+#endif
+
+/**
+ * @brief IRQ epilogue code.
+ * @details This macro must be inserted at the end of all IRQ handlers
+ * enabled to invoke system APIs.
+ */
+#define PORT_IRQ_EPILOGUE() _port_irq_epilogue(_saved_lr)
+
+/**
+ * @brief IRQ handler function declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ */
+#ifdef __cplusplus
+#define PORT_IRQ_HANDLER(id) extern "C" void id(void)
+#else
+#define PORT_IRQ_HANDLER(id) void id(void)
+#endif
+
+/**
+ * @brief Fast IRQ handler function declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ */
+#ifdef __cplusplus
+#define PORT_FAST_IRQ_HANDLER(id) extern "C" void id(void)
+#else
+#define PORT_FAST_IRQ_HANDLER(id) void id(void)
+#endif
+
+/**
+ * @brief Performs a context switch between two threads.
+ * @details This is the most critical code in any port, this function
+ * is responsible for the context switch between 2 threads.
+ * @note The implementation of this code affects directly the context
+ * switch performance so optimize here as much as you can.
+ *
+ * @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread to be switched out
+ */
+#if (CH_DBG_ENABLE_STACK_CHECK == FALSE) || defined(__DOXYGEN__)
+#define port_switch(ntp, otp) _port_switch(ntp, otp)
+#else
+#define port_switch(ntp, otp) { \
+ struct port_intctx *r13 = (struct port_intctx *)__get_PSP(); \
+ if ((stkalign_t *)(r13 - 1) < (otp)->wabase) { \
+ chSysHalt("stack overflow"); \
+ } \
+ _port_switch(ntp, otp); \
+}
+#endif
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void port_init(void);
+ void _port_irq_epilogue(uint32_t lr);
+ void _port_switch(thread_t *ntp, thread_t *otp);
+ void _port_thread_start(void);
+ void _port_switch_from_isr(void);
+ void _port_exit_from_isr(void);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Returns a word encoding the current interrupts status.
+ *
+ * @return The interrupts status.
+ */
+static inline syssts_t port_get_irq_status(void) {
+
+ return (syssts_t)__get_PRIMASK();
+}
+
+/**
+ * @brief Checks the interrupt status.
+ *
+ * @param[in] sts the interrupt status word
+ *
+ * @return The interrupt status.
+ * @retval false the word specified a disabled interrupts status.
+ * @retval true the word specified an enabled interrupts status.
+ */
+static inline bool port_irq_enabled(syssts_t sts) {
+
+ return (sts & (syssts_t)1) == (syssts_t)0;
+}
+
+/**
+ * @brief Determines the current execution context.
+ *
+ * @return The execution context.
+ * @retval false not running in ISR mode.
+ * @retval true running in ISR mode.
+ */
+static inline bool port_is_isr_context(void) {
+
+ return (bool)((__get_IPSR() & 0x1FFU) != 0U);
+}
+
+/**
+ * @brief Kernel-lock action.
+ * @details In this port this function disables interrupts globally.
+ */
+static inline void port_lock(void) {
+
+ __disable_irq();
+}
+
+/**
+ * @brief Kernel-unlock action.
+ * @details In this port this function enables interrupts globally.
+ */
+static inline void port_unlock(void) {
+
+ __enable_irq();
+}
+
+/**
+ * @brief Kernel-lock action from an interrupt handler.
+ * @details In this port this function disables interrupts globally.
+ * @note Same as @p port_lock() in this port.
+ */
+static inline void port_lock_from_isr(void) {
+
+ port_lock();
+}
+
+/**
+ * @brief Kernel-unlock action from an interrupt handler.
+ * @details In this port this function enables interrupts globally.
+ * @note Same as @p port_lock() in this port.
+ */
+static inline void port_unlock_from_isr(void) {
+
+ port_unlock();
+}
+
+/**
+ * @brief Disables all the interrupt sources.
+ */
+static inline void port_disable(void) {
+
+ __disable_irq();
+}
+
+/**
+ * @brief Disables the interrupt sources below kernel-level priority.
+ */
+static inline void port_suspend(void) {
+
+ __disable_irq();
+}
+
+/**
+ * @brief Enables all the interrupt sources.
+ */
+static inline void port_enable(void) {
+
+ __enable_irq();
+}
+
+/**
+ * @brief Enters an architecture-dependent IRQ-waiting mode.
+ * @details The function is meant to return when an interrupt becomes pending.
+ * The simplest implementation is an empty function or macro but this
+ * would not take advantage of architecture-specific power saving
+ * modes.
+ * @note Implemented as an inlined @p WFI instruction.
+ */
+static inline void port_wait_for_interrupt(void) {
+
+#if CORTEX_ENABLE_WFI_IDLE == TRUE
+ __WFI();
+#endif
+}
+
+#endif /* _FROM_ASM_ */
+
+#endif /* CHCORE_V6M_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore_v7m.c b/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore_v7m.c
new file mode 100644
index 0000000..24c94a2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore_v7m.c
@@ -0,0 +1,391 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file chcore_v7m.c
+ * @brief ARMv7-M architecture port code.
+ *
+ * @addtogroup ARMCMx_V7M_CORE
+ * @{
+ */
+
+#include
+
+#include "ch.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module interrupt handlers. */
+/*===========================================================================*/
+
+#if (PORT_USE_SYSCALL == TRUE) || defined(__DOXYGEN__)
+__attribute__((noinline))
+void port_syslock_noinline(void) {
+
+ port_lock();
+ _stats_start_measure_crit_thd();
+ _dbg_check_lock();
+}
+
+uint32_t port_get_s_psp(void) {
+
+ return (uint32_t)currp->ctx.syscall.psp;
+}
+
+__attribute__((weak))
+void port_syscall(struct port_extctx *ctxp, uint32_t n) {
+
+ (void)ctxp;
+ (void)n;
+
+ chSysHalt("svc");
+}
+
+void port_unprivileged_jump(uint32_t pc, uint32_t psp) {
+ struct port_extctx *ectxp;
+ struct port_linkctx *lctxp;
+ uint32_t s_psp = __get_PSP();
+ uint32_t control = __get_CONTROL();
+
+ /* Creating a port_extctx context for user mode entry.*/
+ psp -= sizeof (struct port_extctx);
+ ectxp = (struct port_extctx *)psp;
+
+ /* Initializing the user mode entry context.*/
+ memset((void *)ectxp, 0, sizeof (struct port_extctx));
+ ectxp->pc = pc;
+ ectxp->xpsr = 0x01000000U;
+#if CORTEX_USE_FPU == TRUE
+ ectxp->fpscr = __get_FPSCR();
+#endif
+
+ /* Creating a middle context for user mode entry.*/
+ s_psp -= sizeof (struct port_linkctx);
+ lctxp = (struct port_linkctx *)s_psp;
+
+ /* CONTROL and PSP values for user mode.*/
+ lctxp->control = control | 1U;
+ lctxp->ectxp = ectxp;
+
+ /* PSP now points to the port_linkctx structure, it will be removed
+ by SVC.*/
+ __set_PSP(s_psp);
+
+ asm volatile ("svc 0");
+
+ chSysHalt("svc");
+}
+#endif
+
+#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__)
+/**
+ * @brief SVC vector.
+ * @details The SVC vector is used for exception mode re-entering after a
+ * context switch and, optionally, for system calls.
+ * @note The SVC vector is only used in advanced kernel mode.
+ */
+/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/
+void SVC_Handler(void) {
+/*lint -restore*/
+ uint32_t psp = __get_PSP();
+
+#if PORT_USE_SYSCALL == TRUE
+ uint32_t control;
+ /* Caller context.*/
+ struct port_extctx *ectxp = (struct port_extctx *)psp;
+
+#if defined(__GNUC__)
+ chDbgAssert(((uint32_t)__builtin_return_address(0) & 4U) != 0U,
+ "not process");
+#endif
+
+ /* Checking if the SVC instruction has been used from privileged or
+ non-privileged mode.*/
+ control = __get_CONTROL();
+ if ((control & 1U) != 0) {
+ /* From non-privileged mode, it must be handled as a syscall.*/
+ uint32_t n, s_psp;
+ struct port_linkctx *lctxp;
+ struct port_extctx *newctxp;
+
+ /* Supervisor PSP from the thread context structure.*/
+ s_psp = (uint32_t)currp->ctx.syscall.psp;
+
+ /* Pushing the port_linkctx into the supervisor stack.*/
+ s_psp -= sizeof (struct port_linkctx);
+ lctxp = (struct port_linkctx *)s_psp;
+ lctxp->control = control;
+ lctxp->ectxp = ectxp;
+
+ /* Enforcing privileged mode before returning.*/
+ __set_CONTROL(control & ~1U);
+
+ /* Number of the SVC instruction.*/
+ n = (uint32_t)*(((const uint16_t *)ectxp->pc) - 1U) & 255U;
+
+ /* Building an artificial return context, we need to make this
+ return in the syscall dispatcher in privileged mode.*/
+ s_psp -= sizeof (struct port_extctx);
+ __set_PSP(s_psp);
+ newctxp = (struct port_extctx *)s_psp;
+ newctxp->r0 = (uint32_t)ectxp;
+ newctxp->r1 = n;
+ newctxp->pc = (uint32_t)port_syscall;
+ newctxp->xpsr = 0x01000000U;
+#if CORTEX_USE_FPU == TRUE
+ newctxp->fpscr = FPU->FPDSCR;
+#endif
+ }
+ else
+#endif
+ {
+ /* From privileged mode, it is used for context discarding in the
+ preemption code.*/
+
+ /* Unstacking procedure, discarding the current exception context and
+ positioning the stack to point to the real one.*/
+ psp += sizeof (struct port_extctx);
+
+#if CORTEX_USE_FPU == TRUE
+ /* Enforcing unstacking of the FP part of the context.*/
+ FPU->FPCCR &= ~FPU_FPCCR_LSPACT_Msk;
+#endif
+
+#if PORT_USE_SYSCALL == TRUE
+ {
+ /* Restoring CONTROL and the original PSP position.*/
+ struct port_linkctx *lctxp = (struct port_linkctx *)psp;
+ __set_CONTROL((uint32_t)lctxp->control);
+ __set_PSP((uint32_t)lctxp->ectxp);
+ }
+#else
+
+ /* Restoring real position of the original stack frame.*/
+ __set_PSP(psp);
+#endif
+
+ /* Restoring the normal interrupts status.*/
+ port_unlock_from_isr();
+ }
+}
+#endif /* CORTEX_SIMPLIFIED_PRIORITY == FALSE */
+
+#if (CORTEX_SIMPLIFIED_PRIORITY == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief PendSV vector.
+ * @details The PendSV vector is used for exception mode re-entering after a
+ * context switch.
+ * @note The PendSV vector is only used in compact kernel mode.
+ */
+/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/
+void PendSV_Handler(void) {
+/*lint -restore*/
+ uint32_t psp = __get_PSP();
+
+#if CORTEX_USE_FPU
+ /* Enforcing unstacking of the FP part of the context.*/
+ FPU->FPCCR &= ~FPU_FPCCR_LSPACT_Msk;
+#endif
+
+ /* Discarding the current exception context and positioning the stack to
+ point to the real one.*/
+ psp += sizeof (struct port_extctx);
+
+#if PORT_USE_SYSCALL == TRUE
+ {
+ /* Restoring previous privileges by restoring CONTROL.*/
+ struct port_linkctx *lctxp = (struct port_linkctx *)psp;
+ __set_CONTROL((uint32_t)lctxp->control);
+ psp += sizeof (struct port_linkctx);
+ }
+#endif
+
+ /* Restoring real position of the original stack frame.*/
+ __set_PSP(psp);
+}
+#endif /* CORTEX_SIMPLIFIED_PRIORITY == TRUE */
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Port-related initialization code.
+ */
+void port_init(void) {
+
+ /* Starting in a known IRQ configuration.*/
+ port_suspend();
+
+ /* Initializing priority grouping.*/
+ NVIC_SetPriorityGrouping(CORTEX_PRIGROUP_INIT);
+
+ /* DWT cycle counter enable, note, the M7 requires DWT unlocking.*/
+ CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
+#if CORTEX_MODEL == 7
+ DWT->LAR = 0xC5ACCE55U;
+#endif
+ DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
+
+ /* Initialization of the system vectors used by the port.*/
+#if CORTEX_SIMPLIFIED_PRIORITY == FALSE
+ NVIC_SetPriority(SVCall_IRQn, CORTEX_PRIORITY_SVCALL);
+#endif
+ NVIC_SetPriority(PendSV_IRQn, CORTEX_PRIORITY_PENDSV);
+
+#if PORT_ENABLE_GUARD_PAGES == TRUE
+ {
+ extern stkalign_t __main_thread_stack_base__;
+
+ /* Setting up the guard page on the main() function stack base
+ initially.*/
+ mpuConfigureRegion(PORT_USE_GUARD_MPU_REGION,
+ &__main_thread_stack_base__,
+ MPU_RASR_ATTR_AP_NA_NA |
+ MPU_RASR_ATTR_NON_CACHEABLE |
+ MPU_RASR_SIZE_32 |
+ MPU_RASR_ENABLE);
+ }
+#endif
+
+#if PORT_USE_SYSCALL == TRUE
+ /* MPU is enabled.*/
+ mpuEnable(MPU_CTRL_PRIVDEFENA);
+#endif
+}
+
+#if ((CH_DBG_ENABLE_STACK_CHECK == TRUE) && \
+ (PORT_ENABLE_GUARD_PAGES == TRUE)) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief Setting up MPU region for the current thread.
+ */
+void _port_set_region(void) {
+
+ mpuSetRegionAddress(PORT_USE_GUARD_MPU_REGION,
+ chThdGetSelfX()->wabase);
+}
+#endif
+
+/**
+ * @brief Exception exit redirection to _port_switch_from_isr().
+ */
+void _port_irq_epilogue(void) {
+
+ port_lock_from_isr();
+ if ((SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) != 0U) {
+ struct port_extctx *ectxp;
+ uint32_t s_psp;
+
+#if CORTEX_USE_FPU == TRUE
+ /* Enforcing a lazy FPU state save by accessing the FPCSR register.*/
+ (void) __get_FPSCR();
+#endif
+
+#if PORT_USE_SYSCALL == TRUE
+ {
+ struct port_linkctx *lctxp;
+ uint32_t control = __get_CONTROL();
+
+ /* Checking if the IRQ has been served in unprivileged mode.*/
+ if ((control & 1U) != 0U) {
+ /* Unprivileged mode, switching to privileged mode.*/
+ __set_CONTROL(control & ~1U);
+
+ /* Switching to S-PSP taking it from the thread context.*/
+ s_psp = (uint32_t)currp->ctx.syscall.psp;
+
+ /* Pushing the middle context for returning to the original frame
+ and mode.*/
+ s_psp = s_psp - sizeof (struct port_linkctx);
+ lctxp = (struct port_linkctx *)s_psp;
+ lctxp->control = control;
+ lctxp->ectxp = (struct port_extctx *)__get_PSP();
+ }
+ else {
+ /* Privileged mode, we are already on S-PSP.*/
+ uint32_t psp = __get_PSP();
+
+ /* Pushing the middle context for returning to the original frame
+ and mode.*/
+ s_psp = psp - sizeof (struct port_linkctx);
+ lctxp = (struct port_linkctx *)s_psp;
+ lctxp->control = control;
+ lctxp->ectxp = (struct port_extctx *)psp;
+ }
+ }
+#else
+ s_psp = __get_PSP();
+#endif
+
+ /* Adding an artificial exception return context, there is no need to
+ populate it fully.*/
+ s_psp -= sizeof (struct port_extctx);
+
+ /* The port_extctx structure is pointed by the S-PSP register.*/
+ ectxp = (struct port_extctx *)s_psp;
+
+ /* Setting up a fake XPSR register value.*/
+ ectxp->xpsr = 0x01000000U;
+#if CORTEX_USE_FPU == TRUE
+ ectxp->fpscr = FPU->FPDSCR;
+#endif
+
+ /* Writing back the modified S-PSP value.*/
+ __set_PSP(s_psp);
+
+ /* The exit sequence is different depending on if a preemption is
+ required or not.*/
+ if (chSchIsPreemptionRequired()) {
+ /* Preemption is required we need to enforce a context switch.*/
+ ectxp->pc = (uint32_t)_port_switch_from_isr;
+ }
+ else {
+ /* Preemption not required, we just need to exit the exception
+ atomically.*/
+ ectxp->pc = (uint32_t)_port_exit_from_isr;
+ }
+
+ /* Note, returning without unlocking is intentional, this is done in
+ order to keep the rest of the context switch atomic.*/
+ return;
+ }
+ port_unlock_from_isr();
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore_v7m.h b/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore_v7m.h
new file mode 100644
index 0000000..2c39a4f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/chcore_v7m.h
@@ -0,0 +1,790 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file chcore_v7m.h
+ * @brief ARMv7-M architecture port macros and structures.
+ *
+ * @addtogroup ARMCMx_V7M_CORE
+ * @{
+ */
+
+#ifndef CHCORE_V7M_H
+#define CHCORE_V7M_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Port Capabilities and Constants
+ * @{
+ */
+/**
+ * @brief This port supports a realtime counter.
+ */
+#define PORT_SUPPORTS_RT TRUE
+
+/**
+ * @brief Natural alignment constant.
+ * @note It is the minimum alignment for pointer-size variables.
+ */
+#define PORT_NATURAL_ALIGN sizeof (void *)
+
+/**
+ * @brief Stack alignment constant.
+ * @note It is the alignment required for the stack pointer.
+ */
+#define PORT_STACK_ALIGN sizeof (stkalign_t)
+
+/**
+ * @brief Working Areas alignment constant.
+ * @note It is the alignment to be enforced for thread working areas.
+ */
+#define PORT_WORKING_AREA_ALIGN ((PORT_ENABLE_GUARD_PAGES == TRUE) ?\
+ 32U : PORT_STACK_ALIGN)
+/** @} */
+
+/**
+ * @brief Disabled value for BASEPRI register.
+ */
+#define CORTEX_BASEPRI_DISABLED 0U
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Implements a syscall interface on SVC.
+ */
+#if !defined(PORT_USE_SYSCALL) || defined(__DOXYGEN__)
+#define PORT_USE_SYSCALL FALSE
+#endif
+
+/**
+ * @brief Number of MPU regions to be saved/restored during context switch.
+ * @note The first region is always region zero.
+ * @note The use of this option has an overhead of 8 bytes for each
+ * region for each thread.
+ * @note Allowed values are 0..4, zero means none.
+ */
+#if !defined(PORT_SWITCHED_REGIONS_NUMBER) || defined(__DOXYGEN__)
+#define PORT_SWITCHED_REGIONS_NUMBER 0
+#endif
+
+/**
+ * @brief Enables stack overflow guard pages using MPU.
+ * @note This option can only be enabled if also option
+ * @p CH_DBG_ENABLE_STACK_CHECK is enabled.
+ * @note The use of this option has an overhead of 32 bytes for each
+ * thread.
+ */
+#if !defined(PORT_ENABLE_GUARD_PAGES) || defined(__DOXYGEN__)
+#define PORT_ENABLE_GUARD_PAGES FALSE
+#endif
+
+/**
+ * @brief MPU region to be used to stack guards.
+ * @note Make sure this region is not included in the
+ * @p PORT_SWITCHED_REGIONS_NUMBER regions range.
+ */
+#if !defined(PORT_USE_GUARD_MPU_REGION) || defined(__DOXYGEN__)
+#define PORT_USE_GUARD_MPU_REGION MPU_REGION_7
+#endif
+
+/**
+ * @brief Stack size for the system idle thread.
+ * @details This size depends on the idle thread implementation, usually
+ * the idle thread should take no more space than those reserved
+ * by @p PORT_INT_REQUIRED_STACK.
+ * @note In this port it is set to 16 because the idle thread does have
+ * a stack frame when compiling without optimizations. You may
+ * reduce this value to zero when compiling with optimizations.
+ */
+#if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__)
+#define PORT_IDLE_THREAD_STACK_SIZE 16
+#endif
+
+/**
+ * @brief Per-thread stack overhead for interrupts servicing.
+ * @details This constant is used in the calculation of the correct working
+ * area size.
+ * @note In this port this value is conservatively set to 64 because the
+ * function @p chSchDoReschedule() can have a stack frame, especially
+ * with compiler optimizations disabled. The value can be reduced
+ * when compiler optimizations are enabled.
+ */
+#if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__)
+#define PORT_INT_REQUIRED_STACK 64
+#endif
+
+/**
+ * @brief Enables the use of the WFI instruction in the idle thread loop.
+ */
+#if !defined(CORTEX_ENABLE_WFI_IDLE)
+#define CORTEX_ENABLE_WFI_IDLE FALSE
+#endif
+
+/**
+ * @brief FPU support in context switch.
+ * @details Activating this option activates the FPU support in the kernel.
+ */
+#if !defined(CORTEX_USE_FPU)
+#define CORTEX_USE_FPU CORTEX_HAS_FPU
+#elif (CORTEX_USE_FPU == TRUE) && (CORTEX_HAS_FPU == FALSE)
+/* This setting requires an FPU presence check in case it is externally
+ redefined.*/
+#error "the selected core does not have an FPU"
+#endif
+
+/**
+ * @brief Simplified priority handling flag.
+ * @details Activating this option makes the Kernel work in compact mode.
+ * In compact mode interrupts are disabled globally instead of
+ * raising the priority mask to some intermediate level.
+ */
+#if !defined(CORTEX_SIMPLIFIED_PRIORITY)
+#define CORTEX_SIMPLIFIED_PRIORITY FALSE
+#endif
+
+/**
+ * @brief SVCALL handler priority.
+ * @note The default SVCALL handler priority is defaulted to
+ * @p CORTEX_MAXIMUM_PRIORITY+1, this reserves the
+ * @p CORTEX_MAXIMUM_PRIORITY priority level as fast interrupts
+ * priority level.
+ */
+#if !defined(CORTEX_PRIORITY_SVCALL)
+#define CORTEX_PRIORITY_SVCALL (CORTEX_MAXIMUM_PRIORITY + 1U)
+#elif !PORT_IRQ_IS_VALID_PRIORITY(CORTEX_PRIORITY_SVCALL)
+/* If it is externally redefined then better perform a validity check on it.*/
+#error "invalid priority level specified for CORTEX_PRIORITY_SVCALL"
+#endif
+
+/**
+ * @brief NVIC PRIGROUP initialization expression.
+ * @details The default assigns all available priority bits as preemption
+ * priority with no sub-priority.
+ */
+#if !defined(CORTEX_PRIGROUP_INIT) || defined(__DOXYGEN__)
+#define CORTEX_PRIGROUP_INIT (7 - CORTEX_PRIORITY_BITS)
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if (PORT_SWITCHED_REGIONS_NUMBER < 0) || (PORT_SWITCHED_REGIONS_NUMBER > 4)
+#error "invalid PORT_SWITCHED_REGIONS_NUMBER value"
+#endif
+
+#if !defined(_FROM_ASM_)
+/**
+ * @brief MPU guard page size.
+ */
+#if (PORT_ENABLE_GUARD_PAGES == TRUE) || defined(__DOXYGEN__)
+ #if CH_DBG_ENABLE_STACK_CHECK == FALSE
+ #error "PORT_ENABLE_GUARD_PAGES requires CH_DBG_ENABLE_STACK_CHECK"
+ #endif
+ #if __MPU_PRESENT == 0
+ #error "MPU not present in current device"
+ #endif
+ #define PORT_GUARD_PAGE_SIZE 32U
+#else
+ #define PORT_GUARD_PAGE_SIZE 0U
+#endif
+#endif /* !defined(_FROM_ASM_) */
+
+/**
+ * @name Architecture and Compiler
+ * @{
+ */
+#if (CORTEX_MODEL == 3) || defined(__DOXYGEN__)
+
+ #if !defined(CH_CUSTOMER_LIC_PORT_CM3)
+ #error "CH_CUSTOMER_LIC_PORT_CM3 not defined"
+ #endif
+
+ #if CH_CUSTOMER_LIC_PORT_CM3 == FALSE
+ #error "ChibiOS Cortex-M3 port not licensed"
+ #endif
+
+/**
+ * @brief Macro defining the specific ARM architecture.
+ */
+#define PORT_ARCHITECTURE_ARM_v7M
+
+/**
+ * @brief Name of the implemented architecture.
+ */
+#define PORT_ARCHITECTURE_NAME "ARMv7-M"
+
+/**
+ * @brief Name of the architecture variant.
+ */
+#if (PORT_ENABLE_GUARD_PAGES == FALSE) || defined(__DOXYGEN__)
+ #define PORT_CORE_VARIANT_NAME "Cortex-M3"
+#else
+ #define PORT_CORE_VARIANT_NAME "Cortex-M3 (MPU)"
+#endif
+
+#elif (CORTEX_MODEL == 4)
+
+ #if !defined(CH_CUSTOMER_LIC_PORT_CM4)
+ #error "CH_CUSTOMER_LIC_PORT_CM4 not defined"
+ #endif
+
+ #if CH_CUSTOMER_LIC_PORT_CM4 == FALSE
+ #error "ChibiOS Cortex-M4 port not licensed"
+ #endif
+
+ #define PORT_ARCHITECTURE_ARM_v7ME
+ #define PORT_ARCHITECTURE_NAME "ARMv7E-M"
+ #if CORTEX_USE_FPU
+ #if PORT_ENABLE_GUARD_PAGES == FALSE
+ #define PORT_CORE_VARIANT_NAME "Cortex-M4F"
+ #else
+ #define PORT_CORE_VARIANT_NAME "Cortex-M4F (MPU)"
+ #endif
+ #else
+ #if PORT_ENABLE_GUARD_PAGES == FALSE
+ #define PORT_CORE_VARIANT_NAME "Cortex-M4"
+ #else
+ #define PORT_CORE_VARIANT_NAME "Cortex-M4 (MPU)"
+ #endif
+ #endif
+
+#elif (CORTEX_MODEL == 7)
+
+ #if !defined(CH_CUSTOMER_LIC_PORT_CM7)
+ #error "CH_CUSTOMER_LIC_PORT_CM7 not defined"
+ #endif
+
+ #if CH_CUSTOMER_LIC_PORT_CM7 == FALSE
+ #error "ChibiOS Cortex-M7 port not licensed"
+ #endif
+
+#define PORT_ARCHITECTURE_ARM_v7ME
+ #define PORT_ARCHITECTURE_NAME "ARMv7E-M"
+ #if CORTEX_USE_FPU
+ #if PORT_ENABLE_GUARD_PAGES == FALSE
+ #define PORT_CORE_VARIANT_NAME "Cortex-M7F"
+ #else
+ #define PORT_CORE_VARIANT_NAME "Cortex-M7F (MPU)"
+ #endif
+ #else
+ #if PORT_ENABLE_GUARD_PAGES == FALSE
+ #define PORT_CORE_VARIANT_NAME "Cortex-M7"
+ #else
+ #define PORT_CORE_VARIANT_NAME "Cortex-M7 (MPU)"
+ #endif
+ #endif
+#endif
+
+/**
+ * @brief Port-specific information string.
+ */
+#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__)
+#define PORT_INFO "Advanced kernel mode"
+#else
+#define PORT_INFO "Compact kernel mode"
+#endif
+/** @} */
+
+#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__)
+/**
+ * @brief Maximum usable priority for normal ISRs.
+ */
+#define CORTEX_MAX_KERNEL_PRIORITY (CORTEX_PRIORITY_SVCALL + 1U)
+
+/**
+ * @brief BASEPRI level within kernel lock.
+ */
+#define CORTEX_BASEPRI_KERNEL \
+ CORTEX_PRIO_MASK(CORTEX_MAX_KERNEL_PRIORITY)
+#else
+
+#define CORTEX_MAX_KERNEL_PRIORITY 0U
+#endif
+
+/**
+ * @brief PendSV priority level.
+ * @note This priority is enforced to be equal to
+ * @p CORTEX_MAX_KERNEL_PRIORITY, this handler always have the
+ * highest priority that cannot preempt the kernel.
+ */
+#define CORTEX_PRIORITY_PENDSV CORTEX_MAX_KERNEL_PRIORITY
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/* The documentation of the following declarations is in chconf.h in order
+ to not have duplicated structure names into the documentation.*/
+#if !defined(__DOXYGEN__)
+struct port_extctx {
+ uint32_t r0;
+ uint32_t r1;
+ uint32_t r2;
+ uint32_t r3;
+ uint32_t r12;
+ uint32_t lr_thd;
+ uint32_t pc;
+ uint32_t xpsr;
+#if CORTEX_USE_FPU
+ uint32_t s0;
+ uint32_t s1;
+ uint32_t s2;
+ uint32_t s3;
+ uint32_t s4;
+ uint32_t s5;
+ uint32_t s6;
+ uint32_t s7;
+ uint32_t s8;
+ uint32_t s9;
+ uint32_t s10;
+ uint32_t s11;
+ uint32_t s12;
+ uint32_t s13;
+ uint32_t s14;
+ uint32_t s15;
+ uint32_t fpscr;
+ uint32_t reserved;
+#endif /* CORTEX_USE_FPU */
+};
+
+#if (PORT_USE_SYSCALL == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Link context structure.
+ * @details This structure is used when there is the need to save extra
+ * context information that is not part of the registers stacked
+ * in HW.
+ */
+struct port_linkctx {
+ uint32_t control;
+ struct port_extctx *ectxp;
+};
+#endif
+
+struct port_intctx {
+#if (PORT_SWITCHED_REGIONS_NUMBER > 0) || defined(__DOXYGEN__)
+ struct {
+ uint32_t rbar;
+ uint32_t rasr;
+ } regions[PORT_SWITCHED_REGIONS_NUMBER];
+#endif
+#if CORTEX_USE_FPU
+ uint32_t s16;
+ uint32_t s17;
+ uint32_t s18;
+ uint32_t s19;
+ uint32_t s20;
+ uint32_t s21;
+ uint32_t s22;
+ uint32_t s23;
+ uint32_t s24;
+ uint32_t s25;
+ uint32_t s26;
+ uint32_t s27;
+ uint32_t s28;
+ uint32_t s29;
+ uint32_t s30;
+ uint32_t s31;
+#endif /* CORTEX_USE_FPU */
+ uint32_t r4;
+ uint32_t r5;
+ uint32_t r6;
+ uint32_t r7;
+ uint32_t r8;
+ uint32_t r9;
+ uint32_t r10;
+ uint32_t r11;
+ uint32_t lr;
+};
+
+struct port_context {
+ struct port_intctx *sp;
+#if (PORT_USE_SYSCALL == TRUE) || defined(__DOXYGEN__)
+ struct {
+ uint32_t psp;
+ const void *p;
+ } syscall;
+#endif
+};
+#endif /* !defined(__DOXYGEN__) */
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/* By default threads have no syscall context information.*/
+#if (PORT_USE_SYSCALL == TRUE) || defined(__DOXYGEN__)
+#define __PORT_SETUP_CONTEXT_SYSCALL(tp, wtop) \
+ (tp)->ctx.syscall.psp = (uint32_t)(wtop); \
+ (tp)->ctx.syscall.p = NULL;
+#else
+#define __PORT_SETUP_CONTEXT_SYSCALL(tp, wtop)
+#endif
+
+/* By default threads have all regions disabled.*/
+#if (PORT_SWITCHED_REGIONS_NUMBER == 0) || defined(__DOXYGEN__)
+#define __PORT_SETUP_CONTEXT_MPU(tp)
+#elif (PORT_SWITCHED_REGIONS_NUMBER == 1) || defined(__DOXYGEN__)
+#define __PORT_SETUP_CONTEXT_MPU(tp) \
+ (tp)->ctx.sp->regions[0].rbar = 0U; \
+ (tp)->ctx.sp->regions[0].rasr = 0U
+#elif (PORT_SWITCHED_REGIONS_NUMBER == 2) || defined(__DOXYGEN__)
+#define __PORT_SETUP_CONTEXT_MPU(tp) \
+ (tp)->ctx.sp->regions[0].rbar = 0U; \
+ (tp)->ctx.sp->regions[0].rasr = 0U; \
+ (tp)->ctx.sp->regions[1].rbar = 0U; \
+ (tp)->ctx.sp->regions[1].rasr = 0U
+#elif (PORT_SWITCHED_REGIONS_NUMBER == 3) || defined(__DOXYGEN__)
+#define __PORT_SETUP_CONTEXT_MPU(tp) \
+ (tp)->ctx.sp->regions[0].rbar = 0U; \
+ (tp)->ctx.sp->regions[0].rasr = 0U; \
+ (tp)->ctx.sp->regions[1].rbar = 0U; \
+ (tp)->ctx.sp->regions[1].rasr = 0U; \
+ (tp)->ctx.sp->regions[2].rbar = 0U; \
+ (tp)->ctx.sp->regions[2].rasr = 0U
+#elif (PORT_SWITCHED_REGIONS_NUMBER == 4) || defined(__DOXYGEN__)
+#define __PORT_SETUP_CONTEXT_MPU(tp) \
+ (tp)->ctx.sp->regions[0].rbar = 0U; \
+ (tp)->ctx.sp->regions[0].rasr = 0U; \
+ (tp)->ctx.sp->regions[1].rbar = 0U; \
+ (tp)->ctx.sp->regions[1].rasr = 0U; \
+ (tp)->ctx.sp->regions[2].rbar = 0U; \
+ (tp)->ctx.sp->regions[2].rasr = 0U; \
+ (tp)->ctx.sp->regions[3].rbar = 0U; \
+ (tp)->ctx.sp->regions[3].rasr = 0U
+#else
+#endif
+
+/**
+ * @brief Platform dependent part of the @p chThdCreateI() API.
+ * @details This code usually setup the context switching frame represented
+ * by an @p port_intctx structure.
+ */
+#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \
+ (tp)->ctx.sp = (struct port_intctx *)((uint8_t *)(wtop) - \
+ sizeof (struct port_intctx)); \
+ (tp)->ctx.sp->r4 = (uint32_t)(pf); \
+ (tp)->ctx.sp->r5 = (uint32_t)(arg); \
+ (tp)->ctx.sp->lr = (uint32_t)_port_thread_start; \
+ __PORT_SETUP_CONTEXT_MPU(tp); \
+ __PORT_SETUP_CONTEXT_SYSCALL(tp, wtop); \
+}
+
+// __PORT_SETUP_CONTEXT_MPU(tp)
+
+/**
+ * @brief Computes the thread working area global size.
+ * @note There is no need to perform alignments in this macro.
+ */
+#define PORT_WA_SIZE(n) ((size_t)PORT_GUARD_PAGE_SIZE + \
+ sizeof (struct port_intctx) + \
+ sizeof (struct port_extctx) + \
+ (size_t)(n) + \
+ (size_t)PORT_INT_REQUIRED_STACK)
+
+/**
+ * @brief Static working area allocation.
+ * @details This macro is used to allocate a static thread working area
+ * aligned as both position and size.
+ *
+ * @param[in] s the name to be assigned to the stack array
+ * @param[in] n the stack size to be assigned to the thread
+ */
+#if (PORT_ENABLE_GUARD_PAGES == FALSE) || defined(__DOXYGEN__)
+#define PORT_WORKING_AREA(s, n) \
+ stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)]
+#else
+#define PORT_WORKING_AREA(s, n) \
+ ALIGNED_VAR(32) stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)]
+#endif
+
+/**
+ * @brief IRQ prologue code.
+ * @details This macro must be inserted at the start of all IRQ handlers
+ * enabled to invoke system APIs.
+ */
+#define PORT_IRQ_PROLOGUE()
+
+/**
+ * @brief IRQ epilogue code.
+ * @details This macro must be inserted at the end of all IRQ handlers
+ * enabled to invoke system APIs.
+ */
+#define PORT_IRQ_EPILOGUE() _port_irq_epilogue()
+
+/**
+ * @brief IRQ handler function declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ */
+#ifdef __cplusplus
+#define PORT_IRQ_HANDLER(id) extern "C" void id(void)
+#else
+#define PORT_IRQ_HANDLER(id) void id(void)
+#endif
+
+/**
+ * @brief Fast IRQ handler function declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ */
+#ifdef __cplusplus
+#define PORT_FAST_IRQ_HANDLER(id) extern "C" void id(void)
+#else
+#define PORT_FAST_IRQ_HANDLER(id) void id(void)
+#endif
+
+/**
+ * @brief Performs a context switch between two threads.
+ * @details This is the most critical code in any port, this function
+ * is responsible for the context switch between 2 threads.
+ * @note The implementation of this code affects directly the context
+ * switch performance so optimize here as much as you can.
+ *
+ * @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread to be switched out
+ */
+#if (CH_DBG_ENABLE_STACK_CHECK == FALSE) || defined(__DOXYGEN__)
+#define port_switch(ntp, otp) _port_switch(ntp, otp)
+#else
+#if PORT_ENABLE_GUARD_PAGES == FALSE
+#define port_switch(ntp, otp) { \
+ struct port_intctx *r13 = (struct port_intctx *)__get_PSP(); \
+ if ((stkalign_t *)(r13 - 1) < (otp)->wabase) { \
+ chSysHalt("stack overflow"); \
+ } \
+ _port_switch(ntp, otp); \
+}
+#else
+#define port_switch(ntp, otp) { \
+ _port_switch(ntp, otp); \
+ \
+ /* Setting up the guard page for the switched-in thread.*/ \
+ mpuSetRegionAddress(PORT_USE_GUARD_MPU_REGION, \
+ chThdGetSelfX()->wabase); \
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void port_init(void);
+ void _port_irq_epilogue(void);
+ void _port_switch(thread_t *ntp, thread_t *otp);
+ void _port_thread_start(void);
+ void _port_switch_from_isr(void);
+ void _port_exit_from_isr(void);
+#if PORT_USE_SYSCALL == TRUE
+ void port_unprivileged_jump(uint32_t pc, uint32_t psp);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Returns a word encoding the current interrupts status.
+ *
+ * @return The interrupts status.
+ */
+__STATIC_FORCEINLINE syssts_t port_get_irq_status(void) {
+ syssts_t sts;
+
+#if CORTEX_SIMPLIFIED_PRIORITY == FALSE
+ sts = (syssts_t)__get_BASEPRI();
+#else /* CORTEX_SIMPLIFIED_PRIORITY */
+ sts = (syssts_t)__get_PRIMASK();
+#endif /* CORTEX_SIMPLIFIED_PRIORITY */
+ return sts;
+}
+
+/**
+ * @brief Checks the interrupt status.
+ *
+ * @param[in] sts the interrupt status word
+ *
+ * @return The interrupt status.
+ * @retval false the word specified a disabled interrupts status.
+ * @retval true the word specified an enabled interrupts status.
+ */
+__STATIC_FORCEINLINE bool port_irq_enabled(syssts_t sts) {
+
+#if CORTEX_SIMPLIFIED_PRIORITY == FALSE
+ return sts == (syssts_t)CORTEX_BASEPRI_DISABLED;
+#else /* CORTEX_SIMPLIFIED_PRIORITY */
+ return (sts & (syssts_t)1) == (syssts_t)0;
+#endif /* CORTEX_SIMPLIFIED_PRIORITY */
+}
+
+/**
+ * @brief Determines the current execution context.
+ *
+ * @return The execution context.
+ * @retval false not running in ISR mode.
+ * @retval true running in ISR mode.
+ */
+__STATIC_FORCEINLINE bool port_is_isr_context(void) {
+
+ return (bool)((__get_IPSR() & 0x1FFU) != 0U);
+}
+
+/**
+ * @brief Kernel-lock action.
+ * @details In this port this function raises the base priority to kernel
+ * level.
+ */
+__STATIC_FORCEINLINE void port_lock(void) {
+
+#if CORTEX_SIMPLIFIED_PRIORITY == FALSE
+#if defined(__CM7_REV)
+#if __CM7_REV <= 1
+ __disable_irq();
+#endif
+#endif
+ __set_BASEPRI(CORTEX_BASEPRI_KERNEL);
+#if defined(__CM7_REV)
+#if __CM7_REV <= 1
+ __enable_irq();
+#endif
+#endif
+#else /* CORTEX_SIMPLIFIED_PRIORITY */
+ __disable_irq();
+#endif /* CORTEX_SIMPLIFIED_PRIORITY */
+}
+
+/**
+ * @brief Kernel-unlock action.
+ * @details In this port this function lowers the base priority to user
+ * level.
+ */
+__STATIC_FORCEINLINE void port_unlock(void) {
+
+#if CORTEX_SIMPLIFIED_PRIORITY == FALSE
+ __set_BASEPRI(CORTEX_BASEPRI_DISABLED);
+#else /* CORTEX_SIMPLIFIED_PRIORITY */
+ __enable_irq();
+#endif /* CORTEX_SIMPLIFIED_PRIORITY */
+}
+
+/**
+ * @brief Kernel-lock action from an interrupt handler.
+ * @details In this port this function raises the base priority to kernel
+ * level.
+ * @note Same as @p port_lock() in this port.
+ */
+__STATIC_FORCEINLINE void port_lock_from_isr(void) {
+
+ port_lock();
+}
+
+/**
+ * @brief Kernel-unlock action from an interrupt handler.
+ * @details In this port this function lowers the base priority to user
+ * level.
+ * @note Same as @p port_unlock() in this port.
+ */
+__STATIC_FORCEINLINE void port_unlock_from_isr(void) {
+
+ port_unlock();
+}
+
+/**
+ * @brief Disables all the interrupt sources.
+ * @note In this port it disables all the interrupt sources by raising
+ * the priority mask to level 0.
+ */
+__STATIC_FORCEINLINE void port_disable(void) {
+
+ __disable_irq();
+}
+
+/**
+ * @brief Disables the interrupt sources below kernel-level priority.
+ * @note Interrupt sources above kernel level remains enabled.
+ * @note In this port it raises/lowers the base priority to kernel level.
+ */
+__STATIC_FORCEINLINE void port_suspend(void) {
+
+#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__)
+ __set_BASEPRI(CORTEX_BASEPRI_KERNEL);
+ __enable_irq();
+#else
+ __disable_irq();
+#endif
+}
+
+/**
+ * @brief Enables all the interrupt sources.
+ * @note In this port it lowers the base priority to user level.
+ */
+__STATIC_FORCEINLINE void port_enable(void) {
+
+#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__)
+ __set_BASEPRI(CORTEX_BASEPRI_DISABLED);
+#endif
+ __enable_irq();
+}
+
+/**
+ * @brief Enters an architecture-dependent IRQ-waiting mode.
+ * @details The function is meant to return when an interrupt becomes pending.
+ * The simplest implementation is an empty function or macro but this
+ * would not take advantage of architecture-specific power saving
+ * modes.
+ * @note Implemented as an inlined @p WFI instruction.
+ */
+__STATIC_FORCEINLINE void port_wait_for_interrupt(void) {
+
+#if CORTEX_ENABLE_WFI_IDLE == TRUE
+ __WFI();
+#endif
+}
+
+/**
+ * @brief Returns the current value of the realtime counter.
+ *
+ * @return The realtime counter value.
+ */
+__STATIC_FORCEINLINE rtcnt_t port_rt_get_counter_value(void) {
+
+ return DWT->CYCCNT;
+}
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CHCORE_V7M_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.S b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.S
new file mode 100644
index 0000000..115559e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.S
@@ -0,0 +1,154 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file compilers/GCC/chcoreasm_v6m.S
+ * @brief ARMv6-M architecture port low level code.
+ *
+ * @addtogroup ARMCMx_GCC_CORE
+ * @{
+ */
+
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+
+#define _FROM_ASM_
+#include "chlicense.h"
+#include "chconf.h"
+#include "chcore.h"
+
+#if !defined(__DOXYGEN__)
+
+/*
+ * RTOS-specific context offset.
+ */
+#if defined(_CHIBIOS_RT_CONF_)
+#define CONTEXT_OFFSET 12
+#elif defined(_CHIBIOS_NIL_CONF_)
+#define CONTEXT_OFFSET 0
+#else
+#error "invalid chconf.h"
+#endif
+
+ .set SCB_ICSR, 0xE000ED04
+ .set ICSR_PENDSVSET, 0x10000000
+ .set ICSR_NMIPENDSET, 0x80000000
+
+ .cpu cortex-m0
+ .fpu softvfp
+
+ .thumb
+ .text
+
+/*--------------------------------------------------------------------------*
+ * Performs a context switch between two threads.
+ *--------------------------------------------------------------------------*/
+ .thumb_func
+ .globl _port_switch
+_port_switch:
+ push {r4, r5, r6, r7, lr}
+ mov r4, r8
+ mov r5, r9
+ mov r6, r10
+ mov r7, r11
+ push {r4, r5, r6, r7}
+
+ mov r3, sp
+ str r3, [r1, #CONTEXT_OFFSET]
+ ldr r3, [r0, #CONTEXT_OFFSET]
+ mov sp, r3
+
+ pop {r4, r5, r6, r7}
+ mov r8, r4
+ mov r9, r5
+ mov r10, r6
+ mov r11, r7
+ pop {r4, r5, r6, r7, pc}
+
+/*--------------------------------------------------------------------------*
+ * Start a thread by invoking its work function.
+ *
+ * Threads execution starts here, the code leaves the system critical zone
+ * and then jumps into the thread function passed in register R4. The
+ * register R5 contains the thread parameter. The function chThdExit() is
+ * called on thread function return.
+ *--------------------------------------------------------------------------*/
+ .thumb_func
+ .globl _port_thread_start
+_port_thread_start:
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_unlock
+#endif
+#if CH_DBG_STATISTICS
+ bl _stats_stop_measure_crit_thd
+#endif
+ cpsie i
+ mov r0, r5
+ blx r4
+ movs r0, #0 /* MSG_OK */
+ bl chThdExit
+_zombies: b _zombies
+
+/*--------------------------------------------------------------------------*
+ * Post-IRQ switch code.
+ *
+ * Exception handlers return here for context switching.
+ *--------------------------------------------------------------------------*/
+ .thumb_func
+ .globl _port_switch_from_isr
+_port_switch_from_isr:
+#if CH_DBG_STATISTICS
+ bl _stats_start_measure_crit_thd
+#endif
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_lock
+#endif
+ bl chSchDoReschedule
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_unlock
+#endif
+#if CH_DBG_STATISTICS
+ bl _stats_stop_measure_crit_thd
+#endif
+ .globl _port_exit_from_isr
+_port_exit_from_isr:
+ ldr r2, .L2
+ ldr r3, .L3
+ str r3, [r2, #0]
+#if CORTEX_ALTERNATE_SWITCH
+ cpsie i
+#endif
+.L1: b .L1
+
+ .align 2
+.L2: .word SCB_ICSR
+#if CORTEX_ALTERNATE_SWITCH
+.L3: .word ICSR_PENDSVSET
+#else
+.L3: .word ICSR_NMIPENDSET
+#endif
+
+#endif /* !defined(__DOXYGEN__) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.S b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.S
new file mode 100644
index 0000000..0833de6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.S
@@ -0,0 +1,242 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file compilers/GCC/chcoreasm_v7m.S
+ * @brief ARMv7-M architecture port low level code.
+ *
+ * @addtogroup ARMCMx_GCC_CORE
+ * @{
+ */
+
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+
+#define _FROM_ASM_
+#include "chlicense.h"
+#include "chconf.h"
+#include "chcore.h"
+
+#if !defined(__DOXYGEN__)
+
+/*
+ * RTOS-specific context offset.
+ */
+#if defined(_CHIBIOS_RT_CONF_)
+#define CONTEXT_OFFSET 12
+#elif defined(_CHIBIOS_NIL_CONF_)
+#define CONTEXT_OFFSET 0
+#else
+#error "invalid chconf.h"
+#endif
+
+/* MPU-related constants.*/
+#define MPU_RBAR 0xE000ED9C
+
+/* Other constants.*/
+#define SCB_ICSR 0xE000ED04
+#define ICSR_PENDSVSET 0x10000000
+
+ .syntax unified
+ .cpu cortex-m4
+#if CORTEX_USE_FPU
+ .fpu fpv4-sp-d16
+#else
+ .fpu softvfp
+#endif
+
+ .thumb
+ .text
+
+/*--------------------------------------------------------------------------*
+ * Performs a context switch between two threads.
+ *--------------------------------------------------------------------------*/
+ .thumb_func
+ .globl _port_switch
+_port_switch:
+ push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
+#if CORTEX_USE_FPU
+ /* Saving FPU context.*/
+ vpush {s16-s31}
+#endif
+
+#if PORT_SWITCHED_REGIONS_NUMBER > 0
+ /* Saving MPU context.*/
+ ldr r2, =MPU_RBAR
+#if PORT_SWITCHED_REGIONS_NUMBER >= 1
+ mov r3, #0
+ str r3, [r2, #-4] /* RNR */
+ ldm r2, {r4, r5} /* RBAR, RASR */
+#endif
+#if PORT_SWITCHED_REGIONS_NUMBER >= 2
+ add r3, #1
+ str r3, [r2, #-4] /* RNR */
+ ldm r2, {r6, r7} /* RBAR, RASR */
+#endif
+#if PORT_SWITCHED_REGIONS_NUMBER >= 3
+ add r3, #1
+ str r3, [r2, #-4] /* RNR */
+ ldm r2, {r8, r9} /* RBAR, RASR */
+#endif
+#if PORT_SWITCHED_REGIONS_NUMBER >= 4
+ add r3, #1
+ str r3, [r2, #-4] /* RNR */
+ ldm r2, {r10, r11} /* RBAR, RASR */
+#endif
+#if PORT_SWITCHED_REGIONS_NUMBER == 1
+ push {r4, r5}
+#endif
+#if PORT_SWITCHED_REGIONS_NUMBER == 2
+ push {r4, r5, r6, r7}
+#endif
+#if PORT_SWITCHED_REGIONS_NUMBER == 3
+ push {r4, r5, r6, r7, r8, r9}
+#endif
+#if PORT_SWITCHED_REGIONS_NUMBER == 4
+ push {r4, r5, r6, r7, r8, r9, r10, r11}
+#endif
+#endif
+
+ str sp, [r1, #CONTEXT_OFFSET]
+#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) && \
+ ((CORTEX_MODEL == 3) || (CORTEX_MODEL == 4))
+ /* Workaround for ARM errata 752419, only applied if
+ condition exists for it to be triggered.*/
+ ldr r3, [r0, #CONTEXT_OFFSET]
+ mov sp, r3
+#else
+ ldr sp, [r0, #CONTEXT_OFFSET]
+#endif
+
+#if PORT_SWITCHED_REGIONS_NUMBER > 0
+ /* Restoring MPU context.*/
+#if PORT_SWITCHED_REGIONS_NUMBER == 1
+ pop {r4, r5}
+#endif
+#if PORT_SWITCHED_REGIONS_NUMBER == 2
+ pop {r4, r5, r6, r7}
+#endif
+#if PORT_SWITCHED_REGIONS_NUMBER == 3
+ pop {r4, r5, r6, r7, r8, r9}
+#endif
+#if PORT_SWITCHED_REGIONS_NUMBER == 4
+ pop {r4, r5, r6, r7, r8, r9, r10, r11}
+#endif
+#if PORT_SWITCHED_REGIONS_NUMBER >= 1
+ mov r3, #0
+ str r3, [r2, #-4] /* RNR */
+ stm r2, {r4, r5} /* RBAR, RASR */
+#endif
+#if PORT_SWITCHED_REGIONS_NUMBER >= 2
+ add r3, #1
+ str r3, [r2, #-4] /* RNR */
+ stm r2, {r6, r7} /* RBAR, RASR */
+#endif
+#if PORT_SWITCHED_REGIONS_NUMBER >= 3
+ add r3, #1
+ str r3, [r2, #-4] /* RNR */
+ stm r2, {r8, r9} /* RBAR, RASR */
+#endif
+#if PORT_SWITCHED_REGIONS_NUMBER >= 4
+ add r3, #1
+ str r3, [r2, #-4] /* RNR */
+ stm r2, {r10, r11} /* RBAR, RASR */
+#endif
+#endif
+
+#if CORTEX_USE_FPU
+ /* Restoring FPU context.*/
+ vpop {s16-s31}
+#endif
+ pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}
+
+/*--------------------------------------------------------------------------*
+ * Start a thread by invoking its work function.
+ *
+ * Threads execution starts here, the code leaves the system critical zone
+ * and then jumps into the thread function passed in register R4. The
+ * register R5 contains the thread parameter. The function chThdExit() is
+ * called on thread function return.
+ *--------------------------------------------------------------------------*/
+ .thumb_func
+ .globl _port_thread_start
+_port_thread_start:
+#if CH_DBG_ENABLE_STACK_CHECK && PORT_ENABLE_GUARD_PAGES
+ bl _port_set_region
+#endif
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_unlock
+#endif
+#if CH_DBG_STATISTICS
+ bl _stats_stop_measure_crit_thd
+#endif
+#if CORTEX_SIMPLIFIED_PRIORITY
+ cpsie i
+#else
+ movs r3, #0 /* CORTEX_BASEPRI_DISABLED */
+ msr BASEPRI, r3
+#endif
+ mov r0, r5
+ blx r4
+ movs r0, #0 /* MSG_OK */
+ bl chThdExit
+_zombies: b _zombies
+
+/*--------------------------------------------------------------------------*
+ * Post-IRQ switch code.
+ *
+ * Exception handlers return here for context switching.
+ *--------------------------------------------------------------------------*/
+ .thumb_func
+ .globl _port_switch_from_isr
+_port_switch_from_isr:
+#if CH_DBG_STATISTICS
+ bl _stats_start_measure_crit_thd
+#endif
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_lock
+#endif
+ bl chSchDoReschedule
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_unlock
+#endif
+#if CH_DBG_STATISTICS
+ bl _stats_stop_measure_crit_thd
+#endif
+ .globl _port_exit_from_isr
+_port_exit_from_isr:
+#if CORTEX_SIMPLIFIED_PRIORITY
+ movw r3, #:lower16:SCB_ICSR
+ movt r3, #:upper16:SCB_ICSR
+ mov r2, ICSR_PENDSVSET
+ str r2, [r3, #0]
+ cpsie i
+#else /* !CORTEX_SIMPLIFIED_PRIORITY */
+ svc #0
+#endif /* !CORTEX_SIMPLIFIED_PRIORITY */
+.L1: b .L1
+
+#endif /* !defined(__DOXYGEN__) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/GCC/chtypes.h b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/GCC/chtypes.h
new file mode 100644
index 0000000..de95804
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/GCC/chtypes.h
@@ -0,0 +1,97 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file ARMCMx/compilers/GCC/chtypes.h
+ * @brief ARM Cortex-Mx port system types.
+ *
+ * @addtogroup ARMCMx_GCC_CORE
+ * @{
+ */
+
+#ifndef CHTYPES_H
+#define CHTYPES_H
+
+#include
+#include
+#include
+
+/**
+ * @name Kernel types
+ * @{
+ */
+typedef uint32_t rtcnt_t; /**< Realtime counter. */
+typedef uint64_t rttime_t; /**< Realtime accumulator. */
+typedef uint32_t syssts_t; /**< System status word. */
+typedef uint8_t tmode_t; /**< Thread flags. */
+typedef uint8_t tstate_t; /**< Thread state. */
+typedef uint8_t trefs_t; /**< Thread references counter. */
+typedef uint8_t tslices_t; /**< Thread time slices counter.*/
+typedef uint32_t tprio_t; /**< Thread priority. */
+typedef int32_t msg_t; /**< Inter-thread message. */
+typedef int32_t eventid_t; /**< Numeric event identifier. */
+typedef uint32_t eventmask_t; /**< Mask of event identifiers. */
+typedef uint32_t eventflags_t; /**< Mask of event flags. */
+typedef int32_t cnt_t; /**< Generic signed counter. */
+typedef uint32_t ucnt_t; /**< Generic unsigned counter. */
+/** @} */
+
+/**
+ * @brief ROM constant modifier.
+ * @note It is set to use the "const" keyword in this port.
+ */
+#define ROMCONST const
+
+/**
+ * @brief Makes functions not inlineable.
+ * @note If the compiler does not support such attribute then some
+ * time-dependent services could be degraded.
+ */
+#define NOINLINE __attribute__((noinline))
+
+/**
+ * @brief Optimized thread function declaration macro.
+ */
+#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg)
+
+/**
+ * @brief Packed variable specifier.
+ */
+#define PACKED_VAR __attribute__((packed))
+
+/**
+ * @brief Memory alignment enforcement for variables.
+ */
+#define ALIGNED_VAR(n) __attribute__((aligned(n)))
+
+/**
+ * @brief Size of a pointer.
+ * @note To be used where the sizeof operator cannot be used, preprocessor
+ * expressions for example.
+ */
+#define SIZEOF_PTR 4
+
+/**
+ * @brief True if alignment is low-high in current architecture.
+ */
+#define REVERSE_ORDER 1
+
+#endif /* CHTYPES_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk
new file mode 100644
index 0000000..1fefa04
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk
@@ -0,0 +1,13 @@
+# List of the ChibiOS/RT Cortex-M0 STM32F0xx port files.
+PORTSRC = $(CHIBIOS)/os/common/ports/ARMCMx/chcore.c \
+ $(CHIBIOS)/os/common/ports/ARMCMx/chcore_v6m.c
+
+PORTASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.S
+
+PORTINC = $(CHIBIOS)/os/common/ports/ARMCMx \
+ $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC
+
+# Shared variables
+ALLXASMSRC += $(PORTASM)
+ALLCSRC += $(PORTSRC)
+ALLINC += $(PORTINC)
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk
new file mode 100644
index 0000000..fb89795
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk
@@ -0,0 +1,13 @@
+# List of the ChibiOS/RT ARMv7M generic port files.
+PORTSRC = $(CHIBIOS)/os/common/ports/ARMCMx/chcore.c \
+ $(CHIBIOS)/os/common/ports/ARMCMx/chcore_v7m.c
+
+PORTASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.S
+
+PORTINC = $(CHIBIOS)/os/common/ports/ARMCMx \
+ $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC
+
+# Shared variables
+ALLXASMSRC += $(PORTASM)
+ALLCSRC += $(PORTSRC)
+ALLINC += $(PORTINC)
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v6m.s b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v6m.s
new file mode 100644
index 0000000..ff9c591
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v6m.s
@@ -0,0 +1,156 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file compilers/IAR/chcoreasm_v6m.s
+ * @brief ARMv6-M architecture port low level code.
+ *
+ * @addtogroup ARMCMx_IAR_CORE
+ * @{
+ */
+
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+
+#define _FROM_ASM_
+#include "chlicense.h"
+#include "chconf.h"
+#include "chcore.h"
+
+#if !defined(__DOXYGEN__)
+
+/*
+ * RTOS-specific context offset.
+ */
+#if defined(_CHIBIOS_RT_CONF_)
+#define CONTEXT_OFFSET 12
+#elif defined(_CHIBIOS_NIL_CONF_)
+#define CONTEXT_OFFSET 0
+#else
+#error "invalid chconf.h"
+#endif
+
+ MODULE ?chcoreasm_v6m
+
+ AAPCS INTERWORK, VFP_COMPATIBLE
+ PRESERVE8
+
+SCB_ICSR SET 0xE000ED04
+
+ SECTION .text:CODE:NOROOT(2)
+
+ EXTERN chThdExit
+ EXTERN chSysHalt
+ EXTERN chSchDoReschedule
+#if CH_DBG_STATISTICS
+ EXTERN _stats_start_measure_crit_thd
+ EXTERN _stats_stop_measure_crit_thd
+#endif
+#if CH_DBG_SYSTEM_STATE_CHECK
+ EXTERN _dbg_check_unlock
+ EXTERN _dbg_check_lock
+#endif
+
+ THUMB
+
+/*
+ * Performs a context switch between two threads.
+ */
+ PUBLIC _port_switch
+_port_switch:
+ push {r4, r5, r6, r7, lr}
+ mov r4, r8
+ mov r5, r9
+ mov r6, r10
+ mov r7, r11
+ push {r4, r5, r6, r7}
+ mov r3, sp
+ str r3, [r1, #CONTEXT_OFFSET]
+ ldr r3, [r0, #CONTEXT_OFFSET]
+ mov sp, r3
+ pop {r4, r5, r6, r7}
+ mov r8, r4
+ mov r9, r5
+ mov r10, r6
+ mov r11, r7
+ pop {r4, r5, r6, r7, pc}
+
+/*
+ * Start a thread by invoking its work function.
+ * If the work function returns @p chThdExit() is automatically invoked.
+ */
+ PUBLIC _port_thread_start
+_port_thread_start:
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_unlock
+#endif
+#if CH_DBG_STATISTICS
+ bl _stats_stop_measure_crit_thd
+#endif
+ cpsie i
+ mov r0, r5
+ blx r4
+ movs r0, #0 /* MSG_OK */
+ bl chThdExit
+_zombies: b _zombies
+
+/*
+ * Post-IRQ switch code.
+ * Exception handlers return here for context switching.
+ */
+ PUBLIC _port_switch_from_isr
+ PUBLIC _port_exit_from_isr
+_port_switch_from_isr:
+#if CH_DBG_STATISTICS
+ bl _stats_start_measure_crit_thd
+#endif
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_lock
+#endif
+ bl chSchDoReschedule
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_unlock
+#endif
+#if CH_DBG_STATISTICS
+ bl _stats_stop_measure_crit_thd
+#endif
+_port_exit_from_isr:
+ ldr r2, =SCB_ICSR
+ movs r3, #128
+#if CORTEX_ALTERNATE_SWITCH
+ lsls r3, r3, #21
+ str r3, [r2, #0]
+ cpsie i
+#else
+ lsls r3, r3, #24
+ str r3, [r2, #0]
+#endif
+waithere:
+ b waithere
+
+ END
+
+#endif /* !defined(__DOXYGEN__) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v7m.s b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v7m.s
new file mode 100644
index 0000000..af8eca8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v7m.s
@@ -0,0 +1,169 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file compilers/IAR/chcoreasm_v7m.s
+ * @brief ARMv7-M architecture port low level code.
+ *
+ * @addtogroup ARMCMx_IAR_CORE
+ * @{
+ */
+
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+
+#define _FROM_ASM_
+#include "chlicense.h"
+#include "chconf.h"
+#include "chcore.h"
+
+#if !defined(__DOXYGEN__)
+
+/*
+ * RTOS-specific context offset.
+ */
+#if defined(_CHIBIOS_RT_CONF_)
+#define CONTEXT_OFFSET 12
+#elif defined(_CHIBIOS_NIL_CONF_)
+#define CONTEXT_OFFSET 0
+#else
+#error "invalid chconf.h"
+#endif
+
+ MODULE ?chcoreasm_v7m
+
+ AAPCS INTERWORK, VFP_COMPATIBLE
+ PRESERVE8
+
+SCB_ICSR SET 0xE000ED04
+ICSR_PENDSVSET SET 0x10000000
+
+ SECTION .text:CODE:NOROOT(2)
+
+ EXTERN chThdExit
+ EXTERN chSchDoReschedule
+#if CH_DBG_ENABLE_STACK_CHECK && PORT_ENABLE_GUARD_PAGES
+ EXTERN _port_set_region
+#endif
+#if CH_DBG_STATISTICS
+ EXTERN _stats_start_measure_crit_thd
+ EXTERN _stats_stop_measure_crit_thd
+#endif
+#if CH_DBG_SYSTEM_STATE_CHECK
+ EXTERN _dbg_check_unlock
+ EXTERN _dbg_check_lock
+#endif
+
+ THUMB
+
+/*
+ * Performs a context switch between two threads.
+ */
+ PUBLIC _port_switch
+_port_switch:
+ push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
+#if CORTEX_USE_FPU
+ vpush {s16-s31}
+#endif
+
+ str sp, [r1, #CONTEXT_OFFSET]
+#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) && \
+ ((CORTEX_MODEL == 3) || (CORTEX_MODEL == 4))
+ /* Workaround for ARM errata 752419, only applied if
+ condition exists for it to be triggered.*/
+ ldr r3, [r0, #CONTEXT_OFFSET]
+ mov sp, r3
+#else
+ ldr sp, [r0, #CONTEXT_OFFSET]
+#endif
+
+#if CORTEX_USE_FPU
+ vpop {s16-s31}
+#endif
+ pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}
+
+/*
+ * Start a thread by invoking its work function.
+ * If the work function returns @p chThdExit() is automatically invoked.
+ */
+ PUBLIC _port_thread_start
+_port_thread_start:
+#if CH_DBG_ENABLE_STACK_CHECK && PORT_ENABLE_GUARD_PAGES
+ bl _port_set_region
+#endif
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_unlock
+#endif
+#if CH_DBG_STATISTICS
+ bl _stats_stop_measure_crit_thd
+#endif
+#if CORTEX_SIMPLIFIED_PRIORITY
+ cpsie i
+#else
+ movs r3, #0 /* CORTEX_BASEPRI_DISABLED */
+ msr BASEPRI, r3
+#endif
+ mov r0, r5
+ blx r4
+ movs r0, #0 /* MSG_OK */
+ bl chThdExit
+_zombies: b _zombies
+
+/*
+ * Post-IRQ switch code.
+ * Exception handlers return here for context switching.
+ */
+ PUBLIC _port_switch_from_isr
+ PUBLIC _port_exit_from_isr
+_port_switch_from_isr:
+#if CH_DBG_STATISTICS
+ bl _stats_start_measure_crit_thd
+#endif
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_lock
+#endif
+ bl chSchDoReschedule
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_unlock
+#endif
+#if CH_DBG_STATISTICS
+ bl _stats_stop_measure_crit_thd
+#endif
+_port_exit_from_isr:
+#if CORTEX_SIMPLIFIED_PRIORITY
+ mov r3, #LWRD SCB_ICSR
+ movt r3, #HWRD SCB_ICSR
+ mov r2, #ICSR_PENDSVSET
+ str r2, [r3]
+ cpsie i
+#else
+ svc #0
+#endif
+.L3: b .L3
+
+ END
+
+#endif /* !defined(__DOXYGEN__) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/IAR/chtypes.h b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/IAR/chtypes.h
new file mode 100644
index 0000000..2bd376d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/IAR/chtypes.h
@@ -0,0 +1,115 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file ARMCMx/compilers/IAR/chtypes.h
+ * @brief ARM Cortex-Mx port system types.
+ *
+ * @addtogroup ARMCMx_IAR_CORE
+ * @{
+ */
+
+#ifndef CHTYPES_H
+#define CHTYPES_H
+
+#include
+#include
+#include
+
+/**
+ * @name Common constants
+ */
+/**
+ * @brief Generic 'false' boolean constant.
+ */
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+/**
+ * @brief Generic 'true' boolean constant.
+ */
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE (!FALSE)
+#endif
+/** @} */
+
+/**
+ * @name Kernel types
+ * @{
+ */
+typedef uint32_t rtcnt_t; /**< Realtime counter. */
+typedef uint64_t rttime_t; /**< Realtime accumulator. */
+typedef uint32_t syssts_t; /**< System status word. */
+typedef uint8_t tmode_t; /**< Thread flags. */
+typedef uint8_t tstate_t; /**< Thread state. */
+typedef uint8_t trefs_t; /**< Thread references counter. */
+typedef uint8_t tslices_t; /**< Thread time slices counter.*/
+typedef uint32_t tprio_t; /**< Thread priority. */
+typedef int32_t msg_t; /**< Inter-thread message. */
+typedef int32_t eventid_t; /**< Numeric event identifier. */
+typedef uint32_t eventmask_t; /**< Mask of event identifiers. */
+typedef uint32_t eventflags_t; /**< Mask of event flags. */
+typedef int32_t cnt_t; /**< Generic signed counter. */
+typedef uint32_t ucnt_t; /**< Generic unsigned counter. */
+/** @} */
+
+/**
+ * @brief ROM constant modifier.
+ * @note It is set to use the "const" keyword in this port.
+ */
+#define ROMCONST const
+
+/**
+ * @brief Makes functions not inlineable.
+ * @note If the compiler does not support such attribute then some
+ * time-dependent services could be degraded.
+ */
+#define NOINLINE _Pragma("inline=never")
+
+/**
+ * @brief Optimized thread function declaration macro.
+ */
+#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg)
+
+/**
+ * @brief Packed variable specifier.
+ */
+#define PACKED_VAR __packed
+
+/**
+ * @brief Memory alignment enforcement for variables.
+ */
+#define ALIGNED_VAR(n) _Pragma(__CH_STRINGIFY(data_alignment=n))
+
+/**
+ * @brief Size of a pointer.
+ * @note To be used where the sizeof operator cannot be used, preprocessor
+ * expressions for example.
+ */
+#define SIZEOF_PTR 4
+
+/**
+ * @brief True if alignment is low-high in current architecture.
+ */
+#define REVERSE_ORDER 1
+
+#endif /* CHTYPES_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/RVCT/chcoreasm_v6m.s b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/RVCT/chcoreasm_v6m.s
new file mode 100644
index 0000000..5784935
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/RVCT/chcoreasm_v6m.s
@@ -0,0 +1,152 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file compilers/RVCT/chcoreasm_v6m.s
+ * @brief ARMv6-M architecture port low level code.
+ *
+ * @addtogroup ARMCMx_RVCT_CORE
+ * @{
+ */
+
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+
+#define _FROM_ASM_
+#include "chlicense.h"
+#include "chconf.h"
+#include "chcore.h"
+
+#if !defined(__DOXYGEN__)
+
+/*
+ * RTOS-specific context offset.
+ */
+#if defined(_CHIBIOS_RT_CONF_)
+#define CONTEXT_OFFSET 12
+#elif defined(_CHIBIOS_NIL_CONF_)
+#define CONTEXT_OFFSET 0
+#else
+#error "invalid chconf.h"
+#endif
+
+SCB_ICSR EQU 0xE000ED04
+
+ PRESERVE8
+ THUMB
+ AREA |.text|, CODE, READONLY
+
+ IMPORT chThdExit
+ IMPORT chSchDoReschedule
+#if CH_DBG_STATISTICS
+ IMPORT _stats_start_measure_crit_thd
+ IMPORT _stats_stop_measure_crit_thd
+#endif
+#if CH_DBG_SYSTEM_STATE_CHECK
+ IMPORT _dbg_check_unlock
+ IMPORT _dbg_check_lock
+#endif
+
+/*
+ * Performs a context switch between two threads.
+ */
+ EXPORT _port_switch
+_port_switch PROC
+ push {r4, r5, r6, r7, lr}
+ mov r4, r8
+ mov r5, r9
+ mov r6, r10
+ mov r7, r11
+ push {r4, r5, r6, r7}
+ mov r3, sp
+ str r3, [r1, #CONTEXT_OFFSET]
+ ldr r3, [r0, #CONTEXT_OFFSET]
+ mov sp, r3
+ pop {r4, r5, r6, r7}
+ mov r8, r4
+ mov r9, r5
+ mov r10, r6
+ mov r11, r7
+ pop {r4, r5, r6, r7, pc}
+ ENDP
+
+/*
+ * Start a thread by invoking its work function.
+ * If the work function returns @p chThdExit() is automatically invoked.
+ */
+ EXPORT _port_thread_start
+_port_thread_start PROC
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_unlock
+#endif
+#if CH_DBG_STATISTICS
+ bl _stats_stop_measure_crit_thd
+#endif
+ cpsie i
+ mov r0, r5
+ blx r4
+ movs r0, #0 /* MSG_OK */
+ bl chThdExit
+_zombies b _zombies
+ ENDP
+
+/*
+ * Post-IRQ switch code.
+ * Exception handlers return here for context switching.
+ */
+ EXPORT _port_switch_from_isr
+ EXPORT _port_exit_from_isr
+_port_switch_from_isr PROC
+#if CH_DBG_STATISTICS
+ bl _stats_start_measure_crit_thd
+#endif
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_lock
+#endif
+ bl chSchDoReschedule
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_unlock
+#endif
+#if CH_DBG_STATISTICS
+ bl _stats_stop_measure_crit_thd
+#endif
+_port_exit_from_isr
+ ldr r2, =SCB_ICSR
+ movs r3, #128
+#if CORTEX_ALTERNATE_SWITCH
+ lsls r3, r3, #21
+ str r3, [r2, #0]
+ cpsie i
+#else
+ lsls r3, r3, #24
+ str r3, [r2, #0]
+#endif
+waithere b waithere
+ ENDP
+
+ END
+
+#endif /* !defined(__DOXYGEN__) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/RVCT/chcoreasm_v7m.s b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/RVCT/chcoreasm_v7m.s
new file mode 100644
index 0000000..2fa01c3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/RVCT/chcoreasm_v7m.s
@@ -0,0 +1,167 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file compilers/RVCT/chcoreasm_v7m.s
+ * @brief ARMv7-M architecture port low level code.
+ *
+ * @addtogroup ARMCMx_RVCT_CORE
+ * @{
+ */
+
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+
+#define _FROM_ASM_
+#include "chlicense.h"
+#include "chconf.h"
+#include "chcore.h"
+
+#if !defined(__DOXYGEN__)
+
+/*
+ * RTOS-specific context offset.
+ */
+#if defined(_CHIBIOS_RT_CONF_)
+#define CONTEXT_OFFSET 12
+#elif defined(_CHIBIOS_NIL_CONF_)
+#define CONTEXT_OFFSET 0
+#else
+#error "invalid chconf.h"
+#endif
+
+SCB_ICSR EQU 0xE000ED04
+ICSR_PENDSVSET EQU 0x10000000
+
+ PRESERVE8
+ THUMB
+ AREA |.text|, CODE, READONLY
+
+ IMPORT chThdExit
+ IMPORT chSchDoReschedule
+#if CH_DBG_ENABLE_STACK_CHECK && PORT_ENABLE_GUARD_PAGES
+ IMPORT _port_set_region
+#endif
+#if CH_DBG_STATISTICS
+ IMPORT _stats_start_measure_crit_thd
+ IMPORT _stats_stop_measure_crit_thd
+#endif
+#if CH_DBG_SYSTEM_STATE_CHECK
+ IMPORT _dbg_check_unlock
+ IMPORT _dbg_check_lock
+#endif
+
+/*
+ * Performs a context switch between two threads.
+ */
+ EXPORT _port_switch
+_port_switch PROC
+ push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
+#if CORTEX_USE_FPU
+ vpush {s16-s31}
+#endif
+
+ str sp, [r1, #CONTEXT_OFFSET]
+#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) && \
+ ((CORTEX_MODEL == 3) || (CORTEX_MODEL == 4))
+ /* Workaround for ARM errata 752419, only applied if
+ condition exists for it to be triggered.*/
+ ldr r3, [r0, #CONTEXT_OFFSET]
+ mov sp, r3
+#else
+ ldr sp, [r0, #CONTEXT_OFFSET]
+#endif
+
+#if CORTEX_USE_FPU
+ vpop {s16-s31}
+#endif
+ pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}
+ ENDP
+
+/*
+ * Start a thread by invoking its work function.
+ * If the work function returns @p chThdExit() is automatically invoked.
+ */
+ EXPORT _port_thread_start
+_port_thread_start PROC
+#if CH_DBG_ENABLE_STACK_CHECK && PORT_ENABLE_GUARD_PAGES
+ bl _port_set_region
+#endif
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_unlock
+#endif
+#if CH_DBG_STATISTICS
+ bl _stats_stop_measure_crit_thd
+#endif
+#if CORTEX_SIMPLIFIED_PRIORITY
+ cpsie i
+#else
+ movs r3, #0 /* CORTEX_BASEPRI_DISABLED */
+ msr BASEPRI, r3
+#endif
+ mov r0, r5
+ blx r4
+ movs r0, #0 /* MSG_OK */
+ bl chThdExit
+_zombies b _zombies
+ ENDP
+
+/*
+ * Post-IRQ switch code.
+ * Exception handlers return here for context switching.
+ */
+ EXPORT _port_switch_from_isr
+ EXPORT _port_exit_from_isr
+_port_switch_from_isr PROC
+#if CH_DBG_STATISTICS
+ bl _stats_start_measure_crit_thd
+#endif
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_lock
+#endif
+ bl chSchDoReschedule
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_unlock
+#endif
+#if CH_DBG_STATISTICS
+ bl _stats_stop_measure_crit_thd
+#endif
+_port_exit_from_isr
+#if CORTEX_SIMPLIFIED_PRIORITY
+ mov r3, #SCB_ICSR :AND: 0xFFFF
+ movt r3, #SCB_ICSR :SHR: 16
+ mov r2, #ICSR_PENDSVSET
+ str r2, [r3, #0]
+ cpsie i
+#else
+ svc #0
+#endif
+waithere b waithere
+ ENDP
+
+ END
+
+#endif /* !defined(__DOXYGEN__) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/RVCT/chtypes.h b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/RVCT/chtypes.h
new file mode 100644
index 0000000..fbda597
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/compilers/RVCT/chtypes.h
@@ -0,0 +1,97 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file ARMCMx/compilers/RVCT/chtypes.h
+ * @brief ARM Cortex-Mx port system types.
+ *
+ * @addtogroup ARMCMx_RVCT_CORE
+ * @{
+ */
+
+#ifndef CHTYPES_H
+#define CHTYPES_H
+
+#include
+#include
+#include
+
+/**
+ * @name Kernel types
+ * @{
+ */
+typedef uint32_t rtcnt_t; /**< Realtime counter. */
+typedef uint64_t rttime_t; /**< Realtime accumulator. */
+typedef uint32_t syssts_t; /**< System status word. */
+typedef uint8_t tmode_t; /**< Thread flags. */
+typedef uint8_t tstate_t; /**< Thread state. */
+typedef uint8_t trefs_t; /**< Thread references counter. */
+typedef uint8_t tslices_t; /**< Thread time slices counter.*/
+typedef uint32_t tprio_t; /**< Thread priority. */
+typedef int32_t msg_t; /**< Inter-thread message. */
+typedef int32_t eventid_t; /**< Numeric event identifier. */
+typedef uint32_t eventmask_t; /**< Mask of event identifiers. */
+typedef uint32_t eventflags_t; /**< Mask of event flags. */
+typedef int32_t cnt_t; /**< Generic signed counter. */
+typedef uint32_t ucnt_t; /**< Generic unsigned counter. */
+/** @} */
+
+/**
+ * @brief ROM constant modifier.
+ * @note It is set to use the "const" keyword in this port.
+ */
+#define ROMCONST const
+
+/**
+ * @brief Makes functions not inlineable.
+ * @note If the compiler does not support such attribute then some
+ * time-dependent services could be degraded.
+ */
+#define NOINLINE __attribute__((noinline))
+
+/**
+ * @brief Optimized thread function declaration macro.
+ */
+#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg)
+
+/**
+ * @brief Packed variable specifier.
+ */
+#define PACKED_VAR __packed
+
+/**
+ * @brief Memory alignment enforcement for variables.
+ */
+#define ALIGNED_VAR(n) __attribute__((aligned(n)))
+
+/**
+ * @brief Size of a pointer.
+ * @note To be used where the sizeof operator cannot be used, preprocessor
+ * expressions for example.
+ */
+#define SIZEOF_PTR 4
+
+/**
+ * @brief True if alignment is low-high in current architecture.
+ */
+#define REVERSE_ORDER 1
+
+#endif /* CHTYPES_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/ARMCMx/mpu.h b/ChibiOS_20.3.2/os/common/ports/ARMCMx/mpu.h
new file mode 100644
index 0000000..850be91
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/ARMCMx/mpu.h
@@ -0,0 +1,228 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file common/ARMCMx/mpu.h
+ * @brief Cortex-Mx MPU support macros and structures.
+ *
+ * @addtogroup COMMON_ARMCMx_MPU
+ * @{
+ */
+
+#ifndef MPU_H
+#define MPU_H
+
+/* Other layers may include another header named mpu_v7m.h which is perfectly
+ compatible, doing a check here to avoid name conflicts.*/
+#ifndef MPUV7M_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name MPU registers definitions
+ * @{
+ */
+#define MPU_TYPE_SEPARATED (1U << 0U)
+#define MPU_TYPE_DREGION(n) (((n) >> 8U) & 255U)
+#define MPU_TYPE_IREGION(n) (((n) >> 16U) & 255U)
+
+#define MPU_CTRL_ENABLE (1U << 0U)
+#define MPU_CTRL_HFNMIENA (1U << 1U)
+#define MPU_CTRL_PRIVDEFENA (1U << 2U)
+
+#define MPU_RNR_REGION_MASK (255U << 0U)
+#define MPU_RNR_REGION(n) ((n) << 0U)
+
+#define MPU_RBAR_REGION_MASK (15U << 0U)
+#define MPU_RBAR_REGION(n) ((n) << 0U)
+#define MPU_RBAR_VALID (1U << 4U)
+#define MPU_RBAR_ADDR_MASK 0xFFFFFFE0U
+#define MPU_RBAR_ADDR(n) ((n) << 5U)
+
+#define MPU_RASR_ENABLE (1U << 0U)
+#define MPU_RASR_SIZE_MASK (31U << 1U)
+#define MPU_RASR_SIZE(n) ((n) << 1U)
+#define MPU_RASR_SIZE_32 MPU_RASR_SIZE(4U)
+#define MPU_RASR_SIZE_64 MPU_RASR_SIZE(5U)
+#define MPU_RASR_SIZE_128 MPU_RASR_SIZE(6U)
+#define MPU_RASR_SIZE_256 MPU_RASR_SIZE(7U)
+#define MPU_RASR_SIZE_512 MPU_RASR_SIZE(8U)
+#define MPU_RASR_SIZE_1K MPU_RASR_SIZE(9U)
+#define MPU_RASR_SIZE_2K MPU_RASR_SIZE(10U)
+#define MPU_RASR_SIZE_4K MPU_RASR_SIZE(11U)
+#define MPU_RASR_SIZE_8K MPU_RASR_SIZE(12U)
+#define MPU_RASR_SIZE_16K MPU_RASR_SIZE(13U)
+#define MPU_RASR_SIZE_32K MPU_RASR_SIZE(14U)
+#define MPU_RASR_SIZE_64K MPU_RASR_SIZE(15U)
+#define MPU_RASR_SIZE_128K MPU_RASR_SIZE(16U)
+#define MPU_RASR_SIZE_256K MPU_RASR_SIZE(17U)
+#define MPU_RASR_SIZE_512K MPU_RASR_SIZE(18U)
+#define MPU_RASR_SIZE_1M MPU_RASR_SIZE(19U)
+#define MPU_RASR_SIZE_2M MPU_RASR_SIZE(20U)
+#define MPU_RASR_SIZE_4M MPU_RASR_SIZE(21U)
+#define MPU_RASR_SIZE_8M MPU_RASR_SIZE(22U)
+#define MPU_RASR_SIZE_16M MPU_RASR_SIZE(23U)
+#define MPU_RASR_SIZE_32M MPU_RASR_SIZE(24U)
+#define MPU_RASR_SIZE_64M MPU_RASR_SIZE(25U)
+#define MPU_RASR_SIZE_128M MPU_RASR_SIZE(26U)
+#define MPU_RASR_SIZE_256M MPU_RASR_SIZE(27U)
+#define MPU_RASR_SIZE_512M MPU_RASR_SIZE(28U)
+#define MPU_RASR_SIZE_1G MPU_RASR_SIZE(29U)
+#define MPU_RASR_SIZE_2G MPU_RASR_SIZE(30U)
+#define MPU_RASR_SIZE_4G MPU_RASR_SIZE(31U)
+#define MPU_RASR_SRD_MASK (255U << 8U)
+#define MPU_RASR_SRD(n) ((n) << 8U)
+#define MPU_RASR_SRD_ALL (0U << 8U)
+#define MPU_RASR_SRD_DISABLE_SUB0 (1U << 8U)
+#define MPU_RASR_SRD_DISABLE_SUB1 (2U << 8U)
+#define MPU_RASR_SRD_DISABLE_SUB2 (4U << 8U)
+#define MPU_RASR_SRD_DISABLE_SUB3 (8U << 8U)
+#define MPU_RASR_SRD_DISABLE_SUB4 (16U << 8U)
+#define MPU_RASR_SRD_DISABLE_SUB5 (32U << 8U)
+#define MPU_RASR_SRD_DISABLE_SUB6 (64U << 8U)
+#define MPU_RASR_SRD_DISABLE_SUB7 (128U << 8U)
+#define MPU_RASR_ATTR_B (1U << 16U)
+#define MPU_RASR_ATTR_C (1U << 17U)
+#define MPU_RASR_ATTR_S (1U << 18U)
+#define MPU_RASR_ATTR_TEX_MASK (7U << 19U)
+#define MPU_RASR_ATTR_TEX(n) ((n) << 19U)
+#define MPU_RASR_ATTR_AP_MASK (7U << 24U)
+#define MPU_RASR_ATTR_AP(n) ((n) << 24U)
+#define MPU_RASR_ATTR_AP_NA_NA (0U << 24U)
+#define MPU_RASR_ATTR_AP_RW_NA (1U << 24U)
+#define MPU_RASR_ATTR_AP_RW_RO (2U << 24U)
+#define MPU_RASR_ATTR_AP_RW_RW (3U << 24U)
+#define MPU_RASR_ATTR_AP_RO_NA (5U << 24U)
+#define MPU_RASR_ATTR_AP_RO_RO (6U << 24U)
+#define MPU_RASR_ATTR_XN (1U << 28U)
+/** @} */
+
+/**
+ * @name Region attributes
+ * @{
+ */
+#define MPU_RASR_ATTR_STRONGLY_ORDERED (MPU_RASR_ATTR_TEX(0))
+#define MPU_RASR_ATTR_SHARED_DEVICE (MPU_RASR_ATTR_TEX(0) | MPU_RASR_ATTR_B)
+#define MPU_RASR_ATTR_CACHEABLE_WT_NWA (MPU_RASR_ATTR_TEX(0) | MPU_RASR_ATTR_C)
+#define MPU_RASR_ATTR_CACHEABLE_WB_NWA (MPU_RASR_ATTR_TEX(0) | MPU_RASR_ATTR_B | MPU_RASR_ATTR_C)
+#define MPU_RASR_ATTR_NON_CACHEABLE (MPU_RASR_ATTR_TEX(1))
+#define MPU_RASR_ATTR_CACHEABLE_WB_WA (MPU_RASR_ATTR_TEX(1) | MPU_RASR_ATTR_B | MPU_RASR_ATTR_C)
+#define MPU_RASR_ATTR_NON_SHARED_DEVICE (MPU_RASR_ATTR_TEX(2))
+/** @} */
+
+/**
+ * @name Region identifiers
+ * @{
+ */
+#define MPU_REGION_0 0U
+#define MPU_REGION_1 1U
+#define MPU_REGION_2 2U
+#define MPU_REGION_3 3U
+#define MPU_REGION_4 4U
+#define MPU_REGION_5 5U
+#define MPU_REGION_6 6U
+#define MPU_REGION_7 7U
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the MPU.
+ * @note MEMFAULENA is enabled in SCB_SHCSR.
+ *
+ * @param[in] ctrl MPU control modes as defined in @p MPU_CTRL register,
+ * the enable bit is enforced
+ *
+ * @api
+ */
+#define mpuEnable(ctrl) { \
+ MPU->CTRL = ((uint32_t)ctrl) | MPU_CTRL_ENABLE; \
+ SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; \
+}
+
+/**
+ * @brief Disables the MPU.
+ * @note MEMFAULENA is disabled in SCB_SHCSR.
+ *
+ * @api
+ */
+#define mpuDisable() { \
+ SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; \
+ MPU->CTRL = 0; \
+}
+
+/**
+ * @brief Configures an MPU region.
+ *
+ * @param[in] region the region number
+ * @param[in] address start address of the region, note, there are alignment
+ * constraints
+ * @param[in] attribs attributes mask as defined in @p MPU_RASR register
+ *
+ * @api
+ */
+#define mpuConfigureRegion(region, addr, attribs) { \
+ MPU->RNR = ((uint32_t)region); \
+ MPU->RBAR = ((uint32_t)addr); \
+ MPU->RASR = ((uint32_t)attribs); \
+}
+
+/**
+ * @brief Changes an MPU region base address.
+ *
+ * @param[in] region the region number
+ * @param[in] address start address of the region, note, there are alignment
+ * constraints
+ *
+ * @api
+ */
+#define mpuSetRegionAddress(region, addr) { \
+ MPU->RNR = ((uint32_t)region); \
+ MPU->RBAR = ((uint32_t)addr); \
+}
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MPUV7M_H */
+
+#endif /* MPU_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/AVR/chcore.c b/ChibiOS_20.3.2/os/common/ports/AVR/chcore.c
new file mode 100644
index 0000000..f75b12e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/AVR/chcore.c
@@ -0,0 +1,159 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file chcore.c
+ * @brief AVR architecture port code.
+ *
+ * @addtogroup AVR_CORE
+ * @{
+ */
+
+#include "ch.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/* Executing-in-ISR global flag.*/
+bool __avr_in_isr;
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Performs a context switch between two threads.
+ * @details This is the most critical code in any port, this function
+ * is responsible for the context switch between 2 threads.
+ * @note The implementation of this code affects directly the context
+ * switch performance so optimize here as much as you can.
+ *
+ * @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread to be switched out
+ *
+ * @todo Put into an asm module, use of naked attribute is problematic.
+ */
+#if !defined(__DOXYGEN__)
+__attribute__((naked, weak))
+#endif
+void _port_switch(thread_t *ntp, thread_t *otp) {
+
+ (void)ntp;
+ (void)otp;
+
+ asm volatile ("push r2");
+ asm volatile ("push r3");
+ asm volatile ("push r4");
+ asm volatile ("push r5");
+ asm volatile ("push r6");
+ asm volatile ("push r7");
+ asm volatile ("push r8");
+ asm volatile ("push r9");
+ asm volatile ("push r10");
+ asm volatile ("push r11");
+ asm volatile ("push r12");
+ asm volatile ("push r13");
+ asm volatile ("push r14");
+ asm volatile ("push r15");
+ asm volatile ("push r16");
+ asm volatile ("push r17");
+ asm volatile ("push r28");
+ asm volatile ("push r29");
+
+#if defined(_CHIBIOS_RT_)
+ asm volatile ("movw r30, r22");
+ asm volatile ("in r0, 0x3d");
+ asm volatile ("std Z+5, r0");
+ asm volatile ("in r0, 0x3e");
+ asm volatile ("std Z+6, r0");
+
+ asm volatile ("movw r30, r24");
+ asm volatile ("ldd r0, Z+5");
+ asm volatile ("out 0x3d, r0");
+ asm volatile ("ldd r0, Z+6");
+ asm volatile ("out 0x3e, r0");
+#endif
+
+#if defined(_CHIBIOS_NIL_)
+ asm volatile ("movw r30, r22");
+ asm volatile ("in r0, 0x3d");
+ asm volatile ("std Z+0, r0");
+ asm volatile ("in r0, 0x3e");
+ asm volatile ("std Z+1, r0");
+
+ asm volatile ("movw r30, r24");
+ asm volatile ("ldd r0, Z+0");
+ asm volatile ("out 0x3d, r0");
+ asm volatile ("ldd r0, Z+1");
+ asm volatile ("out 0x3e, r0");
+#endif
+
+ asm volatile ("pop r29");
+ asm volatile ("pop r28");
+ asm volatile ("pop r17");
+ asm volatile ("pop r16");
+ asm volatile ("pop r15");
+ asm volatile ("pop r14");
+ asm volatile ("pop r13");
+ asm volatile ("pop r12");
+ asm volatile ("pop r11");
+ asm volatile ("pop r10");
+ asm volatile ("pop r9");
+ asm volatile ("pop r8");
+ asm volatile ("pop r7");
+ asm volatile ("pop r6");
+ asm volatile ("pop r5");
+ asm volatile ("pop r4");
+ asm volatile ("pop r3");
+ asm volatile ("pop r2");
+ asm volatile ("ret");
+}
+
+/**
+ * @brief Start a thread by invoking its work function.
+ * @details If the work function returns @p chThdExit() is automatically
+ * invoked.
+ */
+void _port_thread_start(void) {
+
+ chSysUnlock();
+ asm volatile ("movw r24, r4");
+ asm volatile ("movw r30, r2");
+ asm volatile ("icall");
+ asm volatile ("call chThdExit"); /* Used for avr5 Architecture. */
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/AVR/chcore.h b/ChibiOS_20.3.2/os/common/ports/AVR/chcore.h
new file mode 100644
index 0000000..b5f70fc
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/AVR/chcore.h
@@ -0,0 +1,542 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file chcore.h
+ * @brief AVR port macros and structures.
+ *
+ * @addtogroup AVR_CORE
+ * @{
+ */
+
+#ifndef CHCORE_H
+#define CHCORE_H
+
+#include
+#include
+
+extern bool __avr_in_isr;
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Port Capabilities and Constants
+ * @{
+ */
+/**
+ * @brief This port supports a realtime counter.
+ */
+#define PORT_SUPPORTS_RT FALSE
+
+/**
+ * @brief Natural alignment constant.
+ * @note It is the minimum alignment for pointer-size variables.
+ */
+#define PORT_NATURAL_ALIGN 1U
+
+/**
+ * @brief Stack alignment constant.
+ * @note It is the alignment required for the stack pointer.
+ */
+#define PORT_STACK_ALIGN 1U
+
+/**
+ * @brief Working Areas alignment constant.
+ * @note It is the alignment to be enforced for thread working areas.
+ */
+#define PORT_WORKING_AREA_ALIGN 1U
+/** @} */
+
+/**
+ * @name Architecture and Compiler
+ * @{
+ */
+/**
+ * @brief Macro defining an AVR architecture.
+ */
+#define PORT_ARCHITECTURE_AVR
+
+/**
+ * @brief Macro defining the specific AVR architecture.
+ */
+#define PORT_ARCHITECTURE_AVR_MEGAAVR
+
+/**
+ * @brief Name of the implemented architecture.
+ */
+#define PORT_ARCHITECTURE_NAME "MegaAVR"
+
+/**
+ * @brief Compiler name and version.
+ */
+#if defined(__GNUC__) || defined(__DOXYGEN__)
+#define PORT_COMPILER_NAME "GCC " __VERSION__
+
+#else
+#error "unsupported compiler"
+#endif
+
+/**
+ * @brief Port-specific information string.
+ */
+#define PORT_INFO "None"
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Stack size for the system idle thread.
+ * @details This size depends on the idle thread implementation, usually
+ * the idle thread should take no more space than those reserved
+ * by @p PORT_INT_REQUIRED_STACK.
+ */
+#if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__)
+#define PORT_IDLE_THREAD_STACK_SIZE 8
+#endif
+
+/**
+ * @brief Per-thread stack overhead for interrupts servicing.
+ * @details This constant is used in the calculation of the correct working
+ * area size.
+ */
+#if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__)
+#define PORT_INT_REQUIRED_STACK 32
+#endif
+
+/**
+ * @brief Enables an alternative timer implementation.
+ * @details Usually the port uses a timer interface defined in the file
+ * @p chcore_timer.h, if this option is enabled then the file
+ * @p chcore_timer_alt.h is included instead.
+ */
+#if !defined(PORT_USE_ALT_TIMER) || defined(__DOXYGEN__)
+#define PORT_USE_ALT_TIMER FALSE
+#endif
+
+/**
+ * @brief Enables a "wait for interrupt" instruction in the idle loop.
+ */
+#if !defined(PORT_AVR_WFI_SLEEP_IDLE) || defined(__DOXYGEN__)
+#define PORT_AVR_WFI_SLEEP_IDLE FALSE
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/**
+ * @brief Type of stack and memory alignment enforcement.
+ * @note In this architecture the stack alignment is enforced to 8 bits.
+ */
+typedef uint8_t stkalign_t;
+
+/**
+ * @brief Interrupt saved context.
+ * @details This structure represents the stack frame saved during a
+ * preemption-capable interrupt handler.
+ * @note R2 and R13 are not saved because those are assumed to be immutable
+ * during the system life cycle.
+ */
+struct port_extctx {
+ uint8_t _next;
+ uint8_t r31;
+ uint8_t r30;
+ uint8_t r27;
+ uint8_t r26;
+ uint8_t r25;
+ uint8_t r24;
+ uint8_t r23;
+ uint8_t r22;
+ uint8_t r21;
+ uint8_t r20;
+ uint8_t r19;
+ uint8_t r18;
+ uint8_t sr;
+ uint8_t r1;
+ uint8_t r0;
+#if defined(__AVR_3_BYTE_PC__)
+ uint8_t pcx;
+#endif
+ uint16_t pc;
+};
+
+/**
+ * @brief System saved context.
+ * @details This structure represents the inner stack frame during a context
+ * switching.
+ * @note R2 and R13 are not saved because those are assumed to be immutable
+ * during the system life cycle.
+ * @note LR is stored in the caller context so it is not present in this
+ * structure.
+ */
+struct port_intctx {
+ uint8_t _next;
+ uint8_t r29;
+ uint8_t r28;
+ uint8_t r17;
+ uint8_t r16;
+ uint8_t r15;
+ uint8_t r14;
+ uint8_t r13;
+ uint8_t r12;
+ uint8_t r11;
+ uint8_t r10;
+ uint8_t r9;
+ uint8_t r8;
+ uint8_t r7;
+ uint8_t r6;
+ uint8_t r5;
+ uint8_t r4;
+ uint8_t r3;
+ uint8_t r2;
+#if defined(__AVR_3_BYTE_PC__)
+ uint8_t pcx;
+#endif
+ uint8_t pcl;
+ uint8_t pch;
+};
+
+/**
+ * @brief Platform dependent part of the @p thread_t structure.
+ * @details This structure usually contains just the saved stack pointer
+ * defined as a pointer to a @p port_intctx structure.
+ */
+struct port_context {
+ struct port_intctx *sp;
+};
+
+#endif /* !defined(_FROM_ASM_) */
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Platform dependent part of the @p chThdCreateI() API.
+ * @details This code usually setup the context switching frame represented
+ * by an @p port_intctx structure.
+ */
+#if defined(__AVR_3_BYTE_PC__) || defined(__DOXYGEN__)
+#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \
+ tp->ctx.sp = (struct port_intctx *)((uint8_t *)(wtop) - \
+ sizeof(struct port_intctx)); \
+ tp->ctx.sp->r2 = (uint8_t)(0xff & (uint16_t)pf); \
+ tp->ctx.sp->r3 = (uint8_t)((uint16_t)(pf) >> 8); \
+ tp->ctx.sp->r4 = (uint8_t)(0xff & (uint16_t)arg); \
+ tp->ctx.sp->r5 = (uint8_t)((uint16_t)(arg) >> 8); \
+ tp->ctx.sp->pcx = (uint8_t)0; \
+ tp->ctx.sp->pcl = (uint16_t)_port_thread_start >> 8; \
+ tp->ctx.sp->pch = (uint8_t)(0xff & (uint16_t)_port_thread_start); \
+}
+#else /* !__AVR_3_BYTE_PC__ */
+#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \
+ tp->ctx.sp = (struct port_intctx *)((uint8_t *)(wtop) - \
+ sizeof(struct port_intctx)); \
+ tp->ctx.sp->r2 = (uint8_t)(0xff & (uint16_t)pf); \
+ tp->ctx.sp->r3 = (uint8_t)((uint16_t)(pf) >> 8); \
+ tp->ctx.sp->r4 = (uint8_t)(0xff & (uint16_t)arg); \
+ tp->ctx.sp->r5 = (uint8_t)((uint16_t)(arg) >> 8); \
+ tp->ctx.sp->pcl = (uint16_t)_port_thread_start >> 8; \
+ tp->ctx.sp->pch = (uint8_t)(0xff & (uint16_t)_port_thread_start); \
+}
+#endif /* !__AVR_3_BYTE_PC__ */
+
+/**
+ * @brief Computes the thread working area global size.
+ * @note There is no need to perform alignments in this macro.
+ */
+#define PORT_WA_SIZE(n) ((sizeof(struct port_intctx) - 1) + \
+ (sizeof(struct port_extctx) - 1) + \
+ ((size_t)(n)) + ((size_t)(PORT_INT_REQUIRED_STACK)))
+
+/**
+ * @brief Static working area allocation.
+ * @details This macro is used to allocate a static thread working area
+ * aligned as both position and size.
+ *
+ * @param[in] s the name to be assigned to the stack array
+ * @param[in] n the stack size to be assigned to the thread
+ */
+#define PORT_WORKING_AREA(s, n) \
+ stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)]
+
+/**
+ * @brief Priority level verification macro.
+ */
+#define PORT_IRQ_IS_VALID_PRIORITY(n) false
+
+/**
+ * @brief Priority level verification macro.
+ */
+#define PORT_IRQ_IS_VALID_KERNEL_PRIORITY(n) false
+
+/**
+ * @brief IRQ prologue code.
+ * @details This macro must be inserted at the start of all IRQ handlers
+ * enabled to invoke system APIs.
+ * @note This code tricks the compiler to save all the specified registers
+ * by "touching" them.
+ */
+#define PORT_IRQ_PROLOGUE() { \
+ asm ("" : : : "r18", "r19", "r20", "r21", "r22", "r23", "r24", \
+ "r25", "r26", "r27", "r30", "r31"); \
+ __avr_in_isr = true; \
+}
+
+/**
+ * @brief IRQ epilogue code.
+ * @details This macro must be inserted at the end of all IRQ handlers
+ * enabled to invoke system APIs.
+ */
+#define PORT_IRQ_EPILOGUE() { \
+ __avr_in_isr = false; \
+ _dbg_check_lock(); \
+ if (chSchIsPreemptionRequired()) \
+ chSchDoReschedule(); \
+ _dbg_check_unlock(); \
+}
+
+/**
+ * @brief IRQ handler function declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ */
+#define PORT_IRQ_HANDLER(id) ISR(id)
+
+/**
+ * @brief Fast IRQ handler function declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ */
+#define PORT_FAST_IRQ_HANDLER(id) ISR(id)
+
+/**
+ * @brief Performs a context switch between two threads.
+ * @details This is the most critical code in any port, this function
+ * is responsible for the context switch between 2 threads.
+ * @note The implementation of this code affects directly the context
+ * switch performance so optimize here as much as you can.
+ *
+ * @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread to be switched out
+ */
+#define port_switch(ntp, otp) { \
+ _port_switch(ntp, otp); \
+ asm volatile ("" : : : "memory"); \
+}
+
+
+/**
+ * @brief Port-related initialization code.
+ * @note This function is empty in this port.
+ */
+#define port_init() { \
+ __avr_in_isr = true; \
+}
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void _port_switch(thread_t *ntp, thread_t *otp);
+ void _port_thread_start(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined(_FROM_ASM_) */
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/**
+ * @brief Returns a word encoding the current interrupts status.
+ *
+ * @return The interrupts status.
+ */
+static inline syssts_t port_get_irq_status(void) {
+
+ return SREG;
+}
+
+/**
+ * @brief Checks the interrupt status.
+ *
+ * @param[in] sts the interrupt status word
+ *
+ * @return The interrupt status.
+ * @retval false the word specified a disabled interrupts status.
+ * @retval true the word specified an enabled interrupts status.
+ */
+static inline bool port_irq_enabled(syssts_t sts) {
+
+ return (bool)((sts & 0x80) != 0);
+}
+
+/**
+ * @brief Determines the current execution context.
+ *
+ * @return The execution context.
+ * @retval false not running in ISR mode.
+ * @retval true running in ISR mode.
+ */
+static inline bool port_is_isr_context(void) {
+
+ return __avr_in_isr;
+}
+
+/**
+ * @brief Kernel-lock action.
+ * @details Usually this function just disables interrupts but may perform more
+ * actions.
+ */
+static inline void port_lock(void) {
+
+ asm volatile ("cli" : : : "memory");
+}
+
+/**
+ * @brief Kernel-unlock action.
+ * @details Usually this function just enables interrupts but may perform more
+ * actions.
+ */
+static inline void port_unlock(void) {
+
+ asm volatile ("sei" : : : "memory");
+}
+
+/**
+ * @brief Kernel-lock action from an interrupt handler.
+ * @details This function is invoked before invoking I-class APIs from
+ * interrupt handlers. The implementation is architecture dependent,
+ * in its simplest form it is void.
+ * @note This function is empty in this port.
+ */
+static inline void port_lock_from_isr(void) {
+
+}
+
+/**
+ * @brief Kernel-unlock action from an interrupt handler.
+ * @details This function is invoked after invoking I-class APIs from interrupt
+ * handlers. The implementation is architecture dependent, in its
+ * simplest form it is void.
+ * @note This function is empty in this port.
+ */
+static inline void port_unlock_from_isr(void) {
+
+}
+
+/**
+ * @brief Disables all the interrupt sources.
+ * @note Of course non-maskable interrupt sources are not included.
+ */
+static inline void port_disable(void) {
+
+ asm volatile ("cli" : : : "memory");
+}
+
+/**
+ * @brief Disables the interrupt sources below kernel-level priority.
+ * @note Interrupt sources above kernel level remains enabled.
+ */
+static inline void port_suspend(void) {
+
+ asm volatile ("cli" : : : "memory");
+}
+
+/**
+ * @brief Enables all the interrupt sources.
+ */
+static inline void port_enable(void) {
+
+ asm volatile ("sei" : : : "memory");
+}
+
+/**
+ * @brief Enters an architecture-dependent IRQ-waiting mode.
+ * @details The function is meant to return when an interrupt becomes pending.
+ * The simplest implementation is an empty function or macro but this
+ * would not take advantage of architecture-specific power saving
+ * modes.
+ */
+static inline void port_wait_for_interrupt(void) {
+
+#if PORT_AVR_WFI_SLEEP_IDLE
+ asm volatile ("sleep" : : : "memory");
+#endif
+}
+
+/**
+ * @brief Returns the current value of the realtime counter.
+ *
+ * @return The realtime counter value.
+ */
+static inline rtcnt_t port_rt_get_counter_value(void) {
+
+ return 0;
+}
+
+#endif /* !defined(_FROM_ASM_) */
+
+/*===========================================================================*/
+/* Module late inclusions. */
+/*===========================================================================*/
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+#if CH_CFG_ST_TIMEDELTA > 0
+#if !PORT_USE_ALT_TIMER
+#include "chcore_timer.h"
+#else /* PORT_USE_ALT_TIMER */
+#include "chcore_timer_alt.h"
+#endif /* PORT_USE_ALT_TIMER */
+#endif /* CH_CFG_ST_TIMEDELTA > 0 */
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CHCORE_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/AVR/chcore_timer.h b/ChibiOS_20.3.2/os/common/ports/AVR/chcore_timer.h
new file mode 100644
index 0000000..826f24a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/AVR/chcore_timer.h
@@ -0,0 +1,126 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file AVR/chcore_timer.h
+ * @brief System timer header file.
+ *
+ * @addtogroup AVR_TIMER
+ * @{
+ */
+
+#ifndef CHCORE_TIMER_H
+#define CHCORE_TIMER_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Starts the alarm.
+ * @note Makes sure that no spurious alarms are triggered after
+ * this call.
+ *
+ * @param[in] time the time to be set for the first alarm
+ *
+ * @notapi
+ */
+static inline void port_timer_start_alarm(systime_t time) {
+ void stStartAlarm(systime_t time);
+
+ stStartAlarm(time);
+}
+
+/**
+ * @brief Stops the alarm interrupt.
+ *
+ * @notapi
+ */
+static inline void port_timer_stop_alarm(void) {
+ void stStopAlarm(void);
+
+ stStopAlarm();
+}
+
+/**
+ * @brief Sets the alarm time.
+ *
+ * @param[in] time the time to be set for the next alarm
+ *
+ * @notapi
+ */
+static inline void port_timer_set_alarm(systime_t time) {
+ void stSetAlarm(systime_t time);
+
+ stSetAlarm(time);
+}
+
+/**
+ * @brief Returns the system time.
+ *
+ * @return The system time.
+ *
+ * @notapi
+ */
+static inline systime_t port_timer_get_time(void) {
+ systime_t stGetCounter(void);
+
+ return stGetCounter();
+}
+
+/**
+ * @brief Returns the current alarm time.
+ *
+ * @return The currently set alarm time.
+ *
+ * @notapi
+ */
+static inline systime_t port_timer_get_alarm(void) {
+ systime_t stGetAlarm(void);
+
+ return stGetAlarm();
+}
+
+#endif /* CHCORE_TIMER_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/AVR/compilers/GCC/chtypes.h b/ChibiOS_20.3.2/os/common/ports/AVR/compilers/GCC/chtypes.h
new file mode 100644
index 0000000..0bbb9ef
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/AVR/compilers/GCC/chtypes.h
@@ -0,0 +1,98 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file AVR/compilers/GCC/chtypes.h
+ * @brief AVR architecture port system types.
+ *
+ * @addtogroup AVR_CORE
+ * @{
+ */
+
+#ifndef CHTYPES_H
+#define CHTYPES_H
+
+#include
+#include
+#include
+
+/**
+ * @name Kernel types
+ * @{
+ */
+typedef uint32_t rtcnt_t; /**< Realtime counter. */
+typedef uint64_t rttime_t; /**< Realtime accumulator. */
+typedef uint8_t syssts_t; /**< System status word. */
+typedef uint8_t tmode_t; /**< Thread flags. */
+typedef uint8_t tstate_t; /**< Thread state. */
+typedef uint8_t trefs_t; /**< Thread references counter. */
+typedef uint8_t tslices_t; /**< Thread time slices counter.*/
+typedef uint8_t tprio_t; /**< Thread priority. */
+typedef int16_t msg_t; /**< Inter-thread message. */
+typedef int32_t eventid_t; /**< Numeric event identifier. */
+typedef uint8_t eventmask_t; /**< Mask of event identifiers. */
+typedef uint8_t eventflags_t; /**< Mask of event flags. */
+typedef int8_t cnt_t; /**< Generic signed counter. */
+typedef uint8_t ucnt_t; /**< Generic unsigned counter. */
+typedef bool bool_t; /**< Fast boolean type. */
+/** @} */
+
+/**
+ * @brief ROM constant modifier.
+ * @note It is set to use the "const" keyword in this port.
+ */
+#define ROMCONST const
+
+/**
+ * @brief Makes functions not inlineable.
+ * @note If the compiler does not support such attribute then the
+ * realtime counter precision could be degraded.
+ */
+#define NOINLINE __attribute__((noinline))
+
+/**
+ * @brief Optimized thread function declaration macro.
+ */
+#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg)
+
+/**
+ * @brief Packed variable specifier.
+ */
+#define PACKED_VAR __attribute__((packed))
+
+/**
+ * @brief Memory alignment enforcement for variables.
+ */
+#define ALIGNED_VAR(n) __attribute__((aligned(n)))
+
+/**
+ * @brief Size of a pointer.
+ * @note To be used where the sizeof operator cannot be used, preprocessor
+ * expressions for example.
+ */
+#define SIZEOF_PTR 2
+
+/**
+ * @brief True if alignment is low-high in current architecture.
+ */
+#define REVERSE_ORDER 1
+
+#endif /* CHTYPES_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/AVR/compilers/GCC/mk/port.mk b/ChibiOS_20.3.2/os/common/ports/AVR/compilers/GCC/mk/port.mk
new file mode 100644
index 0000000..160b402
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/AVR/compilers/GCC/mk/port.mk
@@ -0,0 +1,12 @@
+# List of the ChibiOS/RT AVR port files.
+PORTSRC = ${CHIBIOS}/os/common/ports/AVR/chcore.c
+
+PORTASM =
+
+PORTINC = ${CHIBIOS}/os/common/ports/AVR \
+ ${CHIBIOS}/os/common/ports/AVR/compilers/GCC
+
+# Shared variables
+ALLXASMSRC += $(PORTASM)
+ALLCSRC += $(PORTSRC)
+ALLINC += $(PORTINC)
diff --git a/ChibiOS_20.3.2/os/common/ports/AVR/compilers/GCC/rules.mk b/ChibiOS_20.3.2/os/common/ports/AVR/compilers/GCC/rules.mk
new file mode 100644
index 0000000..f5a105d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/AVR/compilers/GCC/rules.mk
@@ -0,0 +1,284 @@
+# AVR common makefile scripts and rules.
+
+##############################################################################
+# Processing options coming from the upper Makefile.
+#
+
+# Compiler options
+OPT := $(USE_OPT)
+COPT := $(USE_COPT)
+CPPOPT := $(USE_CPPOPT)
+
+# Output directory and files
+ifeq ($(BUILDDIR),)
+ BUILDDIR = build
+endif
+ifeq ($(BUILDDIR),.)
+ BUILDDIR = build
+endif
+OUTFILES := $(BUILDDIR)/$(PROJECT).elf \
+ $(BUILDDIR)/$(PROJECT).hex \
+ $(BUILDDIR)/$(PROJECT).bin \
+ $(BUILDDIR)/$(PROJECT).eep \
+ $(BUILDDIR)/$(PROJECT).lss \
+ $(BUILDDIR)/$(PROJECT).sym
+
+ifdef SREC
+ OUTFILES += $(BUILDDIR)/$(PROJECT).srec
+endif
+
+# Source files groups and paths
+ASRC := $(CSRC) $(CPPSRC)
+SRCPATHS := $(sort $(dir $(ASMXSRC)) $(dir $(ASMSRC)) $(dir $(ASRC)))
+
+# Various directories
+OBJDIR := $(BUILDDIR)/obj
+LSTDIR := $(BUILDDIR)/lst
+
+# Object files groups
+ACOBJS := $(addprefix $(OBJDIR)/, $(notdir $(CSRC:.c=.o)))
+ACPPOBJS := $(addprefix $(OBJDIR)/, $(notdir $(CPPSRC:.cpp=.o)))
+ASMOBJS := $(addprefix $(OBJDIR)/, $(notdir $(ASMSRC:.s=.o)))
+ASMXOBJS := $(addprefix $(OBJDIR)/, $(notdir $(ASMXSRC:.S=.o)))
+OBJS := $(ASMXOBJS) $(ASMOBJS) $(ACOBJS) $(ACPPOBJS)
+
+# Paths
+IINCDIR := $(patsubst %, -I%,$(INCDIR) $(DINCDIR) $(UINCDIR))
+LLIBDIR := $(patsubst %, -L%,$(DLIBDIR) $(ULIBDIR))
+LLIBDIR += -L$(dir $(LDSCRIPT))
+
+# Macros
+DEFS := $(DDEFS) $(UDEFS)
+ADEFS := $(DADEFS) $(UADEFS)
+
+# Libs
+LIBS := $(DLIBS) $(ULIBS)
+
+# Compiler flag to set the C Standard level.
+# c89 = "ANSI" C
+# gnu89 = c89 plus GCC extensions
+# c99 = ISO C99 standard (not yet fully implemented)
+# gnu99 = c99 plus GCC extensions
+CSTANDARD = -std=gnu11
+
+# Place -D or -U options here for C sources
+CDEFS = -DF_CPU=$(F_CPU)UL
+
+# Place -D or -U options here for ASM sources
+ADEFS = -DF_CPU=$(F_CPU)
+
+# Place -D or -U options here for C++ sources
+CPPDEFS = -DF_CPU=$(F_CPU)UL
+
+# Paths where to search for sources
+VPATH = $(SRCPATHS)
+
+# Various settings
+MCFLAGS := -mmcu=$(MCU)
+CFLAGS = $(MCFLAGS) -I. -gdwarf-2 $(CDEFS) $(OPT) -funsigned-char
+CFLAGS += -funsigned-bitfields -fpack-struct -fshort-enums $(CWARN)
+CFLAGS += -Wa,-adhlns=$(LSTDIR)/$(notdir $(<:.c=.lst)) $(DEFS)
+CFLAGS += -std=gnu11 -mrelax -fdata-sections -ffunction-sections
+CFLAGS += -Wundef -MMD -MP #-MF
+
+#---------------- Assembler Options ----------------
+# -Wa,...: tell GCC to pass this to the assembler.
+# -adhlns: create listing
+# -gstabs: have the assembler create line number information; note that
+# for use in COFF files, additional information about filenames
+# and function names needs to be present in the assembler source
+# files -- see avr-libc docs [FIXME: not yet described there]
+# -listing-cont-lines: Sets the maximum number of continuation lines of hex
+# dump that will be displayed for a given single line of source input.
+ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs, \
+ --listing-cont-lines=100
+
+#---------------- Library Options ----------------
+# Minimalistic printf version
+PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
+
+# Floating point printf version (requires MATH_LIB = -lm below)
+PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
+
+# If this is left blank, then it will use the Standard printf version.
+PRINTF_LIB = $(PRINTF_LIB_MIN)
+#PRINTF_LIB = $(PRINTF_LIB_MIN)
+#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
+
+# Minimalistic scanf version
+SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
+
+# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
+SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
+
+# If this is left blank, then it will use the Standard scanf version.
+SCANF_LIB = $(SCANF_LIB_MIN)
+#SCANF_LIB = $(SCANF_LIB_MIN)
+#SCANF_LIB = $(SCANF_LIB_FLOAT)
+
+MATH_LIB = -lm
+
+#---------------- Linker Options ----------------
+# -Wl,...: tell GCC to pass this to linker.
+# -Map: create map file
+# --cref: add cross reference to map file
+
+#LDFLAGS = -Wl,-Map=$(TARGET).map,--cref,--gc-sections
+#LDFLAGS += $(EXTMEMOPTS)
+#LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
+#LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
+
+LDFLAGS = -Wl,-Map=$(BUILDDIR)/$(PROJECT).map,--cref,--gc-sections
+LDFLAGS += -Wl,-u,vfprintf -lprintf_min -Wl,-u,vfscanf -lscanf_min -lm
+
+#
+# Makefile rules
+#
+
+all: PRE_MAKE_ALL_RULE_HOOK $(OBJS) $(OUTFILES) POST_MAKE_ALL_RULE_HOOK
+
+PRE_MAKE_ALL_RULE_HOOK:
+
+POST_MAKE_ALL_RULE_HOOK:
+
+$(OBJS): | $(BUILDDIR) $(OBJDIR) $(LSTDIR)
+
+$(BUILDDIR):
+ifneq ($(USE_VERBOSE_COMPILE),yes)
+ @echo Compiler Options
+ @echo $(CC) -c $(CFLAGS) -I. $(IINCDIR) main.c -o main.o
+ @echo
+endif
+ @mkdir -p $(BUILDDIR)
+
+$(OBJDIR):
+ @mkdir -p $(OBJDIR)
+
+$(LSTDIR):
+ @mkdir -p $(LSTDIR)
+
+$(ACPPOBJS) : $(OBJDIR)/%.o : %.cpp Makefile
+ifeq ($(USE_VERBOSE_COMPILE),yes)
+ @echo
+ $(CPPC) -c $(CPPFLAGS) $(MOPT) $(IINCDIR) $< -o $@
+else
+ @echo Compiling $( $@
+else
+ @echo Creating $@
+ @$(OD) -h -S $< > $@
+endif
+
+%.sym: %.elf
+ifeq ($(USE_VERBOSE_COMPILE),yes)
+ @echo
+ $(NM) -n $< > $@
+ $(SZ) $<
+ @echo
+ if test -f $(BUILDDIR)/$(PROJECT).elf; then echo; echo $(MSG_SIZE_AFTER); \
+ $(ELFSIZE); 2>/dev/null; echo; fi
+ @echo Done
+else
+ @echo Creating $@
+ @$(NM) -n $< > $@
+ @echo
+ @$(SZ) $<
+ @if test -f $(BUILDDIR)/$(PROJECT).elf; then echo; echo $(MSG_SIZE_AFTER); \
+ $(ELFSIZE); 2>/dev/null; echo; fi
+ @echo Done
+endif
+
+lib: $(OBJS) $(BUILDDIR)/lib$(PROJECT).a
+
+$(BUILDDIR)/lib$(PROJECT).a: $(OBJS)
+ @$(AR) -r $@ $^
+ @echo
+ @echo Done
+
+clean: CLEAN_RULE_HOOK
+ @echo Cleaning
+ -rm -fR .dep $(BUILDDIR)
+ @echo
+ @echo Done
+
+CLEAN_RULE_HOOK:
+
+#
+# Include the dependency files, should be the last of the makefile
+#
+-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
+
+# *** EOF ***
diff --git a/ChibiOS_20.3.2/os/common/ports/SIMIA32/chcore.c b/ChibiOS_20.3.2/os/common/ports/SIMIA32/chcore.c
new file mode 100644
index 0000000..ef1a475
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/SIMIA32/chcore.c
@@ -0,0 +1,131 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file SIMIA32/chcore.c
+ * @brief Simulator on IA32 port code.
+ *
+ * @addtogroup SIMIA32_GCC_CORE
+ * @{
+ */
+
+#if defined(WIN32)
+#include
+#else
+#include
+#endif
+
+#include "ch.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+bool port_isr_context_flag;
+syssts_t port_irq_sts;
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * Performs a context switch between two threads.
+ * @param otp the thread to be switched out
+ * @param ntp the thread to be switched in
+ */
+__attribute__((used))
+static void __dummy(thread_t *ntp, thread_t *otp) {
+ (void)ntp; (void)otp;
+
+ asm volatile (
+#if defined(WIN32)
+ ".globl @port_switch@8 \n\t"
+ "@port_switch@8:"
+#elif defined(__APPLE__)
+ ".globl _port_switch \n\t"
+ "_port_switch:"
+#else
+ ".globl port_switch \n\t"
+ "port_switch:"
+#endif
+ "push %ebp \n\t"
+ "push %esi \n\t"
+ "push %edi \n\t"
+ "push %ebx \n\t"
+ "movl %esp, 12(%edx) \n\t"
+ "movl 12(%ecx), %esp \n\t"
+ "pop %ebx \n\t"
+ "pop %edi \n\t"
+ "pop %esi \n\t"
+ "pop %ebp \n\t"
+ "ret");
+}
+
+/**
+ * @brief Start a thread by invoking its work function.
+ * @details If the work function returns @p chThdExit() is automatically
+ * invoked.
+ */
+__attribute__((cdecl, noreturn))
+void _port_thread_start(msg_t (*pf)(void *), void *p) {
+
+ chSysUnlock();
+ pf(p);
+ chThdExit(0);
+ while(1);
+}
+
+
+/**
+ * @brief Returns the current value of the realtime counter.
+ *
+ * @return The realtime counter value.
+ */
+rtcnt_t port_rt_get_counter_value(void) {
+#if defined(WIN32)
+ LARGE_INTEGER n;
+
+ QueryPerformanceCounter(&n);
+
+ return (rtcnt_t)(n.QuadPart / 1000LL);
+#else
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ return ((rtcnt_t)tv.tv_sec * (rtcnt_t)1000000) + (rtcnt_t)tv.tv_usec;
+#endif
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/SIMIA32/chcore.h b/ChibiOS_20.3.2/os/common/ports/SIMIA32/chcore.h
new file mode 100644
index 0000000..e804193
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/SIMIA32/chcore.h
@@ -0,0 +1,461 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file SIMIA32/chcore.h
+ * @brief Simulator on IA32 port macros and structures.
+ *
+ * @addtogroup SIMIA32_GCC_CORE
+ * @{
+ */
+
+#ifndef CHCORE_H
+#define CHCORE_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Port Capabilities and Constants
+ * @{
+ */
+/**
+ * @brief This port supports a realtime counter.
+ */
+#define PORT_SUPPORTS_RT TRUE
+
+/**
+ * @brief Natural alignment constant.
+ * @note It is the minimum alignment for pointer-size variables.
+ */
+#define PORT_NATURAL_ALIGN sizeof (void *)
+
+/**
+ * @brief Stack alignment constant.
+ * @note It is the alignment required for the stack pointer.
+ */
+#define PORT_STACK_ALIGN sizeof (stkalign_t)
+
+/**
+ * @brief Working Areas alignment constant.
+ * @note It is the alignment to be enforced for thread working areas.
+ */
+#define PORT_WORKING_AREA_ALIGN sizeof (stkalign_t)
+/** @} */
+
+/**
+ * @name Architecture and Compiler
+ * @{
+ */
+/**
+ * Macro defining the a simulated architecture into x86.
+ */
+#define PORT_ARCHITECTURE_SIMIA32
+
+/**
+ * Name of the implemented architecture.
+ */
+#define PORT_ARCHITECTURE_NAME "Simulator"
+
+/**
+ * @brief Name of the architecture variant (optional).
+ */
+#define PORT_CORE_VARIANT_NAME "x86 (integer only)"
+
+/**
+ * @brief Name of the compiler supported by this port.
+ */
+#define PORT_COMPILER_NAME "GCC " __VERSION__
+
+/**
+ * @brief Port-specific information string.
+ */
+#define PORT_INFO "No preemption"
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Stack size for the system idle thread.
+ * @details This size depends on the idle thread implementation, usually
+ * the idle thread should take no more space than those reserved
+ * by @p PORT_INT_REQUIRED_STACK.
+ */
+#if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__)
+#define PORT_IDLE_THREAD_STACK_SIZE 256
+#endif
+
+/**
+ * @brief Per-thread stack overhead for interrupts servicing.
+ * @details This constant is used in the calculation of the correct working
+ * area size.
+ */
+#if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__)
+#define PORT_INT_REQUIRED_STACK 16384
+#endif
+
+/**
+ * @brief Enables an alternative timer implementation.
+ * @details Usually the port uses a timer interface defined in the file
+ * @p chcore_timer.h, if this option is enabled then the file
+ * @p chcore_timer_alt.h is included instead.
+ */
+#if !defined(PORT_USE_ALT_TIMER) || defined(__DOXYGEN__)
+#define PORT_USE_ALT_TIMER FALSE
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if CH_DBG_ENABLE_STACK_CHECK
+#error "option CH_DBG_ENABLE_STACK_CHECK not supported by this port"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/**
+ * @brief 16 bytes stack and memory alignment enforcement.
+ */
+typedef struct {
+ uint8_t a[16];
+} stkalign_t __attribute__((aligned(16)));
+
+/**
+ * @brief Type of a generic x86 register.
+ */
+typedef void *regx86;
+
+/**
+ * @brief Interrupt saved context.
+ * @details This structure represents the stack frame saved during a
+ * preemption-capable interrupt handler.
+ */
+struct port_extctx {
+};
+
+/**
+ * @brief System saved context.
+ * @details This structure represents the inner stack frame during a context
+ * switch.
+ */
+struct port_intctx {
+ regx86 ebx;
+ regx86 edi;
+ regx86 esi;
+ regx86 ebp;
+ regx86 eip;
+};
+
+/**
+ * @brief Platform dependent part of the @p thread_t structure.
+ * @details This structure usually contains just the saved stack pointer
+ * defined as a pointer to a @p port_intctx structure.
+ */
+struct port_context {
+ struct port_intctx *sp;
+};
+
+#endif /* !defined(_FROM_ASM_) */
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+#define APUSH(p, a) do { \
+ (p) -= sizeof(void *); \
+ *(void **)(p) = (void*)(a); \
+} while (false)
+
+/* Darwin requires the stack to be aligned to a 16-byte boundary at
+ * the time of a call instruction (in case the called function needs
+ * to save MMX registers). This aligns to 'mod' module 16, so that we'll end
+ * up with the right alignment after pushing the args. */
+#define AALIGN(p, mask, mod) \
+ p = (void *)((((uint32_t)(p) - (uint32_t)(mod)) & ~(uint32_t)(mask)) + (uint32_t)(mod)) \
+
+/**
+ * @brief Platform dependent part of the @p chThdCreateI() API.
+ * @details This code usually setup the context switching frame represented
+ * by an @p port_intctx structure.
+ */
+#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \
+ /*lint -save -e611 -e9033 -e9074 -e9087 [10.8, 11.1, 11.3] Valid casts.*/ \
+ uint8_t *esp = (uint8_t *)wtop; \
+ APUSH(esp, 0); \
+ uint8_t *savebp = esp; \
+ AALIGN(esp, 15, 8); \
+ APUSH(esp, arg); \
+ APUSH(esp, pf); \
+ APUSH(esp, 0); \
+ esp -= sizeof(struct port_intctx); \
+ ((struct port_intctx *)esp)->eip = (void *)_port_thread_start; \
+ ((struct port_intctx *)esp)->ebx = NULL; \
+ ((struct port_intctx *)esp)->edi = NULL; \
+ ((struct port_intctx *)esp)->esi = NULL; \
+ ((struct port_intctx *)esp)->ebp = (void *)savebp; \
+ (tp)->ctx.sp = (struct port_intctx *)esp; \
+ /*lint -restore*/ \
+}
+
+ /**
+ * @brief Computes the thread working area global size.
+ * @note There is no need to perform alignments in this macro.
+ */
+#define PORT_WA_SIZE(n) ((sizeof (void *) * 4U) + \
+ sizeof (struct port_intctx) + \
+ ((size_t)(n)) + \
+ ((size_t)(PORT_INT_REQUIRED_STACK)))
+
+/**
+ * @brief Static working area allocation.
+ * @details This macro is used to allocate a static thread working area
+ * aligned as both position and size.
+ *
+ * @param[in] s the name to be assigned to the stack array
+ * @param[in] n the stack size to be assigned to the thread
+ */
+#define PORT_WORKING_AREA(s, n) \
+ stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)]
+
+/**
+ * @brief IRQ prologue code.
+ * @details This macro must be inserted at the start of all IRQ handlers
+ * enabled to invoke system APIs.
+ */
+#define PORT_IRQ_PROLOGUE() { \
+ port_isr_context_flag = true; \
+}
+
+/**
+ * @brief IRQ epilogue code.
+ * @details This macro must be inserted at the end of all IRQ handlers
+ * enabled to invoke system APIs.
+ */
+#define PORT_IRQ_EPILOGUE() { \
+ port_isr_context_flag = false; \
+}
+
+/**
+ * @brief IRQ handler function declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ */
+#ifdef __cplusplus
+#define PORT_IRQ_HANDLER(id) extern "C" void id(void)
+#else
+#define PORT_IRQ_HANDLER(id) void id(void)
+#endif
+
+/**
+ * @brief Fast IRQ handler function declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ */
+#ifdef __cplusplus
+#define PORT_FAST_IRQ_HANDLER(id) extern "C" void id(void)
+#else
+#define PORT_FAST_IRQ_HANDLER(id) void id(void)
+#endif
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+extern bool port_isr_context_flag;
+extern syssts_t port_irq_sts;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ /*lint -save -e950 [Dir-2.1] Non-ANSI keywords are fine in the port layer.*/
+ __attribute__((fastcall)) void port_switch(thread_t *ntp, thread_t *otp);
+ __attribute__((cdecl, noreturn)) void _port_thread_start(msg_t (*pf)(void *p),
+ void *p);
+ /*lint -restore*/
+ rtcnt_t port_rt_get_counter_value(void);
+ void _sim_check_for_interrupts(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined(_FROM_ASM_) */
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/**
+ * @brief Port-related initialization code.
+ */
+static inline void port_init(void) {
+
+ port_irq_sts = (syssts_t)0;
+ port_isr_context_flag = false;
+}
+
+/**
+ * @brief Returns a word encoding the current interrupts status.
+ *
+ * @return The interrupts status.
+ */
+static inline syssts_t port_get_irq_status(void) {
+
+ return port_irq_sts;
+}
+
+/**
+ * @brief Checks the interrupt status.
+ *
+ * @param[in] sts the interrupt status word
+ *
+ * @return The interrupt status.
+ * @retval false the word specified a disabled interrupts status.
+ * @retval true the word specified an enabled interrupts status.
+ */
+static inline bool port_irq_enabled(syssts_t sts) {
+
+ return sts == (syssts_t)0;
+}
+
+/**
+ * @brief Determines the current execution context.
+ *
+ * @return The execution context.
+ * @retval false not running in ISR mode.
+ * @retval true running in ISR mode.
+ */
+static inline bool port_is_isr_context(void) {
+
+ return port_isr_context_flag;
+}
+
+/**
+ * @brief Kernel-lock action.
+ * @details In this port this function disables interrupts globally.
+ */
+static inline void port_lock(void) {
+
+ port_irq_sts = (syssts_t)1;
+}
+
+/**
+ * @brief Kernel-unlock action.
+ * @details In this port this function enables interrupts globally.
+ */
+static inline void port_unlock(void) {
+
+ port_irq_sts = (syssts_t)0;
+}
+
+/**
+ * @brief Kernel-lock action from an interrupt handler.
+ * @details In this port this function disables interrupts globally.
+ * @note Same as @p port_lock() in this port.
+ */
+static inline void port_lock_from_isr(void) {
+
+ port_irq_sts = (syssts_t)1;
+}
+
+/**
+ * @brief Kernel-unlock action from an interrupt handler.
+ * @details In this port this function enables interrupts globally.
+ * @note Same as @p port_lock() in this port.
+ */
+static inline void port_unlock_from_isr(void) {
+
+ port_irq_sts = (syssts_t)0;
+}
+
+/**
+ * @brief Disables all the interrupt sources.
+ */
+static inline void port_disable(void) {
+
+ port_irq_sts = (syssts_t)1;
+}
+
+/**
+ * @brief Disables the interrupt sources below kernel-level priority.
+ */
+static inline void port_suspend(void) {
+
+ port_irq_sts = (syssts_t)1;
+}
+
+/**
+ * @brief Enables all the interrupt sources.
+ */
+static inline void port_enable(void) {
+
+ port_irq_sts = (syssts_t)0;
+}
+
+/**
+ * @brief Enters an architecture-dependent IRQ-waiting mode.
+ * @details The function is meant to return when an interrupt becomes pending.
+ * The simplest implementation is an empty function or macro but this
+ * would not take advantage of architecture-specific power saving
+ * modes.
+ * @note Implemented as an inlined @p WFI instruction.
+ */
+static inline void port_wait_for_interrupt(void) {
+
+ _sim_check_for_interrupts();
+}
+
+#endif /* !defined(_FROM_ASM_) */
+
+/*===========================================================================*/
+/* Module late inclusions. */
+/*===========================================================================*/
+
+#if !defined(_FROM_ASM_)
+
+#if CH_CFG_ST_TIMEDELTA > 0
+#if !PORT_USE_ALT_TIMER
+#include "chcore_timer.h"
+#else /* PORT_USE_ALT_TIMER */
+#include "chcore_timer_alt.h"
+#endif /* PORT_USE_ALT_TIMER */
+#endif /* CH_CFG_ST_TIMEDELTA > 0 */
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CHCORE_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/SIMIA32/compilers/GCC/chtypes.h b/ChibiOS_20.3.2/os/common/ports/SIMIA32/compilers/GCC/chtypes.h
new file mode 100644
index 0000000..6ed1f04
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/SIMIA32/compilers/GCC/chtypes.h
@@ -0,0 +1,109 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file SIMIA32/compilers/GCC/chtypes.h
+ * @brief Simulator on IA32 port system types.
+ *
+ * @addtogroup SIMIA32_GCC_CORE
+ * @{
+ */
+
+#ifndef CHTYPES_H
+#define CHTYPES_H
+
+#include
+#include
+#include
+
+/**
+ * @name Derived generic types
+ * @{
+ */
+typedef volatile int8_t vint8_t; /**< Volatile signed 8 bits. */
+typedef volatile uint8_t vuint8_t; /**< Volatile unsigned 8 bits. */
+typedef volatile int16_t vint16_t; /**< Volatile signed 16 bits. */
+typedef volatile uint16_t vuint16_t; /**< Volatile unsigned 16 bits. */
+typedef volatile int32_t vint32_t; /**< Volatile signed 32 bits. */
+typedef volatile uint32_t vuint32_t; /**< Volatile unsigned 32 bits. */
+/** @} */
+
+/**
+ * @name Kernel types
+ * @{
+ */
+typedef uint32_t rtcnt_t; /**< Realtime counter. */
+typedef uint64_t rttime_t; /**< Realtime accumulator. */
+typedef uint32_t syssts_t; /**< System status word. */
+typedef uint8_t tmode_t; /**< Thread flags. */
+typedef uint8_t tstate_t; /**< Thread state. */
+typedef uint8_t trefs_t; /**< Thread references counter. */
+typedef uint8_t tslices_t; /**< Thread time slices counter.*/
+typedef uint32_t tprio_t; /**< Thread priority. */
+typedef int32_t msg_t; /**< Inter-thread message. */
+typedef int32_t eventid_t; /**< Numeric event identifier. */
+typedef uint32_t eventmask_t; /**< Mask of event identifiers. */
+typedef uint32_t eventflags_t; /**< Mask of event flags. */
+typedef int32_t cnt_t; /**< Generic signed counter. */
+typedef uint32_t ucnt_t; /**< Generic unsigned counter. */
+/** @} */
+
+/**
+ * @brief ROM constant modifier.
+ * @note It is set to use the "const" keyword in this port.
+ */
+#define ROMCONST const
+
+/**
+ * @brief Makes functions not inlineable.
+ * @note If the compiler does not support such attribute then some
+ * time-dependent services could be degraded.
+ */
+#define NOINLINE __attribute__((noinline))
+
+/**
+ * @brief Optimized thread function declaration macro.
+ */
+#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg)
+
+/**
+ * @brief Packed variable specifier.
+ */
+#define PACKED_VAR __attribute__((packed))
+
+/**
+ * @brief Memory alignment enforcement for variables.
+ */
+#define ALIGNED_VAR(n) __attribute__((aligned(n)))
+
+/**
+ * @brief Size of a pointer.
+ * @note To be used where the sizeof operator cannot be used, preprocessor
+ * expressions for example.
+ */
+#define SIZEOF_PTR 4
+
+/**
+ * @brief True if alignment is low-high in current architecture.
+ */
+#define REVERSE_ORDER 1
+
+#endif /* CHTYPES_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/SIMIA32/compilers/GCC/port.mk b/ChibiOS_20.3.2/os/common/ports/SIMIA32/compilers/GCC/port.mk
new file mode 100644
index 0000000..f3657ee
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/SIMIA32/compilers/GCC/port.mk
@@ -0,0 +1,12 @@
+# List of the ChibiOS/RT SIMIA32 port files.
+PORTSRC = ${CHIBIOS}/os/common/ports/SIMIA32/chcore.c
+
+PORTASM =
+
+PORTINC = ${CHIBIOS}/os/common/ports/SIMIA32/compilers/GCC \
+ ${CHIBIOS}/os/common/ports/SIMIA32
+
+# Shared variables
+ALLXASMSRC += $(PORTASM)
+ALLCSRC += $(PORTSRC)
+ALLINC += $(PORTINC)
diff --git a/ChibiOS_20.3.2/os/common/ports/e200/chcore.c b/ChibiOS_20.3.2/os/common/ports/e200/chcore.c
new file mode 100644
index 0000000..ed0b908
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/e200/chcore.c
@@ -0,0 +1,54 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file e200/chcore.c
+ * @brief Power e200 port code.
+ *
+ * @addtogroup PPC_CORE
+ * @{
+ */
+
+#include "ch.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/e200/chcore.h b/ChibiOS_20.3.2/os/common/ports/e200/chcore.h
new file mode 100644
index 0000000..f7832ef
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/e200/chcore.h
@@ -0,0 +1,722 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file PPC/chcore.h
+ * @brief Power e200 port macros and structures.
+ *
+ * @addtogroup PPC_CORE
+ * @{
+ */
+
+#ifndef CHCORE_H
+#define CHCORE_H
+
+#if defined(__ghs__) && !defined(_FROM_ASM_)
+#include
+#endif
+
+#include "intc.h"
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Port Capabilities and Constants
+ * @{
+ */
+/**
+ * @brief This port supports a realtime counter.
+ */
+#define PORT_SUPPORTS_RT FALSE
+
+/**
+ * @brief Natural alignment constant.
+ * @note It is the minimum alignment for pointer-size variables.
+ */
+#define PORT_NATURAL_ALIGN sizeof (void *)
+
+/**
+ * @brief Stack alignment constant.
+ * @note It is the alignment required for the stack pointer.
+ */
+#define PORT_STACK_ALIGN sizeof (stkalign_t)
+
+/**
+ * @brief Working Areas alignment constant.
+ * @note It is the alignment to be enforced for thread working areas.
+ */
+#define PORT_WORKING_AREA_ALIGN sizeof (stkalign_t)
+/** @} */
+
+/**
+ * @name Architecture and Compiler
+ * @{
+ */
+/**
+ * @brief Macro defining an PPC architecture.
+ */
+#define PORT_ARCHITECTURE_PPC
+
+/**
+ * @brief Macro defining the specific PPC architecture.
+ */
+#define PORT_ARCHITECTURE_PPC_E200
+
+/**
+ * @brief Name of the implemented architecture.
+ */
+#define PORT_ARCHITECTURE_NAME "Power Architecture e200"
+
+/**
+ * @brief Compiler name and version.
+ */
+#if (defined(__GNUC__) && !defined(__ghs__)) || defined(__DOXYGEN__)
+#define PORT_COMPILER_NAME "GCC " __VERSION__
+
+#elif defined(__MWERKS__)
+#define PORT_COMPILER_NAME "CW"
+
+#elif defined(__ghs__)
+#define PORT_COMPILER_NAME "GHS"
+
+#else
+#error "unsupported compiler"
+#endif
+/** @} */
+
+/**
+ * @name E200 core variants
+ * @{
+ */
+#define PPC_VARIANT_e200z0 200
+#define PPC_VARIANT_e200z2 202
+#define PPC_VARIANT_e200z3 203
+#define PPC_VARIANT_e200z4 204
+/** @} */
+
+/* Inclusion of the PPC implementation specific parameters.*/
+#include "ppcparams.h"
+#include "vectors.h"
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Stack size for the system idle thread.
+ * @details This size depends on the idle thread implementation, usually
+ * the idle thread should take no more space than those reserved
+ * by @p PORT_INT_REQUIRED_STACK.
+ * @note In this port it is set to 32 because the idle thread does have
+ * a stack frame when compiling without optimizations. You may
+ * reduce this value to zero when compiling with optimizations.
+ */
+#if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__)
+#define PORT_IDLE_THREAD_STACK_SIZE 32
+#endif
+
+/**
+ * @brief Per-thread stack overhead for interrupts servicing.
+ * @details This constant is used in the calculation of the correct working
+ * area size.
+ * @note In this port this value is conservatively is set to 256 because
+ * there is no separate interrupts stack (yet).
+ */
+#if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__)
+#define PORT_INT_REQUIRED_STACK 256
+#endif
+
+/**
+ * @brief Enables an alternative timer implementation.
+ * @details Usually the port uses a timer interface defined in the file
+ * @p chcore_timer.h, if this option is enabled then the file
+ * @p chcore_timer_alt.h is included instead.
+ */
+#if !defined(PORT_USE_ALT_TIMER) || defined(__DOXYGEN__)
+#define PORT_USE_ALT_TIMER FALSE
+#endif
+
+/**
+ * @brief Use VLE instruction set.
+ * @note This parameter is usually set in the Makefile.
+ */
+#if !defined(PPC_USE_VLE) || defined(__DOXYGEN__)
+#define PPC_USE_VLE TRUE
+#endif
+
+/**
+ * @brief Enables the use of the @p WFI instruction.
+ */
+#if !defined(PPC_ENABLE_WFI_IDLE) || defined(__DOXYGEN__)
+#define PPC_ENABLE_WFI_IDLE FALSE
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if PPC_USE_VLE && !PPC_SUPPORTS_VLE
+#error "the selected MCU does not support VLE instructions set"
+#endif
+
+#if !PPC_USE_VLE && !PPC_SUPPORTS_BOOKE
+#error "the selected MCU does not support BookE instructions set"
+#endif
+
+/**
+ * @brief Name of the architecture variant.
+ */
+#if (PPC_VARIANT == PPC_VARIANT_e200z0) || defined(__DOXYGEN__)
+
+#if !defined(CH_CUSTOMER_LIC_PORT_E200Z0)
+#error "CH_CUSTOMER_LIC_PORT_E200Z0 not defined"
+#endif
+
+#if CH_CUSTOMER_LIC_PORT_E200Z0 == FALSE
+#error "ChibiOS Power e200z0 port not licensed"
+#endif
+
+#define PORT_CORE_VARIANT_NAME "e200z0"
+
+#elif PPC_VARIANT == PPC_VARIANT_e200z2
+
+#if !defined(CH_CUSTOMER_LIC_PORT_E200Z2)
+#error "CH_CUSTOMER_LIC_PORT_E200Z2 not defined"
+#endif
+
+#if CH_CUSTOMER_LIC_PORT_E200Z2 == FALSE
+#error "ChibiOS Power e200z2 port not licensed"
+#endif
+
+#define PORT_CORE_VARIANT_NAME "e200z2"
+
+#elif PPC_VARIANT == PPC_VARIANT_e200z3
+
+#if !defined(CH_CUSTOMER_LIC_PORT_E200Z3)
+#error "CH_CUSTOMER_LIC_PORT_E200Z3 not defined"
+#endif
+
+#if CH_CUSTOMER_LIC_PORT_E200Z3 == FALSE
+#error "ChibiOS Power e200z3 port not licensed"
+#endif
+
+#define PORT_CORE_VARIANT_NAME "e200z3"
+
+#elif PPC_VARIANT == PPC_VARIANT_e200z4
+
+#if !defined(CH_CUSTOMER_LIC_PORT_E200Z4)
+#error "CH_CUSTOMER_LIC_PORT_E200Z4 not defined"
+#endif
+
+#if CH_CUSTOMER_LIC_PORT_E200Z4 == FALSE
+#error "ChibiOS Power e200z4 port not licensed"
+#endif
+
+#define PORT_CORE_VARIANT_NAME "e200z4"
+
+#else
+#error "unknown or unsupported PowerPC variant specified"
+#endif
+
+/**
+ * @brief Port-specific information string.
+ */
+#if PPC_USE_VLE
+#define PORT_INFO "VLE mode"
+#else
+#define PORT_INFO "Book-E mode"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/**
+ * @brief Type of stack and memory alignment enforcement.
+ * @note In this architecture the stack alignment is enforced to 64 bits.
+ */
+typedef uint64_t stkalign_t;
+
+/**
+ * @brief Generic PPC register.
+ */
+typedef void *regppc_t;
+
+/**
+ * @brief Mandatory part of a stack frame.
+ */
+struct port_eabi_frame {
+ uint32_t slink; /**< Stack back link. */
+ uint32_t shole; /**< Stack hole for LR storage. */
+};
+
+/**
+ * @brief Interrupt saved context.
+ * @details This structure represents the stack frame saved during a
+ * preemption-capable interrupt handler.
+ * @note R2 and R13 are not saved because those are assumed to be immutable
+ * during the system life cycle.
+ */
+struct port_extctx {
+ struct port_eabi_frame frame;
+ /* Start of the e_stmvsrrw frame (offset 8).*/
+ regppc_t pc;
+ regppc_t msr;
+ /* Start of the e_stmvsprw frame (offset 16).*/
+ regppc_t cr;
+ regppc_t lr;
+ regppc_t ctr;
+ regppc_t xer;
+ /* Start of the e_stmvgprw frame (offset 32).*/
+ regppc_t r0;
+ regppc_t r3;
+ regppc_t r4;
+ regppc_t r5;
+ regppc_t r6;
+ regppc_t r7;
+ regppc_t r8;
+ regppc_t r9;
+ regppc_t r10;
+ regppc_t r11;
+ regppc_t r12;
+ regppc_t padding;
+};
+
+/**
+ * @brief System saved context.
+ * @details This structure represents the inner stack frame during a context
+ * switching.
+ * @note R2 and R13 are not saved because those are assumed to be immutable
+ * during the system life cycle.
+ * @note LR is stored in the caller context so it is not present in this
+ * structure.
+ */
+struct port_intctx {
+ regppc_t cr; /* Part of it is not volatile... */
+ regppc_t r14;
+ regppc_t r15;
+ regppc_t r16;
+ regppc_t r17;
+ regppc_t r18;
+ regppc_t r19;
+ regppc_t r20;
+ regppc_t r21;
+ regppc_t r22;
+ regppc_t r23;
+ regppc_t r24;
+ regppc_t r25;
+ regppc_t r26;
+ regppc_t r27;
+ regppc_t r28;
+ regppc_t r29;
+ regppc_t r30;
+ regppc_t r31;
+ regppc_t padding;
+};
+
+/**
+ * @brief Platform dependent part of the @p thread_t structure.
+ * @details This structure usually contains just the saved stack pointer
+ * defined as a pointer to a @p port_intctx structure.
+ */
+struct port_context {
+ struct port_intctx *sp;
+};
+
+#endif /* !defined(_FROM_ASM_) */
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Platform dependent part of the @p chThdCreateI() API.
+ * @details This code usually setup the context switching frame represented
+ * by an @p port_intctx structure.
+ */
+#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \
+ uint8_t *sp = (uint8_t *)(wtop) - sizeof(struct port_eabi_frame); \
+ ((struct port_eabi_frame *)sp)->slink = 0; \
+ ((struct port_eabi_frame *)sp)->shole = (uint32_t)_port_thread_start; \
+ (tp)->ctx.sp = (struct port_intctx *)(sp - sizeof(struct port_intctx)); \
+ (tp)->ctx.sp->r31 = (regppc_t)(arg); \
+ (tp)->ctx.sp->r30 = (regppc_t)(pf); \
+}
+
+/**
+ * @brief Computes the thread working area global size.
+ * @note There is no need to perform alignments in this macro.
+ */
+#define PORT_WA_SIZE(n) (sizeof(struct port_intctx) + \
+ sizeof(struct port_extctx) + \
+ ((size_t)(n)) + ((size_t)(PORT_INT_REQUIRED_STACK)))
+
+/**
+ * @brief Static working area allocation.
+ * @details This macro is used to allocate a static thread working area
+ * aligned as both position and size.
+ *
+ * @param[in] s the name to be assigned to the stack array
+ * @param[in] n the stack size to be assigned to the thread
+ */
+#define PORT_WORKING_AREA(s, n) \
+ stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)]
+
+/**
+ * @brief IRQ prologue code.
+ * @details This macro must be inserted at the start of all IRQ handlers
+ * enabled to invoke system APIs.
+ */
+#define PORT_IRQ_PROLOGUE()
+
+/**
+ * @brief IRQ epilogue code.
+ * @details This macro must be inserted at the end of all IRQ handlers
+ * enabled to invoke system APIs.
+ */
+#define PORT_IRQ_EPILOGUE()
+
+/**
+ * @brief IRQ handler function declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ */
+#ifdef __cplusplus
+#define PORT_IRQ_HANDLER(id) extern "C" void id(void)
+#else
+#define PORT_IRQ_HANDLER(id) void id(void)
+#endif
+
+/**
+ * @brief Fast IRQ handler function declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ */
+#ifdef __cplusplus
+#define PORT_FAST_IRQ_HANDLER(id) extern "C" void id(void)
+#else
+#define PORT_FAST_IRQ_HANDLER(id) void id(void)
+#endif
+
+/**
+ * @brief Priority level verification macro.
+ */
+#define PORT_IRQ_IS_VALID_PRIORITY(n) \
+ (((n) >= 0U) && ((n) < INTC_PRIORITY_LEVELS))
+
+/**
+ * @brief Priority level verification macro.
+ */
+#define PORT_IRQ_IS_VALID_KERNEL_PRIORITY(n) \
+ (((n) >= 0U) && ((n) < INTC_PRIORITY_LEVELS))
+
+/**
+ * @brief Performs a context switch between two threads.
+ * @details This is the most critical code in any port, this function
+ * is responsible for the context switch between 2 threads.
+ * @note The implementation of this code affects directly the context
+ * switch performance so optimize here as much as you can.
+ *
+ * @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread to be switched out
+ */
+#if !CH_DBG_ENABLE_STACK_CHECK || defined(__DOXYGEN__)
+#define port_switch(ntp, otp) _port_switch(ntp, otp)
+#else
+#define port_switch(ntp, otp) { \
+ register struct port_intctx *sp asm ("%r1"); \
+ if ((stkalign_t *)(sp - 1) < otp->wabase) \
+ chSysHalt("stack overflow"); \
+ _port_switch(ntp, otp); \
+}
+#endif
+
+/**
+ * @brief Writes to a special register.
+ *
+ * @param[in] spr special register number
+ * @param[in] val value to be written, must be an automatic variable
+ */
+#if !defined(__ghs__) || defined(__DOXYGEN__)
+#define port_write_spr(spr, val) \
+ asm volatile ("mtspr %[p0], %[p1]" : : [p0] "n" (spr), [p1] "r" (val))
+#else
+#define port_write_spr(spr, val) \
+ __MTSPR(spr, val);
+#endif
+
+/**
+ * @brief Reads a special register.
+ *
+ * @param[in] spr special register number
+ * @param[in] val returned value, must be an automatic variable
+ */
+#if !defined(__ghs__) || defined(__DOXYGEN__)
+#define port_read_spr(spr, val) \
+ asm volatile ("mfspr %[p0], %[p1]" : [p0] "=r" (val) : [p1] "n" (spr))
+#else
+#define port_read_spr(spr, val) \
+ val = __MFSPR(spr)
+#endif
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void _port_switch(thread_t *ntp, thread_t *otp);
+ void _port_thread_start(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined(_FROM_ASM_) */
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+extern void _IVOR4(void);
+extern void _IVOR10(void);
+
+/**
+ * @brief Kernel port layer initialization.
+ * @details IVOR4 and IVOR10 initialization.
+ */
+static inline void port_init(void) {
+ uint32_t n;
+ unsigned i;
+
+ /* Initializing the SPRG0 register to zero, it is required for interrupts
+ handling.*/
+ n = 0;
+ port_write_spr(272, n);
+
+#if PPC_SUPPORTS_IVORS
+ {
+ /* The CPU supports IVOR registers, the kernel requires IVOR4 and IVOR10
+ and the initialization is performed here.*/
+ port_write_spr(404, (uint32_t)_IVOR4);
+
+#if PPC_SUPPORTS_DECREMENTER
+ port_write_spr(410, (uint32_t)_IVOR10);
+#endif
+ }
+#endif
+
+ /* INTC initialization, software vector mode, 4 bytes vectors, starting
+ at priority 0.*/
+ INTC_BCR = 0;
+ for (i = 0; i < PPC_CORE_NUMBER; i++) {
+ INTC_CPR(i) = 0;
+ INTC_IACKR(i) = (uint32_t)_vectors;
+ }
+}
+
+/**
+ * @brief Returns a word encoding the current interrupts status.
+ *
+ * @return The interrupts status.
+ */
+static inline syssts_t port_get_irq_status(void) {
+ uint32_t sts;
+
+#if defined(__ghs__)
+ sts = __GETSR();
+#else
+ asm volatile ("mfmsr %[p0]" : [p0] "=r" (sts) :);
+#endif
+
+ return sts;
+}
+
+/**
+ * @brief Checks the interrupt status.
+ *
+ * @param[in] sts the interrupt status word
+ *
+ * @return The interrupt status.
+ * @retval false the word specified a disabled interrupts status.
+ * @retval true the word specified an enabled interrupts status.
+ */
+static inline bool port_irq_enabled(syssts_t sts) {
+
+ return (bool)((sts & (1 << 15)) != 0);
+}
+
+/**
+ * @brief Determines the current execution context.
+ *
+ * @return The execution context.
+ * @retval false not running in ISR mode.
+ * @retval true running in ISR mode.
+ */
+static inline bool port_is_isr_context(void) {
+ uint32_t sprg0;
+
+ /* The SPRG0 register is increased before entering interrupt handlers and
+ decreased at the end.*/
+ port_read_spr(272, sprg0);
+ return (bool)(sprg0 > 0);
+}
+
+/**
+ * @brief Kernel-lock action.
+ * @note Implemented as global interrupt disable.
+ */
+static inline void port_lock(void) {
+
+#if defined(__ghs__)
+ __DI();
+#else
+ asm volatile ("wrteei 0" : : : "memory");
+#endif
+}
+
+/**
+ * @brief Kernel-unlock action.
+ * @note Implemented as global interrupt enable.
+ */
+static inline void port_unlock(void) {
+
+#if defined(__ghs__)
+ __EI();
+#else
+ asm volatile("wrteei 1" : : : "memory");
+#endif
+}
+
+/**
+ * @brief Kernel-lock action from an interrupt handler.
+ * @note Implementation not needed.
+ */
+static inline void port_lock_from_isr(void) {
+
+}
+
+/**
+ * @brief Kernel-unlock action from an interrupt handler.
+ * @note Implementation not needed.
+ */
+static inline void port_unlock_from_isr(void) {
+
+}
+
+/**
+ * @brief Disables all the interrupt sources.
+ * @note Implemented as global interrupt disable.
+ */
+static inline void port_disable(void) {
+
+#if defined(__ghs__)
+ __DI();
+#else
+ asm volatile ("wrteei 0" : : : "memory");
+#endif
+}
+
+/**
+ * @brief Disables the interrupt sources below kernel-level priority.
+ * @note Same as @p port_disable() in this port, there is no difference
+ * between the two states.
+ */
+static inline void port_suspend(void) {
+
+#if defined(__ghs__)
+ __DI();
+#else
+ asm volatile ("wrteei 0" : : : "memory");
+#endif
+}
+
+/**
+ * @brief Enables all the interrupt sources.
+ * @note Implemented as global interrupt enable.
+ */
+static inline void port_enable(void) {
+
+#if defined(__ghs__)
+ __EI();
+#else
+ asm volatile ("wrteei 1" : : : "memory");
+#endif
+}
+
+/**
+ * @brief Enters an architecture-dependent IRQ-waiting mode.
+ * @details The function is meant to return when an interrupt becomes pending.
+ * The simplest implementation is an empty function or macro but this
+ * would not take advantage of architecture-specific power saving
+ * modes.
+ * @note Implemented as an inlined @p wait instruction.
+ */
+static inline void port_wait_for_interrupt(void) {
+
+#if PPC_ENABLE_WFI_IDLE
+ asm volatile ("wait" : : : "memory");
+#endif
+}
+
+/**
+ * @brief Returns the current value of the realtime counter.
+ *
+ * @return The realtime counter value.
+ */
+static inline rtcnt_t port_rt_get_counter_value(void) {
+
+ return 0;
+}
+
+#endif /* !defined(_FROM_ASM_) */
+
+/*===========================================================================*/
+/* Module late inclusions. */
+/*===========================================================================*/
+
+#if !defined(_FROM_ASM_)
+
+#if CH_CFG_ST_TIMEDELTA > 0
+#if !PORT_USE_ALT_TIMER
+#include "chcore_timer.h"
+#else /* PORT_USE_ALT_TIMER */
+#include "chcore_timer_alt.h"
+#endif /* PORT_USE_ALT_TIMER */
+#endif /* CH_CFG_ST_TIMEDELTA > 0 */
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CHCORE_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/e200/compilers/CW/chcoreasm.s b/ChibiOS_20.3.2/os/common/ports/e200/compilers/CW/chcoreasm.s
new file mode 100644
index 0000000..5e55281
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/e200/compilers/CW/chcoreasm.s
@@ -0,0 +1,119 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file e200/compilers/GCC/chcoreasm.s
+ * @brief Power Architecture port low level code.
+ *
+ * @addtogroup PPC_GCC_CORE
+ * @{
+ */
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+
+/*===========================================================================*/
+/* Code section. */
+/*===========================================================================*/
+
+/*
+ * Imports the PPC configuration headers.
+ */
+#define _FROM_ASM_
+#include "chlicense.h"
+#include "chconf.h"
+#include "chcore.h"
+
+#if !defined(__DOXYGEN__)
+
+/*
+ * RTOS-specific context offset.
+ */
+#if defined(_CHIBIOS_RT_CONF_)
+#define CONTEXT_OFFSET 12
+#elif defined(_CHIBIOS_NIL_CONF_)
+#define CONTEXT_OFFSET 0
+#else
+#error "invalid chconf.h"
+#endif
+
+#if defined(_CHIBIOS_RT_CONF_)
+ .extern chThdExit
+#endif
+
+#if PPC_USE_VLE == TRUE
+ .section .text_vle, 16
+
+ .align 2
+ .globl _port_switch
+ .type _port_switch, @function
+_port_switch:
+ e_subi r1, r1, 80
+ se_mflr r0
+ e_stw r0, 84(r1)
+ mfcr r0
+ se_stw r0, 0(r1)
+ e_stmw r14, 4(r1)
+
+ se_stw r1, 12(r4)
+ se_lwz r1, 12(r3)
+
+ e_lmw r14, 4(r1)
+ se_lwz r0, 0(r1)
+ mtcr r0
+ e_lwz r0, 84(r1)
+ se_mtlr r0
+ e_addi r1, r1, 80
+ se_blr
+
+ .align 2
+ .globl _port_thread_start
+ .type _port_thread_start, @function
+_port_thread_start:
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_unlock
+#endif
+#if CH_DBG_STATISTICS
+ bl _stats_stop_measure_crit_thd
+#endif
+ wrteei 1
+ mr r3, r31
+ mtctr r30
+ se_bctrl
+ se_li r0, 0
+ e_bl chThdExit
+
+#else /* PPC_USE_VLE == FALSE */
+
+#error "non-VLE mode not yet implemented"
+
+#endif /* PPC_USE_VLE == FALSE */
+
+#endif /* !defined(__DOXYGEN__) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/e200/compilers/CW/chtypes.h b/ChibiOS_20.3.2/os/common/ports/e200/compilers/CW/chtypes.h
new file mode 100644
index 0000000..22be822
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/e200/compilers/CW/chtypes.h
@@ -0,0 +1,97 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file e200/compilers/CW/chtypes.h
+ * @brief Power e200 port system types.
+ *
+ * @addtogroup PPC_CW_CORE
+ * @{
+ */
+
+#ifndef CHTYPES_H
+#define CHTYPES_H
+
+#include
+#include
+#include
+
+/**
+ * @name Kernel types
+ * @{
+ */
+typedef uint32_t rtcnt_t; /**< Realtime counter. */
+typedef uint64_t rttime_t; /**< Realtime accumulator. */
+typedef uint32_t syssts_t; /**< System status word. */
+typedef uint8_t tmode_t; /**< Thread flags. */
+typedef uint8_t tstate_t; /**< Thread state. */
+typedef uint8_t trefs_t; /**< Thread references counter. */
+typedef uint8_t tslices_t; /**< Thread time slices counter.*/
+typedef uint32_t tprio_t; /**< Thread priority. */
+typedef int32_t msg_t; /**< Inter-thread message. */
+typedef int32_t eventid_t; /**< Numeric event identifier. */
+typedef uint32_t eventmask_t; /**< Mask of event identifiers. */
+typedef uint32_t eventflags_t; /**< Mask of event flags. */
+typedef int32_t cnt_t; /**< Generic signed counter. */
+typedef uint32_t ucnt_t; /**< Generic unsigned counter. */
+/** @} */
+
+/**
+ * @brief ROM constant modifier.
+ * @note It is set to use the "const" keyword in this port.
+ */
+#define ROMCONST const
+
+/**
+ * @brief Makes functions not inlineable.
+ * @note If the compiler does not support such attribute then some
+ * time-dependent services could be degraded.
+ */
+#define NOINLINE __attribute__((noinline))
+
+/**
+ * @brief Optimized thread function declaration macro.
+ */
+#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg)
+
+/**
+ * @brief Packed variable specifier.
+ */
+#define PACKED_VAR __attribute__((packed))
+
+/**
+ * @brief Memory alignment enforcement for variables.
+ */
+#define ALIGNED_VAR(n) __attribute__((aligned(n)))
+
+/**
+ * @brief Size of a pointer.
+ * @note To be used where the sizeof operator cannot be used, preprocessor
+ * expressions for example.
+ */
+#define SIZEOF_PTR 4
+
+/**
+ * @brief True if alignment is low-high in current architecture.
+ */
+#define REVERSE_ORDER 0
+
+#endif /* CHTYPES_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/e200/compilers/CW/ivor.s b/ChibiOS_20.3.2/os/common/ports/e200/compilers/CW/ivor.s
new file mode 100644
index 0000000..64b2408
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/e200/compilers/CW/ivor.s
@@ -0,0 +1,205 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file ivor.s
+ * @brief Kernel ISRs.
+ *
+ * @addtogroup PPC_CORE
+ * @{
+ */
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+
+/*===========================================================================*/
+/* Code section. */
+/*===========================================================================*/
+
+/*
+ * Imports the PPC configuration headers.
+ */
+#define _FROM_ASM_
+#include "chlicense.h"
+#include "chconf.h"
+#include "chcore.h"
+
+#if !defined(__DOXYGEN__)
+
+ .extern _stats_start_measure_crit_thd
+ .extern _stats_stop_measure_crit_thd
+ .extern _dbg_check_lock
+ .extern _dbg_check_unlock
+ .extern chSchIsPreemptionRequired
+ .extern chSchDoReschedule
+ .extern chSysTimerHandlerI
+
+ .section .handlers, text_vle
+
+#if PPC_USE_VLE == TRUE
+
+#if PPC_SUPPORTS_DECREMENTER
+ /*
+ * _IVOR10 handler (Book-E decrementer).
+ */
+ .align 16
+ .globl _IVOR10
+ .type _IVOR10, @function
+_IVOR10:
+ /* Saving the external context (port_extctx structure).*/
+ e_stwu r1, -80(r1)
+ e_stmvsrrw 8(r1) /* Saves PC, MSR. */
+ e_stmvsprw 16(r1) /* Saves CR, LR, CTR, XER. */
+ e_stmvgprw 32(r1) /* Saves GPR0, GPR3...GPR12. */
+
+ /* Increasing the SPGR0 register.*/
+ mfspr r0, 272
+ se_addi r0, 1
+ mtspr 272, r0
+
+ /* Reset DIE bit in TSR register.*/
+ e_lis r3, 0x0800 /* DIS bit mask. */
+ mtspr 336, r3 /* TSR register. */
+
+ /* Restoring pre-IRQ MSR register value.*/
+ mfSRR1 r0
+#if !PPC_USE_IRQ_PREEMPTION
+ /* No preemption, keeping EE disabled.*/
+ se_bclri r0, 16 /* EE = bit 16. */
+#endif
+ mtMSR r0
+
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_enter_isr
+ bl _dbg_check_lock_from_isr
+#endif
+ /* System tick handler invocation.*/
+ e_bl chSysTimerHandlerI
+#if CH_DBG_SYSTEM_STATE_CHECK
+ bl _dbg_check_unlock_from_isr
+ bl _dbg_check_leave_isr
+#endif
+
+#if PPC_USE_IRQ_PREEMPTION
+ /* Prevents preemption again.*/
+ wrteei 0
+#endif
+
+ /* Jumps to the common IVOR epilogue code.*/
+ se_b _ivor_exit
+#endif /* PPC_SUPPORTS_DECREMENTER */
+
+ /*
+ * _IVOR4 handler (Book-E external interrupt).
+ */
+ .align 16
+ .globl _IVOR4
+ .type _IVOR4, @function
+_IVOR4:
+ /* Saving the external context (port_extctx structure).*/
+ e_stwu r1, -80(r1)
+ e_stmvsrrw 8(r1) /* Saves PC, MSR. */
+ e_stmvsprw 16(r1) /* Saves CR, LR, CTR, XER. */
+ e_stmvgprw 32(r1) /* Saves GPR0, GPR3...GPR12. */
+
+ /* Increasing the SPGR0 register.*/
+ mfspr r0, 272
+ se_addi r0, 1
+ mtspr 272, r0
+
+ /* Software vector address from the INTC register.*/
+ e_lis r3, INTC_IACKR_ADDR@h
+ e_or2i r3, INTC_IACKR_ADDR@l /* IACKR register address. */
+ se_lwz r3, 0(r3) /* IACKR register value. */
+ se_lwz r3, 0(r3)
+ mtCTR r3 /* Software handler address. */
+
+ /* Restoring pre-IRQ MSR register value.*/
+ mfSRR1 r0
+#if !PPC_USE_IRQ_PREEMPTION
+ /* No preemption, keeping EE disabled.*/
+ se_bclri r0, 16 /* EE = bit 16. */
+#endif
+ mtMSR r0
+
+ /* Exectes the software handler.*/
+ se_bctrl
+
+#if PPC_USE_IRQ_PREEMPTION
+ /* Prevents preemption again.*/
+ wrteei 0
+#endif
+
+ /* Informs the INTC that the interrupt has been served.*/
+ mbar 0
+ e_lis r3, INTC_EOIR_ADDR@h
+ e_or2i r3, INTC_EOIR_ADDR@l
+ se_stw r3, 0(r3) /* Writing any value should do. */
+
+ /* Common IVOR epilogue code, context restore.*/
+ .globl _ivor_exit
+_ivor_exit:
+ /* Decreasing the SPGR0 register.*/
+ mfspr r0, 272
+ se_subi r0, 1
+ mtspr 272, r0
+
+#if CH_DBG_STATISTICS
+ e_bl _stats_start_measure_crit_thd
+#endif
+#if CH_DBG_SYSTEM_STATE_CHECK
+ e_bl _dbg_check_lock
+#endif
+ e_bl chSchIsPreemptionRequired
+ e_cmpli cr0, r3, 0
+ se_beq .noresch
+ e_bl chSchDoReschedule
+.noresch:
+#if CH_DBG_SYSTEM_STATE_CHECK
+ e_bl _dbg_check_unlock
+#endif
+#if CH_DBG_STATISTICS
+ e_bl _stats_stop_measure_crit_thd
+#endif
+
+ /* Restoring the external context.*/
+ e_lmvgprw 32(r1) /* Restores GPR0, GPR3...GPR12. */
+ e_lmvsprw 16(r1) /* Restores CR, LR, CTR, XER. */
+ e_lmvsrrw 8(r1) /* Restores PC, MSR. */
+ e_addi r1, r1, 80 /* Back to the previous frame. */
+ se_rfi
+
+#else /* PPC_USE_VLE == FALSE */
+
+#error "non-VLE mode not yet implemented"
+
+#endif /* PPC_USE_VLE == FALSE */
+
+#endif /* !defined(__DOXYGEN__) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/e200/compilers/GCC/chcoreasm.S b/ChibiOS_20.3.2/os/common/ports/e200/compilers/GCC/chcoreasm.S
new file mode 100644
index 0000000..4b31238
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/e200/compilers/GCC/chcoreasm.S
@@ -0,0 +1,113 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file e200/compilers/GCC/chcoreasm.S
+ * @brief Power Architecture port low level code.
+ *
+ * @addtogroup PPC_GCC_CORE
+ * @{
+ */
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+
+/*===========================================================================*/
+/* Code section. */
+/*===========================================================================*/
+
+#define _FROM_ASM_
+#include "chlicense.h"
+#include "chconf.h"
+#include "chcore.h"
+
+#if defined(__HIGHTEC__)
+#define e_subi subi
+#endif
+
+#if !defined(__DOXYGEN__)
+
+/*
+ * RTOS-specific context offset.
+ */
+#if defined(_CHIBIOS_RT_CONF_)
+#define CONTEXT_OFFSET 12
+#elif defined(_CHIBIOS_NIL_CONF_)
+#define CONTEXT_OFFSET 0
+#else
+#error "invalid chconf.h"
+#endif
+
+#if PPC_USE_VLE == TRUE
+ .section .text_vle, "ax"
+#else
+ .section .text, "ax"
+#endif
+
+ .align 2
+ .globl _port_switch
+ .type _port_switch, @function
+_port_switch:
+ e_subi sp, sp, 80
+ mflr r0
+ e_stw r0, 84(sp)
+ mfcr r0
+ se_stw r0, 0(sp)
+ e_stmw r14, 4(sp)
+
+ se_stw sp, CONTEXT_OFFSET(r4)
+ se_lwz sp, CONTEXT_OFFSET(r3)
+
+ e_lmw r14, 4(sp)
+ se_lwz r0, 0(sp)
+ mtcr r0
+ e_lwz r0, 84(sp)
+ mtlr r0
+ e_addi sp, sp, 80
+ se_blr
+
+ .align 2
+ .globl _port_thread_start
+ .type _port_thread_start, @function
+_port_thread_start:
+#if CH_DBG_SYSTEM_STATE_CHECK
+ e_bl _dbg_check_unlock
+#endif
+#if CH_DBG_STATISTICS
+ e_bl _stats_stop_measure_crit_thd
+#endif
+ wrteei 1
+ mr r3, r31
+ mtctr r30
+ se_bctrl
+ e_li r0, 0
+ e_bl chThdExit
+
+#endif /* !defined(__DOXYGEN__) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/e200/compilers/GCC/chtypes.h b/ChibiOS_20.3.2/os/common/ports/e200/compilers/GCC/chtypes.h
new file mode 100644
index 0000000..ae4d116
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/e200/compilers/GCC/chtypes.h
@@ -0,0 +1,97 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file e200/compilers/GCC/chtypes.h
+ * @brief Power e200 port system types.
+ *
+ * @addtogroup PPC_GCC_CORE
+ * @{
+ */
+
+#ifndef CHTYPES_H
+#define CHTYPES_H
+
+#include
+#include
+#include
+
+/**
+ * @name Kernel types
+ * @{
+ */
+typedef uint32_t rtcnt_t; /**< Realtime counter. */
+typedef uint64_t rttime_t; /**< Realtime accumulator. */
+typedef uint32_t syssts_t; /**< System status word. */
+typedef uint8_t tmode_t; /**< Thread flags. */
+typedef uint8_t tstate_t; /**< Thread state. */
+typedef uint8_t trefs_t; /**< Thread references counter. */
+typedef uint8_t tslices_t; /**< Thread time slices counter.*/
+typedef uint32_t tprio_t; /**< Thread priority. */
+typedef int32_t msg_t; /**< Inter-thread message. */
+typedef int32_t eventid_t; /**< Numeric event identifier. */
+typedef uint32_t eventmask_t; /**< Mask of event identifiers. */
+typedef uint32_t eventflags_t; /**< Mask of event flags. */
+typedef int32_t cnt_t; /**< Generic signed counter. */
+typedef uint32_t ucnt_t; /**< Generic unsigned counter. */
+/** @} */
+
+/**
+ * @brief ROM constant modifier.
+ * @note It is set to use the "const" keyword in this port.
+ */
+#define ROMCONST const
+
+/**
+ * @brief Makes functions not inlineable.
+ * @note If the compiler does not support such attribute then some
+ * time-dependent services could be degraded.
+ */
+#define NOINLINE __attribute__((noinline))
+
+/**
+ * @brief Optimized thread function declaration macro.
+ */
+#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg)
+
+/**
+ * @brief Packed variable specifier.
+ */
+#define PACKED_VAR __attribute__((packed))
+
+/**
+ * @brief Memory alignment enforcement for variables.
+ */
+#define ALIGNED_VAR(n) __attribute__((aligned(n)))
+
+/**
+ * @brief Size of a pointer.
+ * @note To be used where the sizeof operator cannot be used, preprocessor
+ * expressions for example.
+ */
+#define SIZEOF_PTR 4
+
+/**
+ * @brief True if alignment is low-high in current architecture.
+ */
+#define REVERSE_ORDER 0
+
+#endif /* CHTYPES_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/e200/compilers/GCC/ivor.S b/ChibiOS_20.3.2/os/common/ports/e200/compilers/GCC/ivor.S
new file mode 100644
index 0000000..6bc2f5b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/e200/compilers/GCC/ivor.S
@@ -0,0 +1,263 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file GCC/ivor.S
+ * @brief Kernel ISRs.
+ *
+ * @addtogroup PPC_CORE
+ * @{
+ */
+
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+
+/*
+ * Imports the PPC configuration headers.
+ */
+#define _FROM_ASM_
+#include "chlicense.h"
+#include "chconf.h"
+#include "chcore.h"
+
+#if defined(__HIGHTEC__)
+#define se_beq beq
+#endif
+
+#if !defined(__DOXYGEN__)
+
+ .section .handlers, "ax"
+
+#if PPC_SUPPORTS_DECREMENTER
+ /*
+ * _IVOR10 handler (Book-E decrementer).
+ */
+ .align 4
+ .globl _IVOR10
+ .type _IVOR10, @function
+_IVOR10:
+ /* Saving the external context (port_extctx structure).*/
+ e_stwu sp, -80(sp)
+#if PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI
+ e_stmvsrrw 8(sp) /* Saves PC, MSR. */
+ e_stmvsprw 16(sp) /* Saves CR, LR, CTR, XER. */
+ e_stmvgprw 32(sp) /* Saves GPR0, GPR3...GPR12. */
+#else /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */
+ se_stw r0, 32(sp) /* Saves GPR0. */
+ mfSRR0 r0
+ se_stw r0, 8(sp) /* Saves PC. */
+ mfSRR1 r0
+ se_stw r0, 12(sp) /* Saves MSR. */
+ mfCR r0
+ se_stw r0, 16(sp) /* Saves CR. */
+ mfLR r0
+ se_stw r0, 20(sp) /* Saves LR. */
+ mfCTR r0
+ se_stw r0, 24(sp) /* Saves CTR. */
+ mfXER r0
+ se_stw r0, 28(sp) /* Saves XER. */
+ se_stw r3, 36(sp) /* Saves GPR3...GPR12. */
+ se_stw r4, 40(sp)
+ se_stw r5, 44(sp)
+ se_stw r6, 48(sp)
+ se_stw r7, 52(sp)
+ e_stw r8, 56(sp)
+ e_stw r9, 60(sp)
+ e_stw r10, 64(sp)
+ e_stw r11, 68(sp)
+ e_stw r12, 72(sp)
+#endif /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */
+
+ /* Increasing the SPGR0 register.*/
+ mfspr r0, 272
+ se_addi r0, 1
+ mtspr 272, r0
+
+ /* Reset DIE bit in TSR register.*/
+ e_lis r3, 0x0800 /* DIS bit mask. */
+ mtspr 336, r3 /* TSR register. */
+
+ /* Restoring pre-IRQ MSR register value.*/
+ mfSRR1 r0
+#if !PPC_USE_IRQ_PREEMPTION
+ /* No preemption, keeping EE disabled.*/
+ se_bclri r0, 16 /* EE = bit 16. */
+#endif
+ mtMSR r0
+
+#if CH_DBG_SYSTEM_STATE_CHECK
+ e_bl _dbg_check_enter_isr
+ e_bl _dbg_check_lock_from_isr
+#endif
+ /* System tick handler invocation.*/
+ e_bl chSysTimerHandlerI
+#if CH_DBG_SYSTEM_STATE_CHECK
+ e_bl _dbg_check_unlock_from_isr
+ e_bl _dbg_check_leave_isr
+#endif
+
+#if PPC_USE_IRQ_PREEMPTION
+ /* Prevents preemption again.*/
+ wrteei 0
+#endif
+
+ /* Jumps to the common IVOR epilogue code.*/
+ e_b _ivor_exit
+#endif /* PPC_SUPPORTS_DECREMENTER */
+
+ /*
+ * _IVOR4 handler (Book-E external interrupt).
+ */
+ .align 4
+ .globl _IVOR4
+ .type _IVOR4, @function
+_IVOR4:
+ /* Saving the external context (port_extctx structure).*/
+ e_stwu sp, -80(sp)
+#if PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI
+ e_stmvsrrw 8(sp) /* Saves PC, MSR. */
+ e_stmvsprw 16(sp) /* Saves CR, LR, CTR, XER. */
+ e_stmvgprw 32(sp) /* Saves GPR0, GPR3...GPR12. */
+#else /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */
+ se_stw r0, 32(sp) /* Saves GPR0. */
+ mfSRR0 r0
+ se_stw r0, 8(sp) /* Saves PC. */
+ mfSRR1 r0
+ se_stw r0, 12(sp) /* Saves MSR. */
+ mfCR r0
+ se_stw r0, 16(sp) /* Saves CR. */
+ mfLR r0
+ se_stw r0, 20(sp) /* Saves LR. */
+ mfCTR r0
+ se_stw r0, 24(sp) /* Saves CTR. */
+ mfXER r0
+ se_stw r0, 28(sp) /* Saves XER. */
+ se_stw r3, 36(sp) /* Saves GPR3...GPR12. */
+ se_stw r4, 40(sp)
+ se_stw r5, 44(sp)
+ se_stw r6, 48(sp)
+ se_stw r7, 52(sp)
+ e_stw r8, 56(sp)
+ e_stw r9, 60(sp)
+ e_stw r10, 64(sp)
+ e_stw r11, 68(sp)
+ e_stw r12, 72(sp)
+#endif /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */
+
+ /* Increasing the SPGR0 register.*/
+ mfspr r0, 272
+ se_addi r0, 1
+ mtspr 272, r0
+
+ /* Software vector address from the INTC register.*/
+ e_lis r3, INTC_IACKR_ADDR@h
+ e_or2i r3, INTC_IACKR_ADDR@l /* IACKR register address. */
+ e_lwz r3, 0(r3) /* IACKR register value. */
+ e_lwz r3, 0(r3)
+ mtCTR r3 /* Software handler address. */
+
+ /* Restoring pre-IRQ MSR register value.*/
+ mfSRR1 r0
+#if !PPC_USE_IRQ_PREEMPTION
+ /* No preemption, keeping EE disabled.*/
+ se_bclri r0, 16 /* EE = bit 16. */
+#endif
+ mtMSR r0
+
+ /* Exectes the software handler.*/
+ se_bctrl
+
+#if PPC_USE_IRQ_PREEMPTION
+ /* Prevents preemption again.*/
+ wrteei 0
+#endif
+
+ /* Informs the INTC that the interrupt has been served.*/
+ mbar 0
+ e_lis r3, INTC_EOIR_ADDR@h
+ e_or2i r3, INTC_EOIR_ADDR@l
+ se_stw r3, 0(r3) /* Writing any value should do. */
+
+ /* Common IVOR epilogue code, context restore.*/
+ .globl _ivor_exit
+_ivor_exit:
+ /* Decreasing the SPGR0 register.*/
+ mfspr r0, 272
+ se_subi r0, 1
+ mtspr 272, r0
+
+#if CH_DBG_STATISTICS
+ e_bl _stats_start_measure_crit_thd
+#endif
+#if CH_DBG_SYSTEM_STATE_CHECK
+ e_bl _dbg_check_lock
+#endif
+ e_bl chSchIsPreemptionRequired
+ se_cmpi r3, 0
+ se_beq .noresch
+ e_bl chSchDoReschedule
+.noresch:
+#if CH_DBG_SYSTEM_STATE_CHECK
+ e_bl _dbg_check_unlock
+#endif
+#if CH_DBG_STATISTICS
+ e_bl _stats_stop_measure_crit_thd
+#endif
+
+ /* Restoring the external context.*/
+#if PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI
+ e_lmvgprw 32(sp) /* Restores GPR0, GPR3...GPR12. */
+ e_lmvsprw 16(sp) /* Restores CR, LR, CTR, XER. */
+ e_lmvsrrw 8(sp) /* Restores PC, MSR. */
+#else /*!(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */
+ se_lwz r3, 36(sp) /* Restores GPR3...GPR12. */
+ se_lwz r4, 40(sp)
+ se_lwz r5, 44(sp)
+ se_lwz r6, 48(sp)
+ se_lwz r7, 52(sp)
+ e_lwz r8, 56(sp)
+ e_lwz r9, 60(sp)
+ e_lwz r10, 64(sp)
+ e_lwz r11, 68(sp)
+ e_lwz r12, 72(sp)
+ se_lwz r0, 8(sp)
+ mtSRR0 r0 /* Restores PC. */
+ se_lwz r0, 12(sp)
+ mtSRR1 r0 /* Restores MSR. */
+ se_lwz r0, 16(sp)
+ mtCR r0 /* Restores CR. */
+ se_lwz r0, 20(sp)
+ mtLR r0 /* Restores LR. */
+ se_lwz r0, 24(sp)
+ mtCTR r0 /* Restores CTR. */
+ se_lwz r0, 28(sp)
+ mtXER r0 /* Restores XER. */
+ se_lwz r0, 32(sp) /* Restores GPR0. */
+#endif /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */
+ e_addi sp, sp, 80 /* Back to the previous frame. */
+ se_rfi
+
+#endif /* !defined(__DOXYGEN__) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/e200/compilers/GCC/mk/port.mk b/ChibiOS_20.3.2/os/common/ports/e200/compilers/GCC/mk/port.mk
new file mode 100644
index 0000000..063beb4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/e200/compilers/GCC/mk/port.mk
@@ -0,0 +1,13 @@
+# List of the ChibiOS/RT e200 generic port files.
+PORTSRC = $(CHIBIOS)/os/common/ports/e200/chcore.c
+
+PORTASM = $(CHIBIOS)/os/common/ports/e200/compilers/GCC/ivor.S \
+ $(CHIBIOS)/os/common/ports/e200/compilers/GCC/chcoreasm.S
+
+PORTINC = $(CHIBIOS)/os/common/ports/e200 \
+ $(CHIBIOS)/os/common/ports/e200/compilers/GCC
+
+# Shared variables
+ALLXASMSRC += $(PORTASM)
+ALLCSRC += $(PORTSRC)
+ALLINC += $(PORTINC)
diff --git a/ChibiOS_20.3.2/os/common/ports/e200/compilers/GHS/chcoreasm.s b/ChibiOS_20.3.2/os/common/ports/e200/compilers/GHS/chcoreasm.s
new file mode 100644
index 0000000..9d49a7d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/e200/compilers/GHS/chcoreasm.s
@@ -0,0 +1,107 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file e200/compilers/GHS/chcoreasm.S
+ * @brief Power Architecture port low level code.
+ *
+ * @addtogroup PPC_GHS_CORE
+ * @{
+ */
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+
+/*===========================================================================*/
+/* Code section. */
+/*===========================================================================*/
+
+#define _FROM_ASM_
+#include "chlicense.h"
+#include "chconf.h"
+#include "chcore.h"
+
+#if !defined(__DOXYGEN__)
+
+/*
+ * RTOS-specific context offset.
+ */
+#if defined(_CHIBIOS_RT_CONF_)
+#define CONTEXT_OFFSET 12
+#elif defined(_CHIBIOS_NIL_CONF_)
+#define CONTEXT_OFFSET 0
+#else
+#error "invalid chconf.h"
+#endif
+
+ .vle
+
+ .section .vletext, "axv"
+
+ .align 2
+ .globl _port_switch
+ .type _port_switch, @function
+_port_switch:
+ e_subi sp, sp, 80
+ mflr r0
+ e_stw r0, 84(sp)
+ mfcr r0
+ se_stw r0, 0(sp)
+ e_stmw r14, 4(sp)
+
+ se_stw sp, CONTEXT_OFFSET(r4)
+ se_lwz sp, CONTEXT_OFFSET(r3)
+
+ e_lmw r14, 4(sp)
+ se_lwz r0, 0(sp)
+ mtcr r0
+ e_lwz r0, 84(sp)
+ mtlr r0
+ e_addi sp, sp, 80
+ se_blr
+
+ .align 2
+ .globl _port_thread_start
+ .type _port_thread_start, @function
+_port_thread_start:
+#if CH_DBG_SYSTEM_STATE_CHECK
+ e_bl _dbg_check_unlock
+#endif
+#if CH_DBG_STATISTICS
+ e_bl _stats_stop_measure_crit_thd
+#endif
+ wrteei 1
+ mr r3, r31
+ mtctr r30
+ se_bctrl
+ e_li r0, 0
+ e_bl chThdExit
+
+#endif /* !defined(__DOXYGEN__) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/e200/compilers/GHS/chtypes.h b/ChibiOS_20.3.2/os/common/ports/e200/compilers/GHS/chtypes.h
new file mode 100644
index 0000000..ae4d116
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/e200/compilers/GHS/chtypes.h
@@ -0,0 +1,97 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file e200/compilers/GCC/chtypes.h
+ * @brief Power e200 port system types.
+ *
+ * @addtogroup PPC_GCC_CORE
+ * @{
+ */
+
+#ifndef CHTYPES_H
+#define CHTYPES_H
+
+#include
+#include
+#include
+
+/**
+ * @name Kernel types
+ * @{
+ */
+typedef uint32_t rtcnt_t; /**< Realtime counter. */
+typedef uint64_t rttime_t; /**< Realtime accumulator. */
+typedef uint32_t syssts_t; /**< System status word. */
+typedef uint8_t tmode_t; /**< Thread flags. */
+typedef uint8_t tstate_t; /**< Thread state. */
+typedef uint8_t trefs_t; /**< Thread references counter. */
+typedef uint8_t tslices_t; /**< Thread time slices counter.*/
+typedef uint32_t tprio_t; /**< Thread priority. */
+typedef int32_t msg_t; /**< Inter-thread message. */
+typedef int32_t eventid_t; /**< Numeric event identifier. */
+typedef uint32_t eventmask_t; /**< Mask of event identifiers. */
+typedef uint32_t eventflags_t; /**< Mask of event flags. */
+typedef int32_t cnt_t; /**< Generic signed counter. */
+typedef uint32_t ucnt_t; /**< Generic unsigned counter. */
+/** @} */
+
+/**
+ * @brief ROM constant modifier.
+ * @note It is set to use the "const" keyword in this port.
+ */
+#define ROMCONST const
+
+/**
+ * @brief Makes functions not inlineable.
+ * @note If the compiler does not support such attribute then some
+ * time-dependent services could be degraded.
+ */
+#define NOINLINE __attribute__((noinline))
+
+/**
+ * @brief Optimized thread function declaration macro.
+ */
+#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg)
+
+/**
+ * @brief Packed variable specifier.
+ */
+#define PACKED_VAR __attribute__((packed))
+
+/**
+ * @brief Memory alignment enforcement for variables.
+ */
+#define ALIGNED_VAR(n) __attribute__((aligned(n)))
+
+/**
+ * @brief Size of a pointer.
+ * @note To be used where the sizeof operator cannot be used, preprocessor
+ * expressions for example.
+ */
+#define SIZEOF_PTR 4
+
+/**
+ * @brief True if alignment is low-high in current architecture.
+ */
+#define REVERSE_ORDER 0
+
+#endif /* CHTYPES_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/e200/compilers/GHS/ivor.s b/ChibiOS_20.3.2/os/common/ports/e200/compilers/GHS/ivor.s
new file mode 100644
index 0000000..2fd98ba
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/e200/compilers/GHS/ivor.s
@@ -0,0 +1,265 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file e200/compilers/GHS/ivor.S
+ * @brief Kernel ISRs.
+ *
+ * @addtogroup PPC_GHS_CORE
+ * @{
+ */
+
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+
+/*
+ * Imports the PPC configuration headers.
+ */
+#define _FROM_ASM_
+#include "chlicense.h"
+#include "chconf.h"
+#include "chcore.h"
+
+#if defined(__HIGHTEC__)
+#define se_beq beq
+#endif
+
+#if !defined(__DOXYGEN__)
+
+ .vle
+
+ .section .handlers, "axv"
+
+#if PPC_SUPPORTS_DECREMENTER
+ /*
+ * _IVOR10 handler (Book-E decrementer).
+ */
+ .align 4
+ .globl _IVOR10
+ .type _IVOR10, @function
+_IVOR10:
+ /* Saving the external context (port_extctx structure).*/
+ e_stwu sp, -80(sp)
+#if PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI
+ e_stmvsrrw 8(sp) /* Saves PC, MSR. */
+ e_stmvsprw 16(sp) /* Saves CR, LR, CTR, XER. */
+ e_stmvgprw 32(sp) /* Saves GPR0, GPR3...GPR12. */
+#else /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */
+ se_stw r0, 32(sp) /* Saves GPR0. */
+ mfSRR0 r0
+ se_stw r0, 8(sp) /* Saves PC. */
+ mfSRR1 r0
+ se_stw r0, 12(sp) /* Saves MSR. */
+ mfCR r0
+ se_stw r0, 16(sp) /* Saves CR. */
+ mfLR r0
+ se_stw r0, 20(sp) /* Saves LR. */
+ mfCTR r0
+ se_stw r0, 24(sp) /* Saves CTR. */
+ mfXER r0
+ se_stw r0, 28(sp) /* Saves XER. */
+ se_stw r3, 36(sp) /* Saves GPR3...GPR12. */
+ se_stw r4, 40(sp)
+ se_stw r5, 44(sp)
+ se_stw r6, 48(sp)
+ se_stw r7, 52(sp)
+ e_stw r8, 56(sp)
+ e_stw r9, 60(sp)
+ e_stw r10, 64(sp)
+ e_stw r11, 68(sp)
+ e_stw r12, 72(sp)
+#endif /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */
+
+ /* Increasing the SPGR0 register.*/
+ mfspr r0, 272
+ se_addi r0, 1
+ mtspr 272, r0
+
+ /* Reset DIE bit in TSR register.*/
+ e_lis r3, 0x0800 /* DIS bit mask. */
+ mtspr 336, r3 /* TSR register. */
+
+ /* Restoring pre-IRQ MSR register value.*/
+ mfSRR1 r0
+#if !PPC_USE_IRQ_PREEMPTION
+ /* No preemption, keeping EE disabled.*/
+ se_bclri r0, 16 /* EE = bit 16. */
+#endif
+ mtMSR r0
+
+#if CH_DBG_SYSTEM_STATE_CHECK
+ e_bl _dbg_check_enter_isr
+ e_bl _dbg_check_lock_from_isr
+#endif
+ /* System tick handler invocation.*/
+ e_bl chSysTimerHandlerI
+#if CH_DBG_SYSTEM_STATE_CHECK
+ e_bl _dbg_check_unlock_from_isr
+ e_bl _dbg_check_leave_isr
+#endif
+
+#if PPC_USE_IRQ_PREEMPTION
+ /* Prevents preemption again.*/
+ wrteei 0
+#endif
+
+ /* Jumps to the common IVOR epilogue code.*/
+ e_b _ivor_exit
+#endif /* PPC_SUPPORTS_DECREMENTER */
+
+ /*
+ * _IVOR4 handler (Book-E external interrupt).
+ */
+ .align 4
+ .globl _IVOR4
+ .type _IVOR4, @function
+_IVOR4:
+ /* Saving the external context (port_extctx structure).*/
+ e_stwu sp, -80(sp)
+#if PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI
+ e_stmvsrrw 8(sp) /* Saves PC, MSR. */
+ e_stmvsprw 16(sp) /* Saves CR, LR, CTR, XER. */
+ e_stmvgprw 32(sp) /* Saves GPR0, GPR3...GPR12. */
+#else /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */
+ se_stw r0, 32(sp) /* Saves GPR0. */
+ mfSRR0 r0
+ se_stw r0, 8(sp) /* Saves PC. */
+ mfSRR1 r0
+ se_stw r0, 12(sp) /* Saves MSR. */
+ mfCR r0
+ se_stw r0, 16(sp) /* Saves CR. */
+ mfLR r0
+ se_stw r0, 20(sp) /* Saves LR. */
+ mfCTR r0
+ se_stw r0, 24(sp) /* Saves CTR. */
+ mfXER r0
+ se_stw r0, 28(sp) /* Saves XER. */
+ se_stw r3, 36(sp) /* Saves GPR3...GPR12. */
+ se_stw r4, 40(sp)
+ se_stw r5, 44(sp)
+ se_stw r6, 48(sp)
+ se_stw r7, 52(sp)
+ e_stw r8, 56(sp)
+ e_stw r9, 60(sp)
+ e_stw r10, 64(sp)
+ e_stw r11, 68(sp)
+ e_stw r12, 72(sp)
+#endif /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */
+
+ /* Increasing the SPGR0 register.*/
+ mfspr r0, 272
+ se_addi r0, 1
+ mtspr 272, r0
+
+ /* Software vector address from the INTC register.*/
+ e_lis r3, INTC_IACKR_ADDR@h
+ e_or2i r3, INTC_IACKR_ADDR@l /* IACKR register address. */
+ e_lwz r3, 0(r3) /* IACKR register value. */
+ e_lwz r3, 0(r3)
+ mtCTR r3 /* Software handler address. */
+
+ /* Restoring pre-IRQ MSR register value.*/
+ mfSRR1 r0
+#if !PPC_USE_IRQ_PREEMPTION
+ /* No preemption, keeping EE disabled.*/
+ se_bclri r0, 16 /* EE = bit 16. */
+#endif
+ mtMSR r0
+
+ /* Exectes the software handler.*/
+ se_bctrl
+
+#if PPC_USE_IRQ_PREEMPTION
+ /* Prevents preemption again.*/
+ wrteei 0
+#endif
+
+ /* Informs the INTC that the interrupt has been served.*/
+ mbar 0
+ e_lis r3, INTC_EOIR_ADDR@h
+ e_or2i r3, INTC_EOIR_ADDR@l
+ se_stw r3, 0(r3) /* Writing any value should do. */
+
+ /* Common IVOR epilogue code, context restore.*/
+ .globl _ivor_exit
+_ivor_exit:
+ /* Decreasing the SPGR0 register.*/
+ mfspr r0, 272
+ se_subi r0, 1
+ mtspr 272, r0
+
+#if CH_DBG_STATISTICS
+ e_bl _stats_start_measure_crit_thd
+#endif
+#if CH_DBG_SYSTEM_STATE_CHECK
+ e_bl _dbg_check_lock
+#endif
+ e_bl chSchIsPreemptionRequired
+ se_cmpi r3, 0
+ se_beq .noresch
+ e_bl chSchDoReschedule
+.noresch:
+#if CH_DBG_SYSTEM_STATE_CHECK
+ e_bl _dbg_check_unlock
+#endif
+#if CH_DBG_STATISTICS
+ e_bl _stats_stop_measure_crit_thd
+#endif
+
+ /* Restoring the external context.*/
+#if PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI
+ e_lmvgprw 32(sp) /* Restores GPR0, GPR3...GPR12. */
+ e_lmvsprw 16(sp) /* Restores CR, LR, CTR, XER. */
+ e_lmvsrrw 8(sp) /* Restores PC, MSR. */
+#else /*!(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */
+ se_lwz r3, 36(sp) /* Restores GPR3...GPR12. */
+ se_lwz r4, 40(sp)
+ se_lwz r5, 44(sp)
+ se_lwz r6, 48(sp)
+ se_lwz r7, 52(sp)
+ e_lwz r8, 56(sp)
+ e_lwz r9, 60(sp)
+ e_lwz r10, 64(sp)
+ e_lwz r11, 68(sp)
+ e_lwz r12, 72(sp)
+ se_lwz r0, 8(sp)
+ mtSRR0 r0 /* Restores PC. */
+ se_lwz r0, 12(sp)
+ mtSRR1 r0 /* Restores MSR. */
+ se_lwz r0, 16(sp)
+ mtCR r0 /* Restores CR. */
+ se_lwz r0, 20(sp)
+ mtLR r0 /* Restores LR. */
+ se_lwz r0, 24(sp)
+ mtCTR r0 /* Restores CTR. */
+ se_lwz r0, 28(sp)
+ mtXER r0 /* Restores XER. */
+ se_lwz r0, 32(sp) /* Restores GPR0. */
+#endif /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */
+ e_addi sp, sp, 80 /* Back to the previous frame. */
+ se_rfi
+
+#endif /* !defined(__DOXYGEN__) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/e200/compilers/GHS/mk/port.mk b/ChibiOS_20.3.2/os/common/ports/e200/compilers/GHS/mk/port.mk
new file mode 100644
index 0000000..f58e5a8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/e200/compilers/GHS/mk/port.mk
@@ -0,0 +1,13 @@
+# List of the ChibiOS/RT e200 generic port files.
+PORTSRC = $(CHIBIOS)/os/common/ports/e200/chcore.c
+
+PORTASM = $(CHIBIOS)/os/common/ports/e200/compilers/GHS/ivor.s \
+ $(CHIBIOS)/os/common/ports/e200/compilers/GHS/chcoreasm.s
+
+PORTINC = $(CHIBIOS)/os/common/ports/e200 \
+ $(CHIBIOS)/os/common/ports/e200/compilers/GHS
+
+# Shared variables
+ALLASMSRC += $(PORTASM)
+ALLCSRC += $(PORTSRC)
+ALLINC += $(PORTINC)
diff --git a/ChibiOS_20.3.2/os/common/ports/readme.txt b/ChibiOS_20.3.2/os/common/ports/readme.txt
new file mode 100644
index 0000000..71e7249
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/readme.txt
@@ -0,0 +1,3 @@
+All the code contained under ./os/common/ports are RTOS ports compatible
+with both RT and NIL. The code is placed under ./os/common in order to
+prevent code duplication and disalignments.
diff --git a/ChibiOS_20.3.2/os/common/ports/templates/chcore.c b/ChibiOS_20.3.2/os/common/ports/templates/chcore.c
new file mode 100644
index 0000000..217e49b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/templates/chcore.c
@@ -0,0 +1,75 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file templates/chcore.c
+ * @brief Port related template code.
+ *
+ * @addtogroup port_core
+ * @details Non portable code templates.
+ * @{
+ */
+
+#include "ch.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Port-related initialization code.
+ * @note This function is usually empty.
+ */
+void _port_init(void) {
+}
+
+/**
+ * @brief Performs a context switch between two threads.
+ * @details This is the most critical code in any port, this function
+ * is responsible for the context switch between 2 threads.
+ * @note The implementation of this code affects directly the context
+ * switch performance so optimize here as much as you can.
+ *
+ * @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread to be switched out
+ */
+void _port_switch(thread_t *ntp, thread_t *otp) {
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/templates/chcore.dox b/ChibiOS_20.3.2/os/common/ports/templates/chcore.dox
new file mode 100644
index 0000000..16a4da6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/templates/chcore.dox
@@ -0,0 +1,33 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+/**
+ * @defgroup port Port Layer
+ * @details The Port Layer is the link between the portable RT and NIL kernels
+ * and the underlying CPU architecture. This is a port template not
+ * related to any specific architecture.
+ */
+
+/**
+ * @defgroup port_core Port Core
+ * @ingroup port
+ */
+/**
+ * @defgroup port_types Port Types
+ * @ingroup port
+ */
diff --git a/ChibiOS_20.3.2/os/common/ports/templates/chcore.h b/ChibiOS_20.3.2/os/common/ports/templates/chcore.h
new file mode 100644
index 0000000..bcc8db4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/templates/chcore.h
@@ -0,0 +1,460 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file templates/chcore.h
+ * @brief Port related template macros and structures.
+ * @details This file is a template of the system driver macros provided by
+ * a port.
+ *
+ * @addtogroup port_core
+ * @{
+ */
+
+#ifndef CHCORE_H
+#define CHCORE_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Port Capabilities and Constants
+ * @{
+ */
+/**
+ * @brief This port supports a realtime counter.
+ */
+#define PORT_SUPPORTS_RT FALSE
+
+/**
+ * @brief Natural alignment constant.
+ * @note It is the minimum alignment for pointer-size variables.
+ */
+#define PORT_NATURAL_ALIGN sizeof (void *)
+
+/**
+ * @brief Stack alignment constant.
+ * @note It is the alignment required for the stack pointer.
+ */
+#define PORT_STACK_ALIGN sizeof (stkalign_t)
+
+/**
+ * @brief Working Areas alignment constant.
+ * @note It is the alignment to be enforced for thread working areas.
+ */
+#define PORT_WORKING_AREA_ALIGN sizeof (stkalign_t)
+/** @} */
+
+/**
+ * @name Architecture and Compiler
+ * @{
+ */
+/**
+ * @brief Macro defining an XXX architecture.
+ */
+#define PORT_ARCHITECTURE_XXX
+
+/**
+ * @brief Macro defining the specific XXX architecture.
+ */
+#define PORT_ARCHITECTURE_XXX_YYY
+
+/**
+ * @brief Name of the implemented architecture.
+ */
+#define PORT_ARCHITECTURE_NAME "XXX Architecture"
+
+/**
+ * @brief Compiler name and version.
+ */
+#if defined(__GNUC__) || defined(__DOXYGEN__)
+#define PORT_COMPILER_NAME "GCC " __VERSION__
+
+#else
+#error "unsupported compiler"
+#endif
+
+/**
+ * @brief Port-specific information string.
+ */
+#define PORT_INFO "no info"
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Stack size for the system idle thread.
+ * @details This size depends on the idle thread implementation, usually
+ * the idle thread should take no more space than those reserved
+ * by @p PORT_INT_REQUIRED_STACK.
+ */
+#if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__)
+#define PORT_IDLE_THREAD_STACK_SIZE 32
+#endif
+
+/**
+ * @brief Per-thread stack overhead for interrupts servicing.
+ * @details This constant is used in the calculation of the correct working
+ * area size.
+ */
+#if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__)
+#define PORT_INT_REQUIRED_STACK 256
+#endif
+
+/**
+ * @brief Enables an alternative timer implementation.
+ * @details Usually the port uses a timer interface defined in the file
+ * @p chcore_timer.h, if this option is enabled then the file
+ * @p chcore_timer_alt.h is included instead.
+ */
+#if !defined(PORT_USE_ALT_TIMER) || defined(__DOXYGEN__)
+#define PORT_USE_ALT_TIMER FALSE
+#endif
+
+/**
+ * @brief Enables a "wait for interrupt" instruction in the idle loop.
+ */
+#if !defined(PORT_XXX_WFI_SLEEP_IDLE) || defined(__DOXYGEN__)
+#define PORT_XXX_ENABLE_WFI_IDLE FALSE
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/**
+ * @brief Type of stack and memory alignment enforcement.
+ * @note In this architecture the stack alignment is enforced to 64 bits.
+ */
+typedef uint64_t stkalign_t;
+
+/**
+ * @brief Interrupt saved context.
+ * @details This structure represents the stack frame saved during a
+ * preemption-capable interrupt handler.
+ * @note R2 and R13 are not saved because those are assumed to be immutable
+ * during the system life cycle.
+ */
+struct port_extctx {
+};
+
+/**
+ * @brief System saved context.
+ * @details This structure represents the inner stack frame during a context
+ * switching.
+ * @note R2 and R13 are not saved because those are assumed to be immutable
+ * during the system life cycle.
+ * @note LR is stored in the caller context so it is not present in this
+ * structure.
+ */
+struct port_intctx {
+};
+
+/**
+ * @brief Platform dependent part of the @p thread_t structure.
+ * @details This structure usually contains just the saved stack pointer
+ * defined as a pointer to a @p port_intctx structure.
+ */
+struct port_context {
+ struct port_intctx *sp;
+};
+
+#endif /* !defined(_FROM_ASM_) */
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Platform dependent part of the @p chThdCreateI() API.
+ * @details This code usually setup the context switching frame represented
+ * by an @p port_intctx structure.
+ */
+#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \
+}
+
+/**
+ * @brief Computes the thread working area global size.
+ * @note There is no need to perform alignments in this macro.
+ */
+#define PORT_WA_SIZE(n) (sizeof(struct port_intctx) + \
+ sizeof(struct port_extctx) + \
+ ((size_t)(n)) + ((size_t)(PORT_INT_REQUIRED_STACK)))
+
+/**
+ * @brief Static working area allocation.
+ * @details This macro is used to allocate a static thread working area
+ * aligned as both position and size.
+ *
+ * @param[in] s the name to be assigned to the stack array
+ * @param[in] n the stack size to be assigned to the thread
+ */
+#define PORT_WORKING_AREA(s, n) \
+ stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)]
+
+/**
+ * @brief Priority level verification macro.
+ */
+#define PORT_IRQ_IS_VALID_PRIORITY(n) false
+
+/**
+ * @brief Priority level verification macro.
+ */
+#define PORT_IRQ_IS_VALID_KERNEL_PRIORITY(n) false
+
+/**
+ * @brief IRQ prologue code.
+ * @details This macro must be inserted at the start of all IRQ handlers
+ * enabled to invoke system APIs.
+ */
+#define PORT_IRQ_PROLOGUE()
+
+/**
+ * @brief IRQ epilogue code.
+ * @details This macro must be inserted at the end of all IRQ handlers
+ * enabled to invoke system APIs.
+ */
+#define PORT_IRQ_EPILOGUE()
+
+/**
+ * @brief IRQ handler function declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ */
+#ifdef __cplusplus
+#define PORT_IRQ_HANDLER(id) extern "C" void id(void)
+#else
+#define PORT_IRQ_HANDLER(id) void id(void)
+#endif
+
+/**
+ * @brief Fast IRQ handler function declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ */
+#ifdef __cplusplus
+#define PORT_FAST_IRQ_HANDLER(id) extern "C" void id(void)
+#else
+#define PORT_FAST_IRQ_HANDLER(id) void id(void)
+#endif
+
+/**
+ * @brief Performs a context switch between two threads.
+ * @details This is the most critical code in any port, this function
+ * is responsible for the context switch between 2 threads.
+ * @note The implementation of this code affects directly the context
+ * switch performance so optimize here as much as you can.
+ *
+ * @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread to be switched out
+ */
+#if !CH_DBG_ENABLE_STACK_CHECK || defined(__DOXYGEN__)
+#define port_switch(ntp, otp) _port_switch(ntp, otp)
+#else
+#define port_switch(ntp, otp) { \
+ register struct port_intctx *sp asm ("%r1"); \
+ if ((stkalign_t *)(sp - 1) < otp->wabase) \
+ chSysHalt("stack overflow"); \
+ _port_switch(ntp, otp); \
+}
+#endif
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void _port_init(void);
+ void _port_switch(thread_t *ntp, thread_t *otp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined(_FROM_ASM_) */
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/**
+ * @brief Returns a word encoding the current interrupts status.
+ *
+ * @return The interrupts status.
+ */
+static inline syssts_t port_get_irq_status(void) {
+
+ return 0;
+}
+
+/**
+ * @brief Checks the interrupt status.
+ *
+ * @param[in] sts the interrupt status word
+ *
+ * @return The interrupt status.
+ * @retval false the word specified a disabled interrupts status.
+ * @retval true the word specified an enabled interrupts status.
+ */
+static inline bool port_irq_enabled(syssts_t sts) {
+
+ (void)sts;
+
+ return false;
+}
+
+/**
+ * @brief Determines the current execution context.
+ *
+ * @return The execution context.
+ * @retval false not running in ISR mode.
+ * @retval true running in ISR mode.
+ */
+static inline bool port_is_isr_context(void) {
+
+ return false;
+}
+
+/**
+ * @brief Kernel-lock action.
+ * @details Usually this function just disables interrupts but may perform more
+ * actions.
+ */
+static inline void port_lock(void) {
+
+}
+
+/**
+ * @brief Kernel-unlock action.
+ * @details Usually this function just enables interrupts but may perform more
+ * actions.
+ */
+static inline void port_unlock(void) {
+
+}
+
+/**
+ * @brief Kernel-lock action from an interrupt handler.
+ * @details This function is invoked before invoking I-class APIs from
+ * interrupt handlers. The implementation is architecture dependent,
+ * in its simplest form it is void.
+ */
+static inline void port_lock_from_isr(void) {
+
+}
+
+/**
+ * @brief Kernel-unlock action from an interrupt handler.
+ * @details This function is invoked after invoking I-class APIs from interrupt
+ * handlers. The implementation is architecture dependent, in its
+ * simplest form it is void.
+ */
+static inline void port_unlock_from_isr(void) {
+
+}
+
+/**
+ * @brief Disables all the interrupt sources.
+ * @note Of course non-maskable interrupt sources are not included.
+ */
+static inline void port_disable(void) {
+
+}
+
+/**
+ * @brief Disables the interrupt sources below kernel-level priority.
+ * @note Interrupt sources above kernel level remains enabled.
+ */
+static inline void port_suspend(void) {
+
+}
+
+/**
+ * @brief Enables all the interrupt sources.
+ */
+static inline void port_enable(void) {
+
+}
+
+/**
+ * @brief Enters an architecture-dependent IRQ-waiting mode.
+ * @details The function is meant to return when an interrupt becomes pending.
+ * The simplest implementation is an empty function or macro but this
+ * would not take advantage of architecture-specific power saving
+ * modes.
+ */
+static inline void port_wait_for_interrupt(void) {
+
+#if PORT_XXX_ENABLE_WFI_IDLE
+#endif
+}
+
+/**
+ * @brief Returns the current value of the realtime counter.
+ *
+ * @return The realtime counter value.
+ */
+static inline rtcnt_t port_rt_get_counter_value(void) {
+
+ return 0;
+}
+
+#endif /* !defined(_FROM_ASM_) */
+
+/*===========================================================================*/
+/* Module late inclusions. */
+/*===========================================================================*/
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+#if CH_CFG_ST_TIMEDELTA > 0
+#if !PORT_USE_ALT_TIMER
+#include "chcore_timer.h"
+#else /* PORT_USE_ALT_TIMER */
+#include "chcore_timer_alt.h"
+#endif /* PORT_USE_ALT_TIMER */
+#endif /* CH_CFG_ST_TIMEDELTA > 0 */
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CHCORE_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/ports/templates/chtypes.h b/ChibiOS_20.3.2/os/common/ports/templates/chtypes.h
new file mode 100644
index 0000000..fe30eff
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/ports/templates/chtypes.h
@@ -0,0 +1,101 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file templates/chtypes.h
+ * @brief System types template.
+ *
+ * @addtogroup port_types
+ * @details The types defined in this file may change depending on the target
+ * architecture. You may also try to optimize the size of the various
+ * types in order to privilege size or performance, be careful in
+ * doing so.
+ * @{
+ */
+
+#ifndef CHTYPES_H
+#define CHTYPES_H
+
+#include
+#include
+#include
+
+/**
+ * @name Kernel types
+ * @{
+ */
+typedef uint32_t rtcnt_t; /**< Realtime counter. */
+typedef uint64_t rttime_t; /**< Realtime accumulator. */
+typedef uint32_t syssts_t; /**< System status word. */
+typedef uint8_t tmode_t; /**< Thread flags. */
+typedef uint8_t tstate_t; /**< Thread state. */
+typedef uint8_t trefs_t; /**< Thread references counter. */
+typedef uint8_t tslices_t; /**< Thread time slices counter.*/
+typedef uint32_t tprio_t; /**< Thread priority. */
+typedef int32_t msg_t; /**< Inter-thread message. */
+typedef int32_t eventid_t; /**< Numeric event identifier. */
+typedef uint32_t eventmask_t; /**< Mask of event identifiers. */
+typedef uint32_t eventflags_t; /**< Mask of event flags. */
+typedef int32_t cnt_t; /**< Generic signed counter. */
+typedef uint32_t ucnt_t; /**< Generic unsigned counter. */
+/** @} */
+
+/**
+ * @brief ROM constant modifier.
+ * @note It is set to use the "const" keyword in this port.
+ */
+#define ROMCONST const
+
+/**
+ * @brief Makes functions not inlineable.
+ * @note If the compiler does not support such attribute then the
+ * realtime counter precision could be degraded.
+ */
+#define NOINLINE __attribute__((noinline))
+
+/**
+ * @brief Optimized thread function declaration macro.
+ */
+#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg)
+
+/**
+ * @brief Packed variable specifier.
+ */
+#define PACKED_VAR __attribute__((packed))
+
+/**
+ * @brief Memory alignment enforcement for variables.
+ */
+#define ALIGNED_VAR(n) __attribute__((aligned(n)))
+
+/**
+ * @brief Size of a pointer.
+ * @note To be used where the sizeof operator cannot be used, preprocessor
+ * expressions for example.
+ */
+#define SIZEOF_PTR 4
+
+/**
+ * @brief True if alignment is low-high in current architecture.
+ */
+#define REVERSE_ORDER 1
+
+#endif /* CHTYPES_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.S b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.S
new file mode 100644
index 0000000..4adb573
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.S
@@ -0,0 +1,288 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file crt0_v6m.S
+ * @brief Generic ARMv6-M (Cortex-M0/M1) startup file for ChibiOS.
+ *
+ * @addtogroup ARMCMx_GCC_STARTUP_V6M
+ * @{
+ */
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+
+#define CONTROL_MODE_PRIVILEGED 0
+#define CONTROL_MODE_UNPRIVILEGED 1
+#define CONTROL_USE_MSP 0
+#define CONTROL_USE_PSP 2
+
+#define SCB_VTOR 0xE000ED08
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enforces initialization of MSP.
+ * @note This is required if the boot process is not reliable for whatever
+ * reason (bad ROMs, bad bootloaders, bad debuggers=.
+ */
+#if !defined(CRT0_FORCE_MSP_INIT) || defined(__DOXYGEN__)
+#define CRT0_FORCE_MSP_INIT TRUE
+#endif
+
+/**
+ * @brief VTOR special register initialization.
+ * @details VTOR is initialized to point to the vectors table.
+ * @note This option can only be enabled on Cortex-M0+ cores.
+ */
+#if !defined(CRT0_VTOR_INIT) || defined(__DOXYGEN__)
+#define CRT0_VTOR_INIT FALSE
+#endif
+
+/**
+ * @brief Control special register initialization value.
+ * @details The system is setup to run in privileged mode using the PSP
+ * stack (dual stack mode).
+ */
+#if !defined(CRT0_CONTROL_INIT) || defined(__DOXYGEN__)
+#define CRT0_CONTROL_INIT (CONTROL_USE_PSP | \
+ CONTROL_MODE_PRIVILEGED)
+#endif
+
+/**
+ * @brief Core initialization switch.
+ */
+#if !defined(CRT0_INIT_CORE) || defined(__DOXYGEN__)
+#define CRT0_INIT_CORE TRUE
+#endif
+
+/**
+ * @brief Stack segments initialization switch.
+ */
+#if !defined(CRT0_STACKS_FILL_PATTERN) || defined(__DOXYGEN__)
+#define CRT0_STACKS_FILL_PATTERN 0x55555555
+#endif
+
+/**
+ * @brief Stack segments initialization switch.
+ */
+#if !defined(CRT0_INIT_STACKS) || defined(__DOXYGEN__)
+#define CRT0_INIT_STACKS TRUE
+#endif
+
+/**
+ * @brief DATA segment initialization switch.
+ */
+#if !defined(CRT0_INIT_DATA) || defined(__DOXYGEN__)
+#define CRT0_INIT_DATA TRUE
+#endif
+
+/**
+ * @brief BSS segment initialization switch.
+ */
+#if !defined(CRT0_INIT_BSS) || defined(__DOXYGEN__)
+#define CRT0_INIT_BSS TRUE
+#endif
+
+/**
+ * @brief RAM areas initialization switch.
+ */
+#if !defined(CRT0_INIT_RAM_AREAS) || defined(__DOXYGEN__)
+#define CRT0_INIT_RAM_AREAS TRUE
+#endif
+
+/**
+ * @brief Constructors invocation switch.
+ */
+#if !defined(CRT0_CALL_CONSTRUCTORS) || defined(__DOXYGEN__)
+#define CRT0_CALL_CONSTRUCTORS TRUE
+#endif
+
+/**
+ * @brief Destructors invocation switch.
+ */
+#if !defined(CRT0_CALL_DESTRUCTORS) || defined(__DOXYGEN__)
+#define CRT0_CALL_DESTRUCTORS TRUE
+#endif
+
+/*===========================================================================*/
+/* Code section. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+
+ .cpu cortex-m0
+ .fpu softvfp
+ .syntax unified
+ .thumb
+ .text
+
+/*
+ * CRT0 entry point.
+ */
+ .align 2
+ .thumb_func
+ .global _crt0_entry
+_crt0_entry:
+ /* Interrupts are globally masked initially.*/
+ cpsid i
+
+#if CRT0_FORCE_MSP_INIT == TRUE
+ /* MSP stack pointers initialization.*/
+ ldr r0, =__main_stack_end__
+ msr MSP, r0
+#endif
+
+ /* PSP stack pointers initialization.*/
+ ldr r0, =__process_stack_end__
+ msr PSP, r0
+
+ /* CPU mode initialization as configured.*/
+ movs r0, #CRT0_CONTROL_INIT
+ msr CONTROL, r0
+ isb
+
+#if CRT0_VTOR_INIT == TRUE
+ ldr r0, =_vectors
+ ldr r1, =SCB_VTOR
+ str r0, [r1]
+#endif
+
+#if CRT0_INIT_CORE == TRUE
+ /* Core initialization.*/
+ bl __core_init
+#endif
+
+ /* Early initialization..*/
+ bl __early_init
+
+#if CRT0_INIT_STACKS == TRUE
+ ldr r0, =CRT0_STACKS_FILL_PATTERN
+ /* Main Stack initialization. Note, it assumes that the
+ stack size is a multiple of 4 so the linker file must
+ ensure this.*/
+ ldr r1, =__main_stack_base__
+ ldr r2, =__main_stack_end__
+msloop:
+ cmp r1, r2
+ bge endmsloop
+ str r0, [r1]
+ adds r1, #4
+ b msloop
+endmsloop:
+ /* Process Stack initialization. Note, it assumes that the
+ stack size is a multiple of 4 so the linker file must
+ ensure this.*/
+ ldr r1, =__process_stack_base__
+ ldr r2, =__process_stack_end__
+psloop:
+ cmp r1, r2
+ bge endpsloop
+ str r0, [r1]
+ adds r1, #4
+ b psloop
+endpsloop:
+#endif
+
+#if CRT0_INIT_DATA == TRUE
+ /* Data initialization. Note, it assumes that the DATA size
+ is a multiple of 4 so the linker file must ensure this.*/
+ ldr r1, =__textdata_base__
+ ldr r2, =__data_base__
+ ldr r3, =__data_end__
+dloop:
+ cmp r2, r3
+ bge enddloop
+ ldr r0, [r1]
+ str r0, [r2]
+ adds r1, #4
+ adds r2, #4
+ b dloop
+enddloop:
+#endif
+
+#if CRT0_INIT_BSS == TRUE
+ /* BSS initialization. Note, it assumes that the DATA size
+ is a multiple of 4 so the linker file must ensure this.*/
+ movs r0, #0
+ ldr r1, =__bss_base__
+ ldr r2, =__bss_end__
+bloop:
+ cmp r1, r2
+ bge endbloop
+ str r0, [r1]
+ adds r1, #4
+ b bloop
+endbloop:
+#endif
+
+#if CRT0_INIT_RAM_AREAS == TRUE
+ /* RAM areas initialization.*/
+ bl __init_ram_areas
+#endif
+
+ /* Late initialization..*/
+ bl __late_init
+
+#if CRT0_CALL_CONSTRUCTORS == TRUE
+ /* Constructors invocation.*/
+ ldr r4, =__init_array_base__
+ ldr r5, =__init_array_end__
+initloop:
+ cmp r4, r5
+ bge endinitloop
+ ldr r1, [r4]
+ blx r1
+ adds r4, #4
+ b initloop
+endinitloop:
+#endif
+
+ /* Main program invocation, r0 contains the returned value.*/
+ bl main
+
+#if CRT0_CALL_DESTRUCTORS == TRUE
+ /* Destructors invocation.*/
+ ldr r4, =__fini_array_base__
+ ldr r5, =__fini_array_end__
+finiloop:
+ cmp r4, r5
+ bge endfiniloop
+ ldr r1, [r4]
+ blx r1
+ adds r4, #4
+ b finiloop
+endfiniloop:
+#endif
+
+ /* Branching to the defined exit handler.*/
+ ldr r1, =__default_exit
+ bx r1
+
+#endif
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S
new file mode 100644
index 0000000..4ce96d6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S
@@ -0,0 +1,350 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file crt0_v7m.S
+ * @brief Generic ARMv7-M (Cortex-M3/M4/M7) startup file for ChibiOS.
+ *
+ * @addtogroup ARMCMx_GCC_STARTUP_V7M
+ * @{
+ */
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+
+#define CONTROL_MODE_PRIVILEGED 0
+#define CONTROL_MODE_UNPRIVILEGED 1
+#define CONTROL_USE_MSP 0
+#define CONTROL_USE_PSP 2
+#define CONTROL_FPCA 4
+
+#define FPCCR_ASPEN (1 << 31)
+#define FPCCR_LSPEN (1 << 30)
+
+#define SCB_VTOR 0xE000ED08
+#define SCB_CPACR 0xE000ED88
+#define SCB_FPCCR 0xE000EF34
+#define SCB_FPDSCR 0xE000EF3C
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enforces initialization of MSP.
+ * @note This is required if the boot process is not reliable for whatever
+ * reason (bad ROMs, bad bootloaders, bad debuggers=.
+ */
+#if !defined(CRT0_FORCE_MSP_INIT) || defined(__DOXYGEN__)
+#define CRT0_FORCE_MSP_INIT TRUE
+#endif
+
+/**
+ * @brief VTOR special register initialization.
+ * @details VTOR is initialized to point to the vectors table.
+ */
+#if !defined(CRT0_VTOR_INIT) || defined(__DOXYGEN__)
+#define CRT0_VTOR_INIT TRUE
+#endif
+
+/**
+ * @brief FPU initialization switch.
+ */
+#if !defined(CRT0_INIT_FPU) || defined(__DOXYGEN__)
+#if defined(CORTEX_USE_FPU) || defined(__DOXYGEN__)
+#define CRT0_INIT_FPU CORTEX_USE_FPU
+#else
+#define CRT0_INIT_FPU FALSE
+#endif
+#endif
+
+/**
+ * @brief Control special register initialization value.
+ * @details The system is setup to run in privileged mode using the PSP
+ * stack (dual stack mode).
+ */
+#if !defined(CRT0_CONTROL_INIT) || defined(__DOXYGEN__)
+#define CRT0_CONTROL_INIT (CONTROL_USE_PSP | \
+ CONTROL_MODE_PRIVILEGED)
+#endif
+
+/**
+ * @brief Core initialization switch.
+ */
+#if !defined(CRT0_INIT_CORE) || defined(__DOXYGEN__)
+#define CRT0_INIT_CORE TRUE
+#endif
+
+/**
+ * @brief Stack segments initialization switch.
+ */
+#if !defined(CRT0_STACKS_FILL_PATTERN) || defined(__DOXYGEN__)
+#define CRT0_STACKS_FILL_PATTERN 0x55555555
+#endif
+
+/**
+ * @brief Stack segments initialization switch.
+ */
+#if !defined(CRT0_INIT_STACKS) || defined(__DOXYGEN__)
+#define CRT0_INIT_STACKS TRUE
+#endif
+
+/**
+ * @brief DATA segment initialization switch.
+ */
+#if !defined(CRT0_INIT_DATA) || defined(__DOXYGEN__)
+#define CRT0_INIT_DATA TRUE
+#endif
+
+/**
+ * @brief BSS segment initialization switch.
+ */
+#if !defined(CRT0_INIT_BSS) || defined(__DOXYGEN__)
+#define CRT0_INIT_BSS TRUE
+#endif
+
+/**
+ * @brief RAM areas initialization switch.
+ */
+#if !defined(CRT0_INIT_RAM_AREAS) || defined(__DOXYGEN__)
+#define CRT0_INIT_RAM_AREAS TRUE
+#endif
+
+/**
+ * @brief Constructors invocation switch.
+ */
+#if !defined(CRT0_CALL_CONSTRUCTORS) || defined(__DOXYGEN__)
+#define CRT0_CALL_CONSTRUCTORS TRUE
+#endif
+
+/**
+ * @brief Destructors invocation switch.
+ */
+#if !defined(CRT0_CALL_DESTRUCTORS) || defined(__DOXYGEN__)
+#define CRT0_CALL_DESTRUCTORS TRUE
+#endif
+
+/**
+ * @brief FPU FPCCR register initialization value.
+ * @note Only used if @p CRT0_INIT_FPU is equal to @p TRUE.
+ */
+#if !defined(CRT0_FPCCR_INIT) || defined(__DOXYGEN__)
+#define CRT0_FPCCR_INIT (FPCCR_ASPEN | FPCCR_LSPEN)
+#endif
+
+/**
+ * @brief CPACR register initialization value.
+ * @note Only used if @p CRT0_INIT_FPU is equal to @p TRUE.
+ */
+#if !defined(CRT0_CPACR_INIT) || defined(__DOXYGEN__)
+#define CRT0_CPACR_INIT 0x00F00000
+#endif
+
+/*===========================================================================*/
+/* Code section. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+
+ .syntax unified
+ .cpu cortex-m3
+#if CRT0_INIT_FPU == TRUE
+ .fpu fpv4-sp-d16
+#else
+ .fpu softvfp
+#endif
+
+ .thumb
+ .text
+
+/*
+ * CRT0 entry point.
+ */
+ .align 2
+ .thumb_func
+ .global _crt0_entry
+_crt0_entry:
+ /* Interrupts are globally masked initially.*/
+ cpsid i
+
+#if CRT0_FORCE_MSP_INIT == TRUE
+ /* MSP stack pointers initialization.*/
+ ldr r0, =__main_stack_end__
+ msr MSP, r0
+#endif
+
+ /* PSP stack pointers initialization.*/
+ ldr r0, =__process_stack_end__
+ msr PSP, r0
+
+#if CRT0_VTOR_INIT == TRUE
+ ldr r0, =_vectors
+ movw r1, #SCB_VTOR & 0xFFFF
+ movt r1, #SCB_VTOR >> 16
+ str r0, [r1]
+#endif
+
+#if CRT0_INIT_FPU == TRUE
+ /* FPU FPCCR initialization.*/
+ movw r0, #CRT0_FPCCR_INIT & 0xFFFF
+ movt r0, #CRT0_FPCCR_INIT >> 16
+ movw r1, #SCB_FPCCR & 0xFFFF
+ movt r1, #SCB_FPCCR >> 16
+ str r0, [r1]
+ dsb
+ isb
+
+ /* CPACR initialization.*/
+ movw r0, #CRT0_CPACR_INIT & 0xFFFF
+ movt r0, #CRT0_CPACR_INIT >> 16
+ movw r1, #SCB_CPACR & 0xFFFF
+ movt r1, #SCB_CPACR >> 16
+ str r0, [r1]
+ dsb
+ isb
+
+ /* FPU FPSCR initially cleared.*/
+ mov r0, #0
+ vmsr FPSCR, r0
+
+ /* FPU FPDSCR initially cleared.*/
+ movw r1, #SCB_FPDSCR & 0xFFFF
+ movt r1, #SCB_FPDSCR >> 16
+ str r0, [r1]
+
+ /* Enforcing FPCA bit in the CONTROL register.*/
+ movs r0, #CRT0_CONTROL_INIT | CONTROL_FPCA
+
+#else
+ movs r0, #CRT0_CONTROL_INIT
+#endif
+
+ /* CONTROL register initialization as configured.*/
+ msr CONTROL, r0
+ isb
+
+#if CRT0_INIT_CORE == TRUE
+ /* Core initialization.*/
+ bl __core_init
+#endif
+
+ /* Early initialization.*/
+ bl __early_init
+
+#if CRT0_INIT_STACKS == TRUE
+ ldr r0, =CRT0_STACKS_FILL_PATTERN
+ /* Main Stack initialization. Note, it assumes that the
+ stack size is a multiple of 4 so the linker file must
+ ensure this.*/
+ ldr r1, =__main_stack_base__
+ ldr r2, =__main_stack_end__
+msloop:
+ cmp r1, r2
+ itt lo
+ strlo r0, [r1], #4
+ blo msloop
+
+ /* Process Stack initialization. Note, it assumes that the
+ stack size is a multiple of 4 so the linker file must
+ ensure this.*/
+ ldr r1, =__process_stack_base__
+ ldr r2, =__process_stack_end__
+psloop:
+ cmp r1, r2
+ itt lo
+ strlo r0, [r1], #4
+ blo psloop
+#endif
+
+#if CRT0_INIT_DATA == TRUE
+ /* Data initialization. Note, it assumes that the DATA size
+ is a multiple of 4 so the linker file must ensure this.*/
+ ldr r1, =__textdata_base__
+ ldr r2, =__data_base__
+ ldr r3, =__data_end__
+dloop:
+ cmp r2, r3
+ ittt lo
+ ldrlo r0, [r1], #4
+ strlo r0, [r2], #4
+ blo dloop
+#endif
+
+#if CRT0_INIT_BSS == TRUE
+ /* BSS initialization. Note, it assumes that the DATA size
+ is a multiple of 4 so the linker file must ensure this.*/
+ movs r0, #0
+ ldr r1, =__bss_base__
+ ldr r2, =__bss_end__
+bloop:
+ cmp r1, r2
+ itt lo
+ strlo r0, [r1], #4
+ blo bloop
+#endif
+
+#if CRT0_INIT_RAM_AREAS == TRUE
+ /* RAM areas initialization.*/
+ bl __init_ram_areas
+#endif
+
+ /* Late initialization..*/
+ bl __late_init
+
+#if CRT0_CALL_CONSTRUCTORS == TRUE
+ /* Constructors invocation.*/
+ ldr r4, =__init_array_base__
+ ldr r5, =__init_array_end__
+initloop:
+ cmp r4, r5
+ bge endinitloop
+ ldr r1, [r4], #4
+ blx r1
+ b initloop
+endinitloop:
+#endif
+
+ /* Main program invocation, r0 contains the returned value.*/
+ bl main
+
+#if CRT0_CALL_DESTRUCTORS == TRUE
+ /* Destructors invocation.*/
+ ldr r4, =__fini_array_base__
+ ldr r5, =__fini_array_end__
+finiloop:
+ cmp r4, r5
+ bge endfiniloop
+ ldr r1, [r4], #4
+ blx r1
+ b finiloop
+endfiniloop:
+#endif
+
+ /* Branching to the defined exit handler.*/
+ b __default_exit
+
+#endif /* !defined(__DOXYGEN__) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/crt1.c b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/crt1.c
new file mode 100644
index 0000000..87179c4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/crt1.c
@@ -0,0 +1,219 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ARMCMx/compilers/GCC/crt1.c
+ * @brief Startup stub functions.
+ *
+ * @addtogroup ARMCMx_GCC_STARTUP
+ * @{
+ */
+
+#include
+#include
+
+#include "cmparams.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+#if !defined(CRT1_AREAS_NUMBER) || defined(__DOXYGEN__)
+#define CRT1_AREAS_NUMBER 8
+#endif
+
+#if (CRT1_AREAS_NUMBER < 0) || (CRT1_AREAS_NUMBER > 8)
+#error "CRT1_AREAS_NUMBER must be within 0 and 8"
+#endif
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of an area to be initialized.
+ */
+typedef struct {
+ uint32_t *init_text_area;
+ uint32_t *init_area;
+ uint32_t *clear_area;
+ uint32_t *no_init_area;
+} ram_init_area_t;
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+#if (CRT1_AREAS_NUMBER > 0) || defined(__DOXYGEN__)
+extern uint32_t __ram0_init_text__, __ram0_init__, __ram0_clear__, __ram0_noinit__;
+#endif
+#if (CRT1_AREAS_NUMBER > 1) || defined(__DOXYGEN__)
+extern uint32_t __ram1_init_text__, __ram1_init__, __ram1_clear__, __ram1_noinit__;
+#endif
+#if (CRT1_AREAS_NUMBER > 2) || defined(__DOXYGEN__)
+extern uint32_t __ram2_init_text__, __ram2_init__, __ram2_clear__, __ram2_noinit__;
+#endif
+#if (CRT1_AREAS_NUMBER > 3) || defined(__DOXYGEN__)
+extern uint32_t __ram3_init_text__, __ram3_init__, __ram3_clear__, __ram3_noinit__;
+#endif
+#if (CRT1_AREAS_NUMBER > 4) || defined(__DOXYGEN__)
+extern uint32_t __ram4_init_text__, __ram4_init__, __ram4_clear__, __ram4_noinit__;
+#endif
+#if (CRT1_AREAS_NUMBER > 5) || defined(__DOXYGEN__)
+extern uint32_t __ram5_init_text__, __ram5_init__, __ram5_clear__, __ram5_noinit__;
+#endif
+#if (CRT1_AREAS_NUMBER > 6) || defined(__DOXYGEN__)
+extern uint32_t __ram6_init_text__, __ram6_init__, __ram6_clear__, __ram6_noinit__;
+#endif
+#if (CRT1_AREAS_NUMBER > 7) || defined(__DOXYGEN__)
+extern uint32_t __ram7_init_text__, __ram7_init__, __ram7_clear__, __ram7_noinit__;
+#endif
+
+/**
+ * @brief Static table of areas to be initialized.
+ */
+#if (CRT1_AREAS_NUMBER > 0) || defined(__DOXYGEN__)
+static const ram_init_area_t ram_areas[CRT1_AREAS_NUMBER] = {
+ {&__ram0_init_text__, &__ram0_init__, &__ram0_clear__, &__ram0_noinit__},
+#if (CRT1_AREAS_NUMBER > 1) || defined(__DOXYGEN__)
+ {&__ram1_init_text__, &__ram1_init__, &__ram1_clear__, &__ram1_noinit__},
+#endif
+#if (CRT1_AREAS_NUMBER > 2) || defined(__DOXYGEN__)
+ {&__ram2_init_text__, &__ram2_init__, &__ram2_clear__, &__ram2_noinit__},
+#endif
+#if (CRT1_AREAS_NUMBER > 3) || defined(__DOXYGEN__)
+ {&__ram3_init_text__, &__ram3_init__, &__ram3_clear__, &__ram3_noinit__},
+#endif
+#if (CRT1_AREAS_NUMBER > 4) || defined(__DOXYGEN__)
+ {&__ram4_init_text__, &__ram4_init__, &__ram4_clear__, &__ram4_noinit__},
+#endif
+#if (CRT1_AREAS_NUMBER > 5) || defined(__DOXYGEN__)
+ {&__ram5_init_text__, &__ram5_init__, &__ram5_clear__, &__ram5_noinit__},
+#endif
+#if (CRT1_AREAS_NUMBER > 6) || defined(__DOXYGEN__)
+ {&__ram6_init_text__, &__ram6_init__, &__ram6_clear__, &__ram6_noinit__},
+#endif
+#if (CRT1_AREAS_NUMBER > 7) || defined(__DOXYGEN__)
+ {&__ram7_init_text__, &__ram7_init__, &__ram7_clear__, &__ram7_noinit__},
+#endif
+};
+#endif
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Architecture-dependent core initialization.
+ * @details This hook is invoked immediately after the stack initialization
+ * and before the DATA and BSS segments initialization.
+ * @note This function is a weak symbol.
+ */
+#if !defined(__DOXYGEN__)
+__attribute__((weak))
+#endif
+/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/
+void __core_init(void) {
+
+#if CORTEX_MODEL == 7
+ SCB_EnableICache();
+ SCB_EnableDCache();
+#endif
+}
+
+/**
+ * @brief Early initialization.
+ * @details This hook is invoked immediately after the stack and core
+ * initialization and before the DATA and BSS segments
+ * initialization.
+ * @note This function is a weak symbol.
+ */
+#if !defined(__DOXYGEN__)
+__attribute__((weak))
+#endif
+/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/
+void __early_init(void) {}
+/*lint -restore*/
+
+/**
+ * @brief Late initialization.
+ * @details This hook is invoked after the DATA and BSS segments
+ * initialization and before any static constructor. The
+ * default behavior is to do nothing.
+ * @note This function is a weak symbol.
+ */
+#if !defined(__DOXYGEN__)
+__attribute__((weak))
+#endif
+/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/
+void __late_init(void) {}
+/*lint -restore*/
+
+/**
+ * @brief Default @p main() function exit handler.
+ * @details This handler is invoked or the @p main() function exit. The
+ * default behavior is to enter an infinite loop.
+ * @note This function is a weak symbol.
+ */
+#if !defined(__DOXYGEN__)
+__attribute__((noreturn, weak))
+#endif
+/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/
+void __default_exit(void) {
+/*lint -restore*/
+
+ while (true) {
+ }
+}
+
+/**
+ * @brief Performs the initialization of the various RAM areas.
+ */
+void __init_ram_areas(void) {
+#if CRT1_AREAS_NUMBER > 0
+ const ram_init_area_t *rap = ram_areas;
+
+ do {
+ uint32_t *tp = rap->init_text_area;
+ uint32_t *p = rap->init_area;
+
+ /* Copying initialization data.*/
+ while (p < rap->clear_area) {
+ *p = *tp;
+ p++;
+ tp++;
+ }
+
+ /* Zeroing clear area.*/
+ while (p < rap->no_init_area) {
+ *p = 0;
+ p++;
+ }
+ rap++;
+ }
+ while (rap < &ram_areas[CRT1_AREAS_NUMBER]);
+#endif
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/ADUCM360.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/ADUCM360.ld
new file mode 100644
index 0000000..6393a09
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/ADUCM360.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * ADUCM360 memory setup.
+ * Note: Use of ram1 and ram2 is mutually exclusive with use of ram0.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x00000000, len = 128k /* On-chip Flash/EE */
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 8k /* SRAM */
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/ADUCM410.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/ADUCM410.ld
new file mode 100644
index 0000000..be56f7b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/ADUCM410.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * ADUCM410 memory setup.
+ * Note: Use of ram1 and ram2 is mutually exclusive with use of ram0.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x00000000, len = 512k /* Flash Block 0 */
+ flash1 (rx) : org = 0x00080000, len = 512k /* Flash Block 1 */
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 128k /* SRAM with ECC */
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F030x4.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F030x4.ld
new file mode 100644
index 0000000..52c131a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F030x4.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F030x4 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 16k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 4k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F030x6.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F030x6.ld
new file mode 100644
index 0000000..5afc8cb
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F030x6.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F030x6 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 32k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 4k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F030x8.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F030x8.ld
new file mode 100644
index 0000000..c2732f0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F030x8.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F030x8 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 64k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 8k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F031x6.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F031x6.ld
new file mode 100644
index 0000000..5ff7b07
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F031x6.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F031x6 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 32k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 4k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F042x6.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F042x6.ld
new file mode 100644
index 0000000..22ee72f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F042x6.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F042x6 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 32k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 6k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F051x8.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F051x8.ld
new file mode 100644
index 0000000..89d3cb0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F051x8.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F051x8 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 64k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 8k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F070x6.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F070x6.ld
new file mode 100644
index 0000000..0430df4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F070x6.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F070x6 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 32k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 6k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F070xB.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F070xB.ld
new file mode 100644
index 0000000..a848ef8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F070xB.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F070xB memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 128k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 16k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F072xB.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F072xB.ld
new file mode 100644
index 0000000..353ffb5
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F072xB.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F072xB memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 128k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 16k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F091xC.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F091xC.ld
new file mode 100644
index 0000000..fd5b883
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F091xC.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F091xC memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 256k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 32k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F100xB.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F100xB.ld
new file mode 100644
index 0000000..fb6ef4f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F100xB.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * ST32F100xB memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 128k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 8k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F103x8.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F103x8.ld
new file mode 100644
index 0000000..3de103d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F103x8.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * ST32F103x8 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 64k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 20k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F103xB.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F103xB.ld
new file mode 100644
index 0000000..2a5b200
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F103xB.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * ST32F103xB memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 128k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 20k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F103xB_maplemini_bootloader.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F103xB_maplemini_bootloader.ld
new file mode 100644
index 0000000..be17184
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F103xB_maplemini_bootloader.ld
@@ -0,0 +1,88 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * ST32F103xB memory setup for use with the maplemini bootloader.
+ * You will have to
+ * #define CORTEX_VTOR_INIT 0x5000
+ * in your projects chconf.h
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08005000, len = 128k - 0x5000
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000C00, len = 20k - 0xC00
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F103xD.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F103xD.ld
new file mode 100644
index 0000000..b5bbb32
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F103xD.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * ST32F103xE memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 384k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 64k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F103xE.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F103xE.ld
new file mode 100644
index 0000000..082a76e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F103xE.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * ST32F103xE memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 512k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 64k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F103xG.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F103xG.ld
new file mode 100644
index 0000000..02326fa
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F103xG.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * ST32F103xG memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 1M
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 96k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F107xC.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F107xC.ld
new file mode 100644
index 0000000..0b4749a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F107xC.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * ST32F107xC memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 256k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 64k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F207xG.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F207xG.ld
new file mode 100644
index 0000000..853d10e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F207xG.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F207xG memory setup.
+ * Note: Use of ram1 and ram2 is mutually exclusive with use of ram0.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 1M
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 128k /* SRAM1 + SRAM2 */
+ ram1 (wx) : org = 0x20000000, len = 112k /* SRAM1 */
+ ram2 (wx) : org = 0x2001C000, len = 16k /* SRAM2 */
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x10000000, len = 64k /* CCM SRAM */
+ ram5 (wx) : org = 0x40024000, len = 4k /* BCKP SRAM */
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F302x8.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F302x8.ld
new file mode 100644
index 0000000..f32b744
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F302x8.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F302x8 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 64k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 16k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F303x8.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F303x8.ld
new file mode 100644
index 0000000..739e7a4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F303x8.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F303x8 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 64k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 12k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x10000000, len = 4k
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F303xC.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F303xC.ld
new file mode 100644
index 0000000..c6e2bc8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F303xC.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F303xC memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 256k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 40k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x10000000, len = 8k
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F303xE.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F303xE.ld
new file mode 100644
index 0000000..ac78bde
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F303xE.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F303xE memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 512k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 64k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x10000000, len = 16k
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F334x8.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F334x8.ld
new file mode 100644
index 0000000..c95fb24
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F334x8.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F3334x8 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 64k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 12k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x10000000, len = 4k
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F373xC.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F373xC.ld
new file mode 100644
index 0000000..fbb3a3b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F373xC.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F303xC memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 256k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 32k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F401xC.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F401xC.ld
new file mode 100644
index 0000000..33b128f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F401xC.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F401xC memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 256k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 64k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F401xE.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F401xE.ld
new file mode 100644
index 0000000..ad8b786
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F401xE.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F401xE memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 512k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 96k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F405xG.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F405xG.ld
new file mode 100644
index 0000000..3d0c214
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F405xG.ld
@@ -0,0 +1,86 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F405xG memory setup.
+ * Note: Use of ram1 and ram2 is mutually exclusive with use of ram0.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 1M
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 128k /* SRAM1 + SRAM2 */
+ ram1 (wx) : org = 0x20000000, len = 112k /* SRAM1 */
+ ram2 (wx) : org = 0x2001C000, len = 16k /* SRAM2 */
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x10000000, len = 64k /* CCM SRAM */
+ ram5 (wx) : org = 0x40024000, len = 4k /* BCKP SRAM */
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F407xE.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F407xE.ld
new file mode 100644
index 0000000..b00c3b8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F407xE.ld
@@ -0,0 +1,86 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F407xE memory setup.
+ * Note: Use of ram1 and ram2 is mutually exclusive with use of ram0.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 512k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 128k /* SRAM1 + SRAM2 */
+ ram1 (wx) : org = 0x20000000, len = 112k /* SRAM1 */
+ ram2 (wx) : org = 0x2001C000, len = 16k /* SRAM2 */
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x10000000, len = 64k /* CCM SRAM */
+ ram5 (wx) : org = 0x40024000, len = 4k /* BCKP SRAM */
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F407xG.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F407xG.ld
new file mode 100644
index 0000000..e6d633a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F407xG.ld
@@ -0,0 +1,86 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F407xG memory setup.
+ * Note: Use of ram1 and ram2 is mutually exclusive with use of ram0.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 1M
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 128k /* SRAM1 + SRAM2 */
+ ram1 (wx) : org = 0x20000000, len = 112k /* SRAM1 */
+ ram2 (wx) : org = 0x2001C000, len = 16k /* SRAM2 */
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x10000000, len = 64k /* CCM SRAM */
+ ram5 (wx) : org = 0x40024000, len = 4k /* BCKP SRAM */
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F410x8.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F410x8.ld
new file mode 100644
index 0000000..6e5fac4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F410x8.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F410x8 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 64k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 32k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F410xB.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F410xB.ld
new file mode 100644
index 0000000..32737bd
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F410xB.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F410xB memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 128k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 32k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F411xC.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F411xC.ld
new file mode 100644
index 0000000..4cc2580
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F411xC.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F411xC memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 256k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 128k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F411xE.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F411xE.ld
new file mode 100644
index 0000000..dbaafc4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F411xE.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F411xE memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 512k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 128k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F412xE.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F412xE.ld
new file mode 100644
index 0000000..e485983
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F412xE.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F412xE memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 512k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 256k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F412xG.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F412xG.ld
new file mode 100644
index 0000000..176d33c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F412xG.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F412xG memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 1M
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 256k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F413xH.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F413xH.ld
new file mode 100644
index 0000000..2d32dae
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F413xH.ld
@@ -0,0 +1,86 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F413xH memory setup.
+ * Note: Use of ram1 and ram2 is mutually exclusive with use of ram0.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 1536k /* Program memory */
+ flash1 (rx) : org = 0x1FFF7800, len = 528 /* OTP memory */
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 320k /* SRAM1 + SRAM2 */
+ ram1 (wx) : org = 0x20000000, len = 256k /* SRAM1 */
+ ram2 (wx) : org = 0x20040000, len = 64k /* SRAM2 */
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x10000000, len = 64k /* CCM SRAM2 */
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F429xI.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F429xI.ld
new file mode 100644
index 0000000..57c9b41
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F429xI.ld
@@ -0,0 +1,86 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * ST32F429xI memory setup.
+ * Note: Use of ram1, ram2 and ram3 is mutually exclusive with use of ram0.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 1M
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 192k /* SRAM1 + SRAM2 + SRAM3 */
+ ram1 (wx) : org = 0x20000000, len = 112k /* SRAM1 */
+ ram2 (wx) : org = 0x2001C000, len = 16k /* SRAM2 */
+ ram3 (wx) : org = 0x20020000, len = 64k /* SRAM3 */
+ ram4 (wx) : org = 0x10000000, len = 64k /* CCM SRAM */
+ ram5 (wx) : org = 0x40024000, len = 4k /* BCKP SRAM */
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F446xC.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F446xC.ld
new file mode 100644
index 0000000..9d5ca51
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F446xC.ld
@@ -0,0 +1,86 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * ST32F446xC memory setup.
+ * Note: Use of ram1 and ram2 is mutually exclusive with use of ram0.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 256k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 128k /* SRAM1 + SRAM2 */
+ ram1 (wx) : org = 0x20000000, len = 112k /* SRAM1 */
+ ram2 (wx) : org = 0x00000000, len = 16k /* SRAM2 */
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F446xE.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F446xE.ld
new file mode 100644
index 0000000..de7d56c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F446xE.ld
@@ -0,0 +1,86 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * ST32F446xE memory setup.
+ * Note: Use of ram1 and ram2 is mutually exclusive with use of ram0.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 512k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 128k /* SRAM1 + SRAM2 */
+ ram1 (wx) : org = 0x20000000, len = 112k /* SRAM1 */
+ ram2 (wx) : org = 0x00000000, len = 16k /* SRAM2 */
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F469xI.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F469xI.ld
new file mode 100644
index 0000000..5dcac00
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F469xI.ld
@@ -0,0 +1,86 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * ST32F469xI memory setup.
+ * Note: Use of ram1, ram2 and ram3 is mutually exclusive with use of ram0.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 1M
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 384k /* SRAM1 + SRAM2 + SRAM3 */
+ ram1 (wx) : org = 0x20000000, len = 160k /* SRAM1 */
+ ram2 (wx) : org = 0x20028000, len = 32k /* SRAM2 */
+ ram3 (wx) : org = 0x20030000, len = 128k /* SRAM3 */
+ ram4 (wx) : org = 0x10000000, len = 64k /* CCM SRAM */
+ ram5 (wx) : org = 0x40024000, len = 4k /* BCKP SRAM */
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F722xE.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F722xE.ld
new file mode 100644
index 0000000..f3915db
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F722xE.ld
@@ -0,0 +1,136 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * ST32F722xE generic setup.
+ *
+ * RAM0 - Data, Heap.
+ * RAM3 - Main Stack, Process Stack, BSS, NOCACHE, ETH.
+ *
+ * Notes:
+ * BSS is placed in DTCM RAM in order to simplify DMA buffers management.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 1M /* Flash as AXIM (writable) */
+ flash1 (rx) : org = 0x00200000, len = 1M /* Flash as ITCM */
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20010000, len = 192k /* SRAM1 + SRAM2 */
+ ram1 (wx) : org = 0x20010000, len = 176k /* SRAM1 */
+ ram2 (wx) : org = 0x2003C000, len = 16k /* SRAM2 */
+ ram3 (wx) : org = 0x20000000, len = 64k /* DTCM-RAM */
+ ram4 (wx) : org = 0x00000000, len = 16k /* ITCM-RAM */
+ ram5 (wx) : org = 0x40024000, len = 4k /* BCKP SRAM */
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash1);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash1);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash1);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash1);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram3);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram3);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram3);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Stack rules inclusion.*/
+INCLUDE rules_stacks.ld
+
+/*===========================================================================*/
+/* Custom sections for STM32F7xx. */
+/*===========================================================================*/
+
+/* RAM region to be used for nocache segment.*/
+REGION_ALIAS("NOCACHE_RAM", ram3);
+
+/* RAM region to be used for eth segment.*/
+REGION_ALIAS("ETH_RAM", ram3);
+
+SECTIONS
+{
+ /* Special section for non cache-able areas.*/
+ .nocache (NOLOAD) : ALIGN(4)
+ {
+ __nocache_base__ = .;
+ *(.nocache)
+ *(.nocache.*)
+ *(.bss.__nocache_*)
+ . = ALIGN(4);
+ __nocache_end__ = .;
+ } > NOCACHE_RAM
+
+ /* Special section for Ethernet DMA non cache-able areas.*/
+ .eth (NOLOAD) : ALIGN(4)
+ {
+ __eth_base__ = .;
+ *(.eth)
+ *(.eth.*)
+ *(.bss.__eth_*)
+ . = ALIGN(4);
+ __eth_end__ = .;
+ } > ETH_RAM
+}
+
+/* Code rules inclusion.*/
+INCLUDE rules_code.ld
+
+/* Data rules inclusion.*/
+INCLUDE rules_data.ld
+
+/* Memory rules inclusion.*/
+INCLUDE rules_memory.ld
+
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F746xG.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F746xG.ld
new file mode 100644
index 0000000..82ce157
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F746xG.ld
@@ -0,0 +1,136 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F746xG generic setup.
+ *
+ * RAM0 - Data, Heap.
+ * RAM3 - Main Stack, Process Stack, BSS, NOCACHE, ETH.
+ *
+ * Notes:
+ * BSS is placed in DTCM RAM in order to simplify DMA buffers management.
+ */
+MEMORY
+{
+ flash0 (RX) : org = 0x08000000, len = 1M /* Flash as AXIM (writable) */
+ flash1 (RX) : org = 0x00200000, len = 1M /* Flash as ITCM */
+ flash2 (RX) : org = 0x00000000, len = 0
+ flash3 (RX) : org = 0x00000000, len = 0
+ flash4 (RX) : org = 0x00000000, len = 0
+ flash5 (RX) : org = 0x00000000, len = 0
+ flash6 (RX) : org = 0x00000000, len = 0
+ flash7 (RX) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20010000, len = 256k /* SRAM1 + SRAM2 */
+ ram1 (wx) : org = 0x20010000, len = 240k /* SRAM1 */
+ ram2 (wx) : org = 0x2004C000, len = 16k /* SRAM2 */
+ ram3 (wx) : org = 0x20000000, len = 64k /* DTCM-RAM */
+ ram4 (wx) : org = 0x00000000, len = 16k /* ITCM-RAM */
+ ram5 (wx) : org = 0x40024000, len = 4k /* BCKP SRAM */
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash1);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash1);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash1);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash1);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram3);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram3);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram3);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Stack rules inclusion.*/
+INCLUDE rules_stacks.ld
+
+/*===========================================================================*/
+/* Custom sections for STM32F7xx. */
+/*===========================================================================*/
+
+/* RAM region to be used for nocache segment.*/
+REGION_ALIAS("NOCACHE_RAM", ram3);
+
+/* RAM region to be used for eth segment.*/
+REGION_ALIAS("ETH_RAM", ram3);
+
+SECTIONS
+{
+ /* Special section for non cache-able areas.*/
+ .nocache (NOLOAD) : ALIGN(4)
+ {
+ __nocache_base__ = .;
+ *(.nocache)
+ *(.nocache.*)
+ *(.bss.__nocache_*)
+ . = ALIGN(4);
+ __nocache_end__ = .;
+ } > NOCACHE_RAM
+
+ /* Special section for Ethernet DMA non cache-able areas.*/
+ .eth (NOLOAD) : ALIGN(4)
+ {
+ __eth_base__ = .;
+ *(.eth)
+ *(.eth.*)
+ *(.bss.__eth_*)
+ . = ALIGN(4);
+ __eth_end__ = .;
+ } > ETH_RAM
+}
+
+/* Code rules inclusion.*/
+INCLUDE rules_code.ld
+
+/* Data rules inclusion.*/
+INCLUDE rules_data.ld
+
+/* Memory rules inclusion.*/
+INCLUDE rules_memory.ld
+
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F746xG_ETH.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F746xG_ETH.ld
new file mode 100644
index 0000000..6f6de62
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F746xG_ETH.ld
@@ -0,0 +1,137 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F746xG Ethernet setup.
+ *
+ * RAM1 - Data, Heap.
+ * RAM2 - ETH.
+ * RAM3 - Main Stack, Process Stack, BSS, NOCACHE.
+ *
+ * Notes:
+ * BSS is placed in DTCM RAM in order to simplify DMA buffers management.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 1M /* Flash as AXIM (writable) */
+ flash1 (rx) : org = 0x00200000, len = 1M /* Flash as ITCM */
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20010000, len = 256k /* SRAM1 + SRAM2 */
+ ram1 (wx) : org = 0x20010000, len = 240k /* SRAM1 */
+ ram2 (wx) : org = 0x2004C000, len = 16k /* SRAM2 */
+ ram3 (wx) : org = 0x20000000, len = 64k /* DTCM-RAM */
+ ram4 (wx) : org = 0x00000000, len = 16k /* ITCM-RAM */
+ ram5 (wx) : org = 0x40024000, len = 4k /* BCKP SRAM */
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash1);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash1);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash1);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash1);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram3);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram3);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram1);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram3);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram1);
+
+/* Stack rules inclusion.*/
+INCLUDE rules_stacks.ld
+
+/*===========================================================================*/
+/* Custom sections for STM32F7xx. */
+/*===========================================================================*/
+
+/* RAM region to be used for nocache segment.*/
+REGION_ALIAS("NOCACHE_RAM", ram3);
+
+/* RAM region to be used for eth segment.*/
+REGION_ALIAS("ETH_RAM", ram2);
+
+SECTIONS
+{
+ /* Special section for non cache-able areas.*/
+ .nocache (NOLOAD) : ALIGN(4)
+ {
+ __nocache_base__ = .;
+ *(.nocache)
+ *(.nocache.*)
+ *(.bss.__nocache_*)
+ . = ALIGN(4);
+ __nocache_end__ = .;
+ } > NOCACHE_RAM
+
+ /* Special section for Ethernet DMA non cache-able areas.*/
+ .eth (NOLOAD) : ALIGN(4)
+ {
+ __eth_base__ = .;
+ *(.eth)
+ *(.eth.*)
+ *(.bss.__eth_*)
+ . = ALIGN(4);
+ __eth_end__ = .;
+ } > ETH_RAM
+}
+
+/* Code rules inclusion.*/
+INCLUDE rules_code.ld
+
+/* Data rules inclusion.*/
+INCLUDE rules_data.ld
+
+/* Memory rules inclusion.*/
+INCLUDE rules_memory.ld
+
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F746xG_MAX.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F746xG_MAX.ld
new file mode 100644
index 0000000..d2917e9
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F746xG_MAX.ld
@@ -0,0 +1,138 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F746xG maximum RAM setup.
+ *
+ * RAM0 - Data, BSS, Heap.
+ * RAM3 - Main Stack, Process Stack, NOCACHE, ETH.
+ *
+ * Notes:
+ * BSS is placed in cached RAM, DMA buffers management is delegated to the
+ * application code. This setup maximizes the linear RAM available to BSS and
+ * Heap.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 1M /* Flash as AXIM (writable) */
+ flash1 (rx) : org = 0x00200000, len = 1M /* Flash as ITCM */
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20010000, len = 256k /* SRAM1 + SRAM2 */
+ ram1 (wx) : org = 0x20010000, len = 240k /* SRAM1 */
+ ram2 (wx) : org = 0x2004C000, len = 16k /* SRAM2 */
+ ram3 (wx) : org = 0x20000000, len = 64k /* DTCM-RAM */
+ ram4 (wx) : org = 0x00000000, len = 16k /* ITCM-RAM */
+ ram5 (wx) : org = 0x40024000, len = 4k /* BCKP SRAM */
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash1);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash1);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash1);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash1);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram3);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram3);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Stack rules inclusion.*/
+INCLUDE rules_stacks.ld
+
+/*===========================================================================*/
+/* Custom sections for STM32F7xx. */
+/*===========================================================================*/
+
+/* RAM region to be used for nocache segment.*/
+REGION_ALIAS("NOCACHE_RAM", ram3);
+
+/* RAM region to be used for eth segment.*/
+REGION_ALIAS("ETH_RAM", ram3);
+
+SECTIONS
+{
+ /* Special section for non cache-able areas.*/
+ .nocache (NOLOAD) : ALIGN(4)
+ {
+ __nocache_base__ = .;
+ *(.nocache)
+ *(.nocache.*)
+ *(.bss.__nocache_*)
+ . = ALIGN(4);
+ __nocache_end__ = .;
+ } > NOCACHE_RAM
+
+ /* Special section for Ethernet DMA non cache-able areas.*/
+ .eth (NOLOAD) : ALIGN(4)
+ {
+ __eth_base__ = .;
+ *(.eth)
+ *(.eth.*)
+ *(.bss.__eth_*)
+ . = ALIGN(4);
+ __eth_end__ = .;
+ } > ETH_RAM
+}
+
+/* Code rules inclusion.*/
+INCLUDE rules_code.ld
+
+/* Data rules inclusion.*/
+INCLUDE rules_data.ld
+
+/* Memory rules inclusion.*/
+INCLUDE rules_memory.ld
+
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F756xG.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F756xG.ld
new file mode 100644
index 0000000..75ba962
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F756xG.ld
@@ -0,0 +1,136 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F756xG generic setup.
+ *
+ * RAM0 - Data, Heap.
+ * RAM3 - Main Stack, Process Stack, BSS, NOCACHE, ETH.
+ *
+ * Notes:
+ * BSS is placed in DTCM RAM in order to simplify DMA buffers management.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 1M /* Flash as AXIM (writable) */
+ flash1 (rx) : org = 0x00200000, len = 1M /* Flash as ITCM */
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20010000, len = 256k /* SRAM1 + SRAM2 */
+ ram1 (wx) : org = 0x20010000, len = 240k /* SRAM1 */
+ ram2 (wx) : org = 0x2004C000, len = 16k /* SRAM2 */
+ ram3 (wx) : org = 0x20000000, len = 64k /* DTCM-RAM */
+ ram4 (wx) : org = 0x00000000, len = 16k /* ITCM-RAM */
+ ram5 (wx) : org = 0x40024000, len = 4k /* BCKP SRAM */
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash1);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash1);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash1);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash1);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram3);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram3);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram3);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Stack rules inclusion.*/
+INCLUDE rules_stacks.ld
+
+/*===========================================================================*/
+/* Custom sections for STM32F7xx. */
+/*===========================================================================*/
+
+/* RAM region to be used for nocache segment.*/
+REGION_ALIAS("NOCACHE_RAM", ram3);
+
+/* RAM region to be used for eth segment.*/
+REGION_ALIAS("ETH_RAM", ram3);
+
+SECTIONS
+{
+ /* Special section for non cache-able areas.*/
+ .nocache (NOLOAD) : ALIGN(4)
+ {
+ __nocache_base__ = .;
+ *(.nocache)
+ *(.nocache.*)
+ *(.bss.__nocache_*)
+ . = ALIGN(4);
+ __nocache_end__ = .;
+ } > NOCACHE_RAM
+
+ /* Special section for Ethernet DMA non cache-able areas.*/
+ .eth (NOLOAD) : ALIGN(4)
+ {
+ __eth_base__ = .;
+ *(.eth)
+ *(.eth.*)
+ *(.bss.__eth_*)
+ . = ALIGN(4);
+ __eth_end__ = .;
+ } > ETH_RAM
+}
+
+/* Code rules inclusion.*/
+INCLUDE rules_code.ld
+
+/* Data rules inclusion.*/
+INCLUDE rules_data.ld
+
+/* Memory rules inclusion.*/
+INCLUDE rules_memory.ld
+
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F76xxG.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F76xxG.ld
new file mode 100644
index 0000000..74d8ba9
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F76xxG.ld
@@ -0,0 +1,136 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F76xxG generic setup.
+ *
+ * RAM0 - Data, Heap.
+ * RAM3 - Main Stack, Process Stack, BSS, NOCACHE, ETH.
+ *
+ * Notes:
+ * BSS is placed in DTCM RAM in order to simplify DMA buffers management.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 1M /* Flash as AXIM (writable) */
+ flash1 (rx) : org = 0x00200000, len = 1M /* Flash as ITCM */
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20020000, len = 384k /* SRAM1 + SRAM2 */
+ ram1 (wx) : org = 0x20020000, len = 368k /* SRAM1 */
+ ram2 (wx) : org = 0x2007C000, len = 16k /* SRAM2 */
+ ram3 (wx) : org = 0x20000000, len = 128k /* DTCM-RAM */
+ ram4 (wx) : org = 0x00000000, len = 16k /* ITCM-RAM */
+ ram5 (wx) : org = 0x40024000, len = 4k /* BCKP SRAM */
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash1);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash1);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash1);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash1);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram3);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram3);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram3);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Stack rules inclusion.*/
+INCLUDE rules_stacks.ld
+
+/*===========================================================================*/
+/* Custom sections for STM32F7xx. */
+/*===========================================================================*/
+
+/* RAM region to be used for nocache segment.*/
+REGION_ALIAS("NOCACHE_RAM", ram3);
+
+/* RAM region to be used for eth segment.*/
+REGION_ALIAS("ETH_RAM", ram3);
+
+SECTIONS
+{
+ /* Special section for non cache-able areas.*/
+ .nocache (NOLOAD) : ALIGN(4)
+ {
+ __nocache_base__ = .;
+ *(.nocache)
+ *(.nocache.*)
+ *(.bss.__nocache_*)
+ . = ALIGN(4);
+ __nocache_end__ = .;
+ } > NOCACHE_RAM
+
+ /* Special section for Ethernet DMA non cache-able areas.*/
+ .eth (NOLOAD) : ALIGN(4)
+ {
+ __eth_base__ = .;
+ *(.eth)
+ *(.eth.*)
+ *(.bss.__eth_*)
+ . = ALIGN(4);
+ __eth_end__ = .;
+ } > ETH_RAM
+}
+
+/* Code rules inclusion.*/
+INCLUDE rules_code.ld
+
+/* Data rules inclusion.*/
+INCLUDE rules_data.ld
+
+/* Memory rules inclusion.*/
+INCLUDE rules_memory.ld
+
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F76xxI.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F76xxI.ld
new file mode 100644
index 0000000..19fbfa8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32F76xxI.ld
@@ -0,0 +1,136 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32F76xxI generic setup.
+ *
+ * RAM0 - Data, Heap.
+ * RAM3 - Main Stack, Process Stack, BSS, NOCACHE, ETH.
+ *
+ * Notes:
+ * BSS is placed in DTCM RAM in order to simplify DMA buffers management.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 2M /* Flash as AXIM (writable) */
+ flash1 (rx) : org = 0x00200000, len = 2M /* Flash as ITCM */
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20020000, len = 384k /* SRAM1 + SRAM2 */
+ ram1 (wx) : org = 0x20020000, len = 368k /* SRAM1 */
+ ram2 (wx) : org = 0x2007C000, len = 16k /* SRAM2 */
+ ram3 (wx) : org = 0x20000000, len = 128k /* DTCM-RAM */
+ ram4 (wx) : org = 0x00000000, len = 16k /* ITCM-RAM */
+ ram5 (wx) : org = 0x40024000, len = 4k /* BCKP SRAM */
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash1);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash1);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash1);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash1);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram3);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram3);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram3);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Stack rules inclusion.*/
+INCLUDE rules_stacks.ld
+
+/*===========================================================================*/
+/* Custom sections for STM32F7xx. */
+/*===========================================================================*/
+
+/* RAM region to be used for nocache segment.*/
+REGION_ALIAS("NOCACHE_RAM", ram3);
+
+/* RAM region to be used for eth segment.*/
+REGION_ALIAS("ETH_RAM", ram3);
+
+SECTIONS
+{
+ /* Special section for non cache-able areas.*/
+ .nocache (NOLOAD) : ALIGN(4)
+ {
+ __nocache_base__ = .;
+ *(.nocache)
+ *(.nocache.*)
+ *(.bss.__nocache_*)
+ . = ALIGN(4);
+ __nocache_end__ = .;
+ } > NOCACHE_RAM
+
+ /* Special section for Ethernet DMA non cache-able areas.*/
+ .eth (NOLOAD) : ALIGN(4)
+ {
+ __eth_base__ = .;
+ *(.eth)
+ *(.eth.*)
+ *(.bss.__eth_*)
+ . = ALIGN(4);
+ __eth_end__ = .;
+ } > ETH_RAM
+}
+
+/* Code rules inclusion.*/
+INCLUDE rules_code.ld
+
+/* Data rules inclusion.*/
+INCLUDE rules_data.ld
+
+/* Memory rules inclusion.*/
+INCLUDE rules_memory.ld
+
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32G071xB.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32G071xB.ld
new file mode 100644
index 0000000..a752e3d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32G071xB.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32G071xB memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 128k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 36k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32G431xB.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32G431xB.ld
new file mode 100644
index 0000000..a02962b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32G431xB.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32G431xB memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 128k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 32k /* SRAM1+SRAM2+CCM */
+ ram1 (wx) : org = 0x20000000, len = 22k /* SRAM1+SRAM2 */
+ ram2 (wx) : org = 0x20000000, len = 16k /* SRAM1 */
+ ram3 (wx) : org = 0x20004000, len = 6k /* SRAM2 */
+ ram4 (wx) : org = 0x20005800, len = 10k /* CCM */
+ ram5 (wx) : org = 0x10000000, len = 10k /* CCM alias */
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32G474xE.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32G474xE.ld
new file mode 100644
index 0000000..a412843
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32G474xE.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32G474xE memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 512k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 128k /* SRAM1+SRAM2+CCM */
+ ram1 (wx) : org = 0x20000000, len = 96k /* SRAM1+SRAM2 */
+ ram2 (wx) : org = 0x20000000, len = 80k /* SRAM1 */
+ ram3 (wx) : org = 0x20014000, len = 16k /* SRAM2 */
+ ram4 (wx) : org = 0x20018000, len = 32k /* CCM */
+ ram5 (wx) : org = 0x10000000, len = 32k /* CCM alias */
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32H743xI.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32H743xI.ld
new file mode 100755
index 0000000..f715a8f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32H743xI.ld
@@ -0,0 +1,139 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32H743xI generic setup.
+ *
+ * AXI SRAM - BSS, Data, Heap.
+ * SRAM1+SRAM2 - None.
+ * SRAM3 - NOCACHE, ETH.
+ * SRAM4 - None.
+ * DTCM-RAM - Main Stack, Process Stack.
+ * ITCM-RAM - None.
+ * BCKP SRAM - None.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 2M /* Flash bank1+bank2 */
+ flash1 (rx) : org = 0x08000000, len = 1M /* Flash bank 1 */
+ flash2 (rx) : org = 0x08100000, len = 1M /* Flash bank 2 */
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x24000000, len = 512k /* AXI SRAM */
+ ram1 (wx) : org = 0x30000000, len = 256k /* AHB SRAM1+SRAM2 */
+ ram2 (wx) : org = 0x30000000, len = 288k /* AHB SRAM1+SRAM2+SRAM3 */
+ ram3 (wx) : org = 0x30040000, len = 32k /* AHB SRAM3 */
+ ram4 (wx) : org = 0x38000000, len = 64k /* AHB SRAM4 */
+ ram5 (wx) : org = 0x20000000, len = 128k /* DTCM-RAM */
+ ram6 (wx) : org = 0x00000000, len = 64k /* ITCM-RAM */
+ ram7 (wx) : org = 0x38800000, len = 4k /* BCKP SRAM */
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram5);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram5);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Stack rules inclusion.*/
+INCLUDE rules_stacks.ld
+
+/*===========================================================================*/
+/* Custom sections for STM32H7xx. */
+/* SRAM3 is assumed to be marked non-cacheable using MPU. */
+/*===========================================================================*/
+
+/* RAM region to be used for nocache segment.*/
+REGION_ALIAS("NOCACHE_RAM", ram3);
+
+/* RAM region to be used for eth segment.*/
+REGION_ALIAS("ETH_RAM", ram3);
+
+SECTIONS
+{
+ /* Special section for non cache-able areas.*/
+ .nocache (NOLOAD) : ALIGN(4)
+ {
+ __nocache_base__ = .;
+ *(.nocache)
+ *(.nocache.*)
+ *(.bss.__nocache_*)
+ . = ALIGN(4);
+ __nocache_end__ = .;
+ } > NOCACHE_RAM
+
+ /* Special section for Ethernet DMA non cache-able areas.*/
+ .eth (NOLOAD) : ALIGN(4)
+ {
+ __eth_base__ = .;
+ *(.eth)
+ *(.eth.*)
+ *(.bss.__eth_*)
+ . = ALIGN(4);
+ __eth_end__ = .;
+ } > ETH_RAM
+}
+
+/* Code rules inclusion.*/
+INCLUDE rules_code.ld
+
+/* Data rules inclusion.*/
+INCLUDE rules_data.ld
+
+/* Memory rules inclusion.*/
+INCLUDE rules_memory.ld
+
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32H755xI_M7.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32H755xI_M7.ld
new file mode 100644
index 0000000..11af7dc
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32H755xI_M7.ld
@@ -0,0 +1,143 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32H755xI (M7 side) generic setup.
+ * Flash1 is assumed to be in use for the M7 core.
+ * Flash2 is not touched and can be used by the M4 core.
+ * RAM1 and RAM2 are assumed to be in use for the M7 core.
+ * RAM3 and RAM4 are not touched and can be used by the M4 core.
+ *
+ * AXI SRAM - BSS, Data, Heap.
+ * SRAM1+SRAM2 - None.
+ * SRAM3 - NOCACHE, ETH.
+ * SRAM4 - None.
+ * DTCM-RAM - Main Stack, Process Stack.
+ * ITCM-RAM - None.
+ * BCKP SRAM - None.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 2M /* Flash bank1+bank2 */
+ flash1 (rx) : org = 0x08000000, len = 1M /* Flash bank 1 */
+ flash2 (rx) : org = 0x08100000, len = 1M /* Flash bank 2 */
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x24000000, len = 512k /* AXI SRAM */
+ ram1 (wx) : org = 0x30000000, len = 256k /* AHB SRAM1+SRAM2 */
+ ram2 (wx) : org = 0x30000000, len = 288k /* AHB SRAM1+SRAM2+SRAM3 */
+ ram3 (wx) : org = 0x30040000, len = 32k /* AHB SRAM3 */
+ ram4 (wx) : org = 0x38000000, len = 64k /* AHB SRAM4 */
+ ram5 (wx) : org = 0x20000000, len = 128k /* DTCM-RAM */
+ ram6 (wx) : org = 0x00000000, len = 64k /* ITCM-RAM */
+ ram7 (wx) : org = 0x38800000, len = 4k /* BCKP SRAM */
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash1);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash1);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash1);
+REGION_ALIAS("XTORS_FLASH_LMA", flash1);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash1);
+REGION_ALIAS("TEXT_FLASH_LMA", flash1);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash1);
+REGION_ALIAS("RODATA_FLASH_LMA", flash1);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash1);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash1);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash1);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram5);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram5);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash1);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Stack rules inclusion.*/
+INCLUDE rules_stacks.ld
+
+/*===========================================================================*/
+/* Custom sections for STM32H7xx. */
+/* SRAM3 is assumed to be marked non-cacheable using MPU. */
+/*===========================================================================*/
+
+/* RAM region to be used for nocache segment.*/
+REGION_ALIAS("NOCACHE_RAM", ram3);
+
+/* RAM region to be used for eth segment.*/
+REGION_ALIAS("ETH_RAM", ram3);
+
+SECTIONS
+{
+ /* Special section for non cache-able areas.*/
+ .nocache (NOLOAD) : ALIGN(4)
+ {
+ __nocache_base__ = .;
+ *(.nocache)
+ *(.nocache.*)
+ *(.bss.__nocache_*)
+ . = ALIGN(4);
+ __nocache_end__ = .;
+ } > NOCACHE_RAM
+
+ /* Special section for Ethernet DMA non cache-able areas.*/
+ .eth (NOLOAD) : ALIGN(4)
+ {
+ __eth_base__ = .;
+ *(.eth)
+ *(.eth.*)
+ *(.bss.__eth_*)
+ . = ALIGN(4);
+ __eth_end__ = .;
+ } > ETH_RAM
+}
+
+/* Code rules inclusion.*/
+INCLUDE rules_code.ld
+
+/* Data rules inclusion.*/
+INCLUDE rules_data.ld
+
+/* Memory rules inclusion.*/
+INCLUDE rules_memory.ld
+
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L011x3.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L011x3.ld
new file mode 100644
index 0000000..878feb4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L011x3.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L011x3 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 8k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 2k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L011x4.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L011x4.ld
new file mode 100644
index 0000000..a896621
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L011x4.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L011x4 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 16k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 2k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L031x4.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L031x4.ld
new file mode 100644
index 0000000..527783e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L031x4.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L031x4 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 16k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 8k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L031x6.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L031x6.ld
new file mode 100644
index 0000000..c424b5a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L031x6.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L031x6 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 32k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 8k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L052x6.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L052x6.ld
new file mode 100644
index 0000000..e478aad
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L052x6.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L052x8 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 16k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 8k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L052x8.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L052x8.ld
new file mode 100644
index 0000000..64f0c15
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L052x8.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L052x8 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 64k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 8k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L053x6.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L053x6.ld
new file mode 100644
index 0000000..6b2116d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L053x6.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L053x6 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 32k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 8k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L053x8.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L053x8.ld
new file mode 100644
index 0000000..3a6f917
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L053x8.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L053x8 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 64k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 8k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L073x8.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L073x8.ld
new file mode 100644
index 0000000..7503de2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L073x8.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L073x8 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 64k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 20k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L073xB.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L073xB.ld
new file mode 100644
index 0000000..1b92681
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L073xB.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L073xB memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 128k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 20k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L073xZ.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L073xZ.ld
new file mode 100644
index 0000000..e60ebe0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L073xZ.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L073xZ memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 192k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 20k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L151x6.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L151x6.ld
new file mode 100644
index 0000000..8ec6e1b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L151x6.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L151x6 memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 32k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 10k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L152xB.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L152xB.ld
new file mode 100644
index 0000000..e899a77
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L152xB.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L152xB memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 128k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 16k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L152xE.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L152xE.ld
new file mode 100644
index 0000000..5552026
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L152xE.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L152xB memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 512k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 80k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L432xB.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L432xB.ld
new file mode 100644
index 0000000..f7e723b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L432xB.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L432xB memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 128k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 64k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x00000000, len = 0
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/STM32L432xC_stmdsp.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L432xC.ld
similarity index 94%
rename from STM32L432xC_stmdsp.ld
rename to ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L432xC.ld
index 0226659..e09722f 100644
--- a/STM32L432xC_stmdsp.ld
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L432xC.ld
@@ -27,7 +27,7 @@ MEMORY
flash5 (rx) : org = 0x00000000, len = 0
flash6 (rx) : org = 0x00000000, len = 0
flash7 (rx) : org = 0x00000000, len = 0
- ram0 (wx) : org = 0x20000000, len = 48k /* Save 16k of SRAM2 for loaded ELF */
+ ram0 (wx) : org = 0x20000000, len = 64k
ram1 (wx) : org = 0x00000000, len = 0
ram2 (wx) : org = 0x00000000, len = 0
ram3 (wx) : org = 0x00000000, len = 0
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L452xE.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L452xE.ld
new file mode 100644
index 0000000..d84ddb6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L452xE.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L452xE memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 512k
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 128k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x10000000, len = 32k /* This memory also mapped at address 0x20020000 */
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/STM32L476xG_stmdsp.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L476xG.ld
similarity index 94%
rename from STM32L476xG_stmdsp.ld
rename to ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L476xG.ld
index f54ab51..986e259 100644
--- a/STM32L476xG_stmdsp.ld
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L476xG.ld
@@ -31,7 +31,7 @@ MEMORY
ram1 (wx) : org = 0x00000000, len = 0
ram2 (wx) : org = 0x00000000, len = 0
ram3 (wx) : org = 0x00000000, len = 0
- ram4 (wx) : org = 0x10000000, len = 0 /* Save 32k for ELF load */
+ ram4 (wx) : org = 0x10000000, len = 32k
ram5 (wx) : org = 0x00000000, len = 0
ram6 (wx) : org = 0x00000000, len = 0
ram7 (wx) : org = 0x00000000, len = 0
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L496xG.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L496xG.ld
new file mode 100644
index 0000000..d773328
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L496xG.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L496xG memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 1M
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 256k
+ ram1 (wx) : org = 0x00000000, len = 0
+ ram2 (wx) : org = 0x00000000, len = 0
+ ram3 (wx) : org = 0x00000000, len = 0
+ ram4 (wx) : org = 0x10000000, len = 64k /* This memory also mapped at address 0x20040000 */
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L4R5xI.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L4R5xI.ld
new file mode 100644
index 0000000..64ed234
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L4R5xI.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L4R5xI memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 2M
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 640k /* SRAM1+SRAM2+SRAM3 */
+ ram1 (wx) : org = 0x20000000, len = 192k /* SRAM1 */
+ ram2 (wx) : org = 0x00000000, len = 64k /* SRAM2 */
+ ram3 (wx) : org = 0x00000000, len = 384k /* SRAM3 */
+ ram4 (wx) : org = 0x10000000, len = 64k /* SRAM2 alias */
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L4R9xI.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L4R9xI.ld
new file mode 100644
index 0000000..a985bee
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/STM32L4R9xI.ld
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * STM32L4R9xI memory setup.
+ */
+MEMORY
+{
+ flash0 (rx) : org = 0x08000000, len = 2M
+ flash1 (rx) : org = 0x00000000, len = 0
+ flash2 (rx) : org = 0x00000000, len = 0
+ flash3 (rx) : org = 0x00000000, len = 0
+ flash4 (rx) : org = 0x00000000, len = 0
+ flash5 (rx) : org = 0x00000000, len = 0
+ flash6 (rx) : org = 0x00000000, len = 0
+ flash7 (rx) : org = 0x00000000, len = 0
+ ram0 (wx) : org = 0x20000000, len = 640k /* SRAM1+SRAM2+SRAM3 */
+ ram1 (wx) : org = 0x20000000, len = 192k /* SRAM1 */
+ ram2 (wx) : org = 0x00000000, len = 64k /* SRAM2 */
+ ram3 (wx) : org = 0x00000000, len = 384k /* SRAM3 */
+ ram4 (wx) : org = 0x10000000, len = 64k /* SRAM2 alias */
+ ram5 (wx) : org = 0x00000000, len = 0
+ ram6 (wx) : org = 0x00000000, len = 0
+ ram7 (wx) : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/rules.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/rules.ld
new file mode 100644
index 0000000..8ca9a47
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/rules.ld
@@ -0,0 +1,11 @@
+/* Stack rules inclusion.*/
+INCLUDE rules_stacks.ld
+
+/* Code rules inclusion.*/
+INCLUDE rules_code.ld
+
+/* Data rules inclusion.*/
+INCLUDE rules_data.ld
+
+/* Memory rules inclusion.*/
+INCLUDE rules_memory.ld
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/rules_code.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/rules_code.ld
new file mode 100644
index 0000000..5a288af
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/rules_code.ld
@@ -0,0 +1,80 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+ .vectors : ALIGN(1024)
+ {
+ KEEP(*(.vectors))
+ } > VECTORS_FLASH AT > VECTORS_FLASH_LMA
+
+ .xtors : ALIGN(4)
+ {
+ __init_array_base__ = .;
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array))
+ __init_array_end__ = .;
+ __fini_array_base__ = .;
+ KEEP(*(.fini_array))
+ KEEP(*(SORT(.fini_array.*)))
+ __fini_array_end__ = .;
+ } > XTORS_FLASH AT > XTORS_FLASH_LMA
+
+ .text : ALIGN_WITH_INPUT
+ {
+ __text_base__ = .;
+ *(.text)
+ *(.text.*)
+ *(.glue_7t)
+ *(.glue_7)
+ *(.gcc*)
+ __text_end__ = .;
+ } > TEXT_FLASH AT > TEXT_FLASH_LMA
+
+ .rodata : ALIGN(4)
+ {
+ __rodata_base__ = .;
+ *(.rodata)
+ *(.rodata.*)
+ . = ALIGN(4);
+ __rodata_end__ = .;
+ } > RODATA_FLASH AT > RODATA_FLASH_LMA
+
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } > VARIOUS_FLASH AT > VARIOUS_FLASH_LMA
+
+ .ARM.exidx : {
+ __exidx_base__ = .;
+ __exidx_start = .;
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ __exidx_end__ = .;
+ __exidx_end = .;
+ } > VARIOUS_FLASH AT > VARIOUS_FLASH_LMA
+
+ .eh_frame_hdr :
+ {
+ *(.eh_frame_hdr)
+ } > VARIOUS_FLASH AT > VARIOUS_FLASH_LMA
+
+ .eh_frame : ONLY_IF_RO
+ {
+ *(.eh_frame)
+ } > VARIOUS_FLASH AT > VARIOUS_FLASH_LMA
+}
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/rules_data.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/rules_data.ld
new file mode 100644
index 0000000..c7fe00c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/rules_data.ld
@@ -0,0 +1,43 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+SECTIONS
+{
+ .data : ALIGN(4)
+ {
+ PROVIDE(_textdata = LOADADDR(.data));
+ PROVIDE(_data = .);
+ __textdata_base__ = LOADADDR(.data);
+ __data_base__ = .;
+ *(.data)
+ *(.data.*)
+ *(.ramtext)
+ . = ALIGN(4);
+ PROVIDE(_edata = .);
+ __data_end__ = .;
+ } > DATA_RAM AT > DATA_RAM_LMA
+
+ .bss (NOLOAD) : ALIGN(4)
+ {
+ __bss_base__ = .;
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ . = ALIGN(4);
+ __bss_end__ = .;
+ PROVIDE(end = .);
+ } > BSS_RAM
+}
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/rules_memory.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/rules_memory.ld
new file mode 100644
index 0000000..ab914b6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/rules_memory.ld
@@ -0,0 +1,317 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+__ram0_base__ = ORIGIN(ram0);
+__ram0_size__ = LENGTH(ram0);
+__ram0_end__ = __ram0_base__ + __ram0_size__;
+__ram1_base__ = ORIGIN(ram1);
+__ram1_size__ = LENGTH(ram1);
+__ram1_end__ = __ram1_base__ + __ram1_size__;
+__ram2_base__ = ORIGIN(ram2);
+__ram2_size__ = LENGTH(ram2);
+__ram2_end__ = __ram2_base__ + __ram2_size__;
+__ram3_base__ = ORIGIN(ram3);
+__ram3_size__ = LENGTH(ram3);
+__ram3_end__ = __ram3_base__ + __ram3_size__;
+__ram4_base__ = ORIGIN(ram4);
+__ram4_size__ = LENGTH(ram4);
+__ram4_end__ = __ram4_base__ + __ram4_size__;
+__ram5_base__ = ORIGIN(ram5);
+__ram5_size__ = LENGTH(ram5);
+__ram5_end__ = __ram5_base__ + __ram5_size__;
+__ram6_base__ = ORIGIN(ram6);
+__ram6_size__ = LENGTH(ram6);
+__ram6_end__ = __ram6_base__ + __ram6_size__;
+__ram7_base__ = ORIGIN(ram7);
+__ram7_size__ = LENGTH(ram7);
+__ram7_end__ = __ram7_base__ + __ram7_size__;
+
+__flash0_base__ = ORIGIN(flash0);
+__flash0_size__ = LENGTH(flash0);
+__flash0_end__ = __flash0_base__ + __flash0_size__;
+__flash1_base__ = ORIGIN(flash1);
+__flash1_size__ = LENGTH(flash1);
+__flash1_end__ = __flash1_base__ + __flash1_size__;
+__flash2_base__ = ORIGIN(flash2);
+__flash2_size__ = LENGTH(flash2);
+__flash2_end__ = __flash2_base__ + __flash2_size__;
+__flash3_base__ = ORIGIN(flash3);
+__flash3_size__ = LENGTH(flash3);
+__flash3_end__ = __flash3_base__ + __flash3_size__;
+__flash4_base__ = ORIGIN(flash4);
+__flash4_size__ = LENGTH(flash4);
+__flash4_end__ = __flash4_base__ + __flash4_size__;
+__flash5_base__ = ORIGIN(flash5);
+__flash5_size__ = LENGTH(flash5);
+__flash5_end__ = __flash5_base__ + __flash5_size__;
+__flash6_base__ = ORIGIN(flash6);
+__flash6_size__ = LENGTH(flash6);
+__flash6_end__ = __flash6_base__ + __flash6_size__;
+__flash7_base__ = ORIGIN(flash7);
+__flash7_size__ = LENGTH(flash7);
+__flash7_end__ = __flash7_base__ + __flash7_size__;
+
+SECTIONS
+{
+ .ram0_init : ALIGN(4)
+ {
+ __ram0_init_text__ = LOADADDR(.ram0_init);
+ __ram0_init__ = .;
+ KEEP(*(.ram0_init))
+ KEEP(*(.ram0_init.*))
+ . = ALIGN(4);
+ } > ram0 AT > RAM_INIT_FLASH_LMA
+
+ .ram0 (NOLOAD) : ALIGN(4)
+ {
+ __ram0_clear__ = .;
+ *(.ram0_clear)
+ *(.ram0_clear.*)
+ . = ALIGN(4);
+ __ram0_noinit__ = .;
+ *(.ram0)
+ *(.ram0.*)
+ . = ALIGN(4);
+ __ram0_free__ = .;
+ } > ram0
+
+ .ram1_init : ALIGN(4)
+ {
+ __ram1_init_text__ = LOADADDR(.ram1_init);
+ __ram1_init__ = .;
+ KEEP(*(.ram1_init))
+ KEEP(*(.ram1_init.*))
+ . = ALIGN(4);
+ } > ram1 AT > RAM_INIT_FLASH_LMA
+
+ .ram1 (NOLOAD) : ALIGN(4)
+ {
+ __ram1_clear__ = .;
+ *(.ram1_clear)
+ *(.ram1_clear.*)
+ . = ALIGN(4);
+ __ram1_noinit__ = .;
+ *(.ram1)
+ *(.ram1.*)
+ . = ALIGN(4);
+ __ram1_free__ = .;
+ } > ram1
+
+ .ram2_init : ALIGN(4)
+ {
+ __ram2_init_text__ = LOADADDR(.ram2_init);
+ __ram2_init__ = .;
+ KEEP(*(.ram2_init))
+ KEEP(*(.ram2_init.*))
+ . = ALIGN(4);
+ } > ram2 AT > RAM_INIT_FLASH_LMA
+
+ .ram2 (NOLOAD) : ALIGN(4)
+ {
+ __ram2_clear__ = .;
+ *(.ram2_clear)
+ *(.ram2_clear.*)
+ . = ALIGN(4);
+ __ram2_noinit__ = .;
+ *(.ram2)
+ *(.ram2.*)
+ . = ALIGN(4);
+ __ram2_free__ = .;
+ } > ram2
+
+ .ram3_init : ALIGN(4)
+ {
+ __ram3_init_text__ = LOADADDR(.ram3_init);
+ __ram3_init__ = .;
+ KEEP(*(.ram3_init))
+ KEEP(*(.ram3_init.*))
+ . = ALIGN(4);
+ } > ram3 AT > RAM_INIT_FLASH_LMA
+
+ .ram3 (NOLOAD) : ALIGN(4)
+ {
+ __ram3_clear__ = .;
+ *(.ram3_clear)
+ *(.ram3_clear.*)
+ . = ALIGN(4);
+ __ram3_noinit__ = .;
+ *(.ram3)
+ *(.ram3.*)
+ . = ALIGN(4);
+ __ram3_free__ = .;
+ } > ram3
+
+ .ram4_init : ALIGN(4)
+ {
+ __ram4_init_text__ = LOADADDR(.ram4_init);
+ __ram4_init__ = .;
+ KEEP(*(.ram4_init))
+ KEEP(*(.ram4_init.*))
+ . = ALIGN(4);
+ } > ram4 AT > RAM_INIT_FLASH_LMA
+
+ .ram4 (NOLOAD) : ALIGN(4)
+ {
+ __ram4_clear__ = .;
+ *(.ram4_clear)
+ *(.ram4_clear.*)
+ . = ALIGN(4);
+ __ram4_noinit__ = .;
+ *(.ram4)
+ *(.ram4.*)
+ . = ALIGN(4);
+ __ram4_free__ = .;
+ } > ram4
+
+ .ram5_init : ALIGN(4)
+ {
+ __ram5_init_text__ = LOADADDR(.ram5_init);
+ __ram5_init__ = .;
+ KEEP(*(.ram5_init))
+ KEEP(*(.ram5_init.*))
+ . = ALIGN(4);
+ } > ram5 AT > RAM_INIT_FLASH_LMA
+
+ .ram5 (NOLOAD) : ALIGN(4)
+ {
+ __ram5_clear__ = .;
+ *(.ram5_clear)
+ *(.ram5_clear.*)
+ . = ALIGN(4);
+ __ram5_noinit__ = .;
+ *(.ram5)
+ *(.ram5.*)
+ . = ALIGN(4);
+ __ram5_free__ = .;
+ } > ram5
+
+ .ram6_init : ALIGN(4)
+ {
+ __ram6_init_text__ = LOADADDR(.ram6_init);
+ __ram6_init__ = .;
+ KEEP(*(.ram6_init))
+ KEEP(*(.ram6_init.*))
+ . = ALIGN(4);
+ } > ram6 AT > RAM_INIT_FLASH_LMA
+
+ .ram6 (NOLOAD) : ALIGN(4)
+ {
+ __ram6_clear__ = .;
+ *(.ram6_clear)
+ *(.ram6_clear.*)
+ . = ALIGN(4);
+ __ram6_noinit__ = .;
+ *(.ram6)
+ *(.ram6.*)
+ . = ALIGN(4);
+ __ram6_free__ = .;
+ } > ram6
+
+ .ram7_init : ALIGN(4)
+ {
+ __ram7_init_text__ = LOADADDR(.ram7_init);
+ __ram7_init__ = .;
+ KEEP(*(.ram7_init))
+ KEEP(*(.ram7_init.*))
+ . = ALIGN(4);
+ } > ram7 AT > RAM_INIT_FLASH_LMA
+
+ .ram7 (NOLOAD) : ALIGN(4)
+ {
+ __ram7_clear__ = .;
+ *(.ram7_clear)
+ *(.ram7_clear.*)
+ . = ALIGN(4);
+ __ram7_noinit__ = .;
+ *(.ram7)
+ *(.ram7.*)
+ . = ALIGN(4);
+ __ram7_free__ = .;
+ } > ram7
+
+ .flash0 : ALIGN(4)
+ {
+ __flash0_init__ = .;
+ KEEP(*(.flash0_init))
+ KEEP(*(.flash0_init.*))
+ __flash0_free__ = .;
+ } > flash0
+
+ .flash1 : ALIGN(4)
+ {
+ __flash1_init__ = .;
+ KEEP(*(.flash1_init))
+ KEEP(*(.flash1_init.*))
+ __flash1_free__ = .;
+ } > flash1
+
+ .flash2 : ALIGN(4)
+ {
+ __flash2_init__ = .;
+ KEEP(*(.flash2_init))
+ KEEP(*(.flash2_init.*))
+ __flash2_free__ = .;
+ } > flash2
+
+ .flash3 : ALIGN(4)
+ {
+ __flash3_init__ = .;
+ KEEP(*(.flash3_init))
+ KEEP(*(.flash3_init.*))
+ __flash3_free__ = .;
+ } > flash3
+
+ .flash4 : ALIGN(4)
+ {
+ __flash4_init__ = .;
+ KEEP(*(.flash4_init))
+ KEEP(*(.flash4_init.*))
+ __flash4_free__ = .;
+ } > flash4
+
+ .flash5 : ALIGN(4)
+ {
+ __flash5_init__ = .;
+ KEEP(*(.flash5_init))
+ KEEP(*(.flash5_init.*))
+ __flash5_free__ = .;
+ } > flash5
+
+ .flash6 : ALIGN(4)
+ {
+ __flash6_init__ = .;
+ KEEP(*(.flash6_init))
+ KEEP(*(.flash6_init.*))
+ __flash6_free__ = .;
+ } > flash6
+
+ .flash7 : ALIGN(4)
+ {
+ __flash7_init__ = .;
+ KEEP(*(.flash7_init))
+ KEEP(*(.flash7_init.*))
+ __flash7_free__ = .;
+ } > flash7
+
+ /* The default heap uses the (statically) unused part of a RAM section.*/
+ .heap (NOLOAD) :
+ {
+ . = ALIGN(8);
+ __heap_base__ = .;
+ . = ORIGIN(HEAP_RAM) + LENGTH(HEAP_RAM);
+ __heap_end__ = .;
+ } > HEAP_RAM
+}
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/rules_stacks.ld b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/rules_stacks.ld
new file mode 100644
index 0000000..1c64a44
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/ld/rules_stacks.ld
@@ -0,0 +1,40 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+SECTIONS
+{
+ /* Special section for exceptions stack.*/
+ .mstack (NOLOAD) :
+ {
+ . = ALIGN(8);
+ __main_stack_base__ = .;
+ . += __main_stack_size__;
+ . = ALIGN(8);
+ __main_stack_end__ = .;
+ } > MAIN_STACK_RAM
+
+ /* Special section for process stack.*/
+ .pstack (NOLOAD) :
+ {
+ . = ALIGN(8);
+ __process_stack_base__ = .;
+ __main_thread_stack_base__ = .;
+ . += __process_stack_size__;
+ . = ALIGN(8);
+ __process_stack_end__ = .;
+ __main_thread_stack_end__ = .;
+ } > PROCESS_STACK_RAM
+}
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/arm-none-eabi.mk b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/arm-none-eabi.mk
new file mode 100644
index 0000000..5df5fe2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/arm-none-eabi.mk
@@ -0,0 +1,23 @@
+##############################################################################
+# Compiler settings
+#
+
+TRGT = arm-none-eabi-
+CC = $(TRGT)gcc
+CPPC = $(TRGT)g++
+# Enable loading with g++ only if you need C++ runtime support.
+# NOTE: You can use C++ even without C++ support if you are careful. C++
+# runtime support makes code size explode.
+LD = $(TRGT)gcc
+#LD = $(TRGT)g++
+CP = $(TRGT)objcopy
+AS = $(TRGT)gcc -x assembler-with-cpp
+AR = $(TRGT)ar
+OD = $(TRGT)objdump
+SZ = $(TRGT)size
+HEX = $(CP) -O ihex
+BIN = $(CP) -O binary
+
+#
+# Compiler settings
+##############################################################################
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/rules.mk b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/rules.mk
new file mode 100644
index 0000000..4f7178d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/rules.mk
@@ -0,0 +1,291 @@
+# ARM Cortex-Mx common makefile scripts and rules.
+
+##############################################################################
+# Processing options coming from the upper Makefile.
+#
+
+# Compiler options
+OPT := $(USE_OPT)
+COPT := $(USE_COPT)
+CPPOPT := $(USE_CPPOPT)
+
+# Garbage collection
+ifeq ($(USE_LINK_GC),yes)
+ OPT += -ffunction-sections -fdata-sections -fno-common
+ LDOPT := ,--gc-sections
+else
+ LDOPT :=
+endif
+
+# Linker extra options
+ifneq ($(USE_LDOPT),)
+ LDOPT := $(LDOPT),$(USE_LDOPT)
+endif
+
+# Link time optimizations
+ifeq ($(USE_LTO),yes)
+ OPT += -flto
+endif
+
+# FPU options default (Cortex-M4 and Cortex-M7 single precision).
+ifeq ($(USE_FPU_OPT),)
+ USE_FPU_OPT = -mfloat-abi=$(USE_FPU) -mfpu=fpv4-sp-d16
+endif
+
+# FPU-related options
+ifeq ($(USE_FPU),)
+ USE_FPU = no
+endif
+ifneq ($(USE_FPU),no)
+ OPT += $(USE_FPU_OPT)
+ DDEFS += -DCORTEX_USE_FPU=TRUE
+ DADEFS += -DCORTEX_USE_FPU=TRUE
+else
+ DDEFS += -DCORTEX_USE_FPU=FALSE
+ DADEFS += -DCORTEX_USE_FPU=FALSE
+endif
+
+# Process stack size
+ifeq ($(USE_PROCESS_STACKSIZE),)
+ LDOPT := $(LDOPT),--defsym=__process_stack_size__=0x400
+else
+ LDOPT := $(LDOPT),--defsym=__process_stack_size__=$(USE_PROCESS_STACKSIZE)
+endif
+
+# Exceptions stack size
+ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
+ LDOPT := $(LDOPT),--defsym=__main_stack_size__=0x400
+else
+ LDOPT := $(LDOPT),--defsym=__main_stack_size__=$(USE_EXCEPTIONS_STACKSIZE)
+endif
+
+# Output directory and files
+ifeq ($(BUILDDIR),)
+ BUILDDIR = build
+endif
+ifeq ($(BUILDDIR),.)
+ BUILDDIR = build
+endif
+
+# Dependencies directory
+ifeq ($(DEPDIR),)
+ DEPDIR = .dep
+endif
+ifeq ($(DEPDIR),.)
+ DEPDIR = .dep
+endif
+
+OUTFILES := $(BUILDDIR)/$(PROJECT).elf \
+ $(BUILDDIR)/$(PROJECT).hex \
+ $(BUILDDIR)/$(PROJECT).bin \
+ $(BUILDDIR)/$(PROJECT).dmp \
+ $(BUILDDIR)/$(PROJECT).list
+
+ifdef SREC
+ OUTFILES += $(BUILDDIR)/$(PROJECT).srec
+endif
+
+# Source files groups and paths
+TCSRC += $(CSRC)
+TCPPSRC += $(CPPSRC)
+TSRC := $(TCSRC) $(TCPPSRC)
+SRCPATHS := $(sort $(dir $(ASMXSRC)) $(dir $(ASMSRC)) $(dir $(TSRC)))
+
+# Various directories
+OBJDIR := $(BUILDDIR)/obj
+LSTDIR := $(BUILDDIR)/lst
+
+# Object files groups
+TCOBJS := $(addprefix $(OBJDIR)/, $(notdir $(TCSRC:.c=.o)))
+#TCPPOBJS := $(addprefix $(OBJDIR)/, $(notdir $(TCPPSRC:.cpp=.o)))
+TCPPOBJS := $(addprefix $(OBJDIR)/, $(notdir $(patsubst %.cpp, %.o, $(filter %.cpp, $(TCPPSRC)))))
+TCCOBJS := $(addprefix $(OBJDIR)/, $(notdir $(patsubst %.cc, %.o, $(filter %.cc, $(TCPPSRC)))))
+ASMOBJS := $(addprefix $(OBJDIR)/, $(notdir $(ASMSRC:.s=.o)))
+ASMXOBJS := $(addprefix $(OBJDIR)/, $(notdir $(ASMXSRC:.S=.o)))
+#OBJS := $(ASMXOBJS) $(ASMOBJS) $(ACOBJS) $(TCOBJS) $(ACPPOBJS) $(TCPPOBJS)
+OBJS := $(ASMXOBJS) $(ASMOBJS) $(ACOBJS) $(TCOBJS) $(ACPPOBJS) $(TCPPOBJS) $(TCCOBJS)
+
+# Paths
+IINCDIR := $(patsubst %,-I%,$(INCDIR) $(DINCDIR) $(UINCDIR))
+LLIBDIR := $(patsubst %,-L%,$(DLIBDIR) $(ULIBDIR))
+
+# Macros
+DEFS := $(DDEFS) $(UDEFS)
+ADEFS := $(DADEFS) $(UADEFS)
+
+# Libs
+LIBS := $(DLIBS) $(ULIBS)
+
+# Various settings
+MCFLAGS := -mcpu=$(MCU) -mthumb
+ODFLAGS = -x --syms
+ASFLAGS = $(MCFLAGS) $(OPT) -Wa,-amhls=$(LSTDIR)/$(notdir $(<:.s=.lst)) $(ADEFS)
+ASXFLAGS = $(MCFLAGS) $(OPT) -Wa,-amhls=$(LSTDIR)/$(notdir $(<:.S=.lst)) $(ADEFS)
+CFLAGS = $(MCFLAGS) $(OPT) $(COPT) $(CWARN) -Wa,-alms=$(LSTDIR)/$(notdir $(<:.c=.lst)) $(DEFS)
+CPPFLAGS = $(MCFLAGS) $(OPT) $(CPPOPT) $(CPPWARN) -Wa,-alms=$(LSTDIR)/$(notdir $(<:.cpp=.lst)) $(DEFS)
+LDFLAGS = $(MCFLAGS) $(OPT) -nostartfiles $(LLIBDIR) -Wl,-Map=$(BUILDDIR)/$(PROJECT).map,--cref,--no-warn-mismatch,--library-path=$(STARTUPLD),--script=$(LDSCRIPT)$(LDOPT)
+
+# Generate dependency information
+ASFLAGS += -MD -MP -MF $(DEPDIR)/$(@F).d
+ASXFLAGS += -MD -MP -MF $(DEPDIR)/$(@F).d
+CFLAGS += -MD -MP -MF $(DEPDIR)/$(@F).d
+CPPFLAGS += -MD -MP -MF $(DEPDIR)/$(@F).d
+
+# Paths where to search for sources
+VPATH = $(SRCPATHS)
+
+#
+# Makefile rules
+#
+
+all: PRE_MAKE_ALL_RULE_HOOK $(OBJS) $(OUTFILES) POST_MAKE_ALL_RULE_HOOK
+
+PRE_MAKE_ALL_RULE_HOOK:
+
+POST_MAKE_ALL_RULE_HOOK:
+
+$(OBJS): | PRE_MAKE_ALL_RULE_HOOK $(BUILDDIR) $(OBJDIR) $(LSTDIR) $(DEPDIR)
+
+$(BUILDDIR):
+ifneq ($(USE_VERBOSE_COMPILE),yes)
+ @echo Compiler Options
+ @echo $(CC) -c $(CFLAGS) -I. $(IINCDIR) main.c -o main.o
+ @echo
+endif
+ @mkdir -p $(BUILDDIR)
+
+$(OBJDIR):
+ @mkdir -p $(OBJDIR)
+
+$(LSTDIR):
+ @mkdir -p $(LSTDIR)
+
+$(DEPDIR):
+ @mkdir -p $(DEPDIR)
+
+$(TCPPOBJS) : $(OBJDIR)/%.o : %.cpp $(MAKEFILE_LIST)
+ifeq ($(USE_VERBOSE_COMPILE),yes)
+ @echo
+ $(CPPC) -c $(CPPFLAGS) -I. $(IINCDIR) $< -o $@
+else
+ @echo Compiling $( $@
+ $(SZ) $<
+else
+ @echo Creating $@
+ @$(OD) $(ODFLAGS) $< > $@
+ @echo
+ @$(SZ) $<
+endif
+
+%.list: %.elf
+ifeq ($(USE_VERBOSE_COMPILE),yes)
+ $(OD) -S $< > $@
+else
+ @echo Creating $@
+ @$(OD) -S $< > $@
+ @echo
+ @echo Done
+endif
+
+lib: $(OBJS) $(BUILDDIR)/lib$(PROJECT).a
+
+$(BUILDDIR)/lib$(PROJECT).a: $(OBJS)
+ @$(AR) -r $@ $^
+ @echo
+ @echo Done
+
+clean: CLEAN_RULE_HOOK
+ @echo Cleaning
+ @echo - $(DEPDIR)
+ @-rm -fR $(DEPDIR)/* $(BUILDDIR)/* 2>/dev/null
+ @-if [ -d "$(DEPDIR)" ]; then rmdir -p --ignore-fail-on-non-empty $(subst ./,,$(DEPDIR)) 2>/dev/null; fi
+ @echo - $(BUILDDIR)
+ @-if [ -d "$(BUILDDIR)" ]; then rmdir -p --ignore-fail-on-non-empty $(subst ./,,$(BUILDDIR)) 2>/dev/null; fi
+ @echo
+ @echo Done
+
+CLEAN_RULE_HOOK:
+
+#
+# Include the dependency files, should be the last of the makefile
+#
+-include $(wildcard $(DEPDIR)/*)
+
+# *** EOF ***
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_aducm36x.mk b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_aducm36x.mk
new file mode 100644
index 0000000..7a9ad98
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_aducm36x.mk
@@ -0,0 +1,18 @@
+# List of the ChibiOS generic ADUCM36x startup and CMSIS files.
+STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c
+
+STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S
+
+STARTUPINC = $(CHIBIOS)/os/common/portability/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/devices/ADUCM36x \
+ $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
+ $(CHIBIOS)/os/common/ext/ADI/ADUCM36x
+
+STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
+
+# Shared variables
+ALLXASMSRC += $(STARTUPASM)
+ALLCSRC += $(STARTUPSRC)
+ALLINC += $(STARTUPINC)
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_aducm41x.mk b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_aducm41x.mk
new file mode 100644
index 0000000..c40b34b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_aducm41x.mk
@@ -0,0 +1,18 @@
+# List of the ChibiOS generic ADUCM41x startup and CMSIS files.
+STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c
+
+STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S
+
+STARTUPINC = $(CHIBIOS)/os/common/portability/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/devices/ADUCM41x \
+ $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
+ $(CHIBIOS)/os/common/ext/ADI/ADUCM41x
+
+STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
+
+# Shared variables
+ALLXASMSRC += $(STARTUPASM)
+ALLCSRC += $(STARTUPSRC)
+ALLINC += $(STARTUPINC)
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f0xx.mk b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f0xx.mk
new file mode 100644
index 0000000..3101560
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f0xx.mk
@@ -0,0 +1,18 @@
+# List of the ChibiOS generic STM32F0xx startup and CMSIS files.
+STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c
+
+STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.S \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S
+
+STARTUPINC = $(CHIBIOS)/os/common/portability/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32F0xx \
+ $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
+ $(CHIBIOS)/os/common/ext/ST/STM32F0xx
+
+STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
+
+# Shared variables
+ALLXASMSRC += $(STARTUPASM)
+ALLCSRC += $(STARTUPSRC)
+ALLINC += $(STARTUPINC)
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f1xx.mk b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f1xx.mk
new file mode 100644
index 0000000..0247e72
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f1xx.mk
@@ -0,0 +1,18 @@
+# List of the ChibiOS generic STM32F1xx startup and CMSIS files.
+STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c
+
+STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S
+
+STARTUPINC = $(CHIBIOS)/os/common/portability/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32F1xx \
+ $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
+ $(CHIBIOS)/os/common/ext/ST/STM32F1xx
+
+STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
+
+# Shared variables
+ALLXASMSRC += $(STARTUPASM)
+ALLCSRC += $(STARTUPSRC)
+ALLINC += $(STARTUPINC)
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f2xx.mk b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f2xx.mk
new file mode 100644
index 0000000..e216f1e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f2xx.mk
@@ -0,0 +1,18 @@
+# List of the ChibiOS generic STM32F2xx startup and CMSIS files.
+STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c
+
+STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S
+
+STARTUPINC = $(CHIBIOS)/os/common/portability/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32F2xx \
+ $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
+ $(CHIBIOS)/os/common/ext/ST/STM32F2xx
+
+STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
+
+# Shared variables
+ALLXASMSRC += $(STARTUPASM)
+ALLCSRC += $(STARTUPSRC)
+ALLINC += $(STARTUPINC)
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f3xx.mk b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f3xx.mk
new file mode 100644
index 0000000..7650405
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f3xx.mk
@@ -0,0 +1,18 @@
+# List of the ChibiOS generic STM32F3xx startup and CMSIS files.
+STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c
+
+STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S
+
+STARTUPINC = $(CHIBIOS)/os/common/portability/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32F3xx \
+ $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
+ $(CHIBIOS)/os/common/ext/ST/STM32F3xx
+
+STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
+
+# Shared variables
+ALLXASMSRC += $(STARTUPASM)
+ALLCSRC += $(STARTUPSRC)
+ALLINC += $(STARTUPINC)
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
new file mode 100644
index 0000000..e0c8d55
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
@@ -0,0 +1,18 @@
+# List of the ChibiOS generic STM32F4xx startup and CMSIS files.
+STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c
+
+STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S
+
+STARTUPINC = $(CHIBIOS)/os/common/portability/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32F4xx \
+ $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
+ $(CHIBIOS)/os/common/ext/ST/STM32F4xx
+
+STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
+
+# Shared variables
+ALLXASMSRC += $(STARTUPASM)
+ALLCSRC += $(STARTUPSRC)
+ALLINC += $(STARTUPINC)
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f7xx.mk b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f7xx.mk
new file mode 100644
index 0000000..1846f43
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f7xx.mk
@@ -0,0 +1,18 @@
+# List of the ChibiOS generic STM32F7xx startup and CMSIS files.
+STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c
+
+STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S
+
+STARTUPINC = $(CHIBIOS)/os/common/portability/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32F7xx \
+ $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
+ $(CHIBIOS)/os/common/ext/ST/STM32F7xx
+
+STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
+
+# Shared variables
+ALLXASMSRC += $(STARTUPASM)
+ALLCSRC += $(STARTUPSRC)
+ALLINC += $(STARTUPINC)
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32g0xx.mk b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32g0xx.mk
new file mode 100644
index 0000000..5f9eb71
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32g0xx.mk
@@ -0,0 +1,18 @@
+# List of the ChibiOS generic STM32G0xx startup and CMSIS files.
+STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c
+
+STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.S \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S
+
+STARTUPINC = $(CHIBIOS)/os/common/portability/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32G0xx \
+ $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
+ $(CHIBIOS)/os/common/ext/ST/STM32G0xx
+
+STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
+
+# Shared variables
+ALLXASMSRC += $(STARTUPASM)
+ALLCSRC += $(STARTUPSRC)
+ALLINC += $(STARTUPINC)
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32g4xx.mk b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32g4xx.mk
new file mode 100644
index 0000000..669ff62
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32g4xx.mk
@@ -0,0 +1,18 @@
+# List of the ChibiOS generic STM32G4xx startup and CMSIS files.
+STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c
+
+STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S
+
+STARTUPINC = $(CHIBIOS)/os/common/portability/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32G4xx \
+ $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
+ $(CHIBIOS)/os/common/ext/ST/STM32G4xx
+
+STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
+
+# Shared variables
+ALLXASMSRC += $(STARTUPASM)
+ALLCSRC += $(STARTUPSRC)
+ALLINC += $(STARTUPINC)
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32h7xx.mk b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32h7xx.mk
new file mode 100644
index 0000000..e467162
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32h7xx.mk
@@ -0,0 +1,18 @@
+# List of the ChibiOS generic STM32H7xx startup and CMSIS files.
+STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c
+
+STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S
+
+STARTUPINC = $(CHIBIOS)/os/common/portability/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32H7xx \
+ $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
+ $(CHIBIOS)/os/common/ext/ST/STM32H7xx
+
+STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
+
+# Shared variables
+ALLXASMSRC += $(STARTUPASM)
+ALLCSRC += $(STARTUPSRC)
+ALLINC += $(STARTUPINC)
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l0xx.mk b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l0xx.mk
new file mode 100644
index 0000000..0c6fc35
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l0xx.mk
@@ -0,0 +1,18 @@
+# List of the ChibiOS generic STM32L0xx startup and CMSIS files.
+STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c
+
+STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.S \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S
+
+STARTUPINC = $(CHIBIOS)/os/common/portability/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32L0xx \
+ $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
+ $(CHIBIOS)/os/common/ext/ST/STM32L0xx
+
+STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
+
+# Shared variables
+ALLXASMSRC += $(STARTUPASM)
+ALLCSRC += $(STARTUPSRC)
+ALLINC += $(STARTUPINC)
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l1xx.mk b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l1xx.mk
new file mode 100644
index 0000000..96510e4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l1xx.mk
@@ -0,0 +1,18 @@
+# List of the ChibiOS generic STM32L1xx startup and CMSIS files.
+STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c
+
+STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S
+
+STARTUPINC = $(CHIBIOS)/os/common/portability/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32L1xx \
+ $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
+ $(CHIBIOS)/os/common/ext/ST/STM32L1xx
+
+STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
+
+# Shared variables
+ALLXASMSRC += $(STARTUPASM)
+ALLCSRC += $(STARTUPSRC)
+ALLINC += $(STARTUPINC)
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l4xx.mk b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l4xx.mk
new file mode 100644
index 0000000..87f6587
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l4xx.mk
@@ -0,0 +1,18 @@
+# List of the ChibiOS generic STM32L4xx startup and CMSIS files.
+STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c
+
+STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S
+
+STARTUPINC = $(CHIBIOS)/os/common/portability/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \
+ $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32L4xx \
+ $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \
+ $(CHIBIOS)/os/common/ext/ST/STM32L4xx
+
+STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld
+
+# Shared variables
+ALLXASMSRC += $(STARTUPASM)
+ALLCSRC += $(STARTUPSRC)
+ALLINC += $(STARTUPINC)
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/vectors.S b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/vectors.S
new file mode 100644
index 0000000..ef1c7bc
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/GCC/vectors.S
@@ -0,0 +1,1031 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ARMCMx/GCC/vectors.S
+ * @brief Interrupt vectors for Cortex-Mx devices.
+ *
+ * @defgroup ARMCMx_GCC_VECTORS Cortex-Mx Interrupt Vectors
+ * @{
+ */
+
+#define _FROM_ASM_
+#include "cmparams.h"
+
+#if (CORTEX_NUM_VECTORS % 8) != 0
+#error "the constant CORTEX_NUM_VECTORS must be a multiple of 8"
+#endif
+
+#if (CORTEX_NUM_VECTORS < 8) || (CORTEX_NUM_VECTORS > 240)
+#error "the constant CORTEX_NUM_VECTORS must be between 8 and 240 inclusive"
+#endif
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Code section. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+
+ .syntax unified
+ .cpu cortex-m0
+ .thumb
+
+ .section .vectors, "ax"
+ .align 4
+ .globl _vectors
+_vectors:
+ .long __main_stack_end__
+ .long Reset_Handler
+ .long NMI_Handler
+ .long HardFault_Handler
+ .long MemManage_Handler
+ .long BusFault_Handler
+ .long UsageFault_Handler
+ .long Vector1C
+ .long Vector20
+ .long Vector24
+ .long Vector28
+ .long SVC_Handler
+ .long DebugMon_Handler
+ .long Vector34
+ .long PendSV_Handler
+ .long SysTick_Handler
+ .long Vector40, Vector44, Vector48, Vector4C
+#if CORTEX_NUM_VECTORS > 4
+ .long Vector50, Vector54, Vector58, Vector5C
+#endif
+#if CORTEX_NUM_VECTORS > 8
+ .long Vector60, Vector64, Vector68, Vector6C
+#endif
+#if CORTEX_NUM_VECTORS > 12
+ .long Vector70, Vector74, Vector78, Vector7C
+#endif
+#if CORTEX_NUM_VECTORS > 16
+ .long Vector80, Vector84, Vector88, Vector8C
+#endif
+#if CORTEX_NUM_VECTORS > 20
+ .long Vector90, Vector94, Vector98, Vector9C
+#endif
+#if CORTEX_NUM_VECTORS > 24
+ .long VectorA0, VectorA4, VectorA8, VectorAC
+#endif
+#if CORTEX_NUM_VECTORS > 28
+ .long VectorB0, VectorB4, VectorB8, VectorBC
+#endif
+#if CORTEX_NUM_VECTORS > 32
+ .long VectorC0, VectorC4, VectorC8, VectorCC
+#endif
+#if CORTEX_NUM_VECTORS > 36
+ .long VectorD0, VectorD4, VectorD8, VectorDC
+#endif
+#if CORTEX_NUM_VECTORS > 40
+ .long VectorE0, VectorE4, VectorE8, VectorEC
+#endif
+#if CORTEX_NUM_VECTORS > 44
+ .long VectorF0, VectorF4, VectorF8, VectorFC
+#endif
+#if CORTEX_NUM_VECTORS > 48
+ .long Vector100, Vector104, Vector108, Vector10C
+#endif
+#if CORTEX_NUM_VECTORS > 52
+ .long Vector110, Vector114, Vector118, Vector11C
+#endif
+#if CORTEX_NUM_VECTORS > 56
+ .long Vector120, Vector124, Vector128, Vector12C
+#endif
+#if CORTEX_NUM_VECTORS > 60
+ .long Vector130, Vector134, Vector138, Vector13C
+#endif
+#if CORTEX_NUM_VECTORS > 64
+ .long Vector140, Vector144, Vector148, Vector14C
+#endif
+#if CORTEX_NUM_VECTORS > 68
+ .long Vector150, Vector154, Vector158, Vector15C
+#endif
+#if CORTEX_NUM_VECTORS > 72
+ .long Vector160, Vector164, Vector168, Vector16C
+#endif
+#if CORTEX_NUM_VECTORS > 76
+ .long Vector170, Vector174, Vector178, Vector17C
+#endif
+#if CORTEX_NUM_VECTORS > 80
+ .long Vector180, Vector184, Vector188, Vector18C
+#endif
+#if CORTEX_NUM_VECTORS > 84
+ .long Vector190, Vector194, Vector198, Vector19C
+#endif
+#if CORTEX_NUM_VECTORS > 88
+ .long Vector1A0, Vector1A4, Vector1A8, Vector1AC
+#endif
+#if CORTEX_NUM_VECTORS > 92
+ .long Vector1B0, Vector1B4, Vector1B8, Vector1BC
+#endif
+#if CORTEX_NUM_VECTORS > 96
+ .long Vector1C0, Vector1C4, Vector1C8, Vector1CC
+#endif
+#if CORTEX_NUM_VECTORS > 100
+ .long Vector1D0, Vector1D4, Vector1D8, Vector1DC
+#endif
+#if CORTEX_NUM_VECTORS > 104
+ .long Vector1E0, Vector1E4, Vector1E8, Vector1EC
+#endif
+#if CORTEX_NUM_VECTORS > 108
+ .long Vector1F0, Vector1F4, Vector1F8, Vector1FC
+#endif
+#if CORTEX_NUM_VECTORS > 112
+ .long Vector200, Vector204, Vector208, Vector20C
+#endif
+#if CORTEX_NUM_VECTORS > 116
+ .long Vector210, Vector214, Vector218, Vector21C
+#endif
+#if CORTEX_NUM_VECTORS > 120
+ .long Vector220, Vector224, Vector228, Vector22C
+#endif
+#if CORTEX_NUM_VECTORS > 124
+ .long Vector230, Vector234, Vector238, Vector23C
+#endif
+#if CORTEX_NUM_VECTORS > 128
+ .long Vector240, Vector244, Vector248, Vector24C
+#endif
+#if CORTEX_NUM_VECTORS > 132
+ .long Vector250, Vector254, Vector258, Vector25C
+#endif
+#if CORTEX_NUM_VECTORS > 136
+ .long Vector260, Vector264, Vector268, Vector26C
+#endif
+#if CORTEX_NUM_VECTORS > 140
+ .long Vector270, Vector274, Vector278, Vector27C
+#endif
+#if CORTEX_NUM_VECTORS > 144
+ .long Vector280, Vector284, Vector288, Vector28C
+#endif
+#if CORTEX_NUM_VECTORS > 148
+ .long Vector290, Vector294, Vector298, Vector29C
+#endif
+#if CORTEX_NUM_VECTORS > 152
+ .long Vector2A0, Vector2A4, Vector2A8, Vector2AC
+#endif
+#if CORTEX_NUM_VECTORS > 156
+ .long Vector2B0, Vector2B4, Vector2B8, Vector2BC
+#endif
+#if CORTEX_NUM_VECTORS > 160
+ .long Vector2C0, Vector2C4, Vector2C8, Vector2CC
+#endif
+#if CORTEX_NUM_VECTORS > 164
+ .long Vector2D0, Vector2D4, Vector2D8, Vector2DC
+#endif
+#if CORTEX_NUM_VECTORS > 168
+ .long Vector2E0, Vector2E4, Vector2E8, Vector2EC
+#endif
+#if CORTEX_NUM_VECTORS > 172
+ .long Vector2F0, Vector2F4, Vector2F8, Vector2FC
+#endif
+#if CORTEX_NUM_VECTORS > 176
+ .long Vector300, Vector304, Vector308, Vector30C
+#endif
+#if CORTEX_NUM_VECTORS > 180
+ .long Vector310, Vector314, Vector318, Vector31C
+#endif
+#if CORTEX_NUM_VECTORS > 184
+ .long Vector320, Vector324, Vector328, Vector32C
+#endif
+#if CORTEX_NUM_VECTORS > 188
+ .long Vector330, Vector334, Vector338, Vector33C
+#endif
+#if CORTEX_NUM_VECTORS > 192
+ .long Vector340, Vector344, Vector348, Vector34C
+#endif
+#if CORTEX_NUM_VECTORS > 196
+ .long Vector350, Vector354, Vector358, Vector35C
+#endif
+#if CORTEX_NUM_VECTORS > 200
+ .long Vector360, Vector364, Vector368, Vector36C
+#endif
+#if CORTEX_NUM_VECTORS > 204
+ .long Vector370, Vector374, Vector378, Vector37C
+#endif
+#if CORTEX_NUM_VECTORS > 208
+ .long Vector380, Vector384, Vector388, Vector38C
+#endif
+#if CORTEX_NUM_VECTORS > 212
+ .long Vector390, Vector394, Vector398, Vector39C
+#endif
+#if CORTEX_NUM_VECTORS > 216
+ .long Vector3A0, Vector3A4, Vector3A8, Vector3AC
+#endif
+#if CORTEX_NUM_VECTORS > 220
+ .long Vector3B0, Vector3B4, Vector3B8, Vector3BC
+#endif
+#if CORTEX_NUM_VECTORS > 224
+ .long Vector3C0, Vector3C4, Vector3C8, Vector3CC
+#endif
+#if CORTEX_NUM_VECTORS > 228
+ .long Vector3D0, Vector3D4, Vector3D8, Vector3DC
+#endif
+#if CORTEX_NUM_VECTORS > 232
+ .long Vector3E0, Vector3E4, Vector3E8, Vector3EC
+#endif
+#if CORTEX_NUM_VECTORS > 236
+ .long Vector3F0, Vector3F4, Vector3F8, Vector3FC
+#endif
+
+ .text
+
+ .align 2
+ .thumb_func
+ .weak Reset_Handler
+Reset_Handler:
+ b _crt0_entry
+
+ .thumb_func
+ .weak NMI_Handler
+ .weak HardFault_Handler
+ .weak MemManage_Handler
+ .weak BusFault_Handler
+ .weak UsageFault_Handler
+ .weak Vector1C
+ .weak Vector20
+ .weak Vector24
+ .weak Vector28
+ .weak SVC_Handler
+ .weak DebugMon_Handler
+ .weak Vector34
+ .weak PendSV_Handler
+ .weak SysTick_Handler
+ .weak Vector40, Vector44, Vector48, Vector4C
+#if CORTEX_NUM_VECTORS > 4
+ .weak Vector50, Vector54, Vector58, Vector5C
+#endif
+#if CORTEX_NUM_VECTORS > 8
+ .weak Vector60, Vector64, Vector68, Vector6C
+#endif
+#if CORTEX_NUM_VECTORS > 12
+ .weak Vector70, Vector74, Vector78, Vector7C
+#endif
+#if CORTEX_NUM_VECTORS > 16
+ .weak Vector80, Vector84, Vector88, Vector8C
+#endif
+#if CORTEX_NUM_VECTORS > 20
+ .weak Vector90, Vector94, Vector98, Vector9C
+#endif
+#if CORTEX_NUM_VECTORS > 24
+ .weak VectorA0, VectorA4, VectorA8, VectorAC
+#endif
+#if CORTEX_NUM_VECTORS > 28
+ .weak VectorB0, VectorB4, VectorB8, VectorBC
+#endif
+#if CORTEX_NUM_VECTORS > 32
+ .weak VectorC0, VectorC4, VectorC8, VectorCC
+#endif
+#if CORTEX_NUM_VECTORS > 36
+ .weak VectorD0, VectorD4, VectorD8, VectorDC
+#endif
+#if CORTEX_NUM_VECTORS > 40
+ .weak VectorE0, VectorE4, VectorE8, VectorEC
+#endif
+#if CORTEX_NUM_VECTORS > 44
+ .weak VectorF0, VectorF4, VectorF8, VectorFC
+#endif
+#if CORTEX_NUM_VECTORS > 48
+ .weak Vector100, Vector104, Vector108, Vector10C
+#endif
+#if CORTEX_NUM_VECTORS > 52
+ .weak Vector110, Vector114, Vector118, Vector11C
+#endif
+#if CORTEX_NUM_VECTORS > 56
+ .weak Vector120, Vector124, Vector128, Vector12C
+#endif
+#if CORTEX_NUM_VECTORS > 60
+ .weak Vector130, Vector134, Vector138, Vector13C
+#endif
+#if CORTEX_NUM_VECTORS > 64
+ .weak Vector140, Vector144, Vector148, Vector14C
+#endif
+#if CORTEX_NUM_VECTORS > 68
+ .weak Vector150, Vector154, Vector158, Vector15C
+#endif
+#if CORTEX_NUM_VECTORS > 72
+ .weak Vector160, Vector164, Vector168, Vector16C
+#endif
+#if CORTEX_NUM_VECTORS > 76
+ .weak Vector170, Vector174, Vector178, Vector17C
+#endif
+#if CORTEX_NUM_VECTORS > 80
+ .weak Vector180, Vector184, Vector188, Vector18C
+#endif
+#if CORTEX_NUM_VECTORS > 84
+ .weak Vector190, Vector194, Vector198, Vector19C
+#endif
+#if CORTEX_NUM_VECTORS > 88
+ .weak Vector1A0, Vector1A4, Vector1A8, Vector1AC
+#endif
+#if CORTEX_NUM_VECTORS > 92
+ .weak Vector1B0, Vector1B4, Vector1B8, Vector1BC
+#endif
+#if CORTEX_NUM_VECTORS > 96
+ .weak Vector1C0, Vector1C4, Vector1C8, Vector1CC
+#endif
+#if CORTEX_NUM_VECTORS > 100
+ .weak Vector1D0, Vector1D4, Vector1D8, Vector1DC
+#endif
+#if CORTEX_NUM_VECTORS > 104
+ .weak Vector1E0, Vector1E4, Vector1E8, Vector1EC
+#endif
+#if CORTEX_NUM_VECTORS > 108
+ .weak Vector1F0, Vector1F4, Vector1F8, Vector1FC
+#endif
+#if CORTEX_NUM_VECTORS > 112
+ .weak Vector200, Vector204, Vector208, Vector20C
+#endif
+#if CORTEX_NUM_VECTORS > 116
+ .weak Vector210, Vector214, Vector218, Vector21C
+#endif
+#if CORTEX_NUM_VECTORS > 120
+ .weak Vector220, Vector224, Vector228, Vector22C
+#endif
+#if CORTEX_NUM_VECTORS > 124
+ .weak Vector230, Vector234, Vector238, Vector23C
+#endif
+#if CORTEX_NUM_VECTORS > 128
+ .weak Vector240, Vector244, Vector248, Vector24C
+#endif
+#if CORTEX_NUM_VECTORS > 132
+ .weak Vector250, Vector254, Vector258, Vector25C
+#endif
+#if CORTEX_NUM_VECTORS > 136
+ .weak Vector260, Vector264, Vector268, Vector26C
+#endif
+#if CORTEX_NUM_VECTORS > 140
+ .weak Vector270, Vector274, Vector278, Vector27C
+#endif
+#if CORTEX_NUM_VECTORS > 144
+ .weak Vector280, Vector284, Vector288, Vector28C
+#endif
+#if CORTEX_NUM_VECTORS > 148
+ .weak Vector290, Vector294, Vector298, Vector29C
+#endif
+#if CORTEX_NUM_VECTORS > 152
+ .weak Vector2A0, Vector2A4, Vector2A8, Vector2AC
+#endif
+#if CORTEX_NUM_VECTORS > 156
+ .weak Vector2B0, Vector2B4, Vector2B8, Vector2BC
+#endif
+#if CORTEX_NUM_VECTORS > 160
+ .weak Vector2C0, Vector2C4, Vector2C8, Vector2CC
+#endif
+#if CORTEX_NUM_VECTORS > 164
+ .weak Vector2D0, Vector2D4, Vector2D8, Vector2DC
+#endif
+#if CORTEX_NUM_VECTORS > 168
+ .weak Vector2E0, Vector2E4, Vector2E8, Vector2EC
+#endif
+#if CORTEX_NUM_VECTORS > 172
+ .weak Vector2F0, Vector2F4, Vector2F8, Vector2FC
+#endif
+#if CORTEX_NUM_VECTORS > 176
+ .weak Vector300, Vector304, Vector308, Vector30C
+#endif
+#if CORTEX_NUM_VECTORS > 180
+ .weak Vector310, Vector314, Vector318, Vector31C
+#endif
+#if CORTEX_NUM_VECTORS > 184
+ .weak Vector320, Vector324, Vector328, Vector32C
+#endif
+#if CORTEX_NUM_VECTORS > 188
+ .weak Vector330, Vector334, Vector338, Vector33C
+#endif
+#if CORTEX_NUM_VECTORS > 192
+ .weak Vector340, Vector344, Vector348, Vector34C
+#endif
+#if CORTEX_NUM_VECTORS > 196
+ .weak Vector350, Vector354, Vector358, Vector35C
+#endif
+#if CORTEX_NUM_VECTORS > 200
+ .weak Vector360, Vector364, Vector368, Vector36C
+#endif
+#if CORTEX_NUM_VECTORS > 204
+ .weak Vector370, Vector374, Vector378, Vector37C
+#endif
+#if CORTEX_NUM_VECTORS > 208
+ .weak Vector380, Vector384, Vector388, Vector38C
+#endif
+#if CORTEX_NUM_VECTORS > 212
+ .weak Vector390, Vector394, Vector398, Vector39C
+#endif
+#if CORTEX_NUM_VECTORS > 216
+ .weak Vector3A0, Vector3A4, Vector3A8, Vector3AC
+#endif
+#if CORTEX_NUM_VECTORS > 220
+ .weak Vector3B0, Vector3B4, Vector3B8, Vector3BC
+#endif
+#if CORTEX_NUM_VECTORS > 224
+ .weak Vector3C0, Vector3C4, Vector3C8, Vector3CC
+#endif
+#if CORTEX_NUM_VECTORS > 228
+ .weak Vector3D0, Vector3D4, Vector3D8, Vector3DC
+#endif
+#if CORTEX_NUM_VECTORS > 232
+ .weak Vector3E0, Vector3E4, Vector3E8, Vector3EC
+#endif
+#if CORTEX_NUM_VECTORS > 236
+ .weak Vector3F0, Vector3F4, Vector3F8, Vector3FC
+#endif
+
+ .thumb_func
+NMI_Handler:
+ .thumb_func
+HardFault_Handler:
+ .thumb_func
+MemManage_Handler:
+ .thumb_func
+BusFault_Handler:
+ .thumb_func
+UsageFault_Handler:
+ .thumb_func
+Vector1C:
+ .thumb_func
+Vector20:
+ .thumb_func
+Vector24:
+ .thumb_func
+Vector28:
+ .thumb_func
+SVC_Handler:
+ .thumb_func
+DebugMon_Handler:
+ .thumb_func
+Vector34:
+ .thumb_func
+PendSV_Handler:
+ .thumb_func
+SysTick_Handler:
+ .thumb_func
+Vector40:
+ .thumb_func
+Vector44:
+ .thumb_func
+Vector48:
+ .thumb_func
+Vector4C:
+ .thumb_func
+Vector50:
+ .thumb_func
+Vector54:
+ .thumb_func
+Vector58:
+ .thumb_func
+Vector5C:
+#if CORTEX_NUM_VECTORS > 8
+ .thumb_func
+Vector60:
+ .thumb_func
+Vector64:
+ .thumb_func
+Vector68:
+ .thumb_func
+Vector6C:
+ .thumb_func
+Vector70:
+ .thumb_func
+Vector74:
+ .thumb_func
+Vector78:
+ .thumb_func
+Vector7C:
+#endif
+#if CORTEX_NUM_VECTORS > 16
+ .thumb_func
+Vector80:
+ .thumb_func
+Vector84:
+ .thumb_func
+Vector88:
+ .thumb_func
+Vector8C:
+ .thumb_func
+Vector90:
+ .thumb_func
+Vector94:
+ .thumb_func
+Vector98:
+ .thumb_func
+Vector9C:
+#endif
+#if CORTEX_NUM_VECTORS > 24
+ .thumb_func
+VectorA0:
+ .thumb_func
+VectorA4:
+ .thumb_func
+VectorA8:
+ .thumb_func
+VectorAC:
+ .thumb_func
+VectorB0:
+ .thumb_func
+VectorB4:
+ .thumb_func
+VectorB8:
+ .thumb_func
+VectorBC:
+#endif
+#if CORTEX_NUM_VECTORS > 32
+ .thumb_func
+VectorC0:
+ .thumb_func
+VectorC4:
+ .thumb_func
+VectorC8:
+ .thumb_func
+VectorCC:
+ .thumb_func
+VectorD0:
+ .thumb_func
+VectorD4:
+ .thumb_func
+VectorD8:
+ .thumb_func
+VectorDC:
+#endif
+#if CORTEX_NUM_VECTORS > 40
+ .thumb_func
+VectorE0:
+ .thumb_func
+VectorE4:
+ .thumb_func
+VectorE8:
+ .thumb_func
+VectorEC:
+ .thumb_func
+VectorF0:
+ .thumb_func
+VectorF4:
+ .thumb_func
+VectorF8:
+ .thumb_func
+VectorFC:
+#endif
+#if CORTEX_NUM_VECTORS > 48
+ .thumb_func
+Vector100:
+ .thumb_func
+Vector104:
+ .thumb_func
+Vector108:
+ .thumb_func
+Vector10C:
+ .thumb_func
+Vector110:
+ .thumb_func
+Vector114:
+ .thumb_func
+Vector118:
+ .thumb_func
+Vector11C:
+#endif
+#if CORTEX_NUM_VECTORS > 56
+ .thumb_func
+Vector120:
+ .thumb_func
+Vector124:
+ .thumb_func
+Vector128:
+ .thumb_func
+Vector12C:
+ .thumb_func
+Vector130:
+ .thumb_func
+Vector134:
+ .thumb_func
+Vector138:
+ .thumb_func
+Vector13C:
+#endif
+#if CORTEX_NUM_VECTORS > 64
+ .thumb_func
+Vector140:
+ .thumb_func
+Vector144:
+ .thumb_func
+Vector148:
+ .thumb_func
+Vector14C:
+ .thumb_func
+Vector150:
+ .thumb_func
+Vector154:
+ .thumb_func
+Vector158:
+ .thumb_func
+Vector15C:
+#endif
+#if CORTEX_NUM_VECTORS > 72
+ .thumb_func
+Vector160:
+ .thumb_func
+Vector164:
+ .thumb_func
+Vector168:
+ .thumb_func
+Vector16C:
+ .thumb_func
+Vector170:
+ .thumb_func
+Vector174:
+ .thumb_func
+Vector178:
+ .thumb_func
+Vector17C:
+#endif
+#if CORTEX_NUM_VECTORS > 80
+ .thumb_func
+Vector180:
+ .thumb_func
+Vector184:
+ .thumb_func
+Vector188:
+ .thumb_func
+Vector18C:
+ .thumb_func
+Vector190:
+ .thumb_func
+Vector194:
+ .thumb_func
+Vector198:
+ .thumb_func
+Vector19C:
+#endif
+#if CORTEX_NUM_VECTORS > 88
+ .thumb_func
+Vector1A0:
+ .thumb_func
+Vector1A4:
+ .thumb_func
+Vector1A8:
+ .thumb_func
+Vector1AC:
+ .thumb_func
+Vector1B0:
+ .thumb_func
+Vector1B4:
+ .thumb_func
+Vector1B8:
+ .thumb_func
+Vector1BC:
+#endif
+#if CORTEX_NUM_VECTORS > 96
+ .thumb_func
+Vector1C0:
+ .thumb_func
+Vector1C4:
+ .thumb_func
+Vector1C8:
+ .thumb_func
+Vector1CC:
+ .thumb_func
+Vector1D0:
+ .thumb_func
+Vector1D4:
+ .thumb_func
+Vector1D8:
+ .thumb_func
+Vector1DC:
+#endif
+#if CORTEX_NUM_VECTORS > 104
+ .thumb_func
+Vector1E0:
+ .thumb_func
+Vector1E4:
+ .thumb_func
+Vector1E8:
+ .thumb_func
+Vector1EC:
+ .thumb_func
+Vector1F0:
+ .thumb_func
+Vector1F4:
+ .thumb_func
+Vector1F8:
+ .thumb_func
+Vector1FC:
+#endif
+#if CORTEX_NUM_VECTORS > 112
+ .thumb_func
+Vector200:
+ .thumb_func
+Vector204:
+ .thumb_func
+Vector208:
+ .thumb_func
+Vector20C:
+ .thumb_func
+Vector210:
+ .thumb_func
+Vector214:
+ .thumb_func
+Vector218:
+ .thumb_func
+Vector21C:
+#endif
+#if CORTEX_NUM_VECTORS > 120
+ .thumb_func
+Vector220:
+ .thumb_func
+Vector224:
+ .thumb_func
+Vector228:
+ .thumb_func
+Vector22C:
+ .thumb_func
+Vector230:
+ .thumb_func
+Vector234:
+ .thumb_func
+Vector238:
+ .thumb_func
+Vector23C:
+#endif
+#if CORTEX_NUM_VECTORS > 128
+ .thumb_func
+Vector240:
+ .thumb_func
+Vector244:
+ .thumb_func
+Vector248:
+ .thumb_func
+Vector24C:
+ .thumb_func
+Vector250:
+ .thumb_func
+Vector254:
+ .thumb_func
+Vector258:
+ .thumb_func
+Vector25C:
+#endif
+#if CORTEX_NUM_VECTORS > 136
+ .thumb_func
+Vector260:
+ .thumb_func
+Vector264:
+ .thumb_func
+Vector268:
+ .thumb_func
+Vector26C:
+ .thumb_func
+Vector270:
+ .thumb_func
+Vector274:
+ .thumb_func
+Vector278:
+ .thumb_func
+Vector27C:
+#endif
+#if CORTEX_NUM_VECTORS > 144
+ .thumb_func
+Vector280:
+ .thumb_func
+Vector284:
+ .thumb_func
+Vector288:
+ .thumb_func
+Vector28C:
+ .thumb_func
+Vector290:
+ .thumb_func
+Vector294:
+ .thumb_func
+Vector298:
+ .thumb_func
+Vector29C:
+#endif
+#if CORTEX_NUM_VECTORS > 152
+ .thumb_func
+Vector2A0:
+ .thumb_func
+Vector2A4:
+ .thumb_func
+Vector2A8:
+ .thumb_func
+Vector2AC:
+ .thumb_func
+Vector2B0:
+ .thumb_func
+Vector2B4:
+ .thumb_func
+Vector2B8:
+ .thumb_func
+Vector2BC:
+#endif
+#if CORTEX_NUM_VECTORS > 160
+ .thumb_func
+Vector2C0:
+ .thumb_func
+Vector2C4:
+ .thumb_func
+Vector2C8:
+ .thumb_func
+Vector2CC:
+ .thumb_func
+Vector2D0:
+ .thumb_func
+Vector2D4:
+ .thumb_func
+Vector2D8:
+ .thumb_func
+Vector2DC:
+#endif
+#if CORTEX_NUM_VECTORS > 168
+ .thumb_func
+Vector2E0:
+ .thumb_func
+Vector2E4:
+ .thumb_func
+Vector2E8:
+ .thumb_func
+Vector2EC:
+ .thumb_func
+Vector2F0:
+ .thumb_func
+Vector2F4:
+ .thumb_func
+Vector2F8:
+ .thumb_func
+Vector2FC:
+#endif
+#if CORTEX_NUM_VECTORS > 176
+ .thumb_func
+Vector300:
+ .thumb_func
+Vector304:
+ .thumb_func
+Vector308:
+ .thumb_func
+Vector30C:
+ .thumb_func
+Vector310:
+ .thumb_func
+Vector314:
+ .thumb_func
+Vector318:
+ .thumb_func
+Vector31C:
+#endif
+#if CORTEX_NUM_VECTORS > 184
+ .thumb_func
+Vector320:
+ .thumb_func
+Vector324:
+ .thumb_func
+Vector328:
+ .thumb_func
+Vector32C:
+ .thumb_func
+Vector330:
+ .thumb_func
+Vector334:
+ .thumb_func
+Vector338:
+ .thumb_func
+Vector33C:
+#endif
+#if CORTEX_NUM_VECTORS > 192
+ .thumb_func
+Vector340:
+ .thumb_func
+Vector344:
+ .thumb_func
+Vector348:
+ .thumb_func
+Vector34C:
+ .thumb_func
+Vector350:
+ .thumb_func
+Vector354:
+ .thumb_func
+Vector358:
+ .thumb_func
+Vector35C:
+#endif
+#if CORTEX_NUM_VECTORS > 200
+ .thumb_func
+Vector360:
+ .thumb_func
+Vector364:
+ .thumb_func
+Vector368:
+ .thumb_func
+Vector36C:
+ .thumb_func
+Vector370:
+ .thumb_func
+Vector374:
+ .thumb_func
+Vector378:
+ .thumb_func
+Vector37C:
+#endif
+#if CORTEX_NUM_VECTORS > 208
+ .thumb_func
+Vector380:
+ .thumb_func
+Vector384:
+ .thumb_func
+Vector388:
+ .thumb_func
+Vector38C:
+ .thumb_func
+Vector390:
+ .thumb_func
+Vector394:
+ .thumb_func
+Vector398:
+ .thumb_func
+Vector39C:
+#endif
+#if CORTEX_NUM_VECTORS > 216
+ .thumb_func
+Vector3A0:
+ .thumb_func
+Vector3A4:
+ .thumb_func
+Vector3A8:
+ .thumb_func
+Vector3AC:
+ .thumb_func
+Vector3B0:
+ .thumb_func
+Vector3B4:
+ .thumb_func
+Vector3B8:
+ .thumb_func
+Vector3BC:
+#endif
+#if CORTEX_NUM_VECTORS > 224
+ .thumb_func
+Vector3C0:
+ .thumb_func
+Vector3C4:
+ .thumb_func
+Vector3C8:
+ .thumb_func
+Vector3CC:
+ .thumb_func
+Vector3D0:
+ .thumb_func
+Vector3D4:
+ .thumb_func
+Vector3D8:
+ .thumb_func
+Vector3DC:
+#endif
+#if CORTEX_NUM_VECTORS > 232
+ .thumb_func
+Vector3E0:
+ .thumb_func
+Vector3E4:
+ .thumb_func
+Vector3E8:
+ .thumb_func
+Vector3EC:
+ .thumb_func
+Vector3F0:
+ .thumb_func
+Vector3F4:
+ .thumb_func
+Vector3F8:
+ .thumb_func
+Vector3FC:
+#endif
+ bl _unhandled_exception
+
+ .thumb_func
+ .weak _unhandled_exception
+_unhandled_exception:
+.stay:
+ b .stay
+
+#endif /* !defined(__DOXYGEN__) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/IAR/cstartup.s b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/IAR/cstartup.s
new file mode 100644
index 0000000..bf7aeca
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/IAR/cstartup.s
@@ -0,0 +1,169 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ARMCMx/compilers/IAR/cstartup.s
+ * @brief Generic IAR Cortex-Mx startup file.
+ *
+ * @addtogroup ARMCMx_IAR_STARTUP
+ * @{
+ */
+
+#if !defined(__DOXYGEN__)
+
+#define SCB_VTOR 0xE000ED08
+
+ /**
+ * @brief VTOR special register initialization.
+ * @details VTOR is initialized to point to the vectors table.
+ * @note IAR assembler #if directive conditions do not work like C/C++ conditions.
+ * @details Set to 0 to disable the function, 1 to enable
+ */
+#ifndef CRT0_VTOR_INIT
+#define CRT0_VTOR_INIT 1
+#endif
+/**
+ * @brief Stack segments initialization value.
+ */
+#ifndef CRT0_STACKS_FILL_PATTERN
+#define CRT0_STACKS_FILL_PATTERN 0x55555555
+#endif
+
+/**
+ * @brief Stack segments initialization switch.
+ * @details Set to 0 to disable the function, 1 to enable
+ */
+#ifndef CRT0_INIT_STACKS
+#define CRT0_INIT_STACKS 1
+#endif
+
+/**
+ * @brief Heap segment initialization value.
+ */
+#ifndef CRT0_HEAP_FILL_PATTERN
+#define CRT0_HEAP_FILL_PATTERN 0xCCCCCCCC
+#endif
+
+/**
+ * @brief Heap segment initialization switch.
+ * @details Set to 0 to disable the function, 1 to enable
+ */
+#ifndef CRT0_INIT_HEAP
+#define CRT0_INIT_HEAP 1
+#endif
+
+
+ MODULE ?cstartup
+
+CONTROL_MODE_PRIVILEGED SET 0
+CONTROL_MODE_UNPRIVILEGED SET 1
+CONTROL_USE_MSP SET 0
+CONTROL_USE_PSP SET 2
+
+ AAPCS INTERWORK, VFP_COMPATIBLE, ROPI
+ PRESERVE8
+
+ SECTION HEAP:DATA:NOROOT(3)
+ PUBLIC __heap_base__
+__heap_base__: /* Note: heap section defines sysheap base */
+
+ SECTION SYSHEAP:DATA:NOROOT(3)
+ PUBLIC __heap_end__
+__heap_end__: /* Note: sysheap section defines sysheap end */
+
+ PUBLIC __iar_program_start
+ EXTWEAK __iar_init_core
+ EXTWEAK __iar_init_vfp
+ EXTERN __cmain
+ EXTERN __vector_table
+ EXTERN __main_stack_base__
+ EXTERN __main_stack_end__
+ EXTERN __process_stack_base__
+ EXTERN __process_stack_end__
+
+ SECTION IRQSTACK:DATA:NOROOT(3)
+ SECTION CSTACK:DATA:NOROOT(3)
+ SECTION .text:CODE:REORDER(2)
+ THUMB
+
+__iar_program_start:
+ cpsid i
+ ldr r0, =SFE(IRQSTACK)
+ msr MSP, r0
+ ldr r0, =SFE(CSTACK)
+ msr PSP, r0
+ movs r0, #CONTROL_MODE_PRIVILEGED | CONTROL_USE_PSP
+ msr CONTROL, r0
+ isb
+
+#if (CRT0_VTOR_INIT)
+ ldr r0, =__vector_table
+ movw r1, #SCB_VTOR & 0xFFFF
+ movt r1, #SCB_VTOR >> 16
+ str r0, [r1]
+#endif
+
+#if (CRT0_INIT_STACKS)
+ ldr r0, =CRT0_STACKS_FILL_PATTERN
+ /* Main Stack initialization. Note, it assumes that the stack size
+ is a multiple of 4 so the linker file must ensure this.*/
+ ldr r1, =__main_stack_base__
+ ldr r2, =__main_stack_end__
+msloop:
+ cmp r1, r2
+ itt lo
+ strlo r0, [r1], #4
+ blo msloop
+
+ /* Process Stack initialization. Note, it assumes that the stack size
+ is a multiple of 4 so the linker file must ensure this.*/
+ ldr r1, =__process_stack_base__
+ ldr r2, =__process_stack_end__
+psloop:
+ cmp r1, r2
+ itt lo
+ strlo r0, [r1], #4
+ blo psloop
+#endif
+
+#if (CRT0_INIT_HEAP)
+ ldr r0, =CRT0_HEAP_FILL_PATTERN
+ /* Sys Heap initialization. Note, it assumes that the heap size
+ is a multiple of 4 so the linker file must ensure this.*/
+ ldr r1, =__heap_base__
+ ldr r2, =__heap_end__
+hloop:
+ cmp r1, r2
+ itt lo
+ strlo r0, [r1], #4
+ blo hloop
+#endif
+
+ bl __early_init
+ bl __iar_init_core
+ bl __iar_init_vfp
+ b __cmain
+
+ SECTION .text:CODE:NOROOT:REORDER(2)
+ PUBWEAK __early_init
+__early_init:
+ bx lr
+
+ END
+
+#endif /* !defined(__DOXYGEN__) */
+
+/**< @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/IAR/vectors.s b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/IAR/vectors.s
new file mode 100644
index 0000000..ec0360e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/IAR/vectors.s
@@ -0,0 +1,1006 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ARMCMx/compilers/IAR/vectors.c
+ * @brief Interrupt vectors for Cortex-Mx devices.
+ *
+ * @defgroup ARMCMx_IAR_VECTORS Cortex-Mx Interrupt Vectors
+ * @{
+ */
+
+#define _FROM_ASM_
+#include "cmparams.h"
+
+#if !defined(__DOXYGEN__)
+
+#if (CORTEX_NUM_VECTORS & 7) != 0
+#error "the constant CORTEX_NUM_VECTORS must be a multiple of 8"
+#endif
+
+#if (CORTEX_NUM_VECTORS < 8) || (CORTEX_NUM_VECTORS > 240)
+#error "the constant CORTEX_NUM_VECTORS must be between 8 and 240 inclusive"
+#endif
+
+ MODULE ?vectors
+
+ AAPCS INTERWORK, VFP_COMPATIBLE, RWPI_COMPATIBLE
+ PRESERVE8
+
+ SECTION IRQSTACK:DATA:NOROOT(3)
+ SECTION .intvec:CODE:NOROOT(3)
+
+ EXTERN __iar_program_start
+ PUBLIC __vector_table
+
+ DATA
+
+__vector_table:
+ DCD SFE(IRQSTACK)
+ DCD __iar_program_start
+ DCD NMI_Handler
+ DCD HardFault_Handler
+ DCD MemManage_Handler
+ DCD BusFault_Handler
+ DCD UsageFault_Handler
+ DCD Vector1C
+ DCD Vector20
+ DCD Vector24
+ DCD Vector28
+ DCD SVC_Handler
+ DCD DebugMon_Handler
+ DCD Vector34
+ DCD PendSV_Handler
+ DCD SysTick_Handler
+ DCD Vector40
+ DCD Vector44
+ DCD Vector48
+ DCD Vector4C
+ DCD Vector50
+ DCD Vector54
+ DCD Vector58
+ DCD Vector5C
+#if CORTEX_NUM_VECTORS > 8
+ DCD Vector60
+ DCD Vector64
+ DCD Vector68
+ DCD Vector6C
+ DCD Vector70
+ DCD Vector74
+ DCD Vector78
+ DCD Vector7C
+#endif
+#if CORTEX_NUM_VECTORS > 16
+ DCD Vector80
+ DCD Vector84
+ DCD Vector88
+ DCD Vector8C
+ DCD Vector90
+ DCD Vector94
+ DCD Vector98
+ DCD Vector9C
+#endif
+#if CORTEX_NUM_VECTORS > 24
+ DCD VectorA0
+ DCD VectorA4
+ DCD VectorA8
+ DCD VectorAC
+ DCD VectorB0
+ DCD VectorB4
+ DCD VectorB8
+ DCD VectorBC
+#endif
+#if CORTEX_NUM_VECTORS > 32
+ DCD VectorC0
+ DCD VectorC4
+ DCD VectorC8
+ DCD VectorCC
+ DCD VectorD0
+ DCD VectorD4
+ DCD VectorD8
+ DCD VectorDC
+#endif
+#if CORTEX_NUM_VECTORS > 40
+ DCD VectorE0
+ DCD VectorE4
+ DCD VectorE8
+ DCD VectorEC
+ DCD VectorF0
+ DCD VectorF4
+ DCD VectorF8
+ DCD VectorFC
+#endif
+#if CORTEX_NUM_VECTORS > 48
+ DCD Vector100
+ DCD Vector104
+ DCD Vector108
+ DCD Vector10C
+ DCD Vector110
+ DCD Vector114
+ DCD Vector118
+ DCD Vector11C
+#endif
+#if CORTEX_NUM_VECTORS > 56
+ DCD Vector120
+ DCD Vector124
+ DCD Vector128
+ DCD Vector12C
+ DCD Vector130
+ DCD Vector134
+ DCD Vector138
+ DCD Vector13C
+#endif
+#if CORTEX_NUM_VECTORS > 64
+ DCD Vector140
+ DCD Vector144
+ DCD Vector148
+ DCD Vector14C
+ DCD Vector150
+ DCD Vector154
+ DCD Vector158
+ DCD Vector15C
+#endif
+#if CORTEX_NUM_VECTORS > 72
+ DCD Vector160
+ DCD Vector164
+ DCD Vector168
+ DCD Vector16C
+ DCD Vector170
+ DCD Vector174
+ DCD Vector178
+ DCD Vector17C
+#endif
+#if CORTEX_NUM_VECTORS > 80
+ DCD Vector180
+ DCD Vector184
+ DCD Vector188
+ DCD Vector18C
+ DCD Vector190
+ DCD Vector194
+ DCD Vector198
+ DCD Vector19C
+#endif
+#if CORTEX_NUM_VECTORS > 88
+ DCD Vector1A0
+ DCD Vector1A4
+ DCD Vector1A8
+ DCD Vector1AC
+ DCD Vector1B0
+ DCD Vector1B4
+ DCD Vector1B8
+ DCD Vector1BC
+#endif
+#if CORTEX_NUM_VECTORS > 96
+ DCD Vector1C0
+ DCD Vector1C4
+ DCD Vector1C8
+ DCD Vector1CC
+ DCD Vector1D0
+ DCD Vector1D4
+ DCD Vector1D8
+ DCD Vector1DC
+#endif
+#if CORTEX_NUM_VECTORS > 104
+ DCD Vector1E0
+ DCD Vector1E4
+ DCD Vector1E8
+ DCD Vector1EC
+ DCD Vector1F0
+ DCD Vector1F4
+ DCD Vector1F8
+ DCD Vector1FC
+#endif
+#if CORTEX_NUM_VECTORS > 112
+ DCD Vector200
+ DCD Vector204
+ DCD Vector208
+ DCD Vector20C
+ DCD Vector210
+ DCD Vector214
+ DCD Vector218
+ DCD Vector21C
+#endif
+#if CORTEX_NUM_VECTORS > 120
+ DCD Vector220
+ DCD Vector224
+ DCD Vector228
+ DCD Vector22C
+ DCD Vector230
+ DCD Vector234
+ DCD Vector238
+ DCD Vector23C
+#endif
+#if CORTEX_NUM_VECTORS > 128
+ DCD Vector240
+ DCD Vector244
+ DCD Vector248
+ DCD Vector24C
+ DCD Vector250
+ DCD Vector254
+ DCD Vector258
+ DCD Vector25C
+#endif
+#if CORTEX_NUM_VECTORS > 136
+ DCD Vector260
+ DCD Vector264
+ DCD Vector268
+ DCD Vector26C
+ DCD Vector270
+ DCD Vector274
+ DCD Vector278
+ DCD Vector27C
+#endif
+#if CORTEX_NUM_VECTORS > 144
+ DCD Vector280
+ DCD Vector284
+ DCD Vector288
+ DCD Vector28C
+ DCD Vector290
+ DCD Vector294
+ DCD Vector298
+ DCD Vector29C
+#endif
+#if CORTEX_NUM_VECTORS > 152
+ DCD Vector2A0
+ DCD Vector2A4
+ DCD Vector2A8
+ DCD Vector2AC
+ DCD Vector2B0
+ DCD Vector2B4
+ DCD Vector2B8
+ DCD Vector2BC
+#endif
+#if CORTEX_NUM_VECTORS > 160
+ DCD Vector2C0
+ DCD Vector2C4
+ DCD Vector2C8
+ DCD Vector2CC
+ DCD Vector2D0
+ DCD Vector2D4
+ DCD Vector2D8
+ DCD Vector2DC
+#endif
+#if CORTEX_NUM_VECTORS > 168
+ DCD Vector2E0
+ DCD Vector2E4
+ DCD Vector2E8
+ DCD Vector2EC
+ DCD Vector2F0
+ DCD Vector2F4
+ DCD Vector2F8
+ DCD Vector2FC
+#endif
+#if CORTEX_NUM_VECTORS > 176
+ DCD Vector300
+ DCD Vector304
+ DCD Vector308
+ DCD Vector30C
+ DCD Vector310
+ DCD Vector314
+ DCD Vector318
+ DCD Vector31C
+#endif
+#if CORTEX_NUM_VECTORS > 184
+ DCD Vector320
+ DCD Vector324
+ DCD Vector328
+ DCD Vector32C
+ DCD Vector330
+ DCD Vector334
+ DCD Vector338
+ DCD Vector33C
+#endif
+#if CORTEX_NUM_VECTORS > 192
+ DCD Vector340
+ DCD Vector344
+ DCD Vector348
+ DCD Vector34C
+ DCD Vector350
+ DCD Vector354
+ DCD Vector358
+ DCD Vector35C
+#endif
+#if CORTEX_NUM_VECTORS > 200
+ DCD Vector360
+ DCD Vector364
+ DCD Vector368
+ DCD Vector36C
+ DCD Vector370
+ DCD Vector374
+ DCD Vector378
+ DCD Vector37C
+#endif
+#if CORTEX_NUM_VECTORS > 208
+ DCD Vector380
+ DCD Vector384
+ DCD Vector388
+ DCD Vector38C
+ DCD Vector390
+ DCD Vector394
+ DCD Vector398
+ DCD Vector39C
+#endif
+#if CORTEX_NUM_VECTORS > 216
+ DCD Vector3A0
+ DCD Vector3A4
+ DCD Vector3A8
+ DCD Vector3AC
+ DCD Vector3B0
+ DCD Vector3B4
+ DCD Vector3B8
+ DCD Vector3BC
+#endif
+#if CORTEX_NUM_VECTORS > 224
+ DCD Vector3C0
+ DCD Vector3C4
+ DCD Vector3C8
+ DCD Vector3CC
+ DCD Vector3D0
+ DCD Vector3D4
+ DCD Vector3D8
+ DCD Vector3DC
+#endif
+#if CORTEX_NUM_VECTORS > 232
+ DCD Vector3E0
+ DCD Vector3E4
+ DCD Vector3E8
+ DCD Vector3EC
+ DCD Vector3F0
+ DCD Vector3F4
+ DCD Vector3F8
+ DCD Vector3FC
+#endif
+
+/*
+ * Default interrupt handlers.
+ */
+ PUBWEAK NMI_Handler
+ PUBWEAK HardFault_Handler
+ PUBWEAK MemManage_Handler
+ PUBWEAK BusFault_Handler
+ PUBWEAK UsageFault_Handler
+ PUBWEAK Vector1C
+ PUBWEAK Vector20
+ PUBWEAK Vector24
+ PUBWEAK Vector28
+ PUBWEAK SVC_Handler
+ PUBWEAK DebugMon_Handler
+ PUBWEAK Vector34
+ PUBWEAK PendSV_Handler
+ PUBWEAK SysTick_Handler
+ PUBWEAK Vector40
+ PUBWEAK Vector44
+ PUBWEAK Vector48
+ PUBWEAK Vector4C
+ PUBWEAK Vector50
+ PUBWEAK Vector54
+ PUBWEAK Vector58
+ PUBWEAK Vector5C
+#if CORTEX_NUM_VECTORS > 8
+ PUBWEAK Vector60
+ PUBWEAK Vector64
+ PUBWEAK Vector68
+ PUBWEAK Vector6C
+ PUBWEAK Vector70
+ PUBWEAK Vector74
+ PUBWEAK Vector78
+ PUBWEAK Vector7C
+#endif
+#if CORTEX_NUM_VECTORS > 16
+ PUBWEAK Vector80
+ PUBWEAK Vector84
+ PUBWEAK Vector88
+ PUBWEAK Vector8C
+ PUBWEAK Vector90
+ PUBWEAK Vector94
+ PUBWEAK Vector98
+ PUBWEAK Vector9C
+#endif
+#if CORTEX_NUM_VECTORS > 24
+ PUBWEAK VectorA0
+ PUBWEAK VectorA4
+ PUBWEAK VectorA8
+ PUBWEAK VectorAC
+ PUBWEAK VectorB0
+ PUBWEAK VectorB4
+ PUBWEAK VectorB8
+ PUBWEAK VectorBC
+#endif
+#if CORTEX_NUM_VECTORS > 32
+ PUBWEAK VectorC0
+ PUBWEAK VectorC4
+ PUBWEAK VectorC8
+ PUBWEAK VectorCC
+ PUBWEAK VectorD0
+ PUBWEAK VectorD4
+ PUBWEAK VectorD8
+ PUBWEAK VectorDC
+#endif
+#if CORTEX_NUM_VECTORS > 40
+ PUBWEAK VectorE0
+ PUBWEAK VectorE4
+ PUBWEAK VectorE8
+ PUBWEAK VectorEC
+ PUBWEAK VectorF0
+ PUBWEAK VectorF4
+ PUBWEAK VectorF8
+ PUBWEAK VectorFC
+#endif
+#if CORTEX_NUM_VECTORS > 48
+ PUBWEAK Vector100
+ PUBWEAK Vector104
+ PUBWEAK Vector108
+ PUBWEAK Vector10C
+ PUBWEAK Vector110
+ PUBWEAK Vector114
+ PUBWEAK Vector118
+ PUBWEAK Vector11C
+#endif
+#if CORTEX_NUM_VECTORS > 56
+ PUBWEAK Vector120
+ PUBWEAK Vector124
+ PUBWEAK Vector128
+ PUBWEAK Vector12C
+ PUBWEAK Vector130
+ PUBWEAK Vector134
+ PUBWEAK Vector138
+ PUBWEAK Vector13C
+#endif
+#if CORTEX_NUM_VECTORS > 64
+ PUBWEAK Vector140
+ PUBWEAK Vector144
+ PUBWEAK Vector148
+ PUBWEAK Vector14C
+ PUBWEAK Vector150
+ PUBWEAK Vector154
+ PUBWEAK Vector158
+ PUBWEAK Vector15C
+#endif
+#if CORTEX_NUM_VECTORS > 72
+ PUBWEAK Vector160
+ PUBWEAK Vector164
+ PUBWEAK Vector168
+ PUBWEAK Vector16C
+ PUBWEAK Vector170
+ PUBWEAK Vector174
+ PUBWEAK Vector178
+ PUBWEAK Vector17C
+#endif
+#if CORTEX_NUM_VECTORS > 80
+ PUBWEAK Vector180
+ PUBWEAK Vector184
+ PUBWEAK Vector188
+ PUBWEAK Vector18C
+ PUBWEAK Vector190
+ PUBWEAK Vector194
+ PUBWEAK Vector198
+ PUBWEAK Vector19C
+#endif
+#if CORTEX_NUM_VECTORS > 88
+ PUBWEAK Vector1A0
+ PUBWEAK Vector1A4
+ PUBWEAK Vector1A8
+ PUBWEAK Vector1AC
+ PUBWEAK Vector1B0
+ PUBWEAK Vector1B4
+ PUBWEAK Vector1B8
+ PUBWEAK Vector1BC
+#endif
+#if CORTEX_NUM_VECTORS > 96
+ PUBWEAK Vector1C0
+ PUBWEAK Vector1C4
+ PUBWEAK Vector1C8
+ PUBWEAK Vector1CC
+ PUBWEAK Vector1D0
+ PUBWEAK Vector1D4
+ PUBWEAK Vector1D8
+ PUBWEAK Vector1DC
+#endif
+#if CORTEX_NUM_VECTORS > 104
+ PUBWEAK Vector1E0
+ PUBWEAK Vector1E4
+ PUBWEAK Vector1E8
+ PUBWEAK Vector1EC
+ PUBWEAK Vector1F0
+ PUBWEAK Vector1F4
+ PUBWEAK Vector1F8
+ PUBWEAK Vector1FC
+#endif
+#if CORTEX_NUM_VECTORS > 112
+ PUBWEAK Vector200
+ PUBWEAK Vector204
+ PUBWEAK Vector208
+ PUBWEAK Vector20C
+ PUBWEAK Vector210
+ PUBWEAK Vector214
+ PUBWEAK Vector218
+ PUBWEAK Vector21C
+#endif
+#if CORTEX_NUM_VECTORS > 120
+ PUBWEAK Vector220
+ PUBWEAK Vector224
+ PUBWEAK Vector228
+ PUBWEAK Vector22C
+ PUBWEAK Vector230
+ PUBWEAK Vector234
+ PUBWEAK Vector238
+ PUBWEAK Vector23C
+#endif
+#if CORTEX_NUM_VECTORS > 128
+ PUBWEAK Vector240
+ PUBWEAK Vector244
+ PUBWEAK Vector248
+ PUBWEAK Vector24C
+ PUBWEAK Vector250
+ PUBWEAK Vector254
+ PUBWEAK Vector258
+ PUBWEAK Vector25C
+#endif
+#if CORTEX_NUM_VECTORS > 136
+ PUBWEAK Vector260
+ PUBWEAK Vector264
+ PUBWEAK Vector268
+ PUBWEAK Vector26C
+ PUBWEAK Vector270
+ PUBWEAK Vector274
+ PUBWEAK Vector278
+ PUBWEAK Vector27C
+#endif
+#if CORTEX_NUM_VECTORS > 144
+ PUBWEAK Vector280
+ PUBWEAK Vector284
+ PUBWEAK Vector288
+ PUBWEAK Vector28C
+ PUBWEAK Vector290
+ PUBWEAK Vector294
+ PUBWEAK Vector298
+ PUBWEAK Vector29C
+#endif
+#if CORTEX_NUM_VECTORS > 152
+ PUBWEAK Vector2A0
+ PUBWEAK Vector2A4
+ PUBWEAK Vector2A8
+ PUBWEAK Vector2AC
+ PUBWEAK Vector2B0
+ PUBWEAK Vector2B4
+ PUBWEAK Vector2B8
+ PUBWEAK Vector2BC
+#endif
+#if CORTEX_NUM_VECTORS > 160
+ PUBWEAK Vector2C0
+ PUBWEAK Vector2C4
+ PUBWEAK Vector2C8
+ PUBWEAK Vector2CC
+ PUBWEAK Vector2D0
+ PUBWEAK Vector2D4
+ PUBWEAK Vector2D8
+ PUBWEAK Vector2DC
+#endif
+#if CORTEX_NUM_VECTORS > 168
+ PUBWEAK Vector2E0
+ PUBWEAK Vector2E4
+ PUBWEAK Vector2E8
+ PUBWEAK Vector2EC
+ PUBWEAK Vector2F0
+ PUBWEAK Vector2F4
+ PUBWEAK Vector2F8
+ PUBWEAK Vector2FC
+#endif
+#if CORTEX_NUM_VECTORS > 176
+ PUBWEAK Vector300
+ PUBWEAK Vector304
+ PUBWEAK Vector308
+ PUBWEAK Vector30C
+ PUBWEAK Vector310
+ PUBWEAK Vector314
+ PUBWEAK Vector318
+ PUBWEAK Vector31C
+#endif
+#if CORTEX_NUM_VECTORS > 184
+ PUBWEAK Vector320
+ PUBWEAK Vector324
+ PUBWEAK Vector328
+ PUBWEAK Vector32C
+ PUBWEAK Vector330
+ PUBWEAK Vector334
+ PUBWEAK Vector338
+ PUBWEAK Vector33C
+#endif
+#if CORTEX_NUM_VECTORS > 192
+ PUBWEAK Vector340
+ PUBWEAK Vector344
+ PUBWEAK Vector348
+ PUBWEAK Vector34C
+ PUBWEAK Vector350
+ PUBWEAK Vector354
+ PUBWEAK Vector358
+ PUBWEAK Vector35C
+#endif
+#if CORTEX_NUM_VECTORS > 200
+ PUBWEAK Vector360
+ PUBWEAK Vector364
+ PUBWEAK Vector368
+ PUBWEAK Vector36C
+ PUBWEAK Vector370
+ PUBWEAK Vector374
+ PUBWEAK Vector378
+ PUBWEAK Vector37C
+#endif
+#if CORTEX_NUM_VECTORS > 208
+ PUBWEAK Vector380
+ PUBWEAK Vector384
+ PUBWEAK Vector388
+ PUBWEAK Vector38C
+ PUBWEAK Vector390
+ PUBWEAK Vector394
+ PUBWEAK Vector398
+ PUBWEAK Vector39C
+#endif
+#if CORTEX_NUM_VECTORS > 216
+ PUBWEAK Vector3A0
+ PUBWEAK Vector3A4
+ PUBWEAK Vector3A8
+ PUBWEAK Vector3AC
+ PUBWEAK Vector3B0
+ PUBWEAK Vector3B4
+ PUBWEAK Vector3B8
+ PUBWEAK Vector3BC
+#endif
+#if CORTEX_NUM_VECTORS > 224
+ PUBWEAK Vector3C0
+ PUBWEAK Vector3C4
+ PUBWEAK Vector3C8
+ PUBWEAK Vector3CC
+ PUBWEAK Vector3D0
+ PUBWEAK Vector3D4
+ PUBWEAK Vector3D8
+ PUBWEAK Vector3DC
+#endif
+#if CORTEX_NUM_VECTORS > 232
+ PUBWEAK Vector3E0
+ PUBWEAK Vector3E4
+ PUBWEAK Vector3E8
+ PUBWEAK Vector3EC
+ PUBWEAK Vector3F0
+ PUBWEAK Vector3F4
+ PUBWEAK Vector3F8
+ PUBWEAK Vector3FC
+#endif
+ PUBLIC _unhandled_exception
+
+ SECTION .text:CODE:NOROOT:REORDER(1)
+ THUMB
+
+NMI_Handler
+HardFault_Handler
+MemManage_Handler
+BusFault_Handler
+UsageFault_Handler
+Vector1C
+Vector20
+Vector24
+Vector28
+SVC_Handler
+DebugMon_Handler
+Vector34
+PendSV_Handler
+SysTick_Handler
+Vector40
+Vector44
+Vector48
+Vector4C
+Vector50
+Vector54
+Vector58
+Vector5C
+#if CORTEX_NUM_VECTORS > 8
+Vector60
+Vector64
+Vector68
+Vector6C
+Vector70
+Vector74
+Vector78
+Vector7C
+#endif
+#if CORTEX_NUM_VECTORS > 16
+Vector80
+Vector84
+Vector88
+Vector8C
+Vector90
+Vector94
+Vector98
+Vector9C
+#endif
+#if CORTEX_NUM_VECTORS > 24
+VectorA0
+VectorA4
+VectorA8
+VectorAC
+VectorB0
+VectorB4
+VectorB8
+VectorBC
+#endif
+#if CORTEX_NUM_VECTORS > 32
+VectorC0
+VectorC4
+VectorC8
+VectorCC
+VectorD0
+VectorD4
+VectorD8
+VectorDC
+#endif
+#if CORTEX_NUM_VECTORS > 40
+VectorE0
+VectorE4
+VectorE8
+VectorEC
+VectorF0
+VectorF4
+VectorF8
+VectorFC
+#endif
+#if CORTEX_NUM_VECTORS > 48
+Vector100
+Vector104
+Vector108
+Vector10C
+Vector110
+Vector114
+Vector118
+Vector11C
+#endif
+#if CORTEX_NUM_VECTORS > 56
+Vector120
+Vector124
+Vector128
+Vector12C
+Vector130
+Vector134
+Vector138
+Vector13C
+#endif
+#if CORTEX_NUM_VECTORS > 64
+Vector140
+Vector144
+Vector148
+Vector14C
+Vector150
+Vector154
+Vector158
+Vector15C
+#endif
+#if CORTEX_NUM_VECTORS > 72
+Vector160
+Vector164
+Vector168
+Vector16C
+Vector170
+Vector174
+Vector178
+Vector17C
+#endif
+#if CORTEX_NUM_VECTORS > 80
+Vector180
+Vector184
+Vector188
+Vector18C
+Vector190
+Vector194
+Vector198
+Vector19C
+#endif
+#if CORTEX_NUM_VECTORS > 88
+Vector1A0
+Vector1A4
+Vector1A8
+Vector1AC
+Vector1B0
+Vector1B4
+Vector1B8
+Vector1BC
+#endif
+#if CORTEX_NUM_VECTORS > 96
+Vector1C0
+Vector1C4
+Vector1C8
+Vector1CC
+Vector1D0
+Vector1D4
+Vector1D8
+Vector1DC
+#endif
+#if CORTEX_NUM_VECTORS > 104
+Vector1E0
+Vector1E4
+Vector1E8
+Vector1EC
+Vector1F0
+Vector1F4
+Vector1F8
+Vector1FC
+#endif
+#if CORTEX_NUM_VECTORS > 112
+Vector200
+Vector204
+Vector208
+Vector20C
+Vector210
+Vector214
+Vector218
+Vector21C
+#endif
+#if CORTEX_NUM_VECTORS > 120
+Vector220
+Vector224
+Vector228
+Vector22C
+Vector230
+Vector234
+Vector238
+Vector23C
+#endif
+#if CORTEX_NUM_VECTORS > 128
+Vector240
+Vector244
+Vector248
+Vector24C
+Vector250
+Vector254
+Vector258
+Vector25C
+#endif
+#if CORTEX_NUM_VECTORS > 136
+Vector260
+Vector264
+Vector268
+Vector26C
+Vector270
+Vector274
+Vector278
+Vector27C
+#endif
+#if CORTEX_NUM_VECTORS > 144
+Vector280
+Vector284
+Vector288
+Vector28C
+Vector290
+Vector294
+Vector298
+Vector29C
+#endif
+#if CORTEX_NUM_VECTORS > 152
+Vector2A0
+Vector2A4
+Vector2A8
+Vector2AC
+Vector2B0
+Vector2B4
+Vector2B8
+Vector2BC
+#endif
+#if CORTEX_NUM_VECTORS > 160
+Vector2C0
+Vector2C4
+Vector2C8
+Vector2CC
+Vector2D0
+Vector2D4
+Vector2D8
+Vector2DC
+#endif
+#if CORTEX_NUM_VECTORS > 168
+Vector2E0
+Vector2E4
+Vector2E8
+Vector2EC
+Vector2F0
+Vector2F4
+Vector2F8
+Vector2FC
+#endif
+#if CORTEX_NUM_VECTORS > 176
+Vector300
+Vector304
+Vector308
+Vector30C
+Vector310
+Vector314
+Vector318
+Vector31C
+#endif
+#if CORTEX_NUM_VECTORS > 184
+Vector320
+Vector324
+Vector328
+Vector32C
+Vector330
+Vector334
+Vector338
+Vector33C
+#endif
+#if CORTEX_NUM_VECTORS > 192
+Vector340
+Vector344
+Vector348
+Vector34C
+Vector350
+Vector354
+Vector358
+Vector35C
+#endif
+#if CORTEX_NUM_VECTORS > 200
+Vector360
+Vector364
+Vector368
+Vector36C
+Vector370
+Vector374
+Vector378
+Vector37C
+#endif
+#if CORTEX_NUM_VECTORS > 208
+Vector380
+Vector384
+Vector388
+Vector38C
+Vector390
+Vector394
+Vector398
+Vector39C
+#endif
+#if CORTEX_NUM_VECTORS > 216
+Vector3A0
+Vector3A4
+Vector3A8
+Vector3AC
+Vector3B0
+Vector3B4
+Vector3B8
+Vector3BC
+#endif
+#if CORTEX_NUM_VECTORS > 224
+Vector3C0
+Vector3C4
+Vector3C8
+Vector3CC
+Vector3D0
+Vector3D4
+Vector3D8
+Vector3DC
+#endif
+#if CORTEX_NUM_VECTORS > 232
+Vector3E0
+Vector3E4
+Vector3E8
+Vector3EC
+Vector3F0
+Vector3F4
+Vector3F8
+Vector3FC
+#endif
+_unhandled_exception
+ b _unhandled_exception
+
+ END
+
+#endif /* !defined(__DOXYGEN__) */
+
+/**< @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/LLVM/mk/clang.mk b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/LLVM/mk/clang.mk
new file mode 100644
index 0000000..db0f1e4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/LLVM/mk/clang.mk
@@ -0,0 +1,19 @@
+##############################################################################
+# Compiler settings
+#
+
+TRGT = aarch32-
+CC = clang
+CPPC = clang++
+LD = clang
+CP = $(TRGT)objcopy
+AS = $(TRGT)as -x assembler-with-cpp
+AR = $(TRGT)ar
+OD = $(TRGT)objdump
+SZ = $(TRGT)size
+HEX = $(CP) -O ihex
+BIN = $(CP) -O binary
+
+#
+# Compiler settings
+##############################################################################
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/LLVM/mk/rules.mk b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/LLVM/mk/rules.mk
new file mode 100644
index 0000000..0d6af76
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/LLVM/mk/rules.mk
@@ -0,0 +1,284 @@
+# ARM Cortex-Mx common makefile scripts and rules.
+
+##############################################################################
+# Processing options coming from the upper Makefile.
+#
+
+# Compiler options
+OPT := $(USE_OPT)
+COPT := $(USE_COPT)
+CPPOPT := $(USE_CPPOPT)
+
+# Garbage collection
+ifeq ($(USE_LINK_GC),yes)
+ OPT += -ffunction-sections -fdata-sections -fno-common
+ LDOPT := ,--gc-sections
+else
+ LDOPT :=
+endif
+
+# Linker extra options
+ifneq ($(USE_LDOPT),)
+ LDOPT := $(LDOPT),$(USE_LDOPT)
+endif
+
+# Link time optimizations
+ifeq ($(USE_LTO),yes)
+ OPT += -flto
+endif
+
+# FPU options default (Cortex-M4 and Cortex-M7 single precision).
+ifeq ($(USE_FPU_OPT),)
+ USE_FPU_OPT = -mfloat-abi=$(USE_FPU) -mfpu=fpv4-sp-d16
+endif
+
+# FPU-related options
+ifeq ($(USE_FPU),)
+ USE_FPU = no
+endif
+ifneq ($(USE_FPU),no)
+ OPT += $(USE_FPU_OPT)
+ DDEFS += -DCORTEX_USE_FPU=TRUE
+ DADEFS += -DCORTEX_USE_FPU=TRUE
+else
+ OPT += -mfloat-abi=soft
+ DDEFS += -DCORTEX_USE_FPU=FALSE
+ DADEFS += -DCORTEX_USE_FPU=FALSE
+endif
+
+# Process stack size
+ifeq ($(USE_PROCESS_STACKSIZE),)
+ LDOPT := $(LDOPT),--defsym=__process_stack_size__=0x400
+else
+ LDOPT := $(LDOPT),--defsym=__process_stack_size__=$(USE_PROCESS_STACKSIZE)
+endif
+
+# Exceptions stack size
+ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
+ LDOPT := $(LDOPT),--defsym=__main_stack_size__=0x400
+else
+ LDOPT := $(LDOPT),--defsym=__main_stack_size__=$(USE_EXCEPTIONS_STACKSIZE)
+endif
+
+# Output directory and files
+ifeq ($(BUILDDIR),)
+ BUILDDIR = build
+endif
+ifeq ($(BUILDDIR),.)
+ BUILDDIR = build
+endif
+
+# Dependencies directory
+ifeq ($(DEPDIR),)
+ DEPDIR = .dep
+endif
+ifeq ($(DEPDIR),.)
+ DEPDIR = .dep
+endif
+
+OUTFILES := $(BUILDDIR)/$(PROJECT).elf \
+ $(BUILDDIR)/$(PROJECT).hex \
+ $(BUILDDIR)/$(PROJECT).bin \
+ $(BUILDDIR)/$(PROJECT).dmp \
+ $(BUILDDIR)/$(PROJECT).list
+
+ifdef SREC
+ OUTFILES += $(BUILDDIR)/$(PROJECT).srec
+endif
+
+# Source files groups and paths
+TCSRC += $(CSRC)
+TCPPSRC += $(CPPSRC)
+TSRC := $(TCSRC) $(TCPPSRC)
+SRCPATHS := $(sort $(dir $(ASMXSRC)) $(dir $(ASMSRC)) $(dir $(TSRC)))
+
+# Various directories
+OBJDIR := $(BUILDDIR)/obj
+LSTDIR := $(BUILDDIR)/lst
+
+# Object files groups
+TCOBJS := $(addprefix $(OBJDIR)/, $(notdir $(TCSRC:.c=.o)))
+TCPPOBJS := $(addprefix $(OBJDIR)/, $(notdir $(TCPPSRC:.cpp=.o)))
+ASMOBJS := $(addprefix $(OBJDIR)/, $(notdir $(ASMSRC:.s=.o)))
+ASMXOBJS := $(addprefix $(OBJDIR)/, $(notdir $(ASMXSRC:.S=.o)))
+OBJS := $(ASMXOBJS) $(ASMOBJS) $(ACOBJS) $(TCOBJS) $(ACPPOBJS) $(TCPPOBJS)
+
+# Paths
+IINCDIR := $(patsubst %,-I%,$(INCDIR) $(DINCDIR) $(UINCDIR))
+LLIBDIR := $(patsubst %,-L%,$(DLIBDIR) $(ULIBDIR))
+
+# Macros
+DEFS := $(DDEFS) $(UDEFS)
+ADEFS := $(DADEFS) $(UADEFS)
+
+# Libs
+LIBS := $(DLIBS) $(ULIBS)
+
+# Various settings
+MCFLAGS := -mcpu=$(MCU) -mthumb
+ODFLAGS = -x --syms
+ASFLAGS = $(MCFLAGS) $(OPT) $(ADEFS)
+ASXFLAGS = $(MCFLAGS) $(OPT) $(ADEFS)
+CFLAGS = $(MCFLAGS) $(OPT) $(COPT) $(CWARN) $(DEFS)
+CPPFLAGS = $(MCFLAGS) $(OPT) $(CPPOPT) $(CPPWARN) $(DEFS)
+#ASFLAGS = $(MCFLAGS) $(OPT) -Wa,-amhls=$(LSTDIR)/$(notdir $(<:.s=.lst)) $(ADEFS)
+#ASXFLAGS = $(MCFLAGS) $(OPT) -Wa,-amhls=$(LSTDIR)/$(notdir $(<:.S=.lst)) $(ADEFS)
+#CFLAGS = $(MCFLAGS) $(OPT) $(COPT) $(CWARN) -Wa,-alms=$(LSTDIR)/$(notdir $(<:.c=.lst)) $(DEFS)
+#CPPFLAGS = $(MCFLAGS) $(OPT) $(CPPOPT) $(CPPWARN) -Wa,-alms=$(LSTDIR)/$(notdir $(<:.cpp=.lst)) $(DEFS)
+LDFLAGS = $(MCFLAGS) $(OPT) -nostartfiles $(LLIBDIR) -Wl,-Map=$(BUILDDIR)/$(PROJECT).map,--cref,--no-warn-mismatch,--library-path=$(STARTUPLD),--script=$(LDSCRIPT)$(LDOPT)
+
+# Generate dependency information
+ASFLAGS += -MD -MP -MF $(DEPDIR)/$(@F).d
+ASXFLAGS += -MD -MP -MF $(DEPDIR)/$(@F).d
+CFLAGS += -MD -MP -MF $(DEPDIR)/$(@F).d
+CPPFLAGS += -MD -MP -MF $(DEPDIR)/$(@F).d
+
+# Paths where to search for sources
+VPATH = $(SRCPATHS)
+
+#
+# Makefile rules
+#
+
+all: PRE_MAKE_ALL_RULE_HOOK $(OBJS) $(OUTFILES) POST_MAKE_ALL_RULE_HOOK
+
+PRE_MAKE_ALL_RULE_HOOK:
+
+POST_MAKE_ALL_RULE_HOOK:
+
+$(OBJS): | PRE_MAKE_ALL_RULE_HOOK $(BUILDDIR) $(OBJDIR) $(LSTDIR) $(DEPDIR)
+
+$(BUILDDIR):
+ifneq ($(USE_VERBOSE_COMPILE),yes)
+ @echo Compiler Options
+ @echo $(CC) -c $(CFLAGS) -I. $(IINCDIR) main.c -o main.o
+ @echo
+endif
+ @mkdir -p $(BUILDDIR)
+
+$(OBJDIR):
+ @mkdir -p $(OBJDIR)
+
+$(LSTDIR):
+ @mkdir -p $(LSTDIR)
+
+$(DEPDIR):
+ @mkdir -p $(DEPDIR)
+
+$(TCPPOBJS) : $(OBJDIR)/%.o : %.cpp $(MAKEFILE_LIST)
+ifeq ($(USE_VERBOSE_COMPILE),yes)
+ @echo
+ $(CPPC) -c $(CPPFLAGS) -I. $(IINCDIR) $< -o $@
+else
+ @echo Compiling $( $@
+ $(SZ) $<
+else
+ @echo Creating $@
+ @$(OD) $(ODFLAGS) $< > $@
+ @echo
+ @$(SZ) $<
+endif
+
+%.list: %.elf
+ifeq ($(USE_VERBOSE_COMPILE),yes)
+ $(OD) -S $< > $@
+else
+ @echo Creating $@
+ @$(OD) -S $< > $@
+ @echo
+ @echo Done
+endif
+
+lib: $(OBJS) $(BUILDDIR)/lib$(PROJECT).a
+
+$(BUILDDIR)/lib$(PROJECT).a: $(OBJS)
+ @$(AR) -r $@ $^
+ @echo
+ @echo Done
+
+clean: CLEAN_RULE_HOOK
+ @echo Cleaning
+ @echo - $(DEPDIR)
+ @-rm -fR $(DEPDIR)/* $(BUILDDIR)/* 2>/dev/null
+ @-if [ -d "$(DEPDIR)" ]; then rmdir -p --ignore-fail-on-non-empty $(subst ./,,$(DEPDIR)) 2>/dev/null; fi
+ @echo - $(BUILDDIR)
+ @-if [ -d "$(BUILDDIR)" ]; then rmdir -p --ignore-fail-on-non-empty $(subst ./,,$(BUILDDIR)) 2>/dev/null; fi
+ @echo
+ @echo Done
+
+CLEAN_RULE_HOOK:
+
+#
+# Include the dependency files, should be the last of the makefile
+#
+-include $(wildcard $(DEPDIR)/*)
+
+# *** EOF ***
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/RVCT/cstartup.s b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/RVCT/cstartup.s
new file mode 100644
index 0000000..6a94d13
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/RVCT/cstartup.s
@@ -0,0 +1,131 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ARMCMx/RVCT/cstartup.s
+ * @brief Generic RVCT Cortex-Mx startup file.
+ *
+ * @addtogroup ARMCMx_RVCT_STARTUP
+ * @{
+ */
+
+#if !defined(__DOXYGEN__)
+
+;/* <<< Use Configuration Wizard in Context Menu >>> */
+
+;// Main Stack Configuration (IRQ Stack)
+;// Main Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
+;//
+main_stack_size EQU 0x00000400
+
+;// Process Stack Configuration
+;// Process Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
+;//
+proc_stack_size EQU 0x00000400
+
+;// C-runtime heap size
+;// C-runtime heap size (in Bytes) <0x0-0xFFFFFFFF:8>
+;//
+heap_size EQU 0x00000400
+
+ AREA MSTACK, NOINIT, READWRITE, ALIGN=3
+main_stack_mem SPACE main_stack_size
+ EXPORT __initial_msp
+__initial_msp
+
+ AREA CSTACK, NOINIT, READWRITE, ALIGN=3
+__main_thread_stack_base__
+ EXPORT __main_thread_stack_base__
+proc_stack_mem SPACE proc_stack_size
+ EXPORT __initial_sp
+__initial_sp
+
+ AREA HEAP, NOINIT, READWRITE, ALIGN=3
+__heap_base
+Heap_Mem SPACE heap_size
+__heap_limit
+
+CONTROL_MODE_PRIVILEGED EQU 0
+CONTROL_MODE_UNPRIVILEGED EQU 1
+CONTROL_USE_MSP EQU 0
+CONTROL_USE_PSP EQU 2
+
+ PRESERVE8
+ THUMB
+
+ AREA |.text|, CODE, READONLY
+
+/*
+ * Reset handler.
+ */
+ IMPORT __main
+ EXPORT Reset_Handler
+Reset_Handler PROC
+ cpsid i
+ ldr r0, =__initial_sp
+ msr PSP, r0
+ movs r0, #CONTROL_MODE_PRIVILEGED :OR: CONTROL_USE_PSP
+ msr CONTROL, r0
+ isb
+ bl __early_init
+
+ IF {CPU} = "Cortex-M4.fp.sp"
+ LDR R0, =0xE000ED88 ; Enable CP10,CP11
+ LDR R1, [R0]
+ ORR R1, R1, #(0xF << 20)
+ STR R1, [R0]
+ ENDIF
+
+ ldr r0, =__main
+ bx r0
+ ENDP
+
+__early_init PROC
+ EXPORT __early_init [WEAK]
+ bx lr
+ ENDP
+
+ ALIGN
+
+/*
+ * User Initial Stack & Heap.
+ */
+ IF :DEF:__MICROLIB
+
+ EXPORT __initial_sp
+ EXPORT __heap_base
+ EXPORT __heap_limit
+
+ ELSE
+
+ IMPORT __use_two_region_memory
+ EXPORT __user_initial_stackheap
+__user_initial_stackheap
+ ldr r0, =Heap_Mem
+ ldr r1, =(proc_stack_mem + proc_stack_size)
+ ldr r2, =(Heap_Mem + heap_size)
+ ldr r3, =proc_stack_mem
+ bx lr
+
+ ALIGN
+
+ ENDIF
+
+ END
+
+#endif /* !defined(__DOXYGEN__) */
+
+/**< @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/RVCT/vectors.s b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/RVCT/vectors.s
new file mode 100644
index 0000000..13329ba
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/compilers/RVCT/vectors.s
@@ -0,0 +1,1002 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ARMCMx/RVCT/vectors.c
+ * @brief Interrupt vectors for Cortex-Mx devices.
+ *
+ * @defgroup ARMCMx_RVCT_VECTORS Cortex-Mx Interrupt Vectors
+ * @{
+ */
+
+#define _FROM_ASM_
+#include "cmparams.h"
+
+#if !defined(__DOXYGEN__)
+
+#if (CORTEX_NUM_VECTORS & 7) != 0
+#error "the constant CORTEX_NUM_VECTORS must be a multiple of 8"
+#endif
+
+#if (CORTEX_NUM_VECTORS < 8) || (CORTEX_NUM_VECTORS > 240)
+#error "the constant CORTEX_NUM_VECTORS must be between 8 and 240 inclusive"
+#endif
+
+ PRESERVE8
+
+ AREA RESET, DATA, READONLY
+
+ IMPORT __initial_msp
+ IMPORT Reset_Handler
+ EXPORT __Vectors
+
+__Vectors
+ DCD __initial_msp
+ DCD Reset_Handler
+ DCD NMI_Handler
+ DCD HardFault_Handler
+ DCD MemManage_Handler
+ DCD BusFault_Handler
+ DCD UsageFault_Handler
+ DCD Vector1C
+ DCD Vector20
+ DCD Vector24
+ DCD Vector28
+ DCD SVC_Handler
+ DCD DebugMon_Handler
+ DCD Vector34
+ DCD PendSV_Handler
+ DCD SysTick_Handler
+ DCD Vector40
+ DCD Vector44
+ DCD Vector48
+ DCD Vector4C
+ DCD Vector50
+ DCD Vector54
+ DCD Vector58
+ DCD Vector5C
+#if CORTEX_NUM_VECTORS > 8
+ DCD Vector60
+ DCD Vector64
+ DCD Vector68
+ DCD Vector6C
+ DCD Vector70
+ DCD Vector74
+ DCD Vector78
+ DCD Vector7C
+#endif
+#if CORTEX_NUM_VECTORS > 16
+ DCD Vector80
+ DCD Vector84
+ DCD Vector88
+ DCD Vector8C
+ DCD Vector90
+ DCD Vector94
+ DCD Vector98
+ DCD Vector9C
+#endif
+#if CORTEX_NUM_VECTORS > 24
+ DCD VectorA0
+ DCD VectorA4
+ DCD VectorA8
+ DCD VectorAC
+ DCD VectorB0
+ DCD VectorB4
+ DCD VectorB8
+ DCD VectorBC
+#endif
+#if CORTEX_NUM_VECTORS > 32
+ DCD VectorC0
+ DCD VectorC4
+ DCD VectorC8
+ DCD VectorCC
+ DCD VectorD0
+ DCD VectorD4
+ DCD VectorD8
+ DCD VectorDC
+#endif
+#if CORTEX_NUM_VECTORS > 40
+ DCD VectorE0
+ DCD VectorE4
+ DCD VectorE8
+ DCD VectorEC
+ DCD VectorF0
+ DCD VectorF4
+ DCD VectorF8
+ DCD VectorFC
+#endif
+#if CORTEX_NUM_VECTORS > 48
+ DCD Vector100
+ DCD Vector104
+ DCD Vector108
+ DCD Vector10C
+ DCD Vector110
+ DCD Vector114
+ DCD Vector118
+ DCD Vector11C
+#endif
+#if CORTEX_NUM_VECTORS > 56
+ DCD Vector120
+ DCD Vector124
+ DCD Vector128
+ DCD Vector12C
+ DCD Vector130
+ DCD Vector134
+ DCD Vector138
+ DCD Vector13C
+#endif
+#if CORTEX_NUM_VECTORS > 64
+ DCD Vector140
+ DCD Vector144
+ DCD Vector148
+ DCD Vector14C
+ DCD Vector150
+ DCD Vector154
+ DCD Vector158
+ DCD Vector15C
+#endif
+#if CORTEX_NUM_VECTORS > 72
+ DCD Vector160
+ DCD Vector164
+ DCD Vector168
+ DCD Vector16C
+ DCD Vector170
+ DCD Vector174
+ DCD Vector178
+ DCD Vector17C
+#endif
+#if CORTEX_NUM_VECTORS > 80
+ DCD Vector180
+ DCD Vector184
+ DCD Vector188
+ DCD Vector18C
+ DCD Vector190
+ DCD Vector194
+ DCD Vector198
+ DCD Vector19C
+#endif
+#if CORTEX_NUM_VECTORS > 88
+ DCD Vector1A0
+ DCD Vector1A4
+ DCD Vector1A8
+ DCD Vector1AC
+ DCD Vector1B0
+ DCD Vector1B4
+ DCD Vector1B8
+ DCD Vector1BC
+#endif
+#if CORTEX_NUM_VECTORS > 96
+ DCD Vector1C0
+ DCD Vector1C4
+ DCD Vector1C8
+ DCD Vector1CC
+ DCD Vector1D0
+ DCD Vector1D4
+ DCD Vector1D8
+ DCD Vector1DC
+#endif
+#if CORTEX_NUM_VECTORS > 104
+ DCD Vector1E0
+ DCD Vector1E4
+ DCD Vector1E8
+ DCD Vector1EC
+ DCD Vector1F0
+ DCD Vector1F4
+ DCD Vector1F8
+ DCD Vector1FC
+#endif
+#if CORTEX_NUM_VECTORS > 112
+ DCD Vector200
+ DCD Vector204
+ DCD Vector208
+ DCD Vector20C
+ DCD Vector210
+ DCD Vector214
+ DCD Vector218
+ DCD Vector21C
+#endif
+#if CORTEX_NUM_VECTORS > 120
+ DCD Vector220
+ DCD Vector224
+ DCD Vector228
+ DCD Vector22C
+ DCD Vector230
+ DCD Vector234
+ DCD Vector238
+ DCD Vector23C
+#endif
+#if CORTEX_NUM_VECTORS > 128
+ DCD Vector240
+ DCD Vector244
+ DCD Vector248
+ DCD Vector24C
+ DCD Vector250
+ DCD Vector254
+ DCD Vector258
+ DCD Vector25C
+#endif
+#if CORTEX_NUM_VECTORS > 136
+ DCD Vector260
+ DCD Vector264
+ DCD Vector268
+ DCD Vector26C
+ DCD Vector270
+ DCD Vector274
+ DCD Vector278
+ DCD Vector27C
+#endif
+#if CORTEX_NUM_VECTORS > 144
+ DCD Vector280
+ DCD Vector284
+ DCD Vector288
+ DCD Vector28C
+ DCD Vector290
+ DCD Vector294
+ DCD Vector298
+ DCD Vector29C
+#endif
+#if CORTEX_NUM_VECTORS > 152
+ DCD Vector2A0
+ DCD Vector2A4
+ DCD Vector2A8
+ DCD Vector2AC
+ DCD Vector2B0
+ DCD Vector2B4
+ DCD Vector2B8
+ DCD Vector2BC
+#endif
+#if CORTEX_NUM_VECTORS > 160
+ DCD Vector2C0
+ DCD Vector2C4
+ DCD Vector2C8
+ DCD Vector2CC
+ DCD Vector2D0
+ DCD Vector2D4
+ DCD Vector2D8
+ DCD Vector2DC
+#endif
+#if CORTEX_NUM_VECTORS > 168
+ DCD Vector2E0
+ DCD Vector2E4
+ DCD Vector2E8
+ DCD Vector2EC
+ DCD Vector2F0
+ DCD Vector2F4
+ DCD Vector2F8
+ DCD Vector2FC
+#endif
+#if CORTEX_NUM_VECTORS > 176
+ DCD Vector300
+ DCD Vector304
+ DCD Vector308
+ DCD Vector30C
+ DCD Vector310
+ DCD Vector314
+ DCD Vector318
+ DCD Vector31C
+#endif
+#if CORTEX_NUM_VECTORS > 184
+ DCD Vector320
+ DCD Vector324
+ DCD Vector328
+ DCD Vector32C
+ DCD Vector330
+ DCD Vector334
+ DCD Vector338
+ DCD Vector33C
+#endif
+#if CORTEX_NUM_VECTORS > 192
+ DCD Vector340
+ DCD Vector344
+ DCD Vector348
+ DCD Vector34C
+ DCD Vector350
+ DCD Vector354
+ DCD Vector358
+ DCD Vector35C
+#endif
+#if CORTEX_NUM_VECTORS > 200
+ DCD Vector360
+ DCD Vector364
+ DCD Vector368
+ DCD Vector36C
+ DCD Vector370
+ DCD Vector374
+ DCD Vector378
+ DCD Vector37C
+#endif
+#if CORTEX_NUM_VECTORS > 208
+ DCD Vector380
+ DCD Vector384
+ DCD Vector388
+ DCD Vector38C
+ DCD Vector390
+ DCD Vector394
+ DCD Vector398
+ DCD Vector39C
+#endif
+#if CORTEX_NUM_VECTORS > 216
+ DCD Vector3A0
+ DCD Vector3A4
+ DCD Vector3A8
+ DCD Vector3AC
+ DCD Vector3B0
+ DCD Vector3B4
+ DCD Vector3B8
+ DCD Vector3BC
+#endif
+#if CORTEX_NUM_VECTORS > 224
+ DCD Vector3C0
+ DCD Vector3C4
+ DCD Vector3C8
+ DCD Vector3CC
+ DCD Vector3D0
+ DCD Vector3D4
+ DCD Vector3D8
+ DCD Vector3DC
+#endif
+#if CORTEX_NUM_VECTORS > 232
+ DCD Vector3E0
+ DCD Vector3E4
+ DCD Vector3E8
+ DCD Vector3EC
+ DCD Vector3F0
+ DCD Vector3F4
+ DCD Vector3F8
+ DCD Vector3FC
+#endif
+
+ AREA |.text|, CODE, READONLY
+ THUMB
+
+/*
+ * Default interrupt handlers.
+ */
+ EXPORT _unhandled_exception
+_unhandled_exception PROC
+ EXPORT NMI_Handler [WEAK]
+ EXPORT HardFault_Handler [WEAK]
+ EXPORT MemManage_Handler [WEAK]
+ EXPORT BusFault_Handler [WEAK]
+ EXPORT UsageFault_Handler [WEAK]
+ EXPORT Vector1C [WEAK]
+ EXPORT Vector20 [WEAK]
+ EXPORT Vector24 [WEAK]
+ EXPORT Vector28 [WEAK]
+ EXPORT SVC_Handler [WEAK]
+ EXPORT DebugMon_Handler [WEAK]
+ EXPORT Vector34 [WEAK]
+ EXPORT PendSV_Handler [WEAK]
+ EXPORT SysTick_Handler [WEAK]
+ EXPORT Vector40 [WEAK]
+ EXPORT Vector44 [WEAK]
+ EXPORT Vector48 [WEAK]
+ EXPORT Vector4C [WEAK]
+ EXPORT Vector50 [WEAK]
+ EXPORT Vector54 [WEAK]
+ EXPORT Vector58 [WEAK]
+ EXPORT Vector5C [WEAK]
+#if CORTEX_NUM_VECTORS > 8
+ EXPORT Vector60 [WEAK]
+ EXPORT Vector64 [WEAK]
+ EXPORT Vector68 [WEAK]
+ EXPORT Vector6C [WEAK]
+ EXPORT Vector70 [WEAK]
+ EXPORT Vector74 [WEAK]
+ EXPORT Vector78 [WEAK]
+ EXPORT Vector7C [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 16
+ EXPORT Vector80 [WEAK]
+ EXPORT Vector84 [WEAK]
+ EXPORT Vector88 [WEAK]
+ EXPORT Vector8C [WEAK]
+ EXPORT Vector90 [WEAK]
+ EXPORT Vector94 [WEAK]
+ EXPORT Vector98 [WEAK]
+ EXPORT Vector9C [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 24
+ EXPORT VectorA0 [WEAK]
+ EXPORT VectorA4 [WEAK]
+ EXPORT VectorA8 [WEAK]
+ EXPORT VectorAC [WEAK]
+ EXPORT VectorB0 [WEAK]
+ EXPORT VectorB4 [WEAK]
+ EXPORT VectorB8 [WEAK]
+ EXPORT VectorBC [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 32
+ EXPORT VectorC0 [WEAK]
+ EXPORT VectorC4 [WEAK]
+ EXPORT VectorC8 [WEAK]
+ EXPORT VectorCC [WEAK]
+ EXPORT VectorD0 [WEAK]
+ EXPORT VectorD4 [WEAK]
+ EXPORT VectorD8 [WEAK]
+ EXPORT VectorDC [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 40
+ EXPORT VectorE0 [WEAK]
+ EXPORT VectorE4 [WEAK]
+ EXPORT VectorE8 [WEAK]
+ EXPORT VectorEC [WEAK]
+ EXPORT VectorF0 [WEAK]
+ EXPORT VectorF4 [WEAK]
+ EXPORT VectorF8 [WEAK]
+ EXPORT VectorFC [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 48
+ EXPORT Vector100 [WEAK]
+ EXPORT Vector104 [WEAK]
+ EXPORT Vector108 [WEAK]
+ EXPORT Vector10C [WEAK]
+ EXPORT Vector110 [WEAK]
+ EXPORT Vector114 [WEAK]
+ EXPORT Vector118 [WEAK]
+ EXPORT Vector11C [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 56
+ EXPORT Vector120 [WEAK]
+ EXPORT Vector124 [WEAK]
+ EXPORT Vector128 [WEAK]
+ EXPORT Vector12C [WEAK]
+ EXPORT Vector130 [WEAK]
+ EXPORT Vector134 [WEAK]
+ EXPORT Vector138 [WEAK]
+ EXPORT Vector13C [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 64
+ EXPORT Vector140 [WEAK]
+ EXPORT Vector144 [WEAK]
+ EXPORT Vector148 [WEAK]
+ EXPORT Vector14C [WEAK]
+ EXPORT Vector150 [WEAK]
+ EXPORT Vector154 [WEAK]
+ EXPORT Vector158 [WEAK]
+ EXPORT Vector15C [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 72
+ EXPORT Vector160 [WEAK]
+ EXPORT Vector164 [WEAK]
+ EXPORT Vector168 [WEAK]
+ EXPORT Vector16C [WEAK]
+ EXPORT Vector170 [WEAK]
+ EXPORT Vector174 [WEAK]
+ EXPORT Vector178 [WEAK]
+ EXPORT Vector17C [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 80
+ EXPORT Vector180 [WEAK]
+ EXPORT Vector184 [WEAK]
+ EXPORT Vector188 [WEAK]
+ EXPORT Vector18C [WEAK]
+ EXPORT Vector190 [WEAK]
+ EXPORT Vector194 [WEAK]
+ EXPORT Vector198 [WEAK]
+ EXPORT Vector19C [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 88
+ EXPORT Vector1A0 [WEAK]
+ EXPORT Vector1A4 [WEAK]
+ EXPORT Vector1A8 [WEAK]
+ EXPORT Vector1AC [WEAK]
+ EXPORT Vector1B0 [WEAK]
+ EXPORT Vector1B4 [WEAK]
+ EXPORT Vector1B8 [WEAK]
+ EXPORT Vector1BC [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 96
+ EXPORT Vector1C0 [WEAK]
+ EXPORT Vector1C4 [WEAK]
+ EXPORT Vector1C8 [WEAK]
+ EXPORT Vector1CC [WEAK]
+ EXPORT Vector1D0 [WEAK]
+ EXPORT Vector1D4 [WEAK]
+ EXPORT Vector1D8 [WEAK]
+ EXPORT Vector1DC [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 104
+ EXPORT Vector1E0 [WEAK]
+ EXPORT Vector1E4 [WEAK]
+ EXPORT Vector1E8 [WEAK]
+ EXPORT Vector1EC [WEAK]
+ EXPORT Vector1F0 [WEAK]
+ EXPORT Vector1F4 [WEAK]
+ EXPORT Vector1F8 [WEAK]
+ EXPORT Vector1FC [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 112
+ EXPORT Vector200 [WEAK]
+ EXPORT Vector204 [WEAK]
+ EXPORT Vector208 [WEAK]
+ EXPORT Vector20C [WEAK]
+ EXPORT Vector210 [WEAK]
+ EXPORT Vector214 [WEAK]
+ EXPORT Vector218 [WEAK]
+ EXPORT Vector21C [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 120
+ EXPORT Vector220 [WEAK]
+ EXPORT Vector224 [WEAK]
+ EXPORT Vector228 [WEAK]
+ EXPORT Vector22C [WEAK]
+ EXPORT Vector230 [WEAK]
+ EXPORT Vector234 [WEAK]
+ EXPORT Vector238 [WEAK]
+ EXPORT Vector23C [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 128
+ EXPORT Vector240 [WEAK]
+ EXPORT Vector244 [WEAK]
+ EXPORT Vector248 [WEAK]
+ EXPORT Vector24C [WEAK]
+ EXPORT Vector250 [WEAK]
+ EXPORT Vector254 [WEAK]
+ EXPORT Vector258 [WEAK]
+ EXPORT Vector25C [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 136
+ EXPORT Vector260 [WEAK]
+ EXPORT Vector264 [WEAK]
+ EXPORT Vector268 [WEAK]
+ EXPORT Vector26C [WEAK]
+ EXPORT Vector270 [WEAK]
+ EXPORT Vector274 [WEAK]
+ EXPORT Vector278 [WEAK]
+ EXPORT Vector27C [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 144
+ EXPORT Vector280 [WEAK]
+ EXPORT Vector284 [WEAK]
+ EXPORT Vector288 [WEAK]
+ EXPORT Vector28C [WEAK]
+ EXPORT Vector290 [WEAK]
+ EXPORT Vector294 [WEAK]
+ EXPORT Vector298 [WEAK]
+ EXPORT Vector29C [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 152
+ EXPORT Vector2A0 [WEAK]
+ EXPORT Vector2A4 [WEAK]
+ EXPORT Vector2A8 [WEAK]
+ EXPORT Vector2AC [WEAK]
+ EXPORT Vector2B0 [WEAK]
+ EXPORT Vector2B4 [WEAK]
+ EXPORT Vector2B8 [WEAK]
+ EXPORT Vector2BC [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 160
+ EXPORT Vector2C0 [WEAK]
+ EXPORT Vector2C4 [WEAK]
+ EXPORT Vector2C8 [WEAK]
+ EXPORT Vector2CC [WEAK]
+ EXPORT Vector2D0 [WEAK]
+ EXPORT Vector2D4 [WEAK]
+ EXPORT Vector2D8 [WEAK]
+ EXPORT Vector2DC [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 168
+ EXPORT Vector2E0 [WEAK]
+ EXPORT Vector2E4 [WEAK]
+ EXPORT Vector2E8 [WEAK]
+ EXPORT Vector2EC [WEAK]
+ EXPORT Vector2F0 [WEAK]
+ EXPORT Vector2F4 [WEAK]
+ EXPORT Vector2F8 [WEAK]
+ EXPORT Vector2FC [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 176
+ EXPORT Vector300 [WEAK]
+ EXPORT Vector304 [WEAK]
+ EXPORT Vector308 [WEAK]
+ EXPORT Vector30C [WEAK]
+ EXPORT Vector310 [WEAK]
+ EXPORT Vector314 [WEAK]
+ EXPORT Vector318 [WEAK]
+ EXPORT Vector31C [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 184
+ EXPORT Vector320 [WEAK]
+ EXPORT Vector324 [WEAK]
+ EXPORT Vector328 [WEAK]
+ EXPORT Vector32C [WEAK]
+ EXPORT Vector330 [WEAK]
+ EXPORT Vector334 [WEAK]
+ EXPORT Vector338 [WEAK]
+ EXPORT Vector33C [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 192
+ EXPORT Vector340 [WEAK]
+ EXPORT Vector344 [WEAK]
+ EXPORT Vector348 [WEAK]
+ EXPORT Vector34C [WEAK]
+ EXPORT Vector350 [WEAK]
+ EXPORT Vector354 [WEAK]
+ EXPORT Vector358 [WEAK]
+ EXPORT Vector35C [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 200
+ EXPORT Vector360 [WEAK]
+ EXPORT Vector364 [WEAK]
+ EXPORT Vector368 [WEAK]
+ EXPORT Vector36C [WEAK]
+ EXPORT Vector370 [WEAK]
+ EXPORT Vector374 [WEAK]
+ EXPORT Vector378 [WEAK]
+ EXPORT Vector37C [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 208
+ EXPORT Vector380 [WEAK]
+ EXPORT Vector384 [WEAK]
+ EXPORT Vector388 [WEAK]
+ EXPORT Vector38C [WEAK]
+ EXPORT Vector390 [WEAK]
+ EXPORT Vector394 [WEAK]
+ EXPORT Vector398 [WEAK]
+ EXPORT Vector39C [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 216
+ EXPORT Vector3A0 [WEAK]
+ EXPORT Vector3A4 [WEAK]
+ EXPORT Vector3A8 [WEAK]
+ EXPORT Vector3AC [WEAK]
+ EXPORT Vector3B0 [WEAK]
+ EXPORT Vector3B4 [WEAK]
+ EXPORT Vector3B8 [WEAK]
+ EXPORT Vector3BC [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 224
+ EXPORT Vector3C0 [WEAK]
+ EXPORT Vector3C4 [WEAK]
+ EXPORT Vector3C8 [WEAK]
+ EXPORT Vector3CC [WEAK]
+ EXPORT Vector3D0 [WEAK]
+ EXPORT Vector3D4 [WEAK]
+ EXPORT Vector3D8 [WEAK]
+ EXPORT Vector3DC [WEAK]
+#endif
+#if CORTEX_NUM_VECTORS > 232
+ EXPORT Vector3E0 [WEAK]
+ EXPORT Vector3E4 [WEAK]
+ EXPORT Vector3E8 [WEAK]
+ EXPORT Vector3EC [WEAK]
+ EXPORT Vector3F0 [WEAK]
+ EXPORT Vector3F4 [WEAK]
+ EXPORT Vector3F8 [WEAK]
+ EXPORT Vector3FC [WEAK]
+#endif
+
+NMI_Handler
+HardFault_Handler
+MemManage_Handler
+BusFault_Handler
+UsageFault_Handler
+Vector1C
+Vector20
+Vector24
+Vector28
+SVC_Handler
+DebugMon_Handler
+Vector34
+PendSV_Handler
+SysTick_Handler
+Vector40
+Vector44
+Vector48
+Vector4C
+Vector50
+Vector54
+Vector58
+Vector5C
+#if CORTEX_NUM_VECTORS > 8
+Vector60
+Vector64
+Vector68
+Vector6C
+Vector70
+Vector74
+Vector78
+Vector7C
+#endif
+#if CORTEX_NUM_VECTORS > 16
+Vector80
+Vector84
+Vector88
+Vector8C
+Vector90
+Vector94
+Vector98
+Vector9C
+#endif
+#if CORTEX_NUM_VECTORS > 24
+VectorA0
+VectorA4
+VectorA8
+VectorAC
+VectorB0
+VectorB4
+VectorB8
+VectorBC
+#endif
+#if CORTEX_NUM_VECTORS > 32
+VectorC0
+VectorC4
+VectorC8
+VectorCC
+VectorD0
+VectorD4
+VectorD8
+VectorDC
+#endif
+#if CORTEX_NUM_VECTORS > 40
+VectorE0
+VectorE4
+VectorE8
+VectorEC
+VectorF0
+VectorF4
+VectorF8
+VectorFC
+#endif
+#if CORTEX_NUM_VECTORS > 48
+Vector100
+Vector104
+Vector108
+Vector10C
+Vector110
+Vector114
+Vector118
+Vector11C
+#endif
+#if CORTEX_NUM_VECTORS > 56
+Vector120
+Vector124
+Vector128
+Vector12C
+Vector130
+Vector134
+Vector138
+Vector13C
+#endif
+#if CORTEX_NUM_VECTORS > 64
+Vector140
+Vector144
+Vector148
+Vector14C
+Vector150
+Vector154
+Vector158
+Vector15C
+#endif
+#if CORTEX_NUM_VECTORS > 72
+Vector160
+Vector164
+Vector168
+Vector16C
+Vector170
+Vector174
+Vector178
+Vector17C
+#endif
+#if CORTEX_NUM_VECTORS > 80
+Vector180
+Vector184
+Vector188
+Vector18C
+Vector190
+Vector194
+Vector198
+Vector19C
+#endif
+#if CORTEX_NUM_VECTORS > 88
+Vector1A0
+Vector1A4
+Vector1A8
+Vector1AC
+Vector1B0
+Vector1B4
+Vector1B8
+Vector1BC
+#endif
+#if CORTEX_NUM_VECTORS > 96
+Vector1C0
+Vector1C4
+Vector1C8
+Vector1CC
+Vector1D0
+Vector1D4
+Vector1D8
+Vector1DC
+#endif
+#if CORTEX_NUM_VECTORS > 104
+Vector1E0
+Vector1E4
+Vector1E8
+Vector1EC
+Vector1F0
+Vector1F4
+Vector1F8
+Vector1FC
+#endif
+#if CORTEX_NUM_VECTORS > 112
+Vector200
+Vector204
+Vector208
+Vector20C
+Vector210
+Vector214
+Vector218
+Vector21C
+#endif
+#if CORTEX_NUM_VECTORS > 120
+Vector220
+Vector224
+Vector228
+Vector22C
+Vector230
+Vector234
+Vector238
+Vector23C
+#endif
+#if CORTEX_NUM_VECTORS > 128
+Vector240
+Vector244
+Vector248
+Vector24C
+Vector250
+Vector254
+Vector258
+Vector25C
+#endif
+#if CORTEX_NUM_VECTORS > 136
+Vector260
+Vector264
+Vector268
+Vector26C
+Vector270
+Vector274
+Vector278
+Vector27C
+#endif
+#if CORTEX_NUM_VECTORS > 144
+Vector280
+Vector284
+Vector288
+Vector28C
+Vector290
+Vector294
+Vector298
+Vector29C
+#endif
+#if CORTEX_NUM_VECTORS > 152
+Vector2A0
+Vector2A4
+Vector2A8
+Vector2AC
+Vector2B0
+Vector2B4
+Vector2B8
+Vector2BC
+#endif
+#if CORTEX_NUM_VECTORS > 160
+Vector2C0
+Vector2C4
+Vector2C8
+Vector2CC
+Vector2D0
+Vector2D4
+Vector2D8
+Vector2DC
+#endif
+#if CORTEX_NUM_VECTORS > 168
+Vector2E0
+Vector2E4
+Vector2E8
+Vector2EC
+Vector2F0
+Vector2F4
+Vector2F8
+Vector2FC
+#endif
+#if CORTEX_NUM_VECTORS > 176
+Vector300
+Vector304
+Vector308
+Vector30C
+Vector310
+Vector314
+Vector318
+Vector31C
+#endif
+#if CORTEX_NUM_VECTORS > 184
+Vector320
+Vector324
+Vector328
+Vector32C
+Vector330
+Vector334
+Vector338
+Vector33C
+#endif
+#if CORTEX_NUM_VECTORS > 192
+Vector340
+Vector344
+Vector348
+Vector34C
+Vector350
+Vector354
+Vector358
+Vector35C
+#endif
+#if CORTEX_NUM_VECTORS > 200
+Vector360
+Vector364
+Vector368
+Vector36C
+Vector370
+Vector374
+Vector378
+Vector37C
+#endif
+#if CORTEX_NUM_VECTORS > 208
+Vector380
+Vector384
+Vector388
+Vector38C
+Vector390
+Vector394
+Vector398
+Vector39C
+#endif
+#if CORTEX_NUM_VECTORS > 216
+Vector3A0
+Vector3A4
+Vector3A8
+Vector3AC
+Vector3B0
+Vector3B4
+Vector3B8
+Vector3BC
+#endif
+#if CORTEX_NUM_VECTORS > 224
+Vector3C0
+Vector3C4
+Vector3C8
+Vector3CC
+Vector3D0
+Vector3D4
+Vector3D8
+Vector3DC
+#endif
+#if CORTEX_NUM_VECTORS > 232
+Vector3E0
+Vector3E4
+Vector3E8
+Vector3EC
+Vector3F0
+Vector3F4
+Vector3F8
+Vector3FC
+#endif
+ b _unhandled_exception
+ ENDP
+
+ END
+
+#endif /* !defined(__DOXYGEN__) */
+
+/**< @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/ADUCM36x/cmparams.h b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/ADUCM36x/cmparams.h
new file mode 100644
index 0000000..cd712bd
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/ADUCM36x/cmparams.h
@@ -0,0 +1,84 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F2xx/cmparams.h
+ * @brief ARM Cortex-M3 parameters for the STM32F2xx.
+ *
+ * @defgroup ARMCMx_STM32F2xx STM32F2xx Specific Parameters
+ * @ingroup ARMCMx_SPECIFIC
+ * @details This file contains the Cortex-M3 specific parameters for the
+ * STM32F2xx platform.
+ * @{
+ */
+
+#ifndef CMPARAMS_H
+#define CMPARAMS_H
+
+/**
+ * @brief Cortex core model.
+ */
+#define CORTEX_MODEL 3
+
+/**
+ * @brief Floating Point unit presence.
+ */
+#define CORTEX_HAS_FPU 0
+
+/**
+ * @brief Number of bits in priority masks.
+ */
+#define CORTEX_PRIORITY_BITS 3
+
+/* If the device type is not externally defined, for example from the Makefile,
+ then a file named board.h is included. This file must contain a device
+ definition compatible with the vendor include file.*/
+#if !defined(ADUCM36X)
+#include "board.h"
+#endif
+
+/**
+ * @brief Number of interrupt vectors.
+ * @note This number does not include the 16 system vectors and must be
+ * rounded to a multiple of 8.
+ */
+#define CORTEX_NUM_VECTORS 40
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/* Including the device CMSIS header. Note, we are not using the definitions
+ from this header because we need this file to be usable also from
+ assembler source files. We verify that the info matches instead.*/
+#include "ADuCM36x.h"
+
+/*lint -save -e9029 [10.4] Signedness comes from external files, it is
+ unpredictable but gives no problems.*/
+#if CORTEX_MODEL != __CORTEX_M
+#error "CMSIS __CORTEX_M mismatch"
+#endif
+
+#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS
+#error "CMSIS __NVIC_PRIO_BITS mismatch"
+#endif
+/*lint -restore*/
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CMPARAMS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/ADUCM41x/cmparams.h b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/ADUCM41x/cmparams.h
new file mode 100644
index 0000000..536b70e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/ADUCM41x/cmparams.h
@@ -0,0 +1,89 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ADUCM41x/cmparams.h
+ * @brief ARM Cortex-M4 parameters for the ADUCM41x.
+ *
+ * @defgroup ARMCMx_ADUCM41x ADUCM41x Specific Parameters
+ * @ingroup ARMCMx_SPECIFIC
+ * @details This file contains the Cortex-M33 specific parameters for the
+ * ADUCM41x platform.
+ * @{
+ */
+
+#ifndef CMPARAMS_H
+#define CMPARAMS_H
+
+/**
+ * @brief Cortex core model.
+ * @todo Switch to M33 when port is done.
+ */
+#define CORTEX_MODEL 4
+
+/**
+ * @brief Floating Point unit presence.
+ */
+#define CORTEX_HAS_FPU 1
+
+/**
+ * @brief Number of bits in priority masks.
+ */
+#define CORTEX_PRIORITY_BITS 3
+
+/* If the device type is not externally defined, for example from the Makefile,
+ then a file named board.h is included. This file must contain a device
+ definition compatible with the vendor include file.*/
+#if !defined(ADUCM41X)
+#include "board.h"
+#endif
+
+/**
+ * @brief Number of interrupt vectors.
+ * @note This number does not include the 16 system vectors and must be
+ * rounded to a multiple of 8.
+ */
+#define CORTEX_NUM_VECTORS 80
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/* Including the device CMSIS header. Note, we are not using the definitions
+ from this header because we need this file to be usable also from
+ assembler source files. We verify that the info matches instead.*/
+#include "aducm41x.h"
+
+/*lint -save -e9029 [10.4] Signedness comes from external files, it is
+ unpredictable but gives no problems.*/
+#if CORTEX_MODEL != __CORTEX_M
+#error "CMSIS __CORTEX_M mismatch"
+#endif
+
+#if CORTEX_HAS_FPU != __FPU_PRESENT
+#error "CMSIS __FPU_PRESENT mismatch"
+#endif
+
+#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS
+#error "CMSIS __NVIC_PRIO_BITS mismatch"
+#endif
+/*lint -restore*/
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CMPARAMS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32F0xx/cmparams.h b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32F0xx/cmparams.h
new file mode 100644
index 0000000..a5ffdcf
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32F0xx/cmparams.h
@@ -0,0 +1,93 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F0xx/cmparams.h
+ * @brief ARM Cortex-M0 parameters for the STM32F0xx.
+ *
+ * @defgroup ARMCMx_STM32F0xx STM32F0xx Specific Parameters
+ * @ingroup ARMCMx_SPECIFIC
+ * @details This file contains the Cortex-M0 specific parameters for the
+ * STM32F0xx platform.
+ * @{
+ */
+
+#ifndef CMPARAMS_H
+#define CMPARAMS_H
+
+/**
+ * @brief Cortex core model.
+ */
+#define CORTEX_MODEL 0
+
+/**
+ * @brief Floating Point unit presence.
+ */
+#define CORTEX_HAS_FPU 0
+
+/**
+ * @brief Number of bits in priority masks.
+ */
+#define CORTEX_PRIORITY_BITS 2
+
+/* If the device type is not externally defined, for example from the Makefile,
+ then a file named board.h is included. This file must contain a device
+ definition compatible with the vendor include file.*/
+#if !defined (STM32F030x4) && !defined (STM32F030x6) && \
+ !defined (STM32F030x8) && !defined (STM32F030xC) && \
+ !defined (STM32F070x6) && !defined (STM32F070xB) && \
+ !defined (STM32F031x6) && !defined (STM32F051x8) && \
+ !defined (STM32F071xB) && !defined (STM32F091xC) && \
+ !defined (STM32F042x6) && !defined (STM32F072xB) && \
+ !defined (STM32F038xx) && !defined (STM32F048xx) && \
+ !defined (STM32F058xx) && !defined (STM32F078xx) && \
+ !defined (STM32F098xx) \
+
+#include "board.h"
+#endif
+
+/**
+ * @brief Number of interrupt vectors.
+ * @note This number does not include the 16 system vectors and must be
+ * rounded to a multiple of 8.
+ */
+#define CORTEX_NUM_VECTORS 32
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/* Including the device CMSIS header. Note, we are not using the definitions
+ from this header because we need this file to be usable also from
+ assembler source files. We verify that the info matches instead.*/
+#include "stm32f0xx.h"
+
+/*lint -save -e9029 [10.4] Signedness comes from external files, it is
+ unpredictable but gives no problems.*/
+#if CORTEX_MODEL != __CORTEX_M
+#error "CMSIS __CORTEX_M mismatch"
+#endif
+
+#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS
+#error "CMSIS __NVIC_PRIO_BITS mismatch"
+#endif
+/*lint -restore*/
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CMPARAMS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32F1xx/cmparams.h b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32F1xx/cmparams.h
new file mode 100644
index 0000000..8ac35ed
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32F1xx/cmparams.h
@@ -0,0 +1,90 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F1xx/cmparams.h
+ * @brief ARM Cortex-M3 parameters for the STM32F1xx.
+ *
+ * @defgroup ARMCMx_STM32F1xx STM32F1xx Specific Parameters
+ * @ingroup ARMCMx_SPECIFIC
+ * @details This file contains the Cortex-M4 specific parameters for the
+ * STM32F1xx platform.
+ * @{
+ */
+
+#ifndef CMPARAMS_H
+#define CMPARAMS_H
+
+/**
+ * @brief Cortex core model.
+ */
+#define CORTEX_MODEL 3
+
+/**
+ * @brief Floating Point unit presence.
+ */
+#define CORTEX_HAS_FPU 0
+
+/**
+ * @brief Number of bits in priority masks.
+ */
+#define CORTEX_PRIORITY_BITS 4
+
+/* If the device type is not externally defined, for example from the Makefile,
+ then a file named board.h is included. This file must contain a device
+ definition compatible with the vendor include file.*/
+#if !defined(STM32F100xB) && !defined(STM32F100xE) && \
+ !defined(STM32F101x6) && !defined(STM32F101xB) && \
+ !defined(STM32F101xE) && !defined(STM32F101xG) && \
+ !defined(STM32F102x6) && !defined(STM32F102xB) && \
+ !defined(STM32F103x6) && !defined(STM32F103xB) && \
+ !defined(STM32F103xE) && !defined(STM32F103xG) && \
+ !defined(STM32F105xC) && !defined(STM32F107xC)
+#include "board.h"
+#endif
+
+/**
+ * @brief Number of interrupt vectors.
+ * @note This number does not include the 16 system vectors and must be
+ * rounded to a multiple of 8.
+ */
+#define CORTEX_NUM_VECTORS 72
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/* Including the device CMSIS header. Note, we are not using the definitions
+ from this header because we need this file to be usable also from
+ assembler source files. We verify that the info matches instead.*/
+#include "stm32f1xx.h"
+
+/*lint -save -e9029 [10.4] Signedness comes from external files, it is
+ unpredictable but gives no problems.*/
+#if CORTEX_MODEL != __CORTEX_M
+#error "CMSIS __CORTEX_M mismatch"
+#endif
+
+#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS
+#error "CMSIS __NVIC_PRIO_BITS mismatch"
+#endif
+/*lint -restore*/
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CMPARAMS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32F2xx/cmparams.h b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32F2xx/cmparams.h
new file mode 100644
index 0000000..0451134
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32F2xx/cmparams.h
@@ -0,0 +1,84 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F2xx/cmparams.h
+ * @brief ARM Cortex-M3 parameters for the STM32F2xx.
+ *
+ * @defgroup ARMCMx_STM32F2xx STM32F2xx Specific Parameters
+ * @ingroup ARMCMx_SPECIFIC
+ * @details This file contains the Cortex-M3 specific parameters for the
+ * STM32F2xx platform.
+ * @{
+ */
+
+#ifndef CMPARAMS_H
+#define CMPARAMS_H
+
+/**
+ * @brief Cortex core model.
+ */
+#define CORTEX_MODEL 3
+
+/**
+ * @brief Floating Point unit presence.
+ */
+#define CORTEX_HAS_FPU 0
+
+/**
+ * @brief Number of bits in priority masks.
+ */
+#define CORTEX_PRIORITY_BITS 4
+
+/* If the device type is not externally defined, for example from the Makefile,
+ then a file named board.h is included. This file must contain a device
+ definition compatible with the vendor include file.*/
+#if !defined(STM32F2XX)
+#include "board.h"
+#endif
+
+/**
+ * @brief Number of interrupt vectors.
+ * @note This number does not include the 16 system vectors and must be
+ * rounded to a multiple of 8.
+ */
+#define CORTEX_NUM_VECTORS 96
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/* Including the device CMSIS header. Note, we are not using the definitions
+ from this header because we need this file to be usable also from
+ assembler source files. We verify that the info matches instead.*/
+#include "stm32f2xx.h"
+
+/*lint -save -e9029 [10.4] Signedness comes from external files, it is
+ unpredictable but gives no problems.*/
+#if CORTEX_MODEL != __CORTEX_M
+#error "CMSIS __CORTEX_M mismatch"
+#endif
+
+#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS
+#error "CMSIS __NVIC_PRIO_BITS mismatch"
+#endif
+/*lint -restore*/
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CMPARAMS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32F3xx/cmparams.h b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32F3xx/cmparams.h
new file mode 100644
index 0000000..8c2877e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32F3xx/cmparams.h
@@ -0,0 +1,93 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F3xx/cmparams.h
+ * @brief ARM Cortex-M4 parameters for the STM32F3xx.
+ *
+ * @defgroup ARMCMx_STM32F3xx STM32F3xx Specific Parameters
+ * @ingroup ARMCMx_SPECIFIC
+ * @details This file contains the Cortex-M4 specific parameters for the
+ * STM32F3xx platform.
+ * @{
+ */
+
+#ifndef CMPARAMS_H
+#define CMPARAMS_H
+
+/**
+ * @brief Cortex core model.
+ */
+#define CORTEX_MODEL 4
+
+/**
+ * @brief Floating Point unit presence.
+ */
+#define CORTEX_HAS_FPU 1
+
+/**
+ * @brief Number of bits in priority masks.
+ */
+#define CORTEX_PRIORITY_BITS 4
+
+/* If the device type is not externally defined, for example from the Makefile,
+ then a file named board.h is included. This file must contain a device
+ definition compatible with the vendor include file.*/
+#if !defined (STM32F301x8) && !defined (STM32F318xx) && \
+ !defined (STM32F302x8) && !defined (STM32F302xC) && \
+ !defined (STM32F303x8) && !defined (STM32F303xC) && \
+ !defined (STM32F358xx) && !defined (STM32F334x8) && \
+ !defined (STM32F328xx) && \
+ !defined (STM32F373xC) && !defined (STM32F378xx)
+#include "board.h"
+#endif
+
+/**
+ * @brief Number of interrupt vectors.
+ * @note This number does not include the 16 system vectors and must be
+ * rounded to a multiple of 8.
+ */
+#define CORTEX_NUM_VECTORS 88
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/* Including the device CMSIS header. Note, we are not using the definitions
+ from this header because we need this file to be usable also from
+ assembler source files. We verify that the info matches instead.*/
+#include "stm32f3xx.h"
+
+/*lint -save -e9029 [10.4] Signedness comes from external files, it is
+ unpredictable but gives no problems.*/
+#if CORTEX_MODEL != __CORTEX_M
+#error "CMSIS __CORTEX_M mismatch"
+#endif
+
+#if CORTEX_HAS_FPU != __FPU_PRESENT
+#error "CMSIS __FPU_PRESENT mismatch"
+#endif
+
+#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS
+#error "CMSIS __NVIC_PRIO_BITS mismatch"
+#endif
+/*lint -restore*/
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CMPARAMS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32F4xx/cmparams.h b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32F4xx/cmparams.h
new file mode 100644
index 0000000..1fa5e8c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32F4xx/cmparams.h
@@ -0,0 +1,100 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F4xx/cmparams.h
+ * @brief ARM Cortex-M4 parameters for the STM32F4xx.
+ *
+ * @defgroup ARMCMx_STM32F4xx STM32F4xx Specific Parameters
+ * @ingroup ARMCMx_SPECIFIC
+ * @details This file contains the Cortex-M4 specific parameters for the
+ * STM32F4xx platform.
+ * @{
+ */
+
+#ifndef CMPARAMS_H
+#define CMPARAMS_H
+
+/**
+ * @brief Cortex core model.
+ */
+#define CORTEX_MODEL 4
+
+/**
+ * @brief Floating Point unit presence.
+ */
+#define CORTEX_HAS_FPU 1
+
+/**
+ * @brief Number of bits in priority masks.
+ */
+#define CORTEX_PRIORITY_BITS 4
+
+/* If the device type is not externally defined, for example from the Makefile,
+ then a file named board.h is included. This file must contain a device
+ definition compatible with the vendor include file.*/
+#if !defined(STM32F405xx) && !defined(STM32F415xx) && \
+ !defined(STM32F407xx) && !defined(STM32F417xx) && \
+ !defined(STM32F427xx) && !defined(STM32F437xx) && \
+ !defined(STM32F429xx) && !defined(STM32F439xx) && \
+ !defined(STM32F401xC) && !defined(STM32F401xE) && \
+ !defined(STM32F410Cx) && !defined(STM32F410Rx) && \
+ !defined(STM32F410Tx) && \
+ !defined(STM32F411xE) && \
+ !defined(STM32F412Cx) && !defined(STM32F412Rx) && \
+ !defined(STM32F412Vx) && !defined(STM32F412Zx) && \
+ !defined(STM32F413xx) && \
+ !defined(STM32F446xx) && \
+ !defined(STM32F469xx) && !defined(STM32F479xx)
+#include "board.h"
+#endif
+
+/**
+ * @brief Number of interrupt vectors.
+ * @note This number does not include the 16 system vectors and must be
+ * rounded to a multiple of 8.
+ */
+#define CORTEX_NUM_VECTORS 104
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/* Including the device CMSIS header. Note, we are not using the definitions
+ from this header because we need this file to be usable also from
+ assembler source files. We verify that the info matches instead.*/
+#include "stm32f4xx.h"
+
+/*lint -save -e9029 [10.4] Signedness comes from external files, it is
+ unpredictable but gives no problems.*/
+#if CORTEX_MODEL != __CORTEX_M
+#error "CMSIS __CORTEX_M mismatch"
+#endif
+
+#if CORTEX_HAS_FPU != __FPU_PRESENT
+#error "CMSIS __FPU_PRESENT mismatch"
+#endif
+
+#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS
+#error "CMSIS __NVIC_PRIO_BITS mismatch"
+#endif
+/*lint -restore*/
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CMPARAMS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32F7xx/cmparams.h b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32F7xx/cmparams.h
new file mode 100644
index 0000000..fae6394
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32F7xx/cmparams.h
@@ -0,0 +1,93 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F7xx/cmparams.h
+ * @brief ARM Cortex-M7 parameters for the STM32F4xx.
+ *
+ * @defgroup ARMCMx_STM32F7xx STM32F7xx Specific Parameters
+ * @ingroup ARMCMx_SPECIFIC
+ * @details This file contains the Cortex-M7 specific parameters for the
+ * STM32F7xx platform.
+ * @{
+ */
+
+#ifndef CMPARAMS_H
+#define CMPARAMS_H
+
+/**
+ * @brief Cortex core model.
+ */
+#define CORTEX_MODEL 7
+
+/**
+ * @brief Floating Point unit presence.
+ */
+#define CORTEX_HAS_FPU 1
+
+/**
+ * @brief Number of bits in priority masks.
+ */
+#define CORTEX_PRIORITY_BITS 4
+
+/* If the device type is not externally defined, for example from the Makefile,
+ then a file named board.h is included. This file must contain a device
+ definition compatible with the vendor include file.*/
+#if !defined(STM32F722xx) && !defined(STM32F723xx) && \
+ !defined(STM32F732xx) && !defined(STM32F733xx) && \
+ !defined(STM32F745xx) && !defined(STM32F746xx) && \
+ !defined(STM32F756xx) && !defined(STM32F765xx) && \
+ !defined(STM32F767xx) && !defined(STM32F769xx) && \
+ !defined(STM32F777xx) && !defined(STM32F779xx)
+#include "board.h"
+#endif
+
+/**
+ * @brief Number of interrupt vectors.
+ * @note This number does not include the 16 system vectors and must be
+ * rounded to a multiple of 8.
+ */
+#define CORTEX_NUM_VECTORS 112
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/* Including the device CMSIS header. Note, we are not using the definitions
+ from this header because we need this file to be usable also from
+ assembler source files. We verify that the info matches instead.*/
+#include "stm32f7xx.h"
+
+/*lint -save -e9029 [10.4] Signedness comes from external files, it is
+ unpredictable but gives no problems.*/
+#if CORTEX_MODEL != __CORTEX_M
+#error "CMSIS __CORTEX_M mismatch"
+#endif
+
+#if CORTEX_HAS_FPU != __FPU_PRESENT
+#error "CMSIS __FPU_PRESENT mismatch"
+#endif
+
+#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS
+#error "CMSIS __NVIC_PRIO_BITS mismatch"
+#endif
+/*lint -restore*/
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CMPARAMS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32G0xx/cmparams.h b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32G0xx/cmparams.h
new file mode 100644
index 0000000..83121a3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32G0xx/cmparams.h
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32G0xx/cmparams.h
+ * @brief ARM Cortex-M0 parameters for the STM32G0xx.
+ *
+ * @defgroup ARMCMx_STM32G0xx STM32G0xx Specific Parameters
+ * @ingroup ARMCMx_SPECIFIC
+ * @details This file contains the Cortex-M0 specific parameters for the
+ * STM32G0xx platform.
+ * @{
+ */
+
+#ifndef CMPARAMS_H
+#define CMPARAMS_H
+
+/**
+ * @brief Cortex core model.
+ */
+#define CORTEX_MODEL 0
+
+/**
+ * @brief Floating Point unit presence.
+ */
+#define CORTEX_HAS_FPU 0
+
+/**
+ * @brief Number of bits in priority masks.
+ */
+#define CORTEX_PRIORITY_BITS 2
+
+/* If the device type is not externally defined, for example from the Makefile,
+ then a file named board.h is included. This file must contain a device
+ definition compatible with the vendor include file.*/
+#if !defined (STM32G071xx) && !defined (STM32G081xx) && \
+ !defined (STM32G070xx)
+#include "board.h"
+#endif
+
+/**
+ * @brief Number of interrupt vectors.
+ * @note This number does not include the 16 system vectors and must be
+ * rounded to a multiple of 8.
+ */
+#define CORTEX_NUM_VECTORS 32
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/* Including the device CMSIS header. Note, we are not using the definitions
+ from this header because we need this file to be usable also from
+ assembler source files. We verify that the info matches instead.*/
+#include "stm32g0xx.h"
+
+/*lint -save -e9029 [10.4] Signedness comes from external files, it is
+ unpredictable but gives no problems.*/
+#if CORTEX_MODEL != __CORTEX_M
+#error "CMSIS __CORTEX_M mismatch"
+#endif
+
+#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS
+#error "CMSIS __NVIC_PRIO_BITS mismatch"
+#endif
+/*lint -restore*/
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CMPARAMS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32G4xx/cmparams.h b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32G4xx/cmparams.h
new file mode 100644
index 0000000..972f9df
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32G4xx/cmparams.h
@@ -0,0 +1,91 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32G4xx/cmparams.h
+ * @brief ARM Cortex-M4 parameters for the STM32G4xx.
+ *
+ * @defgroup ARMCMx_STM32FGxx STM32FGxx Specific Parameters
+ * @ingroup ARMCMx_SPECIFIC
+ * @details This file contains the Cortex-M4 specific parameters for the
+ * STM32G4xx platform.
+ * @{
+ */
+
+#ifndef CMPARAMS_H
+#define CMPARAMS_H
+
+/**
+ * @brief Cortex core model.
+ */
+#define CORTEX_MODEL 4
+
+/**
+ * @brief Floating Point unit presence.
+ */
+#define CORTEX_HAS_FPU 1
+
+/**
+ * @brief Number of bits in priority masks.
+ */
+#define CORTEX_PRIORITY_BITS 4
+
+/* If the device type is not externally defined, for example from the Makefile,
+ then a file named board.h is included. This file must contain a device
+ definition compatible with the vendor include file.*/
+#if !defined(STM32G431xx) && !defined(STM32G441xx) && \
+ !defined(STM32G471xx) && !defined(STM32G473xx) && \
+ !defined(STM32G474xx) && !defined(STM32G483xx) && \
+ !defined(STM32G484xx) && !defined(STM32GBK1CB)
+#include "board.h"
+#endif
+
+/**
+ * @brief Number of interrupt vectors.
+ * @note This number does not include the 16 system vectors and must be
+ * rounded to a multiple of 8.
+ */
+#define CORTEX_NUM_VECTORS 104
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/* Including the device CMSIS header. Note, we are not using the definitions
+ from this header because we need this file to be usable also from
+ assembler source files. We verify that the info matches instead.*/
+#include "stm32g4xx.h"
+
+/*lint -save -e9029 [10.4] Signedness comes from external files, it is
+ unpredictable but gives no problems.*/
+#if CORTEX_MODEL != __CORTEX_M
+#error "CMSIS __CORTEX_M mismatch"
+#endif
+
+#if CORTEX_HAS_FPU != __FPU_PRESENT
+#error "CMSIS __FPU_PRESENT mismatch"
+#endif
+
+#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS
+#error "CMSIS __NVIC_PRIO_BITS mismatch"
+#endif
+/*lint -restore*/
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CMPARAMS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32H7xx/cmparams.h b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32H7xx/cmparams.h
new file mode 100644
index 0000000..0854f36
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32H7xx/cmparams.h
@@ -0,0 +1,94 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32H7xx/cmparams.h
+ * @brief ARM Cortex-M7 parameters for the STM32F4xx.
+ *
+ * @defgroup ARMCMx_STM32H7xx STM32H7xx Specific Parameters
+ * @ingroup ARMCMx_SPECIFIC
+ * @details This file contains the Cortex-M7 specific parameters for the
+ * STM32H7xx platform.
+ * @{
+ */
+
+#ifndef CMPARAMS_H
+#define CMPARAMS_H
+
+/**
+ * @brief Cortex core model.
+ */
+#define CORTEX_MODEL 7
+
+/**
+ * @brief Floating Point unit presence.
+ */
+#define CORTEX_HAS_FPU 1
+
+/**
+ * @brief Number of bits in priority masks.
+ */
+#define CORTEX_PRIORITY_BITS 4
+
+/* If the device type is not externally defined, for example from the Makefile,
+ then a file named board.h is included. This file must contain a device
+ definition compatible with the vendor include file.*/
+#if !defined(STM32H742xx) && !defined(STM32H750xx) && \
+ !defined(STM32H743xx) && !defined(STM32H753xx) && \
+ !defined(STM32H747xx) && !defined(STM32H757xx) && \
+ !defined(STM32H745xx) && !defined(STM32H755xx) && \
+ !defined(STM32H7B0xx) && !defined(STM32H7B0xxQ) && \
+ !defined(STM32H7A3xx) && !defined(STM32H7A3xxQ) && \
+ !defined(STM32H7B3xx) && !defined(STM32H7B3xxQ)
+#include "board.h"
+#endif
+
+/**
+ * @brief Number of interrupt vectors.
+ * @note This number does not include the 16 system vectors and must be
+ * rounded to a multiple of 8.
+ */
+#define CORTEX_NUM_VECTORS 152
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/* Including the device CMSIS header. Note, we are not using the definitions
+ from this header because we need this file to be usable also from
+ assembler source files. We verify that the info matches instead.*/
+#include "stm32h7xx.h"
+
+/*lint -save -e9029 [10.4] Signedness comes from external files, it is
+ unpredictable but gives no problems.*/
+#if CORTEX_MODEL != __CORTEX_M
+#error "CMSIS __CORTEX_M mismatch"
+#endif
+
+#if CORTEX_HAS_FPU != __FPU_PRESENT
+#error "CMSIS __FPU_PRESENT mismatch"
+#endif
+
+#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS
+#error "CMSIS __NVIC_PRIO_BITS mismatch"
+#endif
+/*lint -restore*/
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CMPARAMS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32L0xx/cmparams.h b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32L0xx/cmparams.h
new file mode 100644
index 0000000..1913a67
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32L0xx/cmparams.h
@@ -0,0 +1,88 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32L0xx/cmparams.h
+ * @brief ARM Cortex-M0+ parameters for the STM32L0xx.
+ *
+ * @defgroup ARMCMx_STM32L0xx STM32L0xx Specific Parameters
+ * @ingroup ARMCMx_SPECIFIC
+ * @details This file contains the Cortex-M0 specific parameters for the
+ * STM32L0xx platform.
+ * @{
+ */
+
+#ifndef CMPARAMS_H
+#define CMPARAMS_H
+
+/**
+ * @brief Cortex core model.
+ */
+#define CORTEX_MODEL 0
+
+/**
+ * @brief Floating Point unit presence.
+ */
+#define CORTEX_HAS_FPU 0
+
+/**
+ * @brief Number of bits in priority masks.
+ */
+#define CORTEX_PRIORITY_BITS 2
+
+/* If the device type is not externally defined, for example from the Makefile,
+ then a file named board.h is included. This file must contain a device
+ definition compatible with the vendor include file.*/
+#if !defined(STM32L011xx) && !defined(STM32L031xx) && \
+ !defined(STM32L051xx) && !defined(STM32L052xx) && \
+ !defined(STM32L053xx) && !defined(STM32L061xx) && \
+ !defined(STM32L062xx) && !defined(STM32L063xx) && \
+ !defined(STM32L073xx)
+#include "board.h"
+#endif
+
+/**
+ * @brief Number of interrupt vectors.
+ * @note This number does not include the 16 system vectors and must be
+ * rounded to a multiple of 8.
+ */
+#define CORTEX_NUM_VECTORS 32
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/* Including the device CMSIS header. Note, we are not using the definitions
+ from this header because we need this file to be usable also from
+ assembler source files. We verify that the info matches instead.*/
+#include "stm32l0xx.h"
+
+/*lint -save -e9029 [10.4] Signedness comes from external files, it is
+ unpredictable but gives no problems.*/
+#if CORTEX_MODEL != __CORTEX_M
+#error "CMSIS __CORTEX_M mismatch"
+#endif
+
+#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS
+#error "CMSIS __NVIC_PRIO_BITS mismatch"
+#endif
+/*lint -restore*/
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CMPARAMS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32L1xx/cmparams.h b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32L1xx/cmparams.h
new file mode 100644
index 0000000..5b3f5f4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32L1xx/cmparams.h
@@ -0,0 +1,97 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32L1xx/cmparams.h
+ * @brief ARM Cortex-M3 parameters for the STM32L1xx.
+ *
+ * @defgroup ARMCMx_STM32L1xx STM32L1xx Specific Parameters
+ * @ingroup ARMCMx_SPECIFIC
+ * @details This file contains the Cortex-M3 specific parameters for the
+ * STM32L1xx platform.
+ * @{
+ */
+
+#ifndef CMPARAMS_H
+#define CMPARAMS_H
+
+/**
+ * @brief Cortex core model.
+ */
+#define CORTEX_MODEL 3
+
+/**
+ * @brief Floating Point unit presence.
+ */
+#define CORTEX_HAS_FPU 0
+
+/**
+ * @brief Number of bits in priority masks.
+ */
+#define CORTEX_PRIORITY_BITS 4
+
+/* If the device type is not externally defined, for example from the Makefile,
+ then a file named board.h is included. This file must contain a device
+ definition compatible with the vendor include file.*/
+#if !defined(STM32L100xB) && !defined(STM32L100xBA) && \
+ !defined(STM32L100xC) && !defined(STM32L151xB) && \
+ !defined(STM32L151xBA) && !defined(STM32L151xC) && \
+ !defined(STM32L151xCA) && !defined(STM32L151xD) && \
+ !defined(STM32L151xDX) && !defined(STM32L151xE) && \
+ !defined(STM32L152xB) && !defined(STM32L152xBA) && \
+ !defined(STM32L152xC) && !defined(STM32L152xCA) && \
+ !defined(STM32L152xD) && !defined(STM32L152xDX) && \
+ !defined(STM32L152xE) && !defined(STM32L162xC) && \
+ !defined(STM32L162xCA) && !defined(STM32L162xD) && \
+ !defined(STM32L162xDX) && !defined(STM32L162xE)
+#include "board.h"
+#endif
+
+/**
+ * @brief Number of interrupt vectors.
+ * @note This number does not include the 16 system vectors and must be
+ * rounded to a multiple of 8.
+ */
+#define CORTEX_NUM_VECTORS 64
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/* Including the device CMSIS header. Note, we are not using the definitions
+ from this header because we need this file to be usable also from
+ assembler source files. We verify that the info matches instead.*/
+#include "stm32l1xx.h"
+
+/*lint -save -e9029 [10.4] Signedness comes from external files, it is
+ unpredictable but gives no problems.*/
+#if CORTEX_MODEL != __CORTEX_M
+#error "CMSIS __CORTEX_M mismatch"
+#endif
+
+#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS
+#error "CMSIS __NVIC_PRIO_BITS mismatch"
+#endif
+/*lint -restore*/
+
+/* Fix for yet another consistency error in ST headers.*/
+#define SVCall_IRQn SVC_IRQn
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CMPARAMS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32L4xx/cmparams.h b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32L4xx/cmparams.h
new file mode 100644
index 0000000..c55fcc1
--- /dev/null
+++ b/ChibiOS_20.3.2/os/common/startup/ARMCMx/devices/STM32L4xx/cmparams.h
@@ -0,0 +1,104 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32L4xx/cmparams.h
+ * @brief ARM Cortex-M4 parameters for the STM32L4xx.
+ *
+ * @defgroup ARMCMx_STM32L4xx STM32L4xx Specific Parameters
+ * @ingroup ARMCMx_SPECIFIC
+ * @details This file contains the Cortex-M4 specific parameters for the
+ * STM32L4xx platform.
+ * @{
+ */
+
+#ifndef CMPARAMS_H
+#define CMPARAMS_H
+
+/**
+ * @brief Cortex core model.
+ */
+#define CORTEX_MODEL 4
+
+/**
+ * @brief Floating Point unit presence.
+ */
+#define CORTEX_HAS_FPU 1
+
+/**
+ * @brief Number of bits in priority masks.
+ */
+#define CORTEX_PRIORITY_BITS 4
+
+/* If the device type is not externally defined, for example from the Makefile,
+ then a file named board.h is included. This file must contain a device
+ definition compatible with the vendor include file.*/
+#if !defined(STM32L431xx) && !defined(STM32L432xx) && \
+ !defined(STM32L433xx) && !defined(STM32L442xx) && \
+ !defined(STM32L443xx) && !defined(STM32L451xx) && \
+ !defined(STM32L452xx) && !defined(STM32L462xx) && \
+ !defined(STM32L471xx) && !defined(STM32L475xx) && \
+ !defined(STM32L476xx) && !defined(STM32L485xx) && \
+ !defined(STM32L486xx) && !defined(STM32L496xx) && \
+ !defined(STM32L4A6xx) && \
+ !defined(STM32L4R5xx) && !defined(STM32L4R7xx) && \
+ !defined(STM32L4R9xx) && !defined(STM32L4S5xx) && \
+ !defined(STM32L4S7xx) && !defined(STM32L4S9xx)
+#include "board.h"
+#endif
+
+/**
+ * @brief Number of interrupt vectors.
+ * @note This number does not include the 16 system vectors and must be
+ * rounded to a multiple of 8.
+ */
+#if defined(STM32L496xx) || defined(STM32L4A6xx) || defined(STM32L4R5xx) || \
+ defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || \
+ defined(STM32L4S7xx) || defined(STM32L4S9xx)
+#define CORTEX_NUM_VECTORS 96
+#else
+#define CORTEX_NUM_VECTORS 88
+#endif
+
+/* The following code is not processed when the file is included from an
+ asm module.*/
+#if !defined(_FROM_ASM_)
+
+/* Including the device CMSIS header. Note, we are not using the definitions
+ from this header because we need this file to be usable also from
+ assembler source files. We verify that the info matches instead.*/
+#include "stm32l4xx.h"
+
+/*lint -save -e9029 [10.4] Signedness comes from external files, it is
+ unpredictable but gives no problems.*/
+#if CORTEX_MODEL != __CORTEX_M
+#error "CMSIS __CORTEX_M mismatch"
+#endif
+
+#if CORTEX_HAS_FPU != __FPU_PRESENT
+#error "CMSIS __FPU_PRESENT mismatch"
+#endif
+
+#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS
+#error "CMSIS __NVIC_PRIO_BITS mismatch"
+#endif
+/*lint -restore*/
+
+#endif /* !defined(_FROM_ASM_) */
+
+#endif /* CMPARAMS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/Bosch/bmp085.c b/ChibiOS_20.3.2/os/ex/devices/Bosch/bmp085.c
new file mode 100644
index 0000000..61f6d13
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/Bosch/bmp085.c
@@ -0,0 +1,788 @@
+/*
+ ChibiOS - Copyright (C) 2016..2017 Theodore Ateba
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file bmp085.c
+ * @brief BMP085 Digital pressure sensor interface module code.
+ *
+ * @addtogroup BMP085
+ * @ingroup EX_BOSCH
+ * @{
+ */
+
+#include "hal.h"
+#include "bmp085.h"
+
+/*==========================================================================*/
+/* Driver local definitions. */
+/*==========================================================================*/
+
+#define BMP085_SAD 0x77
+
+#define BMP085_CR_P_VAL0 0x34
+#define BMP085_CR_P_VAL1 0x74
+#define BMP085_CR_P_VAL2 0xB4
+#define BMP085_CR_P_VAL3 0xF4
+
+#define BMP085_CR_T_VAL 0x2E
+
+/*==========================================================================*/
+/* Driver exported variables. */
+/*==========================================================================*/
+
+/*==========================================================================*/
+/* Driver local variables and types. */
+/*==========================================================================*/
+
+/*==========================================================================*/
+/* Driver local functions. */
+/*==========================================================================*/
+
+#if (BMP085_USE_I2C) || defined(__DOXYGEN__)
+/**
+ * @brief Reads registers value using I2C.
+ * @pre The I2C interface must be initialized and the driver started.
+ *
+ * @param[in] i2cp pointer to the I2C interface
+ * @param[in] reg first sub-register address
+ * @param[out] rxbufp pointer to an output buffer
+ * @param[in] n number of consecutive register to read
+ *
+ * @return the operation status
+ * @notapi
+ */
+msg_t bmp085I2CReadRegister(I2CDriver *i2cp, uint8_t reg, uint8_t *rxbufp,
+ size_t n) {
+ uint8_t txbuf = reg;
+
+ return i2cMasterTransmitTimeout(i2cp, BMP085_SAD, &txbuf, 1, rxbufp, n,
+ TIME_INFINITE);
+}
+
+/**
+ * @brief Writes a value into a register using I2C.
+ * @pre The I2C interface must be initialized and the driver started.
+ *
+ * @param[in] i2cp pointer to the I2C interface
+ * @param[in] txbufp buffer containing sub-address value in first position
+ * and values to write
+ * @param[in] n size of txbuf less one (not considering the first
+ * element)
+ *
+ * @return the operation status
+ * @notapi
+ */
+msg_t bmp085I2CWriteRegister(I2CDriver *i2cp, uint8_t *txbufp, size_t n) {
+
+ return i2cMasterTransmitTimeout(i2cp, BMP085_SAD, txbufp, n + 1, NULL, 0,
+ TIME_INFINITE);
+}
+#endif /* BMP085_USE_I2C */
+
+/**
+ * @brief Read all the calibration data from the BMP085 EEPROM.
+ * @pre The I2C interface must be initialized and the driver started.
+ *
+ * @param[in] devp pointer to the BMP085 device driver sensor
+ * @param[in] reg first calibration coefficient register to read
+ *
+ * @return msg the operation status
+ */
+static msg_t bmp085ReadCoefficient(BMP085Driver *devp, uint8_t reg) {
+
+ uint8_t rxbuf[22];
+
+#if BMP085_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+#endif /* BMP085_SHARED_I2C */
+
+ msg_t msg = bmp085I2CReadRegister(devp->config->i2cp, reg, rxbuf, 22);
+
+#if BMP085_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* BMP085_SHARED_I2C */
+
+ if (msg == MSG_OK) {
+ devp->calibrationdata.ac1 = ((rxbuf[ 0] << 8) | rxbuf[ 1]);
+ devp->calibrationdata.ac2 = ((rxbuf[ 2] << 8) | rxbuf[ 3]);
+ devp->calibrationdata.ac3 = ((rxbuf[ 4] << 8) | rxbuf[ 5]);
+ devp->calibrationdata.ac4 = ((rxbuf[ 6] << 8) | rxbuf[ 7]);
+ devp->calibrationdata.ac5 = ((rxbuf[ 8] << 8) | rxbuf[ 9]);
+ devp->calibrationdata.ac6 = ((rxbuf[10] << 8) | rxbuf[11]);
+ devp->calibrationdata.b1 = ((rxbuf[12] << 8) | rxbuf[13]);
+ devp->calibrationdata.b2 = ((rxbuf[14] << 8) | rxbuf[15]);
+ devp->calibrationdata.mb = ((rxbuf[16] << 8) | rxbuf[17]);
+ devp->calibrationdata.mc = ((rxbuf[18] << 8) | rxbuf[19]);
+ devp->calibrationdata.md = ((rxbuf[20] << 8) | rxbuf[21]);
+ }
+
+ return msg;
+}
+
+/**
+ * @brief Calcul the true temperature.
+ *
+ * @param[in] devp pointer to the BMP085 device driver sensor
+ * @param[in] ut uncompensated temperature
+ * @param[out] ctp pointer of the compensated temperature
+ */
+static void calcul_t(BMP085Driver *devp, int32_t ut, float *ctp) {
+
+ int32_t x1, x2;
+
+ /* Converting the temperature value. */
+ x1 = ((ut - devp->calibrationdata.ac6) * devp->calibrationdata.ac5) >> 15;
+ x2 = (devp->calibrationdata.mc << 11) / (x1 + devp->calibrationdata.md);
+ devp->calibrationdata.b5 = x1 + x2;
+ *ctp = (float)((devp->calibrationdata.b5 + 8) >> 4)*BMP085_T_RES;
+}
+
+/**
+ * @brief Calcul the true pressure.
+ *
+ * @param[in] devp pointer to the BMP085 device driver sensor
+ * @param[in] up uncompensated pressure
+ * @param[in] oss over sampling setting
+ * @param[out] cpp pointer of the compensated pressure
+ */
+static void calcul_p(BMP085Driver *devp, int32_t up, uint8_t oss, float *cpp) {
+
+ int32_t press;
+ int32_t x1,x2,x3;
+ int32_t b3,b6;
+ uint32_t b4,b7;
+
+ /* Converting the pressure value. */
+ b6 = devp->calibrationdata.b5 - 4000;
+ x1 = (devp->calibrationdata.b2 * ((b6 * b6) >> 12)) >> 11;
+ x2 = (devp->calibrationdata.ac2 * b6) >> 11;
+ x3 = x1 + x2;
+ b3 = ((((int32_t)devp->calibrationdata.ac1 * 4 + x3) << oss) + 2) >> 2;
+ x1 = ((devp->calibrationdata.ac3)*b6) >> 13;
+ x2 = (devp->calibrationdata.b1 * (b6*b6 >> 12)) >> 16;
+ x3 = ((x1 + x2) + 2) >> 2;
+ b4 = devp->calibrationdata.ac4 * (uint32_t)(x3 + 32768) >> 15;
+ b7 = ((uint32_t)up - b3)*(50000 >> oss);
+
+ if (b7 < 0x80000000)
+ press = (b7*2)/b4;
+ else
+ press = (b7/b4)*2;
+
+ x1 = (press >> 8)*(press >> 8);
+ x1 = (x1*3038) >> 16;
+ x2 = (-7357*press) >> 16;
+ *cpp =(float)((press + ((x1 + x2 + 3791) >> 4))*BMP085_P_RES);
+}
+
+/**
+ * @brief Start temperature measurement.
+ *
+ * @param[in] devp pointer to the BMP085 device driver
+ *
+ * @return the operation status
+ */
+static msg_t start_t_measurement(BMP085Driver *devp) {
+
+ uint8_t txbuf[2] = {BMP085_AD_CR, BMP085_CR_T_VAL};
+
+ i2cAcquireBus(devp->config->i2cp);
+ msg_t msg = bmp085I2CWriteRegister(devp->config->i2cp, txbuf, 2);
+ i2cReleaseBus(devp->config->i2cp);
+
+ /* Conversion time for the temperature. */
+ chThdSleepMilliseconds(BMP085_THERMO_CT_LOW);
+ //chThdSleepMilliseconds(devp->config.tct); // TODO: use this instead of the top line:
+
+ return msg;
+}
+
+/**
+ * @brief Start the pressure measurment.
+ *
+ * @param[in] devp pointer to the BMP085 driver
+ * @return msg the operation status
+ */
+static msg_t start_p_measurement(BMP085Driver *devp) {
+
+ uint8_t oss, delay;
+ uint8_t txbuf[2];
+
+ oss = devp->config->oss;
+ txbuf[0] = BMP085_AD_CR;
+
+ /* Check the oss according the bmp085 mode. */
+ if (oss == BMP085_BARO_OSS_0) {
+ txbuf[1] = BMP085_CR_P_VAL0 + (oss << 6);
+ delay = BMP085_BARO_CT_LOW;
+ }
+ else if (oss == BMP085_BARO_OSS_1) {
+ txbuf[1] = BMP085_CR_P_VAL1 + (oss << 6);
+ delay = BMP085_BARO_CT_STD;
+ }
+ else if (oss == BMP085_BARO_OSS_2) {
+ txbuf[1] = BMP085_CR_P_VAL2 + (oss << 6);
+ delay = BMP085_BARO_CT_HR;
+ }
+ else {
+ txbuf[1] = BMP085_CR_P_VAL3 + (oss << 6);
+ delay = BMP085_BARO_CT_LUHR;
+ }
+
+ /* Start the sensor for sampling. */
+#if BMP085_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+#endif /* BMP085_SHARED_I2C */
+
+ msg_t msg = bmp085I2CWriteRegister(devp->config->i2cp, txbuf, 2);
+
+#if BMP085_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* BMP085_SHARED_I2C */
+
+ /* Conversion time for the pressure, max time for the moment. */
+ chThdSleepMilliseconds(delay);
+
+ return msg;
+}
+
+/**
+ * @brief Read the uncompensated temperature from the BMP085 register.
+ *
+ * @param[in] devp pointer to the BMP085 driver
+ * @param[out] utemp uncompensated temperature read from the sensor register
+ *
+ * @return msg the operation status
+ */
+static msg_t acquire_ut(BMP085Driver *devp, int32_t *utemp) {
+
+ uint8_t rxbuf[2];
+ msg_t msg;
+
+ /* Start the temperature measurement. */
+ start_t_measurement(devp);
+
+ /* Start the sensor for sampling. */
+#if BMP085_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+#endif /* BMP085_SHARED_I2C */
+
+ /* Get the temperature. */
+ msg = bmp085I2CReadRegister(devp->config->i2cp, BMP085_AD_T_DR_MSB, rxbuf,
+ 2);
+
+#if BMP085_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* BMP085_SHARED_I2C */
+
+ if(msg == MSG_OK){
+ /* Building the uncompensated temperature value. */
+ *utemp = (int32_t)((rxbuf[0] << 8) | rxbuf[1]);
+ }
+
+ return msg;
+}
+
+/**
+ * @brief Read the uncompensated pressure from the BMP085 register.
+ *
+ * @param[in] devp pointer to the BMP085 driver
+ * @param[out] upress uncompensated pressure read from the sensor register
+ *
+ * @return msg the operation status
+ */
+static msg_t acquire_up(BMP085Driver *devp, int32_t *upress) {
+
+ uint8_t rxbuf[3];
+ uint8_t oss;
+ msg_t msg;
+
+ /* Get the oversampling setting from the driver configuratioin. */
+ oss = devp->config->oss;
+
+ /* Start the pressure measurement. */
+ start_p_measurement(devp);
+
+ /* Start the sensor for sampling. */
+#if BMP085_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+#endif /* BMP085_SHARED_I2C */
+
+ /* Get the pressure */
+ msg = bmp085I2CReadRegister(devp->config->i2cp, BMP085_AD_P_DR_MSB, rxbuf,
+ 3);
+
+#if BMP085_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* BMP085_SHARED_I2C */
+
+ if (msg == MSG_OK) {
+ /* Building the uncompensated pressure value. */
+ *upress = (int32_t)((rxbuf[0] << 16)|(rxbuf[1] << 8)|rxbuf[2]);
+ *upress = *upress >> (8-oss);
+ }
+
+ return msg;
+}
+
+/*==========================================================================*/
+/* Interface implementation. */
+/*==========================================================================*/
+
+/**
+ * @brief Get the barometer number of axes.
+ *
+ * @param[in] ip interface pointer of the BMP085 sensor
+ *
+ * @return barometer number of axes
+ */
+static size_t baro_get_axes_number(void *ip) {
+
+ osalDbgCheck(ip != NULL);
+
+ return BMP085_BARO_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Get the thermometer number of axes.
+ *
+ * @param[in] ip interface pointer of the BMP085 sensor
+ *
+ * @return thermometer number of axes
+ */
+static size_t thermo_get_axes_number(void *ip) {
+
+ osalDbgCheck(ip != NULL);
+
+ return BMP085_THERMO_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Get the sensor number of axes.
+ *
+ * @param[in] ip interface pointer of the BMP085 sensor
+ *
+ * @return sensor number of axes
+ */
+static size_t sens_get_axes_number(void *ip) {
+
+ osalDbgCheck(ip != NULL);
+
+ return (baro_get_axes_number(ip) + thermo_get_axes_number(ip));
+}
+
+/**
+ * @brief Read baromether raw data.
+ *
+ * @param[in] ip interface pointer of the sensor
+ * @param[in] axes buffer for various axes data
+ *
+ * @return msg the result of the reading operation
+ */
+static msg_t baro_read_raw(void *ip, int32_t axes[]) {
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+ osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY),
+ "baro_read_raw(), invalid state");
+
+#if BMP085_USE_I2C
+ osalDbgAssert((((BMP085Driver *)ip)->config->i2cp->state == I2C_READY),
+ "baro_read_raw(), channel not ready");
+#if BMP085_SHARED_I2C
+ i2cAcquireBus(((BMP085Driver *)ip)->config->i2cp);
+ i2cStart(((BMP085Driver *)ip)->config->i2cp,
+ ((BMP085Driver *)ip)->config->i2ccfg);
+#endif /* BMP085_SHARED_I2C. */
+
+ /* Measure the uncompensated pressure. */
+ msg_t msg = acquire_up(((BMP085Driver *)ip), axes);
+
+#if BMP085_SHARED_I2C
+ i2cReleaseBus(((BMP085Driver *)ip)->config->i2cp);
+#endif /* BMP085_SHARED_I2C. */
+#endif /* BMP085_USE_I2C. */
+
+ return msg;
+}
+
+/**
+ * @brief Read thermometer raw data.
+ *
+ * @param[in] ip interface pointer of the BMP085 sensor
+ * @param[in] axes buffer for various axes data
+ *
+ * @return msg the result of the reading operation
+ */
+static msg_t thermo_read_raw(void *ip, int32_t axes[]) {
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+ osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY),
+ "thermo_read_raw(), invalid state");
+
+#if BMP085_USE_I2C
+ osalDbgAssert((((BMP085Driver *)ip)->config->i2cp->state == I2C_READY),
+ "thermo_read_raw(), channel not ready");
+#if BMP085_SHARED_I2C
+ i2cAcquireBus(((BMP085Driver *)ip)->config->i2cp);
+ i2cStart(((BMP085Driver *)ip)->config->i2cp,
+ ((BMP085Driver *)ip)->config->i2ccfg);
+#endif /* BMP085_SHARED_I2C. */
+
+ /* Measure the uncompensated temperature. */
+ msg_t msg = acquire_ut(((BMP085Driver *)ip), axes);
+
+#if BMP085_SHARED_I2C
+ i2cReleaseBus(((LSM303DLHCDriver *)ip)->config->i2cp);
+#endif /* BMP085_SHARED_I2C. */
+#endif /* BMP085_USE_I2C. */
+
+ return msg;
+}
+
+/**
+ * @brief Read BMP085 sensor raw data.
+ *
+ * @param[in] ip interface pointer of the BMP085 sensor
+ * @param[in] axes buffer for various axes data
+ *
+ * @return msg the result of the reading operation
+ */
+static msg_t sens_read_raw(void *ip, int32_t axes[]) {
+
+ int32_t* bp = axes;
+ msg_t msg;
+
+ msg = baro_read_raw(ip, bp);
+
+ if (msg != MSG_OK)
+ return msg;
+
+ bp += BMP085_BARO_NUMBER_OF_AXES;
+
+ msg = thermo_read_raw(ip, bp);
+
+ return msg;
+}
+
+/**
+ * @brief Read barometer cooked data.
+ *
+ * @param[in] ip interface pointer of the BMP085 sensor
+ * @param[in] axes buffer for various axes data
+ *
+ * @return msg the result of the reading operation
+ */
+static msg_t baro_read_cooked(void *ip, float axes[]) {
+
+ uint32_t i;
+ int32_t raw[BMP085_BARO_NUMBER_OF_AXES];
+ msg_t msg;
+ uint8_t oss;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+ osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY),
+ "baro_read_cooked(), invalid state");
+
+ msg = baro_read_raw(ip, raw);
+ oss = ((BMP085Driver *)ip)->config->oss;
+
+ for (i = 0; i < BMP085_BARO_NUMBER_OF_AXES; i++)
+ calcul_p(ip, raw[i], oss, &axes[i]);
+
+ return msg;
+}
+
+/**
+ * @brief Read thermometer cooked data.
+ *
+ * @param[in] ip interface pointer of the BMP085 sensor
+ * @param[in] axes buffer for various axes data
+ *
+ * @return msg the result of the reading operation
+ */
+static msg_t thermo_read_cooked(void *ip, float axes[]) {
+
+ uint32_t i;
+ int32_t raw[BMP085_THERMO_NUMBER_OF_AXES];
+ msg_t msg;
+
+ osalDbgCheck(((ip != NULL) && (axes != NULL)));
+ osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY),
+ "thermo_read_cooked(), invalid state");
+ msg = thermo_read_raw(ip, raw);
+
+ for (i = 0; i < BMP085_THERMO_NUMBER_OF_AXES; i++)
+ calcul_t(ip, raw[i], &axes[i]);
+
+ return msg;
+}
+
+/**
+ * @brief Read BMP085 sensor cooked data.
+ *
+ * @param[in] ip interface pointer of the BMP085 sensor
+ * @param[in] axes buffer for various axes data
+ *
+ * @return msg the result of the reading operation
+ */
+static msg_t sens_read_cooked(void *ip, float axes[]) {
+
+ float* bp = axes;
+ msg_t msg;
+
+ msg = baro_read_cooked(ip, bp);
+
+ if (msg != MSG_OK)
+ return msg;
+
+ bp += BMP085_BARO_NUMBER_OF_AXES;
+ msg = thermo_read_cooked(ip, bp);
+
+ return msg;
+}
+
+/**
+ * @brief Set the barometer bias.
+ *
+ * @param[in] ip interface pointer of the BMP085 sensor
+ * @param[in] bp pointer to the bias value
+ *
+ * @return msg the result of the setting operation
+ */
+static msg_t baro_set_bias(void *ip, float *bp) {
+
+ osalDbgCheck((ip != NULL) && (bp !=NULL));
+ osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY) ||
+ (((BMP085Driver *)ip)->state == BMP085_STOP),
+ "baro_set_bias(), invalid state");
+ return MSG_OK;
+}
+
+/**
+ * @brief Set the thermometer bias.
+ *
+ * @param[in] ip interface pointer of the BMP085 sensor
+ * @param[in] bp pointer to the bias value
+ *
+ * @return msg the result of the setting operation
+ */
+static msg_t thermo_set_bias(void *ip, float *bp) {
+
+ osalDbgCheck((ip != NULL) && (bp !=NULL));
+ osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY) ||
+ (((BMP085Driver *)ip)->state == BMP085_STOP),
+ "thermo_set_bias(), invalid state");
+ return MSG_OK;
+}
+
+/**
+ * @brief Reset the barometer bias.
+ *
+ * @param[in] ip interface pointer of the BMP085 sensor
+ *
+ * @return msg the result of the reset operation
+ */
+static msg_t baro_reset_bias(void *ip) {
+
+ osalDbgCheck(ip != NULL);
+ osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY) ||
+ (((BMP085Driver *)ip)->state == BMP085_STOP),
+ "baro_reset_bias(), invalid state");
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Reset the thermometer bias.
+ *
+ * @param[in] ip interface pointer of the BMP085 sensor
+ *
+ * @return msg the result of the reset operation
+ */
+static msg_t thermo_reset_bias(void *ip) {
+
+ osalDbgCheck(ip != NULL);
+ osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY) ||
+ (((BMP085Driver *)ip)->state == BMP085_STOP),
+ "thermo_reset_bias(), invalid state");
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Set the barometer sensivity.
+ *
+ * @param[in] ip interface pointer of the BMP085 sensor
+ * @param[in] sp pointer to the sensivity value
+ *
+ * @return msg the result of the setting operation
+ */
+static msg_t baro_set_sensivity(void *ip, float *sp) {
+
+ osalDbgCheck((ip != NULL) && (sp !=NULL));
+ osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY),
+ "baro_set_sensivity(), invalid state");
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Set the thermometer sensivity.
+ *
+ * @param[in] ip interface pointer of the BMP085 sensor
+ * @param[in] sp pointer to the sensivity value
+ *
+ * @return msg the result of the setting operation
+ */
+static msg_t thermo_set_sensivity(void *ip, float *sp) {
+
+ osalDbgCheck((ip != NULL) && (sp !=NULL));
+ osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY),
+ "thermo_set_sensivity(), invalid state");
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Reset the barometer sensivity.
+ *
+ * @param[in] ip interface pointer of the BMP085 sensor
+ *
+ * @return msg the result of the reset operation
+ */
+static msg_t baro_reset_sensivity(void *ip) {
+
+ osalDbgCheck(ip != NULL);
+ osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY),
+ "baro_reset_sensivity(), invalid state");
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Reset the thermometer sensivity.
+ *
+ * @param[in] ip interface pointer of the BMP085 sensor
+ *
+ * @return msg the result of the reset operation
+ */
+static msg_t thermo_reset_sensivity(void *ip) {
+
+ osalDbgCheck(ip != NULL);
+ osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY),
+ "thermo_reset_sensivity(), invalid state");
+
+ return MSG_OK;
+}
+
+static const struct BaseSensorVMT vmt_basesensor = {
+ sens_get_axes_number, sens_read_raw, sens_read_cooked
+};
+
+static const struct BaseBarometerVMT vmt_basebarometer = {
+ baro_get_axes_number, baro_read_raw, baro_read_cooked,
+ baro_set_bias, baro_reset_bias,
+ baro_set_sensivity, baro_reset_sensivity
+};
+
+static const struct BaseThermometerVMT vmt_basethermometer = {
+ thermo_get_axes_number, thermo_read_raw, thermo_read_cooked,
+ thermo_set_bias, thermo_reset_bias,
+ thermo_set_sensivity, thermo_reset_sensivity
+};
+
+/*==========================================================================*/
+/* Driver exported functions. */
+/*==========================================================================*/
+
+/**
+ * @brief Initializes an instance.
+ *
+ * @param[out] devp pointer to the @p BMP085Driver object
+ *
+ * @init
+ */
+void bmp085ObjectInit(BMP085Driver *devp) {
+
+ devp->vmt_basesensor = &vmt_basesensor;
+ devp->vmt_basebarometer = &vmt_basebarometer;
+ devp->vmt_basethermometer = &vmt_basethermometer;
+ devp->config = NULL;
+ devp->state = BMP085_STOP;
+}
+
+/**
+ * @brief Configures and activates BMP085 Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p BMP085Driver object
+ * @param[in] config pointer to the @p BMP085Config object
+ *
+ * @api
+ */
+void bmp085Start(BMP085Driver *devp, const BMP085Config *config) {
+
+ osalDbgCheck((devp != NULL) && (config != NULL));
+ osalDbgAssert((devp->state == BMP085_STOP) ||
+ (devp->state == BMP085_READY),
+ "bmp085cStart(), invalid state");
+ devp->config = config;
+#if BMP085_USE_I2C
+#if BMP085_SHARED_I2C
+ i2cAcquireBus((devp)->config->i2cp);
+#endif /* BMP085_SHARED_I2C. */
+ /* Read the Calibrations data. */
+ i2cStart((devp)->config->i2cp, (devp)->config->i2ccfg);
+ bmp085ReadCoefficient(devp, BMP085_AD_CC_AC1_MSB);
+#if BMP085_SHARED_I2C
+ i2cReleaseBus((devp)->config->i2cp);
+#endif /* BMP085_SHARED_I2C. */
+#endif /* BMP085_USE_I2C. */
+ if(devp->state != BMP085_READY)
+ devp->state = BMP085_READY;
+}
+
+/**
+ * @brief Deactivates the BMP085 Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p BMP085Driver object
+ *
+ * @api
+ */
+void bmp085Stop(BMP085Driver *devp) {
+
+ osalDbgCheck(devp != NULL);
+ osalDbgAssert((devp->state == BMP085_STOP) ||
+ (devp->state == BMP085_READY),
+ "bmp085Stop(), invalid state");
+#if (BMP085_USE_I2C)
+ if (devp->state == BMP085_STOP) {
+#if BMP085_SHARED_I2C
+ i2cAcquireBus((devp)->config->i2cp);
+ i2cStart((devp)->config->i2cp, (devp)->config->i2ccfg);
+#endif /* BMP085_SHARED_I2C. */
+#if BMP085_SHARED_I2C
+ i2cReleaseBus((devp)->config->i2cp);
+#endif /* BMP085_SHARED_I2C. */
+ }
+#endif /* BMP085_USE_I2C. */
+ if (devp->state != BMP085_STOP)
+ devp->state = BMP085_STOP;
+}
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/Bosch/bmp085.h b/ChibiOS_20.3.2/os/ex/devices/Bosch/bmp085.h
new file mode 100644
index 0000000..f188c6b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/Bosch/bmp085.h
@@ -0,0 +1,403 @@
+/*
+ ChibiOS - Copyright (C) 2016..2017 Theodore Ateba
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file bmp085.h
+ * @brief BMP085 Digital pressure sensor interface module header.
+ *
+ * @addtogroup BMP085
+ * @ingroup EX_BOSCH
+ * @{
+ */
+
+#ifndef BMP085_H
+#define BMP085_H
+
+#include "ex_barometer.h"
+#include "ex_thermometer.h"
+
+/*==========================================================================*/
+/* Driver constants. */
+/*==========================================================================*/
+
+/**
+ * @name Version identification
+ * @{
+ */
+
+/**
+ * @brief BMP085 driver version string.
+ */
+#define EX_BMP085_VERSION "1.0.1"
+
+/**
+ * @brief BMP085 driver version major number.
+ */
+#define EX_BMP085_MAJOR 1
+
+/**
+ * @brief BMP085 driver version minor number.
+ */
+#define EX_BMP085_MINOR 0
+
+/**
+ * @brief BMP085 driver version patch number.
+ */
+#define EX_BMP085_PATCH 1
+/** @}*/
+
+/**
+ * @brief BMP085 barometer subsystem characteristics.
+ * @{
+ */
+#define BMP085_BARO_NUMBER_OF_AXES 1U /**< Number of axes */
+
+#define BMP085_P_RES 0.01 /**< LSB/hP */
+/** @} */
+
+/**
+ * @brief BMP085 thermometer subsystem characteristics.
+ * @{
+ */
+#define BMP085_THERMO_NUMBER_OF_AXES 1U /**< Number of axes */
+
+#define BMP085_T_RES 0.1 /**< LSB/C° */
+/** @} */
+
+/**
+ * @name BMP085 Registers addresses.
+ * @{
+ */
+#define BMP085_AD_CR 0xF4 /**< Control register address. */
+#define BMP085_AD_T_DR_MSB 0xF6 /**< Temp MSB data register addr. */
+#define BMP085_AD_T_DR_LSB 0xF7 /**< Temp LSB data register addr. */
+#define BMP085_AD_P_DR_MSB 0xF6 /**< Press MSB data register addr. */
+#define BMP085_AD_P_DR_LSB 0xF7 /**< Press LSB data register addr. */
+#define BMP085_AD_P_DR_XLSB 0xF8 /**< Press XLSB data register addr.*/
+#define BMP085_AD_CC_AC1_MSB 0xAA /**< AC1 MSB calib coef reg addr. */
+#define BMP085_AD_CC_AC1_LSB 0xAB /**< AC1 LSB calib coef reg addr. */
+#define BMP085_AD_CC_AC2_MSB 0xAC /**< AC2 MSB calib coef reg addr. */
+#define BMP085_AD_CC_AC2_LSB 0xAD /**< AC2 LSB calib coef reg addr. */
+#define BMP085_AD_CC_AC3_MSB 0xAE /**< AC3 MSB calib coef reg addr. */
+#define BMP085_AD_CC_AC3_LSB 0xAF /**< AC3 LSB calib coef reg addr. */
+#define BMP085_AD_CC_AC4_MSB 0xB0 /**< AC4 MSB calib coef reg addr. */
+#define BMP085_AD_CC_AC4_LSB 0xB1 /**< AC4 LSB calib coef reg addr. */
+#define BMP085_AD_CC_AC5_MSB 0xB2 /**< AC5 MSB calib coef reg addr. */
+#define BMP085_AD_CC_AC5_LSB 0xB3 /**< AC5 LSB calib coef reg addr. */
+#define BMP085_AD_CC_AC6_MSB 0xB4 /**< AC6 MSB calib coef reg addr. */
+#define BMP085_AD_CC_AC6_LSB 0xB5 /**< AC6 LSB calib coef reg addr. */
+#define BMP085_AD_CC_B1_MSB 0xB6 /**< B1 MSB calib coef reg addr. */
+#define BMP085_AD_CC_B1_LSB 0xB7 /**< B1 LSB calib coef reg addr. */
+#define BMP085_AD_CC_B2_MSB 0xB8 /**< B2 MSB calib coef reg addr. */
+#define BMP085_AD_CC_B2_LSB 0xB9 /**< B2 LSB calib coef reg addr. */
+#define BMP085_AD_CC_MB_MSB 0xBA /**< MB MSB calib coef reg addr. */
+#define BMP085_AD_CC_MB_LSB 0xBB /**< MB LSB calib coef reg addr. */
+#define BMP085_AD_CC_MC_MSB 0xBC /**< MC MSB calib coef reg addr. */
+#define BMP085_AD_CC_MC_LSB 0xBD /**< MC LSB calib coef reg addr. */
+#define BMP085_AD_CC_MD_MSB 0xBE /**< MD MSB calib coef reg addr. */
+#define BMP085_AD_CC_MD_LSB 0xBF /**< MD LSB calib coef reg addr. */
+/** @} */
+
+/*==========================================================================*/
+/* Driver pre-compile time settings. */
+/*==========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+
+/**
+ * @brief BMP085 I2C interface selector.
+ * @details If set to @p TRUE the support for I2C is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(BMP085_USE_I2C) || defined(__DOXYGEN__)
+#define BMP085_USE_I2C TRUE
+#endif
+
+/**
+ * @brief BMP085 sensor subsystem advanced configurations switch.
+ * @details If set to @p TRUE more configurations are available.
+ * @note The default is @p TRUE.
+ */
+#if !defined(BMP085_USE_ADVANCED) || defined(__DOXYGEN__)
+#define BMP085_USE_ADVANCED TRUE
+#endif
+
+/**
+ * @brief BMP085 shared I2C switch.
+ * @details If set to @p TRUE the device acquires I2C bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(BMP085_SHARED_I2C) || defined(__DOXYGEN__)
+#define BMP085_SHARED_I2C FALSE
+#endif
+/** @} */
+
+/*==========================================================================*/
+/* Derived constants and error checks. */
+/*==========================================================================*/
+
+#if !HAL_USE_I2C
+#error "BMP085_USE_I2C requires HAL_USE_I2C"
+#endif
+
+#if BMP085_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
+#error "BMP085_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
+#endif
+
+/*==========================================================================*/
+/* Driver data structures and types. */
+/*==========================================================================*/
+
+/**
+ * @name BMP085 barometer subsystem data structures and types.
+ * @{
+ */
+
+/**
+ * @brief BMP085 barometer subsystem pressure conversion time.
+ */
+typedef enum {
+ BMP085_BARO_CT_LOW = 0x05, /**< Convers time in ultra low power mode. */
+ BMP085_BARO_CT_STD = 0x18, /**< Convers time in standard mode. */
+ BMP085_BARO_CT_HR = 0x0E, /**< Convers time in high resolution mode. */
+ BMP085_BARO_CT_LUHR = 0x1A /**< Convers time in ultra high res. mode. */
+} bmp085_baro_ct_t;
+
+/**
+ * @brief BMP085 barometer subsystem mode.
+ */
+typedef enum {
+ BMP085_BARO_MODE_LOW = 0x00, /**< BMP085 ultra low power mode. */
+ BMP085_BARO_MODE_STD = 0x01, /**< BMP085 standard mode. */
+ BMP085_BARO_MODE_HR = 0x02, /**< BMP085 high resolution mode. */
+ BMP085_BARO_MODE_LUHR = 0x03 /**< BMP085 ultra high res. mode. */
+} bmp085_baro_mode_t;
+
+/**
+ * @brief BMP085 barometer oversampling setting.
+ */
+typedef enum {
+ BMP085_BARO_OSS_0 = 0x00, /**< Ultra low power sampling rate. */
+ BMP085_BARO_OSS_1 = 0x01, /**< Standard mode sampling rate. */
+ BMP085_BARO_OSS_2 = 0x02, /**< High resolution sampling rate. */
+ BMP085_BARO_OSS_3 = 0x04 /**< ultra high resolution sampling rate. */
+}bmp085_baro_oss_t;
+
+/**
+ * @brief BMP085 barometer subsystem calibration data.
+ */
+typedef struct {
+ int16_t ac1;
+ int16_t ac2;
+ int16_t ac3;
+ int16_t b1;
+ int16_t b2;
+ int16_t mb;
+ int16_t mc;
+ int16_t md;
+ uint16_t ac4;
+ uint16_t ac5;
+ uint16_t ac6;
+ int32_t b5;
+} bmp085_cd_t;
+
+/** @} */
+
+/**
+ * @name BMP085 thermometer subsystem data structures and types.
+ * @{
+ */
+
+/**
+ * @brief BMP085 thermometer subsystem temperature conversion time.
+ */
+typedef enum {
+ BMP085_THERMO_CT_LOW = 0x05, /**< Conv time in ultra low power mode. */
+ BMP085_THERMO_CT_STD = 0x18, /**< Conv time in standard mode. */
+ BMP085_THERMO_CT_HR = 0x0E, /**< Conv time in high resolution mode. */
+ BMP085_THERMO_CT_LUHR = 0x1A /**< Conv time in ultra high res. mode. */
+} bmp085_thermo_ct_t;
+
+/** @} */
+
+/**
+ * @name BMP085 main system data structures and types.
+ * @{
+ */
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ BMP085_UNINIT = 0, /**< Not initialized. */
+ BMP085_STOP = 1, /**< Stopped. */
+ BMP085_READY = 2 /**< Ready. */
+} bmp085_state_t;
+
+/**
+ * @brief BMP085 configuration structure.
+ */
+typedef struct {
+#if BMP085_USE_I2C || defined(__DOXYGEN__)
+ /**
+ * @brief I2C driver associated to this BMP085.
+ */
+ I2CDriver *i2cp;
+
+ /**
+ * @brief I2C configuration associated to this BMP085 subsystem.
+ */
+ const I2CConfig *i2ccfg;
+#endif /* BMP085_USE_I2C */
+ /**
+ * @brief HTS221 initial sensitivity.
+ * @note Value are respectively related to hygrometer
+ * and thermometer.
+ */
+ float* sensitivity;
+ /**
+ * @brief HTS221 initial bias.
+ * @note Value are respectively related to hygrometer
+ * and thermometer.
+ */
+ float* bias;
+ /**
+ * @brief HTS221 output data rate selection.
+ */
+ float* outputdatarate;
+#if BMP085_USE_ADVANCED || defined(__DOXYGEN__)
+ /**
+ * @brief BMP085 barometer subsystem pressure conversion time.
+ */
+ bmp085_baro_ct_t bct;
+
+ /**
+ * @brief BMP085 barometer subsystem mode.
+ */
+ bmp085_baro_mode_t mode;
+
+ /**
+ * @brief BMP085 barometer subsystem oversampling setting.
+ */
+ bmp085_baro_oss_t oss;
+
+ /**
+ * @brief BMP085 thermometer subsystem temperature conversion time.
+ */
+ bmp085_thermo_ct_t tct;
+#endif /* BMP085_USE_ADVANCED */
+} BMP085Config;
+
+/**
+ * @brief Structure representing a BMP085 driver.
+ */
+typedef struct BMP085Driver BMP085Driver;
+
+/**
+ * @brief @p BMP085 barometer subsystem specific methods.
+ */
+#define _bmp085_baro_methods \
+ _base_barometer_methods
+
+/**
+ * @brief @p BMP085 thermometer subsystem specific methods.
+ */
+#define _bmp085_thermo_methods \
+ _base_thermometer_methods
+
+/**
+ * @extends BaseBarometerVMT
+ *
+ * @brief @p BMP085 barometer virtual methods table.
+ */
+struct BMP085BAROVMT {
+ _bmp085_baro_methods
+};
+
+/**
+ * @extends BaseThermometerVMT
+ *
+ * @brief @p BMP085 thermometer virtual methods table.
+ */
+struct BMP085THERMOVMT {
+ _bmp085_thermo_methods
+};
+
+/**
+ * @brief @p BMP085Driver specific data.
+ */
+#define _bmp085_data \
+ _base_barometer_data \
+ _base_thermometer_data \
+ /* Driver state. */ \
+ bmp085_state_t state; \
+ /* Current configuration data. */ \
+ const BMP085Config *config; \
+ /* Current barometer sensitivity. */ \
+ float barosensitivity[BMP085_BARO_NUMBER_OF_AXES]; \
+ /* Barometer bias data. */ \
+ int32_t barobias[BMP085_BARO_NUMBER_OF_AXES]; \
+ /* Current thermometer sensitivity. */ \
+ float thermosensitivity[BMP085_THERMO_NUMBER_OF_AXES]; \
+ /* Thermometer bias data. */ \
+ int32_t thermobias[BMP085_THERMO_NUMBER_OF_AXES]; \
+ /* BMP085 calibration data. */ \
+ bmp085_cd_t calibrationdata;
+
+/**
+ * @brief BMP085 driver structure.
+ */
+struct BMP085Driver {
+ /** @brief BaseSensor Virtual Methods Table. */
+ const struct BaseSensorVMT *vmt_basesensor;
+ /** @brief BaseBarometer Virtual Methods Table. */
+ const struct BaseBarometerVMT *vmt_basebarometer;
+ /** @brief BaseThermometer Virtual Methods Table. */
+ const struct BaseThermometerVMT *vmt_basethermometer;
+ _bmp085_data;
+};
+
+/** @} */
+
+/*==========================================================================*/
+/* Driver macros. */
+/*==========================================================================*/
+
+/*==========================================================================*/
+/* External declarations. */
+/*==========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void bmp085ObjectInit(BMP085Driver *devp);
+ void bmp085Start(BMP085Driver *devp, const BMP085Config *config);
+ void bmp085Stop(BMP085Driver *devp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BMP085_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/Bosch/bmp085.mk b/ChibiOS_20.3.2/os/ex/devices/Bosch/bmp085.mk
new file mode 100644
index 0000000..7c868ca
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/Bosch/bmp085.mk
@@ -0,0 +1,10 @@
+# List of all the BMP085 device files.
+BMP085SRC := $(CHIBIOS)/os/ex/devices/Bosch/bmp085.c
+
+# Required include directories
+BMP085INC := $(CHIBIOS)/os/ex/include \
+ $(CHIBIOS)/os/ex/devices/Bosch
+
+# Shared variables
+ALLCSRC += $(BMP085SRC)
+ALLINC += $(BMP085INC)
\ No newline at end of file
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/hts221.c b/ChibiOS_20.3.2/os/ex/devices/ST/hts221.c
new file mode 100644
index 0000000..eb04ef7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/hts221.c
@@ -0,0 +1,781 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file hts221.c
+ * @brief HTS221 MEMS interface module code.
+ *
+ * @addtogroup HTS221
+ * @ingroup EX_ST
+ * @{
+ */
+
+#include "hal.h"
+#include "hts221.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define HTS221_SEL(mask, offset) (int16_t)(mask << offset)
+
+#define HTS221_FLAG_HYGRO_BIAS 0x01
+#define HTS221_FLAG_HYGRO_SENS 0x02
+#define HTS221_FLAG_THERMO_BIAS 0x04
+#define HTS221_FLAG_THERMO_SENS 0x08
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#if (HTS221_USE_I2C) || defined(__DOXYGEN__)
+/**
+ * @brief Reads registers value using I2C.
+ * @pre The I2C interface must be initialized and the driver started.
+ *
+ * @param[in] i2cp pointer to the I2C interface
+ * @param[in] reg first sub-register address
+ * @param[out] rxbuf pointer to an output buffer
+ * @param[in] n number of consecutive register to read
+ * @return the operation status.
+ *
+ * @notapi
+ */
+static msg_t hts221I2CReadRegister(I2CDriver *i2cp, uint8_t reg, uint8_t* rxbuf,
+ size_t n) {
+ uint8_t txbuf = reg;
+ if (n > 1)
+ txbuf |= HTS221_SUB_MS;
+
+ return i2cMasterTransmitTimeout(i2cp, HTS221_SAD, &txbuf, 1, rxbuf, n,
+ TIME_INFINITE);
+}
+
+/**
+ * @brief Writes a value into a register using I2C.
+ * @pre The I2C interface must be initialized and the driver started.
+ *
+ * @param[in] i2cp pointer to the I2C interface
+ * @param[in] txbuf buffer containing sub-address value in first position
+ * and values to write
+ * @param[in] n size of txbuf less one (not considering the first
+ * element)
+ * @return the operation status.
+ *
+ * @notapi
+ */
+static msg_t hts221I2CWriteRegister(I2CDriver *i2cp, uint8_t* txbuf, size_t n) {
+ if (n > 1)
+ (*txbuf) |= HTS221_SUB_MS;
+
+ return i2cMasterTransmitTimeout(i2cp, HTS221_SAD, txbuf, n + 1, NULL, 0,
+ TIME_INFINITE);
+}
+#endif /* HTS221_USE_I2C */
+
+/**
+ * @brief Computes biases and sensitivities starting from data stored in
+ * calibration registers.
+ * @note Factory bias and sensitivity values are stored into the driver
+ * structure.
+ *
+ * @param[in] devp pointer to the HTS221 interface
+ * @return the operation status.
+ *
+ * @notapi
+ */
+static msg_t hts221Calibrate(HTS221Driver *devp) {
+ msg_t msg;
+ uint8_t calib[16], H0_rH_x2, H1_rH_x2, msb;
+ int16_t H0_T0_OUT, H1_T0_OUT, T0_degC_x8, T1_degC_x8, T0_OUT, T1_OUT;
+
+ /* Retrieving rH values from Calibration registers */
+ msg = hts221I2CReadRegister(devp->config->i2cp,
+ HTS221_AD_CALIB_0, calib, 16);
+
+ H0_rH_x2 = calib[0];
+ H1_rH_x2 = calib[1];
+ H0_T0_OUT = calib[6];
+ H0_T0_OUT += calib[7] << 8;
+ H1_T0_OUT = calib[10];
+ H1_T0_OUT += calib[11] << 8;
+
+ T0_degC_x8 = calib[2];
+
+ /* Completing T0_degC_x8 value */
+ msb = (calib[5] & HTS221_SEL(0x03, 0));
+ if (msb & HTS221_SEL(0x01, 1)) {
+ msb |= HTS221_SEL(0x3F, 2);
+ }
+ T0_degC_x8 += msb << 8;
+
+ T1_degC_x8 = calib[3];
+ /* Completing T1_degC_x8 value */
+ msb = ((calib[5] & HTS221_SEL(0x03, 2)) >> 2);
+ if (msb & HTS221_SEL(0x01, 1)) {
+ msb |= HTS221_SEL(0x3F, 2);
+ }
+ T1_degC_x8 += msb << 8;
+
+ T0_OUT = calib[12];
+ T0_OUT += calib[13] << 8;
+ T1_OUT = calib[14];
+ T1_OUT += calib[15] << 8;
+
+ devp->hygrofactorysensitivity = ((float)H1_rH_x2 - (float)H0_rH_x2) /
+ (((float)H1_T0_OUT - (float)H0_T0_OUT) * 2.0f);
+
+
+ devp->hygrofactorybias = (devp->hygrofactorysensitivity * (float)H0_T0_OUT) -
+ ((float)H0_rH_x2 / 2.0f);
+
+ devp->thermofactorysensitivity = ((float)T1_degC_x8 - (float)T0_degC_x8) /
+ (((float)T1_OUT - (float)T0_OUT) * 8.0f);
+
+ devp->thermofactorybias = (devp->thermofactorysensitivity * (float)T0_OUT) -
+ ((float)T0_degC_x8 / 8.0f);
+
+ return msg;
+}
+
+/**
+ * @brief Return the number of axes of the BaseHygrometer.
+ *
+ * @param[in] ip pointer to @p BaseHygrometer interface.
+ *
+ * @return the number of axes.
+ */
+static size_t hygro_get_axes_number(void *ip) {
+ (void)ip;
+
+ return HTS221_HYGRO_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Retrieves raw data from the BaseHygrometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseHygrometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseHygrometer interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t hygro_read_raw(void *ip, int32_t axes[]) {
+ HTS221Driver* devp;
+ uint8_t buff[2];
+ int16_t tmp;
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(HTS221Driver*, (BaseHygrometer*)ip);
+
+ osalDbgAssert((devp->state == HTS221_READY),
+ "hygro_read_raw(), invalid state");
+
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "hygro_read_raw(), channel not ready");
+
+#if HTS221_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* HTS221_SHARED_I2C */
+
+ msg = hts221I2CReadRegister(devp->config->i2cp, HTS221_AD_HUMIDITY_OUT_L,
+ buff, 2);
+
+#if HTS221_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* HTS221_SHARED_I2C */
+
+ if (msg == MSG_OK) {
+ tmp = buff[0] + (buff[1] << 8);
+ *axes = (int32_t)tmp;
+ }
+ return msg;
+}
+
+/**
+ * @brief Retrieves cooked data from the BaseHygrometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as %rH.
+ * @note The axes array must be at least the same size of the
+ * BaseHygrometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseHygrometer interface.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t hygro_read_cooked(void *ip, float axes[]) {
+ HTS221Driver* devp;
+ int32_t raw;
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(HTS221Driver*, (BaseHygrometer*)ip);
+
+ osalDbgAssert((devp->state == HTS221_READY),
+ "hygro_read_cooked(), invalid state");
+
+ msg = hygro_read_raw(ip, &raw);
+
+ *axes = (raw * devp->hygrosensitivity) - devp->hygrobias;
+
+ return msg;
+}
+
+/**
+ * @brief Set bias values for the BaseHygrometer.
+ * @note Bias must be expressed as %rH.
+ * @note The bias buffer must be at least the same size of the
+ * BaseHygrometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseHygrometer interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t hygro_set_bias(void *ip, float *bp) {
+ HTS221Driver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (bp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(HTS221Driver*, (BaseHygrometer*)ip);
+
+ osalDbgAssert((devp->state == HTS221_READY),
+ "hygro_set_bias(), invalid state");
+
+ devp->hygrobias = *bp;
+ return msg;
+}
+
+/**
+ * @brief Reset bias values for the BaseHygrometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] ip pointer to @p BaseHygrometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t hygro_reset_bias(void *ip) {
+ HTS221Driver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(HTS221Driver*, (BaseHygrometer*)ip);
+
+ osalDbgAssert((devp->state == HTS221_READY),
+ "hygro_reset_bias(), invalid state");
+
+ devp->hygrobias = devp->hygrofactorybias;
+ return msg;
+}
+
+/**
+ * @brief Set sensitivity values for the BaseHygrometer.
+ * @note Sensitivity must be expressed as %rH/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseHygrometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseHygrometer interface.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t hygro_set_sensitivity(void *ip, float *sp) {
+ HTS221Driver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (sp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(HTS221Driver*, (BaseHygrometer*)ip);
+
+ osalDbgAssert((devp->state == HTS221_READY),
+ "hygro_set_sensitivity(), invalid state");
+
+ devp->hygrosensitivity = *sp;
+ return msg;
+}
+
+/**
+ * @brief Reset sensitivity values for the BaseHygrometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] ip pointer to @p BaseHygrometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t hygro_reset_sensitivity(void *ip) {
+ HTS221Driver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(HTS221Driver*, (BaseHygrometer*)ip);
+
+ osalDbgAssert((devp->state == HTS221_READY),
+ "hygro_reset_sensitivity(), invalid state");
+
+ devp->hygrosensitivity = devp->hygrofactorysensitivity;
+ return msg;
+}
+
+/**
+ * @brief Return the number of axes of the BaseThermometer.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ *
+ * @return the number of axes.
+ */
+static size_t thermo_get_axes_number(void *ip) {
+ (void)ip;
+
+ return HTS221_THERMO_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Retrieves raw data from the BaseThermometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t thermo_read_raw(void *ip, int32_t axes[]) {
+ HTS221Driver* devp;
+ int16_t tmp;
+ uint8_t buff[2];
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(HTS221Driver*, (BaseThermometer*)ip);
+
+ osalDbgAssert((devp->state == HTS221_READY),
+ "thermo_read_raw(), invalid state");
+
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "thermo_read_raw(), channel not ready");
+
+#if HTS221_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* HTS221_SHARED_I2C */
+
+ msg = hts221I2CReadRegister(devp->config->i2cp, HTS221_AD_TEMP_OUT_L,
+ buff, 2);
+
+#if HTS221_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* HTS221_SHARED_I2C */
+
+ if (msg == MSG_OK) {
+ tmp = buff[0] + (buff[1] << 8);
+ *axes = (int32_t)tmp;
+ }
+ return msg;
+}
+
+/**
+ * @brief Retrieves cooked data from the BaseThermometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as °C.
+ * @note The axes array must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ * @param[out] axis a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t thermo_read_cooked(void *ip, float* axis) {
+ HTS221Driver* devp;
+ int32_t raw;
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axis != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(HTS221Driver*, (BaseThermometer*)ip);
+
+ osalDbgAssert((devp->state == HTS221_READY),
+ "thermo_read_cooked(), invalid state");
+
+ msg = thermo_read_raw(devp, &raw);
+
+ *axis = (raw * devp->thermosensitivity) - devp->thermobias;
+
+ return msg;
+}
+
+/**
+ * @brief Set bias values for the BaseThermometer.
+ * @note Bias must be expressed as °C.
+ * @note The bias buffer must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t thermo_set_bias(void *ip, float *bp) {
+ HTS221Driver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (bp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(HTS221Driver*, (BaseThermometer*)ip);
+
+ osalDbgAssert((devp->state == HTS221_READY),
+ "thermo_set_bias(), invalid state");
+
+ devp->thermobias = *bp;
+
+ return msg;
+}
+
+/**
+ * @brief Reset bias values for the BaseThermometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t thermo_reset_bias(void *ip) {
+ HTS221Driver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(HTS221Driver*, (BaseThermometer*)ip);
+
+ osalDbgAssert((devp->state == HTS221_READY),
+ "thermo_reset_bias(), invalid state");
+
+ devp->thermobias = devp->thermofactorybias;
+
+ return msg;
+}
+
+/**
+ * @brief Set sensitivity values for the BaseThermometer.
+ * @note Sensitivity must be expressed as °C/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t thermo_set_sensitivity(void *ip, float *sp) {
+ HTS221Driver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (sp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(HTS221Driver*, (BaseThermometer*)ip);
+
+ osalDbgAssert((devp->state == HTS221_READY),
+ "thermo_set_sensitivity(), invalid state");
+
+ devp->thermosensitivity = *sp;
+
+ return msg;
+}
+
+/**
+ * @brief Reset sensitivity values for the BaseThermometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t thermo_reset_sensitivity(void *ip) {
+ HTS221Driver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(HTS221Driver*, (BaseThermometer*)ip);
+
+ osalDbgAssert((devp->state == HTS221_READY),
+ "thermo_reset_sensitivity(), invalid state");
+
+ devp->thermosensitivity = devp->thermofactorysensitivity;
+
+ return msg;
+}
+
+static const struct HTS221VMT vmt_device = {
+ (size_t)0
+};
+
+static const struct BaseHygrometerVMT vmt_hygrometer = {
+ sizeof(struct HTS221VMT*),
+ hygro_get_axes_number, hygro_read_raw, hygro_read_cooked,
+ hygro_set_bias, hygro_reset_bias, hygro_set_sensitivity,
+ hygro_reset_sensitivity
+};
+
+static const struct BaseThermometerVMT vmt_thermometer = {
+ sizeof(struct HTS221VMT*) + sizeof(BaseHygrometer),
+ thermo_get_axes_number, thermo_read_raw, thermo_read_cooked,
+ thermo_set_bias, thermo_reset_bias, thermo_set_sensitivity,
+ thermo_reset_sensitivity
+};
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes an instance.
+ *
+ * @param[out] devp pointer to the @p HTS221Driver object
+ *
+ * @init
+ */
+void hts221ObjectInit(HTS221Driver *devp) {
+
+ devp->vmt = &vmt_device;
+ devp->hygro_if.vmt = &vmt_hygrometer;
+ devp->thermo_if.vmt = &vmt_thermometer;
+
+ devp->config = NULL;
+
+ devp->hygroaxes = HTS221_HYGRO_NUMBER_OF_AXES;
+ devp->thermoaxes = HTS221_THERMO_NUMBER_OF_AXES;
+
+ devp->hygrobias = 0.0f;
+ devp->thermobias = 0.0f;
+
+ devp->state = HTS221_STOP;
+}
+
+/**
+ * @brief Configures and activates HTS221 Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p HTS221Driver object
+ * @param[in] config pointer to the @p HTS221Config object
+ *
+ * @api
+ */
+void hts221Start(HTS221Driver *devp, const HTS221Config *config) {
+ uint8_t cr[2];
+ osalDbgCheck((devp != NULL) && (config != NULL));
+
+ osalDbgAssert((devp->state == HTS221_STOP) || (devp->state == HTS221_READY),
+ "hts221Start(), invalid state");
+
+ devp->config = config;
+
+#if HTS221_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+#endif /* HTS221_SHARED_I2C */
+
+ /* Intializing the I2C. */
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+
+ hts221Calibrate(devp);
+
+#if HTS221_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* HTS221_SHARED_I2C */
+
+
+ if(devp->config->hygrosensitivity == NULL) {
+ devp->hygrosensitivity = devp->hygrofactorysensitivity;
+ }
+ else{
+ /* Taking hygrometer sensitivity from user configurations */
+ devp->hygrosensitivity = *(devp->config->hygrosensitivity);
+ }
+
+ if(devp->config->hygrobias == NULL) {
+ devp->hygrobias = devp->hygrofactorybias;
+ }
+ else{
+ /* Taking hygrometer bias from user configurations */
+ devp->hygrobias = *(devp->config->hygrobias);
+ }
+
+ if(devp->config->thermosensitivity == NULL) {
+ devp->thermosensitivity = devp->thermofactorysensitivity;
+ }
+ else{
+ /* Taking thermometer sensitivity from user configurations */
+ devp->thermosensitivity = *(devp->config->thermosensitivity);
+ }
+
+ if(devp->config->thermobias == NULL) {
+ devp->thermobias = devp->thermofactorybias;
+ }
+ else{
+ /* Taking thermometer bias from user configurations */
+ devp->thermobias = *(devp->config->thermobias);
+ }
+
+ /* Control register 1 configuration block.*/
+ {
+ cr[0] = HTS221_AD_CTRL_REG1;
+ cr[1] = devp->config->outputdatarate | HTS221_CTRL_REG1_PD;
+#if HTS221_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[1] |= devp->config->blockdataupdate;
+#endif
+
+#if HTS221_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+#endif /* HTS221_SHARED_I2C */
+
+ hts221I2CWriteRegister(devp->config->i2cp, cr, 1);
+
+#if HTS221_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* HTS221_SHARED_I2C */
+ }
+
+ /* Average register configuration block.*/
+ {
+ cr[0] = HTS221_AD_AV_CONF;
+ cr[1] = 0x05;
+#if HTS221_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[1] = devp->config->hygroresolution | devp->config->thermoresolution;
+#endif
+
+#if HTS221_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+#endif /* HTS221_SHARED_I2C */
+
+ hts221I2CWriteRegister(devp->config->i2cp, cr, 1);
+
+#if HTS221_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* HTS221_SHARED_I2C */
+ }
+
+ /* This is the MEMS transient recovery time */
+ osalThreadSleepMilliseconds(5);
+
+ devp->state = HTS221_READY;
+}
+
+/**
+ * @brief Deactivates the HTS221 Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p HTS221Driver object
+ *
+ * @api
+ */
+void hts221Stop(HTS221Driver *devp) {
+ uint8_t cr[2];
+
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == HTS221_STOP) || (devp->state == HTS221_READY),
+ "hts221Stop(), invalid state");
+
+ if (devp->state == HTS221_READY) {
+
+#if HTS221_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+#endif /* HTS221_SHARED_I2C */
+
+ cr[0] = HTS221_AD_CTRL_REG1;
+ cr[1] = 0;
+ hts221I2CWriteRegister(devp->config->i2cp, cr, 1);
+
+ i2cStop(devp->config->i2cp);
+#if HTS221_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* HTS221_SHARED_I2C */
+ }
+ devp->state = HTS221_STOP;
+}
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/hts221.h b/ChibiOS_20.3.2/os/ex/devices/ST/hts221.h
new file mode 100644
index 0000000..d79972d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/hts221.h
@@ -0,0 +1,707 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file hts221.h
+ * @brief HTS221 MEMS interface module header.
+ *
+ *
+ * @addtogroup HTS221
+ * @ingroup EX_ST
+ * @{
+ */
+#ifndef _HTS221_H_
+#define _HTS221_H_
+
+#include "ex_hygrometer.h"
+#include "ex_thermometer.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Version identification
+ * @{
+ */
+/**
+ * @brief HTS221 driver version string.
+ */
+#define EX_HTS221_VERSION "1.1.2"
+
+/**
+ * @brief HTS221 driver version major number.
+ */
+#define EX_HTS221_MAJOR 1
+
+/**
+ * @brief HTS221 driver version minor number.
+ */
+#define EX_HTS221_MINOR 1
+
+/**
+ * @brief HTS221 driver version patch number.
+ */
+#define EX_HTS221_PATCH 2
+/** @} */
+
+/**
+ * @brief HTS221 hygrometer subsystem characteristics.
+ * @note Sensitivity is expressed as %rH/LSB whereas %rH stand for percentage
+ * of relative humidity.
+ * @note Bias is expressed as %rH.
+ * @{
+ */
+#define HTS221_HYGRO_NUMBER_OF_AXES 1U
+
+#define HTS221_HYGRO_SENS 0.00390625f
+#define HTS221_HYGRO_BIAS 0.0f
+/** @} */
+
+/**
+ * @brief HTS221 thermometer subsystem characteristics.
+ * @note Sensitivity is expressed as �C/LSB.
+ * @note Bias is expressed as �C.
+ *
+ * @{
+ */
+#define HTS221_THERMO_NUMBER_OF_AXES 1U
+
+#define HTS221_THERMO_SENS 0.0015625f
+#define HTS221_THERMO_BIAS 0.0f
+/** @} */
+
+/**
+ * @name HTS221 communication interfaces related bit masks
+ * @{
+ */
+#define HTS221_DI_MASK 0xFF
+#define HTS221_DI(n) (1 << n)
+#define HTS221_AD_MASK 0x3F
+#define HTS221_AD(n) (1 << n)
+#define HTS221_MS (1 << 6)
+#define HTS221_RW (1 << 7)
+
+#define HTS221_SUB_MS (1 << 7)
+
+#define HTS221_SAD 0x5F
+/** @} */
+
+/**
+ * @name HTS221 register addresses
+ * @{
+ */
+#define HTS221_AD_WHO_AM_I 0x0F
+#define HTS221_AD_AV_CONF 0x10
+#define HTS221_AD_CTRL_REG1 0x20
+#define HTS221_AD_CTRL_REG2 0x21
+#define HTS221_AD_CTRL_REG3 0x22
+#define HTS221_AD_STATUS_REG 0x27
+#define HTS221_AD_HUMIDITY_OUT_L 0x28
+#define HTS221_AD_HUMIDITY_OUT_H 0x29
+#define HTS221_AD_TEMP_OUT_L 0x2A
+#define HTS221_AD_TEMP_OUT_H 0x2B
+#define HTS221_AD_CALIB_0 0x30
+#define HTS221_AD_CALIB_1 0x31
+#define HTS221_AD_CALIB_2 0x32
+#define HTS221_AD_CALIB_3 0x33
+#define HTS221_AD_CALIB_4 0x34
+#define HTS221_AD_CALIB_5 0x35
+#define HTS221_AD_CALIB_6 0x36
+#define HTS221_AD_CALIB_7 0x37
+#define HTS221_AD_CALIB_8 0x38
+#define HTS221_AD_CALIB_9 0x39
+#define HTS221_AD_CALIB_A 0x3A
+#define HTS221_AD_CALIB_B 0x3B
+#define HTS221_AD_CALIB_C 0x3C
+#define HTS221_AD_CALIB_D 0x3D
+#define HTS221_AD_CALIB_E 0x3E
+#define HTS221_AD_CALIB_F 0x3F
+/** @} */
+
+/**
+ * @name HTS221_CTRL_REG1 register bits definitions
+ * @{
+ */
+#define HTS221_CTRL_REG1_MASK 0x87
+#define HTS221_CTRL_REG1_ODR0 (1 << 0)
+#define HTS221_CTRL_REG1_ODR1 (1 << 1)
+#define HTS221_CTRL_REG1_BDU (1 << 2)
+#define HTS221_CTRL_REG1_PD (1 << 7)
+/** @} */
+
+/**
+ * @name HTS221_CTRL_REG2 register bits definitions
+ * @{
+ */
+#define HTS221_CTRL_REG2_MASK 0x83
+#define HTS221_CTRL_REG2_ONE_SHOT (1 << 0)
+#define HTS221_CTRL_REG2_HEATER (1 << 1)
+#define HTS221_CTRL_REG2_BOOT (1 << 7)
+/** @} */
+
+/**
+ * @name HTS221_CTRL_REG3 register bits definitions
+ * @{
+ */
+#define HTS221_CTRL_REG3_MASK 0xC4
+#define HTS221_CTRL_REG3_DRDY (1 << 2)
+#define HTS221_CTRL_REG3_PP_OD (1 << 6)
+#define HTS221_CTRL_REG3_INT_H_L (1 << 7)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief HTS221 SPI interface switch.
+ * @details If set to @p TRUE the support for SPI is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(HTS221_USE_SPI) || defined(__DOXYGEN__)
+#define HTS221_USE_SPI FALSE
+#endif
+
+/**
+ * @brief HTS221 shared SPI switch.
+ * @details If set to @p TRUE the device acquires SPI bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION
+ */
+#if !defined(HTS221_SHARED_SPI) || defined(__DOXYGEN__)
+#define HTS221_SHARED_SPI FALSE
+#endif
+
+/**
+ * @brief HTS221 I2C interface switch.
+ * @details If set to @p TRUE the support for I2C is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(HTS221_USE_I2C) || defined(__DOXYGEN__)
+#define HTS221_USE_I2C TRUE
+#endif
+
+/**
+ * @brief HTS221 shared I2C switch.
+ * @details If set to @p TRUE the device acquires I2C bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION
+ */
+#if !defined(HTS221_SHARED_I2C) || defined(__DOXYGEN__)
+#define HTS221_SHARED_I2C FALSE
+#endif
+
+/**
+ * @brief HTS221 advanced configurations switch.
+ * @details If set to @p TRUE more configurations are available.
+ * @note The default is @p FALSE.
+ */
+#if !defined(HTS221_USE_ADVANCED) || defined(__DOXYGEN__)
+#define HTS221_USE_ADVANCED FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !(HTS221_USE_SPI ^ HTS221_USE_I2C)
+#error "HTS221_USE_SPI and HTS221_USE_I2C cannot be both true or both false"
+#endif
+
+#if HTS221_USE_SPI && !HAL_USE_SPI
+#error "HTS221_USE_SPI requires HAL_USE_SPI"
+#endif
+
+#if HTS221_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION
+#error "HTS221_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
+#endif
+
+#if HTS221_USE_I2C && !HAL_USE_I2C
+#error "HTS221_USE_I2C requires HAL_USE_I2C"
+#endif
+
+#if HTS221_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
+#error "HTS221_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
+#endif
+
+/*
+ * CHTODO: Add support for HTS221 over SPI.
+ */
+#if HTS221_USE_SPI
+#error "HTS221 over SPI still not supported."
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @name HTS221 data structures and types.
+ * @{
+ */
+/**
+ * @brief Structure representing a HTS221 driver.
+ */
+typedef struct HTS221Driver HTS221Driver;
+
+/**
+ * @brief HTS221 output data rate and bandwidth.
+ */
+typedef enum {
+ HTS221_ODR_ONE_SHOT = 0x00, /**< One shot. */
+ HTS221_ODR_1HZ = 0x01, /**< Output data rate 1 Hz. */
+ HTS221_ODR_7HZ = 0x02, /**< Output data rate 7 Hz. */
+ HTS221_ODR_12P5HZ = 0x03, /**< Output data rate 12.5 Hz. */
+}hts221_odr_t;
+
+/**
+ * @brief HTS221 humidity resolution.
+ */
+typedef enum {
+ HTS221_AVGH_4 = 0x00, /**< Number of internal average is 4. */
+ HTS221_AVGH_8 = 0x01, /**< Number of internal average is 8. */
+ HTS221_AVGH_16 = 0x02, /**< Number of internal average is 16. */
+ HTS221_AVGH_32 = 0x03, /**< Number of internal average is 32. */
+ HTS221_AVGH_64 = 0x04, /**< Number of internal average is 64. */
+ HTS221_AVGH_128 = 0x05, /**< Number of internal average is 128. */
+ HTS221_AVGH_256 = 0x06, /**< Number of internal average is 256. */
+ HTS221_AVGH_512 = 0x07 /**< Number of internal average is 512. */
+}hts221_avgh_t;
+
+/**
+ * @brief HTS221 temperature resolution.
+ */
+typedef enum {
+ HTS221_AVGT_2 = 0x00, /**< Number of internal average is 2. */
+ HTS221_AVGT_4 = 0x08, /**< Number of internal average is 4. */
+ HTS221_AVGT_8 = 0x10, /**< Number of internal average is 8. */
+ HTS221_AVGT_16 = 0x18, /**< Number of internal average is 16. */
+ HTS221_AVGT_32 = 0x20, /**< Number of internal average is 32. */
+ HTS221_AVGT_64 = 0x28, /**< Number of internal average is 64. */
+ HTS221_AVGT_128 = 0x30, /**< Number of internal average is 128. */
+ HTS221_AVGT_256 = 0x38, /**< Number of internal average is 256. */
+}hts221_avgt_t;
+
+/**
+ * @brief HTS221 block data update.
+ */
+typedef enum {
+ HTS221_BDU_CONTINUOUS = 0x00, /**< Block data continuously updated. */
+ HTS221_BDU_BLOCKED = 0x40 /**< Block data updated after reading. */
+}hts221_bdu_t;
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ HTS221_UNINIT = 0, /**< Not initialized. */
+ HTS221_STOP = 1, /**< Stopped. */
+ HTS221_READY = 2, /**< Ready. */
+} hts221_state_t;
+
+/**
+ * @brief HTS221 configuration structure.
+ */
+typedef struct {
+
+#if HTS221_USE_SPI || defined(__DOXYGEN__)
+ /**
+ * @brief SPI driver associated to this HTS221.
+ */
+ SPIDriver *spip;
+ /**
+ * @brief SPI configuration associated to this HTS221.
+ */
+ const SPIConfig *spicfg;
+#endif /* HTS221_USE_SPI */
+#if HTS221_USE_I2C || defined(__DOXYGEN__)
+ /**
+ * @brief I2C driver associated to this HTS221.
+ */
+ I2CDriver *i2cp;
+ /**
+ * @brief I2C configuration associated to this HTS221.
+ */
+ const I2CConfig *i2ccfg;
+#endif /* HTS221_USE_I2C */
+ /**
+ * @brief HTS221 hygrometer subsystem initial sensitivity.
+ */
+ float *hygrosensitivity;
+ /**
+ * @brief HTS221 hygrometer subsystem initial bias.
+ */
+ float *hygrobias;
+ /**
+ * @brief HTS221 thermometer subsystem initial sensitivity.
+ */
+ float *thermosensitivity;
+ /**
+ * @brief HTS221 thermometer subsystem initial bias.
+ */
+ float *thermobias;
+ /**
+ * @brief HTS221 output data rate selection.
+ */
+ hts221_odr_t outputdatarate;
+#if HTS221_USE_ADVANCED || defined(__DOXYGEN__)
+ /**
+ * @brief HTS221 block data update.
+ */
+ hts221_bdu_t blockdataupdate;
+ /**
+ * @brief HTS221 hygrometer subsystem resolution.
+ */
+ hts221_avgh_t hygroresolution;
+ /**
+ * @brief HTS221 thermometer subsystem resolution.
+ */
+ hts221_avgt_t thermoresolution;
+#endif
+} HTS221Config;
+
+/**
+ * @brief @p HTS221 specific methods.
+ * @note No methods so far, just a common ancestor interface.
+ */
+#define _hts221_methods_alone
+
+/**
+ * @brief @p HTS221 specific methods with inherited ones.
+ */
+#define _hts221_methods \
+ _base_object_methods \
+ _hts221_methods_alone
+
+/**
+ * @extends BaseObjectVMT
+ *
+ * @brief @p HTS221 virtual methods table.
+ */
+struct HTS221VMT {
+ _hts221_methods
+};
+
+/**
+ * @brief @p HTS221Driver specific data.
+ */
+#define _hts221_data \
+ /* Driver state.*/ \
+ hts221_state_t state; \
+ /* Current configuration data.*/ \
+ const HTS221Config *config; \
+ /* Hygrometer subsystem axes number.*/ \
+ size_t hygroaxes; \
+ /* Hygrometer subsystem current sensitivity.*/ \
+ float hygrosensitivity; \
+ /* Hygrometer subsystem current bias .*/ \
+ float hygrobias; \
+ /* Hygrometer subsystem factory sensitivity.*/ \
+ float hygrofactorysensitivity; \
+ /* Hygrometer subsystem factory bias .*/ \
+ float hygrofactorybias; \
+ /* Thermometer subsystem axes number.*/ \
+ size_t thermoaxes; \
+ /* Thermometer subsystem current sensitivity.*/ \
+ float thermosensitivity; \
+ /* Thermometer subsystem current bias.*/ \
+ float thermobias; \
+ /* Thermometer subsystem factory sensitivity.*/ \
+ float thermofactorysensitivity; \
+ /* Thermometer subsystem factory bias.*/ \
+ float thermofactorybias;
+
+/**
+ * @brief HTS221 2-axis hygrometer/thermometer class.
+ */
+struct HTS221Driver {
+ /** @brief Virtual Methods Table.*/
+ const struct HTS221VMT *vmt;
+ /** @brief Base hygrometer interface.*/
+ BaseHygrometer hygro_if;
+ /** @brief Base thermometer interface.*/
+ BaseThermometer thermo_if;
+ _hts221_data
+};
+/** @} */
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Return the number of axes of the BaseHygrometer.
+ *
+ * @param[in] devp pointer to @p HTS221Driver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define hts221HygrometerGetAxesNumber(devp) \
+ hygrometerGetAxesNumber(&((devp)->hygro_if))
+
+/**
+ * @brief Retrieves raw data from the BaseHygrometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseHygrometer axes number.
+ *
+ * @param[in] devp pointer to @p HTS221Driver.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define hts221HygrometerReadRaw(devp, axes) \
+ hygrometerReadRaw(&((devp)->hygro_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseHygrometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as %rH.
+ * @note The axes array must be at least the same size of the
+ * BaseHygrometer axes number.
+ *
+ * @param[in] devp pointer to @p HTS221Driver.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define hts221HygrometerReadCooked(devp, axes) \
+ hygrometerReadCooked(&((devp)->hygro_if), axes)
+
+/**
+ * @brief Set bias values for the BaseHygrometer.
+ * @note Bias must be expressed as %rH.
+ * @note The bias buffer must be at least the same size of the
+ * BaseHygrometer axes number.
+ *
+ * @param[in] devp pointer to @p HTS221Driver.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define hts221HygrometerSetBias(devp, bp) \
+ hygrometerSetBias(&((devp)->hygro_if), bp)
+
+/**
+ * @brief Reset bias values for the BaseHygrometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] devp pointer to @p HTS221Driver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define hts221HygrometerResetBias(devp) \
+ hygrometerResetBias(&((devp)->hygro_if))
+
+/**
+ * @brief Set sensitivity values for the BaseHygrometer.
+ * @note Sensitivity must be expressed as %rH/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseHygrometer axes number.
+ *
+ * @param[in] devp pointer to @p HTS221Driver.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define hts221HygrometerSetSensitivity(devp, sp) \
+ hygrometerSetSensitivity(&((devp)->hygro_if), sp)
+
+/**
+ * @brief Reset sensitivity values for the BaseHygrometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] devp pointer to @p HTS221Driver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define hts221HygrometerResetSensitivity(devp) \
+ hygrometerResetSensitivity(&((devp)->hygro_if))
+
+/**
+ * @brief Return the number of axes of the BaseThermometer.
+ *
+ * @param[in] devp pointer to @p HTS221Driver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define hts221ThermometerGetAxesNumber(devp) \
+ thermometerGetAxesNumber(&((devp)->thermo_if))
+
+/**
+ * @brief Retrieves raw data from the BaseThermometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] devp pointer to @p HTS221Driver.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define hts221ThermometerReadRaw(devp, axes) \
+ thermometerReadRaw(&((devp)->thermo_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseThermometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as �C.
+ * @note The axes array must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] devp pointer to @p HTS221Driver.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define hts221ThermometerReadCooked(devp, axes) \
+ thermometerReadCooked(&((devp)->thermo_if), axes)
+
+/**
+ * @brief Set bias values for the BaseThermometer.
+ * @note Bias must be expressed as �C.
+ * @note The bias buffer must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] devp pointer to @p HTS221Driver.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define hts221ThermometerSetBias(devp, bp) \
+ thermometerSetBias(&((devp)->thermo_if), bp)
+
+/**
+ * @brief Reset bias values for the BaseThermometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] devp pointer to @p HTS221Driver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define hts221ThermometerResetBias(devp) \
+ thermometerResetBias(&((devp)->thermo_if))
+
+/**
+ * @brief Set sensitivity values for the BaseThermometer.
+ * @note Sensitivity must be expressed as �C/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] devp pointer to @p HTS221Driver.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define hts221ThermometerSetSensitivity(devp, sp) \
+ thermometerSetSensitivity(&((devp)->thermo_if), sp)
+
+/**
+ * @brief Reset sensitivity values for the BaseThermometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] devp pointer to @p HTS221Driver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define hts221ThermometerResetSensitivity(devp) \
+ thermometerResetSensitivity(&((devp)->thermo_if))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void hts221ObjectInit(HTS221Driver *devp);
+ void hts221Start(HTS221Driver *devp, const HTS221Config *config);
+ void hts221Stop(HTS221Driver *devp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HTS221_H_ */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/hts221.mk b/ChibiOS_20.3.2/os/ex/devices/ST/hts221.mk
new file mode 100644
index 0000000..1b9223a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/hts221.mk
@@ -0,0 +1,10 @@
+# List of all the HTS221 device files.
+HTS221SRC := $(CHIBIOS)/os/ex/devices/ST/hts221.c
+
+# Required include directories
+HTS221INC := $(CHIBIOS)/os/ex/include \
+ $(CHIBIOS)/os/ex/devices/ST
+
+# Shared variables
+ALLCSRC += $(HTS221SRC)
+ALLINC += $(HTS221INC)
\ No newline at end of file
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/l3gd20.c b/ChibiOS_20.3.2/os/ex/devices/ST/l3gd20.c
new file mode 100644
index 0000000..7ac57aa
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/l3gd20.c
@@ -0,0 +1,642 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file l3gd20.c
+ * @brief L3GD20 MEMS interface module code.
+ *
+ * @addtogroup L3GD20
+ * @ingroup EX_ST
+ * @{
+ */
+
+#include "hal.h"
+#include "l3gd20.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#if (L3GD20_USE_SPI) || defined(__DOXYGEN__)
+/**
+ * @brief Reads a generic register value using SPI.
+ * @pre The SPI interface must be initialized and the driver started.
+ *
+ * @param[in] spip pointer to the SPI interface
+ * @param[in] reg starting register address
+ * @param[in] n number of consecutive registers to read
+ * @param[in] b pointer to an output buffer.
+ */
+static void l3gd20SPIReadRegister(SPIDriver *spip, uint8_t reg, size_t n,
+ uint8_t* b) {
+ uint8_t cmd;
+ (n == 1) ? (cmd = reg | L3GD20_RW) : (cmd = reg | L3GD20_RW | L3GD20_MS);
+ spiSelect(spip);
+ spiSend(spip, 1, &cmd);
+ spiReceive(spip, n, b);
+ spiUnselect(spip);
+}
+
+/**
+ * @brief Writes a value into a generic register using SPI.
+ * @pre The SPI interface must be initialized and the driver started.
+ *
+ * @param[in] spip pointer to the SPI interface
+ * @param[in] reg starting register address
+ * @param[in] n number of adjacent registers to write
+ * @param[in] b pointer to a buffer of values.
+ */
+static void l3gd20SPIWriteRegister(SPIDriver *spip, uint8_t reg, size_t n,
+ uint8_t* b) {
+ uint8_t cmd;
+ (n == 1) ? (cmd = reg) : (cmd = reg | L3GD20_MS);
+ spiSelect(spip);
+ spiSend(spip, 1, &cmd);
+ spiSend(spip, n, b);
+ spiUnselect(spip);
+}
+#endif /* L3GD20_USE_SPI */
+
+/**
+ * @brief Return the number of axes of the BaseGyroscope.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ *
+ * @return the number of axes.
+ */
+static size_t gyro_get_axes_number(void *ip) {
+ (void)ip;
+
+ return L3GD20_GYRO_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Retrieves raw data from the BaseGyroscope.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseGyroscope axes number.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t gyro_read_raw(void *ip, int32_t axes[L3GD20_GYRO_NUMBER_OF_AXES]) {
+ L3GD20Driver* devp;
+ int16_t tmp;
+ uint8_t i, buff [2 * L3GD20_GYRO_NUMBER_OF_AXES];
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == L3GD20_READY),
+ "gyro_read_raw(), invalid state");
+#if L3GD20_USE_SPI
+ osalDbgAssert((devp->config->spip->state == SPI_READY),
+ "gyro_read_raw(), channel not ready");
+
+#if L3GD20_SHARED_SPI
+ spiAcquireBus(devp->config->spip);
+ spiStart(devp->config->spip,
+ devp->config->spicfg);
+#endif /* L3GD20_SHARED_SPI */
+
+ l3gd20SPIReadRegister(devp->config->spip, L3GD20_AD_OUT_X_L,
+ L3GD20_GYRO_NUMBER_OF_AXES * 2, buff);
+
+#if L3GD20_SHARED_SPI
+ spiReleaseBus(devp->config->spip);
+#endif /* L3GD20_SHARED_SPI */
+#endif /* L3GD20_USE_SPI */
+
+ for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) {
+ tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
+ axes[i] = (int32_t)tmp;
+ }
+ return msg;
+}
+
+/**
+ * @brief Retrieves cooked data from the BaseGyroscope.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as DPS.
+ * @note The axes array must be at least the same size of the
+ * BaseGyroscope axes number.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t gyro_read_cooked(void *ip, float axes[]) {
+ L3GD20Driver* devp;
+ uint32_t i;
+ int32_t raw[L3GD20_GYRO_NUMBER_OF_AXES];
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == L3GD20_READY),
+ "gyro_read_cooked(), invalid state");
+
+ msg = gyro_read_raw(ip, raw);
+ for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++){
+ axes[i] = (raw[i] * devp->gyrosensitivity[i]) - devp->gyrobias[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Samples bias values for the BaseGyroscope.
+ * @note The L3GD20 shall not be moved during the whole procedure.
+ * @note After this function internal bias is automatically updated.
+ * @note The behavior of this function depends on @p L3GD20_BIAS_ACQ_TIMES
+ * and @p L3GD20_BIAS_SETTLING_US.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t gyro_sample_bias(void *ip) {
+ L3GD20Driver* devp;
+ uint32_t i, j;
+ int32_t raw[L3GD20_GYRO_NUMBER_OF_AXES];
+ int32_t buff[L3GD20_GYRO_NUMBER_OF_AXES] = {0, 0, 0};
+ msg_t msg;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == L3GD20_READY),
+ "gyro_sample_bias(), invalid state");
+#if L3GD20_USE_SPI
+ osalDbgAssert((devp->config->spip->state == SPI_READY),
+ "gyro_sample_bias(), channel not ready");
+#endif
+
+ for(i = 0; i < L3GD20_BIAS_ACQ_TIMES; i++){
+ msg = gyro_read_raw(ip, raw);
+ if(msg != MSG_OK)
+ return msg;
+ for(j = 0; j < L3GD20_GYRO_NUMBER_OF_AXES; j++){
+ buff[j] += raw[j];
+ }
+ osalThreadSleepMicroseconds(L3GD20_BIAS_SETTLING_US);
+ }
+
+ for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++){
+ devp->gyrobias[i] = (buff[i] / L3GD20_BIAS_ACQ_TIMES);
+ devp->gyrobias[i] *= devp->gyrosensitivity[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Set bias values for the BaseGyroscope.
+ * @note Bias must be expressed as DPS.
+ * @note The bias buffer must be at least the same size of the BaseGyroscope
+ * axes number.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t gyro_set_bias(void *ip, float *bp) {
+ L3GD20Driver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (bp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == L3GD20_READY),
+ "gyro_set_bias(), invalid state");
+
+ for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) {
+ devp->gyrobias[i] = bp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset bias values for the BaseGyroscope.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t gyro_reset_bias(void *ip) {
+ L3GD20Driver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == L3GD20_READY),
+ "gyro_reset_bias(), invalid state");
+
+ for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrobias[i] = L3GD20_GYRO_BIAS;
+ return msg;
+}
+
+/**
+ * @brief Set sensitivity values for the BaseGyroscope.
+ * @note Sensitivity must be expressed as DPS/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseGyroscope axes number.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t gyro_set_sensivity(void *ip, float *sp) {
+ L3GD20Driver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (sp !=NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == L3GD20_READY),
+ "gyro_set_sensivity(), invalid state");
+
+ for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) {
+ devp->gyrosensitivity[i] = sp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset sensitivity values for the BaseGyroscope.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t gyro_reset_sensivity(void *ip) {
+ L3GD20Driver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == L3GD20_READY),
+ "gyro_reset_sensivity(), invalid state");
+
+ if(devp->config->gyrofullscale == L3GD20_FS_250DPS)
+ for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrosensitivity[i] = L3GD20_GYRO_SENS_250DPS;
+ else if(devp->config->gyrofullscale == L3GD20_FS_500DPS)
+ for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrosensitivity[i] = L3GD20_GYRO_SENS_500DPS;
+ else if(devp->config->gyrofullscale == L3GD20_FS_2000DPS)
+ for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrosensitivity[i] = L3GD20_GYRO_SENS_2000DPS;
+ else {
+ osalDbgAssert(FALSE, "gyro_reset_sensivity(), full scale issue");
+ return MSG_RESET;
+ }
+ return msg;
+}
+
+/**
+ * @brief Changes the L3GD20Driver gyroscope fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p BaseGyroscope interface.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t gyro_set_full_scale(L3GD20Driver *devp, l3gd20_fs_t fs) {
+ float newfs, scale;
+ uint8_t i, cr;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == L3GD20_READY),
+ "gyro_set_full_scale(), invalid state");
+#if L3GD20_USE_SPI
+ osalDbgAssert((devp->config->spip->state == SPI_READY),
+ "gyro_set_full_scale(), channel not ready");
+#endif
+
+ if(fs == L3GD20_FS_250DPS) {
+ newfs = L3GD20_250DPS;
+ }
+ else if(fs == L3GD20_FS_500DPS) {
+ newfs = L3GD20_500DPS;
+ }
+ else if(fs == L3GD20_FS_2000DPS) {
+ newfs = L3GD20_2000DPS;
+ }
+ else {
+ return MSG_RESET;
+ }
+
+ if(newfs != devp->gyrofullscale) {
+ scale = newfs / devp->gyrofullscale;
+ devp->gyrofullscale = newfs;
+
+#if L3GD20_USE_SPI
+#if L3GD20_SHARED_SPI
+ spiAcquireBus(devp->config->spip);
+ spiStart(devp->config->spip,
+ devp->config->spicfg);
+#endif /* L3GD20_SHARED_SPI */
+
+ /* Updating register.*/
+ l3gd20SPIReadRegister(devp->config->spip,
+ L3GD20_AD_CTRL_REG4, 1, &cr);
+
+#if L3GD20_SHARED_SPI
+ spiReleaseBus(devp->config->spip);
+#endif /* L3GD20_SHARED_SPI */
+#endif /* L3GD20_USE_SPI */
+ cr &= ~(L3GD20_CTRL_REG4_FS_MASK);
+ cr |= fs;
+
+#if L3GD20_USE_SPI
+#if L3GD20_SHARED_SPI
+ spiAcquireBus(devp->config->spip);
+ spiStart(devp->config->spip,
+ devp->config->spicfg);
+#endif /* L3GD20_SHARED_SPI */
+
+ l3gd20SPIWriteRegister(devp->config->spip,
+ L3GD20_AD_CTRL_REG4, 1, &cr);
+#if L3GD20_SHARED_SPI
+ spiReleaseBus(devp->config->spip);
+#endif /* L3GD20_SHARED_SPI */
+#endif /* L3GD20_USE_SPI */
+
+ /* Scaling sensitivity and bias. Re-calibration is suggested anyway. */
+ for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) {
+ devp->gyrosensitivity[i] *= scale;
+ devp->gyrobias[i] *= scale;
+ }
+ }
+ return msg;
+}
+
+static const struct L3GD20VMT vmt_device = {
+ (size_t)0,
+ gyro_set_full_scale
+};
+
+static const struct BaseGyroscopeVMT vmt_gyroscope = {
+ sizeof(struct L3GD20VMT*),
+ gyro_get_axes_number, gyro_read_raw, gyro_read_cooked,
+ gyro_sample_bias, gyro_set_bias, gyro_reset_bias,
+ gyro_set_sensivity, gyro_reset_sensivity
+};
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes an instance.
+ *
+ * @param[out] devp pointer to the @p L3GD20Driver object
+ *
+ * @init
+ */
+void l3gd20ObjectInit(L3GD20Driver *devp) {
+ devp->vmt = &vmt_device;
+ devp->gyro_if.vmt = &vmt_gyroscope;
+
+ devp->config = NULL;
+
+ devp->state = L3GD20_STOP;
+}
+
+/**
+ * @brief Configures and activates L3GD20 Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p L3GD20Driver object
+ * @param[in] config pointer to the @p L3GD20Config object
+ *
+ * @api
+ */
+void l3gd20Start(L3GD20Driver *devp, const L3GD20Config *config) {
+ uint32_t i;
+ uint8_t cr[5] = {0, 0, 0, 0, 0};
+ osalDbgCheck((devp != NULL) && (config != NULL));
+
+ osalDbgAssert((devp->state == L3GD20_STOP) || (devp->state == L3GD20_READY),
+ "l3gd20Start(), invalid state");
+
+ devp->config = config;
+
+ /* Control register 1 configuration block.*/
+ {
+ cr[0] = L3GD20_CTRL_REG1_XEN | L3GD20_CTRL_REG1_YEN |
+ L3GD20_CTRL_REG1_ZEN | L3GD20_CTRL_REG1_PD |
+ devp->config->gyrooutputdatarate;
+#if L3GD20_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[0] |= devp->config->gyrobandwidth;
+#endif
+ }
+
+ /* Control register 2 configuration block.*/
+ {
+#if L3GD20_USE_ADVANCED || defined(__DOXYGEN__)
+ if(devp->config->gyrohpmode != L3GD20_HPM_BYPASSED)
+ cr[1] = devp->config->gyrohpmode | devp->config->gyrohpconfiguration;
+#endif
+ }
+
+ /* Control register 4 configuration block.*/
+ {
+ cr[3] = devp->config->gyrofullscale;
+#if L3GD20_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[3] |= devp->config->gyroblockdataupdate |
+ devp->config->gyroendianness;
+#endif
+ }
+
+ /* Control register 5 configuration block.*/
+ {
+#if L3GD20_USE_ADVANCED || defined(__DOXYGEN__)
+ if((devp->config->gyrohpmode != L3GD20_HPM_BYPASSED)) {
+ cr[4] = L3GD20_CTRL_REG5_HPEN;
+ if(devp->config->gyrolp2mode != L3GD20_LP2M_BYPASSED) {
+ cr[4] |= L3GD20_CTRL_REG5_INT1_SEL1 |
+ L3GD20_CTRL_REG5_OUT_SEL1;
+ }
+ else {
+ cr[4] |= L3GD20_CTRL_REG5_INT1_SEL0 |
+ L3GD20_CTRL_REG5_OUT_SEL0;
+ }
+ }
+#endif
+ }
+
+#if L3GD20_USE_SPI
+#if L3GD20_SHARED_SPI
+ spiAcquireBus(devp->config->spip);
+#endif /* L3GD20_SHARED_SPI */
+ spiStart(devp->config->spip,
+ devp->config->spicfg);
+
+ l3gd20SPIWriteRegister(devp->config->spip, L3GD20_AD_CTRL_REG1,
+ 5, cr);
+#if L3GD20_SHARED_SPI
+ spiReleaseBus(devp->config->spip);
+#endif /* L3GD20_SHARED_SPI */
+#endif /* L3GD20_USE_SPI */
+
+ /* Storing sensitivity information according to full scale.*/
+ if(devp->config->gyrofullscale == L3GD20_FS_250DPS) {
+ devp->gyrofullscale = L3GD20_250DPS;
+ for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) {
+ if (devp->config->gyrosensitivity == NULL)
+ devp->gyrosensitivity[i] = L3GD20_GYRO_SENS_250DPS;
+ else
+ devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
+ }
+ }
+ else if(devp->config->gyrofullscale == L3GD20_FS_500DPS) {
+ devp->gyrofullscale = L3GD20_500DPS;
+ for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) {
+ if (devp->config->gyrosensitivity == NULL)
+ devp->gyrosensitivity[i] = L3GD20_GYRO_SENS_500DPS;
+ else
+ devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
+ }
+ }
+ else if(devp->config->gyrofullscale == L3GD20_FS_2000DPS) {
+ devp->gyrofullscale = L3GD20_2000DPS;
+ for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) {
+ if (devp->config->gyrosensitivity == NULL)
+ devp->gyrosensitivity[i] = L3GD20_GYRO_SENS_2000DPS;
+ else
+ devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
+ }
+ }
+ else
+ osalDbgAssert(FALSE, "l3gd20Start(), full scale issue");
+
+ /* Storing bias information.*/
+ if(devp->config->gyrobias != NULL) {
+ for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) {
+ devp->gyrobias[i] = devp->config->gyrobias[i];
+ }
+ }
+ else {
+ for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrobias[i] = L3GD20_GYRO_BIAS;
+ }
+
+ /* This is the Gyroscope transient recovery time.*/
+ osalThreadSleepMilliseconds(10);
+
+ devp->state = L3GD20_READY;
+}
+
+/**
+ * @brief Deactivates the L3GD20 Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p L3GD20Driver object
+ *
+ * @api
+ */
+void l3gd20Stop(L3GD20Driver *devp) {
+ uint8_t cr1;
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == L3GD20_STOP) || (devp->state == L3GD20_READY),
+ "l3gd20Stop(), invalid state");
+
+ if (devp->state == L3GD20_READY) {
+ /* Disabling all axes and enabling power down mode.*/
+ cr1 = 0;
+
+#if L3GD20_USE_SPI
+#if L3GD20_SHARED_SPI
+ spiAcquireBus(devp->config->spip);
+ spiStart(devp->config->spip,
+ devp->config->spicfg);
+#endif /* L3GD20_SHARED_SPI */
+
+ l3gd20SPIWriteRegister(devp->config->spip, L3GD20_AD_CTRL_REG1,
+ 1, &cr1);
+ spiStop(devp->config->spip);
+
+#if L3GD20_SHARED_SPI
+ spiReleaseBus(devp->config->spip);
+#endif /* L3GD20_SHARED_SPI */
+#endif /* L3GD20_USE_SPI */
+ }
+ devp->state = L3GD20_STOP;
+}
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/l3gd20.h b/ChibiOS_20.3.2/os/ex/devices/ST/l3gd20.h
new file mode 100644
index 0000000..5528ecc
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/l3gd20.h
@@ -0,0 +1,725 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file l3gd20.h
+ * @brief L3GD20 MEMS interface module header.
+ *
+ * @addtogroup L3GD20
+ * @ingroup EX_ST
+ * @{
+ */
+#ifndef _L3GD20_H_
+#define _L3GD20_H_
+
+#include "ex_gyroscope.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Version identification
+ * @{
+ */
+/**
+ * @brief L3GD20 driver version string.
+ */
+#define EX_L3GD20_VERSION "1.1.2"
+
+/**
+ * @brief L3GD20 driver version major number.
+ */
+#define EX_L3GD20_MAJOR 1
+
+/**
+ * @brief L3GD20 driver version minor number.
+ */
+#define EX_L3GD20_MINOR 1
+
+/**
+ * @brief L3GD20 driver version patch number.
+ */
+#define EX_L3GD20_PATCH 2
+/** @} */
+
+/**
+ * @brief L3GD20 gyroscope system characteristics.
+ * @note Sensitivity is expressed as DPS/LSB whereas DPS stand for Degree
+ * per second [°/s].
+ * @note Bias is expressed as DPS.
+ *
+ * @{
+ */
+#define L3GD20_GYRO_NUMBER_OF_AXES 3U
+
+#define L3GD20_250DPS 250.0f
+#define L3GD20_500DPS 500.0f
+#define L3GD20_2000DPS 2000.0f
+
+#define L3GD20_GYRO_SENS_250DPS 0.00875f
+#define L3GD20_GYRO_SENS_500DPS 0.01750f
+#define L3GD20_GYRO_SENS_2000DPS 0.07000f
+
+#define L3GD20_GYRO_BIAS 0.0f
+/** @} */
+
+/**
+ * @name L3GD20 communication interfaces related bit masks
+ * @{
+ */
+#define L3GD20_DI_MASK 0xFF
+#define L3GD20_DI(n) (1 << n)
+#define L3GD20_AD_MASK 0x3F
+#define L3GD20_AD(n) (1 << n)
+#define L3GD20_MS (1 << 6)
+#define L3GD20_RW (1 << 7)
+/** @} */
+
+/**
+ * @name L3GD20 register addresses
+ * @{
+ */
+#define L3GD20_AD_WHO_AM_I 0x0F
+#define L3GD20_AD_CTRL_REG1 0x20
+#define L3GD20_AD_CTRL_REG2 0x21
+#define L3GD20_AD_CTRL_REG3 0x22
+#define L3GD20_AD_CTRL_REG4 0x23
+#define L3GD20_AD_CTRL_REG5 0x24
+#define L3GD20_AD_REFERENCE 0x25
+#define L3GD20_AD_OUT_TEMP 0x26
+#define L3GD20_AD_STATUS_REG 0x27
+#define L3GD20_AD_OUT_X_L 0x28
+#define L3GD20_AD_OUT_X_H 0x29
+#define L3GD20_AD_OUT_Y_L 0x2A
+#define L3GD20_AD_OUT_Y_H 0x2B
+#define L3GD20_AD_OUT_Z_L 0x2C
+#define L3GD20_AD_OUT_Z_H 0x2D
+#define L3GD20_AD_FIFO_CTRL_REG 0x2E
+#define L3GD20_AD_FIFO_SRC_REG 0x2F
+#define L3GD20_AD_INT1_CFG 0x30
+#define L3GD20_AD_INT1_SRC 0x31
+#define L3GD20_AD_INT1_THS_XH 0x32
+#define L3GD20_AD_INT1_THS_XL 0x33
+#define L3GD20_AD_INT1_THS_YH 0x34
+#define L3GD20_AD_INT1_THS_YL 0x35
+#define L3GD20_AD_INT1_THS_ZH 0x36
+#define L3GD20_AD_INT1_THS_ZL 0x37
+#define L3GD20_AD_INT1_DURATION 0x38
+/** @} */
+
+/**
+ * @name L3GD20_CTRL_REG1 register bits definitions
+ * @{
+ */
+#define L3GD20_CTRL_REG1_MASK 0xFF
+#define L3GD20_CTRL_REG1_XEN (1 << 0)
+#define L3GD20_CTRL_REG1_YEN (1 << 1)
+#define L3GD20_CTRL_REG1_ZEN (1 << 2)
+#define L3GD20_CTRL_REG1_PD (1 << 3)
+#define L3GD20_CTRL_REG1_BW0 (1 << 4)
+#define L3GD20_CTRL_REG1_BW1 (1 << 5)
+#define L3GD20_CTRL_REG1_DR0 (1 << 6)
+#define L3GD20_CTRL_REG1_DR1 (1 << 7)
+/** @} */
+
+/**
+ * @name L3GD20_CTRL_REG2 register bits definitions
+ * @{
+ */
+#define L3GD20_CTRL_REG2_MASK 0x3F
+#define L3GD20_CTRL_REG2_HPCF0 (1 << 0)
+#define L3GD20_CTRL_REG2_HPCF1 (1 << 1)
+#define L3GD20_CTRL_REG2_HPCF2 (1 << 2)
+#define L3GD20_CTRL_REG2_HPCF3 (1 << 3)
+#define L3GD20_CTRL_REG2_HPM0 (1 << 4)
+#define L3GD20_CTRL_REG2_HPM1 (1 << 5)
+/** @} */
+
+/**
+ * @name L3GD20_CTRL_REG3 register bits definitions
+ * @{
+ */
+#define L3GD20_CTRL_REG3_MASK 0xFF
+#define L3GD20_CTRL_REG3_I2_EMPTY (1 << 0)
+#define L3GD20_CTRL_REG3_I2_ORUN (1 << 1)
+#define L3GD20_CTRL_REG3_I2_WTM (1 << 2)
+#define L3GD20_CTRL_REG3_I2_DRDY (1 << 3)
+#define L3GD20_CTRL_REG3_PP_OD (1 << 4)
+#define L3GD20_CTRL_REG3_H_LACTIVE (1 << 5)
+#define L3GD20_CTRL_REG3_I1_BOOT (1 << 6)
+#define L3GD20_CTRL_REG3_I1_INT1 (1 << 7)
+/** @} */
+
+/**
+ * @name L3GD20_CTRL_REG4 register bits definitions
+ * @{
+ */
+#define L3GD20_CTRL_REG4_MASK 0xF1
+#define L3GD20_CTRL_REG4_SIM (1 << 0)
+#define L3GD20_CTRL_REG4_FS_MASK 0x30
+#define L3GD20_CTRL_REG4_FS0 (1 << 4)
+#define L3GD20_CTRL_REG4_FS1 (1 << 5)
+#define L3GD20_CTRL_REG4_BLE (1 << 6)
+#define L3GD20_CTRL_REG4_BDU (1 << 7)
+/** @} */
+
+/**
+ * @name L3GD20_CTRL_REG5 register bits definitions
+ * @{
+ */
+#define L3GD20_CTRL_REG5_MASK 0xDF
+#define L3GD20_CTRL_REG5_OUT_SEL0 (1 << 0)
+#define L3GD20_CTRL_REG5_OUT_SEL1 (1 << 1)
+#define L3GD20_CTRL_REG5_INT1_SEL0 (1 << 2)
+#define L3GD20_CTRL_REG5_INT1_SEL1 (1 << 3)
+#define L3GD20_CTRL_REG5_HPEN (1 << 4)
+#define L3GD20_CTRL_REG5_FIFO_EN (1 << 6)
+#define L3GD20_CTRL_REG5_BOOT (1 << 7)
+/** @} */
+
+/**
+ * @name L3GD20_INT1_CFG register bits definitions
+ * @{
+ */
+#define L3GD20_INT1_CFG_MASK 0xFF
+#define L3GD20_INT1_CFG_XLIE (1 << 0)
+#define L3GD20_INT1_CFG_XHIE (1 << 1)
+#define L3GD20_INT1_CFG_YLIE (1 << 2)
+#define L3GD20_INT1_CFG_YHIE (1 << 3)
+#define L3GD20_INT1_CFG_ZLIE (1 << 4)
+#define L3GD20_INT1_CFG_ZHIE (1 << 5)
+#define L3GD20_INT1_CFG_LIR (1 << 6)
+#define L3GD20_INT1_CFG_AND_OR (1 << 7)
+/** @} */
+
+/**
+ * @name L3GD20_INT1_SRC register bits definitions
+ * @{
+ */
+#define L3GD20_INT1_SRC_MASK 0x7F
+#define L3GD20_INT1_SRC_XL (1 << 0)
+#define L3GD20_INT1_SRC_XH (1 << 1)
+#define L3GD20_INT1_SRC_YL (1 << 2)
+#define L3GD20_INT1_SRC_YH (1 << 3)
+#define L3GD20_INT1_SRC_ZL (1 << 4)
+#define L3GD20_INT1_SRC_ZH (1 << 5)
+#define L3GD20_INT1_SRC_IA (1 << 6)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief L3GD20 SPI interface switch.
+ * @details If set to @p TRUE the support for SPI is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(L3GD20_USE_SPI) || defined(__DOXYGEN__)
+#define L3GD20_USE_SPI TRUE
+#endif
+
+/**
+ * @brief L3GD20 shared SPI switch.
+ * @details If set to @p TRUE the device acquires SPI bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(L3GD20_SHARED_SPI) || defined(__DOXYGEN__)
+#define L3GD20_SHARED_SPI FALSE
+#endif
+
+/**
+ * @brief L3GD20 I2C interface switch.
+ * @details If set to @p TRUE the support for I2C is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(L3GD20_USE_I2C) || defined(__DOXYGEN__)
+#define L3GD20_USE_I2C FALSE
+#endif
+
+/**
+ * @brief L3GD20 shared I2C switch.
+ * @details If set to @p TRUE the device acquires I2C bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(L3GD20_SHARED_I2C) || defined(__DOXYGEN__)
+#define L3GD20_SHARED_I2C FALSE
+#endif
+
+/**
+ * @brief L3GD20 advanced configurations switch.
+ * @details If set to @p TRUE more configurations are available.
+ * @note The default is @p FALSE.
+ */
+#if !defined(L3GD20_USE_ADVANCED) || defined(__DOXYGEN__)
+#define L3GD20_USE_ADVANCED FALSE
+#endif
+
+/**
+ * @brief Number of acquisitions for bias removal
+ * @details This is the number of acquisitions performed to compute the
+ * bias. A repetition is required in order to remove noise.
+ */
+#if !defined(L3GD20_BIAS_ACQ_TIMES) || defined(__DOXYGEN__)
+#define L3GD20_BIAS_ACQ_TIMES 50
+#endif
+
+/**
+ * @brief Settling time for bias removal
+ * @details This is the time between each bias acquisition.
+ */
+#if !defined(L3GD20_BIAS_SETTLING_US) || defined(__DOXYGEN__)
+#define L3GD20_BIAS_SETTLING_US 5000
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !(L3GD20_USE_SPI ^ L3GD20_USE_I2C)
+#error "L3GD20_USE_SPI and L3GD20_USE_I2C cannot be both true or both false"
+#endif
+
+#if L3GD20_USE_SPI && !HAL_USE_SPI
+#error "L3GD20_USE_SPI requires HAL_USE_SPI"
+#endif
+
+#if L3GD20_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION
+#error "L3GD20_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
+#endif
+
+#if L3GD20_USE_I2C && !HAL_USE_I2C
+#error "L3GD20_USE_I2C requires HAL_USE_I2C"
+#endif
+
+#if L3GD20_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
+#error "L3GD20_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
+#endif
+
+/*
+ * CHTODO: Add support for L3GD20 over I2C.
+ */
+#if L3GD20_USE_I2C
+#error "L3GD20 over I2C still not supported"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @name L3GD20 data structures and types.
+ * @{
+ */
+/**
+ * @brief Structure representing a L3GD20 driver.
+ */
+typedef struct L3GD20Driver L3GD20Driver;
+
+/**
+ * @brief L3GD20 full scale.
+ */
+typedef enum {
+ L3GD20_FS_250DPS = 0x00, /**< Full scale 250 degree per second. */
+ L3GD20_FS_500DPS = 0x10, /**< Full scale 500 degree per second. */
+ L3GD20_FS_2000DPS = 0x20 /**< Full scale 2000 degree per second. */
+} l3gd20_fs_t;
+
+/**
+ * @brief L3GD20 output data rate and bandwidth.
+ */
+typedef enum {
+ L3GD20_ODR_95HZ = 0x00, /**< Output data rate 95 Hz. */
+ L3GD20_ODR_190HZ = 0x40, /**< Output data rate 190 Hz. */
+ L3GD20_ODR_380HZ = 0x80, /**< Output data rate 380 Hz. */
+ L3GD20_ODR_760HZ = 0xC0 /**< Output data rate 760 Hz. */
+} l3gd20_odr_t;
+
+/**
+ * @brief L3GD20 low pass filter 1 bandwidth.
+ */
+typedef enum {
+ L3GD20_BW0 = 0x00, /**< LPF1 bandwidth. Depends on ODR. */
+ L3GD20_BW1 = 0x40, /**< LPF1 bandwidth. Depends on ODR. */
+ L3GD20_BW2 = 0x80, /**< LPF1 bandwidth. Depends on ODR. */
+ L3GD20_BW3 = 0xC0 /**< LPF1 bandwidth. Depends on ODR. */
+} l3gd20_bw_t;
+
+/**
+ * @brief L3GD20 block data update.
+ */
+typedef enum {
+ L3GD20_BDU_CONTINUOUS = 0x00, /**< Block data continuously updated. */
+ L3GD20_BDU_BLOCKED = 0x80 /**< Block data updated after reading. */
+} l3gd20_bdu_t;
+
+/**
+ * @brief L3GD20 HP filter mode.
+ */
+typedef enum {
+ L3GD20_HPM_NORMAL = 0x00, /**< Normal mode. */
+ L3GD20_HPM_REFERENCE = 0x10, /**< Reference signal for filtering. */
+ L3GD20_HPM_AUTORESET = 0x30, /**< Autoreset on interrupt event. */
+ L3GD20_HPM_BYPASSED = 0xFF /**< HP filter bypassed */
+} l3gd20_hpm_t;
+
+/**
+ * @brief L3GD20 HP configuration.
+ */
+typedef enum {
+ L3GD20_HPCF_0 = 0x00, /**< Depends on ODR (Table 26 for more).*/
+ L3GD20_HPCF_1 = 0x01, /**< Depends on ODR (Table 26 for more).*/
+ L3GD20_HPCF_2 = 0x02, /**< Depends on ODR (Table 26 for more).*/
+ L3GD20_HPCF_3 = 0x03, /**< Depends on ODR (Table 26 for more).*/
+ L3GD20_HPCF_4 = 0x04, /**< Depends on ODR (Table 26 for more).*/
+ L3GD20_HPCF_5 = 0x05, /**< Depends on ODR (Table 26 for more).*/
+ L3GD20_HPCF_6 = 0x06, /**< Depends on ODR (Table 26 for more).*/
+ L3GD20_HPCF_7 = 0x07, /**< Depends on ODR (Table 26 for more).*/
+ L3GD20_HPCF_8 = 0x08, /**< Depends on ODR (Table 26 for more).*/
+ L3GD20_HPCF_9 = 0x09 /**< Depends on ODR (Table 26 for more).*/
+} l3gd20_hpcf_t;
+
+/**
+ * @brief L3GD20 LP2 filter mode.
+ * @details To activate LP2 HP should be active
+ */
+typedef enum {
+ L3GD20_LP2M_ON = 0x00, /**< LP2 filter activated. */
+ L3GD20_LP2M_BYPASSED = 0xFF, /**< LP2 filter bypassed. */
+} l3gd20_lp2m_t;
+
+/**
+ * @brief L3GD20 endianness.
+ */
+typedef enum {
+ L3GD20_END_LITTLE = 0x00, /**< Little endian. */
+ L3GD20_END_BIG = 0x40 /**< Big endian. */
+} l3gd20_end_t;
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ L3GD20_UNINIT = 0, /**< Not initialized. */
+ L3GD20_STOP = 1, /**< Stopped. */
+ L3GD20_READY = 2 /**< Ready. */
+} l3gd20_state_t;
+
+/**
+ * @brief L3GD20 configuration structure.
+ */
+typedef struct {
+
+#if L3GD20_USE_SPI || defined(__DOXYGEN__)
+ /**
+ * @brief SPI driver associated to this L3GD20.
+ */
+ SPIDriver *spip;
+ /**
+ * @brief SPI configuration associated to this L3GD20.
+ */
+ const SPIConfig *spicfg;
+#endif /* L3GD20_USE_SPI */
+#if L3GD20_USE_I2C || defined(__DOXYGEN__)
+ /**
+ * @brief I2C driver associated to this L3GD20.
+ */
+ I2CDriver *i2cp;
+ /**
+ * @brief I2C configuration associated to this L3GD20.
+ */
+ const I2CConfig *i2ccfg;
+#endif /* L3GD20_USE_I2C */
+ /**
+ * @brief L3GD20 gyroscope system initial sensitivity.
+ */
+ float *gyrosensitivity;
+ /**
+ * @brief L3GD20 gyroscope system initial bias.
+ */
+ float *gyrobias;
+ /**
+ * @brief L3GD20 gyroscope system initial full scale value.
+ */
+ l3gd20_fs_t gyrofullscale;
+ /**
+ * @brief L3GD20 gyroscope system output data rate selection.
+ */
+ l3gd20_odr_t gyrooutputdatarate;
+#if L3GD20_USE_ADVANCED || defined(__DOXYGEN__)
+ /**
+ * @brief L3GD20 gyroscope system block data update.
+ */
+ l3gd20_bdu_t gyroblockdataupdate;
+ /**
+ * @brief L3GD20 gyroscope system endianness.
+ */
+ l3gd20_end_t gyroendianness;
+ /**
+ * @brief L3GD20 gyroscope system LP1 filter bandwidth.
+ */
+ l3gd20_bw_t gyrobandwidth;
+ /**
+ * @brief L3GD20 gyroscope system HP filter mode.
+ */
+ l3gd20_hpm_t gyrohpmode;
+ /**
+ * @brief L3GD20 gyroscope system HP configuration.
+ */
+ l3gd20_hpcf_t gyrohpconfiguration;
+ /**
+ * @brief L3GD20 gyroscope system LP2 filter mode.
+ * @details To activate LP2 HP should be active
+ */
+ l3gd20_lp2m_t gyrolp2mode;
+#endif
+} L3GD20Config;
+
+/**
+ * @brief @p L3GD20 specific methods.
+ */
+#define _l3gd20_methods_alone \
+ /* Change full scale value of L3GD20.*/ \
+ msg_t (*gyro_set_full_scale)(L3GD20Driver *devp, l3gd20_fs_t fs);
+
+/**
+ * @brief @p L3GD20 specific methods with inherited ones.
+ */
+#define _l3gd20_methods \
+ _base_object_methods \
+ _l3gd20_methods_alone
+
+/**
+ * @extends BaseObjectVMT
+ *
+ * @brief @p L3GD20 virtual methods table.
+ */
+struct L3GD20VMT {
+ _l3gd20_methods
+};
+
+/**
+ * @brief @p L3GD20Driver specific data.
+ */
+#define _l3gd20_data \
+ _base_sensor_data \
+ /* Driver state.*/ \
+ l3gd20_state_t state; \
+ /* Current configuration data.*/ \
+ const L3GD20Config *config; \
+ /* Gyroscope subsystem axes number.*/ \
+ size_t gyroaxes; \
+ /* Gyroscope subsystem current sensitivity.*/ \
+ float gyrosensitivity[L3GD20_GYRO_NUMBER_OF_AXES]; \
+ /* Gyroscope subsystem current Bias.*/ \
+ float gyrobias[L3GD20_GYRO_NUMBER_OF_AXES]; \
+ /* Gyroscope subsystem current full scale value.*/ \
+ float gyrofullscale;
+
+/**
+ * @brief L3GD20 3-axis gyroscope class.
+ */
+struct L3GD20Driver {
+ /** @brief Virtual Methods Table. */
+ const struct L3GD20VMT *vmt;
+ /** @brief Base gyroscope interface.*/
+ BaseGyroscope gyro_if;
+ _l3gd20_data
+};
+/** @} */
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Return the number of axes of the BaseGyroscope.
+ *
+ * @param[in] devp pointer to @p L3GD20Driver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define l3gd20GyroscopeGetAxesNumber(devp) \
+ gyroscopeGetAxesNumber(&((devp)->gyro_if))
+
+/**
+ * @brief Retrieves raw data from the BaseGyroscope.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseGyroscope axes number.
+ *
+ * @param[in] devp pointer to @p L3GD20Driver.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define l3gd20GyroscopeReadRaw(devp, axes) \
+ gyroscopeReadRaw(&((devp)->gyro_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseGyroscope.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as DPS.
+ * @note The axes array must be at least the same size of the
+ * BaseGyroscope axes number.
+ *
+ * @param[in] devp pointer to @p L3GD20Driver.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define l3gd20GyroscopeReadCooked(devp, axes) \
+ gyroscopeReadCooked(&((devp)->gyro_if), axes)
+
+/**
+ * @brief Samples bias values for the BaseGyroscope.
+ * @note The L3GD20 shall not be moved during the whole procedure.
+ * @note After this function internal bias is automatically updated.
+ * @note The behavior of this function depends on @p L3GD20_BIAS_ACQ_TIMES
+ * and @p L3GD20_BIAS_SETTLING_US.
+ *
+ * @param[in] devp pointer to @p L3GD20Driver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define l3gd20GyroscopeSampleBias(devp) \
+ gyroscopeSampleBias(&((devp)->gyro_if))
+
+/**
+ * @brief Set bias values for the BaseGyroscope.
+ * @note Bias must be expressed as DPS.
+ * @note The bias buffer must be at least the same size of the BaseGyroscope
+ * axes number.
+ *
+ * @param[in] devp pointer to @p L3GD20Driver.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define l3gd20GyroscopeSetBias(devp, bp) \
+ gyroscopeSetBias(&((devp)->gyro_if), bp)
+
+/**
+ * @brief Reset bias values for the BaseGyroscope.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] devp pointer to @p L3GD20Driver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define l3gd20GyroscopeResetBias(devp) \
+ gyroscopeResetBias(&((devp)->gyro_if))
+
+/**
+ * @brief Set sensitivity values for the BaseGyroscope.
+ * @note Sensitivity must be expressed as DPS/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseGyroscope axes number.
+ *
+ * @param[in] devp pointer to @p L3GD20Driver.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define l3gd20GyroscopeSetSensitivity(devp, sp) \
+ gyroscopeSetSensitivity(&((devp)->gyro_if), sp)
+
+/**
+ * @brief Reset sensitivity values for the BaseGyroscope.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] devp pointer to @p L3GD20Driver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define l3gd20GyroscopeResetSensitivity(devp) \
+ gyroscopeResetSensitivity(&((devp)->gyro_if))
+
+/**
+ * @brief Changes the L3GD20Driver gyroscope fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p L3GD20Driver.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define l3gd20GyroscopeSetFullScale(devp, fs) \
+ (devp)->vmt->acc_set_full_scale(devp, fs)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void l3gd20ObjectInit(L3GD20Driver *devp);
+ void l3gd20Start(L3GD20Driver *devp, const L3GD20Config *config);
+ void l3gd20Stop(L3GD20Driver *devp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _L3GD20_H_ */
+
+/** @} */
+
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/l3gd20.mk b/ChibiOS_20.3.2/os/ex/devices/ST/l3gd20.mk
new file mode 100644
index 0000000..94a4ec6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/l3gd20.mk
@@ -0,0 +1,10 @@
+# List of all the L3GD20 device files.
+L3GD20SRC := $(CHIBIOS)/os/ex/devices/ST/l3gd20.c
+
+# Required include directories
+L3GD20INC := $(CHIBIOS)/os/ex/include \
+ $(CHIBIOS)/os/ex/devices/ST
+
+# Shared variables
+ALLCSRC += $(L3GD20SRC)
+ALLINC += $(L3GD20INC)
\ No newline at end of file
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lis302dl.c b/ChibiOS_20.3.2/os/ex/devices/ST/lis302dl.c
new file mode 100644
index 0000000..099698d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lis302dl.c
@@ -0,0 +1,554 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file lis302dl.c
+ * @brief LIS302DL MEMS interface module code.
+ *
+ * @addtogroup LIS302DL
+ * @ingroup EX_ST
+ * @{
+ */
+
+#include "hal.h"
+#include "lis302dl.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#if (LIS302DL_USE_SPI) || defined(__DOXYGEN__)
+/**
+ * @brief Reads a generic register value using SPI.
+ * @pre The SPI interface must be initialized and the driver started.
+ *
+ * @param[in] spip pointer to the SPI interface
+ * @param[in] reg starting register address
+ * @param[in] n number of adjacent registers to write
+ * @param[in] b pointer to a buffer.
+ */
+static void lis302dlSPIReadRegister(SPIDriver *spip, uint8_t reg, size_t n,
+ uint8_t* b) {
+ uint8_t cmd;
+ (n == 1) ? (cmd = reg | LIS302DL_RW) : (cmd = reg | LIS302DL_RW | LIS302DL_MS);
+ spiSelect(spip);
+ spiSend(spip, 1, &cmd);
+ spiReceive(spip, n, b);
+ spiUnselect(spip);
+}
+
+/**
+ * @brief Writes a value into a generic register using SPI.
+ * @pre The SPI interface must be initialized and the driver started.
+ *
+ * @param[in] spip pointer to the SPI interface
+ * @param[in] reg starting register address
+ * @param[in] n number of adjacent registers to write
+ * @param[in] b pointer to a buffer of values.
+ */
+static void lis302dlSPIWriteRegister(SPIDriver *spip, uint8_t reg, size_t n,
+ uint8_t* b) {
+ uint8_t cmd;
+ (n == 1) ? (cmd = reg) : (cmd = reg | LIS302DL_MS);
+ spiSelect(spip);
+ spiSend(spip, 1, &cmd);
+ spiSend(spip, n, b);
+ spiUnselect(spip);
+}
+#endif /* LIS302DL_USE_SPI */
+
+/**
+ * @brief Return the number of axes of the BaseAccelerometer.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ *
+ * @return the number of axes.
+ */
+static size_t acc_get_axes_number(void *ip) {
+ (void)ip;
+
+ return LIS302DL_ACC_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Retrieves raw data from the BaseAccelerometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t acc_read_raw(void *ip, int32_t axes[]) {
+ LIS302DLDriver* devp;
+ uint8_t i, tmp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LIS302DLDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LIS302DL_READY),
+ "acc_read_raw(), invalid state");
+
+#if LIS302DL_USE_SPI
+#if LIS302DL_SHARED_SPI
+ osalDbgAssert((devp->config->spip->state == SPI_READY),
+ "acc_read_raw(), channel not ready");
+
+ spiAcquireBus(devp->config->spip);
+ spiStart(devp->config->spip,
+ devp->config->spicfg);
+#endif /* LIS302DL_SHARED_SPI */
+
+ for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++) {
+ lis302dlSPIReadRegister(devp->config->spip,
+ LIS302DL_AD_OUT_X + (i * 2), 1, &tmp);
+ axes[i] = (int32_t)((int8_t)tmp);
+ }
+
+#if LIS302DL_SHARED_SPI
+ spiReleaseBus(devp->config->spip);
+#endif /* LIS302DL_SHARED_SPI */
+#endif /* LIS302DL_USE_SPI */
+ return msg;
+}
+
+/**
+ * @brief Retrieves cooked data from the BaseAccelerometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as milli-G.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t acc_read_cooked(void *ip, float axes[]) {
+ LIS302DLDriver* devp;
+ uint32_t i;
+ int32_t raw[LIS302DL_ACC_NUMBER_OF_AXES];
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LIS302DLDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LIS302DL_READY),
+ "acc_read_cooked(), invalid state");
+
+ msg = acc_read_raw(ip, raw);
+ for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++) {
+ axes[i] = (raw[i] * devp->accsensitivity[i]) - devp->accbias[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Set bias values for the BaseAccelerometer.
+ * @note Bias must be expressed as milli-G.
+ * @note The bias buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t acc_set_bias(void *ip, float *bp) {
+ LIS302DLDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (bp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LIS302DLDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LIS302DL_READY),
+ "acc_set_bias(), invalid state");
+
+ for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++) {
+ devp->accbias[i] = bp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset bias values for the BaseAccelerometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t acc_reset_bias(void *ip) {
+ LIS302DLDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LIS302DLDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LIS302DL_READY),
+ "acc_reset_bias(), invalid state");
+
+ for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++)
+ devp->accbias[i] = LIS302DL_ACC_BIAS;
+ return msg;
+}
+
+/**
+ * @brief Set sensitivity values for the BaseAccelerometer.
+ * @note Sensitivity must be expressed as milli-G/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t acc_set_sensivity(void *ip, float *sp) {
+ LIS302DLDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LIS302DLDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgCheck((ip != NULL) && (sp != NULL));
+
+ osalDbgAssert((devp->state == LIS302DL_READY),
+ "acc_set_sensivity(), invalid state");
+
+ for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++) {
+ devp->accsensitivity[i] = sp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset sensitivity values for the BaseAccelerometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t acc_reset_sensivity(void *ip) {
+ LIS302DLDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LIS302DLDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LIS302DL_READY),
+ "acc_reset_sensivity(), invalid state");
+
+ if(devp->config->accfullscale == LIS302DL_ACC_FS_2G)
+ for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LIS302DL_ACC_SENS_2G;
+ else if(devp->config->accfullscale == LIS302DL_ACC_FS_8G)
+ for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LIS302DL_ACC_SENS_8G;
+ else {
+ osalDbgAssert(FALSE,
+ "acc_reset_sensivity(), accelerometer full scale issue");
+ return MSG_RESET;
+ }
+ return msg;
+}
+
+/**
+ * @brief Changes the LIS302DLDriver accelerometer fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p LIS302DLDriver interface.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t acc_set_full_scale(LIS302DLDriver *devp, lis302dl_acc_fs_t fs) {
+ float newfs, scale;
+ uint8_t i, cr;
+ msg_t msg;
+
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LIS302DL_READY),
+ "acc_set_full_scale(), invalid state");
+ osalDbgAssert((devp->config->spip->state == SPI_READY),
+ "acc_set_full_scale(), channel not ready");
+
+ /* Computing new fullscale value.*/
+ if(fs == LIS302DL_ACC_FS_2G) {
+ newfs = LIS302DL_ACC_2G;
+ }
+ else if(fs == LIS302DL_ACC_FS_8G) {
+ newfs = LIS302DL_ACC_8G;
+ }
+ else {
+ msg = MSG_RESET;
+ return msg;
+ }
+
+ if(newfs != devp->accfullscale) {
+ /* Computing scale value.*/
+ scale = newfs / devp->accfullscale;
+ devp->accfullscale = newfs;
+
+#if LIS302DL_USE_SPI
+#if LIS302DL_SHARED_SPI
+ spiAcquireBus(devp->config->spip);
+ spiStart(devp->config->spip,
+ devp->config->spicfg);
+#endif /* LIS302DL_SHARED_SPI */
+
+ /* Getting data from register.*/
+ lis302dlSPIReadRegister(devp->config->spip, LIS302DL_AD_CTRL_REG1, 1, &cr);
+
+#if LIS302DL_SHARED_SPI
+ spiReleaseBus(devp->config->spip);
+#endif /* LIS302DL_SHARED_SPI */
+#endif /* LIS302DL_USE_SPI */
+
+ cr &= ~(LIS302DL_CTRL_REG1_FS_MASK);
+ cr |= fs;
+
+#if LIS302DL_USE_SPI
+#if LIS302DL_SHARED_SPI
+ spiAcquireBus(devp->config->spip);
+ spiStart(devp->config->spip,
+ devp->config->spicfg);
+#endif /* LIS302DL_SHARED_SPI */
+
+ /* Getting data from register.*/
+ lis302dlSPIWriteRegister(devp->config->spip, LIS302DL_AD_CTRL_REG1, 1, &cr);
+
+#if LIS302DL_SHARED_SPI
+ spiReleaseBus(devp->config->spip);
+#endif /* LIS302DL_SHARED_SPI */
+#endif /* LIS302DL_USE_SPI */
+
+ /* Scaling sensitivity and bias. Re-calibration is suggested anyway. */
+ for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++) {
+ devp->accsensitivity[i] *= scale;
+ devp->accbias[i] *= scale;
+ }
+ }
+ return msg;
+}
+
+static const struct LIS302DLVMT vmt_device = {
+ (size_t)0,
+ acc_set_full_scale
+};
+
+static const struct BaseAccelerometerVMT vmt_accelerometer = {
+ sizeof(struct LIS302DLVMT*),
+ acc_get_axes_number, acc_read_raw, acc_read_cooked,
+ acc_set_bias, acc_reset_bias, acc_set_sensivity, acc_reset_sensivity
+};
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes an instance.
+ *
+ * @param[out] devp pointer to the @p LIS302DLDriver object
+ *
+ * @init
+ */
+void lis302dlObjectInit(LIS302DLDriver *devp) {
+ devp->vmt = &vmt_device;
+ devp->acc_if.vmt = &vmt_accelerometer;
+
+ devp->config = NULL;
+
+ devp->accaxes = LIS302DL_ACC_NUMBER_OF_AXES;
+
+ devp->state = LIS302DL_STOP;
+}
+
+/**
+ * @brief Configures and activates LIS302DL Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p LIS302DLDriver object
+ * @param[in] config pointer to the @p LIS302DLConfig object
+ *
+ * @api
+ */
+void lis302dlStart(LIS302DLDriver *devp, const LIS302DLConfig *config) {
+ uint32_t i;
+ uint8_t cr[2] = {0, 0};
+ osalDbgCheck((devp != NULL) && (config != NULL));
+
+ osalDbgAssert((devp->state == LIS302DL_STOP) || (devp->state == LIS302DL_READY),
+ "lis302dlStart(), invalid state");
+
+ devp->config = config;
+
+ /* Control register 1 configuration block.*/
+ {
+ cr[0] = LIS302DL_CTRL_REG1_XEN | LIS302DL_CTRL_REG1_YEN |
+ LIS302DL_CTRL_REG1_ZEN | LIS302DL_CTRL_REG1_PD |
+ devp->config->accoutputdatarate |
+ devp->config->accfullscale;
+ }
+
+ /* Control register 2 configuration block.*/
+ {
+#if LIS302DL_USE_ADVANCED || defined(__DOXYGEN__)
+ if(devp->config->hpmode != LIS302DL_HPM_BYPASSED)
+ cr[1] = devp->config->acchighpass;
+#endif
+ }
+
+#if LIS302DL_USE_SPI
+#if LIS302DL_SHARED_SPI
+ spiAcquireBus((devp)->config->spip);
+#endif /* LIS302DL_SHARED_SPI */
+ spiStart((devp)->config->spip, (devp)->config->spicfg);
+
+ lis302dlSPIWriteRegister(devp->config->spip, LIS302DL_AD_CTRL_REG1,
+ 2, cr);
+
+#if LIS302DL_SHARED_SPI
+ spiReleaseBus((devp)->config->spip);
+#endif /* LIS302DL_SHARED_SPI */
+#endif /* LIS302DL_USE_SPI */
+
+ /* Storing sensitivity information according to full scale value */
+ if(devp->config->accfullscale == LIS302DL_ACC_FS_2G) {
+ devp->accfullscale = LIS302DL_ACC_2G;
+ if(devp->config->accsensitivity == NULL)
+ for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LIS302DL_ACC_SENS_2G;
+ else
+ for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ else if(devp->config->accfullscale == LIS302DL_ACC_FS_8G) {
+ devp->accfullscale = LIS302DL_ACC_8G;
+ if(devp->config->accsensitivity == NULL)
+ for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LIS302DL_ACC_SENS_8G;
+ else
+ for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ else {
+ osalDbgAssert(FALSE, "lis302dlStart(), accelerometer full scale issue");
+ }
+
+ /* Storing bias information according to user setting */
+ if(devp->config->accbias != NULL)
+ for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++)
+ devp->accbias[i] = devp->config->accbias[i];
+ else
+ for(i = 0; i < LIS302DL_ACC_NUMBER_OF_AXES; i++)
+ devp->accbias[i] = LIS302DL_ACC_BIAS;
+
+ /* This is the Accelerometer transient recovery time */
+ osalThreadSleepMilliseconds(10);
+
+ devp->state = LIS302DL_READY;
+}
+
+/**
+ * @brief Deactivates the LIS302DL Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p LIS302DLDriver object
+ *
+ * @api
+ */
+void lis302dlStop(LIS302DLDriver *devp) {
+ uint8_t cr1;
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LIS302DL_STOP) ||
+ (devp->state == LIS302DL_READY),
+ "lis302dlStop(), invalid state");
+
+ if (devp->state == LIS302DL_READY) {
+#if LIS302DL_USE_SPI
+#if LIS302DL_SHARED_SPI
+ spiAcquireBus((devp)->config->spip);
+ spiStart((devp)->config->spip,
+ (devp)->config->spicfg);
+#endif /* LIS302DL_SHARED_SPI */
+ /* Disabling all axes and enabling power down mode.*/
+ cr1 = 0;
+ lis302dlSPIWriteRegister(devp->config->spip, LIS302DL_AD_CTRL_REG1, 1, &cr1);
+ spiStop((devp)->config->spip);
+#if LIS302DL_SHARED_SPI
+ spiReleaseBus((devp)->config->spip);
+#endif /* LIS302DL_SHARED_SPI */
+#endif /* LIS302DL_USE_SPI */
+ }
+ devp->state = LIS302DL_STOP;
+}
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lis302dl.h b/ChibiOS_20.3.2/os/ex/devices/ST/lis302dl.h
new file mode 100644
index 0000000..3c662f4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lis302dl.h
@@ -0,0 +1,566 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file lis302dl.h
+ * @brief LIS302DL MEMS interface module header.
+ *
+ * @addtogroup LIS302DL
+ * @ingroup EX_ST
+ * @{
+ */
+
+#ifndef _LIS302DL_H_
+#define _LIS302DL_H_
+
+#include "ex_accelerometer.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Version identification
+ * @{
+ */
+/**
+ * @brief LIS302DL driver version string.
+ */
+#define EX_LIS302DL_VERSION "1.1.1"
+
+/**
+ * @brief LIS302DL driver version major number.
+ */
+#define EX_LIS302DL_MAJOR 1
+
+/**
+ * @brief LIS302DL driver version minor number.
+ */
+#define EX_LIS302DL_MINOR 1
+
+/**
+ * @brief LIS302DL driver version patch number.
+ */
+#define EX_LIS302DL_PATCH 1
+/** @} */
+
+/**
+ * @brief LIS302DL accelerometer subsystem characteristics.
+ * @note Sensitivity is expressed as milli-G/LSB whereas
+ * 1 milli-G = 0.00980665 m/s^2.
+ * @note Bias is expressed as milli-G.
+ *
+ * @{
+ */
+#define LIS302DL_ACC_NUMBER_OF_AXES 3U
+
+#define LIS302DL_ACC_2G 2.0f
+#define LIS302DL_ACC_8G 8.0f
+
+#define LIS302DL_ACC_SENS_2G 18.0f
+#define LIS302DL_ACC_SENS_8G 72.0f
+
+#define LIS302DL_ACC_BIAS 0.0f
+/** @} */
+
+/**
+ * @name LIS302DL communication interfaces related bit masks
+ * @{
+ */
+#define LIS302DL_DI_MASK 0xFF
+#define LIS302DL_DI(n) (1 << n)
+#define LIS302DL_AD_MASK 0x3F
+#define LIS302DL_AD(n) (1 << n)
+#define LIS302DL_MS (1 << 6)
+#define LIS302DL_RW (1 << 7)
+/** @} */
+
+/**
+ * @name LIS302DL register addresses
+ * @{
+ */
+#define LIS302DL_AD_WHO_AM_I 0x0F
+#define LIS302DL_AD_CTRL_REG1 0x20
+#define LIS302DL_AD_CTRL_REG2 0x21
+#define LIS302DL_AD_CTRL_REG3 0x22
+#define LIS302DL_AD_HP_FILER_RESET 0x23
+#define LIS302DL_AD_STATUS_REG 0x27
+#define LIS302DL_AD_OUT_X 0x29
+#define LIS302DL_AD_OUT_Y 0x2B
+#define LIS302DL_AD_OUT_Z 0x2D
+#define LIS302DL_AD_FF_WU_CFG_1 0x30
+#define LIS302DL_AD_FF_WU_SRC_1 0x31
+#define LIS302DL_AD_FF_WU_THS_1 0x32
+#define LIS302DL_AD_FF_WU_DURATION_1 0x33
+#define LIS302DL_AD_FF_WU_CFG_2 0x34
+#define LIS302DL_AD_FF_WU_SRC_2 0x35
+#define LIS302DL_AD_FF_WU_THS_2 0x36
+#define LIS302DL_AD_FF_WU_DURATION_2 0x37
+#define LIS302DL_AD_CLICK_CFG 0x38
+#define LIS302DL_AD_CLICK_SRC 0x39
+#define LIS302DL_AD_CLICK_THSY_X 0x3B
+#define LIS302DL_AD_CLICK_THSZ 0x3C
+#define LIS302DL_AD_CLICK_TIME_LIMIT 0x3D
+#define LIS302DL_AD_CLICK_LATENCY 0x3E
+#define LIS302DL_AD_CLICK_WINDOW 0x3F
+/** @} */
+
+/**
+ * @name LIS302DL_CTRL_REG1 register bits definitions
+ * @{
+ */
+#define LIS302DL_CTRL_REG1_MASK 0xFF
+#define LIS302DL_CTRL_REG1_XEN (1 << 0)
+#define LIS302DL_CTRL_REG1_YEN (1 << 1)
+#define LIS302DL_CTRL_REG1_ZEN (1 << 2)
+#define LIS302DL_CTRL_REG1_STM (1 << 3)
+#define LIS302DL_CTRL_REG1_STP (1 << 4)
+#define LIS302DL_CTRL_REG1_FS_MASK 0x20
+#define LIS302DL_CTRL_REG1_FS (1 << 5)
+#define LIS302DL_CTRL_REG1_PD (1 << 6)
+#define LIS302DL_CTRL_REG1_DR (1 << 7)
+/** @} */
+
+/**
+ * @name LIS302DL_CTRL_REG2 register bits definitions
+ * @{
+ */
+#define LIS302DL_CTRL_REG2_MASK 0xDF
+#define LIS302DL_CTRL_REG2_HPCF1 (1 << 0)
+#define LIS302DL_CTRL_REG2_HPCF2 (1 << 1)
+#define LIS302DL_CTRL_REG2_HPFFWU1 (1 << 2)
+#define LIS302DL_CTRL_REG2_HPFFWU2 (1 << 3)
+#define LIS302DL_CTRL_REG2_FDS (1 << 4)
+#define LIS302DL_CTRL_REG2_BOOT (1 << 6)
+#define LIS302DL_CTRL_REG2_SIM (1 << 7)
+/** @} */
+
+/**
+ * @name LIS302DL_CTRL_REG3 register bits definitions
+ * @{
+ */
+#define LIS302DL_CTRL_REG3_MASK 0xFF
+#define LIS302DL_CTRL_REG3_I1CFG0 (1 << 0)
+#define LIS302DL_CTRL_REG3_I1CFG1 (1 << 1)
+#define LIS302DL_CTRL_REG3_I1CFG2 (1 << 2)
+#define LIS302DL_CTRL_REG3_I2CFG0 (1 << 3)
+#define LIS302DL_CTRL_REG3_I2CFG1 (1 << 4)
+#define LIS302DL_CTRL_REG3_I2CFG2 (1 << 5)
+#define LIS302DL_CTRL_REG3_PP_OD (1 << 6)
+#define LIS302DL_CTRL_REG3_IHL (1 << 7)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief LIS302DL SPI interface switch.
+ * @details If set to @p TRUE the support for SPI is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(LIS302DL_USE_SPI) || defined(__DOXYGEN__)
+#define LIS302DL_USE_SPI TRUE
+#endif
+
+/**
+ * @brief LIS302DL shared SPI switch.
+ * @details If set to @p TRUE the device acquires SPI bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(LIS302DL_SHARED_SPI) || defined(__DOXYGEN__)
+#define LIS302DL_SHARED_SPI FALSE
+#endif
+
+/**
+ * @brief LIS302DL I2C interface switch.
+ * @details If set to @p TRUE the support for I2C is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(LIS302DL_USE_I2C) || defined(__DOXYGEN__)
+#define LIS302DL_USE_I2C FALSE
+#endif
+
+/**
+ * @brief LIS302DL shared I2C switch.
+ * @details If set to @p TRUE the device acquires I2C bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(LIS302DL_SHARED_I2C) || defined(__DOXYGEN__)
+#define LIS302DL_SHARED_I2C FALSE
+#endif
+
+/**
+ * @brief LIS302DL advanced configurations switch.
+ * @details If set to @p TRUE more configurations are available.
+ * @note The default is @p FALSE.
+ */
+#if !defined(LIS302DL_USE_ADVANCED) || defined(__DOXYGEN__)
+#define LIS302DL_USE_ADVANCED FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !(LIS302DL_USE_SPI ^ LIS302DL_USE_I2C)
+#error "LIS302DL_USE_SPI and LIS302DL_USE_I2C cannot be both true or both false"
+#endif
+
+#if LIS302DL_USE_SPI && !HAL_USE_SPI
+#error "LIS302DL_USE_SPI requires HAL_USE_SPI"
+#endif
+
+#if LIS302DL_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION
+#error "LIS302DL_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
+#endif
+
+#if LIS302DL_USE_I2C && !HAL_USE_I2C
+#error "LIS302DL_USE_I2C requires HAL_USE_I2C"
+#endif
+
+#if LIS302DL_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
+#error "LIS302DL_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
+#endif
+
+/*
+ * CHTODO: Add support for LIS302DL over I2C.
+ */
+#if LIS302DL_USE_I2C
+#error "LIS302DL over I2C still not supported"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @name LIS302DL data structures and types
+ * @{
+ */
+/**
+ * @brief Structure representing a LIS302DL driver.
+ */
+typedef struct LIS302DLDriver LIS302DLDriver;
+
+/**
+ * @brief LIS302DL full scale.
+ */
+typedef enum {
+ LIS302DL_ACC_FS_2G = 0x00, /**< Full scale �2g. */
+ LIS302DL_ACC_FS_8G = 0x20 /**< Full scale �8g. */
+}lis302dl_acc_fs_t;
+
+/**
+ * @brief LIS302DL output data rate and bandwidth.
+ */
+typedef enum {
+ LIS302DL_ACC_ODR_100HZ = 0x00, /**< ODR 100 Hz. */
+ LIS302DL_ACC_ODR_400HZ = 0x80 /**< ODR 400 Hz. */
+}lis302dl_acc_odr_t;
+
+/**
+ * @brief LIS302DL high pass filtering.
+ */
+typedef enum {
+ LIS302DL_ACC_HP_DISABLED = 0x00, /**< HP bypassed. */
+ LIS302DL_ACC_HP_0 = 0x10, /**< HP cutoff 2Hz (ODR 100Hz) or 8Hz */
+ LIS302DL_ACC_HP_1 = 0x11, /**< HP cutoff 1Hz or 4Hz */
+ LIS302DL_ACC_HP_2 = 0x12, /**< HP cutoff 0.5Hz or 2Hz */
+ LIS302DL_ACC_HP_3 = 0x13 /**< HP cutoff 0.25Hz or 1Hz */
+}lis302dl_acc_hp_t;
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ LIS302DL_UNINIT = 0, /**< Not initialized. */
+ LIS302DL_STOP = 1, /**< Stopped. */
+ LIS302DL_READY = 2, /**< Ready. */
+} lis302dl_state_t;
+
+/**
+ * @brief LIS302DL configuration structure.
+ */
+typedef struct {
+
+#if (LIS302DL_USE_SPI) || defined(__DOXYGEN__)
+ /**
+ * @brief SPI driver associated to this LIS302DL.
+ */
+ SPIDriver *spip;
+ /**
+ * @brief SPI configuration associated to this LIS302DL.
+ */
+ const SPIConfig *spicfg;
+#endif /* LIS302DL_USE_SPI */
+#if (LIS302DL_USE_I2C) || defined(__DOXYGEN__)
+ /**
+ * @brief I2C driver associated to this LIS302DL.
+ */
+ I2CDriver *i2cp;
+ /**
+ * @brief I2C configuration associated to this LIS302DL.
+ */
+ const I2CConfig *i2ccfg;
+#endif /* LIS302DL_USE_I2C */
+ /**
+ * @brief LIS302DL accelerometer subsystem initial sensitivity.
+ */
+ float *accsensitivity;
+ /**
+ * @brief LIS302DL accelerometer subsystem initial bias.
+ */
+ float *accbias;
+ /**
+ * @brief LIS302DL accelerometer subsystem initial full scale.
+ */
+ lis302dl_acc_fs_t accfullscale;
+ /**
+ * @brief LIS302DL output data rate selection.
+ */
+ lis302dl_acc_odr_t accoutputdatarate;
+#if LIS302DL_USE_ADVANCED || defined(__DOXYGEN__)
+ /**
+ * @brief LIS302DL high pass filtering.
+ */
+ lis302dl_acc_hp_t acchighpass;
+#endif
+} LIS302DLConfig;
+
+/**
+ * @brief @p LIS302DL specific methods.
+ */
+#define _lis302dl_methods_alone \
+ /* Change full scale value of LIS302DL .*/ \
+ msg_t (*set_full_scale)(LIS302DLDriver *devp, lis302dl_acc_fs_t fs);
+
+
+/**
+ * @brief @p LIS302DL specific methods with inherited ones.
+ */
+#define _lis302dl_methods \
+ _base_object_methods \
+ _lis302dl_methods_alone
+
+/**
+ * @extends BaseObjectVMT
+ *
+ * @brief @p LIS302DL accelerometer virtual methods table.
+ */
+struct LIS302DLVMT {
+ _lis302dl_methods
+};
+
+/**
+ * @brief @p LIS302DLDriver specific data.
+ */
+#define _lis302dl_data \
+ /* Driver state.*/ \
+ lis302dl_state_t state; \
+ /* Current configuration data.*/ \
+ const LIS302DLConfig *config; \
+ /* Accelerometer subsystem axes number.*/ \
+ size_t accaxes; \
+ /* Current sensitivity.*/ \
+ float accsensitivity[LIS302DL_ACC_NUMBER_OF_AXES]; \
+ /* Bias data.*/ \
+ int32_t accbias[LIS302DL_ACC_NUMBER_OF_AXES]; \
+ /* Current full scale value.*/ \
+ float accfullscale;
+
+/**
+ * @brief LIS302DL 3-axis accelerometer class.
+ */
+struct LIS302DLDriver {
+ /** @brief Virtual Methods Table.*/
+ const struct LIS302DLVMT *vmt;
+ /** @brief Base accelerometer interface.*/
+ BaseAccelerometer acc_if;
+ _lis302dl_data
+};
+/** @} */
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Return the number of axes of the BaseAccelerometer.
+ *
+ * @param[in] devp pointer to @p LIS302DLDriver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define lis302dlAccelerometerGetAxesNumber(devp) \
+ accelerometerGetAxesNumber(&((devp)->acc_if))
+
+/**
+ * @brief Retrieves raw data from the BaseAccelerometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LIS302DLDriver.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lis302dlAccelerometerReadRaw(devp, axes) \
+ accelerometerReadRaw(&((devp)->acc_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseAccelerometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as milli-G.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LIS302DLDriver.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lis302dlAccelerometerReadCooked(devp, axes) \
+ accelerometerReadCooked(&((devp)->acc_if), axes)
+
+/**
+ * @brief Set bias values for the BaseAccelerometer.
+ * @note Bias must be expressed as milli-G.
+ * @note The bias buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LIS302DLDriver.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lis302dlAccelerometerSetBias(devp, bp) \
+ accelerometerSetBias(&((devp)->acc_if), bp)
+
+/**
+ * @brief Reset bias values for the BaseAccelerometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] devp pointer to @p LIS302DLDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lis302dlAccelerometerResetBias(devp) \
+ accelerometerResetBias(&((devp)->acc_if))
+
+/**
+ * @brief Set sensitivity values for the BaseAccelerometer.
+ * @note Sensitivity must be expressed as milli-G/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LIS302DLDriver.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lis302dlAccelerometerSetSensitivity(devp, sp) \
+ accelerometerSetSensitivity(&((devp)->acc_if), sp)
+
+/**
+ * @brief Reset sensitivity values for the BaseAccelerometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] devp pointer to @p LIS302DLDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lis302dlAccelerometerResetSensitivity(devp) \
+ accelerometerResetSensitivity(&((devp)->acc_if))
+
+/**
+ * @brief Changes the LIS302DLDriver accelerometer fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p LIS302DLDriver.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lis302dlAccelerometerSetFullScale(devp, fs) \
+ (devp)->vmt->acc_set_full_scale(devp, fs)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void lis302dlObjectInit(LIS302DLDriver *devp);
+ void lis302dlStart(LIS302DLDriver *devp, const LIS302DLConfig *config);
+ void lis302dlStop(LIS302DLDriver *devp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIS302DL_H_ */
+
+/** @} */
+
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lis302dl.mk b/ChibiOS_20.3.2/os/ex/devices/ST/lis302dl.mk
new file mode 100644
index 0000000..b7850ba
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lis302dl.mk
@@ -0,0 +1,10 @@
+# List of all the LIS302DL device files.
+LIS302DLSRC := $(CHIBIOS)/os/ex/devices/ST/lis302dl.c
+
+# Required include directories
+LIS302DLINC := $(CHIBIOS)/os/ex/include \
+ $(CHIBIOS)/os/ex/devices/ST
+
+# Shared variables
+ALLCSRC += $(LIS302DLSRC)
+ALLINC += $(LIS302DLINC)
\ No newline at end of file
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lis3dsh.c b/ChibiOS_20.3.2/os/ex/devices/ST/lis3dsh.c
new file mode 100644
index 0000000..865ff79
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lis3dsh.c
@@ -0,0 +1,641 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file lis3dsh.c
+ * @brief LIS3DSH MEMS interface module code.
+ *
+ * @addtogroup LIS3DSH
+ * @ingroup EX_ST
+ * @{
+ */
+
+#include "hal.h"
+#include "lis3dsh.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#if (LIS3DSH_USE_SPI) || defined(__DOXYGEN__)
+/**
+ * @brief Reads a generic register value using SPI.
+ * @pre The SPI interface must be initialized and the driver started.
+ * @note Multiple write/read requires proper settings in CTRL_REG6.
+ *
+ * @param[in] spip pointer to the SPI interface
+ * @param[in] reg starting register address
+ * @param[in] n number of adjacent registers to write
+ * @param[in] b pointer to a buffer.
+ */
+static void lis3dshSPIReadRegister(SPIDriver *spip, uint8_t reg, size_t n,
+ uint8_t* b) {
+ uint8_t cmd;
+ cmd = reg | LIS3DSH_RW;
+ spiSelect(spip);
+ spiSend(spip, 1, &cmd);
+ spiReceive(spip, n, b);
+ spiUnselect(spip);
+}
+
+/**
+ * @brief Writes a value into a generic register using SPI.
+ * @pre The SPI interface must be initialized and the driver started.
+ * @note Multiple write/read requires proper settings in CTRL_REG6.
+ *
+ * @param[in] spip pointer to the SPI interface
+ * @param[in] reg starting register address
+ * @param[in] n number of adjacent registers to write
+ * @param[in] b pointer to a buffer of values.
+ */
+static void lis3dshSPIWriteRegister(SPIDriver *spip, uint8_t reg, size_t n,
+ uint8_t* b) {
+ uint8_t cmd;
+ cmd = reg;
+ spiSelect(spip);
+ spiSend(spip, 1, &cmd);
+ spiSend(spip, n, b);
+ spiUnselect(spip);
+}
+#endif /* LIS3DSH_USE_SPI */
+
+/**
+ * @brief Return the number of axes of the BaseAccelerometer.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ *
+ * @return the number of axes.
+ */
+static size_t acc_get_axes_number(void *ip) {
+ (void)ip;
+
+ return LIS3DSH_ACC_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Retrieves raw data from the BaseAccelerometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t acc_read_raw(void *ip, int32_t axes[]) {
+ LIS3DSHDriver* devp;
+ uint8_t buff [LIS3DSH_ACC_NUMBER_OF_AXES * 2], i;
+ int16_t tmp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LIS3DSHDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LIS3DSH_READY),
+ "acc_read_raw(), invalid state");
+
+#if LIS3DSH_USE_SPI
+#if LIS3DSH_SHARED_SPI
+ osalDbgAssert((devp->config->spip->state == SPI_READY),
+ "acc_read_raw(), channel not ready");
+
+ spiAcquireBus(devp->config->spip);
+ spiStart(devp->config->spip,
+ devp->config->spicfg);
+#endif /* LIS3DSH_SHARED_SPI */
+
+ lis3dshSPIReadRegister(devp->config->spip, LIS3DSH_AD_OUT_X_L,
+ LIS3DSH_ACC_NUMBER_OF_AXES * 2, buff);
+
+#if LIS3DSH_SHARED_SPI
+ spiReleaseBus(devp->config->spip);
+#endif /* LIS3DSH_SHARED_SPI */
+#endif /* LIS3DSH_USE_SPI */
+
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++) {
+ tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
+ axes[i] = (int32_t)tmp;
+ }
+ return msg;
+}
+
+/**
+ * @brief Retrieves cooked data from the BaseAccelerometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as milli-G.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t acc_read_cooked(void *ip, float axes[]) {
+ LIS3DSHDriver* devp;
+ uint32_t i;
+ int32_t raw[LIS3DSH_ACC_NUMBER_OF_AXES];
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LIS3DSHDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LIS3DSH_READY),
+ "acc_read_cooked(), invalid state");
+
+ msg = acc_read_raw(ip, raw);
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++) {
+ axes[i] = (raw[i] * devp->accsensitivity[i]) - devp->accbias[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Set bias values for the BaseAccelerometer.
+ * @note Bias must be expressed as milli-G.
+ * @note The bias buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t acc_set_bias(void *ip, float *bp) {
+ LIS3DSHDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (bp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LIS3DSHDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LIS3DSH_READY),
+ "acc_set_bias(), invalid state");
+
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++) {
+ devp->accbias[i] = bp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset bias values for the BaseAccelerometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t acc_reset_bias(void *ip) {
+ LIS3DSHDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LIS3DSHDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LIS3DSH_READY),
+ "acc_reset_bias(), invalid state");
+
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
+ devp->accbias[i] = LIS3DSH_ACC_BIAS;
+ return msg;
+}
+
+/**
+ * @brief Set sensitivity values for the BaseAccelerometer.
+ * @note Sensitivity must be expressed as milli-G/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t acc_set_sensivity(void *ip, float *sp) {
+ LIS3DSHDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LIS3DSHDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgCheck((ip != NULL) && (sp != NULL));
+
+ osalDbgAssert((devp->state == LIS3DSH_READY),
+ "acc_set_sensivity(), invalid state");
+
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++) {
+ devp->accsensitivity[i] = sp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset sensitivity values for the BaseAccelerometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t acc_reset_sensivity(void *ip) {
+ LIS3DSHDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LIS3DSHDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LIS3DSH_READY),
+ "acc_reset_sensivity(), invalid state");
+
+ if(devp->config->accfullscale == LIS3DSH_ACC_FS_2G)
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LIS3DSH_ACC_SENS_2G;
+ else if(devp->config->accfullscale == LIS3DSH_ACC_FS_4G)
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LIS3DSH_ACC_SENS_4G;
+ else if(devp->config->accfullscale == LIS3DSH_ACC_FS_6G)
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LIS3DSH_ACC_SENS_6G;
+ else if(devp->config->accfullscale == LIS3DSH_ACC_FS_8G)
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LIS3DSH_ACC_SENS_8G;
+ else if(devp->config->accfullscale == LIS3DSH_ACC_FS_16G)
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LIS3DSH_ACC_SENS_16G;
+ else {
+ osalDbgAssert(FALSE,
+ "acc_reset_sensivity(), accelerometer full scale issue");
+ return MSG_RESET;
+ }
+ return msg;
+}
+
+/**
+ * @brief Changes the LIS3DSHDriver accelerometer fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p LIS3DSHDriver interface.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t acc_set_full_scale(LIS3DSHDriver *devp, lis3dsh_acc_fs_t fs) {
+ float newfs, scale;
+ uint8_t i, cr;
+ msg_t msg;
+
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LIS3DSH_READY),
+ "acc_set_full_scale(), invalid state");
+ osalDbgAssert((devp->config->spip->state == SPI_READY),
+ "acc_set_full_scale(), channel not ready");
+
+ /* Computing new fullscale value.*/
+ if(fs == LIS3DSH_ACC_FS_2G) {
+ newfs = LIS3DSH_ACC_2G;
+ }
+ else if(fs == LIS3DSH_ACC_FS_4G) {
+ newfs = LIS3DSH_ACC_4G;
+ }
+ else if(fs == LIS3DSH_ACC_FS_6G) {
+ newfs = LIS3DSH_ACC_6G;
+ }
+ else if(fs == LIS3DSH_ACC_FS_8G) {
+ newfs = LIS3DSH_ACC_8G;
+ }
+ else if(fs == LIS3DSH_ACC_FS_16G) {
+ newfs = LIS3DSH_ACC_16G;
+ }
+ else {
+ msg = MSG_RESET;
+ return msg;
+ }
+
+ if(newfs != devp->accfullscale) {
+ /* Computing scale value.*/
+ scale = newfs / devp->accfullscale;
+ devp->accfullscale = newfs;
+
+#if LIS3DSH_USE_SPI
+#if LIS3DSH_SHARED_SPI
+ spiAcquireBus(devp->config->spip);
+ spiStart(devp->config->spip,
+ devp->config->spicfg);
+#endif /* LIS3DSH_SHARED_SPI */
+
+ /* Getting data from register.*/
+ lis3dshSPIReadRegister(devp->config->spip, LIS3DSH_AD_CTRL_REG5, 1, &cr);
+
+#if LIS3DSH_SHARED_SPI
+ spiReleaseBus(devp->config->spip);
+#endif /* LIS3DSH_SHARED_SPI */
+#endif /* LIS3DSH_USE_SPI */
+
+ cr &= ~(LIS3DSH_CTRL_REG5_FS_MASK);
+ cr |= fs;
+
+#if LIS3DSH_USE_SPI
+#if LIS3DSH_SHARED_SPI
+ spiAcquireBus(devp->config->spip);
+ spiStart(devp->config->spip,
+ devp->config->spicfg);
+#endif /* LIS3DSH_SHARED_SPI */
+
+ /* Getting data from register.*/
+ lis3dshSPIWriteRegister(devp->config->spip, LIS3DSH_AD_CTRL_REG5, 1, &cr);
+
+#if LIS3DSH_SHARED_SPI
+ spiReleaseBus(devp->config->spip);
+#endif /* LIS3DSH_SHARED_SPI */
+#endif /* LIS3DSH_USE_SPI */
+
+ /* Scaling sensitivity and bias. Re-calibration is suggested anyway. */
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++) {
+ devp->accsensitivity[i] *= scale;
+ devp->accbias[i] *= scale;
+ }
+ }
+ return msg;
+}
+
+static const struct LIS3DSHVMT vmt_device = {
+ (size_t)0,
+ acc_set_full_scale
+};
+
+static const struct BaseAccelerometerVMT vmt_accelerometer = {
+ sizeof(struct LIS3DSHVMT*),
+ acc_get_axes_number, acc_read_raw, acc_read_cooked,
+ acc_set_bias, acc_reset_bias, acc_set_sensivity, acc_reset_sensivity
+};
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes an instance.
+ *
+ * @param[out] devp pointer to the @p LIS3DSHDriver object
+ *
+ * @init
+ */
+void lis3dshObjectInit(LIS3DSHDriver *devp) {
+ devp->vmt = &vmt_device;
+ devp->acc_if.vmt = &vmt_accelerometer;
+
+ devp->config = NULL;
+
+ devp->accaxes = LIS3DSH_ACC_NUMBER_OF_AXES;
+
+ devp->state = LIS3DSH_STOP;
+}
+
+/**
+ * @brief Configures and activates LIS3DSH Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p LIS3DSHDriver object
+ * @param[in] config pointer to the @p LIS3DSHConfig object
+ *
+ * @api
+ */
+void lis3dshStart(LIS3DSHDriver *devp, const LIS3DSHConfig *config) {
+ uint32_t i;
+ uint8_t cr;
+ osalDbgCheck((devp != NULL) && (config != NULL));
+
+ osalDbgAssert((devp->state == LIS3DSH_STOP) ||
+ (devp->state == LIS3DSH_READY),
+ "lis3dshStart(), invalid state");
+
+ devp->config = config;
+
+ /* Control register 4 configuration block.*/
+ {
+ cr = LIS3DSH_CTRL_REG4_XEN | LIS3DSH_CTRL_REG4_YEN | LIS3DSH_CTRL_REG4_ZEN |
+ devp->config->accoutputdatarate;
+#if LIS3DSH_USE_ADVANCED || defined(__DOXYGEN__)
+ cr |= devp->config->accblockdataupdate;
+#endif
+ }
+
+#if LIS3DSH_USE_SPI
+#if LIS3DSH_SHARED_SPI
+ spiAcquireBus(devp->config->spip);
+#endif /* LIS3DSH_SHARED_SPI */
+ spiStart(devp->config->spip, devp->config->spicfg);
+
+ lis3dshSPIWriteRegister(devp->config->spip, LIS3DSH_AD_CTRL_REG4, 1, &cr);
+
+#if LIS3DSH_SHARED_SPI
+ spiReleaseBus(devp->config->spip);
+#endif /* LIS3DSH_SHARED_SPI */
+#endif /* LIS3DSH_USE_SPI */
+
+ /* Control register 5 configuration block.*/
+ {
+ cr = devp->config->accfullscale;
+#if LIS3DSH_USE_ADVANCED || defined(__DOXYGEN__)
+ cr |= devp->config->accantialiasing;
+#endif
+ }
+
+#if LIS3DSH_USE_SPI
+#if LIS3DSH_SHARED_SPI
+ spiAcquireBus(devp->config->spip);
+ spiStart(devp->config->spip, devp->config->spicfg);
+#endif /* LIS3DSH_SHARED_SPI */
+
+ lis3dshSPIWriteRegister(devp->config->spip, LIS3DSH_AD_CTRL_REG5, 1, &cr);
+
+#if LIS3DSH_SHARED_SPI
+ spiReleaseBus(devp->config->spip);
+#endif /* LIS3DSH_SHARED_SPI */
+#endif /* LIS3DSH_USE_SPI */
+
+ /* Control register 6 configuration block.*/
+ {
+ cr = LIS3DSH_CTRL_REG6_ADD_INC;
+#if LIS3DSH_USE_ADVANCED || defined(__DOXYGEN__)
+ cr |= devp->config->accblockdataupdate;
+#endif
+ }
+
+#if LIS3DSH_USE_SPI
+#if LIS3DSH_SHARED_SPI
+ spiAcquireBus(devp->config->spip);
+ spiStart(devp->config->spip, devp->config->spicfg);
+#endif /* LIS3DSH_SHARED_SPI */
+
+ lis3dshSPIWriteRegister(devp->config->spip, LIS3DSH_AD_CTRL_REG6, 1, &cr);
+
+#if LIS3DSH_SHARED_SPI
+ spiReleaseBus(devp->config->spip);
+#endif /* LIS3DSH_SHARED_SPI */
+#endif /* LIS3DSH_USE_SPI */
+
+ /* Storing sensitivity information according to user setting */
+ if(devp->config->accfullscale == LIS3DSH_ACC_FS_2G) {
+ devp->accfullscale = LIS3DSH_ACC_2G;
+ if(devp->config->accsensitivity == NULL)
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LIS3DSH_ACC_SENS_2G;
+ else
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ else if(devp->config->accfullscale == LIS3DSH_ACC_FS_4G) {
+ devp->accfullscale = LIS3DSH_ACC_4G;
+ if(devp->config->accsensitivity == NULL)
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LIS3DSH_ACC_SENS_4G;
+ else
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ else if(devp->config->accfullscale == LIS3DSH_ACC_FS_6G) {
+ devp->accfullscale = LIS3DSH_ACC_6G;
+ if(devp->config->accsensitivity == NULL)
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LIS3DSH_ACC_SENS_6G;
+ else
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ else if(devp->config->accfullscale == LIS3DSH_ACC_FS_8G) {
+ devp->accfullscale = LIS3DSH_ACC_8G;
+ if(devp->config->accsensitivity == NULL)
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LIS3DSH_ACC_SENS_8G;
+ else
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ else if(devp->config->accfullscale == LIS3DSH_ACC_FS_16G) {
+ devp->accfullscale = LIS3DSH_ACC_16G;
+ if(devp->config->accsensitivity == NULL)
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LIS3DSH_ACC_SENS_16G;
+ else
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ else {
+ osalDbgAssert(FALSE, "lis3dshStart(), accelerometer full scale issue");
+ }
+
+ /* Storing bias information according to user setting */
+ if(devp->config->accbias != NULL)
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
+ devp->accbias[i] = devp->config->accbias[i];
+ else
+ for(i = 0; i < LIS3DSH_ACC_NUMBER_OF_AXES; i++)
+ devp->accbias[i] = LIS3DSH_ACC_BIAS;
+
+ /* This is the Accelerometer transient recovery time */
+ osalThreadSleepMilliseconds(10);
+
+ devp->state = LIS3DSH_READY;
+}
+
+/**
+ * @brief Deactivates the LIS3DSH Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p LIS3DSHDriver object
+ *
+ * @api
+ */
+void lis3dshStop(LIS3DSHDriver *devp) {
+ uint8_t cr4;
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LIS3DSH_STOP) ||
+ (devp->state == LIS3DSH_READY),
+ "lis3dshStop(), invalid state");
+
+ if (devp->state == LIS3DSH_READY) {
+#if (LIS3DSH_USE_SPI)
+#if LIS3DSH_SHARED_SPI
+ spiAcquireBus(devp->config->spip);
+ spiStart(devp->config->spip,
+ devp->config->spicfg);
+#endif /* LIS3DSH_SHARED_SPI */
+ /* Disabling all axes and enabling power down mode.*/
+ cr4 = 0;
+ lis3dshSPIWriteRegister(devp->config->spip, LIS3DSH_AD_CTRL_REG4,
+ 1, &cr4);
+
+ spiStop(devp->config->spip);
+#if LIS3DSH_SHARED_SPI
+ spiReleaseBus(devp->config->spip);
+#endif /* LIS3DSH_SHARED_SPI */
+#endif /* LIS3DSH_USE_SPI */
+ }
+ devp->state = LIS3DSH_STOP;
+}
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lis3dsh.h b/ChibiOS_20.3.2/os/ex/devices/ST/lis3dsh.h
new file mode 100644
index 0000000..062f7b2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lis3dsh.h
@@ -0,0 +1,708 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file lis3dsh.h
+ * @brief LIS3DSH MEMS interface module header.
+ *
+ * @addtogroup LIS3DSH
+ * @ingroup EX_ST
+ * @{
+ */
+
+#ifndef _LIS3DSH_H_
+#define _LIS3DSH_H_
+
+#include "ex_accelerometer.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Version identification
+ * @{
+ */
+/**
+ * @brief LIS3DSH driver version string.
+ */
+#define EX_LIS3DSH_VERSION "1.1.2"
+
+/**
+ * @brief LIS3DSH driver version major number.
+ */
+#define EX_LIS3DSH_MAJOR 1
+
+/**
+ * @brief LIS3DSH driver version minor number.
+ */
+#define EX_LIS3DSH_MINOR 1
+
+/**
+ * @brief LIS3DSH driver version patch number.
+ */
+#define EX_LIS3DSH_PATCH 2
+/** @} */
+
+/**
+ * @brief LIS3DSH accelerometer subsystem characteristics.
+ * @note Sensitivity is expressed as milli-G/LSB whereas
+ * 1 milli-G = 0.00980665 m/s^2.
+ * @note Bias is expressed as milli-G.
+ *
+ * @{
+ */
+#define LIS3DSH_ACC_NUMBER_OF_AXES 3U
+
+#define LIS3DSH_ACC_2G 2.0f
+#define LIS3DSH_ACC_4G 4.0f
+#define LIS3DSH_ACC_6G 6.0f
+#define LIS3DSH_ACC_8G 8.0f
+#define LIS3DSH_ACC_16G 16.0f
+
+#define LIS3DSH_ACC_SENS_2G 0.06f
+#define LIS3DSH_ACC_SENS_4G 0.12f
+#define LIS3DSH_ACC_SENS_6G 0.18f
+#define LIS3DSH_ACC_SENS_8G 0.24f
+#define LIS3DSH_ACC_SENS_16G 0.73f
+
+#define LIS3DSH_ACC_BIAS 0.0f
+/** @} */
+
+/**
+ * @name LIS3DSH communication interfaces related bit masks
+ * @{
+ */
+#define LIS3DSH_DI_MASK 0xFF
+#define LIS3DSH_DI(n) (1 << n)
+#define LIS3DSH_AD_MASK 0x3F
+#define LIS3DSH_AD(n) (1 << n)
+#define LIS3DSH_MS (1 << 6)
+#define LIS3DSH_RW (1 << 7)
+/** @} */
+
+/**
+ * @name LIS3DSH register addresses
+ * @{
+ */
+#define LIS3DSH_AD_OUT_T 0x0C
+#define LIS3DSH_AD_INFO1 0x0D
+#define LIS3DSH_AD_INFO2 0x0E
+#define LIS3DSH_AD_WHO_AM_I 0x0F
+#define LIS3DSH_AD_OFF_X 0x10
+#define LIS3DSH_AD_OFF_Y 0x11
+#define LIS3DSH_AD_OFF_Z 0x12
+#define LIS3DSH_AD_CS_X 0x13
+#define LIS3DSH_AD_CS_Y 0x14
+#define LIS3DSH_AD_CS_Z 0x15
+#define LIS3DSH_AD_LC_L 0x16
+#define LIS3DSH_AD_LC_H 0x17
+#define LIS3DSH_AD_STAT 0x18
+#define LIS3DSH_AD_PEAK1 0x19
+#define LIS3DSH_AD_PEAK2 0x1A
+#define LIS3DSH_AD_VFC_1 0x1B
+#define LIS3DSH_AD_VFC_2 0x1C
+#define LIS3DSH_AD_VFC_3 0x1D
+#define LIS3DSH_AD_VFC_4 0x1E
+#define LIS3DSH_AD_THRS3 0x1F
+#define LIS3DSH_AD_CTRL_REG4 0x20
+#define LIS3DSH_AD_CTRL_REG1 0x21
+#define LIS3DSH_AD_CTRL_REG2 0x22
+#define LIS3DSH_AD_CTRL_REG3 0x23
+#define LIS3DSH_AD_CTRL_REG5 0x24
+#define LIS3DSH_AD_CTRL_REG6 0x25
+#define LIS3DSH_AD_STATUS 0x27
+#define LIS3DSH_AD_OUT_X_L 0x28
+#define LIS3DSH_AD_OUT_X_H 0x29
+#define LIS3DSH_AD_OUT_Y_L 0x2A
+#define LIS3DSH_AD_OUT_Y_H 0x2B
+#define LIS3DSH_AD_OUT_Z_L 0x2C
+#define LIS3DSH_AD_OUT_Z_H 0x2D
+#define LIS3DSH_AD_FIFO_CTRL 0x2E
+#define LIS3DSH_AD_FIFO_SRC 0x2F
+#define LIS3DSH_AD_ST1_0 0x40
+#define LIS3DSH_AD_ST1_1 0x41
+#define LIS3DSH_AD_ST1_2 0x42
+#define LIS3DSH_AD_ST1_3 0x43
+#define LIS3DSH_AD_ST1_4 0x44
+#define LIS3DSH_AD_ST1_5 0x45
+#define LIS3DSH_AD_ST1_6 0x46
+#define LIS3DSH_AD_ST1_7 0x47
+#define LIS3DSH_AD_ST1_8 0x48
+#define LIS3DSH_AD_ST1_9 0x49
+#define LIS3DSH_AD_ST1_A 0x4A
+#define LIS3DSH_AD_ST1_B 0x4B
+#define LIS3DSH_AD_ST1_C 0x4C
+#define LIS3DSH_AD_ST1_D 0x4D
+#define LIS3DSH_AD_ST1_E 0x4E
+#define LIS3DSH_AD_ST1_F 0x4F
+#define LIS3DSH_AD_TIM4_1 0x50
+#define LIS3DSH_AD_TIM3_1 0x51
+#define LIS3DSH_AD_TIM2_1_L 0x52
+#define LIS3DSH_AD_TIM2_1_H 0x53
+#define LIS3DSH_AD_TIM1_1_L 0x54
+#define LIS3DSH_AD_TIM1_1_H 0x55
+#define LIS3DSH_AD_THRS2_1 0x56
+#define LIS3DSH_AD_THRS1_1 0x57
+#define LIS3DSH_AD_MASK1_B 0x59
+#define LIS3DSH_AD_MASK1_A 0x5A
+#define LIS3DSH_AD_SETT1 0x5B
+#define LIS3DSH_AD_PR1 0x5C
+#define LIS3DSH_AD_TC1_L 0x5D
+#define LIS3DSH_AD_TC1_H 0x5E
+#define LIS3DSH_AD_OUTS1 0x5F
+#define LIS3DSH_AD_ST2_0 0x60
+#define LIS3DSH_AD_ST2_1 0x61
+#define LIS3DSH_AD_ST2_2 0x62
+#define LIS3DSH_AD_ST2_3 0x63
+#define LIS3DSH_AD_ST2_4 0x64
+#define LIS3DSH_AD_ST2_5 0x65
+#define LIS3DSH_AD_ST2_6 0x66
+#define LIS3DSH_AD_ST2_7 0x67
+#define LIS3DSH_AD_ST2_8 0x68
+#define LIS3DSH_AD_ST2_9 0x69
+#define LIS3DSH_AD_ST2_A 0x6A
+#define LIS3DSH_AD_ST2_B 0x6B
+#define LIS3DSH_AD_ST2_C 0x6C
+#define LIS3DSH_AD_ST2_D 0x6D
+#define LIS3DSH_AD_ST2_E 0x6E
+#define LIS3DSH_AD_ST2_F 0x6F
+#define LIS3DSH_AD_TIM4_2 0x70
+#define LIS3DSH_AD_TIM3_2 0x71
+#define LIS3DSH_AD_TIM2_2_L 0x72
+#define LIS3DSH_AD_TIM2_2_H 0x73
+#define LIS3DSH_AD_TIM1_2_L 0x74
+#define LIS3DSH_AD_TIM1_2_H 0x75
+#define LIS3DSH_AD_THRS2_2 0x76
+#define LIS3DSH_AD_THRS1_2 0x77
+#define LIS3DSH_AD_DES2 0x78
+#define LIS3DSH_AD_MASK2_B 0x79
+#define LIS3DSH_AD_MASK2_A 0x7A
+#define LIS3DSH_AD_SETT2 0x7B
+#define LIS3DSH_AD_PR2 0x7C
+#define LIS3DSH_AD_TC2_L 0x7D
+#define LIS3DSH_AD_TC2_H 0x7E
+#define LIS3DSH_AD_OUTS2 0x7F
+/** @} */
+
+/**
+ * @name LIS3DSH_CTRL_REG1 register bits definitions
+ * @{
+ */
+#define LIS3DSH_CTRL_REG1_MASK 0xE9
+#define LIS3DSH_CTRL_REG1_SM1_EN (1 << 0)
+#define LIS3DSH_CTRL_REG1_SM1_PIN (1 << 3)
+#define LIS3DSH_CTRL_REG1_HYST0_1 (1 << 5)
+#define LIS3DSH_CTRL_REG1_HYST1_1 (1 << 6)
+#define LIS3DSH_CTRL_REG1_HYST2_1 (1 << 7)
+/** @} */
+
+/**
+ * @name LIS3DSH_CTRL_REG2 register bits definitions
+ * @{
+ */
+#define LIS3DSH_CTRL_REG2_MASK 0xE9
+#define LIS3DSH_CTRL_REG2_SM2_EN (1 << 0)
+#define LIS3DSH_CTRL_REG2_SM2_PIN (1 << 3)
+#define LIS3DSH_CTRL_REG2_HYST0_2 (1 << 5)
+#define LIS3DSH_CTRL_REG2_HYST1_2 (1 << 6)
+#define LIS3DSH_CTRL_REG2_HYST2_2 (1 << 7)
+/** @} */
+
+/**
+ * @name LIS3DSH_CTRL_REG3 register bits definitions
+ * @{
+ */
+#define LIS3DSH_CTRL_REG3_MASK 0xFF
+#define LIS3DSH_CTRL_REG3_STRT (1 << 0)
+#define LIS3DSH_CTRL_REG3_VFILT (1 << 2)
+#define LIS3DSH_CTRL_REG3_INT1_EN (1 << 3)
+#define LIS3DSH_CTRL_REG3_INT2_EN (1 << 4)
+#define LIS3DSH_CTRL_REG3_IEL (1 << 5)
+#define LIS3DSH_CTRL_REG3_IEA (1 << 6)
+#define LIS3DSH_CTRL_REG3_DR_EN (1 << 7)
+/** @} */
+
+/**
+ * @name LIS3DSH_CTRL_REG4 register bits definitions
+ * @{
+ */
+#define LIS3DSH_CTRL_REG4_MASK 0xFF
+#define LIS3DSH_CTRL_REG4_XEN (1 << 0)
+#define LIS3DSH_CTRL_REG4_YEN (1 << 1)
+#define LIS3DSH_CTRL_REG4_ZEN (1 << 2)
+#define LIS3DSH_CTRL_REG4_BDU (1 << 3)
+#define LIS3DSH_CTRL_REG4_ODR_0 (1 << 4)
+#define LIS3DSH_CTRL_REG4_ODR_1 (1 << 5)
+#define LIS3DSH_CTRL_REG4_ODR_2 (1 << 6)
+#define LIS3DSH_CTRL_REG4_ODR_3 (1 << 7)
+/** @} */
+
+/**
+ * @name LIS3DSH_CTRL_REG5 register bits definitions
+ * @{
+ */
+#define LIS3DSH_CTRL_REG5_MASK 0xFF
+#define LIS3DSH_CTRL_REG5_SIM (1 << 0)
+#define LIS3DSH_CTRL_REG5_ST1 (1 << 1)
+#define LIS3DSH_CTRL_REG5_ST2 (1 << 2)
+#define LIS3DSH_CTRL_REG5_FS_MASK 0x38
+#define LIS3DSH_CTRL_REG5_FS0 (1 << 3)
+#define LIS3DSH_CTRL_REG5_FS1 (1 << 4)
+#define LIS3DSH_CTRL_REG5_FS2 (1 << 5)
+#define LIS3DSH_CTRL_REG5_BW1 (1 << 6)
+#define LIS3DSH_CTRL_REG5_BW2 (1 << 7)
+/** @} */
+
+/**
+ * @name LIS3DSH_CTRL_REG6 register bits definitions
+ * @{
+ */
+#define LIS3DSH_CTRL_REG6_MASK 0xFF
+#define LIS3DSH_CTRL_REG6_P2_BOOT (1 << 0)
+#define LIS3DSH_CTRL_REG6_P1_OVRUN (1 << 1)
+#define LIS3DSH_CTRL_REG6_P1_WTM (1 << 2)
+#define LIS3DSH_CTRL_REG6_P1_EMPTY (1 << 3)
+#define LIS3DSH_CTRL_REG6_ADD_INC (1 << 4)
+#define LIS3DSH_CTRL_REG6_WTM_EN (1 << 5)
+#define LIS3DSH_CTRL_REG6_FIFO_EN (1 << 6)
+#define LIS3DSH_CTRL_REG6_BOOT (1 << 7)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief LIS3DSH SPI interface switch.
+ * @details If set to @p TRUE the support for SPI is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(LIS3DSH_USE_SPI) || defined(__DOXYGEN__)
+#define LIS3DSH_USE_SPI TRUE
+#endif
+
+/**
+ * @brief LIS3DSH shared SPI switch.
+ * @details If set to @p TRUE the device acquires SPI bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(LIS3DSH_SHARED_SPI) || defined(__DOXYGEN__)
+#define LIS3DSH_SHARED_SPI FALSE
+#endif
+
+/**
+ * @brief LIS3DSH I2C interface switch.
+ * @details If set to @p TRUE the support for I2C is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(LIS3DSH_USE_I2C) || defined(__DOXYGEN__)
+#define LIS3DSH_USE_I2C FALSE
+#endif
+
+/**
+ * @brief LIS3DSH shared I2C switch.
+ * @details If set to @p TRUE the device acquires I2C bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(LIS3DSH_SHARED_I2C) || defined(__DOXYGEN__)
+#define LIS3DSH_SHARED_I2C FALSE
+#endif
+
+/**
+ * @brief LIS3DSH advanced configurations switch.
+ * @details If set to @p TRUE more configurations are available.
+ * @note The default is @p FALSE.
+ */
+#if !defined(LIS3DSH_USE_ADVANCED) || defined(__DOXYGEN__)
+#define LIS3DSH_USE_ADVANCED FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !(LIS3DSH_USE_SPI ^ LIS3DSH_USE_I2C)
+#error "LIS3DSH_USE_SPI and LIS3DSH_USE_I2C cannot be both true or both false"
+#endif
+
+#if LIS3DSH_USE_SPI && !HAL_USE_SPI
+#error "LIS3DSH_USE_SPI requires HAL_USE_SPI"
+#endif
+
+#if LIS3DSH_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION
+#error "LIS3DSH_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
+#endif
+
+#if LIS3DSH_USE_I2C && !HAL_USE_I2C
+#error "LIS3DSH_USE_I2C requires HAL_USE_I2C"
+#endif
+
+#if LIS3DSH_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
+#error "LIS3DSH_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
+#endif
+
+/*
+ * CHTODO: Add support for LIS3DSH over I2C.
+ */
+#if LIS3DSH_USE_I2C
+#error "LIS3DSH over I2C still not supported"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @name LIS3DSH data structures and types
+ * @{
+ */
+/**
+ * @brief Structure representing a LIS3DSH driver.
+ */
+typedef struct LIS3DSHDriver LIS3DSHDriver;
+
+/**
+ * @brief LIS3DSH full scale.
+ */
+typedef enum {
+ LIS3DSH_ACC_FS_2G = 0x00, /**< Full scale �2g. */
+ LIS3DSH_ACC_FS_4G = 0x08, /**< Full scale �4g. */
+ LIS3DSH_ACC_FS_6G = 0x10, /**< Full scale �6g. */
+ LIS3DSH_ACC_FS_8G = 0x18, /**< Full scale �8g. */
+ LIS3DSH_ACC_FS_16G = 0x20 /**< Full scale �16g. */
+}lis3dsh_acc_fs_t;
+
+/**
+ * @brief LIS3DSH output data rate.
+ */
+typedef enum {
+ LIS3DSH_ACC_ODR_PD = 0x00, /**< ODR 100 Hz. */
+ LIS3DSH_ACC_ODR_3_125HZ = 0x10, /**< ODR 3.125 Hz. */
+ LIS3DSH_ACC_ODR_6_25HZ = 0x20, /**< ODR 6.25 Hz. */
+ LIS3DSH_ACC_ODR_12_5HZ = 0x30, /**< ODR 12.5 Hz. */
+ LIS3DSH_ACC_ODR_25HZ = 0x40, /**< ODR 25 Hz. */
+ LIS3DSH_ACC_ODR_50HZ = 0x50, /**< ODR 50 Hz. */
+ LIS3DSH_ACC_ODR_100HZ = 0x60, /**< ODR 100 Hz. */
+ LIS3DSH_ACC_ODR_400HZ = 0x70, /**< ODR 400 Hz. */
+ LIS3DSH_ACC_ODR_800HZ = 0x80, /**< ODR 800 Hz. */
+ LIS3DSH_ACC_ODR_1600HZ = 0x90 /**< ODR 1600 Hz. */
+}lis3dsh_acc_odr_t;
+
+/**
+ * @brief LIS3DSH anti-aliasing bandwidth.
+ */
+typedef enum {
+ LIS3DSH_ACC_BW_800HZ = 0x00, /**< AA filter BW 800Hz. */
+ LIS3DSH_ACC_BW_200HZ = 0x40, /**< AA filter BW 200Hz. */
+ LIS3DSH_ACC_BW_400HZ = 0x80, /**< AA filter BW 400Hz. */
+ LIS3DSH_ACC_BW_50HZ = 0xC0 /**< AA filter BW 50Hz. */
+}lis3dsh_acc_bw_t;
+
+/**
+ * @brief LIS3DSH block data update.
+ */
+typedef enum {
+ LIS3DSH_ACC_BDU_CONTINUOUS = 0x00,/**< Block data continuously updated. */
+ LIS3DSH_ACC_BDU_BLOCKED = 0x80 /**< Block data updated after reading. */
+} lis3dsh_acc_bdu_t;
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ LIS3DSH_UNINIT = 0, /**< Not initialized. */
+ LIS3DSH_STOP = 1, /**< Stopped. */
+ LIS3DSH_READY = 2, /**< Ready. */
+} lis3dsh_state_t;
+
+/**
+ * @brief LIS3DSH configuration structure.
+ */
+typedef struct {
+
+#if (LIS3DSH_USE_SPI) || defined(__DOXYGEN__)
+ /**
+ * @brief SPI driver associated to this LIS3DSH.
+ */
+ SPIDriver *spip;
+ /**
+ * @brief SPI configuration associated to this LIS3DSH.
+ */
+ const SPIConfig *spicfg;
+#endif /* LIS3DSH_USE_SPI */
+#if (LIS3DSH_USE_I2C) || defined(__DOXYGEN__)
+ /**
+ * @brief I2C driver associated to this LIS3DSH.
+ */
+ I2CDriver *i2cp;
+ /**
+ * @brief I2C configuration associated to this LIS3DSH.
+ */
+ const I2CConfig *i2ccfg;
+#endif /* LIS3DSH_USE_I2C */
+ /**
+ * @brief LIS3DSH accelerometer subsystem initial sensitivity.
+ */
+ float *accsensitivity;
+ /**
+ * @brief LIS3DSH accelerometer subsystem initial bias.
+ */
+ float *accbias;
+ /**
+ * @brief LIS3DSH accelerometer subsystem initial full scale.
+ */
+ lis3dsh_acc_fs_t accfullscale;
+ /**
+ * @brief LIS3DSH output data rate selection.
+ */
+ lis3dsh_acc_odr_t accoutputdatarate;
+#if LIS3DSH_USE_ADVANCED || defined(__DOXYGEN__)
+ /**
+ * @brief LIS3DSH anti-aliasing bandwidth.
+ */
+ lis3dsh_acc_bw_t accantialiasing;
+ /**
+ * @brief LIS3DSH block data update.
+ */
+ lis3dsh_acc_bdu_t accblockdataupdate;
+#endif
+} LIS3DSHConfig;
+
+/**
+ * @brief @p LIS3DSH specific methods.
+ */
+#define _lis3dsh_methods_alone \
+ /* Change full scale value of LIS3DSH accelerometer subsystem.*/ \
+ msg_t (*acc_set_full_scale)(LIS3DSHDriver *devp, lis3dsh_acc_fs_t fs);
+
+
+/**
+ * @brief @p LIS3DSH specific methods with inherited ones.
+ */
+#define _lis3dsh_methods \
+ _base_object_methods \
+ _lis3dsh_methods_alone
+
+/**
+ * @extends BaseObjectVMT
+ *
+ * @brief @p LIS3DSH virtual methods table.
+ */
+struct LIS3DSHVMT {
+ _lis3dsh_methods
+};
+
+/**
+ * @brief @p LIS3DSHDriver specific data.
+ */
+#define _lis3dsh_data \
+ _base_sensor_data \
+ /* Driver state.*/ \
+ lis3dsh_state_t state; \
+ /* Current configuration data.*/ \
+ const LIS3DSHConfig *config; \
+ /* Accelerometer subsystem axes number.*/ \
+ size_t accaxes; \
+ /* Accelerometer subsystem current sensitivity.*/ \
+ float accsensitivity[LIS3DSH_ACC_NUMBER_OF_AXES]; \
+ /* Accelerometer subsystem current bias .*/ \
+ float accbias[LIS3DSH_ACC_NUMBER_OF_AXES]; \
+ /* Accelerometer subsystem current full scale value.*/ \
+ float accfullscale;
+
+/**
+ * @brief LIS3DSH 3-axis accelerometer class.
+ */
+struct LIS3DSHDriver {
+ /** @brief Virtual Methods Table.*/
+ const struct LIS3DSHVMT *vmt;
+ /** @brief Base accelerometer interface.*/
+ BaseAccelerometer acc_if;
+ _lis3dsh_data
+};
+/** @} */
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Return the number of axes of the BaseAccelerometer.
+ *
+ * @param[in] devp pointer to @p LIS3DSHDriver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define lis3dshAccelerometerGetAxesNumber(devp) \
+ accelerometerGetAxesNumber(&((devp)->acc_if))
+
+/**
+ * @brief Retrieves raw data from the BaseAccelerometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LIS3DSHDriver.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lis3dshAccelerometerReadRaw(devp, axes) \
+ accelerometerReadRaw(&((devp)->acc_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseAccelerometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as milli-G.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LIS3DSHDriver.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lis3dshAccelerometerReadCooked(devp, axes) \
+ accelerometerReadCooked(&((devp)->acc_if), axes)
+
+/**
+ * @brief Set bias values for the BaseAccelerometer.
+ * @note Bias must be expressed as milli-G.
+ * @note The bias buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LIS3DSHDriver.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lis3dshAccelerometerSetBias(devp, bp) \
+ accelerometerSetBias(&((devp)->acc_if), bp)
+
+/**
+ * @brief Reset bias values for the BaseAccelerometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] devp pointer to @p LIS3DSHDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lis3dshAccelerometerResetBias(devp) \
+ accelerometerResetBias(&((devp)->acc_if))
+
+/**
+ * @brief Set sensitivity values for the BaseAccelerometer.
+ * @note Sensitivity must be expressed as milli-G/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LIS3DSHDriver.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lis3dshAccelerometerSetSensitivity(devp, sp) \
+ accelerometerSetSensitivity(&((devp)->acc_if), sp)
+
+/**
+ * @brief Reset sensitivity values for the BaseAccelerometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] devp pointer to @p LIS3DSHDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lis3dshAccelerometerResetSensitivity(devp) \
+ accelerometerResetSensitivity(&((devp)->acc_if))
+
+/**
+ * @brief Changes the LIS3DSHDriver accelerometer fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p LIS3DSHDriver.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lis3dshAccelerometerSetFullScale(devp, fs) \
+ (devp)->vmt->acc_set_full_scale(devp, fs)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void lis3dshObjectInit(LIS3DSHDriver *devp);
+ void lis3dshStart(LIS3DSHDriver *devp, const LIS3DSHConfig *config);
+ void lis3dshStop(LIS3DSHDriver *devp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIS3DSH_H_ */
+
+/** @} */
+
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lis3dsh.mk b/ChibiOS_20.3.2/os/ex/devices/ST/lis3dsh.mk
new file mode 100644
index 0000000..dccac25
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lis3dsh.mk
@@ -0,0 +1,10 @@
+# List of all the LIS3DSH device files.
+LIS3DSHSRC := $(CHIBIOS)/os/ex/devices/ST/lis3dsh.c
+
+# Required include directories
+LIS3DSHINC := $(CHIBIOS)/os/ex/include \
+ $(CHIBIOS)/os/ex/devices/ST
+
+# Shared variables
+ALLCSRC += $(LIS3DSHSRC)
+ALLINC += $(LIS3DSHINC)
\ No newline at end of file
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lis3mdl.c b/ChibiOS_20.3.2/os/ex/devices/ST/lis3mdl.c
new file mode 100644
index 0000000..270ee83
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lis3mdl.c
@@ -0,0 +1,627 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file lis3mdl.c
+ * @brief LIS3MDL MEMS interface module code.
+ *
+ * @addtogroup LIS3MDL
+ * @ingroup EX_ST
+ * @{
+ */
+
+#include "hal.h"
+#include "lis3mdl.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#if (LIS3MDL_USE_I2C) || defined(__DOXYGEN__)
+/**
+ * @brief Reads registers value using I2C.
+ * @pre The I2C interface must be initialized and the driver started.
+ *
+ * @param[in] i2cp pointer to the I2C interface
+ * @param[in] sad slave address without R bit
+ * @param[in] reg first sub-register address
+ * @param[out] rxbuf pointer to an output buffer
+ * @param[in] n number of consecutive register to read
+ * @return the operation status.
+ * @notapi
+ */
+msg_t lis3mdlI2CReadRegister(I2CDriver *i2cp, lis3mdl_sad_t sad, uint8_t reg,
+ uint8_t* rxbuf, size_t n) {
+ uint8_t txbuf = reg;
+ if(n > 1)
+ txbuf |= LIS3MDL_SUB_MS;
+
+ return i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, n,
+ TIME_INFINITE);
+}
+
+/**
+ * @brief Writes a value into a register using I2C.
+ * @pre The I2C interface must be initialized and the driver started.
+ *
+ * @param[in] i2cp pointer to the I2C interface
+ * @param[in] sad slave address without R bit
+ * @param[in] txbuf buffer containing sub-address value in first position
+ * and values to write
+ * @param[in] n size of txbuf less one (not considering the first
+ * element)
+ * @return the operation status.
+ * @notapi
+ */
+msg_t lis3mdlI2CWriteRegister(I2CDriver *i2cp, lis3mdl_sad_t sad, uint8_t* txbuf,
+ uint8_t n) {
+ if (n > 1)
+ (*txbuf) |= LIS3MDL_SUB_MS;
+
+ return i2cMasterTransmitTimeout(i2cp, sad, txbuf, n + 1, NULL, 0,
+ TIME_INFINITE);
+}
+#endif /* LIS3MDL_USE_I2C */
+
+/**
+ * @brief Return the number of axes of the BaseCompass.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface
+ *
+ * @return the number of axes.
+ */
+static size_t comp_get_axes_number(void *ip) {
+
+ osalDbgCheck(ip != NULL);
+ return LIS3MDL_COMP_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Retrieves raw data from the BaseCompass.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t comp_read_raw(void *ip, int32_t axes[]) {
+ LIS3MDLDriver* devp;
+ uint8_t buff [LIS3MDL_COMP_NUMBER_OF_AXES * 2], i;
+ int16_t tmp;
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LIS3MDLDriver*, (BaseCompass*)ip);
+
+ osalDbgAssert((devp->state == LIS3MDL_READY),
+ "comp_read_raw(), invalid state");
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "comp_read_raw(), channel not ready");
+
+#if LIS3MDL_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LIS3MDL_SHARED_I2C */
+ msg = lis3mdlI2CReadRegister(devp->config->i2cp, devp->config->slaveaddress,
+ LIS3MDL_AD_OUT_X_L, buff,
+ LIS3MDL_COMP_NUMBER_OF_AXES * 2);
+
+#if LIS3MDL_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LIS3MDL_SHARED_I2C */
+
+ if(msg == MSG_OK)
+ for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) {
+ tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
+ axes[i] = (int32_t)tmp;
+ }
+ return msg;
+}
+
+/**
+ * @brief Retrieves cooked data from the BaseCompass.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as G.
+ * @note The axes array must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t comp_read_cooked(void *ip, float axes[]) {
+ LIS3MDLDriver* devp;
+ uint32_t i;
+ int32_t raw[LIS3MDL_COMP_NUMBER_OF_AXES];
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LIS3MDLDriver*, (BaseCompass*)ip);
+
+ osalDbgAssert((devp->state == LIS3MDL_READY),
+ "comp_read_cooked(), invalid state");
+
+ msg = comp_read_raw(ip, raw);
+ for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES ; i++) {
+ axes[i] = (raw[i] * devp->compsensitivity[i]) - devp->compbias[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Set bias values for the BaseCompass.
+ * @note Bias must be expressed as G.
+ * @note The bias buffer must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t comp_set_bias(void *ip, float *bp) {
+ LIS3MDLDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (bp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LIS3MDLDriver*, (BaseCompass*)ip);
+
+ osalDbgAssert((devp->state == LIS3MDL_READY),
+ "comp_set_bias(), invalid state");
+
+ for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) {
+ devp->compbias[i] = bp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset bias values for the BaseCompass.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t comp_reset_bias(void *ip) {
+ LIS3MDLDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LIS3MDLDriver*, (BaseCompass*)ip);
+
+ osalDbgAssert((devp->state == LIS3MDL_READY),
+ "comp_reset_bias(), invalid state");
+
+ for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++)
+ devp->compbias[i] = LIS3MDL_COMP_BIAS;
+ return msg;
+}
+
+/**
+ * @brief Set sensitivity values for the BaseCompass.
+ * @note Sensitivity must be expressed as G/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t comp_set_sensivity(void *ip, float *sp) {
+ LIS3MDLDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LIS3MDLDriver*, (BaseCompass*)ip);
+
+ osalDbgCheck((ip != NULL) && (sp != NULL));
+
+ osalDbgAssert((devp->state == LIS3MDL_READY),
+ "comp_set_sensivity(), invalid state");
+
+ for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) {
+ devp->compsensitivity[i] = sp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset sensitivity values for the BaseCompass.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t comp_reset_sensivity(void *ip) {
+ LIS3MDLDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LIS3MDLDriver*, (BaseCompass*)ip);
+
+ osalDbgAssert((devp->state == LIS3MDL_READY),
+ "comp_reset_sensivity(), invalid state");
+
+ if(devp->config->compfullscale == LIS3MDL_COMP_FS_4GA)
+ for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++)
+ devp->compsensitivity[i] = LIS3MDL_COMP_SENS_4GA;
+ else if(devp->config->compfullscale == LIS3MDL_COMP_FS_8GA)
+ for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++)
+ devp->compsensitivity[i] = LIS3MDL_COMP_SENS_8GA;
+ else if(devp->config->compfullscale == LIS3MDL_COMP_FS_12GA)
+ for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++)
+ devp->compsensitivity[i] = LIS3MDL_COMP_SENS_12GA;
+ else if(devp->config->compfullscale == LIS3MDL_COMP_FS_16GA)
+ for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++)
+ devp->compsensitivity[i] = LIS3MDL_COMP_SENS_16GA;
+ else {
+ osalDbgAssert(FALSE, "comp_reset_sensivity(), compass full scale issue");
+ msg = MSG_RESET;
+ }
+ return msg;
+}
+
+/**
+ * @brief Changes the LIS3MDLDriver compass fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p LIS3MDLDriver interface.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t comp_set_full_scale(LIS3MDLDriver *devp, lis3mdl_comp_fs_t fs) {
+ float newfs, scale;
+ uint8_t i, buff[2];
+ msg_t msg;
+
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LIS3MDL_READY),
+ "comp_set_full_scale(), invalid state");
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "comp_set_full_scale(), channel not ready");
+
+ /* Computing new fullscale value.*/
+ if(fs == LIS3MDL_COMP_FS_4GA) {
+ newfs = LIS3MDL_COMP_4GA;
+ }
+ else if(fs == LIS3MDL_COMP_FS_8GA) {
+ newfs = LIS3MDL_COMP_8GA;
+ }
+ else if(fs == LIS3MDL_COMP_FS_12GA) {
+ newfs = LIS3MDL_COMP_12GA;
+ }
+ else if(fs == LIS3MDL_COMP_FS_16GA) {
+ newfs = LIS3MDL_COMP_16GA;
+ }
+ else {
+ msg = MSG_RESET;
+ return msg;
+ }
+
+ if(newfs != devp->compfullscale) {
+ /* Computing scale value.*/
+ scale = newfs / devp->compfullscale;
+ devp->compfullscale = newfs;
+
+#if LIS3MDL_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+#endif /* LIS3MDL_SHARED_I2C */
+
+ /* Updating register.*/
+ msg = lis3mdlI2CReadRegister(devp->config->i2cp, devp->config->slaveaddress,
+ LIS3MDL_AD_CTRL_REG2, &buff[1], 1);
+
+#if LIS3MDL_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LIS3MDL_SHARED_I2C */
+
+ if(msg != MSG_OK)
+ return msg;
+ buff[1] &= ~(LIS3MDL_CTRL_REG2_FS_MASK);
+ buff[1] |= fs;
+ buff[0] = LIS3MDL_AD_CTRL_REG2;
+
+#if LIS3MDL_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+#endif /* LIS3MDL_SHARED_I2C */
+
+ msg = lis3mdlI2CWriteRegister(devp->config->i2cp,
+ devp->config->slaveaddress,
+ buff, 1);
+
+#if LIS3MDL_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LIS3MDL_SHARED_I2C */
+
+ if(msg != MSG_OK)
+ return msg;
+
+ /* Scaling sensitivity and bias. Re-calibration is suggested anyway.*/
+ for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) {
+ devp->compsensitivity[i] *= scale;
+ devp->compbias[i] *= scale;
+ }
+ }
+ return msg;
+}
+
+static const struct LIS3MDLVMT vmt_device = {
+ (size_t)0,
+ comp_set_full_scale
+};
+
+static const struct BaseCompassVMT vmt_compass = {
+ sizeof(struct LIS3MDLVMT*),
+ comp_get_axes_number, comp_read_raw, comp_read_cooked,
+ comp_set_bias, comp_reset_bias, comp_set_sensivity, comp_reset_sensivity
+};
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes an instance.
+ *
+ * @param[out] devp pointer to the @p LIS3MDLDriver object
+ *
+ * @init
+ */
+void lis3mdlObjectInit(LIS3MDLDriver *devp) {
+ devp->vmt = &vmt_device;
+ devp->comp_if.vmt = &vmt_compass;
+
+ devp->config = NULL;
+
+ devp->compaxes = LIS3MDL_COMP_NUMBER_OF_AXES;
+
+ devp->state = LIS3MDL_STOP;
+}
+
+/**
+ * @brief Configures and activates LIS3MDL Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p LIS3MDLDriver object
+ * @param[in] config pointer to the @p LIS3MDLConfig object
+ *
+ * @api
+ */
+void lis3mdlStart(LIS3MDLDriver *devp, const LIS3MDLConfig *config) {
+ uint32_t i;
+ uint8_t cr[6];
+ osalDbgCheck((devp != NULL) && (config != NULL));
+
+ osalDbgAssert((devp->state == LIS3MDL_STOP) || (devp->state == LIS3MDL_READY),
+ "lis3mdlStart(), invalid state");
+
+ devp->config = config;
+
+ /* Control register 1 configuration block.*/
+ {
+ cr[0] = LIS3MDL_AD_CTRL_REG1;
+ cr[1] = devp->config->compoutputdatarate;
+#if LIS3MDL_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[1] |= devp->config->compoperationmodexy;
+#else
+ cr[1] |= LIS3MDL_CTRL_REG1_OM0 | LIS3MDL_CTRL_REG1_OM1;
+#endif
+ }
+
+ /* Control register 2 configuration block.*/
+ {
+ cr[2] = devp->config->compfullscale;
+ }
+
+ /* Control register 3 configuration block.*/
+ {
+ cr[3] = 0;
+#if LIS3MDL_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[3] = devp->config->compconversionmode;
+#endif
+ }
+
+ /* Control register 4 configuration block.*/
+ {
+ cr[4] = 0;
+#if LIS3MDL_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[4] = devp->config->compoperationmodez | devp->config->endianness;
+#endif
+ }
+
+ /* Control register 5 configuration block.*/
+ {
+ cr[5] = 0;
+#if LIS3MDL_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[5] = devp->config->blockdataupdate;
+#endif
+ }
+
+#if LIS3MDL_USE_I2C
+#if LIS3MDL_SHARED_I2C
+ i2cAcquireBus((devp)->config->i2cp);
+#endif /* LIS3MDL_SHARED_I2C */
+ i2cStart((devp)->config->i2cp,
+ (devp)->config->i2ccfg);
+
+ lis3mdlI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
+ cr, 5);
+
+#if LIS3MDL_SHARED_I2C
+ i2cReleaseBus((devp)->config->i2cp);
+#endif /* LIS3MDL_SHARED_I2C */
+#endif /* LIS3MDL_USE_I2C */
+
+ if(devp->config->compfullscale == LIS3MDL_COMP_FS_4GA) {
+ devp->compfullscale = LIS3MDL_COMP_4GA;
+ for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) {
+ if(devp->config->compsensitivity == NULL) {
+ devp->compsensitivity[i] = LIS3MDL_COMP_SENS_4GA;
+ }
+ else {
+ devp->compsensitivity[i] = devp->config->compsensitivity[i];
+ }
+ }
+ }
+ else if(devp->config->compfullscale == LIS3MDL_COMP_FS_8GA) {
+ devp->compfullscale = LIS3MDL_COMP_8GA;
+ for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) {
+ if(devp->config->compsensitivity == NULL) {
+ devp->compsensitivity[i] = LIS3MDL_COMP_SENS_8GA;
+ }
+ else {
+ devp->compsensitivity[i] = devp->config->compsensitivity[i];
+ }
+ }
+ }
+ else if(devp->config->compfullscale == LIS3MDL_COMP_FS_12GA) {
+ devp->compfullscale = LIS3MDL_COMP_12GA;
+ for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) {
+ if(devp->config->compsensitivity == NULL) {
+ devp->compsensitivity[i] = LIS3MDL_COMP_SENS_12GA;
+ }
+ else {
+ devp->compsensitivity[i] = devp->config->compsensitivity[i];
+ }
+ }
+ }
+ else if(devp->config->compfullscale == LIS3MDL_COMP_FS_16GA) {
+ devp->compfullscale = LIS3MDL_COMP_16GA;
+ for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++) {
+ if(devp->config->compsensitivity == NULL) {
+ devp->compsensitivity[i] = LIS3MDL_COMP_SENS_16GA;
+ }
+ else {
+ devp->compsensitivity[i] = devp->config->compsensitivity[i];
+ }
+ }
+ }
+ else
+ osalDbgAssert(FALSE, "lis3mdlStart(), compass full scale issue");
+
+ /* Storing bias information */
+ if(devp->config->compbias != NULL)
+ for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++)
+ devp->compbias[i] = devp->config->compbias[i];
+ else
+ for(i = 0; i < LIS3MDL_COMP_NUMBER_OF_AXES; i++)
+ devp->compbias[i] = LIS3MDL_COMP_BIAS;
+
+ /* This is the MEMS transient recovery time */
+ osalThreadSleepMilliseconds(5);
+
+ devp->state = LIS3MDL_READY;
+}
+
+/**
+ * @brief Deactivates the LIS3MDL Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p LIS3MDLDriver object
+ *
+ * @api
+ */
+void lis3mdlStop(LIS3MDLDriver *devp) {
+ uint8_t cr[2];
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LIS3MDL_STOP) || (devp->state == LIS3MDL_READY),
+ "lis3mdlStop(), invalid state");
+
+ if (devp->state == LIS3MDL_READY) {
+#if (LIS3MDL_USE_I2C)
+#if LIS3MDL_SHARED_I2C
+ i2cAcquireBus((devp)->config->i2cp);
+ i2cStart((devp)->config->i2cp,
+ (devp)->config->i2ccfg);
+#endif /* LIS3MDL_SHARED_I2C */
+
+ /* Disabling compass. */
+ cr[0] = LIS3MDL_AD_CTRL_REG3;
+ cr[1] = LIS3MDL_CTRL_REG3_MD0 | LIS3MDL_CTRL_REG3_MD1;
+ lis3mdlI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
+ cr, 1);
+
+ i2cStop((devp)->config->i2cp);
+#if LIS3MDL_SHARED_I2C
+ i2cReleaseBus((devp)->config->i2cp);
+#endif /* LIS3MDL_SHARED_I2C */
+#endif /* LIS3MDL_USE_I2C */
+ }
+ devp->state = LIS3MDL_STOP;
+}
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lis3mdl.h b/ChibiOS_20.3.2/os/ex/devices/ST/lis3mdl.h
new file mode 100644
index 0000000..59f30f8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lis3mdl.h
@@ -0,0 +1,670 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file lis3mdl.h
+ * @brief LIS3MDL MEMS interface module header.
+ *
+ * @addtogroup LIS3MDL
+ * @ingroup EX_ST
+ * @{
+ */
+#ifndef _LIS3MDL_H_
+#define _LIS3MDL_H_
+
+#include "ex_compass.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Version identification
+ * @{
+ */
+/**
+ * @brief LIS3MDL driver version string.
+ */
+#define EX_LIS3MDL_VERSION "1.1.2"
+
+/**
+ * @brief LIS3MDL driver version major number.
+ */
+#define EX_LIS3MDL_MAJOR 1
+
+/**
+ * @brief LIS3MDL driver version minor number.
+ */
+#define EX_LIS3MDL_MINOR 1
+
+/**
+ * @brief LIS3MDL driver version patch number.
+ */
+#define EX_LIS3MDL_PATCH 2
+/** @} */
+
+/**
+ * @brief LIS3MDL compass subsystem characteristics.
+ * @note Sensitivity is expressed as G/LSB whereas G stands for Gauss.
+ * @note Bias is expressed as G.
+ *
+ * @{
+ */
+#define LIS3MDL_COMP_NUMBER_OF_AXES 3U
+
+#define LIS3MDL_COMP_4GA 4.0f
+#define LIS3MDL_COMP_8GA 8.0f
+#define LIS3MDL_COMP_12GA 12.0f
+#define LIS3MDL_COMP_16GA 16.0f
+
+#define LIS3MDL_COMP_SENS_4GA 0.00014615f
+#define LIS3MDL_COMP_SENS_8GA 0.00029231f
+#define LIS3MDL_COMP_SENS_12GA 0.0004384f
+#define LIS3MDL_COMP_SENS_16GA 0.00058445f
+
+#define LIS3MDL_COMP_BIAS 0.0f
+/** @} */
+
+/**
+ * @name LIS3MDL communication interfaces related bit masks
+ * @{
+ */
+#define LIS3MDL_DI_MASK 0xFF
+#define LIS3MDL_DI(n) (1 << n)
+#define LIS3MDL_AD_MASK 0x3F
+#define LIS3MDL_AD(n) (1 << n)
+#define LIS3MDL_MS (1 << 6)
+#define LIS3MDL_RW (1 << 7)
+
+#define LIS3MDL_SUB_MS (1 << 7)
+/** @} */
+
+/**
+ * @name LIS3MDL register addresses
+ * @{
+ */
+#define LIS3MDL_AD_WHO_AM_I 0x0F
+#define LIS3MDL_AD_CTRL_REG1 0x20
+#define LIS3MDL_AD_CTRL_REG2 0x21
+#define LIS3MDL_AD_CTRL_REG3 0x22
+#define LIS3MDL_AD_CTRL_REG4 0x23
+#define LIS3MDL_AD_CTRL_REG5 0x24
+#define LIS3MDL_AD_STATUS_REG 0x27
+#define LIS3MDL_AD_OUT_X_L 0x28
+#define LIS3MDL_AD_OUT_X_H 0x29
+#define LIS3MDL_AD_OUT_Y_L 0x2A
+#define LIS3MDL_AD_OUT_Y_H 0x2B
+#define LIS3MDL_AD_OUT_Z_L 0x2C
+#define LIS3MDL_AD_OUT_Z_H 0x2D
+#define LIS3MDL_AD_TEMP_OUT_L 0x2E
+#define LIS3MDL_AD_TEMP_OUT_H 0x2F
+#define LIS3MDL_AD_INT_CFG 0x30
+#define LIS3MDL_AD_INT_SOURCE 0x31
+#define LIS3MDL_AD_INT_THS_L 0x32
+#define LIS3MDL_AD_INT_THS_H 0x33
+/** @} */
+
+/**
+ * @name LIS3MDL_CTRL_REG1 register bits definitions
+ * @{
+ */
+#define LIS3MDL_CTRL_REG1_MASK 0xFF
+#define LIS3MDL_CTRL_REG1_ST (1 << 0)
+#define LIS3MDL_CTRL_REG1_FAST_ODR (1 << 1)
+#define LIS3MDL_CTRL_REG1_DO0 (1 << 2)
+#define LIS3MDL_CTRL_REG1_DO1 (1 << 3)
+#define LIS3MDL_CTRL_REG1_DO2 (1 << 4)
+#define LIS3MDL_CTRL_REG1_OM0 (1 << 5)
+#define LIS3MDL_CTRL_REG1_OM1 (1 << 6)
+#define LIS3MDL_CTRL_REG1_TEMP_EN (1 << 7)
+/** @} */
+
+/**
+ * @name LIS3MDL_CTRL_REG2 register bits definitions
+ * @{
+ */
+#define LIS3MDL_CTRL_REG2_MASK 0x6C
+#define LIS3MDL_CTRL_REG2_SOFT_RST (1 << 2)
+#define LIS3MDL_CTRL_REG2_REBOOT (1 << 3)
+#define LIS3MDL_CTRL_REG2_FS_MASK 0x60
+#define LIS3MDL_CTRL_REG2_FS0 (1 << 5)
+#define LIS3MDL_CTRL_REG2_FS1 (1 << 6)
+/** @} */
+
+/**
+ * @name LIS3MDL_CTRL_REG3 register bits definitions
+ * @{
+ */
+#define LIS3MDL_CTRL_REG3_MASK 0x27
+#define LIS3MDL_CTRL_REG3_MD0 (1 << 0)
+#define LIS3MDL_CTRL_REG3_MD1 (1 << 1)
+#define LIS3MDL_CTRL_REG3_SIM (1 << 2)
+#define LIS3MDL_CTRL_REG3_LP (1 << 5)
+/** @} */
+
+/**
+ * @name LIS3MDL_CTRL_REG4 register bits definitions
+ * @{
+ */
+#define LIS3MDL_CTRL_REG4_MASK 0x0E
+#define LIS3MDL_CTRL_REG4_BLE (1 << 1)
+#define LIS3MDL_CTRL_REG4_OMZ0 (1 << 2)
+#define LIS3MDL_CTRL_REG4_OMZ1 (1 << 3)
+/** @} */
+
+/**
+ * @name LIS3MDL_CTRL_REG5 register bits definitions
+ * @{
+ */
+#define LIS3MDL_CTRL_REG5_MASK 0xC0
+#define LIS3MDL_CTRL_REG5_BDU (1 << 6)
+#define LIS3MDL_CTRL_REG5_FAST_READ (1 << 7)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief LIS3MDL SPI interface switch.
+ * @details If set to @p TRUE the support for SPI is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(LIS3MDL_USE_SPI) || defined(__DOXYGEN__)
+#define LIS3MDL_USE_SPI FALSE
+#endif
+
+/**
+ * @brief LIS3MDL shared SPI switch.
+ * @details If set to @p TRUE the device acquires SPI bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(LIS3MDL_SHARED_SPI) || defined(__DOXYGEN__)
+#define LIS3MDL_SHARED_SPI FALSE
+#endif
+
+/**
+ * @brief LIS3MDL I2C interface switch.
+ * @details If set to @p TRUE the support for I2C is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(LIS3MDL_USE_I2C) || defined(__DOXYGEN__)
+#define LIS3MDL_USE_I2C TRUE
+#endif
+
+/**
+ * @brief LIS3MDL shared I2C switch.
+ * @details If set to @p TRUE the device acquires I2C bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION
+ */
+#if !defined(LIS3MDL_SHARED_I2C) || defined(__DOXYGEN__)
+#define LIS3MDL_SHARED_I2C FALSE
+#endif
+
+/**
+ * @brief LIS3MDL advanced configurations switch.
+ * @details If set to @p TRUE more configurations are available.
+ * @note The default is @p FALSE.
+ */
+#if !defined(LIS3MDL_USE_ADVANCED) || defined(__DOXYGEN__)
+#define LIS3MDL_USE_ADVANCED FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !(LIS3MDL_USE_SPI ^ LIS3MDL_USE_I2C)
+#error "LIS3MDL_USE_SPI and LIS3MDL_USE_I2C cannot be both true or both false"
+#endif
+
+#if LIS3MDL_USE_SPI && !HAL_USE_SPI
+#error "LIS3MDL_USE_SPI requires HAL_USE_SPI"
+#endif
+
+#if LIS3MDL_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION
+#error "LIS3MDL_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
+#endif
+
+#if LIS3MDL_USE_I2C && !HAL_USE_I2C
+#error "LIS3MDL_USE_I2C requires HAL_USE_I2C"
+#endif
+
+#if LIS3MDL_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
+#error "LIS3MDL_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
+#endif
+
+/*
+ * CHTODO: Add support for LIS3MDL over SPI.
+ */
+#if LIS3MDL_USE_SPI
+#error "LIS3MDL over SPI still not supported"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @name LIS3MDL data structures and types
+ * @{
+ */
+
+/**
+ * @brief LIS3MDL slave address
+ */
+/**
+ * @brief Structure representing a LIS3MDL driver.
+ */
+typedef struct LIS3MDLDriver LIS3MDLDriver;
+
+/**
+ * @brief LIS3MDL slave address
+ */
+typedef enum {
+ LIS3MDL_SAD_GND = 0x1C, /**< Slave Address when SA1 is to GND */
+ LIS3MDL_SAD_VCC = 0x1E /**< Slave Address when SA1 is to VCC */
+}lis3mdl_sad_t;
+
+/**
+ * @brief LIS3MDL full scale
+ */
+typedef enum {
+ LIS3MDL_COMP_FS_4GA = 0x00, /**< �4 Gauss */
+ LIS3MDL_COMP_FS_8GA = 0x20, /**< �8 Gauss */
+ LIS3MDL_COMP_FS_12GA = 0x40, /**< �12 Gauss */
+ LIS3MDL_COMP_FS_16GA = 0x60 /**< �16 Gauss */
+}lis3mdl_comp_fs_t;
+
+/**
+ * @brief LIS3MDL output data rate
+ */
+typedef enum {
+ LIS3MDL_COMP_ODR_0_625HZ = 0x00, /**< Output Data Rate = 0.625 Hz */
+ LIS3MDL_COMP_ODR_1_25HZ = 0x04, /**< Output Data Rate = 1.25 Hz */
+ LIS3MDL_COMP_ODR_2_5HZ = 0x08, /**< Output Data Rate = 2.5 Hz */
+ LIS3MDL_COMP_ODR_5HZ = 0x0C, /**< Output Data Rate = 5 Hz */
+ LIS3MDL_COMP_ODR_10HZ = 0x10, /**< Output Data Rate = 10 Hz */
+ LIS3MDL_COMP_ODR_20HZ = 0x14, /**< Output Data Rate = 20 Hz */
+ LIS3MDL_COMP_ODR_40HZ = 0x18, /**< Output Data Rate = 40 Hz */
+ LIS3MDL_COMP_ODR_80HZ = 0x1C /**< Output Data Rate = 80 Hz */
+}lis3mdl_comp_odr_t;
+
+/**
+ * @brief LIS3MDL low power mode configuration
+ */
+typedef enum {
+ LIS3MDL_COMP_LP_DISABLED = 0x00, /**< Low Power mode disabled */
+ LIS3MDL_COMP_LP_ENABLED = 0x20 /**< Low Power mode enabled */
+}lis3mdl_comp_lp_t;
+
+/**
+ * @brief LIS3MDL conversion mode
+ */
+typedef enum {
+ LIS3MDL_COMP_MD_CONTINUOUS = 0x00,/**< Continuous conversion mode */
+ LIS3MDL_COMP_MD_SINGLE = 0x01, /**< Single conversion mode */
+ LIS3MDL_COMP_MD_POWER_DOWN = 0x02 /**< Power down mode */
+}lis3mdl_comp_md_t;
+
+/**
+ * @brief LIS3MDL operation mode for X and Y axes
+ */
+typedef enum {
+ LIS3MDL_COMP_OMXY_LP = 0x00, /**< X-Y axes low power mode */
+ LIS3MDL_COMP_OMXY_MEDIUM = 0x20, /**< X-Y axes medium performance mode */
+ LIS3MDL_COMP_OMXY_HIGH = 0x40, /**< X-Y axes high performance mode */
+ LIS3MDL_COMP_OMXY_ULTRA = 0x60 /**< X-Y axes ultra performance mode */
+}lis3mdl_comp_omxy_t;
+
+/**
+ * @brief LIS3MDL operation mode for Z axis
+ */
+typedef enum {
+ LIS3MDL_COMP_OMZ_LP = 0x00, /**< Z axis low power mode */
+ LIS3MDL_COMP_OMZ_MEDIUM = 0x04, /**< Z axis medium performance mode */
+ LIS3MDL_COMP_OMZ_HIGH = 0x08, /**< Z axis high performance mode */
+ LIS3MDL_COMP_OMZ_ULTRA = 0x0C /**< Z axis ultra performance mode */
+}lis3mdl_comp_omz_t;
+
+/**
+ * @brief LIS3MDL temperature sensor enabling
+ */
+typedef enum {
+ LIS3MDL_TEMP_DISABLED = 0x00, /**< Temperature sensor disabled. */
+ LIS3MDL_TEMP_ENABLED = 0x80 /**< Temperature sensor enabled. */
+}lis3mdl_temp_t;
+
+/**
+ * @brief LIS3MDL block data update
+ */
+typedef enum {
+ LIS3MDL_BDU_CONTINUOUS = 0x00, /**< Continuous Update */
+ LIS3MDL_BDU_BLOCKED = 0x40 /**< Block data updated after reading. */
+}lis3mdl_bdu_t;
+
+/**
+ * @brief LIS3MDL endianness
+ */
+typedef enum {
+ LIS3MDL_END_LITTLE = 0x00, /**< Little endian. */
+ LIS3MDL_END_BIG = 0x02 /**< Big endian. */
+}lis3mdl_end_t;
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ LIS3MDL_UNINIT = 0, /**< Not initialized. */
+ LIS3MDL_STOP = 1, /**< Stopped. */
+ LIS3MDL_READY = 2, /**< Ready. */
+} lis3mdl_state_t;
+
+/**
+ * @brief LIS3MDL configuration structure.
+ */
+typedef struct {
+#if (LIS3MDL_USE_SPI) || defined(__DOXYGEN__)
+ /**
+ * @brief SPI driver associated to this LIS3MDL.
+ */
+ SPIDriver *spip;
+ /**
+ * @brief SPI configuration associated to this LIS3MDL.
+ */
+ const SPIConfig *spicfg;
+#endif /* LIS3MDL_USE_SPI */
+#if (LIS3MDL_USE_I2C) || defined(__DOXYGEN__)
+ /**
+ * @brief I2C driver associated to this LIS3MDL.
+ */
+ I2CDriver *i2cp;
+ /**
+ * @brief I2C configuration associated to this LIS3MDL.
+ */
+ const I2CConfig *i2ccfg;
+ /**
+ * @brief LIS3MDL slave address
+ */
+ lis3mdl_sad_t slaveaddress;
+#endif /* LIS3MDL_USE_I2C */
+ /**
+ * @brief LIS3MDL compass subsystem initial sensitivity.
+ */
+ float *compsensitivity;
+ /**
+ * @brief LIS3MDL compass subsystem initial bias.
+ */
+ float *compbias;
+ /**
+ * @brief LIS3MDL compass subsystem full scale.
+ */
+ lis3mdl_comp_fs_t compfullscale;
+ /**
+ * @brief LIS3MDL compass subsystem output data rate.
+ */
+ lis3mdl_comp_odr_t compoutputdatarate;
+#if LIS3MDL_USE_ADVANCED || defined(__DOXYGEN__)
+ /**
+ * @brief LIS3MDL compass subsystem low power mode configuration.
+ */
+ lis3mdl_comp_lp_t complowpowermode;
+ /**
+ * @brief LIS3MDL compass subsystem conversion mode.
+ */
+ lis3mdl_comp_md_t compconversionmode;
+ /**
+ * @brief LIS3MDL compass subsystem operation mode for X and Y axes.
+ */
+ lis3mdl_comp_omxy_t compoperationmodexy;
+ /**
+ * @brief LIS3MDL compass subsystem operation mode for Z axis.
+ */
+ lis3mdl_comp_omz_t compoperationmodez;
+ /**
+ * @brief LIS3MDL block data update.
+ */
+ lis3mdl_bdu_t blockdataupdate;
+ /**
+ * @brief LIS3MDL endianness.
+ */
+ lis3mdl_end_t endianness;
+#endif
+} LIS3MDLConfig;
+
+/**
+ * @brief @p LIS3MDL specific methods.
+ */
+#define _lis3msl_methods_alone \
+ /* Change full scale value of LIS3MDL compass subsystem.*/ \
+ msg_t (*comp_set_full_scale)(LIS3MDLDriver *devp, lis3mdl_comp_fs_t fs);
+
+/**
+ * @brief @p LIS3MDL specific methods with inherited ones.
+ */
+#define _lis3mdl_methods \
+ _base_object_methods \
+ _lis3msl_methods_alone
+
+/**
+ * @extends BaseCompassVMT
+ *
+ * @brief @p LIS3MDL virtual methods table.
+ */
+struct LIS3MDLVMT {
+ _lis3mdl_methods
+};
+
+/**
+ * @brief @p LIS3MDLDriver specific data.
+ */
+#define _lis3mdl_data \
+ _base_compass_data \
+ /* Driver state.*/ \
+ lis3mdl_state_t state; \
+ /* Current configuration data.*/ \
+ const LIS3MDLConfig *config; \
+ /* Compass subsystem axes number.*/ \
+ size_t compaxes; \
+ /* Compass subsystem current sensitivity.*/ \
+ float compsensitivity[LIS3MDL_COMP_NUMBER_OF_AXES]; \
+ /* Compass subsystem current bias.*/ \
+ float compbias[LIS3MDL_COMP_NUMBER_OF_AXES]; \
+ /* Compass subsystem current full scale value.*/ \
+ float compfullscale;
+
+/**
+ * @brief LIS3MDL 3-axis compass class.
+ */
+struct LIS3MDLDriver {
+ /** @brief Virtual Methods Table.*/
+ const struct LIS3MDLVMT *vmt;
+ /** @brief Base compass interface.*/
+ BaseCompass comp_if;
+ _lis3mdl_data
+};
+/** @} */
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Return the number of axes of the BaseCompass.
+ *
+ * @param[in] devp pointer to @p LIS3MDLDriver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define lis3mdlCompassGetAxesNumber(devp) \
+ compassGetAxesNumber(&((devp)->comp_if))
+
+/**
+ * @brief Retrieves raw data from the BaseCompass.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] devp pointer to @p BaseCompass interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lis3mdlCompassReadRaw(devp, axes) \
+ compassReadRaw(&((devp)->comp_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseCompass.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as G.
+ * @note The axes array must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] devp pointer to @p BaseCompass interface.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lis3mdlCompassReadCooked(devp, axes) \
+ compassReadCooked(&((devp)->comp_if), axes)
+
+/**
+ * @brief Set bias values for the BaseCompass.
+ * @note Bias must be expressed as G.
+ * @note The bias buffer must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] devp pointer to @p BaseCompass interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lis3mdlCompassSetBias(devp, bp) \
+ compassSetBias(&((devp)->comp_if), bp)
+
+/**
+ * @brief Reset bias values for the BaseCompass.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] devp pointer to @p LIS3MDLDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lis3mdlCompassResetBias(devp) \
+ compassResetBias(&((devp)->comp_if))
+
+/**
+ * @brief Set sensitivity values for the BaseCompass.
+ * @note Sensitivity must be expressed as G/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] devp pointer to @p LIS3MDLDriver.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lis3mdlCompassSetSensitivity(devp, sp) \
+ compassSetSensitivity(&((devp)->comp_if), sp)
+
+/**
+ * @brief Reset sensitivity values for the BaseCompass.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] devp pointer to @p LIS3MDLDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lis3mdlCompassResetSensitivity(devp) \
+ compassResetSensitivity(&((devp)->comp_if))
+
+/**
+ * @brief Changes the LIS3MDLDriver compass fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p LIS3MDLDriver.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lis3mdlCompassSetFullScale(devp, fs) \
+ (devp)->vmt->comp_set_full_scale(devp, fs)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void lis3mdlObjectInit(LIS3MDLDriver *devp);
+ void lis3mdlStart(LIS3MDLDriver *devp, const LIS3MDLConfig *config);
+ void lis3mdlStop(LIS3MDLDriver *devp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIS3MDL_H_ */
+
+/** @} */
+
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lis3mdl.mk b/ChibiOS_20.3.2/os/ex/devices/ST/lis3mdl.mk
new file mode 100644
index 0000000..00b6b0f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lis3mdl.mk
@@ -0,0 +1,10 @@
+# List of all the LIS3MDL device files.
+LIS3MDLSRC := $(CHIBIOS)/os/ex/devices/ST/lis3mdl.c
+
+# Required include directories
+LIS3MDLINC := $(CHIBIOS)/os/ex/include \
+ $(CHIBIOS)/os/ex/devices/ST
+
+# Shared variables
+ALLCSRC += $(LIS3MDLSRC)
+ALLINC += $(LIS3MDLINC)
\ No newline at end of file
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lps22hb.c b/ChibiOS_20.3.2/os/ex/devices/ST/lps22hb.c
new file mode 100644
index 0000000..9a89125
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lps22hb.c
@@ -0,0 +1,686 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file lps22hb.c
+ * @brief LPS22HB MEMS interface module code.
+ *
+ * @addtogroup LPS22HB
+ * @ingroup EX_ST
+ * @{
+ */
+
+#include "hal.h"
+#include "lps22hb.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#if (LPS22HB_USE_I2C) || defined(__DOXYGEN__)
+/**
+ * @brief Reads registers value using I2C.
+ * @pre The I2C interface must be initialized and the driver started.
+ *
+ * @param[in] i2cp pointer to the I2C interface
+ * @param[in] sad slave address without R bit
+ * @param[in] reg first sub-register address
+ * @param[out] rxbuf pointer to an output buffer
+ * @param[in] n number of consecutive register to read
+ * @return the operation status.
+ *
+ * @notapi
+ */
+static msg_t lps22hbI2CReadRegister(I2CDriver *i2cp, lps22hb_sad_t sad,
+ uint8_t reg, uint8_t* rxbuf, size_t n) {
+
+ return i2cMasterTransmitTimeout(i2cp, sad, ®, 1, rxbuf, n,
+ TIME_INFINITE);
+}
+
+/**
+ * @brief Writes a value into a register using I2C.
+ * @pre The I2C interface must be initialized and the driver started.
+ *
+ * @param[in] i2cp pointer to the I2C interface
+ * @param[in] sad slave address without R bit
+ * @param[in] txbuf buffer containing sub-address value in first position
+ * and values to write
+ * @param[in] n size of txbuf less one (not considering the first
+ * element)
+ * @return the operation status.
+ *
+ * @notapi
+ */
+#define lps22hbI2CWriteRegister(i2cp, sad, txbuf, n) \
+ i2cMasterTransmitTimeout(i2cp, sad, txbuf, n + 1, NULL, 0, \
+ TIME_INFINITE)
+#endif /* LPS22HB_USE_I2C */
+
+/**
+ * @brief Return the number of axes of the BaseBarometer.
+ *
+ * @param[in] ip pointer to @p BaseBarometer interface.
+ *
+ * @return the number of axes.
+ */
+static size_t baro_get_axes_number(void *ip) {
+ (void)ip;
+
+ return LPS22HB_BARO_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Retrieves raw data from the BaseBarometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseBarometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseBarometer interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t baro_read_raw(void *ip, int32_t axes[]) {
+ LPS22HBDriver* devp;
+ uint8_t buff[3];
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS22HBDriver*, (BaseBarometer*)ip);
+
+ osalDbgAssert((devp->state == LPS22HB_READY),
+ "baro_read_raw(), invalid state");
+
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "baro_read_raw(), channel not ready");
+
+#if LPS22HB_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LPS22HB_SHARED_I2C */
+
+ msg = lps22hbI2CReadRegister(devp->config->i2cp, devp->config->slaveaddress,
+ LPS22HB_AD_PRESS_OUT_XL, buff, 3);
+
+#if LPS22HB_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LPS22HB_SHARED_I2C */
+
+ if(msg == MSG_OK) {
+ *axes = buff[0] + (buff[1] << 8) + (buff[2] << 16);
+ }
+ return msg;
+}
+
+/**
+ * @brief Retrieves cooked data from the BaseBarometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as hPa.
+ * @note The axes array must be at least the same size of the
+ * BaseBarometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseBarometer interface.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t baro_read_cooked(void *ip, float axes[]) {
+ LPS22HBDriver* devp;
+ int32_t raw;
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS22HBDriver*, (BaseBarometer*)ip);
+
+ osalDbgAssert((devp->state == LPS22HB_READY),
+ "baro_read_cooked(), invalid state");
+
+ msg = baro_read_raw(ip, &raw);
+
+ *axes = (raw * devp->barosensitivity) - devp->barobias;
+
+ return msg;
+}
+
+/**
+ * @brief Set bias values for the BaseBarometer.
+ * @note Bias must be expressed as hPa.
+ * @note The bias buffer must be at least the same size of the
+ * BaseBarometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseBarometer interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t baro_set_bias(void *ip, float *bp) {
+ LPS22HBDriver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (bp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS22HBDriver*, (BaseBarometer*)ip);
+
+ osalDbgAssert((devp->state == LPS22HB_READY),
+ "baro_set_bias(), invalid state");
+
+ devp->barobias = *bp;
+ return msg;
+}
+
+/**
+ * @brief Reset bias values for the BaseBarometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] ip pointer to @p BaseBarometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t baro_reset_bias(void *ip) {
+ LPS22HBDriver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS22HBDriver*, (BaseBarometer*)ip);
+
+ osalDbgAssert((devp->state == LPS22HB_READY),
+ "baro_reset_bias(), invalid state");
+
+ devp->barobias = LPS22HB_BARO_SENS;
+ return msg;
+}
+
+/**
+ * @brief Set sensitivity values for the BaseBarometer.
+ * @note Sensitivity must be expressed as hPa/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseBarometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseBarometer interface.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t baro_set_sensitivity(void *ip, float *sp) {
+ LPS22HBDriver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (sp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS22HBDriver*, (BaseBarometer*)ip);
+
+ osalDbgAssert((devp->state == LPS22HB_READY),
+ "baro_set_sensitivity(), invalid state");
+
+ devp->barosensitivity = *sp;
+ return msg;
+}
+
+/**
+ * @brief Reset sensitivity values for the BaseBarometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] ip pointer to @p BaseBarometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t baro_reset_sensitivity(void *ip) {
+ LPS22HBDriver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS22HBDriver*, (BaseBarometer*)ip);
+
+ osalDbgAssert((devp->state == LPS22HB_READY),
+ "baro_reset_sensitivity(), invalid state");
+
+ devp->barosensitivity = LPS22HB_BARO_SENS;
+ return msg;
+}
+
+/**
+ * @brief Return the number of axes of the BaseThermometer.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ *
+ * @return the number of axes.
+ */
+static size_t thermo_get_axes_number(void *ip) {
+ (void)ip;
+
+ return LPS22HB_THERMO_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Retrieves raw data from the BaseThermometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t thermo_read_raw(void *ip, int32_t axes[]) {
+ LPS22HBDriver* devp;
+ int16_t tmp;
+ uint8_t buff[2];
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS22HBDriver*, (BaseThermometer*)ip);
+
+ osalDbgAssert((devp->state == LPS22HB_READY),
+ "thermo_read_raw(), invalid state");
+
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "thermo_read_raw(), channel not ready");
+
+#if LPS22HB_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LPS22HB_SHARED_I2C */
+
+ msg = lps22hbI2CReadRegister(devp->config->i2cp, devp->config->slaveaddress,
+ LPS22HB_AD_TEMP_OUT_L, buff, 2);
+
+#if LPS22HB_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LPS22HB_SHARED_I2C */
+
+ if (msg == MSG_OK) {
+ tmp = buff[0] + (buff[1] << 8);
+ *axes = (int32_t)tmp;
+ }
+ return msg;
+}
+
+/**
+ * @brief Retrieves cooked data from the BaseThermometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as °C.
+ * @note The axes array must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ * @param[out] axis a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t thermo_read_cooked(void *ip, float* axis) {
+ LPS22HBDriver* devp;
+ int32_t raw;
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axis != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS22HBDriver*, (BaseThermometer*)ip);
+
+ osalDbgAssert((devp->state == LPS22HB_READY),
+ "thermo_read_cooked(), invalid state");
+
+ msg = thermo_read_raw(devp, &raw);
+
+ *axis = (raw * devp->thermosensitivity) - devp->thermobias;
+
+ return msg;
+}
+
+/**
+ * @brief Set bias values for the BaseThermometer.
+ * @note Bias must be expressed as °C.
+ * @note The bias buffer must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t thermo_set_bias(void *ip, float *bp) {
+ LPS22HBDriver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (bp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS22HBDriver*, (BaseThermometer*)ip);
+
+ osalDbgAssert((devp->state == LPS22HB_READY),
+ "thermo_set_bias(), invalid state");
+
+ devp->thermobias = *bp;
+
+ return msg;
+}
+
+/**
+ * @brief Reset bias values for the BaseThermometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t thermo_reset_bias(void *ip) {
+ LPS22HBDriver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS22HBDriver*, (BaseThermometer*)ip);
+
+ osalDbgAssert((devp->state == LPS22HB_READY),
+ "thermo_reset_bias(), invalid state");
+
+ devp->thermobias = LPS22HB_THERMO_BIAS;
+
+ return msg;
+}
+
+/**
+ * @brief Set sensitivity values for the BaseThermometer.
+ * @note Sensitivity must be expressed as °C/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t thermo_set_sensitivity(void *ip, float *sp) {
+ LPS22HBDriver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (sp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS22HBDriver*, (BaseThermometer*)ip);
+
+ osalDbgAssert((devp->state == LPS22HB_READY),
+ "thermo_set_sensitivity(), invalid state");
+
+ devp->thermosensitivity = *sp;
+
+ return msg;
+}
+
+/**
+ * @brief Reset sensitivity values for the BaseThermometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t thermo_reset_sensitivity(void *ip) {
+ LPS22HBDriver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS22HBDriver*, (BaseThermometer*)ip);
+
+ osalDbgAssert((devp->state == LPS22HB_READY),
+ "thermo_reset_sensitivity(), invalid state");
+
+ devp->thermosensitivity = LPS22HB_THERMO_SENS;
+
+ return msg;
+}
+
+static const struct LPS22HBVMT vmt_device = {
+ (size_t)0
+};
+
+static const struct BaseBarometerVMT vmt_barometer = {
+ sizeof(struct LPS22HBVMT*),
+ baro_get_axes_number, baro_read_raw, baro_read_cooked,
+ baro_set_bias, baro_reset_bias, baro_set_sensitivity,
+ baro_reset_sensitivity
+};
+
+static const struct BaseThermometerVMT vmt_thermometer = {
+ sizeof(struct LPS22HBVMT*) + sizeof(BaseBarometer),
+ thermo_get_axes_number, thermo_read_raw, thermo_read_cooked,
+ thermo_set_bias, thermo_reset_bias, thermo_set_sensitivity,
+ thermo_reset_sensitivity
+};
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes an instance.
+ *
+ * @param[out] devp pointer to the @p LPS22HBDriver object
+ *
+ * @init
+ */
+void lps22hbObjectInit(LPS22HBDriver *devp) {
+
+ devp->vmt = &vmt_device;
+ devp->baro_if.vmt = &vmt_barometer;
+ devp->thermo_if.vmt = &vmt_thermometer;
+
+ devp->config = NULL;
+
+ devp->baroaxes = LPS22HB_BARO_NUMBER_OF_AXES;
+ devp->thermoaxes = LPS22HB_THERMO_NUMBER_OF_AXES;
+
+ devp->state = LPS22HB_STOP;
+}
+
+/**
+ * @brief Configures and activates LPS22HB Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p LPS22HBDriver object
+ * @param[in] config pointer to the @p LPS22HBConfig object
+ *
+ * @api
+ */
+void lps22hbStart(LPS22HBDriver *devp, const LPS22HBConfig *config) {
+ uint8_t cr[2];
+ osalDbgCheck((devp != NULL) && (config != NULL));
+
+ osalDbgAssert((devp->state == LPS22HB_STOP) || (devp->state == LPS22HB_READY),
+ "lps22hbStart(), invalid state");
+
+ devp->config = config;
+
+ /* Enabling register auto-increment.*/
+ /* Control register 1 configuration block.*/
+ {
+ cr[0] = LPS22HB_AD_CTRL_REG2;
+ cr[1] = LPS22HB_CTRL_REG2_IF_ADD_INC;
+ }
+#if LPS22HB_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+#endif /* LPS22HB_SHARED_I2C */
+
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+ lps22hbI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
+ cr, 1);
+
+#if LPS22HB_SHARED_I2C
+ i2cReleaseBus((devp)->config->i2cp);
+#endif /* LPS22HB_SHARED_I2C */
+
+ /* Control register 1 configuration block.*/
+ {
+ cr[0] = LPS22HB_AD_CTRL_REG1;
+ cr[1] = devp->config->outputdatarate;
+#if LPS22HB_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[1] |= devp->config->blockdataupdate;
+ cr[1] |= devp->config->lowpass_filter;
+#endif
+ }
+
+#if LPS22HB_SHARED_I2C
+ i2cAcquireBus((devp)->config->i2cp);
+ i2cStart((devp)->config->i2cp,
+ (devp)->config->i2ccfg);
+#endif /* LPS22HB_SHARED_I2C */
+
+ lps22hbI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress, cr, 1);
+
+#if LPS22HB_SHARED_I2C
+ i2cReleaseBus((devp)->config->i2cp);
+#endif /* LPS22HB_SHARED_I2C */
+
+ if(devp->config->barosensitivity == NULL) {
+ devp->barosensitivity = LPS22HB_BARO_SENS;
+ }
+ else{
+ /* Taking barometer sensitivity from user configurations */
+ devp->barosensitivity = *(devp->config->barosensitivity);
+ }
+
+ if(devp->config->barobias == NULL) {
+ devp->barobias = LPS22HB_BARO_BIAS;
+ }
+ else{
+ /* Taking barometer bias from user configurations */
+ devp->barobias = *(devp->config->barobias);
+ }
+
+ if(devp->config->thermosensitivity == NULL) {
+ devp->thermosensitivity = LPS22HB_THERMO_SENS;
+ }
+ else{
+ /* Taking thermometer sensitivity from user configurations */
+ devp->thermosensitivity = *(devp->config->thermosensitivity);
+ }
+
+ if(devp->config->thermobias == NULL) {
+ devp->thermobias = LPS22HB_THERMO_BIAS;
+ }
+ else{
+ /* Taking thermometer bias from user configurations */
+ devp->thermobias = *(devp->config->thermobias);
+ }
+
+ /* This is the Barometer transient recovery time */
+ osalThreadSleepMilliseconds(5);
+
+ devp->state = LPS22HB_READY;
+}
+
+/**
+ * @brief Deactivates the LPS22HB Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p LPS22HBDriver object
+ *
+ * @api
+ */
+void lps22hbStop(LPS22HBDriver *devp) {
+ uint8_t cr[2];
+
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LPS22HB_STOP) || (devp->state == LPS22HB_READY),
+ "lps22hbStop(), invalid state");
+
+ if (devp->state == LPS22HB_READY) {
+#if LPS22HB_SHARED_I2C
+ i2cAcquireBus((devp)->config->i2cp);
+ i2cStart((devp)->config->i2cp,
+ (devp)->config->i2ccfg);
+#endif /* LPS22HB_SHARED_I2C */
+
+ cr[0] = LPS22HB_AD_CTRL_REG1;
+ cr[1] = 0;
+ lps22hbI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
+ cr, 1);
+
+ i2cStop((devp)->config->i2cp);
+#if LPS22HB_SHARED_I2C
+ i2cReleaseBus((devp)->config->i2cp);
+#endif /* LPS22HB_SHARED_I2C */
+ }
+ devp->state = LPS22HB_STOP;
+}
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lps22hb.h b/ChibiOS_20.3.2/os/ex/devices/ST/lps22hb.h
new file mode 100644
index 0000000..12c9ddc
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lps22hb.h
@@ -0,0 +1,724 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file lps22hb.h
+ * @brief LPS22HB MEMS interface module header.
+ *
+ * @addtogroup LPS22HB
+ * @ingroup EX_ST
+ * @{
+ */
+#ifndef _LPS22HB_H_
+#define _LPS22HB_H_
+
+#include "ex_barometer.h"
+#include "ex_thermometer.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Version identification
+ * @{
+ */
+/**
+ * @brief LPS22HB driver version string.
+ */
+#define EX_LPS22HB_VERSION "1.0.2"
+
+/**
+ * @brief LPS22HB driver version major number.
+ */
+#define EX_LPS22HB_MAJOR 1
+
+/**
+ * @brief LPS22HB driver version minor number.
+ */
+#define EX_LPS22HB_MINOR 0
+
+/**
+ * @brief LPS22HB driver version patch number.
+ */
+#define EX_LPS22HB_PATCH 2
+/** @} */
+
+/**
+ * @brief LPS22HB barometer subsystem characteristics.
+ * @note Sensitivity is expressed as hPa/LSB whereas hPa stand for
+ * hectopascal.
+ * @note Bias is expressed as hPa.
+ *
+ * @{
+ */
+#define LPS22HB_BARO_NUMBER_OF_AXES 1U
+
+#define LPS22HB_BARO_SENS 0.00024414f
+#define LPS22HB_BARO_BIAS 0.0f
+/** @} */
+
+/**
+ * @brief LPS22HB thermometer subsystem characteristics.
+ * @note Sensitivity is expressed as �C/LSB.
+ * @note Bias is expressed as �C.
+ *
+ * @{
+ */
+#define LPS22HB_THERMO_NUMBER_OF_AXES 1U
+
+#define LPS22HB_THERMO_SENS 0.01f
+#define LPS22HB_THERMO_BIAS 0.0f
+/** @} */
+
+/**
+ * @name LPS22HB communication interfaces related bit masks
+ * @{
+ */
+#define LPS22HB_DI_MASK 0xFF
+#define LPS22HB_DI(n) (1 << n)
+#define LPS22HB_AD_MASK 0x3F
+#define LPS22HB_AD(n) (1 << n)
+#define LPS22HB_MS (1 << 6)
+#define LPS22HB_RW (1 << 7)
+
+#define LPS22HB_SUB_MS (1 << 7)
+/** @} */
+
+/**
+ * @name LPS22HB register addresses
+ * @{
+ */
+#define LPS22HB_AD_INT_CFG 0x0B
+#define LPS22HB_AD_THS_P_L 0x0C
+#define LPS22HB_AD_THS_P_H 0x0D
+#define LPS22HB_AD_WHO_AM_I 0x0F
+#define LPS22HB_AD_CTRL_REG1 0x10
+#define LPS22HB_AD_CTRL_REG2 0x11
+#define LPS22HB_AD_CTRL_REG3 0x12
+#define LPS22HB_AD_FIFO_CTRL 0x14
+#define LPS22HB_AD_REF_P_XL 0x15
+#define LPS22HB_AD_REF_P_L 0x16
+#define LPS22HB_AD_REF_P_H 0x17
+#define LPS22HB_AD_RPDS_L 0x18
+#define LPS22HB_AD_RPDS_H 0x19
+#define LPS22HB_AD_RES_CONF 0x1A
+#define LPS22HB_AD_INT_SRC 0x25
+#define LPS22HB_AD_FIFO_SRC 0x26
+#define LPS22HB_AD_STATUS_REG 0x27
+#define LPS22HB_AD_PRESS_OUT_XL 0x28
+#define LPS22HB_AD_PRESS_OUT_L 0x29
+#define LPS22HB_AD_PRESS_OUT_H 0x2A
+#define LPS22HB_AD_TEMP_OUT_L 0x2B
+#define LPS22HB_AD_TEMP_OUT_H 0x2C
+#define LPS22HB_AD_LPFP_RES 0x33
+/** @} */
+
+/**
+ * @name LPS22HB_INT_CFG register bits definitions
+ * @{
+ */
+#define LPS22HB_INT_CFG_MASK 0xFF
+#define LPS22HB_INT_CFG_PHE (1 << 0)
+#define LPS22HB_INT_CFG_PLE (1 << 1)
+#define LPS22HB_INT_CFG_LIR (1 << 2)
+#define LPS22HB_INT_CFG_DIFF_EN (1 << 3)
+#define LPS22HB_INT_CFG_RESET_AZ (1 << 4)
+#define LPS22HB_INT_CFG_AUTOZERO (1 << 5)
+#define LPS22HB_INT_CFG_RESET_ARP (1 << 6)
+#define LPS22HB_INT_CFG_AUTORIFP (1 << 7)
+/** @} */
+
+/**
+ * @name LPS22HB_CTRL_REG1 register bits definitions
+ * @{
+ */
+#define LPS22HB_CTRL_REG1_MASK 0x7F
+#define LPS22HB_CTRL_REG1_SIM (1 << 0)
+#define LPS22HB_CTRL_REG1_BDU (1 << 1)
+#define LPS22HB_CTRL_REG1_LPFP_CFG (1 << 2)
+#define LPS22HB_CTRL_REG1_LPFP_EN (1 << 3)
+#define LPS22HB_CTRL_REG1_ODR0 (1 << 4)
+#define LPS22HB_CTRL_REG1_ODR1 (1 << 5)
+#define LPS22HB_CTRL_REG1_ODR2 (1 << 6)
+/** @} */
+
+/**
+ * @name LPS22HB_CTRL_REG2 register bits definitions
+ * @{
+ */
+#define LPS22HB_CTRL_REG2_MASK 0xFD
+#define LPS22HB_CTRL_REG2_ONE_SHOT (1 << 0)
+#define LPS22HB_CTRL_REG2_SWRESET (1 << 2)
+#define LPS22HB_CTRL_REG2_I2C_DIS (1 << 3)
+#define LPS22HB_CTRL_REG2_IF_ADD_INC (1 << 4)
+#define LPS22HB_CTRL_REG2_STOP_ON_FTH (1 << 5)
+#define LPS22HB_CTRL_REG2_FIFO_EN (1 << 6)
+#define LPS22HB_CTRL_REG2_BOOT (1 << 7)
+/** @} */
+
+/**
+ * @name LPS22HB_CTRL_REG3 register bits definitions
+ * @{
+ */
+#define LPS22HB_CTRL_REG3_MASK 0xFF
+#define LPS22HB_CTRL_REG3_INT_S1 (1 << 0)
+#define LPS22HB_CTRL_REG3_INT_S2 (1 << 1)
+#define LPS22HB_CTRL_REG3_DRDY (1 << 2)
+#define LPS22HB_CTRL_REG3_F_OVR (1 << 3)
+#define LPS22HB_CTRL_REG3_F_FTH (1 << 4)
+#define LPS22HB_CTRL_REG3_F_FSS5 (1 << 5)
+#define LPS22HB_CTRL_REG3_PP_OD (1 << 6)
+#define LPS22HB_CTRL_REG3_INT_H_L (1 << 7)
+/** @} */
+
+/**
+ * @name LPS22HB_INT_SRC register bits definitions
+ * @{
+ */
+#define LPS22HB_INT_SRC_MASK 0x87
+#define LPS22HB_INT_SRC_PH (1 << 0)
+#define LPS22HB_INT_SRC_PL (1 << 1)
+#define LPS22HB_INT_SRC_IA (1 << 2)
+#define LPS22HB_INT_SRC_BOOT_STATUS (1 << 8)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief LPS22HB SPI interface switch.
+ * @details If set to @p TRUE the support for SPI is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(LPS22HB_USE_SPI) || defined(__DOXYGEN__)
+#define LPS22HB_USE_SPI FALSE
+#endif
+
+/**
+ * @brief LPS22HB shared SPI switch.
+ * @details If set to @p TRUE the device acquires SPI bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(LPS22HB_SHARED_SPI) || defined(__DOXYGEN__)
+#define LPS22HB_SHARED_SPI FALSE
+#endif
+
+/**
+ * @brief LPS22HB I2C interface switch.
+ * @details If set to @p TRUE the support for I2C is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(LPS22HB_USE_I2C) || defined(__DOXYGEN__)
+#define LPS22HB_USE_I2C TRUE
+#endif
+
+/**
+ * @brief LPS22HB shared I2C switch.
+ * @details If set to @p TRUE the device acquires I2C bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(LPS22HB_SHARED_I2C) || defined(__DOXYGEN__)
+#define LPS22HB_SHARED_I2C FALSE
+#endif
+
+/**
+ * @brief LPS22HB advanced configurations switch.
+ * @details If set to @p TRUE more configurations are available.
+ * @note The default is @p FALSE.
+ */
+#if !defined(LPS22HB_USE_ADVANCED) || defined(__DOXYGEN__)
+#define LPS22HB_USE_ADVANCED FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !(LPS22HB_USE_SPI ^ LPS22HB_USE_I2C)
+#error "LPS22HB_USE_SPI and LPS22HB_USE_I2C cannot be both true or both false"
+#endif
+
+#if LPS22HB_USE_SPI && !HAL_USE_SPI
+#error "LPS22HB_USE_SPI requires HAL_USE_SPI"
+#endif
+
+#if LPS22HB_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION
+#error "LPS22HB_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
+#endif
+
+#if LPS22HB_USE_I2C && !HAL_USE_I2C
+#error "LPS22HB_USE_I2C requires HAL_USE_I2C"
+#endif
+
+#if LPS22HB_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
+#error "LPS22HB_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
+#endif
+
+/*
+ * CHTODO: Add support for LPS22HB over SPI.
+ */
+#if LPS22HB_USE_SPI
+#error "LPS22HB over SPI still not supported"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @name LPS22HB data structures and types.
+ * @{
+ */
+/**
+ * @brief Structure representing a LPS22HB driver.
+ */
+typedef struct LPS22HBDriver LPS22HBDriver;
+
+/**
+ * @brief LPS22HB slave address
+ */
+typedef enum {
+ LPS22HB_SAD_GND = 0x5C, /**< Slave Address when SA0 is to GND */
+ LPS22HB_SAD_VCC = 0x5D /**< Slave Address when SA0 is to VCC */
+}lps22hb_sad_t;
+
+/**
+ * @brief LPS22HB output data rate and bandwidth.
+ */
+typedef enum {
+ LPS22HB_ODR_PD = 0x00, /**< Power down. */
+ LPS22HB_ODR_1HZ = 0x10, /**< Output data rate 1 Hz. */
+ LPS22HB_ODR_10HZ = 0x20, /**< Output data rate 10 Hz. */
+ LPS22HB_ODR_25HZ = 0x30, /**< Output data rate 25 Hz. */
+ LPS22HB_ODR_50HZ = 0x40, /**< Output data rate 50 Hz. */
+ LPS22HB_ODR_75HZ = 0x50 /**< Output data rate 75 Hz. */
+}lps22hb_odr_t;
+
+/**
+ * @brief LPS22HB pressure resolution.
+ */
+typedef enum {
+ LPS22HB_LP_DISABLED = 0x00, /**< LP Filter disabled. */
+ LPS22HB_LP_ODR_9 = 0x08, /**< LP Filter enabled. Cut-off ORD/9. */
+ LPS22HB_LP_ODR_20 = 0x0C /**< LP Filter enabled. Cut-off ORD/20. */
+}lps22hb_lp_t;
+
+/**
+ * @brief LPS22HB block data update.
+ */
+typedef enum {
+ LPS22HB_BDU_CONTINUOUS = 0x00, /**< Block data continuously updated. */
+ LPS22HB_BDU_BLOCKED = 0x40 /**< Block data updated after reading. */
+}lps22hb_bdu_t;
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ LPS22HB_UNINIT = 0, /**< Not initialized. */
+ LPS22HB_STOP = 1, /**< Stopped. */
+ LPS22HB_READY = 2, /**< Ready. */
+} lps22hb_state_t;
+
+/**
+ * @brief LPS22HB configuration structure.
+ */
+typedef struct {
+
+#if LPS22HB_USE_SPI || defined(__DOXYGEN__)
+ /**
+ * @brief SPI driver associated to this LPS22HB.
+ */
+ SPIDriver *spip;
+ /**
+ * @brief SPI configuration associated to this LPS22HB.
+ */
+ const SPIConfig *spicfg;
+#endif /* LPS22HB_USE_SPI */
+#if LPS22HB_USE_I2C || defined(__DOXYGEN__)
+ /**
+ * @brief I2C driver associated to this LPS22HB.
+ */
+ I2CDriver *i2cp;
+ /**
+ * @brief I2C configuration associated to this LPS22HB.
+ */
+ const I2CConfig *i2ccfg;
+ /**
+ * @brief LPS22HB slave address
+ */
+ lps22hb_sad_t slaveaddress;
+#endif /* LPS22HB_USE_I2C */
+ /**
+ * @brief LPS22HB barometer subsystem initial sensitivity.
+ */
+ float *barosensitivity;
+ /**
+ * @brief LPS22HB barometer subsystem initial bias.
+ */
+ float *barobias;
+ /**
+ * @brief LPS22HB thermometer subsystem initial sensitivity.
+ */
+ float *thermosensitivity;
+ /**
+ * @brief LPS22HB thermometer subsystem initial bias.
+ */
+ float *thermobias;
+ /**
+ * @brief LPS22HB output data rate selection.
+ */
+ lps22hb_odr_t outputdatarate;
+#if LPS22HB_USE_ADVANCED || defined(__DOXYGEN__)
+ /**
+ * @brief LPS22HB block data update.
+ */
+ lps22hb_bdu_t blockdataupdate;
+ /**
+ * @brief LPS22HB barometer subsystem resolution.
+ */
+ lps22hb_lp_t lowpass_filter;
+#endif
+} LPS22HBConfig;
+
+/**
+ * @brief @p LPS22HB specific methods.
+ * @note No methods so far, just a common ancestor interface.
+ */
+#define _lps22hb_methods_alone
+
+/**
+ * @brief @p LPS22HB specific methods with inherited ones.
+ */
+#define _lps22hb_methods \
+ _base_object_methods \
+ _lps22hb_methods_alone
+
+/**
+ * @extends BaseObjectVMT
+ *
+ * @brief @p LPS22HB virtual methods table.
+ */
+struct LPS22HBVMT {
+ _lps22hb_methods
+};
+
+/**
+ * @brief @p LPS22HBDriver specific data.
+ */
+#define _lps22hb_data \
+ /* Driver state.*/ \
+ lps22hb_state_t state; \
+ /* Current configuration data.*/ \
+ const LPS22HBConfig *config; \
+ /* Barometer subsystem axes number.*/ \
+ size_t baroaxes; \
+ /* Barometer subsystem current sensitivity.*/ \
+ float barosensitivity; \
+ /* Barometer subsystem current bias .*/ \
+ float barobias; \
+ /* Thermometer subsystem axes number.*/ \
+ size_t thermoaxes; \
+ /* Thermometer subsystem current sensitivity.*/ \
+ float thermosensitivity; \
+ /* Thermometer subsystem current bias.*/ \
+ float thermobias;
+
+/**
+ * @brief LPS22HB 2-axis barometer/thermometer class.
+ */
+struct LPS22HBDriver {
+ /** @brief Virtual Methods Table.*/
+ const struct LPS22HBVMT *vmt;
+ /** @brief Base barometer interface.*/
+ BaseBarometer baro_if;
+ /** @brief Base thermometer interface.*/
+ BaseThermometer thermo_if;
+ _lps22hb_data
+};
+/** @} */
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Return the number of axes of the BaseBarometer.
+ *
+ * @param[in] devp pointer to @p LPS22HBDriver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define lps22hbBarometerGetAxesNumber(devp) \
+ barometerGetAxesNumber(&((devp)->baro_if))
+
+/**
+ * @brief Retrieves raw data from the BaseBarometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseBarometer axes number.
+ *
+ * @param[in] devp pointer to @p LPS22HBDriver.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lps22hbBarometerReadRaw(devp, axes) \
+ barometerReadRaw(&((devp)->baro_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseBarometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as hPa.
+ * @note The axes array must be at least the same size of the
+ * BaseBarometer axes number.
+ *
+ * @param[in] devp pointer to @p LPS22HBDriver.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lps22hbBarometerReadCooked(devp, axes) \
+ barometerReadCooked(&((devp)->baro_if), axes)
+
+/**
+ * @brief Set bias values for the BaseBarometer.
+ * @note Bias must be expressed as hPa.
+ * @note The bias buffer must be at least the same size of the
+ * BaseBarometer axes number.
+ *
+ * @param[in] devp pointer to @p LPS22HBDriver.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lps22hbBarometerSetBias(devp, bp) \
+ barometerSetBias(&((devp)->baro_if), bp)
+
+/**
+ * @brief Reset bias values for the BaseBarometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] devp pointer to @p LPS22HBDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lps22hbBarometerResetBias(devp) \
+ barometerResetBias(&((devp)->baro_if))
+
+/**
+ * @brief Set sensitivity values for the BaseBarometer.
+ * @note Sensitivity must be expressed as hPa/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseBarometer axes number.
+ *
+ * @param[in] devp pointer to @p LPS22HBDriver.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lps22hbBarometerSetSensitivity(devp, sp) \
+ barometerSetSensitivity(&((devp)->baro_if), sp)
+
+/**
+ * @brief Reset sensitivity values for the BaseBarometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] devp pointer to @p LPS22HBDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lps22hbBarometerResetSensitivity(devp) \
+ barometerResetSensitivity(&((devp)->baro_if))
+
+/**
+ * @brief Return the number of axes of the BaseThermometer.
+ *
+ * @param[in] devp pointer to @p LPS22HBDriver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define lps22hbThermometerGetAxesNumber(devp) \
+ thermometerGetAxesNumber(&((devp)->thermo_if))
+
+/**
+ * @brief Retrieves raw data from the BaseThermometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] devp pointer to @p LPS22HBDriver.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lps22hbThermometerReadRaw(devp, axes) \
+ thermometerReadRaw(&((devp)->thermo_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseThermometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as °C.
+ * @note The axes array must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] devp pointer to @p LPS22HBDriver.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lps22hbThermometerReadCooked(devp, axes) \
+ thermometerReadCooked(&((devp)->thermo_if), axes)
+
+/**
+ * @brief Set bias values for the BaseThermometer.
+ * @note Bias must be expressed as °C.
+ * @note The bias buffer must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] devp pointer to @p LPS22HBDriver.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lps22hbThermometerSetBias(devp, bp) \
+ thermometerSetBias(&((devp)->thermo_if), bp)
+
+/**
+ * @brief Reset bias values for the BaseThermometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] devp pointer to @p LPS22HBDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lps22hbThermometerResetBias(devp) \
+ thermometerResetBias(&((devp)->thermo_if))
+
+/**
+ * @brief Set sensitivity values for the BaseThermometer.
+ * @note Sensitivity must be expressed as °C/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] devp pointer to @p LPS22HBDriver.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lps22hbThermometerSetSensitivity(devp, sp) \
+ thermometerSetSensitivity(&((devp)->thermo_if), sp)
+
+/**
+ * @brief Reset sensitivity values for the BaseThermometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] devp pointer to @p LPS22HBDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lps22hbThermometerResetSensitivity(devp) \
+ thermometerResetSensitivity(&((devp)->thermo_if))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void lps22hbObjectInit(LPS22HBDriver *devp);
+ void lps22hbStart(LPS22HBDriver *devp, const LPS22HBConfig *config);
+ void lps22hbStop(LPS22HBDriver *devp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LPS22HB_H_ */
+
+/** @} */
+
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lps22hb.mk b/ChibiOS_20.3.2/os/ex/devices/ST/lps22hb.mk
new file mode 100644
index 0000000..47fe88e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lps22hb.mk
@@ -0,0 +1,10 @@
+# List of all the LPS22HB device files.
+LPS22HBSRC := $(CHIBIOS)/os/ex/devices/ST/lps22hb.c
+
+# Required include directories
+LPS22HBINC := $(CHIBIOS)/os/ex/include \
+ $(CHIBIOS)/os/ex/devices/ST
+
+# Shared variables
+ALLCSRC += $(LPS22HBSRC)
+ALLINC += $(LPS22HBINC)
\ No newline at end of file
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lps25h.c b/ChibiOS_20.3.2/os/ex/devices/ST/lps25h.c
new file mode 100644
index 0000000..3aa651f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lps25h.c
@@ -0,0 +1,696 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file lps25h.c
+ * @brief LPS25H MEMS interface module code.
+ *
+ * @addtogroup LPS25H
+ * @ingroup EX_ST
+ * @{
+ */
+
+#include "hal.h"
+#include "lps25h.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#if (LPS25H_USE_I2C) || defined(__DOXYGEN__)
+/**
+ * @brief Reads registers value using I2C.
+ * @pre The I2C interface must be initialized and the driver started.
+ *
+ * @param[in] i2cp pointer to the I2C interface
+ * @param[in] sad slave address without R bit
+ * @param[in] reg first sub-register address
+ * @param[out] rxbuf pointer to an output buffer
+ * @param[in] n number of consecutive register to read
+ * @return the operation status.
+ *
+ * @notapi
+ */
+static msg_t lps25hI2CReadRegister(I2CDriver *i2cp, lps25h_sad_t sad,
+ uint8_t reg, uint8_t* rxbuf, size_t n) {
+ uint8_t txbuf = reg;
+ if(n > 1)
+ txbuf |= LPS25H_SUB_MS;
+
+ return i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, n,
+ TIME_INFINITE);
+}
+
+/**
+ * @brief Writes a value into a register using I2C.
+ * @pre The I2C interface must be initialized and the driver started.
+ *
+ * @param[in] i2cp pointer to the I2C interface
+ * @param[in] sad slave address without R bit
+ * @param[in] txbuf buffer containing sub-address value in first position
+ * and values to write
+ * @param[in] n size of txbuf less one (not considering the first
+ * element)
+ * @return the operation status.
+ *
+ * @notapi
+ */
+static msg_t lps25hI2CWriteRegister(I2CDriver *i2cp, lps25h_sad_t sad,
+ uint8_t* txbuf, size_t n) {
+ if (n > 1)
+ (*txbuf) |= LPS25H_SUB_MS;
+ return i2cMasterTransmitTimeout(i2cp, sad, txbuf, n + 1, NULL, 0,
+ TIME_INFINITE);
+}
+#endif /* LPS25H_USE_I2C */
+
+/**
+ * @brief Return the number of axes of the BaseBarometer.
+ *
+ * @param[in] ip pointer to @p BaseBarometer interface.
+ *
+ * @return the number of axes.
+ */
+static size_t baro_get_axes_number(void *ip) {
+ (void)ip;
+
+ return LPS25H_BARO_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Retrieves raw data from the BaseBarometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseBarometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseBarometer interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t baro_read_raw(void *ip, int32_t axes[]) {
+ LPS25HDriver* devp;
+ uint8_t buff[3];
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS25HDriver*, (BaseBarometer*)ip);
+
+ osalDbgAssert((devp->state == LPS25H_READY),
+ "baro_read_raw(), invalid state");
+
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "baro_read_raw(), channel not ready");
+
+#if LPS25H_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LPS25H_SHARED_I2C */
+
+ msg = lps25hI2CReadRegister(devp->config->i2cp, devp->config->slaveaddress,
+ LPS25H_AD_PRESS_OUT_XL, buff, 3);
+
+#if LPS25H_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LPS25H_SHARED_I2C */
+
+ if(msg == MSG_OK) {
+ *axes = buff[0] + (buff[1] << 8) + (buff[2] << 16);
+ }
+ return msg;
+}
+
+/**
+ * @brief Retrieves cooked data from the BaseBarometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as hPa.
+ * @note The axes array must be at least the same size of the
+ * BaseBarometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseBarometer interface.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t baro_read_cooked(void *ip, float axes[]) {
+ LPS25HDriver* devp;
+ int32_t raw;
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS25HDriver*, (BaseBarometer*)ip);
+
+ osalDbgAssert((devp->state == LPS25H_READY),
+ "baro_read_cooked(), invalid state");
+
+ msg = baro_read_raw(ip, &raw);
+
+ *axes = (raw * devp->barosensitivity) - devp->barobias;
+
+ return msg;
+}
+
+/**
+ * @brief Set bias values for the BaseBarometer.
+ * @note Bias must be expressed as hPa.
+ * @note The bias buffer must be at least the same size of the
+ * BaseBarometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseBarometer interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t baro_set_bias(void *ip, float *bp) {
+ LPS25HDriver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (bp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS25HDriver*, (BaseBarometer*)ip);
+
+ osalDbgAssert((devp->state == LPS25H_READY),
+ "baro_set_bias(), invalid state");
+
+ devp->barobias = *bp;
+ return msg;
+}
+
+/**
+ * @brief Reset bias values for the BaseBarometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] ip pointer to @p BaseBarometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t baro_reset_bias(void *ip) {
+ LPS25HDriver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS25HDriver*, (BaseBarometer*)ip);
+
+ osalDbgAssert((devp->state == LPS25H_READY),
+ "baro_reset_bias(), invalid state");
+
+ devp->barobias = LPS25H_BARO_SENS;
+ return msg;
+}
+
+/**
+ * @brief Set sensitivity values for the BaseBarometer.
+ * @note Sensitivity must be expressed as hPa/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseBarometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseBarometer interface.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t baro_set_sensitivity(void *ip, float *sp) {
+ LPS25HDriver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (sp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS25HDriver*, (BaseBarometer*)ip);
+
+ osalDbgAssert((devp->state == LPS25H_READY),
+ "baro_set_sensitivity(), invalid state");
+
+ devp->barosensitivity = *sp;
+ return msg;
+}
+
+/**
+ * @brief Reset sensitivity values for the BaseBarometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] ip pointer to @p BaseBarometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t baro_reset_sensitivity(void *ip) {
+ LPS25HDriver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS25HDriver*, (BaseBarometer*)ip);
+
+ osalDbgAssert((devp->state == LPS25H_READY),
+ "baro_reset_sensitivity(), invalid state");
+
+ devp->barosensitivity = LPS25H_BARO_SENS;
+ return msg;
+}
+
+/**
+ * @brief Return the number of axes of the BaseThermometer.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ *
+ * @return the number of axes.
+ */
+static size_t thermo_get_axes_number(void *ip) {
+ (void)ip;
+
+ return LPS25H_THERMO_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Retrieves raw data from the BaseThermometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t thermo_read_raw(void *ip, int32_t axes[]) {
+ LPS25HDriver* devp;
+ int16_t tmp;
+ uint8_t buff[2];
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS25HDriver*, (BaseThermometer*)ip);
+
+ osalDbgAssert((devp->state == LPS25H_READY),
+ "thermo_read_raw(), invalid state");
+
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "thermo_read_raw(), channel not ready");
+
+#if LPS25H_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LPS25H_SHARED_I2C */
+
+ msg = lps25hI2CReadRegister(devp->config->i2cp, devp->config->slaveaddress,
+ LPS25H_AD_TEMP_OUT_L, buff, 2);
+
+#if LPS25H_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LPS25H_SHARED_I2C */
+
+ if (msg == MSG_OK) {
+ tmp = buff[0] + (buff[1] << 8);
+ *axes = (int32_t)tmp;
+ }
+ return msg;
+}
+
+/**
+ * @brief Retrieves cooked data from the BaseThermometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as °C.
+ * @note The axes array must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ * @param[out] axis a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t thermo_read_cooked(void *ip, float* axis) {
+ LPS25HDriver* devp;
+ int32_t raw;
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axis != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS25HDriver*, (BaseThermometer*)ip);
+
+ osalDbgAssert((devp->state == LPS25H_READY),
+ "thermo_read_cooked(), invalid state");
+
+ msg = thermo_read_raw(devp, &raw);
+
+ *axis = (raw * devp->thermosensitivity) - devp->thermobias;
+
+ return msg;
+}
+
+/**
+ * @brief Set bias values for the BaseThermometer.
+ * @note Bias must be expressed as °C.
+ * @note The bias buffer must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t thermo_set_bias(void *ip, float *bp) {
+ LPS25HDriver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (bp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS25HDriver*, (BaseThermometer*)ip);
+
+ osalDbgAssert((devp->state == LPS25H_READY),
+ "thermo_set_bias(), invalid state");
+
+ devp->thermobias = *bp;
+
+ return msg;
+}
+
+/**
+ * @brief Reset bias values for the BaseThermometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t thermo_reset_bias(void *ip) {
+ LPS25HDriver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS25HDriver*, (BaseThermometer*)ip);
+
+ osalDbgAssert((devp->state == LPS25H_READY),
+ "thermo_reset_bias(), invalid state");
+
+ devp->thermobias = LPS25H_THERMO_BIAS;
+
+ return msg;
+}
+
+/**
+ * @brief Set sensitivity values for the BaseThermometer.
+ * @note Sensitivity must be expressed as °C/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t thermo_set_sensitivity(void *ip, float *sp) {
+ LPS25HDriver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (sp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS25HDriver*, (BaseThermometer*)ip);
+
+ osalDbgAssert((devp->state == LPS25H_READY),
+ "thermo_set_sensitivity(), invalid state");
+
+ devp->thermosensitivity = *sp;
+
+ return msg;
+}
+
+/**
+ * @brief Reset sensitivity values for the BaseThermometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] ip pointer to @p BaseThermometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t thermo_reset_sensitivity(void *ip) {
+ LPS25HDriver* devp;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LPS25HDriver*, (BaseThermometer*)ip);
+
+ osalDbgAssert((devp->state == LPS25H_READY),
+ "thermo_reset_sensitivity(), invalid state");
+
+ devp->thermosensitivity = LPS25H_THERMO_SENS;
+
+ return msg;
+}
+
+static const struct LPS25HVMT vmt_device = {
+ (size_t)0
+};
+
+static const struct BaseBarometerVMT vmt_barometer = {
+ sizeof(struct LPS25HVMT*),
+ baro_get_axes_number, baro_read_raw, baro_read_cooked,
+ baro_set_bias, baro_reset_bias, baro_set_sensitivity,
+ baro_reset_sensitivity
+};
+
+static const struct BaseThermometerVMT vmt_thermometer = {
+ sizeof(struct LPS25HVMT*) + sizeof(BaseBarometer),
+ thermo_get_axes_number, thermo_read_raw, thermo_read_cooked,
+ thermo_set_bias, thermo_reset_bias, thermo_set_sensitivity,
+ thermo_reset_sensitivity
+};
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes an instance.
+ *
+ * @param[out] devp pointer to the @p LPS25HDriver object
+ *
+ * @init
+ */
+void lps25hObjectInit(LPS25HDriver *devp) {
+
+ devp->vmt = &vmt_device;
+ devp->baro_if.vmt = &vmt_barometer;
+ devp->thermo_if.vmt = &vmt_thermometer;
+
+ devp->config = NULL;
+
+ devp->baroaxes = LPS25H_BARO_NUMBER_OF_AXES;
+ devp->thermoaxes = LPS25H_THERMO_NUMBER_OF_AXES;
+
+ devp->state = LPS25H_STOP;
+}
+
+/**
+ * @brief Configures and activates LPS25H Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p LPS25HDriver object
+ * @param[in] config pointer to the @p LPS25HConfig object
+ *
+ * @api
+ */
+void lps25hStart(LPS25HDriver *devp, const LPS25HConfig *config) {
+ uint8_t cr[2];
+ osalDbgCheck((devp != NULL) && (config != NULL));
+
+ osalDbgAssert((devp->state == LPS25H_STOP) || (devp->state == LPS25H_READY),
+ "lps25hStart(), invalid state");
+
+ devp->config = config;
+
+ /* Control register 1 configuration block.*/
+ {
+ cr[0] = LPS25H_AD_CTRL_REG1;
+ cr[1] = devp->config->outputdatarate | LPS25H_CTRL_REG1_PD;
+#if LPS25H_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[1] |= devp->config->blockdataupdate;
+#endif
+ }
+
+#if LPS25H_SHARED_I2C
+ i2cAcquireBus((devp)->config->i2cp);
+#endif /* LPS25H_SHARED_I2C */
+ i2cStart((devp)->config->i2cp,
+ (devp)->config->i2ccfg);
+
+ lps25hI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress, cr, 1);
+
+#if LPS25H_SHARED_I2C
+ i2cReleaseBus((devp)->config->i2cp);
+#endif /* LPS25H_SHARED_I2C */
+
+ /* Resolution configuration block.*/
+ {
+ cr[0] = LPS25H_AD_RES_CONF;
+ cr[1] = 0x05;
+#if LPS25H_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[1] = devp->config->baroresolution | devp->config->thermoresolution;
+#endif
+
+ }
+#if LPS25H_SHARED_I2C
+ i2cAcquireBus((devp)->config->i2cp);
+ i2cStart((devp)->config->i2cp,
+ (devp)->config->i2ccfg);
+#endif /* LPS25H_SHARED_I2C */
+
+ lps25hI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
+ cr, 1);
+
+#if LPS25H_SHARED_I2C
+ i2cReleaseBus((devp)->config->i2cp);
+#endif /* LPS25H_SHARED_I2C */
+
+ if(devp->config->barosensitivity == NULL) {
+ devp->barosensitivity = LPS25H_BARO_SENS;
+ }
+ else{
+ /* Taking barometer sensitivity from user configurations */
+ devp->barosensitivity = *(devp->config->barosensitivity);
+ }
+
+ if(devp->config->barobias == NULL) {
+ devp->barobias = LPS25H_BARO_BIAS;
+ }
+ else{
+ /* Taking barometer bias from user configurations */
+ devp->barobias = *(devp->config->barobias);
+ }
+
+ if(devp->config->thermosensitivity == NULL) {
+ devp->thermosensitivity = LPS25H_THERMO_SENS;
+ }
+ else{
+ /* Taking thermometer sensitivity from user configurations */
+ devp->thermosensitivity = *(devp->config->thermosensitivity);
+ }
+
+ if(devp->config->thermobias == NULL) {
+ devp->thermobias = LPS25H_THERMO_BIAS;
+ }
+ else{
+ /* Taking thermometer bias from user configurations */
+ devp->thermobias = *(devp->config->thermobias);
+ }
+
+ /* This is the Barometer transient recovery time */
+ osalThreadSleepMilliseconds(5);
+
+ devp->state = LPS25H_READY;
+}
+
+/**
+ * @brief Deactivates the LPS25H Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p LPS25HDriver object
+ *
+ * @api
+ */
+void lps25hStop(LPS25HDriver *devp) {
+ uint8_t cr[2];
+
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LPS25H_STOP) || (devp->state == LPS25H_READY),
+ "lps25hStop(), invalid state");
+
+ if (devp->state == LPS25H_READY) {
+#if LPS25H_SHARED_I2C
+ i2cAcquireBus((devp)->config->i2cp);
+ i2cStart((devp)->config->i2cp,
+ (devp)->config->i2ccfg);
+#endif /* LPS25H_SHARED_I2C */
+
+ cr[0] = LPS25H_AD_CTRL_REG1;
+ cr[1] = 0;
+ lps25hI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
+ cr, 1);
+
+ i2cStop((devp)->config->i2cp);
+#if LPS25H_SHARED_I2C
+ i2cReleaseBus((devp)->config->i2cp);
+#endif /* LPS25H_SHARED_I2C */
+ }
+ devp->state = LPS25H_STOP;
+}
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lps25h.h b/ChibiOS_20.3.2/os/ex/devices/ST/lps25h.h
new file mode 100644
index 0000000..3f3f022
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lps25h.h
@@ -0,0 +1,740 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file lps25h.h
+ * @brief LPS25H MEMS interface module header.
+ *
+ * @addtogroup LPS25H
+ * @ingroup EX_ST
+ * @{
+ */
+#ifndef _LPS25H_H_
+#define _LPS25H_H_
+
+#include "ex_barometer.h"
+#include "ex_thermometer.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Version identification
+ * @{
+ */
+/**
+ * @brief LPS25H driver version string.
+ */
+#define EX_LPS25H_VERSION "1.1.2"
+
+/**
+ * @brief LPS25H driver version major number.
+ */
+#define EX_LPS25H_MAJOR 1
+
+/**
+ * @brief LPS25H driver version minor number.
+ */
+#define EX_LPS25H_MINOR 1
+
+/**
+ * @brief LPS25H driver version patch number.
+ */
+#define EX_LPS25H_PATCH 2
+/** @} */
+
+/**
+ * @brief LPS25H barometer subsystem characteristics.
+ * @note Sensitivity is expressed as hPa/LSB whereas hPa stand for
+ * hectopascal.
+ * @note Bias is expressed as hPa.
+ *
+ * @{
+ */
+#define LPS25H_BARO_NUMBER_OF_AXES 1U
+
+#define LPS25H_BARO_SENS 0.00024414f
+#define LPS25H_BARO_BIAS 0.0f
+/** @} */
+
+/**
+ * @brief LPS25H thermometer subsystem characteristics.
+ * @note Sensitivity is expressed as �C/LSB.
+ * @note Bias is expressed as �C.
+ *
+ * @{
+ */
+#define LPS25H_THERMO_NUMBER_OF_AXES 1U
+
+#define LPS25H_THERMO_SENS 0.00208333f
+#define LPS25H_THERMO_BIAS -42.5f
+/** @} */
+
+/**
+ * @name LPS25H communication interfaces related bit masks
+ * @{
+ */
+#define LPS25H_DI_MASK 0xFF
+#define LPS25H_DI(n) (1 << n)
+#define LPS25H_AD_MASK 0x3F
+#define LPS25H_AD(n) (1 << n)
+#define LPS25H_MS (1 << 6)
+#define LPS25H_RW (1 << 7)
+
+#define LPS25H_SUB_MS (1 << 7)
+/** @} */
+
+/**
+ * @name LPS25H register addresses
+ * @{
+ */
+#define LPS25H_AD_REF_P_XL 0x08
+#define LPS25H_AD_REF_P_L 0x09
+#define LPS25H_AD_REF_P_H 0x0A
+#define LPS25H_AD_WHO_AM_I 0x0F
+#define LPS25H_AD_RES_CONF 0x10
+#define LPS25H_AD_CTRL_REG1 0x20
+#define LPS25H_AD_CTRL_REG2 0x21
+#define LPS25H_AD_CTRL_REG3 0x22
+#define LPS25H_AD_CTRL_REG4 0x23
+#define LPS25H_AD_INT_CFG 0x24
+#define LPS25H_AD_INT_SRC 0x25
+#define LPS25H_AD_STATUS_REG 0x27
+#define LPS25H_AD_PRESS_OUT_XL 0x28
+#define LPS25H_AD_PRESS_OUT_L 0x29
+#define LPS25H_AD_PRESS_OUT_H 0x2A
+#define LPS25H_AD_TEMP_OUT_L 0x2B
+#define LPS25H_AD_TEMP_OUT_H 0x2C
+#define LPS25H_AD_FIFO_CTRL 0x2E
+#define LPS25H_AD_FIFO_SRC 0x2F
+#define LPS25H_AD_THS_P_L 0x30
+#define LPS25H_AD_THS_P_H 0x31
+#define LPS25H_AD_RPDS_L 0x39
+#define LPS25H_AD_RPDS_H 0x3A
+/** @} */
+
+/**
+ * @name LPS25H_CTRL_REG1 register bits definitions
+ * @{
+ */
+#define LPS25H_CTRL_REG1_MASK 0xFF
+#define LPS25H_CTRL_REG1_SIM (1 << 0)
+#define LPS25H_CTRL_REG1_RESET_AZ (1 << 1)
+#define LPS25H_CTRL_REG1_BDU (1 << 2)
+#define LPS25H_CTRL_REG1_DIFF_EN (1 << 3)
+#define LPS25H_CTRL_REG1_ODR0 (1 << 4)
+#define LPS25H_CTRL_REG1_ODR1 (1 << 5)
+#define LPS25H_CTRL_REG1_ODR2 (1 << 6)
+#define LPS25H_CTRL_REG1_PD (1 << 7)
+/** @} */
+
+/**
+ * @name LPS25H_CTRL_REG2 register bits definitions
+ * @{
+ */
+#define LPS25H_CTRL_REG2_MASK 0xF3
+#define LPS25H_CTRL_REG2_ONE_SHOT (1 << 0)
+#define LPS25H_CTRL_REG2_AUTO_ZERO (1 << 1)
+#define LPS25H_CTRL_REG2_SWRESET (1 << 2)
+#define LPS25H_CTRL_REG2_FIFO_MEAN_DEC (1 << 4)
+#define LPS25H_CTRL_REG2_WTM_EN (1 << 5)
+#define LPS25H_CTRL_REG2_FIFO_EN (1 << 6)
+#define LPS25H_CTRL_REG2_BOOT (1 << 7)
+/** @} */
+
+/**
+ * @name LPS25H_CTRL_REG3 register bits definitions
+ * @{
+ */
+#define LPS25H_CTRL_REG3_MASK 0xC3
+#define LPS25H_CTRL_REG3_INT_S1 (1 << 0)
+#define LPS25H_CTRL_REG3_INT_S2 (1 << 1)
+#define LPS25H_CTRL_REG3_PP_OD (1 << 6)
+#define LPS25H_CTRL_REG3_INT_H_L (1 << 7)
+/** @} */
+
+/**
+ * @name LPS25H_CTRL_REG4 register bits definitions
+ * @{
+ */
+#define LPS25H_CTRL_REG4_MASK 0x0F
+#define LPS25H_CTRL_REG4_P1_DRDY (1 << 0)
+#define LPS25H_CTRL_REG4_P1_OVERRUN (1 << 1)
+#define LPS25H_CTRL_REG4_P1_WTM (1 << 2)
+#define LPS25H_CTRL_REG4_P1_EMPTY (1 << 3)
+/** @} */
+
+/**
+ * @name LPS25H_INT1_CFG register bits definitions
+ * @{
+ */
+#define LPS25H_INT1_CFG_MASK 0x07
+#define LPS25H_INT1_CFG_PH_E (1 << 0)
+#define LPS25H_INT1_CFG_PL_E (1 << 1)
+#define LPS25H_INT1_CFG_LIR (1 << 2)
+/** @} */
+
+/**
+ * @name LPS25H_INT1_SRC register bits definitions
+ * @{
+ */
+#define LPS25H_INT1_SRC_MASK 0x07
+#define LPS25H_INT1_SRC_PH (1 << 0)
+#define LPS25H_INT1_SRC_PL (1 << 1)
+#define LPS25H_INT1_SRC_IA (1 << 2)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief LPS25H SPI interface switch.
+ * @details If set to @p TRUE the support for SPI is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(LPS25H_USE_SPI) || defined(__DOXYGEN__)
+#define LPS25H_USE_SPI FALSE
+#endif
+
+/**
+ * @brief LPS25H shared SPI switch.
+ * @details If set to @p TRUE the device acquires SPI bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(LPS25H_SHARED_SPI) || defined(__DOXYGEN__)
+#define LPS25H_SHARED_SPI FALSE
+#endif
+
+/**
+ * @brief LPS25H I2C interface switch.
+ * @details If set to @p TRUE the support for I2C is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(LPS25H_USE_I2C) || defined(__DOXYGEN__)
+#define LPS25H_USE_I2C TRUE
+#endif
+
+/**
+ * @brief LPS25H shared I2C switch.
+ * @details If set to @p TRUE the device acquires I2C bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(LPS25H_SHARED_I2C) || defined(__DOXYGEN__)
+#define LPS25H_SHARED_I2C FALSE
+#endif
+
+/**
+ * @brief LPS25H advanced configurations switch.
+ * @details If set to @p TRUE more configurations are available.
+ * @note The default is @p FALSE.
+ */
+#if !defined(LPS25H_USE_ADVANCED) || defined(__DOXYGEN__)
+#define LPS25H_USE_ADVANCED FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !(LPS25H_USE_SPI ^ LPS25H_USE_I2C)
+#error "LPS25H_USE_SPI and LPS25H_USE_I2C cannot be both true or both false"
+#endif
+
+#if LPS25H_USE_SPI && !HAL_USE_SPI
+#error "LPS25H_USE_SPI requires HAL_USE_SPI"
+#endif
+
+#if LPS25H_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION
+#error "LPS25H_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
+#endif
+
+#if LPS25H_USE_I2C && !HAL_USE_I2C
+#error "LPS25H_USE_I2C requires HAL_USE_I2C"
+#endif
+
+#if LPS25H_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
+#error "LPS25H_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
+#endif
+
+/*
+ * CHTODO: Add support for LPS25H over SPI.
+ */
+#if LPS25H_USE_SPI
+#error "LPS25H over SPI still not supported"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @name LPS25H data structures and types.
+ * @{
+ */
+/**
+ * @brief Structure representing a LPS25H driver.
+ */
+typedef struct LPS25HDriver LPS25HDriver;
+
+/**
+ * @brief LPS25H slave address
+ */
+typedef enum {
+ LPS25H_SAD_GND = 0x5C, /**< Slave Address when SA0 is to GND */
+ LPS25H_SAD_VCC = 0x5D /**< Slave Address when SA0 is to VCC */
+}lps25h_sad_t;
+
+/**
+ * @brief LPS25H output data rate and bandwidth.
+ */
+typedef enum {
+ LPS25H_ODR_ONE_SHOT = 0x00, /**< One shot. */
+ LPS25H_ODR_1HZ = 0x10, /**< Output data rate 1 Hz. */
+ LPS25H_ODR_7HZ = 0x20, /**< Output data rate 7 Hz. */
+ LPS25H_ODR_12P5HZ = 0x30, /**< Output data rate 12.5 Hz. */
+ LPS25H_ODR_25HZ = 0x40 /**< Output data rate 25 Hz. */
+}lps25h_odr_t;
+
+/**
+ * @brief LPS25H pressure resolution.
+ */
+typedef enum {
+ LPS25H_AVGP_8 = 0x00, /**< Number of internal average is 8. */
+ LPS25H_AVGP_32 = 0x01, /**< Number of internal average is 32. */
+ LPS25H_AVGP_128 = 0x02, /**< Number of internal average is 128. */
+ LPS25H_AVGP_512 = 0x03, /**< Number of internal average is 512. */
+}lps25h_avgp_t;
+
+/**
+ * @brief LPS25H temperature resolution.
+ */
+typedef enum {
+ LPS25H_AVGT_8 = 0x00, /**< Number of internal average is 8. */
+ LPS25H_AVGT_32 = 0x04, /**< Number of internal average is 32. */
+ LPS25H_AVGT_128 = 0x08, /**< Number of internal average is 128. */
+ LPS25H_AVGT_512 = 0x0C, /**< Number of internal average is 512. */
+}lps25h_avgt_t;
+
+/**
+ * @brief LPS25H block data update.
+ */
+typedef enum {
+ LPS25H_BDU_CONTINUOUS = 0x00, /**< Block data continuously updated. */
+ LPS25H_BDU_BLOCKED = 0x40 /**< Block data updated after reading. */
+}lps25h_bdu_t;
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ LPS25H_UNINIT = 0, /**< Not initialized. */
+ LPS25H_STOP = 1, /**< Stopped. */
+ LPS25H_READY = 2, /**< Ready. */
+} lps25h_state_t;
+
+/**
+ * @brief LPS25H configuration structure.
+ */
+typedef struct {
+
+#if LPS25H_USE_SPI || defined(__DOXYGEN__)
+ /**
+ * @brief SPI driver associated to this LPS25H.
+ */
+ SPIDriver *spip;
+ /**
+ * @brief SPI configuration associated to this LPS25H.
+ */
+ const SPIConfig *spicfg;
+#endif /* LPS25H_USE_SPI */
+#if LPS25H_USE_I2C || defined(__DOXYGEN__)
+ /**
+ * @brief I2C driver associated to this LPS25H.
+ */
+ I2CDriver *i2cp;
+ /**
+ * @brief I2C configuration associated to this LPS25H.
+ */
+ const I2CConfig *i2ccfg;
+ /**
+ * @brief LPS25H slave address
+ */
+ lps25h_sad_t slaveaddress;
+#endif /* LPS25H_USE_I2C */
+ /**
+ * @brief LPS25H barometer subsystem initial sensitivity.
+ */
+ float *barosensitivity;
+ /**
+ * @brief LPS25H barometer subsystem initial bias.
+ */
+ float *barobias;
+ /**
+ * @brief LPS25H thermometer subsystem initial sensitivity.
+ */
+ float *thermosensitivity;
+ /**
+ * @brief LPS25H thermometer subsystem initial bias.
+ */
+ float *thermobias;
+ /**
+ * @brief LPS25H output data rate selection.
+ */
+ lps25h_odr_t outputdatarate;
+#if LPS25H_USE_ADVANCED || defined(__DOXYGEN__)
+ /**
+ * @brief LPS25H block data update.
+ */
+ lps25h_bdu_t blockdataupdate;
+ /**
+ * @brief LPS25H barometer subsystem resolution.
+ */
+ lps25h_avgp_t baroresolution;
+ /**
+ * @brief LPS25H thermometer subsystem resolution.
+ */
+ lps25h_avgt_t thermoresolution;
+#endif
+} LPS25HConfig;
+
+/**
+ * @brief @p LPS25H specific methods.
+ * @note No methods so far, just a common ancestor interface.
+ */
+#define _lps25h_methods_alone
+
+/**
+ * @brief @p LPS25H specific methods with inherited ones.
+ */
+#define _lps25h_methods \
+ _base_object_methods \
+ _lps25h_methods_alone
+
+/**
+ * @extends BaseObjectVMT
+ *
+ * @brief @p LPS25H virtual methods table.
+ */
+struct LPS25HVMT {
+ _lps25h_methods
+};
+
+/**
+ * @brief @p LPS25HDriver specific data.
+ */
+#define _lps25h_data \
+ /* Driver state.*/ \
+ lps25h_state_t state; \
+ /* Current configuration data.*/ \
+ const LPS25HConfig *config; \
+ /* Barometer subsystem axes number.*/ \
+ size_t baroaxes; \
+ /* Barometer subsystem current sensitivity.*/ \
+ float barosensitivity; \
+ /* Barometer subsystem current bias .*/ \
+ float barobias; \
+ /* Thermometer subsystem axes number.*/ \
+ size_t thermoaxes; \
+ /* Thermometer subsystem current sensitivity.*/ \
+ float thermosensitivity; \
+ /* Thermometer subsystem current bias.*/ \
+ float thermobias;
+
+/**
+ * @brief LPS25H 2-axis barometer/thermometer class.
+ */
+struct LPS25HDriver {
+ /** @brief Virtual Methods Table.*/
+ const struct LPS25HVMT *vmt;
+ /** @brief Base barometer interface.*/
+ BaseBarometer baro_if;
+ /** @brief Base thermometer interface.*/
+ BaseThermometer thermo_if;
+ _lps25h_data
+};
+/** @} */
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Return the number of axes of the BaseBarometer.
+ *
+ * @param[in] devp pointer to @p LPS25HDriver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define lps25hBarometerGetAxesNumber(devp) \
+ barometerGetAxesNumber(&((devp)->baro_if))
+
+/**
+ * @brief Retrieves raw data from the BaseBarometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseBarometer axes number.
+ *
+ * @param[in] devp pointer to @p LPS25HDriver.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lps25hBarometerReadRaw(devp, axes) \
+ barometerReadRaw(&((devp)->baro_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseBarometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as hPa.
+ * @note The axes array must be at least the same size of the
+ * BaseBarometer axes number.
+ *
+ * @param[in] devp pointer to @p LPS25HDriver.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lps25hBarometerReadCooked(devp, axes) \
+ barometerReadCooked(&((devp)->baro_if), axes)
+
+/**
+ * @brief Set bias values for the BaseBarometer.
+ * @note Bias must be expressed as hPa.
+ * @note The bias buffer must be at least the same size of the
+ * BaseBarometer axes number.
+ *
+ * @param[in] devp pointer to @p LPS25HDriver.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lps25hBarometerSetBias(devp, bp) \
+ barometerSetBias(&((devp)->baro_if), bp)
+
+/**
+ * @brief Reset bias values for the BaseBarometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] devp pointer to @p LPS25HDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lps25hBarometerResetBias(devp) \
+ barometerResetBias(&((devp)->baro_if))
+
+/**
+ * @brief Set sensitivity values for the BaseBarometer.
+ * @note Sensitivity must be expressed as hPa/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseBarometer axes number.
+ *
+ * @param[in] devp pointer to @p LPS25HDriver.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lps25hBarometerSetSensitivity(devp, sp) \
+ barometerSetSensitivity(&((devp)->baro_if), sp)
+
+/**
+ * @brief Reset sensitivity values for the BaseBarometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] devp pointer to @p LPS25HDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lps25hBarometerResetSensitivity(devp) \
+ barometerResetSensitivity(&((devp)->baro_if))
+
+/**
+ * @brief Return the number of axes of the BaseThermometer.
+ *
+ * @param[in] devp pointer to @p LPS25HDriver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define lps25hThermometerGetAxesNumber(devp) \
+ thermometerGetAxesNumber(&((devp)->thermo_if))
+
+/**
+ * @brief Retrieves raw data from the BaseThermometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] devp pointer to @p LPS25HDriver.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lps25hThermometerReadRaw(devp, axes) \
+ thermometerReadRaw(&((devp)->thermo_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseThermometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as °C.
+ * @note The axes array must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] devp pointer to @p LPS25HDriver.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lps25hThermometerReadCooked(devp, axes) \
+ thermometerReadCooked(&((devp)->thermo_if), axes)
+
+/**
+ * @brief Set bias values for the BaseThermometer.
+ * @note Bias must be expressed as °C.
+ * @note The bias buffer must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] devp pointer to @p LPS25HDriver.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lps25hThermometerSetBias(devp, bp) \
+ thermometerSetBias(&((devp)->thermo_if), bp)
+
+/**
+ * @brief Reset bias values for the BaseThermometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] devp pointer to @p LPS25HDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lps25hThermometerResetBias(devp) \
+ thermometerResetBias(&((devp)->thermo_if))
+
+/**
+ * @brief Set sensitivity values for the BaseThermometer.
+ * @note Sensitivity must be expressed as °C/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseThermometer axes number.
+ *
+ * @param[in] devp pointer to @p LPS25HDriver.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lps25hThermometerSetSensitivity(devp, sp) \
+ thermometerSetSensitivity(&((devp)->thermo_if), sp)
+
+/**
+ * @brief Reset sensitivity values for the BaseThermometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] devp pointer to @p LPS25HDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lps25hThermometerResetSensitivity(devp) \
+ thermometerResetSensitivity(&((devp)->thermo_if))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void lps25hObjectInit(LPS25HDriver *devp);
+ void lps25hStart(LPS25HDriver *devp, const LPS25HConfig *config);
+ void lps25hStop(LPS25HDriver *devp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LPS25H_H_ */
+
+/** @} */
+
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lps25h.mk b/ChibiOS_20.3.2/os/ex/devices/ST/lps25h.mk
new file mode 100644
index 0000000..2cdaf78
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lps25h.mk
@@ -0,0 +1,10 @@
+# List of all the LPS25H device files.
+LPS25HSRC := $(CHIBIOS)/os/ex/devices/ST/lps25h.c
+
+# Required include directories
+LPS25HINC := $(CHIBIOS)/os/ex/include \
+ $(CHIBIOS)/os/ex/devices/ST
+
+# Shared variables
+ALLCSRC += $(LPS25HSRC)
+ALLINC += $(LPS25HINC)
\ No newline at end of file
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lsm303agr.c b/ChibiOS_20.3.2/os/ex/devices/ST/lsm303agr.c
new file mode 100644
index 0000000..6a4c3cd
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lsm303agr.c
@@ -0,0 +1,906 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file lsm303agr.c
+ * @brief LSM303AGR MEMS interface module code.
+ *
+ * @addtogroup LSM303AGR
+ * @ingroup EX_ST
+ * @{
+ */
+
+#include "hal.h"
+#include "lsm303agr.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Accelerometer and Compass Slave Address.
+ */
+typedef enum {
+ LSM303AGR_SAD_ACC = 0x19, /**< SAD for accelerometer. */
+ LSM303AGR_SAD_COMP = 0x1E /**< SAD for compass. */
+} lsm303agr_sad_t;
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Reads registers value using I2C.
+ * @pre The I2C interface must be initialized and the driver started.
+ * @note IF_ADD_INC bit must be 1 in CTRL_REG8.
+ *
+ * @param[in] i2cp pointer to the I2C interface.
+ * @param[in] sad slave address without R bit.
+ * @param[in] reg first sub-register address.
+ * @param[in] rxbuf receiving buffer.
+ * @param[in] n size of rxbuf.
+ * @return the operation status.
+ */
+static msg_t lsm303agrI2CReadRegister(I2CDriver *i2cp, lsm303agr_sad_t sad,
+ uint8_t reg, uint8_t *rxbuf, size_t n) {
+
+ uint8_t txbuf = reg | LSM303AGR_MS;
+ return i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, n,
+ TIME_INFINITE);
+}
+
+/**
+ * @brief Writes a value into a register using I2C.
+ * @pre The I2C interface must be initialized and the driver started.
+ *
+ * @param[in] i2cp pointer to the I2C interface.
+ * @param[in] sad slave address without R bit.
+ * @param[in] txbuf buffer containing sub-address value in first position
+ * and values to write.
+ * @param[in] n size of txbuf less one (not considering the first
+ * element).
+ * @return the operation status.
+ */
+static msg_t lsm303agrI2CWriteRegister(I2CDriver *i2cp, lsm303agr_sad_t sad,
+ uint8_t *txbuf, size_t n) {
+ if (n != 1)
+ *txbuf |= LSM303AGR_MS;
+ return i2cMasterTransmitTimeout(i2cp, sad, txbuf, n + 1, NULL, 0,
+ TIME_INFINITE);
+}
+
+/**
+ * @brief Return the number of axes of the BaseAccelerometer.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ *
+ * @return the number of axes.
+ */
+static size_t acc_get_axes_number(void *ip) {
+ (void)ip;
+
+ return LSM303AGR_ACC_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Retrieves raw data from the BaseAccelerometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t acc_read_raw(void *ip, int32_t axes[]) {
+ LSM303AGRDriver* devp;
+ uint8_t buff [LSM303AGR_ACC_NUMBER_OF_AXES * 2], i;
+ int16_t tmp;
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303AGRDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM303AGR_READY),
+ "acc_read_raw(), invalid state");
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "acc_read_raw(), channel not ready");
+
+#if LSM303AGR_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LSM303AGR_SHARED_I2C */
+
+ msg = lsm303agrI2CReadRegister(devp->config->i2cp, LSM303AGR_SAD_ACC,
+ LSM303AGR_AD_OUT_X_L_A, buff,
+ LSM303AGR_ACC_NUMBER_OF_AXES * 2);
+
+#if LSM303AGR_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM303AGR_SHARED_I2C */
+
+ if(msg == MSG_OK)
+ for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
+ tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
+ axes[i] = (int32_t)tmp;
+ }
+ return msg;
+}
+
+/**
+ * @brief Retrieves cooked data from the BaseAccelerometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as milli-G.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t acc_read_cooked(void *ip, float axes[]) {
+ LSM303AGRDriver* devp;
+ uint32_t i;
+ int32_t raw[LSM303AGR_ACC_NUMBER_OF_AXES];
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303AGRDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM303AGR_READY),
+ "acc_read_cooked(), invalid state");
+
+ msg = acc_read_raw(ip, raw);
+ for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
+ axes[i] = (raw[i] * devp->accsensitivity[i]) - devp->accbias[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Set bias values for the BaseAccelerometer.
+ * @note Bias must be expressed as milli-G.
+ * @note The bias buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t acc_set_bias(void *ip, float *bp) {
+ LSM303AGRDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (bp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303AGRDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM303AGR_READY),
+ "acc_set_bias(), invalid state");
+
+ for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
+ devp->accbias[i] = bp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset bias values for the BaseAccelerometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t acc_reset_bias(void *ip) {
+ LSM303AGRDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303AGRDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM303AGR_READY),
+ "acc_reset_bias(), invalid state");
+
+ for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++)
+ devp->accbias[i] = LSM303AGR_ACC_BIAS;
+ return msg;
+}
+
+/**
+ * @brief Set sensitivity values for the BaseAccelerometer.
+ * @note Sensitivity must be expressed as milli-G/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t acc_set_sensivity(void *ip, float *sp) {
+ LSM303AGRDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303AGRDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgCheck((ip != NULL) && (sp != NULL));
+
+ osalDbgAssert((devp->state == LSM303AGR_READY),
+ "acc_set_sensivity(), invalid state");
+
+ for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
+ devp->accsensitivity[i] = sp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset sensitivity values for the BaseAccelerometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t acc_reset_sensivity(void *ip) {
+ LSM303AGRDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303AGRDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM303AGR_READY),
+ "acc_reset_sensivity(), invalid state");
+
+ if(devp->config->accfullscale == LSM303AGR_ACC_FS_2G) {
+ for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
+ devp->accsensitivity[i] = LSM303AGR_ACC_SENS_2G;
+ }
+ }
+ else if(devp->config->accfullscale == LSM303AGR_ACC_FS_4G) {
+ for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
+ devp->accsensitivity[i] = LSM303AGR_ACC_SENS_4G;
+ }
+ }
+ else if(devp->config->accfullscale == LSM303AGR_ACC_FS_8G) {
+ for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
+ devp->accsensitivity[i] = LSM303AGR_ACC_SENS_8G;
+ }
+ }
+ else if(devp->config->accfullscale == LSM303AGR_ACC_FS_16G) {
+ for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
+ devp->accsensitivity[i] = LSM303AGR_ACC_SENS_16G;
+ }
+ }
+ else {
+ osalDbgAssert(FALSE, "reset_sensivity(), accelerometer full scale issue");
+ msg = MSG_RESET;
+ }
+ return msg;
+}
+
+/**
+ * @brief Changes the LSM303AGRDriver accelerometer fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p LSM303AGRDriver interface.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t acc_set_full_scale(LSM303AGRDriver *devp,
+ lsm303agr_acc_fs_t fs) {
+ float newfs, scale;
+ uint8_t i, buff[2];
+ msg_t msg;
+
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LSM303AGR_READY),
+ "acc_set_full_scale(), invalid state");
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "acc_set_full_scale(), channel not ready");
+
+ /* Computing new fullscale value.*/
+ if(fs == LSM303AGR_ACC_FS_2G) {
+ newfs = LSM303AGR_ACC_2G;
+ }
+ else if(fs == LSM303AGR_ACC_FS_4G) {
+ newfs = LSM303AGR_ACC_4G;
+ }
+ else if(fs == LSM303AGR_ACC_FS_8G) {
+ newfs = LSM303AGR_ACC_8G;
+ }
+ else if(fs == LSM303AGR_ACC_FS_16G) {
+ newfs = LSM303AGR_ACC_16G;
+ }
+ else {
+ msg = MSG_RESET;
+ return msg;
+ }
+
+ if(newfs != devp->accfullscale) {
+ /* Computing scale value.*/
+ scale = newfs / devp->accfullscale;
+ devp->accfullscale = newfs;
+
+#if LSM303AGR_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LSM303AGR_SHARED_I2C */
+
+ /* Updating register.*/
+ msg = lsm303agrI2CReadRegister(devp->config->i2cp,
+ LSM303AGR_SAD_ACC,
+ LSM303AGR_AD_CTRL_REG4_A,
+ &buff[1], 1);
+
+#if LSM303AGR_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM303AGR_SHARED_I2C */
+
+ if(msg != MSG_OK)
+ return msg;
+
+ buff[1] &= ~(LSM303AGR_CTRL_REG4_A_FS_MASK);
+ buff[1] |= fs;
+ buff[0] = LSM303AGR_AD_CTRL_REG4_A;
+
+#if LSM303AGR_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+#endif /* LSM303AGR_SHARED_I2C */
+
+ msg = lsm303agrI2CWriteRegister(devp->config->i2cp,
+ LSM303AGR_SAD_ACC, buff, 1);
+
+#if LSM303AGR_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM303AGR_SHARED_I2C */
+
+ if(msg != MSG_OK)
+ return msg;
+
+ /* Scaling sensitivity and bias. Re-calibration is suggested anyway.*/
+ for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
+ devp->accsensitivity[i] *= scale;
+ devp->accbias[i] *= scale;
+ }
+ }
+ return msg;
+}
+
+/**
+ * @brief Return the number of axes of the BaseCompass.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface
+ *
+ * @return the number of axes.
+ */
+static size_t comp_get_axes_number(void *ip) {
+
+ osalDbgCheck(ip != NULL);
+ return LSM303AGR_COMP_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Retrieves raw data from the BaseCompass.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t comp_read_raw(void *ip, int32_t axes[]) {
+ LSM303AGRDriver* devp;
+ uint8_t buff [LSM303AGR_COMP_NUMBER_OF_AXES * 2], i;
+ int16_t tmp;
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303AGRDriver*, (BaseCompass*)ip);
+
+ osalDbgAssert((devp->state == LSM303AGR_READY),
+ "comp_read_raw(), invalid state");
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "comp_read_raw(), channel not ready");
+
+#if LSM303AGR_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LSM303AGR_SHARED_I2C */
+ msg = lsm303agrI2CReadRegister(devp->config->i2cp, LSM303AGR_SAD_COMP,
+ LSM303AGR_AD_OUTX_L_REG_M, buff,
+ LSM303AGR_COMP_NUMBER_OF_AXES * 2);
+
+#if LSM303AGR_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM303AGR_SHARED_I2C */
+
+ if(msg == MSG_OK)
+ for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES; i++) {
+ tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
+ axes[i] = (int32_t)tmp;
+ }
+ return msg;
+}
+
+/**
+ * @brief Retrieves cooked data from the BaseCompass.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as G.
+ * @note The axes array must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t comp_read_cooked(void *ip, float axes[]) {
+ LSM303AGRDriver* devp;
+ uint32_t i;
+ int32_t raw[LSM303AGR_COMP_NUMBER_OF_AXES];
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303AGRDriver*, (BaseCompass*)ip);
+
+ osalDbgAssert((devp->state == LSM303AGR_READY),
+ "comp_read_cooked(), invalid state");
+
+ msg = comp_read_raw(ip, raw);
+ for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES ; i++) {
+ axes[i] = (raw[i] * devp->compsensitivity[i]) - devp->compbias[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Set bias values for the BaseCompass.
+ * @note Bias must be expressed as G.
+ * @note The bias buffer must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t comp_set_bias(void *ip, float *bp) {
+ LSM303AGRDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (bp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303AGRDriver*, (BaseCompass*)ip);
+
+ osalDbgAssert((devp->state == LSM303AGR_READY),
+ "comp_set_bias(), invalid state");
+
+ for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES; i++) {
+ devp->compbias[i] = bp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset bias values for the BaseCompass.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t comp_reset_bias(void *ip) {
+ LSM303AGRDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303AGRDriver*, (BaseCompass*)ip);
+
+ osalDbgAssert((devp->state == LSM303AGR_READY),
+ "comp_reset_bias(), invalid state");
+
+ for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES; i++)
+ devp->compbias[i] = LSM303AGR_COMP_BIAS;
+ return msg;
+}
+
+/**
+ * @brief Set sensitivity values for the BaseCompass.
+ * @note Sensitivity must be expressed as G/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t comp_set_sensivity(void *ip, float *sp) {
+ LSM303AGRDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303AGRDriver*, (BaseCompass*)ip);
+
+ osalDbgCheck((ip != NULL) && (sp != NULL));
+
+ osalDbgAssert((devp->state == LSM303AGR_READY),
+ "comp_set_sensivity(), invalid state");
+
+ for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES; i++) {
+ devp->compsensitivity[i] = sp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset sensitivity values for the BaseCompass.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t comp_reset_sensivity(void *ip) {
+ LSM303AGRDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303AGRDriver*, (BaseCompass*)ip);
+
+ osalDbgAssert((devp->state == LSM303AGR_READY),
+ "comp_reset_sensivity(), invalid state");
+
+ for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES; i++)
+ devp->compsensitivity[i] = LSM303AGR_COMP_SENS_50GA;
+
+ return msg;
+}
+
+static const struct LSM303AGRVMT vmt_device = {
+ (size_t)0,
+ acc_set_full_scale
+};
+
+static const struct BaseAccelerometerVMT vmt_accelerometer = {
+ sizeof(struct LSM303AGRVMT*),
+ acc_get_axes_number, acc_read_raw, acc_read_cooked,
+ acc_set_bias, acc_reset_bias, acc_set_sensivity, acc_reset_sensivity
+};
+
+static const struct BaseCompassVMT vmt_compass = {
+ sizeof(struct LSM303AGRVMT*) + sizeof(BaseAccelerometer),
+ comp_get_axes_number, comp_read_raw, comp_read_cooked,
+ comp_set_bias, comp_reset_bias, comp_set_sensivity, comp_reset_sensivity
+};
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes an instance.
+ *
+ * @param[out] devp pointer to the @p LSM303AGRDriver object
+ *
+ * @init
+ */
+void lsm303agrObjectInit(LSM303AGRDriver *devp) {
+ devp->vmt = &vmt_device;
+ devp->acc_if.vmt = &vmt_accelerometer;
+ devp->comp_if.vmt = &vmt_compass;
+
+ devp->config = NULL;
+
+ devp->accaxes = LSM303AGR_ACC_NUMBER_OF_AXES;
+ devp->compaxes = LSM303AGR_COMP_NUMBER_OF_AXES;
+
+ devp->state = LSM303AGR_STOP;
+}
+
+/**
+ * @brief Configures and activates LSM303AGR Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p LSM303AGRDriver object
+ * @param[in] config pointer to the @p LSM303AGRConfig object
+ *
+ * @api
+ */
+void lsm303agrStart(LSM303AGRDriver *devp, const LSM303AGRConfig *config) {
+ uint32_t i;
+ uint8_t cr[6];
+ osalDbgCheck((devp != NULL) && (config != NULL));
+
+ osalDbgAssert((devp->state == LSM303AGR_STOP) ||
+ (devp->state == LSM303AGR_READY),
+ "lsm303agrStart(), invalid state");
+
+ devp->config = config;
+
+ /* Configuring Accelerometer subsystem.*/
+
+ /* Multiple write starting address.*/
+ cr[0] = LSM303AGR_AD_CTRL_REG1_A;
+
+ /* Control register 1 configuration block.*/
+ {
+ cr[1] = LSM303AGR_ACC_AE_XYZ | devp->config->accoutdatarate;
+#if LSM303AGR_USE_ADVANCED || defined(__DOXYGEN__)
+ if(devp->config->accmode == LSM303AGR_ACC_MODE_LPOW)
+ cr[1] |= LSM303AGR_CTRL_REG1_A_LPEN;
+#endif
+ }
+
+ /* Control register 2 configuration block.*/
+ {
+ cr[2] = 0;
+ }
+
+ /* Control register 3 configuration block.*/
+ {
+ cr[3] = 0;
+ }
+
+ /* Control register 4 configuration block.*/
+ {
+ cr[4] = devp->config->accfullscale;
+#if LSM303AGR_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[4] |= devp->config->accendianess |
+ devp->config->accblockdataupdate;
+ if(devp->config->accmode == LSM303AGR_ACC_MODE_HRES)
+ cr[4] |= LSM303AGR_CTRL_REG4_A_HR;
+#endif
+ }
+
+ /* Storing sensitivity according to user settings */
+ if(devp->config->accfullscale == LSM303AGR_ACC_FS_2G) {
+ devp->accfullscale = LSM303AGR_ACC_2G;
+ for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
+ if(devp->config->accsensitivity == NULL)
+ devp->accsensitivity[i] = LSM303AGR_ACC_SENS_2G;
+ else
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ }
+ else if(devp->config->accfullscale == LSM303AGR_ACC_FS_4G) {
+ devp->accfullscale = LSM303AGR_ACC_4G;
+ for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
+ if(devp->config->accsensitivity == NULL)
+ devp->accsensitivity[i] = LSM303AGR_ACC_SENS_4G;
+ else
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ }
+ else if(devp->config->accfullscale == LSM303AGR_ACC_FS_8G) {
+ devp->accfullscale = LSM303AGR_ACC_8G;
+ for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
+ if(devp->config->accsensitivity == NULL)
+ devp->accsensitivity[i] = LSM303AGR_ACC_SENS_8G;
+ else
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ }
+ else if(devp->config->accfullscale == LSM303AGR_ACC_FS_16G) {
+ devp->accfullscale = LSM303AGR_ACC_16G;
+ for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++) {
+ if(devp->config->accsensitivity == NULL)
+ devp->accsensitivity[i] = LSM303AGR_ACC_SENS_16G;
+ else
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ }
+ else
+ osalDbgAssert(FALSE, "lsm303dlhcStart(), accelerometer full scale issue");
+
+ /* Storing bias information */
+ if(devp->config->accbias != NULL)
+ for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++)
+ devp->accbias[i] = devp->config->accbias[i];
+ else
+ for(i = 0; i < LSM303AGR_ACC_NUMBER_OF_AXES; i++)
+ devp->accbias[i] = LSM303AGR_ACC_BIAS;
+
+#if LSM303AGR_SHARED_I2C
+ i2cAcquireBus((devp)->config->i2cp);
+#endif /* LSM303AGR_SHARED_I2C */
+ i2cStart((devp)->config->i2cp, (devp)->config->i2ccfg);
+
+ lsm303agrI2CWriteRegister(devp->config->i2cp, LSM303AGR_SAD_ACC, cr, 4);
+
+#if LSM303AGR_SHARED_I2C
+ i2cReleaseBus((devp)->config->i2cp);
+#endif /* LSM303AGR_SHARED_I2C */
+
+ /* Configuring Compass subsystem */
+ /* Multiple write starting address.*/
+ cr[0] = LSM303AGR_AD_CFG_REG_A_M;
+
+ /* Control register A configuration block.*/
+ {
+ cr[1] = devp->config->compoutputdatarate;
+#if LSM303AGR_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[1] |= devp->config->compmode | devp->config->complp;
+#endif
+ }
+
+ /* Control register B configuration block.*/
+ {
+ cr[2] = 0;
+ }
+
+ /* Control register C configuration block.*/
+ {
+ cr[3] = 0;
+ }
+
+#if LSM303AGR_SHARED_I2C
+ i2cAcquireBus((devp)->config->i2cp);
+ i2cStart((devp)->config->i2cp, (devp)->config->i2ccfg);
+#endif /* LSM303AGR_SHARED_I2C */
+
+ lsm303agrI2CWriteRegister(devp->config->i2cp, LSM303AGR_SAD_COMP,
+ cr, 3);
+
+#if LSM303AGR_SHARED_I2C
+ i2cReleaseBus((devp)->config->i2cp);
+#endif /* LSM303AGR_SHARED_I2C */
+
+ devp->compfullscale = LSM303AGR_COMP_50GA;
+ for(i = 0; i < LSM303AGR_COMP_NUMBER_OF_AXES; i++) {
+ if(devp->config->compsensitivity == NULL) {
+ devp->compsensitivity[i] = LSM303AGR_COMP_SENS_50GA;
+ }
+ else {
+ devp->compsensitivity[i] = devp->config->compsensitivity[i];
+ }
+ }
+
+ /* This is the MEMS transient recovery time */
+ osalThreadSleepMilliseconds(5);
+
+ devp->state = LSM303AGR_READY;
+}
+
+/**
+ * @brief Deactivates the LSM303AGR Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p LSM303AGRDriver object
+ *
+ * @api
+ */
+void lsm303agrStop(LSM303AGRDriver *devp) {
+ uint8_t cr[2];
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LSM303AGR_STOP) ||
+ (devp->state == LSM303AGR_READY),
+ "lsm303agrStop(), invalid state");
+
+ if (devp->state == LSM303AGR_READY) {
+#if LSM303AGR_SHARED_I2C
+ i2cAcquireBus((devp)->config->i2cp);
+ i2cStart((devp)->config->i2cp, (devp)->config->i2ccfg);
+#endif /* LSM303AGR_SHARED_I2C */
+
+ /* Disabling accelerometer. */
+ cr[0] = LSM303AGR_AD_CTRL_REG1_A;
+ cr[1] = LSM303AGR_ACC_AE_DISABLED | LSM303AGR_ACC_ODR_PD;
+ lsm303agrI2CWriteRegister(devp->config->i2cp, LSM303AGR_SAD_ACC,
+ cr, 1);
+
+ /* Disabling compass. */
+ cr[0] = LSM303AGR_AD_CFG_REG_A_M;
+ cr[1] = LSM303AGR_COMP_MODE_IDLE;
+ lsm303agrI2CWriteRegister(devp->config->i2cp, LSM303AGR_SAD_COMP,
+ cr, 1);
+
+ i2cStop((devp)->config->i2cp);
+#if LSM303AGR_SHARED_I2C
+ i2cReleaseBus((devp)->config->i2cp);
+#endif /* LSM303AGR_SHARED_I2C */
+ }
+ devp->state = LSM303AGR_STOP;
+}
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lsm303agr.h b/ChibiOS_20.3.2/os/ex/devices/ST/lsm303agr.h
new file mode 100644
index 0000000..887e115
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lsm303agr.h
@@ -0,0 +1,919 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file lsm303agr.h
+ * @brief LSM303AGR MEMS interface module header.
+ *
+ * @addtogroup LSM303AGR
+ * @ingroup EX_ST
+ * @{
+ */
+#ifndef _LSM303AGR_H_
+#define _LSM303AGR_H_
+
+#include "ex_accelerometer.h"
+#include "ex_compass.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Version identification
+ * @{
+ */
+/**
+ * @brief LSM303AGR driver version string.
+ */
+#define EX_LSM303AGR_VERSION "1.0.1"
+
+/**
+ * @brief LSM303AGR driver version major number.
+ */
+#define EX_LSM303AGR_MAJOR 1
+
+/**
+ * @brief LSM303AGR driver version minor number.
+ */
+#define EX_LSM303AGR_MINOR 0
+
+/**
+ * @brief LSM303AGR driver version patch number.
+ */
+#define EX_LSM303AGR_PATCH 1
+/** @} */
+
+/**
+ * @brief LSM303AGR accelerometer subsystem characteristics.
+ * @note Sensitivity is expressed as milli-G/LSB whereas
+ * 1 milli-G = 0.00980665 m/s^2.
+ * @note Bias is expressed as milli-G.
+ *
+ * @{
+ */
+#define LSM303AGR_ACC_NUMBER_OF_AXES 3U
+
+#define LSM303AGR_ACC_2G 2.0f
+#define LSM303AGR_ACC_4G 4.0f
+#define LSM303AGR_ACC_8G 8.0f
+#define LSM303AGR_ACC_16G 16.0f
+
+#define LSM303AGR_ACC_SENS_2G 0.060f
+#define LSM303AGR_ACC_SENS_4G 0.120f
+#define LSM303AGR_ACC_SENS_8G 0.240f
+#define LSM303AGR_ACC_SENS_16G 0.750f
+
+#define LSM303AGR_ACC_BIAS 0.0f
+/** @} */
+
+/**
+ * @brief LSM303AGR compass subsystem characteristics.
+ * @note Sensitivity is expressed as G/LSB whereas G stands for Gauss.
+ * @note Bias is expressed as G.
+ *
+ * @{
+ */
+#define LSM303AGR_COMP_NUMBER_OF_AXES 3U
+
+#define LSM303AGR_COMP_50GA 50.0f
+
+#define LSM303AGR_COMP_SENS_50GA 0.00015f
+
+#define LSM303AGR_COMP_BIAS 0.0f
+/** @} */
+
+/**
+ * @name LSM303AGR communication interfaces related bit masks
+ * @{
+ */
+#define LSM303AGR_DI_MASK 0xFF
+#define LSM303AGR_DI(n) (1 << n)
+#define LSM303AGR_AD_MASK 0x7F
+#define LSM303AGR_AD(n) (1 << n)
+#define LSM303AGR_MS (1 << 7)
+/** @} */
+
+/**
+ * @name LSM303AGR register addresses
+ * @{
+ */
+#define LSM303AGR_AD_STATUS_REG_AUX_A 0x07
+#define LSM303AGR_AD_OUT_TEMP_L_A 0x0C
+#define LSM303AGR_AD_OUT_TEMP_H_A 0x0D
+#define LSM303AGR_AD_INT_COUNTER_REG_A 0x0E
+#define LSM303AGR_AD_WHO_AM_I_A 0x0F
+#define LSM303AGR_AD_TEMP_CFG_REG_A 0x1F
+#define LSM303AGR_AD_CTRL_REG1_A 0x20
+#define LSM303AGR_AD_CTRL_REG2_A 0x21
+#define LSM303AGR_AD_CTRL_REG3_A 0x22
+#define LSM303AGR_AD_CTRL_REG4_A 0x23
+#define LSM303AGR_AD_CTRL_REG5_A 0x24
+#define LSM303AGR_AD_CTRL_REG6_A 0x25
+#define LSM303AGR_AD_REFERENCE_A 0x26
+#define LSM303AGR_AD_STATUS_REG_A 0x27
+#define LSM303AGR_AD_OUT_X_L_A 0x28
+#define LSM303AGR_AD_OUT_X_H_A 0x29
+#define LSM303AGR_AD_OUT_Y_L_A 0x2A
+#define LSM303AGR_AD_OUT_Y_H_A 0x2B
+#define LSM303AGR_AD_OUT_Z_L_A 0x2C
+#define LSM303AGR_AD_OUT_Z_H_A 0x2D
+#define LSM303AGR_AD_FIFO_CTRL_REG_A 0x2E
+#define LSM303AGR_AD_FIFO_SRC_REG_A 0x2F
+#define LSM303AGR_AD_INT1_CFG_A 0x30
+#define LSM303AGR_AD_INT1_SRC_A 0x31
+#define LSM303AGR_AD_INT1_THS_A 0x32
+#define LSM303AGR_AD_INT1_DURATION_A 0x33
+#define LSM303AGR_AD_INT2_CFG_A 0x34
+#define LSM303AGR_AD_INT2_SRC_A 0x35
+#define LSM303AGR_AD_INT2_THS_A 0x36
+#define LSM303AGR_AD_INT2_DURATION_A 0x37
+#define LSM303AGR_AD_CLICK_CFG_A 0x38
+#define LSM303AGR_AD_CLICK_SRC_A 0x39
+#define LSM303AGR_AD_CLICK_THS_A 0x3A
+#define LSM303AGR_AD_TIME_LIMIT_A 0x3B
+#define LSM303AGR_AD_TIME_LATENCY_A 0x3C
+#define LSM303AGR_AD_TIME_WINDOW_A 0x3D
+#define LSM303AGR_AD_ACT_THS_A 0x3E
+#define LSM303AGR_AD_ACT_DUR_A 0x3F
+#define LSM303AGR_AD_OFFSET_X_REG_L_M 0x45
+#define LSM303AGR_AD_OFFSET_X_REG_H_M 0x46
+#define LSM303AGR_AD_OFFSET_Y_REG_L_M 0x47
+#define LSM303AGR_AD_OFFSET_Y_REG_H_M 0x48
+#define LSM303AGR_AD_OFFSET_Z_REG_L_M 0x49
+#define LSM303AGR_AD_OFFSET_Z_REG_H_M 0x4A
+#define LSM303AGR_AD_WHO_AM_I_M 0x4F
+#define LSM303AGR_AD_CFG_REG_A_M 0x60
+#define LSM303AGR_AD_CFG_REG_B_M 0x61
+#define LSM303AGR_AD_CFG_REG_C_M 0x62
+#define LSM303AGR_AD_INT_CRTL_REG_M 0x63
+#define LSM303AGR_AD_INT_SOURCE_REG_M 0x64
+#define LSM303AGR_AD_INT_THS_L_REG_M 0x65
+#define LSM303AGR_AD_INT_THS_H_REG_M 0x66
+#define LSM303AGR_AD_STATUS_REG_M 0x67
+#define LSM303AGR_AD_OUTX_L_REG_M 0x68
+#define LSM303AGR_AD_OUTX_H_REG_M 0x69
+#define LSM303AGR_AD_OUTY_L_REG_M 0x6A
+#define LSM303AGR_AD_OUTY_H_REG_M 0x6B
+#define LSM303AGR_AD_OUTZ_L_REG_M 0x6C
+#define LSM303AGR_AD_OUTZ_H_REG_M 0x6D
+/** @} */
+
+/**
+ * @name LSM303AGR_TEMP_CFG_REG_A register bits definitions
+ * @{
+ */
+#define LSM303AGR_TEMP_CFG_REG_A_TEMP_EN0 (1 << 0)
+#define LSM303AGR_TEMP_CFG_REG_A_TEMP_EN1 (1 << 0)
+/** @} */
+
+/**
+ * @name LSM303AGR_CTRL_REG1_A register bits definitions
+ * @{
+ */
+#define LSM303AGR_CTRL_REG1_A_XEN (1 << 0)
+#define LSM303AGR_CTRL_REG1_A_YEN (1 << 1)
+#define LSM303AGR_CTRL_REG1_A_ZEN (1 << 2)
+#define LSM303AGR_CTRL_REG1_A_LPEN (1 << 3)
+#define LSM303AGR_CTRL_REG1_A_ODR0 (1 << 4)
+#define LSM303AGR_CTRL_REG1_A_ODR1 (1 << 5)
+#define LSM303AGR_CTRL_REG1_A_ODR2 (1 << 6)
+#define LSM303AGR_CTRL_REG1_A_ODR3 (1 << 7)
+/** @} */
+
+/**
+ * @name LSM303AGR_CTRL_REG2_A register bits definitions
+ * @{
+ */
+#define LSM303AGR_CTRL_REG2_A_HPIS1 (1 << 0)
+#define LSM303AGR_CTRL_REG2_A_HPIS2 (1 << 1)
+#define LSM303AGR_CTRL_REG2_A_HPCLICK (1 << 2)
+#define LSM303AGR_CTRL_REG2_A_FDS (1 << 3)
+#define LSM303AGR_CTRL_REG2_A_HPCF1 (1 << 4)
+#define LSM303AGR_CTRL_REG2_A_HPCF2 (1 << 5)
+#define LSM303AGR_CTRL_REG2_A_HPM0 (1 << 6)
+#define LSM303AGR_CTRL_REG2_A_HPM1 (1 << 7)
+/** @} */
+
+/**
+ * @name LSM303AGR_CTRL_REG3_A register bits definitions
+ * @{
+ */
+#define LSM303AGR_CTRL_REG3_A_I1_OVERRUN (1 << 1)
+#define LSM303AGR_CTRL_REG3_A_I1_WTM (1 << 2)
+#define LSM303AGR_CTRL_REG3_A_I1_DRDY2 (1 << 3)
+#define LSM303AGR_CTRL_REG3_A_I1_DRDY1 (1 << 4)
+#define LSM303AGR_CTRL_REG3_A_I1_AOI2 (1 << 5)
+#define LSM303AGR_CTRL_REG3_A_I1_AOI1 (1 << 6)
+#define LSM303AGR_CTRL_REG3_A_I1_CLICK (1 << 7)
+/** @} */
+
+/**
+ * @name LSM303AGR_CTRL_REG4_A register bits definitions
+ * @{
+ */
+#define LSM303AGR_CTRL_REG4_A_SPI_ENABLE (1 << 0)
+#define LSM303AGR_CTRL_REG4_A_ST0 (1 << 1)
+#define LSM303AGR_CTRL_REG4_A_ST1 (1 << 2)
+#define LSM303AGR_CTRL_REG4_A_HR (1 << 3)
+#define LSM303AGR_CTRL_REG4_A_FS_MASK 0x30
+#define LSM303AGR_CTRL_REG4_A_FS0 (1 << 4)
+#define LSM303AGR_CTRL_REG4_A_FS1 (1 << 5)
+#define LSM303AGR_CTRL_REG4_A_BLE (1 << 6)
+#define LSM303AGR_CTRL_REG4_A_BDU (1 << 7)
+/** @} */
+
+/**
+ * @name LSM303AGR_CTRL_REG5_A register bits definitions
+ * @{
+ */
+#define LSM303AGR_CTRL_REG5_A_D4D_INT2 (1 << 0)
+#define LSM303AGR_CTRL_REG5_A_LIR_INT2 (1 << 1)
+#define LSM303AGR_CTRL_REG5_A_D4D_INT1 (1 << 2)
+#define LSM303AGR_CTRL_REG5_A_LIR_INT1 (1 << 3)
+#define LSM303AGR_CTRL_REG5_A_FIFO_EN (1 << 6)
+#define LSM303AGR_CTRL_REG5_A_BOOT (1 << 7)
+/** @} */
+
+/**
+ * @name LSM303AGR_CTRL_REG6_A register bits definitions
+ * @{
+ */
+#define LSM303AGR_CTRL_REG6_A_H_LACTIVE (1 << 1)
+#define LSM303AGR_CTRL_REG6_A_P2_ACT (1 << 3)
+#define LSM303AGR_CTRL_REG6_A_BOOT_I2 (1 << 4)
+#define LSM303AGR_CTRL_REG6_A_I2_INT2 (1 << 5)
+#define LSM303AGR_CTRL_REG6_A_I2_INT1 (1 << 6)
+#define LSM303AGR_CTRL_REG6_A_I2_CLICKEN (1 << 7)
+/** @} */
+
+/**
+ * @name LSM303AGR_CFG_REG_A register bits definitions
+ * @{
+ */
+#define LSM303AGR_CFG_REG_A_M_MD0 (1 << 0)
+#define LSM303AGR_CFG_REG_A_M_MD1 (1 << 1)
+#define LSM303AGR_CFG_REG_A_M_ODR0 (1 << 2)
+#define LSM303AGR_CFG_REG_A_M_ODR1 (1 << 3)
+#define LSM303AGR_CFG_REG_A_M_LP (1 << 4)
+#define LSM303AGR_CFG_REG_A_M_SOFT_RST (1 << 5)
+#define LSM303AGR_CFG_REG_A_M_REBOOT (1 << 6)
+#define LSM303AGR_CFG_REG_A_M_COMP_TEMP_EN (1 << 7)
+/** @} */
+
+/**
+ * @name LSM303AGR_CFG_REG_B register bits definitions
+ * @{
+ */
+#define LSM303AGR_CFG_REG_B_M_LPF (1 << 0)
+#define LSM303AGR_CFG_REG_B_M_OFF_CANC (1 << 1)
+#define LSM303AGR_CFG_REG_B_M_SET_FREQ (1 << 2)
+#define LSM303AGR_CFG_REG_B_M_INT_ON (1 << 3)
+#define LSM303AGR_CFG_REG_B_M_OFF_CANC_OS (1 << 4)
+/** @} */
+
+/**
+ * @name LSM303AGR_CFG_REG_C register bits definitions
+ * @{
+ */
+#define LSM303AGR_CFG_REG_C_M_INT_MAG (1 << 0)
+#define LSM303AGR_CFG_REG_C_M_SELF_TEST (1 << 1)
+#define LSM303AGR_CFG_REG_C_M_BLE (1 << 3)
+#define LSM303AGR_CFG_REG_C_M_BDU (1 << 4)
+#define LSM303AGR_CFG_REG_C_M_I2C_DIS (1 << 5)
+#define LSM303AGR_CFG_REG_C_M_INT_MAG_PIN (1 << 6)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief LSM303AGR SPI interface switch.
+ * @details If set to @p TRUE the support for SPI is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(LSM303AGR_USE_SPI) || defined(__DOXYGEN__)
+#define LSM303AGR_USE_SPI FALSE
+#endif
+
+/**
+ * @brief LSM303AGR shared SPI switch.
+ * @details If set to @p TRUE the device acquires SPI bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(LSM303AGR_SHARED_SPI) || defined(__DOXYGEN__)
+#define LSM303AGR_SHARED_SPI FALSE
+#endif
+
+/**
+ * @brief LSM303AGR I2C interface switch.
+ * @details If set to @p TRUE the support for I2C is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(LSM303AGR_USE_I2C) || defined(__DOXYGEN__)
+#define LSM303AGR_USE_I2C TRUE
+#endif
+
+/**
+ * @brief LSM303AGR shared I2C switch.
+ * @details If set to @p TRUE the device acquires I2C bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(LSM303AGR_SHARED_I2C) || defined(__DOXYGEN__)
+#define LSM303AGR_SHARED_I2C FALSE
+#endif
+
+/**
+ * @brief LSM303AGR advanced configurations switch.
+ * @details If set to @p TRUE more configurations are available.
+ * @note The default is @p FALSE.
+ */
+#if !defined(LSM303AGR_USE_ADVANCED) || defined(__DOXYGEN__)
+#define LSM303AGR_USE_ADVANCED FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !(LSM303AGR_USE_SPI ^ LSM303AGR_USE_I2C)
+#error "LSM303AGR_USE_SPI and LSM303AGR_USE_I2C cannot be both true or both false"
+#endif
+
+#if LSM303AGR_USE_SPI && !HAL_USE_SPI
+#error "LSM303AGR_USE_SPI requires HAL_USE_SPI"
+#endif
+
+#if LSM303AGR_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION
+#error "LSM303AGR_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
+#endif
+
+#if LSM303AGR_USE_I2C && !HAL_USE_I2C
+#error "LSM303AGR_USE_I2C requires HAL_USE_I2C"
+#endif
+
+#if LSM303AGR_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
+#error "LSM303AGR_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
+#endif
+
+/*
+ * CHTODO: Add support for LSM303AGR over SPI.
+ */
+#if LSM303AGR_USE_SPI
+#error "LSM303AGR over SPI still not supported"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @name LSM303AGR accelerometer subsystem data structures and types.
+ * @{
+ */
+/**
+ * @brief Structure representing a LSM303AGR driver.
+ */
+typedef struct LSM303AGRDriver LSM303AGRDriver;
+
+/**
+ * @brief LSM303AGR accelerometer subsystem full scale.
+ */
+typedef enum {
+ LSM303AGR_ACC_FS_2G = 0x00, /**< Full scale �2g. */
+ LSM303AGR_ACC_FS_4G = 0x10, /**< Full scale �4g. */
+ LSM303AGR_ACC_FS_8G = 0x20, /**< Full scale �8g. */
+ LSM303AGR_ACC_FS_16G = 0x30 /**< Full scale �16g. */
+} lsm303agr_acc_fs_t;
+
+/**
+ * @brief LSM303AGR accelerometer subsystem output data rate.
+ */
+typedef enum {
+ LSM303AGR_ACC_ODR_PD = 0x00, /**< Power down */
+ LSM303AGR_ACC_ODR_1Hz = 0x10, /**< ODR 1 Hz */
+ LSM303AGR_ACC_ODR_10Hz = 0x20, /**< ODR 10 Hz */
+ LSM303AGR_ACC_ODR_25Hz = 0x30, /**< ODR 25 Hz */
+ LSM303AGR_ACC_ODR_50Hz = 0x40, /**< ODR 50 Hz */
+ LSM303AGR_ACC_ODR_100Hz = 0x50, /**< ODR 100 Hz */
+ LSM303AGR_ACC_ODR_200Hz = 0x60, /**< ODR 200 Hz */
+ LSM303AGR_ACC_ODR_400Hz = 0x70, /**< ODR 400 Hz */
+ LSM303AGR_ACC_ODR_1620Hz = 0x80, /**< ODR 1620 Hz (LP only) */
+ LSM303AGR_ACC_ODR_1344Hz = 0x90 /**< ODR 1344 Hz or 5376 Hz in LP */
+} lsm303agr_acc_odr_t;
+
+/**
+ * @brief LSM303AGR accelerometer subsystem axes enabling.
+ */
+typedef enum {
+ LSM303AGR_ACC_AE_DISABLED = 0x00,/**< All axes disabled. */
+ LSM303AGR_ACC_AE_X = 0x01, /**< Only X-axis enabled. */
+ LSM303AGR_ACC_AE_Y = 0x02, /**< Only Y-axis enabled. */
+ LSM303AGR_ACC_AE_XY = 0x03, /**< X and Y axes enabled. */
+ LSM303AGR_ACC_AE_Z = 0x04, /**< Only Z-axis enabled. */
+ LSM303AGR_ACC_AE_XZ = 0x05, /**< X and Z axes enabled. */
+ LSM303AGR_ACC_AE_YZ = 0x06, /**< Y and Z axes enabled. */
+ LSM303AGR_ACC_AE_XYZ = 0x07 /**< All axes enabled. */
+} lsm303agr_acc_ae_t;
+
+/**
+ * @brief LSM303AGR accelerometer subsystem operation mode.
+ */
+typedef enum {
+ LSM303AGR_ACC_MODE_NORM = 0, /**< Normal mode. */
+ LSM303AGR_ACC_MODE_LPOW = 1, /**< Low power mode. */
+ LSM303AGR_ACC_MODE_HRES = 2 /**< High resolution mode. */
+} lsm303agr_acc_mode_t;
+
+/**
+ * @brief LSM303AGR accelerometer subsystem block data update.
+ */
+typedef enum {
+ LSM303AGR_ACC_BDU_CONT = 0x00, /**< Continuous update */
+ LSM303AGR_ACC_BDU_BLOCK = 0x80 /**< Update blocked */
+} lsm303agr_acc_bdu_t;
+
+/**
+ * @brief LSM303AGR accelerometer endianness.
+ */
+typedef enum {
+ LSM303AGR_ACC_END_LITTLE = 0x00, /**< Little Endian */
+ LSM303AGR_ACC_END_BIG = 0x40 /**< Big Endian */
+} lsm303agr_acc_end_t;
+
+/**
+ * @name LSM303AGR compass subsystem data structures and types.
+ * @{
+ */
+/**
+ * @brief LSM303AGR compass subsystem output data rate.
+ */
+typedef enum {
+ LSM303AGR_COMP_ODR_10HZ = 0x00, /**< ODR 10 Hz */
+ LSM303AGR_COMP_ODR_20HZ = 0x04, /**< ODR 20 Hz */
+ LSM303AGR_COMP_ODR_50HZ = 0x08, /**< ODR 50 Hz */
+ LSM303AGR_COMP_ODR_100HZ = 0x0C /**< ODR 100 Hz */
+} lsm303agr_comp_odr_t;
+
+/**
+ * @brief LSM303AGR compass subsystem working mode.
+ */
+typedef enum {
+ LSM303AGR_COMP_MODE_NORM = 0x00, /**< Continuous-Conversion Mode */
+ LSM303AGR_COMP_MODE_SINGLE = 0x01,/**< Single-Conversion Mode */
+ LSM303AGR_COMP_MODE_IDLE = 0x02 /**< Sleep Mode */
+} lsm303agr_comp_mode_t;
+
+/**
+ * @brief LSM303AGR compass subsystem working mode.
+ */
+typedef enum {
+ LSM303AGR_COMP_LPOW_DIS = 0x00, /**< High Resolution Mode */
+ LSM303AGR_COMP_LPOW_EN = 0x10 /**< Low Power Mode */
+} lsm303agr_comp_lpow_t;
+
+/**
+ * @name LSM303AGR main system data structures and types.
+ * @{
+ */
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ LSM303AGR_UNINIT = 0, /**< Not initialized. */
+ LSM303AGR_STOP = 1, /**< Stopped. */
+ LSM303AGR_READY = 2, /**< Ready. */
+} lsm303agr_state_t;
+
+/**
+ * @brief LSM303AGR configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief I2C driver associated to this LSM303AGR.
+ */
+ I2CDriver *i2cp;
+ /**
+ * @brief I2C configuration associated to this LSM303AGR.
+ */
+ const I2CConfig *i2ccfg;
+ /**
+ * @brief LSM303AGR accelerometer subsystem initial sensitivity.
+ */
+ float *accsensitivity;
+ /**
+ * @brief LSM303AGR accelerometer subsystem initial bias.
+ */
+ float *accbias;
+ /**
+ * @brief LSM303AGR accelerometer subsystem initial full scale.
+ */
+ lsm303agr_acc_fs_t accfullscale;
+ /**
+ * @brief LSM303AGR accelerometer subsystem output data rate.
+ */
+ lsm303agr_acc_odr_t accoutdatarate;
+#if LSM303AGR_USE_ADVANCED || defined(__DOXYGEN__)
+ /**
+ * @brief LSM303AGR accelerometer subsystem mode.
+ */
+ lsm303agr_acc_mode_t accmode;
+ /**
+ * @brief LSM303AGR accelerometer subsystem block data update.
+ */
+ lsm303agr_acc_bdu_t accblockdataupdate;
+ /**
+ * @brief LSM303AGR accelerometer endianness.
+ */
+ lsm303agr_acc_end_t accendianess;
+#endif
+ /**
+ * @brief LSM303AGR compass initial sensitivity.
+ */
+ float *compsensitivity;
+ /**
+ * @brief LSM303AGR compass initial bias.
+ */
+ float *compbias;
+ /**
+ * @brief LSM303AGR compass subsystem output data rate.
+ */
+ lsm303agr_comp_odr_t compoutputdatarate;
+#if LSM303AGR_USE_ADVANCED || defined(__DOXYGEN__)
+ /**
+ * @brief LSM303AGR compass subsystem working mode.
+ */
+ lsm303agr_comp_mode_t compmode;
+ /**
+ * @brief LSM303AGR compass subsystem lowpower mode.
+ */
+ lsm303agr_comp_lpow_t complp;
+#endif
+} LSM303AGRConfig;
+
+/**
+ * @brief @p LSM303AGR specific methods.
+ */
+#define _lsm303agr_methods_alone \
+ /* Change full scale value of LSM303AGR accelerometer subsystem.*/ \
+ msg_t (*acc_set_full_scale)(LSM303AGRDriver *devp, \
+ lsm303agr_acc_fs_t fs);
+
+/**
+ * @brief @p LSM303AGR specific methods with inherited ones.
+ */
+#define _lsm303agr_methods \
+ _base_object_methods \
+ _lsm303agr_methods_alone
+
+/**
+ * @extends BaseObjectVMT
+ *
+ * @brief @p LSM303AGR virtual methods table.
+ */
+struct LSM303AGRVMT {
+ _lsm303agr_methods
+};
+
+/**
+ * @brief @p LSM303AGRDriver specific data.
+ */
+#define _lsm303agr_data \
+ _base_sensor_data \
+ /* Driver state.*/ \
+ lsm303agr_state_t state; \
+ /* Current configuration data.*/ \
+ const LSM303AGRConfig *config; \
+ /* Accelerometer subsystem axes number.*/ \
+ size_t accaxes; \
+ /* Accelerometer subsystem current sensitivity.*/ \
+ float accsensitivity[LSM303AGR_ACC_NUMBER_OF_AXES]; \
+ /* Accelerometer subsystem current bias .*/ \
+ float accbias[LSM303AGR_ACC_NUMBER_OF_AXES]; \
+ /* Accelerometer subsystem current full scale value.*/ \
+ float accfullscale; \
+ /* Compass subsystem axes number.*/ \
+ size_t compaxes; \
+ /* Compass subsystem current sensitivity.*/ \
+ float compsensitivity[LSM303AGR_COMP_NUMBER_OF_AXES]; \
+ /* Compass subsystem current bias.*/ \
+ float compbias[LSM303AGR_COMP_NUMBER_OF_AXES]; \
+ /* Compass subsystem current full scale value.*/ \
+ float compfullscale;
+
+/**
+ * @brief LSM303AGR 6-axis accelerometer/compass class.
+ */
+struct LSM303AGRDriver {
+ /** @brief Virtual Methods Table.*/
+ const struct LSM303AGRVMT *vmt;
+ /** @brief Base accelerometer interface.*/
+ BaseAccelerometer acc_if;
+ /** @brief Base compass interface.*/
+ BaseCompass comp_if;
+ _lsm303agr_data
+};
+/** @} */
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Return the number of axes of the BaseAccelerometer.
+ *
+ * @param[in] devp pointer to @p LSM303AGRDriver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define lsm303agrAccelerometerGetAxesNumber(devp) \
+ accelerometerGetAxesNumber(&((devp)->acc_if))
+
+/**
+ * @brief Retrieves raw data from the BaseAccelerometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LSM303AGRDriver.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lsm303agrAccelerometerReadRaw(devp, axes) \
+ accelerometerReadRaw(&((devp)->acc_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseAccelerometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as milli-G.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LSM303AGRDriver.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lsm303agrAccelerometerReadCooked(devp, axes) \
+ accelerometerReadCooked(&((devp)->acc_if), axes)
+
+/**
+ * @brief Set bias values for the BaseAccelerometer.
+ * @note Bias must be expressed as milli-G.
+ * @note The bias buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LSM303AGRDriver.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm303agrAccelerometerSetBias(devp, bp) \
+ accelerometerSetBias(&((devp)->acc_if), bp)
+
+/**
+ * @brief Reset bias values for the BaseAccelerometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] devp pointer to @p LSM303AGRDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm303agrAccelerometerResetBias(devp) \
+ accelerometerResetBias(&((devp)->acc_if))
+
+/**
+ * @brief Set sensitivity values for the BaseAccelerometer.
+ * @note Sensitivity must be expressed as milli-G/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LSM303AGRDriver.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm303agrAccelerometerSetSensitivity(devp, sp) \
+ accelerometerSetSensitivity(&((devp)->acc_if), sp)
+
+/**
+ * @brief Reset sensitivity values for the BaseAccelerometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] devp pointer to @p LSM303AGRDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lsm303agrAccelerometerResetSensitivity(devp) \
+ accelerometerResetSensitivity(&((devp)->acc_if))
+
+/**
+ * @brief Changes the LSM303AGRDriver accelerometer fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p LSM303AGRDriver.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lsm303agrAccelerometerSetFullScale(devp, fs) \
+ (devp)->vmt->acc_set_full_scale(devp, fs)
+
+/**
+ * @brief Return the number of axes of the BaseCompass.
+ *
+ * @param[in] devp pointer to @p LSM303AGRDriver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define lsm303agrCompassGetAxesNumber(devp) \
+ compassGetAxesNumber(&((devp)->comp_if))
+
+/**
+ * @brief Retrieves raw data from the BaseCompass.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] devp pointer to @p BaseCompass interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lsm303agrCompassReadRaw(devp, axes) \
+ compassReadRaw(&((devp)->comp_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseCompass.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as G.
+ * @note The axes array must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] devp pointer to @p BaseCompass interface.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lsm303agrCompassReadCooked(devp, axes) \
+ compassReadCooked(&((devp)->comp_if), axes)
+
+/**
+ * @brief Set bias values for the BaseCompass.
+ * @note Bias must be expressed as G.
+ * @note The bias buffer must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] devp pointer to @p BaseCompass interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm303agrCompassSetBias(devp, bp) \
+ compassSetBias(&((devp)->comp_if), bp)
+
+/**
+ * @brief Reset bias values for the BaseCompass.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] devp pointer to @p LSM303AGRDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm303agrCompassResetBias(devp) \
+ compassResetBias(&((devp)->comp_if))
+
+/**
+ * @brief Set sensitivity values for the BaseCompass.
+ * @note Sensitivity must be expressed as G/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] devp pointer to @p LSM303AGRDriver.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm303agrCompassSetSensitivity(devp, sp) \
+ compassSetSensitivity(&((devp)->comp_if), sp)
+
+/**
+ * @brief Reset sensitivity values for the BaseCompass.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] devp pointer to @p LSM303AGRDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lsm303agrCompassResetSensitivity(devp) \
+ compassResetSensitivity(&((devp)->comp_if))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void lsm303agrObjectInit(LSM303AGRDriver *devp);
+ void lsm303agrStart(LSM303AGRDriver *devp, const LSM303AGRConfig *config);
+ void lsm303agrStop(LSM303AGRDriver *devp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LSM303AGR_H_ */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lsm303agr.mk b/ChibiOS_20.3.2/os/ex/devices/ST/lsm303agr.mk
new file mode 100644
index 0000000..ddd54eb
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lsm303agr.mk
@@ -0,0 +1,10 @@
+# List of all the LSM303AGR device files.
+LSM303AGRSRC := $(CHIBIOS)/os/ex/devices/ST/lsm303agr.c
+
+# Required include directories
+LSM303AGRINC := $(CHIBIOS)/os/ex/include \
+ $(CHIBIOS)/os/ex/devices/ST
+
+# Shared variables
+ALLCSRC += $(LSM303AGRSRC)
+ALLINC += $(LSM303AGRINC)
\ No newline at end of file
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lsm303dlhc.c b/ChibiOS_20.3.2/os/ex/devices/ST/lsm303dlhc.c
new file mode 100644
index 0000000..45e0137
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lsm303dlhc.c
@@ -0,0 +1,1175 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file lsm303dlhc.c
+ * @brief LSM303DLHC MEMS interface module code.
+ *
+ * @addtogroup LSM303DLHC
+ * @ingroup EX_ST
+ * @{
+ */
+
+#include "hal.h"
+#include "lsm303dlhc.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Accelerometer and Compass Slave Address.
+ */
+typedef enum {
+ LSM303DLHC_SAD_ACC = 0x19, /**< SAD for accelerometer. */
+ LSM303DLHC_SAD_COMP = 0x1E /**< SAD for compass. */
+} lsm303dlhc_sad_t;
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Reads registers value using I2C.
+ * @pre The I2C interface must be initialized and the driver started.
+ * @note IF_ADD_INC bit must be 1 in CTRL_REG8.
+ *
+ * @param[in] i2cp pointer to the I2C interface.
+ * @param[in] sad slave address without R bit.
+ * @param[in] reg first sub-register address.
+ * @param[in] rxbuf receiving buffer.
+ * @param[in] n size of rxbuf.
+ * @return the operation status.
+ */
+static msg_t lsm303dlhcI2CReadRegister(I2CDriver *i2cp, lsm303dlhc_sad_t sad,
+ uint8_t reg, uint8_t *rxbuf, size_t n) {
+
+ uint8_t txbuf = reg | LSM303DLHC_MS;
+ return i2cMasterTransmitTimeout(i2cp, sad, &txbuf, 1, rxbuf, n,
+ TIME_INFINITE);
+}
+
+/**
+ * @brief Writes a value into a register using I2C.
+ * @pre The I2C interface must be initialized and the driver started.
+ *
+ * @param[in] i2cp pointer to the I2C interface.
+ * @param[in] sad slave address without R bit.
+ * @param[in] txbuf buffer containing sub-address value in first position
+ * and values to write.
+ * @param[in] n size of txbuf less one (not considering the first
+ * element).
+ * @return the operation status.
+ */
+static msg_t lsm303dlhcI2CWriteRegister(I2CDriver *i2cp, lsm303dlhc_sad_t sad,
+ uint8_t *txbuf, size_t n) {
+ if (n != 1)
+ *txbuf |= LSM303DLHC_MS;
+ return i2cMasterTransmitTimeout(i2cp, sad, txbuf, n + 1, NULL, 0,
+ TIME_INFINITE);
+}
+
+/**
+ * @brief Return the number of axes of the BaseAccelerometer.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ *
+ * @return the number of axes.
+ */
+static size_t acc_get_axes_number(void *ip) {
+ (void)ip;
+
+ return LSM303DLHC_ACC_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Retrieves raw data from the BaseAccelerometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t acc_read_raw(void *ip, int32_t axes[]) {
+ LSM303DLHCDriver* devp;
+ uint8_t buff [LSM303DLHC_ACC_NUMBER_OF_AXES * 2], i;
+ int16_t tmp;
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303DLHCDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM303DLHC_READY),
+ "acc_read_raw(), invalid state");
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "acc_read_raw(), channel not ready");
+
+#if LSM303DLHC_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LSM303DLHC_SHARED_I2C */
+
+ msg = lsm303dlhcI2CReadRegister(devp->config->i2cp, LSM303DLHC_SAD_ACC,
+ LSM303DLHC_AD_ACC_OUT_X_L, buff,
+ LSM303DLHC_ACC_NUMBER_OF_AXES * 2);
+
+#if LSM303DLHC_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM303DLHC_SHARED_I2C */
+
+ if(msg == MSG_OK)
+ for(i = 0; i < LSM303DLHC_ACC_NUMBER_OF_AXES; i++) {
+ tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
+ axes[i] = (int32_t)tmp;
+ }
+ return msg;
+}
+
+/**
+ * @brief Retrieves cooked data from the BaseAccelerometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as milli-G.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t acc_read_cooked(void *ip, float axes[]) {
+ LSM303DLHCDriver* devp;
+ uint32_t i;
+ int32_t raw[LSM303DLHC_ACC_NUMBER_OF_AXES];
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303DLHCDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM303DLHC_READY),
+ "acc_read_cooked(), invalid state");
+
+ msg = acc_read_raw(ip, raw);
+ for(i = 0; i < LSM303DLHC_ACC_NUMBER_OF_AXES; i++) {
+ axes[i] = (raw[i] * devp->accsensitivity[i]) - devp->accbias[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Set bias values for the BaseAccelerometer.
+ * @note Bias must be expressed as milli-G.
+ * @note The bias buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t acc_set_bias(void *ip, float *bp) {
+ LSM303DLHCDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (bp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303DLHCDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM303DLHC_READY),
+ "acc_set_bias(), invalid state");
+
+ for(i = 0; i < LSM303DLHC_ACC_NUMBER_OF_AXES; i++) {
+ devp->accbias[i] = bp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset bias values for the BaseAccelerometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t acc_reset_bias(void *ip) {
+ LSM303DLHCDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303DLHCDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM303DLHC_READY),
+ "acc_reset_bias(), invalid state");
+
+ for(i = 0; i < LSM303DLHC_ACC_NUMBER_OF_AXES; i++)
+ devp->accbias[i] = LSM303DLHC_ACC_BIAS;
+ return msg;
+}
+
+/**
+ * @brief Set sensitivity values for the BaseAccelerometer.
+ * @note Sensitivity must be expressed as milli-G/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t acc_set_sensivity(void *ip, float *sp) {
+ LSM303DLHCDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303DLHCDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgCheck((ip != NULL) && (sp != NULL));
+
+ osalDbgAssert((devp->state == LSM303DLHC_READY),
+ "acc_set_sensivity(), invalid state");
+
+ for(i = 0; i < LSM303DLHC_ACC_NUMBER_OF_AXES; i++) {
+ devp->accsensitivity[i] = sp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset sensitivity values for the BaseAccelerometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t acc_reset_sensivity(void *ip) {
+ LSM303DLHCDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303DLHCDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM303DLHC_READY),
+ "acc_reset_sensivity(), invalid state");
+
+ if(devp->config->accfullscale == LSM303DLHC_ACC_FS_2G)
+ for(i = 0; i < LSM303DLHC_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LSM303DLHC_ACC_SENS_2G;
+ else if(devp->config->accfullscale == LSM303DLHC_ACC_FS_4G)
+ for(i = 0; i < LSM303DLHC_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LSM303DLHC_ACC_SENS_4G;
+ else if(devp->config->accfullscale == LSM303DLHC_ACC_FS_8G)
+ for(i = 0; i < LSM303DLHC_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LSM303DLHC_ACC_SENS_8G;
+ else if(devp->config->accfullscale == LSM303DLHC_ACC_FS_16G)
+ for(i = 0; i < LSM303DLHC_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LSM303DLHC_ACC_SENS_16G;
+ else {
+ osalDbgAssert(FALSE, "acc_reset_sensivity(), accelerometer full scale issue");
+ msg = MSG_RESET;
+ }
+ return msg;
+}
+
+/**
+ * @brief Changes the LSM303DLHCDriver accelerometer fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p LSM303DLHCDriver interface.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t acc_set_full_scale(LSM303DLHCDriver *devp,
+ lsm303dlhc_acc_fs_t fs) {
+ float newfs, scale;
+ uint8_t i, buff[2];
+ msg_t msg;
+
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LSM303DLHC_READY),
+ "acc_set_full_scale(), invalid state");
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "acc_set_full_scale(), channel not ready");
+
+ /* Computing new fullscale value.*/
+ if(fs == LSM303DLHC_ACC_FS_2G) {
+ newfs = LSM303DLHC_ACC_2G;
+ }
+ else if(fs == LSM303DLHC_ACC_FS_4G) {
+ newfs = LSM303DLHC_ACC_4G;
+ }
+ else if(fs == LSM303DLHC_ACC_FS_8G) {
+ newfs = LSM303DLHC_ACC_8G;
+ }
+ else if(fs == LSM303DLHC_ACC_FS_16G) {
+ newfs = LSM303DLHC_ACC_16G;
+ }
+ else {
+ msg = MSG_RESET;
+ return msg;
+ }
+
+ if(newfs != devp->accfullscale) {
+ /* Computing scale value.*/
+ scale = newfs / devp->accfullscale;
+ devp->accfullscale = newfs;
+
+#if LSM303DLHC_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LSM303DLHC_SHARED_I2C */
+
+ /* Updating register.*/
+ msg = lsm303dlhcI2CReadRegister(devp->config->i2cp,
+ LSM303DLHC_SAD_ACC,
+ LSM303DLHC_AD_ACC_CTRL_REG4,
+ &buff[1], 1);
+
+#if LSM303DLHC_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM303DLHC_SHARED_I2C */
+
+ if(msg != MSG_OK)
+ return msg;
+
+ buff[1] &= ~(LSM303DLHC_CTRL_REG4_A_FS_MASK);
+ buff[1] |= fs;
+ buff[0] = LSM303DLHC_AD_ACC_CTRL_REG4;
+
+#if LSM303DLHC_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+#endif /* LSM303DLHC_SHARED_I2C */
+
+ msg = lsm303dlhcI2CWriteRegister(devp->config->i2cp,
+ LSM303DLHC_SAD_ACC, buff, 1);
+
+#if LSM303DLHC_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM303DLHC_SHARED_I2C */
+
+ if(msg != MSG_OK)
+ return msg;
+
+ /* Scaling sensitivity and bias. Re-calibration is suggested anyway.*/
+ for(i = 0; i < LSM303DLHC_ACC_NUMBER_OF_AXES; i++) {
+ devp->accsensitivity[i] *= scale;
+ devp->accbias[i] *= scale;
+ }
+ }
+ return msg;
+}
+
+/**
+ * @brief Return the number of axes of the BaseCompass.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface
+ *
+ * @return the number of axes.
+ */
+static size_t comp_get_axes_number(void *ip) {
+
+ osalDbgCheck(ip != NULL);
+ return LSM303DLHC_COMP_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Retrieves raw data from the BaseCompass.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t comp_read_raw(void *ip, int32_t axes[]) {
+ LSM303DLHCDriver* devp;
+ uint8_t buff [LSM303DLHC_COMP_NUMBER_OF_AXES * 2], i;
+ int16_t tmp;
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303DLHCDriver*, (BaseCompass*)ip);
+
+ osalDbgAssert((devp->state == LSM303DLHC_READY),
+ "comp_read_raw(), invalid state");
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "comp_read_raw(), channel not ready");
+
+#if LSM303DLHC_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LSM303DLHC_SHARED_I2C */
+ msg = lsm303dlhcI2CReadRegister(devp->config->i2cp, LSM303DLHC_SAD_COMP,
+ LSM303DLHC_AD_COMP_OUT_X_L, buff,
+ LSM303DLHC_COMP_NUMBER_OF_AXES * 2);
+
+#if LSM303DLHC_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM303DLHC_SHARED_I2C */
+
+ if(msg == MSG_OK)
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++) {
+ tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
+ axes[i] = (int32_t)tmp;
+ }
+ return msg;
+}
+
+/**
+ * @brief Retrieves cooked data from the BaseCompass.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as G.
+ * @note The axes array must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t comp_read_cooked(void *ip, float axes[]) {
+ LSM303DLHCDriver* devp;
+ uint32_t i;
+ int32_t raw[LSM303DLHC_COMP_NUMBER_OF_AXES];
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303DLHCDriver*, (BaseCompass*)ip);
+
+ osalDbgAssert((devp->state == LSM303DLHC_READY),
+ "comp_read_cooked(), invalid state");
+
+ msg = comp_read_raw(ip, raw);
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES ; i++) {
+ axes[i] = (raw[i] * devp->compsensitivity[i]) - devp->compbias[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Set bias values for the BaseCompass.
+ * @note Bias must be expressed as G.
+ * @note The bias buffer must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t comp_set_bias(void *ip, float *bp) {
+ LSM303DLHCDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (bp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303DLHCDriver*, (BaseCompass*)ip);
+
+ osalDbgAssert((devp->state == LSM303DLHC_READY),
+ "comp_set_bias(), invalid state");
+
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++) {
+ devp->compbias[i] = bp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset bias values for the BaseCompass.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t comp_reset_bias(void *ip) {
+ LSM303DLHCDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303DLHCDriver*, (BaseCompass*)ip);
+
+ osalDbgAssert((devp->state == LSM303DLHC_READY),
+ "comp_reset_bias(), invalid state");
+
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++)
+ devp->compbias[i] = LSM303DLHC_COMP_BIAS;
+ return msg;
+}
+
+/**
+ * @brief Set sensitivity values for the BaseCompass.
+ * @note Sensitivity must be expressed as G/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t comp_set_sensivity(void *ip, float *sp) {
+ LSM303DLHCDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303DLHCDriver*, (BaseCompass*)ip);
+
+ osalDbgCheck((ip != NULL) && (sp != NULL));
+
+ osalDbgAssert((devp->state == LSM303DLHC_READY),
+ "comp_set_sensivity(), invalid state");
+
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++) {
+ devp->compsensitivity[i] = sp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset sensitivity values for the BaseCompass.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] ip pointer to @p BaseCompass interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t comp_reset_sensivity(void *ip) {
+ LSM303DLHCDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM303DLHCDriver*, (BaseCompass*)ip);
+
+ osalDbgAssert((devp->state == LSM303DLHC_READY),
+ "comp_reset_sensivity(), invalid state");
+
+ if(devp->config->compfullscale == LSM303DLHC_COMP_FS_1P3GA)
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++) {
+ if(i != 2) {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_XY_1P3GA;
+ }
+ else {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_Z_1P3GA;
+ }
+ }
+ else if(devp->config->compfullscale == LSM303DLHC_COMP_FS_1P9GA)
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++) {
+ if(i != 2) {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_XY_1P9GA;
+ }
+ else {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_Z_1P9GA;
+ }
+ }
+ else if(devp->config->compfullscale == LSM303DLHC_COMP_FS_2P5GA)
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++) {
+ if(i != 2) {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_XY_2P5GA;
+ }
+ else {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_Z_2P5GA;
+ }
+ }
+ else if(devp->config->compfullscale == LSM303DLHC_COMP_FS_4P0GA)
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++) {
+ if(i != 2) {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_XY_4P0GA;
+ }
+ else {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_Z_4P0GA;
+ }
+ }
+ else if(devp->config->compfullscale == LSM303DLHC_COMP_FS_4P7GA)
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++) {
+ if(i != 2) {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_XY_4P7GA;
+ }
+ else {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_Z_4P7GA;
+ }
+ }
+ else if(devp->config->compfullscale == LSM303DLHC_COMP_FS_5P6GA)
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++) {
+ if(i != 2) {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_XY_5P6GA;
+ }
+ else {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_Z_5P6GA;
+ }
+ }
+ else if(devp->config->compfullscale == LSM303DLHC_COMP_FS_8P1GA)
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++) {
+ if(i != 2) {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_XY_8P1GA;
+ }
+ else {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_Z_8P1GA;
+ }
+ }
+ else {
+ osalDbgAssert(FALSE, "comp_reset_sensivity(), compass full scale issue");
+ msg = MSG_RESET;
+ }
+ return msg;
+}
+
+/**
+ * @brief Changes the LSM303DLHCDriver compass fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p LSM303DLHCDriver interface.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t comp_set_full_scale(LSM303DLHCDriver *devp,
+ lsm303dlhc_comp_fs_t fs) {
+ float newfs, scale;
+ uint8_t i, buff[2];
+ msg_t msg;
+
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LSM303DLHC_READY),
+ "comp_set_full_scale(), invalid state");
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "comp_set_full_scale(), channel not ready");
+
+ /* Computing new fullscale value.*/
+ if(fs == LSM303DLHC_COMP_FS_1P3GA) {
+ newfs = LSM303DLHC_COMP_1P3GA;
+ }
+ else if(fs == LSM303DLHC_COMP_FS_1P9GA) {
+ newfs = LSM303DLHC_COMP_1P9GA;
+ }
+ else if(fs == LSM303DLHC_COMP_FS_2P5GA) {
+ newfs = LSM303DLHC_COMP_2P5GA;
+ }
+ else if(fs == LSM303DLHC_COMP_FS_4P0GA) {
+ newfs = LSM303DLHC_COMP_4P0GA;
+ }
+ else if(fs == LSM303DLHC_COMP_FS_4P7GA) {
+ newfs = LSM303DLHC_COMP_4P7GA;
+ }
+ else if(fs == LSM303DLHC_COMP_FS_5P6GA) {
+ newfs = LSM303DLHC_COMP_5P6GA;
+ }
+ else if(fs == LSM303DLHC_COMP_FS_8P1GA) {
+ newfs = LSM303DLHC_COMP_8P1GA;
+ }
+ else {
+ msg = MSG_RESET;
+ return msg;
+ }
+
+ if(newfs != devp->compfullscale) {
+ /* Computing scale value.*/
+ scale = newfs / devp->compfullscale;
+ devp->compfullscale = newfs;
+
+#if LSM303DLHC_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+#endif /* LSM303DLHC_SHARED_I2C */
+
+ /* Updating register.*/
+ msg = lsm303dlhcI2CReadRegister(devp->config->i2cp, LSM303DLHC_SAD_COMP,
+ LSM303DLHC_AD_COMP_CRB_REG, &buff[1], 1);
+
+#if LSM303DLHC_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM303DLHC_SHARED_I2C */
+
+ if(msg != MSG_OK)
+ return msg;
+ buff[1] &= ~(LSM303DLHC_CRB_REG_M_GN_MASK);
+ buff[1] |= fs;
+ buff[0] = LSM303DLHC_AD_COMP_CRB_REG;
+
+#if LSM303DLHC_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+#endif /* LSM303DLHC_SHARED_I2C */
+
+ msg = lsm303dlhcI2CWriteRegister(devp->config->i2cp, LSM303DLHC_SAD_COMP,
+ buff, 1);
+
+#if LSM303DLHC_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM303DLHC_SHARED_I2C */
+
+ if(msg != MSG_OK)
+ return msg;
+
+ /* Scaling sensitivity and bias. Re-calibration is suggested anyway.*/
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++) {
+ devp->compsensitivity[i] *= scale;
+ devp->compbias[i] *= scale;
+ }
+ }
+ return msg;
+}
+
+static const struct LSM303DLHCVMT vmt_device = {
+ (size_t)0,
+ acc_set_full_scale, comp_set_full_scale
+};
+
+static const struct BaseAccelerometerVMT vmt_accelerometer = {
+ sizeof(struct LSM303DLHCVMT*),
+ acc_get_axes_number, acc_read_raw, acc_read_cooked,
+ acc_set_bias, acc_reset_bias, acc_set_sensivity, acc_reset_sensivity
+};
+
+static const struct BaseCompassVMT vmt_compass = {
+ sizeof(struct LSM303DLHCVMT*) + sizeof(BaseAccelerometer),
+ comp_get_axes_number, comp_read_raw, comp_read_cooked,
+ comp_set_bias, comp_reset_bias, comp_set_sensivity, comp_reset_sensivity
+};
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes an instance.
+ *
+ * @param[out] devp pointer to the @p LSM303DLHCDriver object
+ *
+ * @init
+ */
+void lsm303dlhcObjectInit(LSM303DLHCDriver *devp) {
+ devp->vmt = &vmt_device;
+ devp->acc_if.vmt = &vmt_accelerometer;
+ devp->comp_if.vmt = &vmt_compass;
+
+ devp->config = NULL;
+
+ devp->accaxes = LSM303DLHC_ACC_NUMBER_OF_AXES;
+ devp->compaxes = LSM303DLHC_COMP_NUMBER_OF_AXES;
+
+ devp->state = LSM303DLHC_STOP;
+}
+
+/**
+ * @brief Configures and activates LSM303DLHC Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p LSM303DLHCDriver object
+ * @param[in] config pointer to the @p LSM303DLHCConfig object
+ *
+ * @api
+ */
+void lsm303dlhcStart(LSM303DLHCDriver *devp, const LSM303DLHCConfig *config) {
+ uint32_t i;
+ uint8_t cr[6];
+ osalDbgCheck((devp != NULL) && (config != NULL));
+
+ osalDbgAssert((devp->state == LSM303DLHC_STOP) ||
+ (devp->state == LSM303DLHC_READY),
+ "lsm303dlhcStart(), invalid state");
+
+ devp->config = config;
+
+ /* Configuring Accelerometer subsystem.*/
+
+ /* Multiple write starting address.*/
+ cr[0] = LSM303DLHC_AD_ACC_CTRL_REG1;
+
+ /* Control register 1 configuration block.*/
+ {
+ cr[1] = LSM303DLHC_CTRL_REG1_A_XEN | LSM303DLHC_CTRL_REG1_A_YEN |
+ LSM303DLHC_CTRL_REG1_A_ZEN | devp->config->accoutdatarate;
+#if LSM303DLHC_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[1] |= devp->config->acclowpower;
+#endif
+ }
+
+ /* Control register 2 configuration block.*/
+ {
+ cr[2] = 0;
+ }
+
+ /* Control register 3 configuration block.*/
+ {
+ cr[3] = 0;
+ }
+
+ /* Control register 4 configuration block.*/
+ {
+ cr[4] = devp->config->accfullscale;
+#if LSM303DLHC_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[4] |= devp->config->accendianess |
+ devp->config->accblockdataupdate |
+ devp->config->acchighresmode;
+#endif
+ }
+
+#if LSM303DLHC_SHARED_I2C
+ i2cAcquireBus((devp)->config->i2cp);
+#endif /* LSM303DLHC_SHARED_I2C */
+ i2cStart((devp)->config->i2cp, (devp)->config->i2ccfg);
+
+ lsm303dlhcI2CWriteRegister(devp->config->i2cp, LSM303DLHC_SAD_ACC, cr, 4);
+
+#if LSM303DLHC_SHARED_I2C
+ i2cReleaseBus((devp)->config->i2cp);
+#endif /* LSM303DLHC_SHARED_I2C */
+
+ /* Storing sensitivity according to user settings */
+ if(devp->config->accfullscale == LSM303DLHC_ACC_FS_2G) {
+ devp->accfullscale = LSM303DLHC_ACC_2G;
+ for(i = 0; i < LSM303DLHC_ACC_NUMBER_OF_AXES; i++) {
+ if(devp->config->accsensitivity == NULL)
+ devp->accsensitivity[i] = LSM303DLHC_ACC_SENS_2G;
+ else
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ }
+ else if(devp->config->accfullscale == LSM303DLHC_ACC_FS_4G) {
+ devp->accfullscale = LSM303DLHC_ACC_4G;
+ for(i = 0; i < LSM303DLHC_ACC_NUMBER_OF_AXES; i++) {
+ if(devp->config->accsensitivity == NULL)
+ devp->accsensitivity[i] = LSM303DLHC_ACC_SENS_4G;
+ else
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ }
+ else if(devp->config->accfullscale == LSM303DLHC_ACC_FS_8G) {
+ devp->accfullscale = LSM303DLHC_ACC_8G;
+ for(i = 0; i < LSM303DLHC_ACC_NUMBER_OF_AXES; i++) {
+ if(devp->config->accsensitivity == NULL)
+ devp->accsensitivity[i] = LSM303DLHC_ACC_SENS_8G;
+ else
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ }
+ else if(devp->config->accfullscale == LSM303DLHC_ACC_FS_16G) {
+ devp->accfullscale = LSM303DLHC_ACC_16G;
+ for(i = 0; i < LSM303DLHC_ACC_NUMBER_OF_AXES; i++) {
+ if(devp->config->accsensitivity == NULL)
+ devp->accsensitivity[i] = LSM303DLHC_ACC_SENS_16G;
+ else
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ }
+ else
+ osalDbgAssert(FALSE, "lsm303dlhcStart(), accelerometer full scale issue");
+
+ /* Storing bias information */
+ if(devp->config->accbias != NULL)
+ for(i = 0; i < LSM303DLHC_ACC_NUMBER_OF_AXES; i++)
+ devp->accbias[i] = devp->config->accbias[i];
+ else
+ for(i = 0; i < LSM303DLHC_ACC_NUMBER_OF_AXES; i++)
+ devp->accbias[i] = LSM303DLHC_ACC_BIAS;
+
+ /* Configuring Compass subsystem */
+ /* Multiple write starting address.*/
+ cr[0] = LSM303DLHC_AD_COMP_CRA_REG;
+
+ /* Control register A configuration block.*/
+ {
+ cr[1] = devp->config->compoutputdatarate;
+ }
+
+ /* Control register B configuration block.*/
+ {
+ cr[2] = devp->config->compfullscale;
+ }
+
+ /* Mode register configuration block.*/
+ {
+ cr[3] = 0;
+#if LSM303DLHC_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[3] |= devp->config->compmode;
+#endif
+ }
+
+#if LSM303DLHC_SHARED_I2C
+ i2cAcquireBus((devp)->config->i2cp);
+ i2cStart((devp)->config->i2cp, (devp)->config->i2ccfg);
+#endif /* LSM303DLHC_SHARED_I2C */
+
+ lsm303dlhcI2CWriteRegister(devp->config->i2cp, LSM303DLHC_SAD_COMP,
+ cr, 3);
+
+#if LSM303DLHC_SHARED_I2C
+ i2cReleaseBus((devp)->config->i2cp);
+#endif /* LSM303DLHC_SHARED_I2C */
+
+ if(devp->config->compfullscale == LSM303DLHC_COMP_FS_1P3GA) {
+ devp->compfullscale = LSM303DLHC_COMP_1P3GA;
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++) {
+ if(devp->config->compsensitivity == NULL) {
+ if(i != 2) {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_XY_1P3GA;
+ }
+ else {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_Z_1P3GA;
+ }
+ }
+ else {
+ devp->compsensitivity[i] = devp->config->compsensitivity[i];
+ }
+ }
+ }
+ else if(devp->config->compfullscale == LSM303DLHC_COMP_FS_1P9GA) {
+ devp->compfullscale = LSM303DLHC_COMP_1P9GA;
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++) {
+ if(devp->config->compsensitivity == NULL) {
+ if(i != 2) {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_XY_1P9GA;
+ }
+ else {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_Z_1P9GA;
+ }
+ }
+ else {
+ devp->compsensitivity[i] = devp->config->compsensitivity[i];
+ }
+ }
+ }
+ else if(devp->config->compfullscale == LSM303DLHC_COMP_FS_2P5GA) {
+ devp->compfullscale = LSM303DLHC_COMP_2P5GA;
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++) {
+ if(devp->config->compsensitivity == NULL) {
+ if(i != 2) {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_XY_2P5GA;
+ }
+ else {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_Z_2P5GA;
+ }
+ }
+ else {
+ devp->compsensitivity[i] = devp->config->compsensitivity[i];
+ }
+ }
+ }
+ else if(devp->config->compfullscale == LSM303DLHC_COMP_FS_4P0GA) {
+ devp->compfullscale = LSM303DLHC_COMP_4P0GA;
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++) {
+ if(devp->config->compsensitivity == NULL) {
+ if(i != 2) {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_XY_4P0GA;
+ }
+ else {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_Z_4P0GA;
+ }
+ }
+ else {
+ devp->compsensitivity[i] = devp->config->compsensitivity[i];
+ }
+ }
+ }
+ else if(devp->config->compfullscale == LSM303DLHC_COMP_FS_4P7GA) {
+ devp->compfullscale = LSM303DLHC_COMP_4P7GA;
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++) {
+ if(devp->config->compsensitivity == NULL) {
+ if(i != 2) {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_XY_4P7GA;
+ }
+ else {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_Z_4P7GA;
+ }
+ }
+ else {
+ devp->compsensitivity[i] = devp->config->compsensitivity[i];
+ }
+ }
+ }
+ else if(devp->config->compfullscale == LSM303DLHC_COMP_FS_5P6GA) {
+ devp->compfullscale = LSM303DLHC_COMP_5P6GA;
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++) {
+ if(devp->config->compsensitivity == NULL) {
+ if(i != 2) {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_XY_5P6GA;
+ }
+ else {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_Z_5P6GA;
+ }
+ }
+ else {
+ devp->compsensitivity[i] = devp->config->compsensitivity[i];
+ }
+ }
+ }
+ else if(devp->config->compfullscale == LSM303DLHC_COMP_FS_8P1GA) {
+ devp->compfullscale = LSM303DLHC_COMP_8P1GA;
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++) {
+ if(devp->config->compsensitivity == NULL) {
+ if(i != 2) {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_XY_8P1GA;
+ }
+ else {
+ devp->compsensitivity[i] = LSM303DLHC_COMP_SENS_Z_8P1GA;
+ }
+ }
+ else {
+ devp->compsensitivity[i] = devp->config->compsensitivity[i];
+ }
+ }
+ }
+ else
+ osalDbgAssert(FALSE, "lsm303dlhcStart(), compass full scale issue");
+
+ /* Storing bias information */
+ if(devp->config->compbias != NULL)
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++)
+ devp->compbias[i] = devp->config->compbias[i];
+ else
+ for(i = 0; i < LSM303DLHC_COMP_NUMBER_OF_AXES; i++)
+ devp->compbias[i] = LSM303DLHC_COMP_BIAS;
+
+ /* This is the MEMS transient recovery time */
+ osalThreadSleepMilliseconds(5);
+
+ devp->state = LSM303DLHC_READY;
+}
+
+/**
+ * @brief Deactivates the LSM303DLHC Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p LSM303DLHCDriver object
+ *
+ * @api
+ */
+void lsm303dlhcStop(LSM303DLHCDriver *devp) {
+ uint8_t cr[2];
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LSM303DLHC_STOP) ||
+ (devp->state == LSM303DLHC_READY),
+ "lsm303dlhcStop(), invalid state");
+
+ if (devp->state == LSM303DLHC_READY) {
+#if LSM303DLHC_SHARED_I2C
+ i2cAcquireBus((devp)->config->i2cp);
+ i2cStart((devp)->config->i2cp, (devp)->config->i2ccfg);
+#endif /* LSM303DLHC_SHARED_I2C */
+
+ /* Disabling accelerometer. */
+ cr[0] = LSM303DLHC_AD_ACC_CTRL_REG1;
+ cr[1] = LSM303DLHC_ACC_AE_DISABLED | LSM303DLHC_ACC_ODR_PD;
+ lsm303dlhcI2CWriteRegister(devp->config->i2cp, LSM303DLHC_SAD_ACC,
+ cr, 1);
+
+ /* Disabling compass. */
+ cr[0] = LSM303DLHC_AD_COMP_MR_REG;
+ cr[1] = LSM303DLHC_COMP_MD_SLEEP;
+ lsm303dlhcI2CWriteRegister(devp->config->i2cp, LSM303DLHC_SAD_COMP,
+ cr, 1);
+
+ i2cStop((devp)->config->i2cp);
+#if LSM303DLHC_SHARED_I2C
+ i2cReleaseBus((devp)->config->i2cp);
+#endif /* LSM303DLHC_SHARED_I2C */
+ }
+ devp->state = LSM303DLHC_STOP;
+}
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lsm303dlhc.h b/ChibiOS_20.3.2/os/ex/devices/ST/lsm303dlhc.h
new file mode 100644
index 0000000..98bc43a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lsm303dlhc.h
@@ -0,0 +1,955 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file lsm303dlhc.h
+ * @brief LSM303DLHC MEMS interface module header.
+ *
+ * @addtogroup LSM303DLHC
+ * @ingroup EX_ST
+ * @{
+ */
+#ifndef _LSM303DLHC_H_
+#define _LSM303DLHC_H_
+
+#include "ex_accelerometer.h"
+#include "ex_compass.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Version identification
+ * @{
+ */
+/**
+ * @brief LSM303DLHC driver version string.
+ */
+#define EX_LSM303DLHC_VERSION "1.1.2"
+
+/**
+ * @brief LSM303DLHC driver version major number.
+ */
+#define EX_LSM303DLHC_MAJOR 1
+
+/**
+ * @brief LSM303DLHC driver version minor number.
+ */
+#define EX_LSM303DLHC_MINOR 1
+
+/**
+ * @brief LSM303DLHC driver version patch number.
+ */
+#define EX_LSM303DLHC_PATCH 2
+/** @} */
+
+/**
+ * @brief LSM303DLHC accelerometer subsystem characteristics.
+ * @note Sensitivity is expressed as milli-G/LSB whereas
+ * 1 milli-G = 0.00980665 m/s^2.
+ * @note Bias is expressed as milli-G.
+ *
+ * @{
+ */
+#define LSM303DLHC_ACC_NUMBER_OF_AXES 3U
+
+#define LSM303DLHC_ACC_2G 2.0f
+#define LSM303DLHC_ACC_4G 4.0f
+#define LSM303DLHC_ACC_8G 8.0f
+#define LSM303DLHC_ACC_16G 16.0f
+
+#define LSM303DLHC_ACC_SENS_2G 0.0610f
+#define LSM303DLHC_ACC_SENS_4G 0.1221f
+#define LSM303DLHC_ACC_SENS_8G 0.2442f
+#define LSM303DLHC_ACC_SENS_16G 0.4884f
+
+#define LSM303DLHC_ACC_BIAS 0.0f
+/** @} */
+
+/**
+ * @brief LSM303DLHC compass subsystem characteristics.
+ * @note Sensitivity is expressed as G/LSB whereas G stands for Gauss.
+ * @note Bias is expressed as G.
+ *
+ * @{
+ */
+#define LSM303DLHC_COMP_NUMBER_OF_AXES 3U
+
+#define LSM303DLHC_COMP_1P3GA 1.3f
+#define LSM303DLHC_COMP_1P9GA 1.9f
+#define LSM303DLHC_COMP_2P5GA 2.5f
+#define LSM303DLHC_COMP_4P0GA 4.0f
+#define LSM303DLHC_COMP_4P7GA 4.7f
+#define LSM303DLHC_COMP_5P6GA 5.6f
+#define LSM303DLHC_COMP_8P1GA 8.1f
+
+#define LSM303DLHC_COMP_SENS_XY_1P3GA 0.000909f
+#define LSM303DLHC_COMP_SENS_XY_1P9GA 0.001169f
+#define LSM303DLHC_COMP_SENS_XY_2P5GA 0.0014925f
+#define LSM303DLHC_COMP_SENS_XY_4P0GA 0.0022222f
+#define LSM303DLHC_COMP_SENS_XY_4P7GA 0.0025000f
+#define LSM303DLHC_COMP_SENS_XY_5P6GA 0.0030303f
+#define LSM303DLHC_COMP_SENS_XY_8P1GA 0.0043478f
+
+#define LSM303DLHC_COMP_SENS_Z_1P3GA 0.0010204f
+#define LSM303DLHC_COMP_SENS_Z_1P9GA 0.0013071f
+#define LSM303DLHC_COMP_SENS_Z_2P5GA 0.0016666f
+#define LSM303DLHC_COMP_SENS_Z_4P0GA 0.0025000f
+#define LSM303DLHC_COMP_SENS_Z_4P7GA 0.0028169f
+#define LSM303DLHC_COMP_SENS_Z_5P6GA 0.0033898f
+#define LSM303DLHC_COMP_SENS_Z_8P1GA 0.0048780f
+
+#define LSM303DLHC_COMP_BIAS 0.0f
+/** @} */
+
+/**
+ * @name LSM303DLHC communication interfaces related bit masks
+ * @{
+ */
+#define LSM303DLHC_DI_MASK 0xFF
+#define LSM303DLHC_DI(n) (1 << n)
+#define LSM303DLHC_AD_MASK 0x7F
+#define LSM303DLHC_AD(n) (1 << n)
+#define LSM303DLHC_MS (1 << 7)
+/** @} */
+
+/**
+ * @name LSM303DLHC register addresses
+ * @{
+ */
+#define LSM303DLHC_AD_ACC_CTRL_REG1 0x20
+#define LSM303DLHC_AD_ACC_CTRL_REG2 0x21
+#define LSM303DLHC_AD_ACC_CTRL_REG3 0x22
+#define LSM303DLHC_AD_ACC_CTRL_REG4 0x23
+#define LSM303DLHC_AD_ACC_CTRL_REG5 0x24
+#define LSM303DLHC_AD_ACC_CTRL_REG6 0x25
+#define LSM303DLHC_AD_ACC_REFERENCE 0x26
+#define LSM303DLHC_AD_ACC_STATUS_REG 0x27
+#define LSM303DLHC_AD_ACC_OUT_X_L 0x28
+#define LSM303DLHC_AD_ACC_OUT_X_H 0x29
+#define LSM303DLHC_AD_ACC_OUT_Y_L 0x2A
+#define LSM303DLHC_AD_ACC_OUT_Y_H 0x2B
+#define LSM303DLHC_AD_ACC_OUT_Z_L 0x2C
+#define LSM303DLHC_AD_ACC_OUT_Z_H 0x2D
+#define LSM303DLHC_AD_ACC_FIFO_CTRL_REG 0x2E
+#define LSM303DLHC_AD_ACC_FIFO_SRC_REG 0x2F
+#define LSM303DLHC_AD_ACC_INT1_CFG 0x30
+#define LSM303DLHC_AD_ACC_INT1_SRC 0x31
+#define LSM303DLHC_AD_ACC_INT1_THS 0x32
+#define LSM303DLHC_AD_ACC_INT1_DURATION 0x33
+#define LSM303DLHC_AD_ACC_INT2_CFG 0x34
+#define LSM303DLHC_AD_ACC_INT2_SRC 0x35
+#define LSM303DLHC_AD_ACC_INT2_THS 0x36
+#define LSM303DLHC_AD_ACC_INT2_DURATION 0x37
+#define LSM303DLHC_AD_ACC_CLICK_CFG 0x38
+#define LSM303DLHC_AD_ACC_CLICK_SRC 0x39
+#define LSM303DLHC_AD_ACC_CLICK_THS 0x3A
+#define LSM303DLHC_AD_ACC_TIME_LIMIT 0x3B
+#define LSM303DLHC_AD_ACC_TIME_LATENCY 0x3C
+#define LSM303DLHC_AD_ACC_TIME_WINDOW 0x3D
+#define LSM303DLHC_AD_COMP_CRA_REG 0x00
+#define LSM303DLHC_AD_COMP_CRB_REG 0x01
+#define LSM303DLHC_AD_COMP_MR_REG 0x02
+#define LSM303DLHC_AD_COMP_OUT_X_H 0x03
+#define LSM303DLHC_AD_COMP_OUT_X_L 0x04
+#define LSM303DLHC_AD_COMP_OUT_Z_H 0x05
+#define LSM303DLHC_AD_COMP_OUT_Z_L 0x06
+#define LSM303DLHC_AD_COMP_OUT_Y_H 0x07
+#define LSM303DLHC_AD_COMP_OUT_Y_L 0x08
+#define LSM303DLHC_AD_COMP_SR_REG 0x09
+#define LSM303DLHC_AD_COMP_IRA_REG 0x0A
+#define LSM303DLHC_AD_COMP_IRB_REG 0x0B
+#define LSM303DLHC_AD_COMP_IRC_REG 0x0C
+#define LSM303DLHC_AD_COMP_TEMP_OUT_H 0x31
+#define LSM303DLHC_AD_COMP_TEMP_OUT_L 0x32
+/** @} */
+
+/**
+ * @name LSM303DLHC_CTRL_REG1_A register bits definitions
+ * @{
+ */
+#define LSM303DLHC_CTRL_REG1_A_MASK 0xFF
+#define LSM303DLHC_CTRL_REG1_A_XEN (1 << 0)
+#define LSM303DLHC_CTRL_REG1_A_YEN (1 << 1)
+#define LSM303DLHC_CTRL_REG1_A_ZEN (1 << 2)
+#define LSM303DLHC_CTRL_REG1_A_LPEN (1 << 3)
+#define LSM303DLHC_CTRL_REG1_A_ODR0 (1 << 4)
+#define LSM303DLHC_CTRL_REG1_A_ODR1 (1 << 5)
+#define LSM303DLHC_CTRL_REG1_A_ODR2 (1 << 6)
+#define LSM303DLHC_CTRL_REG1_A_ODR3 (1 << 7)
+/** @} */
+
+/**
+ * @name LSM303DLHC_CTRL_REG2_A register bits definitions
+ * @{
+ */
+#define LSM303DLHC_CTRL_REG2_A_MASK 0xFF
+#define LSM303DLHC_CTRL_REG2_A_HPIS1 (1 << 0)
+#define LSM303DLHC_CTRL_REG2_A_HPIS2 (1 << 1)
+#define LSM303DLHC_CTRL_REG2_A_HPCLICK (1 << 2)
+#define LSM303DLHC_CTRL_REG2_A_FDS (1 << 3)
+#define LSM303DLHC_CTRL_REG2_A_HPCF1 (1 << 4)
+#define LSM303DLHC_CTRL_REG2_A_HPCF2 (1 << 5)
+#define LSM303DLHC_CTRL_REG2_A_HPM0 (1 << 6)
+#define LSM303DLHC_CTRL_REG2_A_HPM1 (1 << 7)
+/** @} */
+
+/**
+ * @name LSM303DLHC_CTRL_REG3_A register bits definitions
+ * @{
+ */
+#define LSM303DLHC_CTRL_REG3_A_MASK 0xFD
+#define LSM303DLHC_CTRL_REG3_A_I1_OVERRUN (1 << 1)
+#define LSM303DLHC_CTRL_REG3_A_I1_WTM (1 << 2)
+#define LSM303DLHC_CTRL_REG3_A_I1_DRDY2 (1 << 3)
+#define LSM303DLHC_CTRL_REG3_A_I1_DRDY1 (1 << 4)
+#define LSM303DLHC_CTRL_REG3_A_I1_AOI2 (1 << 5)
+#define LSM303DLHC_CTRL_REG3_A_I1_AOI1 (1 << 6)
+#define LSM303DLHC_CTRL_REG3_A_I1_CLICK (1 << 7)
+/** @} */
+
+/**
+ * @name LSM303DLHC_CTRL_REG4_A register bits definitions
+ * @{
+ */
+#define LSM303DLHC_CTRL_REG4_A_MASK 0xF9
+#define LSM303DLHC_CTRL_REG4_A_SIM (1 << 0)
+#define LSM303DLHC_CTRL_REG4_A_HR (1 << 3)
+#define LSM303DLHC_CTRL_REG4_A_FS_MASK 0x30
+#define LSM303DLHC_CTRL_REG4_A_FS0 (1 << 4)
+#define LSM303DLHC_CTRL_REG4_A_FS1 (1 << 5)
+#define LSM303DLHC_CTRL_REG4_A_BLE (1 << 6)
+#define LSM303DLHC_CTRL_REG4_A_BDU (1 << 7)
+/** @} */
+
+/**
+ * @name LSM303DLHC_CTRL_REG5_A register bits definitions
+ * @{
+ */
+#define LSM303DLHC_CTRL_REG5_A_MASK 0xCF
+#define LSM303DLHC_CTRL_REG5_A_D4D_INT2 (1 << 0)
+#define LSM303DLHC_CTRL_REG5_A_LIR_INT2 (1 << 1)
+#define LSM303DLHC_CTRL_REG5_A_D4D_INT1 (1 << 2)
+#define LSM303DLHC_CTRL_REG5_A_LIR_INT1 (1 << 3)
+#define LSM303DLHC_CTRL_REG5_A_FIFO_EN (1 << 6)
+#define LSM303DLHC_CTRL_REG5_A_BOOT (1 << 7)
+/** @} */
+
+/**
+ * @name LSM303DLHC_CTRL_REG6_A register bits definitions
+ * @{
+ */
+#define LSM303DLHC_CTRL_REG6_A_MASK 0xFA
+#define LSM303DLHC_CTRL_REG6_A_H_LACTIVE (1 << 1)
+#define LSM303DLHC_CTRL_REG6_A_P2_ACT (1 << 3)
+#define LSM303DLHC_CTRL_REG6_A_BOOT_I1 (1 << 4)
+#define LSM303DLHC_CTRL_REG6_A_I2_INT2 (1 << 5)
+#define LSM303DLHC_CTRL_REG6_A_I2_INT1 (1 << 6)
+#define LSM303DLHC_CTRL_REG6_A_I2_CLICKEN (1 << 7)
+/** @} */
+
+/**
+ * @name LSM303DLHC_CRA_REG_M register bits definitions
+ * @{
+ */
+#define LSM303DLHC_CRA_REG_M_MASK 0x9C
+#define LSM303DLHC_CRA_REG_M_DO0 (1 << 2)
+#define LSM303DLHC_CRA_REG_M_DO1 (1 << 3)
+#define LSM303DLHC_CRA_REG_M_DO2 (1 << 4)
+#define LSM303DLHC_CRA_REG_M_TEMP_EN (1 << 7)
+/** @} */
+
+/**
+ * @name LSM303DLHC_CRB_REG_M register bits definitions
+ * @{
+ */
+#define LSM303DLHC_CRB_REG_M_MASK 0xE0
+#define LSM303DLHC_CRB_REG_M_GN_MASK 0xE0
+#define LSM303DLHC_CRB_REG_M_GN0 (1 << 5)
+#define LSM303DLHC_CRB_REG_M_GN1 (1 << 6)
+#define LSM303DLHC_CRB_REG_M_GN2 (1 << 7)
+
+/**
+ * @name LSM303DLHC_CRB_REG_M register bits definitions
+ * @{
+ */
+#define LSM303DLHC_MR_REG_M_MASK 0x03
+#define LSM303DLHC_MR_REG_M_MD0 (1 << 0)
+#define LSM303DLHC_MR_REG_M_MD1 (1 << 1)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief LSM303DLHC SPI interface switch.
+ * @details If set to @p TRUE the support for SPI is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(LSM303DLHC_USE_SPI) || defined(__DOXYGEN__)
+#define LSM303DLHC_USE_SPI FALSE
+#endif
+
+/**
+ * @brief LSM303DLHC shared SPI switch.
+ * @details If set to @p TRUE the device acquires SPI bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(LSM303DLHC_SHARED_SPI) || defined(__DOXYGEN__)
+#define LSM303DLHC_SHARED_SPI FALSE
+#endif
+
+/**
+ * @brief LSM303DLHC I2C interface switch.
+ * @details If set to @p TRUE the support for I2C is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(LSM303DLHC_USE_I2C) || defined(__DOXYGEN__)
+#define LSM303DLHC_USE_I2C TRUE
+#endif
+
+/**
+ * @brief LSM303DLHC shared I2C switch.
+ * @details If set to @p TRUE the device acquires I2C bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(LSM303DLHC_SHARED_I2C) || defined(__DOXYGEN__)
+#define LSM303DLHC_SHARED_I2C FALSE
+#endif
+
+/**
+ * @brief LSM303DLHC advanced configurations switch.
+ * @details If set to @p TRUE more configurations are available.
+ * @note The default is @p FALSE.
+ */
+#if !defined(LSM303DLHC_USE_ADVANCED) || defined(__DOXYGEN__)
+#define LSM303DLHC_USE_ADVANCED FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !(LSM303DLHC_USE_SPI ^ LSM303DLHC_USE_I2C)
+#error "LSM303DLHC_USE_SPI and LSM303DLHC_USE_I2C cannot be both true or both false"
+#endif
+
+#if LSM303DLHC_USE_SPI && !HAL_USE_SPI
+#error "LSM303DLHC_USE_SPI requires HAL_USE_SPI"
+#endif
+
+#if LSM303DLHC_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION
+#error "LSM303DLHC_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
+#endif
+
+#if LSM303DLHC_USE_I2C && !HAL_USE_I2C
+#error "LSM303DLHC_USE_I2C requires HAL_USE_I2C"
+#endif
+
+#if LSM303DLHC_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
+#error "LSM303DLHC_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
+#endif
+
+/*
+ * CHTODO: Add support for LSM303DLHC over SPI.
+ */
+#if LSM303DLHC_USE_SPI
+#error "LSM303DLHC over SPI still not supported"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @name LSM303DLHC accelerometer subsystem data structures and types.
+ * @{
+ */
+/**
+ * @brief Structure representing a LSM303DLHC driver.
+ */
+typedef struct LSM303DLHCDriver LSM303DLHCDriver;
+
+/**
+ * @brief LSM303DLHC accelerometer subsystem full scale.
+ */
+typedef enum {
+ LSM303DLHC_ACC_FS_2G = 0x00, /**< Full scale �2g. */
+ LSM303DLHC_ACC_FS_4G = 0x10, /**< Full scale �4g. */
+ LSM303DLHC_ACC_FS_8G = 0x20, /**< Full scale �8g. */
+ LSM303DLHC_ACC_FS_16G = 0x30 /**< Full scale �16g. */
+} lsm303dlhc_acc_fs_t;
+
+/**
+ * @brief LSM303DLHC accelerometer subsystem output data rate.
+ */
+typedef enum {
+ LSM303DLHC_ACC_ODR_PD = 0x00, /**< Power down */
+ LSM303DLHC_ACC_ODR_1Hz = 0x10, /**< ODR 1 Hz */
+ LSM303DLHC_ACC_ODR_10Hz = 0x20, /**< ODR 10 Hz */
+ LSM303DLHC_ACC_ODR_25Hz = 0x30, /**< ODR 25 Hz */
+ LSM303DLHC_ACC_ODR_50Hz = 0x40, /**< ODR 50 Hz */
+ LSM303DLHC_ACC_ODR_100Hz = 0x50, /**< ODR 100 Hz */
+ LSM303DLHC_ACC_ODR_200Hz = 0x60, /**< ODR 200 Hz */
+ LSM303DLHC_ACC_ODR_400Hz = 0x70, /**< ODR 400 Hz */
+ LSM303DLHC_ACC_ODR_1620Hz = 0x80, /**< ODR 1620 Hz (LP only) */
+ LSM303DLHC_ACC_ODR_1344Hz = 0x90 /**< ODR 1344 Hz or 5376 Hz in LP */
+} lsm303dlhc_acc_odr_t;
+
+/**
+ * @brief LSM303DLHC accelerometer subsystem axes enabling.
+ */
+typedef enum {
+ LSM303DLHC_ACC_AE_DISABLED = 0x00,/**< All axes disabled. */
+ LSM303DLHC_ACC_AE_X = 0x01, /**< Only X-axis enabled. */
+ LSM303DLHC_ACC_AE_Y = 0x02, /**< Only Y-axis enabled. */
+ LSM303DLHC_ACC_AE_XY = 0x03, /**< X and Y axes enabled. */
+ LSM303DLHC_ACC_AE_Z = 0x04, /**< Only Z-axis enabled. */
+ LSM303DLHC_ACC_AE_XZ = 0x05, /**< X and Z axes enabled. */
+ LSM303DLHC_ACC_AE_YZ = 0x06, /**< Y and Z axes enabled. */
+ LSM303DLHC_ACC_AE_XYZ = 0x07 /**< All axes enabled. */
+} lsm303dlhc_acc_ae_t;
+
+/**
+ * @brief LSM303DLHC accelerometer subsystem low power mode.
+ */
+typedef enum {
+ LSM303DLHC_ACC_LP_DISABLED = 0x00,/**< Low power mode disabled. */
+ LSM303DLHC_ACC_LP_ENABLED = 0x40 /**< Low power mode enabled. */
+} lsm303dlhc_acc_lp_t;
+
+/**
+ * @brief LSM303DLHC accelerometer subsystem high resolution mode.
+ */
+typedef enum {
+ LSM303DLHC_ACC_HR_DISABLED = 0x00,/**< High resolution mode disabled. */
+ LSM303DLHC_ACC_HR_ENABLED = 0x08 /**< High resolution mode enabled. */
+} lsm303dlhc_acc_hr_t;
+
+/**
+ * @brief LSM303DLHC accelerometer subsystem block data update.
+ */
+typedef enum {
+ LSM303DLHC_ACC_BDU_CONT = 0x00, /**< Continuous update */
+ LSM303DLHC_ACC_BDU_BLOCK = 0x80 /**< Update blocked */
+} lsm303dlhc_acc_bdu_t;
+
+/**
+ * @brief LSM303DLHC accelerometer endianness.
+ */
+typedef enum {
+ LSM303DLHC_ACC_END_LITTLE = 0x00, /**< Little Endian */
+ LSM303DLHC_ACC_END_BIG = 0x40 /**< Big Endian */
+} lsm303dlhc_acc_end_t;
+
+/**
+ * @name LSM303DLHC compass subsystem data structures and types.
+ * @{
+ */
+/**
+ * @brief LSM303DLHC compass subsystem full scale.
+ */
+typedef enum {
+ LSM303DLHC_COMP_FS_1P3GA = 0x20, /**< Full scale �1.3 Gauss */
+ LSM303DLHC_COMP_FS_1P9GA = 0x40, /**< Full scale �1.9 Gauss */
+ LSM303DLHC_COMP_FS_2P5GA = 0x60, /**< Full scale �2.5 Gauss */
+ LSM303DLHC_COMP_FS_4P0GA = 0x80, /**< Full scale �4.0 Gauss */
+ LSM303DLHC_COMP_FS_4P7GA = 0xA0, /**< Full scale �4.7 Gauss */
+ LSM303DLHC_COMP_FS_5P6GA = 0xC0, /**< Full scale �5.6 Gauss */
+ LSM303DLHC_COMP_FS_8P1GA = 0xE0 /**< Full scale �8.1 Gauss */
+} lsm303dlhc_comp_fs_t;
+
+/**
+ * @brief LSM303DLHC compass subsystem output data rate.
+ */
+typedef enum {
+ LSM303DLHC_COMP_ODR_0P75HZ = 0x00,/**< ODR 0.75 Hz */
+ LSM303DLHC_COMP_ODR_1P5HZ = 0x04, /**< ODR 1.5 Hz */
+ LSM303DLHC_COMP_ODR_3P0HZ = 0x08, /**< ODR 3 Hz */
+ LSM303DLHC_COMP_ODR_7P5HZ = 0x0C, /**< ODR 7.5 Hz */
+ LSM303DLHC_COMP_ODR_15HZ = 0x10, /**< ODR 15 Hz */
+ LSM303DLHC_COMP_ODR_30HZ = 0x14, /**< ODR 30 Hz */
+ LSM303DLHC_COMP_ODR_75HZ = 0x18, /**< ODR 75 Hz */
+ LSM303DLHC_COMP_ODR_220HZ = 0x1C /**< ODR 220 Hz */
+} lsm303dlhc_comp_odr_t;
+
+/**
+ * @brief LSM303DLHC compass subsystem working mode.
+ */
+typedef enum {
+ LSM303DLHC_COMP_MD_CONT = 0x00, /**< Continuous-Conversion Mode */
+ LSM303DLHC_COMP_MD_BLOCK = 0x01, /**< Single-Conversion Mode */
+ LSM303DLHC_COMP_MD_SLEEP = 0x02 /**< Sleep Mode */
+} lsm303dlhc_comp_md_t;
+
+/**
+ * @name LSM303DLHC main system data structures and types.
+ * @{
+ */
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ LSM303DLHC_UNINIT = 0, /**< Not initialized. */
+ LSM303DLHC_STOP = 1, /**< Stopped. */
+ LSM303DLHC_READY = 2, /**< Ready. */
+} lsm303dlhc_state_t;
+
+/**
+ * @brief LSM303DLHC configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief I2C driver associated to this LSM303DLHC.
+ */
+ I2CDriver *i2cp;
+ /**
+ * @brief I2C configuration associated to this LSM303DLHC.
+ */
+ const I2CConfig *i2ccfg;
+ /**
+ * @brief LSM303DLHC accelerometer subsystem initial sensitivity.
+ */
+ float *accsensitivity;
+ /**
+ * @brief LSM303DLHC accelerometer subsystem initial bias.
+ */
+ float *accbias;
+ /**
+ * @brief LSM303DLHC accelerometer subsystem initial full scale.
+ */
+ lsm303dlhc_acc_fs_t accfullscale;
+ /**
+ * @brief LSM303DLHC accelerometer subsystem output data rate.
+ */
+ lsm303dlhc_acc_odr_t accoutdatarate;
+#if LSM303DLHC_USE_ADVANCED || defined(__DOXYGEN__)
+ /**
+ * @brief LSM303DLHC accelerometer subsystem low power mode.
+ */
+ lsm303dlhc_acc_lp_t acclowpower;
+ /**
+ * @brief LSM303DLHC accelerometer subsystem high resolution mode.
+ */
+ lsm303dlhc_acc_hr_t acchighresmode;
+ /**
+ * @brief LSM303DLHC accelerometer subsystem block data update.
+ */
+ lsm303dlhc_acc_bdu_t accblockdataupdate;
+ /**
+ * @brief LSM303DLHC accelerometer endianness.
+ */
+ lsm303dlhc_acc_end_t accendianess;
+#endif
+ /**
+ * @brief LSM303DLHC compass initial sensitivity.
+ */
+ float *compsensitivity;
+ /**
+ * @brief LSM303DLHC compass initial bias.
+ */
+ float *compbias;
+ /**
+ * @brief LSM303DLHC compass subsystem initial full scale.
+ */
+ lsm303dlhc_comp_fs_t compfullscale;
+ /**
+ * @brief LSM303DLHC compass subsystem output data rate.
+ */
+ lsm303dlhc_comp_odr_t compoutputdatarate;
+#if LSM303DLHC_USE_ADVANCED || defined(__DOXYGEN__)
+ /**
+ * @brief LSM303DLHC compass subsystem working mode.
+ */
+ lsm303dlhc_comp_md_t compmode;
+#endif
+} LSM303DLHCConfig;
+
+/**
+ * @brief @p LSM303DLHC specific methods.
+ */
+#define _lsm303dlhc_methods_alone \
+ /* Change full scale value of LSM303DLHC accelerometer subsystem.*/ \
+ msg_t (*acc_set_full_scale)(LSM303DLHCDriver *devp, \
+ lsm303dlhc_acc_fs_t fs); \
+ /* Change full scale value of LSM303DLHC compass subsystem.*/ \
+ msg_t (*comp_set_full_scale)(LSM303DLHCDriver *devp, \
+ lsm303dlhc_comp_fs_t fs); \
+
+/**
+ * @brief @p LSM303DLHC specific methods with inherited ones.
+ */
+#define _lsm303dlhc_methods \
+ _base_object_methods \
+ _lsm303dlhc_methods_alone
+
+/**
+ * @extends BaseObjectVMT
+ *
+ * @brief @p LSM303DLHC virtual methods table.
+ */
+struct LSM303DLHCVMT {
+ _lsm303dlhc_methods
+};
+
+/**
+ * @brief @p LSM303DLHCDriver specific data.
+ */
+#define _lsm303dlhc_data \
+ _base_sensor_data \
+ /* Driver state.*/ \
+ lsm303dlhc_state_t state; \
+ /* Current configuration data.*/ \
+ const LSM303DLHCConfig *config; \
+ /* Accelerometer subsystem axes number.*/ \
+ size_t accaxes; \
+ /* Accelerometer subsystem current sensitivity.*/ \
+ float accsensitivity[LSM303DLHC_ACC_NUMBER_OF_AXES]; \
+ /* Accelerometer subsystem current bias .*/ \
+ float accbias[LSM303DLHC_ACC_NUMBER_OF_AXES]; \
+ /* Accelerometer subsystem current full scale value.*/ \
+ float accfullscale; \
+ /* Compass subsystem axes number.*/ \
+ size_t compaxes; \
+ /* Compass subsystem current sensitivity.*/ \
+ float compsensitivity[LSM303DLHC_COMP_NUMBER_OF_AXES];\
+ /* Compass subsystem current bias.*/ \
+ float compbias[LSM303DLHC_COMP_NUMBER_OF_AXES]; \
+ /* Compass subsystem current full scale value.*/ \
+ float compfullscale;
+
+/**
+ * @brief LSM303DLHC 6-axis accelerometer/compass class.
+ */
+struct LSM303DLHCDriver {
+ /** @brief Virtual Methods Table.*/
+ const struct LSM303DLHCVMT *vmt;
+ /** @brief Base accelerometer interface.*/
+ BaseAccelerometer acc_if;
+ /** @brief Base compass interface.*/
+ BaseCompass comp_if;
+ _lsm303dlhc_data
+};
+/** @} */
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Return the number of axes of the BaseAccelerometer.
+ *
+ * @param[in] devp pointer to @p LSM303DLHCDriver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define lsm303dlhcAccelerometerGetAxesNumber(devp) \
+ accelerometerGetAxesNumber(&((devp)->acc_if))
+
+/**
+ * @brief Retrieves raw data from the BaseAccelerometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LSM303DLHCDriver.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lsm303dlhcAccelerometerReadRaw(devp, axes) \
+ accelerometerReadRaw(&((devp)->acc_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseAccelerometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as milli-G.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LSM303DLHCDriver.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lsm303dlhcAccelerometerReadCooked(devp, axes) \
+ accelerometerReadCooked(&((devp)->acc_if), axes)
+
+/**
+ * @brief Set bias values for the BaseAccelerometer.
+ * @note Bias must be expressed as milli-G.
+ * @note The bias buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LSM303DLHCDriver.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm303dlhcAccelerometerSetBias(devp, bp) \
+ accelerometerSetBias(&((devp)->acc_if), bp)
+
+/**
+ * @brief Reset bias values for the BaseAccelerometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] devp pointer to @p LSM303DLHCDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm303dlhcAccelerometerResetBias(devp) \
+ accelerometerResetBias(&((devp)->acc_if))
+
+/**
+ * @brief Set sensitivity values for the BaseAccelerometer.
+ * @note Sensitivity must be expressed as milli-G/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LSM303DLHCDriver.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm303dlhcAccelerometerSetSensitivity(devp, sp) \
+ accelerometerSetSensitivity(&((devp)->acc_if), sp)
+
+/**
+ * @brief Reset sensitivity values for the BaseAccelerometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] devp pointer to @p LSM303DLHCDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lsm303dlhcAccelerometerResetSensitivity(devp) \
+ accelerometerResetSensitivity(&((devp)->acc_if))
+
+/**
+ * @brief Changes the LSM303DLHCDriver accelerometer fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p LSM303DLHCDriver.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lsm303dlhcAccelerometerSetFullScale(devp, fs) \
+ (devp)->vmt->acc_set_full_scale(devp, fs)
+
+/**
+ * @brief Return the number of axes of the BaseCompass.
+ *
+ * @param[in] devp pointer to @p LSM303DLHCDriver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define lsm303dlhcCompassGetAxesNumber(devp) \
+ compassGetAxesNumber(&((devp)->comp_if))
+
+/**
+ * @brief Retrieves raw data from the BaseCompass.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] devp pointer to @p BaseCompass interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lsm303dlhcCompassReadRaw(devp, axes) \
+ compassReadRaw(&((devp)->comp_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseCompass.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as G.
+ * @note The axes array must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] devp pointer to @p BaseCompass interface.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lsm303dlhcCompassReadCooked(devp, axes) \
+ compassReadCooked(&((devp)->comp_if), axes)
+
+/**
+ * @brief Set bias values for the BaseCompass.
+ * @note Bias must be expressed as G.
+ * @note The bias buffer must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] devp pointer to @p BaseCompass interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm303dlhcCompassSetBias(devp, bp) \
+ compassSetBias(&((devp)->comp_if), bp)
+
+/**
+ * @brief Reset bias values for the BaseCompass.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] devp pointer to @p LSM303DLHCDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm303dlhcCompassResetBias(devp) \
+ compassResetBias(&((devp)->comp_if))
+
+/**
+ * @brief Set sensitivity values for the BaseCompass.
+ * @note Sensitivity must be expressed as G/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseCompass axes number.
+ *
+ * @param[in] devp pointer to @p LSM303DLHCDriver.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm303dlhcCompassSetSensitivity(devp, sp) \
+ compassSetSensitivity(&((devp)->comp_if), sp)
+
+/**
+ * @brief Reset sensitivity values for the BaseCompass.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] devp pointer to @p LSM303DLHCDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lsm303dlhcCompassResetSensitivity(devp) \
+ compassResetSensitivity(&((devp)->comp_if))
+
+/**
+ * @brief Changes the LSM303DLHCDriver compass fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p LSM303DLHCDriver.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lsm303dlhcCompassSetFullScale(devp, fs) \
+ (devp)->vmt->comp_set_full_scale(devp, fs)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void lsm303dlhcObjectInit(LSM303DLHCDriver *devp);
+ void lsm303dlhcStart(LSM303DLHCDriver *devp, const LSM303DLHCConfig *config);
+ void lsm303dlhcStop(LSM303DLHCDriver *devp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LSM303DLHC_H_ */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lsm303dlhc.mk b/ChibiOS_20.3.2/os/ex/devices/ST/lsm303dlhc.mk
new file mode 100644
index 0000000..4e192aa
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lsm303dlhc.mk
@@ -0,0 +1,10 @@
+# List of all the LSM303DLHC device files.
+LSM303DLHCSRC := $(CHIBIOS)/os/ex/devices/ST/lsm303dlhc.c
+
+# Required include directories
+LSM303DLHCINC := $(CHIBIOS)/os/ex/include \
+ $(CHIBIOS)/os/ex/devices/ST
+
+# Shared variables
+ALLCSRC += $(LSM303DLHCSRC)
+ALLINC += $(LSM303DLHCINC)
\ No newline at end of file
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lsm6ds0.c b/ChibiOS_20.3.2/os/ex/devices/ST/lsm6ds0.c
new file mode 100644
index 0000000..4f1b9ec
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lsm6ds0.c
@@ -0,0 +1,1109 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file lsm6ds0.c
+ * @brief LSM6DS0 MEMS interface module code.
+ *
+ * @addtogroup LSM6DS0
+ * @ingroup EX_ST
+ * @{
+ */
+
+#include "hal.h"
+#include "lsm6ds0.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#if (LSM6DS0_USE_I2C) || defined(__DOXYGEN__)
+/**
+ * @brief Reads registers value using I2C.
+ * @pre The I2C interface must be initialized and the driver started.
+ * @note IF_ADD_INC bit must be 1 in CTRL_REG8
+ *
+ * @param[in] i2cp pointer to the I2C interface
+ * @param[in] sad slave address without R bit
+ * @param[in] reg first sub-register address
+ * @param[out] rxbuf pointer to an output buffer
+ * @param[in] n number of consecutive register to read
+ * @return the operation status.
+ * @notapi
+ */
+msg_t lsm6ds0I2CReadRegister(I2CDriver *i2cp, lsm6ds0_sad_t sad, uint8_t reg,
+ uint8_t* rxbuf, size_t n) {
+
+ return i2cMasterTransmitTimeout(i2cp, sad, ®, 1, rxbuf, n,
+ TIME_INFINITE);
+}
+
+/**
+ * @brief Writes a value into a register using I2C.
+ * @pre The I2C interface must be initialized and the driver started.
+ *
+ * @param[in] i2cp pointer to the I2C interface
+ * @param[in] sad slave address without R bit
+ * @param[in] txbuf buffer containing sub-address value in first position
+ * and values to write
+ * @param[in] n size of txbuf less one (not considering the first
+ * element)
+ * @return the operation status.
+ * @notapi
+ */
+#define lsm6ds0I2CWriteRegister(i2cp, sad, txbuf, n) \
+ i2cMasterTransmitTimeout(i2cp, sad, txbuf, n + 1, NULL, 0, \
+ TIME_INFINITE)
+#endif /* LSM6DS0_USE_I2C */
+
+/**
+ * @brief Return the number of axes of the BaseAccelerometer.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ *
+ * @return the number of axes.
+ */
+static size_t acc_get_axes_number(void *ip) {
+ (void)ip;
+
+ return LSM6DS0_ACC_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Retrieves raw data from the BaseAccelerometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t acc_read_raw(void *ip, int32_t axes[]) {
+ LSM6DS0Driver* devp;
+ uint8_t buff [LSM6DS0_ACC_NUMBER_OF_AXES * 2], i;
+ int16_t tmp;
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DS0Driver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM6DS0_READY),
+ "acc_read_raw(), invalid state");
+#if LSM6DS0_USE_I2C
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "acc_read_raw(), channel not ready");
+
+#if LSM6DS0_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LSM6DS0_SHARED_I2C */
+
+ msg = lsm6ds0I2CReadRegister(devp->config->i2cp, devp->config->slaveaddress,
+ LSM6DS0_AD_OUT_X_L_XL, buff,
+ LSM6DS0_ACC_NUMBER_OF_AXES * 2);
+
+#if LSM6DS0_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DS0_SHARED_I2C */
+#endif /* LSM6DS0_USE_I2C */
+ if(msg == MSG_OK)
+ for(i = 0; i < LSM6DS0_ACC_NUMBER_OF_AXES; i++) {
+ tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
+ axes[i] = (int32_t)tmp;
+ }
+ return msg;
+}
+
+/**
+ * @brief Retrieves cooked data from the BaseAccelerometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as milli-G.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t acc_read_cooked(void *ip, float axes[]) {
+ LSM6DS0Driver* devp;
+ uint32_t i;
+ int32_t raw[LSM6DS0_ACC_NUMBER_OF_AXES];
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DS0Driver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM6DS0_READY),
+ "acc_read_cooked(), invalid state");
+
+ msg = acc_read_raw(ip, raw);
+ for(i = 0; i < LSM6DS0_ACC_NUMBER_OF_AXES; i++) {
+ axes[i] = (raw[i] * devp->accsensitivity[i]) - devp->accbias[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Set bias values for the BaseAccelerometer.
+ * @note Bias must be expressed as milli-G.
+ * @note The bias buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t acc_set_bias(void *ip, float *bp) {
+ LSM6DS0Driver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (bp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DS0Driver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM6DS0_READY),
+ "acc_set_bias(), invalid state");
+
+ for(i = 0; i < LSM6DS0_ACC_NUMBER_OF_AXES; i++) {
+ devp->accbias[i] = bp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset bias values for the BaseAccelerometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t acc_reset_bias(void *ip) {
+ LSM6DS0Driver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DS0Driver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM6DS0_READY),
+ "acc_reset_bias(), invalid state");
+
+ for(i = 0; i < LSM6DS0_ACC_NUMBER_OF_AXES; i++)
+ devp->accbias[i] = LSM6DS0_ACC_BIAS;
+ return msg;
+}
+
+/**
+ * @brief Set sensitivity values for the BaseAccelerometer.
+ * @note Sensitivity must be expressed as milli-G/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t acc_set_sensivity(void *ip, float *sp) {
+ LSM6DS0Driver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DS0Driver*, (BaseAccelerometer*)ip);
+
+ osalDbgCheck((ip != NULL) && (sp != NULL));
+
+ osalDbgAssert((devp->state == LSM6DS0_READY),
+ "acc_set_sensivity(), invalid state");
+
+ for(i = 0; i < LSM6DS0_ACC_NUMBER_OF_AXES; i++) {
+ devp->accsensitivity[i] = sp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset sensitivity values for the BaseAccelerometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t acc_reset_sensivity(void *ip) {
+ LSM6DS0Driver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DS0Driver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM6DS0_READY),
+ "acc_reset_sensivity(), invalid state");
+
+ if(devp->config->accfullscale == LSM6DS0_ACC_FS_2G)
+ for(i = 0; i < LSM6DS0_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LSM6DS0_ACC_SENS_2G;
+ else if(devp->config->accfullscale == LSM6DS0_ACC_FS_4G)
+ for(i = 0; i < LSM6DS0_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LSM6DS0_ACC_SENS_4G;
+ else if(devp->config->accfullscale == LSM6DS0_ACC_FS_8G)
+ for(i = 0; i < LSM6DS0_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LSM6DS0_ACC_SENS_8G;
+ else if(devp->config->accfullscale == LSM6DS0_ACC_FS_16G)
+ for(i = 0; i < LSM6DS0_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LSM6DS0_ACC_SENS_16G;
+ else {
+ osalDbgAssert(FALSE, "reset_sensivity(), accelerometer full scale issue");
+ msg = MSG_RESET;
+ }
+ return msg;
+}
+
+/**
+ * @brief Changes the LSM6DS0Driver accelerometer fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p LSM6DS0Driver interface.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t acc_set_full_scale(LSM6DS0Driver *devp, lsm6ds0_acc_fs_t fs) {
+ float newfs, scale;
+ uint8_t i, buff[2];
+ msg_t msg;
+
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LSM6DS0_READY),
+ "acc_set_full_scale(), invalid state");
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "acc_set_full_scale(), channel not ready");
+
+ /* Computing new fullscale value.*/
+ if(fs == LSM6DS0_ACC_FS_2G) {
+ newfs = LSM6DS0_ACC_2G;
+ }
+ else if(fs == LSM6DS0_ACC_FS_4G) {
+ newfs = LSM6DS0_ACC_4G;
+ }
+ else if(fs == LSM6DS0_ACC_FS_8G) {
+ newfs = LSM6DS0_ACC_8G;
+ }
+ else if(fs == LSM6DS0_ACC_FS_16G) {
+ newfs = LSM6DS0_ACC_16G;
+ }
+ else {
+ msg = MSG_RESET;
+ return msg;
+ }
+
+ if(newfs != devp->accfullscale) {
+ /* Computing scale value.*/
+ scale = newfs / devp->accfullscale;
+ devp->accfullscale = newfs;
+
+#if LSM6DS0_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LSM6DS0_SHARED_I2C */
+
+ /* Updating register.*/
+ msg = lsm6ds0I2CReadRegister(devp->config->i2cp,
+ devp->config->slaveaddress,
+ LSM6DS0_AD_CTRL_REG6_XL, &buff[1], 1);
+
+#if LSM6DS0_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DS0_SHARED_I2C */
+
+ if(msg != MSG_OK)
+ return msg;
+
+ buff[1] &= ~(LSM6DS0_CTRL_REG6_XL_FS_MASK);
+ buff[1] |= fs;
+ buff[0] = LSM6DS0_AD_CTRL_REG6_XL;
+
+#if LSM6DS0_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+#endif /* LSM6DS0_SHARED_I2C */
+
+ msg = lsm6ds0I2CWriteRegister(devp->config->i2cp,
+ devp->config->slaveaddress, buff, 1);
+
+#if LSM6DS0_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DS0_SHARED_I2C */
+
+ if(msg != MSG_OK)
+ return msg;
+
+ /* Scaling sensitivity and bias. Re-calibration is suggested anyway.*/
+ for(i = 0; i < LSM6DS0_ACC_NUMBER_OF_AXES; i++) {
+ devp->accsensitivity[i] *= scale;
+ devp->accbias[i] *= scale;
+ }
+ }
+ return msg;
+}
+
+/**
+ * @brief Return the number of axes of the BaseGyroscope.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ *
+ * @return the number of axes.
+ */
+static size_t gyro_get_axes_number(void *ip) {
+ (void)ip;
+
+ return LSM6DS0_GYRO_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Retrieves raw data from the BaseGyroscope.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseGyroscope axes number.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t gyro_read_raw(void *ip, int32_t axes[LSM6DS0_GYRO_NUMBER_OF_AXES]) {
+ LSM6DS0Driver* devp;
+ int16_t tmp;
+ uint8_t i, buff [2 * LSM6DS0_GYRO_NUMBER_OF_AXES];
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DS0Driver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == LSM6DS0_READY),
+ "gyro_read_raw(), invalid state");
+#if LSM6DS0_USE_I2C
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "gyro_read_raw(), channel not ready");
+
+#if LSM6DS0_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LSM6DS0_SHARED_I2C */
+
+ msg = lsm6ds0I2CReadRegister(devp->config->i2cp, devp->config->slaveaddress,
+ LSM6DS0_AD_OUT_X_L_G, buff,
+ LSM6DS0_GYRO_NUMBER_OF_AXES * 2);
+
+#if LSM6DS0_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DS0_SHARED_I2C */
+#endif /* LSM6DS0_USE_I2C */
+
+ for(i = 0; i < LSM6DS0_GYRO_NUMBER_OF_AXES; i++) {
+ tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
+ axes[i] = (int32_t)tmp;
+ }
+ return msg;
+}
+
+/**
+ * @brief Retrieves cooked data from the BaseGyroscope.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as DPS.
+ * @note The axes array must be at least the same size of the
+ * BaseGyroscope axes number.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t gyro_read_cooked(void *ip, float axes[]) {
+ LSM6DS0Driver* devp;
+ uint32_t i;
+ int32_t raw[LSM6DS0_GYRO_NUMBER_OF_AXES];
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DS0Driver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == LSM6DS0_READY),
+ "gyro_read_cooked(), invalid state");
+
+ msg = gyro_read_raw(ip, raw);
+ for(i = 0; i < LSM6DS0_GYRO_NUMBER_OF_AXES; i++){
+ axes[i] = (raw[i] * devp->gyrosensitivity[i]) - devp->gyrobias[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Samples bias values for the BaseGyroscope.
+ * @note The LSM6DS0 shall not be moved during the whole procedure.
+ * @note After this function internal bias is automatically updated.
+ * @note The behavior of this function depends on @p LSM6DS0_BIAS_ACQ_TIMES
+ * and @p LSM6DS0_BIAS_SETTLING_US.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t gyro_sample_bias(void *ip) {
+ LSM6DS0Driver* devp;
+ uint32_t i, j;
+ int32_t raw[LSM6DS0_GYRO_NUMBER_OF_AXES];
+ int32_t buff[LSM6DS0_GYRO_NUMBER_OF_AXES] = {0, 0, 0};
+ msg_t msg;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DS0Driver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == LSM6DS0_READY),
+ "gyro_sample_bias(), invalid state");
+#if LSM6DS0_USE_I2C
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "gyro_sample_bias(), channel not ready");
+#endif
+
+ for(i = 0; i < LSM6DS0_GYRO_BIAS_ACQ_TIMES; i++){
+ msg = gyro_read_raw(ip, raw);
+ if(msg != MSG_OK)
+ return msg;
+ for(j = 0; j < LSM6DS0_GYRO_NUMBER_OF_AXES; j++){
+ buff[j] += raw[j];
+ }
+ osalThreadSleepMicroseconds(LSM6DS0_GYRO_BIAS_SETTLING_US);
+ }
+
+ for(i = 0; i < LSM6DS0_GYRO_NUMBER_OF_AXES; i++){
+ devp->gyrobias[i] = (buff[i] / LSM6DS0_GYRO_BIAS_ACQ_TIMES);
+ devp->gyrobias[i] *= devp->gyrosensitivity[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Set bias values for the BaseGyroscope.
+ * @note Bias must be expressed as DPS.
+ * @note The bias buffer must be at least the same size of the BaseGyroscope
+ * axes number.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t gyro_set_bias(void *ip, float *bp) {
+ LSM6DS0Driver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (bp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DS0Driver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == LSM6DS0_READY),
+ "gyro_set_bias(), invalid state");
+
+ for(i = 0; i < LSM6DS0_GYRO_NUMBER_OF_AXES; i++) {
+ devp->gyrobias[i] = bp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset bias values for the BaseGyroscope.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t gyro_reset_bias(void *ip) {
+ LSM6DS0Driver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DS0Driver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == LSM6DS0_READY),
+ "gyro_reset_bias(), invalid state");
+
+ for(i = 0; i < LSM6DS0_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrobias[i] = LSM6DS0_GYRO_BIAS;
+ return msg;
+}
+
+/**
+ * @brief Set sensitivity values for the BaseGyroscope.
+ * @note Sensitivity must be expressed as DPS/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseGyroscope axes number.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t gyro_set_sensivity(void *ip, float *sp) {
+ LSM6DS0Driver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (sp !=NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DS0Driver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == LSM6DS0_READY),
+ "gyro_set_sensivity(), invalid state");
+
+ for(i = 0; i < LSM6DS0_GYRO_NUMBER_OF_AXES; i++) {
+ devp->gyrosensitivity[i] = sp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset sensitivity values for the BaseGyroscope.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t gyro_reset_sensivity(void *ip) {
+ LSM6DS0Driver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DS0Driver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == LSM6DS0_READY),
+ "gyro_reset_sensivity(), invalid state");
+
+ if(devp->config->gyrofullscale == LSM6DS0_GYRO_FS_245DPS)
+ for(i = 0; i < LSM6DS0_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrosensitivity[i] = LSM6DS0_GYRO_SENS_245DPS;
+ else if(devp->config->gyrofullscale == LSM6DS0_GYRO_FS_500DPS)
+ for(i = 0; i < LSM6DS0_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrosensitivity[i] = LSM6DS0_GYRO_SENS_500DPS;
+ else if(devp->config->gyrofullscale == LSM6DS0_GYRO_FS_2000DPS)
+ for(i = 0; i < LSM6DS0_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrosensitivity[i] = LSM6DS0_GYRO_SENS_2000DPS;
+ else {
+ osalDbgAssert(FALSE, "gyro_reset_sensivity(), full scale issue");
+ return MSG_RESET;
+ }
+ return msg;
+}
+
+/**
+ * @brief Changes the LSM6DS0Driver gyroscope fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p BaseGyroscope interface.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t gyro_set_full_scale(LSM6DS0Driver *devp, lsm6ds0_gyro_fs_t fs) {
+ float newfs, scale;
+ uint8_t i, buff[2];
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LSM6DS0_READY),
+ "gyro_set_full_scale(), invalid state");
+#if LSM6DS0_USE_I2C
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "gyro_set_full_scale(), channel not ready");
+#endif
+
+ if(fs == LSM6DS0_GYRO_FS_245DPS) {
+ newfs = LSM6DS0_GYRO_245DPS;
+ }
+ else if(fs == LSM6DS0_GYRO_FS_500DPS) {
+ newfs = LSM6DS0_GYRO_500DPS;
+ }
+ else if(fs == LSM6DS0_GYRO_FS_2000DPS) {
+ newfs = LSM6DS0_GYRO_2000DPS;
+ }
+ else {
+ return MSG_RESET;
+ }
+
+ if(newfs != devp->gyrofullscale) {
+ scale = newfs / devp->gyrofullscale;
+ devp->gyrofullscale = newfs;
+
+#if LSM6DS0_USE_I2C
+#if LSM6DS0_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LSM6DS0_SHARED_I2C */
+
+ /* Updating register.*/
+ msg = lsm6ds0I2CReadRegister(devp->config->i2cp,
+ devp->config->slaveaddress,
+ LSM6DS0_AD_CTRL_REG1_G, &buff[1], 1);
+
+#if LSM6DS0_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DS0_SHARED_I2C */
+#endif /* LSM6DS0_USE_I2C */
+
+ buff[1] &= ~(LSM6DS0_CTRL_REG1_G_FS_MASK);
+ buff[1] |= fs;
+ buff[0] = LSM6DS0_AD_CTRL_REG1_G;
+
+#if LSM6DS0_USE_I2C
+#if LSM6DS0_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LSM6DS0_SHARED_I2C */
+
+ lsm6ds0I2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
+ buff, 1);
+
+#if LSM6DS0_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DS0_SHARED_I2C */
+#endif /* LSM6DS0_USE_I2C */
+
+ /* Scaling sensitivity and bias. Re-calibration is suggested anyway. */
+ for(i = 0; i < LSM6DS0_GYRO_NUMBER_OF_AXES; i++) {
+ devp->gyrosensitivity[i] *= scale;
+ devp->gyrobias[i] *= scale;
+ }
+ }
+ return msg;
+}
+
+static const struct LSM6DS0VMT vmt_device = {
+ (size_t)0,
+ acc_set_full_scale, gyro_set_full_scale
+};
+
+static const struct BaseAccelerometerVMT vmt_accelerometer = {
+ sizeof(struct LSM6DS0VMT*),
+ acc_get_axes_number, acc_read_raw, acc_read_cooked,
+ acc_set_bias, acc_reset_bias, acc_set_sensivity, acc_reset_sensivity
+};
+
+static const struct BaseGyroscopeVMT vmt_gyroscope = {
+ sizeof(struct LSM6DS0VMT*) + sizeof(BaseAccelerometer),
+ gyro_get_axes_number, gyro_read_raw, gyro_read_cooked,
+ gyro_sample_bias, gyro_set_bias, gyro_reset_bias,
+ gyro_set_sensivity, gyro_reset_sensivity
+};
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes an instance.
+ *
+ * @param[out] devp pointer to the @p LSM6DS0Driver object
+ *
+ * @init
+ */
+void lsm6ds0ObjectInit(LSM6DS0Driver *devp) {
+ devp->vmt = &vmt_device;
+ devp->acc_if.vmt = &vmt_accelerometer;
+ devp->gyro_if.vmt = &vmt_gyroscope;
+
+ devp->config = NULL;
+
+ devp->accaxes = LSM6DS0_ACC_NUMBER_OF_AXES;
+ devp->gyroaxes = LSM6DS0_GYRO_NUMBER_OF_AXES;
+
+ devp->state = LSM6DS0_STOP;
+}
+
+/**
+ * @brief Configures and activates LSM6DS0 Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p LSM6DS0Driver object
+ * @param[in] config pointer to the @p LSM6DS0Config object
+ *
+ * @api
+ */
+void lsm6ds0Start(LSM6DS0Driver *devp, const LSM6DS0Config *config) {
+ uint32_t i;
+ uint8_t cr[5];
+ osalDbgCheck((devp != NULL) && (config != NULL));
+
+ osalDbgAssert((devp->state == LSM6DS0_STOP) ||
+ (devp->state == LSM6DS0_READY),
+ "lsm6ds0Start(), invalid state");
+
+ devp->config = config;
+
+ /* Configuring common registers.*/
+
+ /* Control register 8 configuration block.*/
+ {
+ cr[0] = LSM6DS0_AD_CTRL_REG8;
+ cr[1] = LSM6DS0_CTRL_REG8_IF_ADD_INC;
+#if LSM6DS0_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[1] |= devp->config->endianness | devp->config->blockdataupdate;
+#endif
+ }
+#if LSM6DS0_USE_I2C
+#if LSM6DS0_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+#endif /* LSM6DS0_SHARED_I2C */
+
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+ lsm6ds0I2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
+ cr, 1);
+
+#if LSM6DS0_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DS0_SHARED_I2C */
+#endif /* LSM6DS0_USE_I2C */
+
+ /* Configuring Accelerometer subsystem.*/
+ /* Multiple write starting address.*/
+ cr[0] = LSM6DS0_AD_CTRL_REG5_XL;
+ /* Control register 5 configuration block.*/
+ {
+ cr[1] = LSM6DS0_CTRL_REG5_XL_XEN_XL | LSM6DS0_CTRL_REG5_XL_YEN_XL |
+ LSM6DS0_CTRL_REG5_XL_ZEN_XL;
+#if LSM6DS0_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[1] |= devp->config->accdecmode;
+#endif
+ }
+
+ /* Control register 6 configuration block.*/
+ {
+ cr[2] = devp->config->accoutdatarate |
+ devp->config->accfullscale;
+ }
+
+#if LSM6DS0_USE_I2C
+#if LSM6DS0_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+#endif /* LSM6DS0_SHARED_I2C */
+
+ lsm6ds0I2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
+ cr, 2);
+
+#if LSM6DS0_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DS0_SHARED_I2C */
+#endif /* LSM6DS0_USE_I2C */
+
+ /* Storing sensitivity according to user settings */
+ if(devp->config->accfullscale == LSM6DS0_ACC_FS_2G) {
+ for(i = 0; i < LSM6DS0_ACC_NUMBER_OF_AXES; i++) {
+ if(devp->config->accsensitivity == NULL)
+ devp->accsensitivity[i] = LSM6DS0_ACC_SENS_2G;
+ else
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ devp->accfullscale = LSM6DS0_ACC_2G;
+ }
+ else if(devp->config->accfullscale == LSM6DS0_ACC_FS_4G) {
+ for(i = 0; i < LSM6DS0_ACC_NUMBER_OF_AXES; i++) {
+ if(devp->config->accsensitivity == NULL)
+ devp->accsensitivity[i] = LSM6DS0_ACC_SENS_4G;
+ else
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ devp->accfullscale = LSM6DS0_ACC_4G;
+ }
+ else if(devp->config->accfullscale == LSM6DS0_ACC_FS_8G) {
+ for(i = 0; i < LSM6DS0_ACC_NUMBER_OF_AXES; i++) {
+ if(devp->config->accsensitivity == NULL)
+ devp->accsensitivity[i] = LSM6DS0_ACC_SENS_8G;
+ else
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ devp->accfullscale = LSM6DS0_ACC_8G;
+ }
+ else if(devp->config->accfullscale == LSM6DS0_ACC_FS_16G) {
+ for(i = 0; i < LSM6DS0_ACC_NUMBER_OF_AXES; i++) {
+ if(devp->config->accsensitivity == NULL)
+ devp->accsensitivity[i] = LSM6DS0_ACC_SENS_16G;
+ else
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ devp->accfullscale = LSM6DS0_ACC_16G;
+ }
+ else
+ osalDbgAssert(FALSE, "lsm6ds0Start(), accelerometer full scale issue");
+
+ /* Storing bias information */
+ if(devp->config->accbias != NULL)
+ for(i = 0; i < LSM6DS0_ACC_NUMBER_OF_AXES; i++)
+ devp->accbias[i] = devp->config->accbias[i];
+ else
+ for(i = 0; i < LSM6DS0_ACC_NUMBER_OF_AXES; i++)
+ devp->accbias[i] = LSM6DS0_ACC_BIAS;
+
+ /* Configuring Gyroscope subsystem.*/
+ /* Multiple write starting address.*/
+ cr[0] = LSM6DS0_AD_CTRL_REG1_G;
+
+ /* Control register 1 configuration block.*/
+ {
+ cr[1] = devp->config->gyrofullscale |
+ devp->config->gyrooutdatarate;
+ }
+
+ /* Control register 2 configuration block.*/
+ {
+ cr[2] = 0;
+#if LSM6DS0_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[2] |= devp->config->gyrooutsel;
+#endif
+ }
+
+ /* Control register 3 configuration block.*/
+ {
+ cr[3] = 0;
+#if LSM6DS0_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[3] |= devp->config->gyrohpfenable |
+ devp->config->gyrolowmodecfg |
+ devp->config->gyrohpcfg;
+#endif
+ }
+
+ /* Control register 4 configuration block.*/
+ {
+ cr[4] = LSM6DS0_CTRL_REG4_XEN_G | LSM6DS0_CTRL_REG4_YEN_G |
+ LSM6DS0_CTRL_REG4_ZEN_G;
+ }
+#if LSM6DS0_USE_I2C
+#if LSM6DS0_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+#endif /* LSM6DS0_SHARED_I2C */
+
+ lsm6ds0I2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
+ cr, 4);
+
+#if LSM6DS0_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DS0_SHARED_I2C */
+#endif /* LSM6DS0_USE_I2C */
+
+ cr[0] = LSM6DS0_AD_CTRL_REG9;
+ /* Control register 9 configuration block.*/
+ {
+ cr[1] = 0;
+ }
+#if LSM6DS0_USE_I2C
+#if LSM6DS0_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+#endif /* LSM6DS0_SHARED_I2C */
+
+ lsm6ds0I2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
+ cr, 1);
+
+#if LSM6DS0_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DS0_SHARED_I2C */
+#endif /* LSM6DS0_USE_I2C */
+
+ if(devp->config->gyrofullscale == LSM6DS0_GYRO_FS_245DPS) {
+ for(i = 0; i < LSM6DS0_GYRO_NUMBER_OF_AXES; i++) {
+ if(devp->config->gyrosensitivity == NULL)
+ devp->gyrosensitivity[i] = LSM6DS0_GYRO_SENS_245DPS;
+ else
+ devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
+ }
+ devp->gyrofullscale = LSM6DS0_GYRO_245DPS;
+ }
+ else if(devp->config->gyrofullscale == LSM6DS0_GYRO_FS_500DPS) {
+ for(i = 0; i < LSM6DS0_GYRO_NUMBER_OF_AXES; i++) {
+ if(devp->config->gyrosensitivity == NULL)
+ devp->gyrosensitivity[i] = LSM6DS0_GYRO_SENS_500DPS;
+ else
+ devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
+ }
+ devp->gyrofullscale = LSM6DS0_GYRO_500DPS;
+ }
+ else if(devp->config->gyrofullscale == LSM6DS0_GYRO_FS_2000DPS) {
+ for(i = 0; i < LSM6DS0_GYRO_NUMBER_OF_AXES; i++) {
+ if(devp->config->gyrosensitivity == NULL)
+ devp->gyrosensitivity[i] = LSM6DS0_GYRO_SENS_2000DPS;
+ else
+ devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
+ }
+ devp->gyrofullscale = LSM6DS0_GYRO_2000DPS;
+ }
+ else
+ osalDbgAssert(FALSE, "lsm6ds0Start(), gyroscope full scale issue");
+
+ /* Storing bias information */
+ if(devp->config->gyrobias != NULL)
+ for(i = 0; i < LSM6DS0_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrobias[i] = devp->config->gyrobias[i];
+ else
+ for(i = 0; i < LSM6DS0_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrobias[i] = LSM6DS0_GYRO_BIAS;
+
+ /* This is the MEMS transient recovery time */
+ osalThreadSleepMilliseconds(5);
+
+ devp->state = LSM6DS0_READY;
+}
+
+/**
+ * @brief Deactivates the LSM6DS0 Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p LSM6DS0Driver object
+ *
+ * @api
+ */
+void lsm6ds0Stop(LSM6DS0Driver *devp) {
+ uint8_t cr[2];
+
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LSM6DS0_STOP) || (devp->state == LSM6DS0_READY),
+ "lsm6ds0Stop(), invalid state");
+
+ if (devp->state == LSM6DS0_READY) {
+#if LSM6DS0_USE_I2C
+#if LSM6DS0_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+#endif /* LSM6DS0_SHARED_I2C */
+
+ /* Disabling accelerometer.*/
+ cr[0] = LSM6DS0_AD_CTRL_REG6_XL;
+ cr[1] = 0;
+ lsm6ds0I2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
+ cr, 1);
+
+ /* Disabling gyroscope.*/
+ cr[0] = LSM6DS0_AD_CTRL_REG9;
+ cr[1] = LSM6DS0_CTRL_REG9_SLEEP_G;
+ lsm6ds0I2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
+ cr, 1);
+
+ i2cStop(devp->config->i2cp);
+#if LSM6DS0_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DS0_SHARED_I2C */
+#endif /* LSM6DS0_USE_I2C */
+ }
+ devp->state = LSM6DS0_STOP;
+}
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lsm6ds0.h b/ChibiOS_20.3.2/os/ex/devices/ST/lsm6ds0.h
new file mode 100644
index 0000000..d3afc9e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lsm6ds0.h
@@ -0,0 +1,1034 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file lsm6ds0.h
+ * @brief LSM6DS0 MEMS interface module header.
+ *
+ * @addtogroup LSM6DS0
+ * @ingroup EX_ST
+ * @{
+ */
+#ifndef _LSM6DS0_H_
+#define _LSM6DS0_H_
+
+#include "ex_accelerometer.h"
+#include "ex_gyroscope.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Version identification
+ * @{
+ */
+/**
+ * @brief LSM6DS0 driver version string.
+ */
+#define EX_LSM6DS0_VERSION "1.1.2"
+
+/**
+ * @brief LSM6DS0 driver version major number.
+ */
+#define EX_LSM6DS0_MAJOR 1
+
+/**
+ * @brief LSM6DS0 driver version minor number.
+ */
+#define EX_LSM6DS0_MINOR 1
+
+/**
+ * @brief LSM6DS0 driver version patch number.
+ */
+#define EX_LSM6DS0_PATCH 2
+/** @} */
+
+/**
+ * @brief LSM6DS0 accelerometer subsystem characteristics.
+ * @note Sensitivity is expressed as milli-G/LSB whereas
+ * 1 milli-G = 0.00980665 m/s^2.
+ * @note Bias is expressed as milli-G.
+ *
+ * @{
+ */
+#define LSM6DS0_ACC_NUMBER_OF_AXES 3U
+
+#define LSM6DS0_ACC_2G 2.0f
+#define LSM6DS0_ACC_4G 4.0f
+#define LSM6DS0_ACC_8G 8.0f
+#define LSM6DS0_ACC_16G 16.0f
+
+#define LSM6DS0_ACC_SENS_2G 0.061f
+#define LSM6DS0_ACC_SENS_4G 0.122f
+#define LSM6DS0_ACC_SENS_8G 0.244f
+#define LSM6DS0_ACC_SENS_16G 0.732f
+
+#define LSM6DS0_ACC_BIAS 0.0f
+/** @} */
+
+/**
+ * @brief L3GD20 gyroscope system characteristics.
+ * @note Sensitivity is expressed as DPS/LSB whereas DPS stand for Degree
+ * per second [�/s].
+ * @note Bias is expressed as DPS.
+ *
+ * @{
+ */
+#define LSM6DS0_GYRO_NUMBER_OF_AXES 3U
+
+#define LSM6DS0_GYRO_245DPS 245.0f
+#define LSM6DS0_GYRO_500DPS 500.0f
+#define LSM6DS0_GYRO_2000DPS 2000.0f
+
+#define LSM6DS0_GYRO_SENS_245DPS 0.00875f
+#define LSM6DS0_GYRO_SENS_500DPS 0.01750f
+#define LSM6DS0_GYRO_SENS_2000DPS 0.07000f
+
+#define LSM6DS0_GYRO_BIAS 0.0f
+/** @} */
+
+/**
+ * @name LSM6DS0 communication interfaces related bit masks
+ * @{
+ */
+#define LSM6DS0_DI_MASK 0xFF
+#define LSM6DS0_DI(n) (1 << n)
+#define LSM6DS0_AD_MASK 0x7F
+#define LSM6DS0_AD(n) (1 << n)
+#define LSM6DS0_MS (1 << 7)
+/** @} */
+
+/**
+ * @name LSM6DS0 register addresses
+ * @{
+ */
+#define LSM6DS0_AD_ACT_THS 0x04
+#define LSM6DS0_AD_ACT_DUR 0x05
+#define LSM6DS0_AD_INT_GEN_CFG_XL 0x06
+#define LSM6DS0_AD_INT_GEN_THS_X_XL 0x07
+#define LSM6DS0_AD_INT_GEN_THS_Y_XL 0x08
+#define LSM6DS0_AD_INT_GEN_THS_Z_XL 0x09
+#define LSM6DS0_AD_INT_GEN_DUR_XL 0x0A
+#define LSM6DS0_AD_REFERENCE_G 0x0B
+#define LSM6DS0_AD_INT_CTRL 0x0C
+#define LSM6DS0_AD_WHO_AM_I 0x0F
+#define LSM6DS0_AD_CTRL_REG1_G 0x10
+#define LSM6DS0_AD_CTRL_REG2_G 0x11
+#define LSM6DS0_AD_CTRL_REG3_G 0x12
+#define LSM6DS0_AD_ORIENT_CFG_G 0x13
+#define LSM6DS0_AD_INT_GEN_SRC_G 0x14
+#define LSM6DS0_AD_OUT_TEMP_L 0x15
+#define LSM6DS0_AD_OUT_TEMP_H 0x16
+#define LSM6DS0_AD_STATUS_REG1 0x17
+#define LSM6DS0_AD_OUT_X_L_G 0x18
+#define LSM6DS0_AD_OUT_X_H_G 0x19
+#define LSM6DS0_AD_OUT_Y_L_G 0x1A
+#define LSM6DS0_AD_OUT_Y_H_G 0x1B
+#define LSM6DS0_AD_OUT_Z_L_G 0x1C
+#define LSM6DS0_AD_OUT_Z_H_G 0x1D
+#define LSM6DS0_AD_CTRL_REG4 0x1E
+#define LSM6DS0_AD_CTRL_REG5_XL 0x1F
+#define LSM6DS0_AD_CTRL_REG6_XL 0x20
+#define LSM6DS0_AD_CTRL_REG7_XL 0x21
+#define LSM6DS0_AD_CTRL_REG8 0x22
+#define LSM6DS0_AD_CTRL_REG9 0x23
+#define LSM6DS0_AD_CTRL_REG10 0x24
+#define LSM6DS0_AD_INT_GEN_SRC_XL 0x26
+#define LSM6DS0_AD_STATUS_REG2 0x27
+#define LSM6DS0_AD_OUT_X_L_XL 0x28
+#define LSM6DS0_AD_OUT_X_H_XL 0x29
+#define LSM6DS0_AD_OUT_Y_L_XL 0x2A
+#define LSM6DS0_AD_OUT_Y_H_XL 0x2B
+#define LSM6DS0_AD_OUT_Z_L_XL 0x2C
+#define LSM6DS0_AD_OUT_Z_H_XL 0x2D
+#define LSM6DS0_AD_FIFO_CTRL 0x2E
+#define LSM6DS0_AD_FIFO_SRC 0x2F
+#define LSM6DS0_AD_INT_GEN_CFG_G 0x30
+#define LSM6DS0_AD_INT_GEN_THS_XH_G 0x31
+#define LSM6DS0_AD_INT_GEN_THS_XL_G 0x32
+#define LSM6DS0_AD_INT_GEN_THS_YH_G 0x33
+#define LSM6DS0_AD_INT_GEN_THS_YL_G 0x34
+#define LSM6DS0_AD_INT_GEN_THS_ZH_G 0x35
+#define LSM6DS0_AD_INT_GEN_THS_ZL_G 0x36
+#define LSM6DS0_AD_INT_GEN_DUR_G 0x37
+/** @} */
+
+/**
+ * @name LSM6DS0_AD_CTRL_REG1_G register bits definitions
+ * @{
+ */
+#define LSM6DS0_CTRL_REG1_G 0xFA
+#define LSM6DS0_CTRL_REG1_G_BW_G0 (1 << 0)
+#define LSM6DS0_CTRL_REG1_G_BW_G1 (1 << 1)
+#define LSM6DS0_CTRL_REG1_G_FS_MASK 0x1F
+#define LSM6DS0_CTRL_REG1_G_FS_G0 (1 << 3)
+#define LSM6DS0_CTRL_REG1_G_FS_G1 (1 << 4)
+#define LSM6DS0_CTRL_REG1_G_ODR_G0 (1 << 5)
+#define LSM6DS0_CTRL_REG1_G_ODR_G1 (1 << 6)
+#define LSM6DS0_CTRL_REG1_G_ODR_G2 (1 << 7)
+/** @} */
+
+/**
+ * @name LSM6DS0_AD_CTRL_REG2_G register bits definitions
+ * @{
+ */
+#define LSM6DS0_CTRL_REG2_G 0x0F
+#define LSM6DS0_CTRL_REG2_G_OUT_SEL0 (1 << 0)
+#define LSM6DS0_CTRL_REG2_G_OUT_SEL1 (1 << 1)
+#define LSM6DS0_CTRL_REG2_G_INT_SEL0 (1 << 2)
+#define LSM6DS0_CTRL_REG2_G_INT_SEL1 (1 << 3)
+/** @} */
+
+/**
+ * @name LSM6DS0_AD_CTRL_REG3_G register bits definitions
+ * @{
+ */
+#define LSM6DS0_CTRL_REG3_G 0x64
+#define LSM6DS0_CTRL_REG3_G_HP_CF0_G (1 << 0)
+#define LSM6DS0_CTRL_REG3_G_HP_CF1_G (1 << 1)
+#define LSM6DS0_CTRL_REG3_G_HP_CF2_G (1 << 2)
+#define LSM6DS0_CTRL_REG3_G_HP_CF3_G (1 << 3)
+#define LSM6DS0_CTRL_REG3_G_HP_EN (1 << 6)
+#define LSM6DS0_CTRL_REG3_G_LP_MODE (1 << 7)
+/** @} */
+
+/**
+ * @name LSM6DS0_AD_CTRL_REG4 register bits definitions
+ * @{
+ */
+#define LSM6DS0_CTRL_REG4 0x3A
+#define LSM6DS0_CTRL_REG4_4D_XL1 (1 << 0)
+#define LSM6DS0_CTRL_REG4_LIR_XL1 (1 << 1)
+#define LSM6DS0_CTRL_REG4_XEN_G (1 << 3)
+#define LSM6DS0_CTRL_REG4_YEN_G (1 << 4)
+#define LSM6DS0_CTRL_REG4_ZEN_G (1 << 5)
+/** @} */
+
+/**
+ * @name LSM6DS0_AD_CTRL_REG5_XL register bits definitions
+ * @{
+ */
+#define LSM6DS0_CTRL_REG5_XL 0xF8
+#define LSM6DS0_CTRL_REG5_XL_XEN_XL (1 << 3)
+#define LSM6DS0_CTRL_REG5_XL_YEN_XL (1 << 4)
+#define LSM6DS0_CTRL_REG5_XL_ZEN_XL (1 << 5)
+#define LSM6DS0_CTRL_REG5_XL_DEC0 (1 << 6)
+#define LSM6DS0_CTRL_REG5_XL_DEC1 (1 << 7)
+/** @} */
+
+/**
+ * @name LSM6DS0_AD_CTRL_REG6_XL register bits definitions
+ * @{
+ */
+#define LSM6DS0_CTRL_REG6_XL 0xFF
+#define LSM6DS0_CTRL_REG6_XL_BW_XL0 (1 << 0)
+#define LSM6DS0_CTRL_REG6_XL_BW_XL1 (1 << 1)
+#define LSM6DS0_CTRL_REG6_XL_BW_SCAL_ODR (1 << 2)
+#define LSM6DS0_CTRL_REG6_XL_FS_MASK 0x1F
+#define LSM6DS0_CTRL_REG6_XL_FS0_XL (1 << 3)
+#define LSM6DS0_CTRL_REG6_XL_FS1_XL (1 << 4)
+#define LSM6DS0_CTRL_REG6_XL_ODR_XL0 (1 << 5)
+#define LSM6DS0_CTRL_REG6_XL_ODR_XL1 (1 << 6)
+#define LSM6DS0_CTRL_REG6_XL_ODR_XL2 (1 << 7)
+/** @} */
+
+/**
+ * @name LSM6DS0_AD_CTRL_REG7_XL register bits definitions
+ * @{
+ */
+#define LSM6DS0_CTRL_REG7_XL 0xE5
+#define LSM6DS0_CTRL_REG7_XL_HPIS1 (1 << 0)
+#define LSM6DS0_CTRL_REG7_XL_FDS (1 << 2)
+#define LSM6DS0_CTRL_REG7_XL_DCF0 (1 << 5)
+#define LSM6DS0_CTRL_REG7_XL_DCF1 (1 << 6)
+#define LSM6DS0_CTRL_REG7_XL_HR (1 << 7)
+/** @} */
+
+/**
+ * @name LSM6DS0_AD_CTRL_REG8 register bits definitions
+ * @{
+ */
+#define LSM6DS0_CTRL_REG8 0xFF
+#define LSM6DS0_CTRL_REG8_SW_RESET (1 << 0)
+#define LSM6DS0_CTRL_REG8_BLE (1 << 1)
+#define LSM6DS0_CTRL_REG8_IF_ADD_INC (1 << 2)
+#define LSM6DS0_CTRL_REG8_SIM (1 << 3)
+#define LSM6DS0_CTRL_REG8_PP_OD (1 << 4)
+#define LSM6DS0_CTRL_REG8_H_LACTIVE (1 << 5)
+#define LSM6DS0_CTRL_REG8_BDU (1 << 6)
+#define LSM6DS0_CTRL_REG8_BOOT (1 << 7)
+/** @} */
+
+/**
+ * @name LSM6DS0_AD_CTRL_REG9 register bits definitions
+ * @{
+ */
+#define LSM6DS0_CTRL_REG9 0x5F
+#define LSM6DS0_CTRL_REG9_STOP_ON_FTH (1 << 0)
+#define LSM6DS0_CTRL_REG9_FIFO_EN (1 << 1)
+#define LSM6DS0_CTRL_REG9_I2C_DISABLE (1 << 2)
+#define LSM6DS0_CTRL_REG9_DRDY_MASK_BIT (1 << 3)
+#define LSM6DS0_CTRL_REG9_FIFO_TEMP_EN (1 << 4)
+#define LSM6DS0_CTRL_REG9_SLEEP_G (1 << 6)
+/** @} */
+
+/**
+ * @name LSM6DS0_AD_CTRL_REG10 register bits definitions
+ * @{
+ */
+#define LSM6DS0_CTRL_REG10 0x05
+#define LSM6DS0_CTRL_REG10_ST_XL (1 << 0)
+#define LSM6DS0_CTRL_REG10_ST_G (1 << 2)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief LSM6DS0 SPI interface switch.
+ * @details If set to @p TRUE the support for SPI is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(LSM6DS0_USE_SPI) || defined(__DOXYGEN__)
+#define LSM6DS0_USE_SPI FALSE
+#endif
+
+/**
+ * @brief LSM6DS0 shared SPI switch.
+ * @details If set to @p TRUE the device acquires SPI bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(LSM6DS0_SHARED_SPI) || defined(__DOXYGEN__)
+#define LSM6DS0_SHARED_SPI FALSE
+#endif
+
+/**
+ * @brief LSM6DS0 I2C interface switch.
+ * @details If set to @p TRUE the support for I2C is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(LSM6DS0_USE_I2C) || defined(__DOXYGEN__)
+#define LSM6DS0_USE_I2C TRUE
+#endif
+
+/**
+ * @brief LSM6DS0 shared I2C switch.
+ * @details If set to @p TRUE the device acquires I2C bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(LSM6DS0_SHARED_I2C) || defined(__DOXYGEN__)
+#define LSM6DS0_SHARED_I2C FALSE
+#endif
+
+/**
+ * @brief LSM6DS0 advanced configurations switch.
+ * @details If set to @p TRUE more configurations are available.
+ * @note The default is @p FALSE.
+ */
+#if !defined(LSM6DS0_USE_ADVANCED) || defined(__DOXYGEN__)
+#define LSM6DS0_USE_ADVANCED FALSE
+#endif
+
+/**
+ * @brief Number of acquisitions for gyroscope bias removal.
+ * @details This is the number of acquisitions performed to compute the
+ * bias. A repetition is required in order to remove noise.
+ */
+#if !defined(LSM6DS0_GYRO_BIAS_ACQ_TIMES) || defined(__DOXYGEN__)
+#define LSM6DS0_GYRO_BIAS_ACQ_TIMES 50
+#endif
+
+/**
+ * @brief Settling time for gyroscope bias removal.
+ * @details This is the time between each bias acquisition.
+ */
+#if !defined(LSM6DS0_GYRO_BIAS_SETTLING_US) || defined(__DOXYGEN__)
+#define LSM6DS0_GYRO_BIAS_SETTLING_US 5000
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !(LSM6DS0_USE_SPI ^ LSM6DS0_USE_I2C)
+#error "LSM6DS0_USE_SPI and LSM6DS0_USE_I2C cannot be both true or both false"
+#endif
+
+#if LSM6DS0_USE_SPI && !HAL_USE_SPI
+#error "LSM6DS0_USE_SPI requires HAL_USE_SPI"
+#endif
+
+#if LSM6DS0_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION
+#error "LSM6DS0_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
+#endif
+
+#if LSM6DS0_USE_I2C && !HAL_USE_I2C
+#error "LSM6DS0_USE_I2C requires HAL_USE_I2C"
+#endif
+
+#if LSM6DS0_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
+#error "LSM6DS0_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
+#endif
+
+/*
+ * CHTODO: Add support for LSM6DS0 over SPI.
+ */
+#if LSM6DS0_USE_SPI
+#error "LSM6DS0 over SPI still not supported"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @name LSM6DS0 data structures and types.
+ * @{
+ */
+/**
+ * @brief Structure representing a LSM6DS0 driver.
+ */
+typedef struct LSM6DS0Driver LSM6DS0Driver;
+
+/**
+ * @brief Accelerometer and Gyroscope Slave Address.
+ */
+typedef enum {
+ LSM6DS0_SAD_GND = 0x6A, /**< SAD pin connected to GND. */
+ LSM6DS0_SAD_VCC = 0x6B /**< SAD pin connected to VCC. */
+} lsm6ds0_sad_t;
+
+/**
+ * @brief LSM6DS0 accelerometer subsystem full scale.
+ */
+typedef enum {
+ LSM6DS0_ACC_FS_2G = 0x00, /**< Full scale �2g. */
+ LSM6DS0_ACC_FS_4G = 0x10, /**< Full scale �4g. */
+ LSM6DS0_ACC_FS_8G = 0x18, /**< Full scale �8g. */
+ LSM6DS0_ACC_FS_16G = 0x08 /**< Full scale �16g. */
+} lsm6ds0_acc_fs_t;
+
+/**
+ * @brief LSM6DS0 accelerometer subsystem output data rate.
+ */
+typedef enum {
+ LSM6DS0_ACC_ODR_PD = 0x00, /**< Power down */
+ LSM6DS0_ACC_ODR_10Hz = 0x20, /**< ODR 10 Hz */
+ LSM6DS0_ACC_ODR_50Hz = 0x40, /**< ODR 50 Hz */
+ LSM6DS0_ACC_ODR_119Hz = 0x60, /**< ODR 119 Hz */
+ LSM6DS0_ACC_ODR_238Hz = 0x80, /**< ODR 238 Hz */
+ LSM6DS0_ACC_ODR_476Hz = 0xA0, /**< ODR 476 Hz */
+ LSM6DS0_ACC_ODR_952Hz = 0xC0 /**< ODR 952 Hz */
+} lsm6ds0_acc_odr_t;
+
+/**
+ * @brief LSM6DS0 accelerometer subsystem decimation mode.
+ */
+typedef enum {
+ LSM6DS0_ACC_DEC_DISABLED = 0x00, /**< Decimation disabled. */
+ LSM6DS0_ACC_DEC_X2 = 0x40, /**< Output updated every 2 samples. */
+ LSM6DS0_ACC_DEC_X4 = 0x80, /**< Output updated every 4 samples. */
+ LSM6DS0_ACC_DEC_X8 = 0xC0 /**< Output updated every 8 samples. */
+} lsm6ds0_acc_dec_t;
+
+/**
+ * @brief LSM6DS0 gyroscope subsystem full scale.
+ */
+typedef enum {
+ LSM6DS0_GYRO_FS_245DPS = 0x00, /**< Full scale �245 degree per second */
+ LSM6DS0_GYRO_FS_500DPS = 0x08, /**< Full scale �500 degree per second */
+ LSM6DS0_GYRO_FS_2000DPS = 0x18 /**< Full scale �2000 degree per second */
+} lsm6ds0_gyro_fs_t;
+
+/**
+ * @brief LSM6DS0 gyroscope subsystem output data rate.
+ */
+typedef enum {
+ LSM6DS0_GYRO_ODR_PD = 0x00,
+ LSM6DS0_GYRO_ODR_95HZ_FC_25 = 0x10,
+ LSM6DS0_GYRO_ODR_14_9HZ_FC_5 = 0X20,
+ LSM6DS0_GYRO_ODR_59_5HZ_FC_16 = 0X40,
+ LSM6DS0_GYRO_ODR_119HZ_FC_14 = 0X60,
+ LSM6DS0_GYRO_ODR_119HZ_FC_31 = 0X61,
+ LSM6DS0_GYRO_ODR_238HZ_FC_14 = 0X80,
+ LSM6DS0_GYRO_ODR_238HZ_FC_29 = 0X81,
+ LSM6DS0_GYRO_ODR_238HZ_FC_63 = 0X82,
+ LSM6DS0_GYRO_ODR_238HZ_FC_78 = 0X83,
+ LSM6DS0_GYRO_ODR_476HZ_FC_21 = 0XA0,
+ LSM6DS0_GYRO_ODR_476HZ_FC_28 = 0XA1,
+ LSM6DS0_GYRO_ODR_476HZ_FC_57 = 0XA2,
+ LSM6DS0_GYRO_ODR_476HZ_FC_100 = 0XA3,
+ LSM6DS0_GYRO_ODR_952HZ_FC_33 = 0XC0,
+ LSM6DS0_GYRO_ODR_952HZ_FC_40 = 0XC1,
+ LSM6DS0_GYRO_ODR_952HZ_FC_58 = 0XC2,
+ LSM6DS0_GYRO_ODR_952HZ_FC_100 = 0XC3
+} lsm6ds0_gyro_odr_t;
+
+/**
+ * @brief LSM6DS0 gyroscope subsystem low mode configuration.
+ */
+typedef enum {
+ LSM6DS0_GYRO_LP_DISABLED = 0x00, /**< Low power mode disabled. */
+ LSM6DS0_GYRO_LP_ENABLED = 0x80 /**< Low power mode enabled. */
+} lsm6ds0_gyro_lp_t;
+
+/**
+ * @brief LSM6DS0 gyroscope subsystem output selection.
+ */
+typedef enum {
+ LSM6DS0_GYRO_OUT_SEL_0 = 0x00, /**< Low pass filter 1. */
+ LSM6DS0_GYRO_OUT_SEL_1 = 0x01, /**< High pass filter 1 if enabled. */
+ LSM6DS0_GYRO_OUT_SEL_2 = 0x02 /**< Low pass filter 2. */
+} lsm6ds0_gyro_out_sel_t;
+
+/**
+ * @brief LSM6DS0 gyroscope subsystem high pass filter.
+ */
+typedef enum {
+ LSM6DS0_GYRO_HP_DISABLED = 0x00, /**< High pass filter disabled. */
+ LSM6DS0_GYRO_HP_ENABLED = 0x40 /**< High pass filter enabled. */
+} lsm6ds0_gyro_hp_t;
+
+/**
+ * @brief LSM6DS0 gyroscope subsystem high pass filter configuration.
+ */
+typedef enum {
+ LSM6DS0_GYRO_HPCF_0 = 0x00, /**< Refer to table 48 of RM */
+ LSM6DS0_GYRO_HPCF_1 = 0x01,
+ LSM6DS0_GYRO_HPCF_2 = 0x02,
+ LSM6DS0_GYRO_HPCF_3 = 0x03,
+ LSM6DS0_GYRO_HPCF_4 = 0x04,
+ LSM6DS0_GYRO_HPCF_5 = 0x05,
+ LSM6DS0_GYRO_HPCF_6 = 0x06,
+ LSM6DS0_GYRO_HPCF_7 = 0x07,
+ LSM6DS0_GYRO_HPCF_8 = 0x08,
+ LSM6DS0_GYRO_HPCF_9 = 0x09
+} lsm6ds0_gyro_hpcf_t;
+
+/**
+ * @brief LSM6DS0 block data update.
+ */
+typedef enum {
+ LSM6DS0_BDU_CONTINUOUS = 0x00, /**< Block data continuously updated. */
+ LSM6DS0_BDU_BLOCKED = 0x40 /**< Block data updated after reading. */
+} lsm6ds0_bdu_t;
+
+/**
+ * @brief LSM6DS0 endianness.
+ */
+typedef enum {
+ LSM6DS0_END_LITTLE = 0x00, /**< Little endian. */
+ LSM6DS0_END_BIG = 0x20 /**< Big endian. */
+} lsm6ds0_end_t;
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ LSM6DS0_UNINIT = 0, /**< Not initialized. */
+ LSM6DS0_STOP = 1, /**< Stopped. */
+ LSM6DS0_READY = 2, /**< Ready. */
+} lsm6ds0_state_t;
+
+/**
+ * @brief LSM6DS0 configuration structure.
+ */
+typedef struct {
+#if (LSM6DS0_USE_SPI) || defined(__DOXYGEN__)
+ /**
+ * @brief SPI driver associated to this LSM6DS0.
+ */
+ SPIDriver *spip;
+ /**
+ * @brief SPI configuration associated to this LSM6DS0 accelerometer
+ * subsystem.
+ */
+ const SPIConfig *accspicfg;
+#endif /* LSM6DS0_USE_SPI */
+#if (LSM6DS0_USE_I2C) || defined(__DOXYGEN__)
+ /**
+ * @brief I2C driver associated to this LSM6DS0.
+ */
+ I2CDriver *i2cp;
+ /**
+ * @brief I2C configuration associated to this LSM6DS0 accelerometer
+ * subsystem.
+ */
+ const I2CConfig *i2ccfg;
+ /**
+ * @brief LSM6DS0 Slave Address
+ */
+ lsm6ds0_sad_t slaveaddress;
+#endif /* LSM6DS0_USE_I2C */
+ /**
+ * @brief LSM6DS0 accelerometer subsystem initial sensitivity.
+ */
+ float *accsensitivity;
+ /**
+ * @brief LSM6DS0 accelerometer subsystem initial bias.
+ */
+ float *accbias;
+ /**
+ * @brief LSM6DS0 accelerometer subsystem full scale.
+ */
+ lsm6ds0_acc_fs_t accfullscale;
+ /**
+ * @brief LSM6DS0 accelerometer subsystem output data rate.
+ */
+ lsm6ds0_acc_odr_t accoutdatarate;
+#if LSM6DS0_USE_ADVANCED || defined(__DOXYGEN__)
+ /**
+ * @brief LSM6DS0 accelerometer subsystem decimation mode.
+ */
+ lsm6ds0_acc_dec_t accdecmode;
+#endif /* LSM6DS0_USE_ADVANCED */
+ /**
+ * @brief LSM6DS0 gyroscope subsystem initial sensitivity.
+ */
+ float *gyrosensitivity;
+ /**
+ * @brief LSM6DS0 gyroscope subsystem initial bias.
+ */
+ float *gyrobias;
+ /**
+ * @brief LSM6DS0 gyroscope subsystem full scale.
+ */
+ lsm6ds0_gyro_fs_t gyrofullscale;
+ /**
+ * @brief LSM6DS0 gyroscope subsystem output data rate.
+ */
+ lsm6ds0_gyro_odr_t gyrooutdatarate;
+#if LSM6DS0_USE_ADVANCED || defined(__DOXYGEN__)
+ /**
+ * @brief LSM6DS0 gyroscope subsystem low mode configuration.
+ */
+ lsm6ds0_gyro_lp_t gyrolowmodecfg;
+ /**
+ * @brief LSM6DS0 gyroscope subsystem output selection.
+ */
+ lsm6ds0_gyro_out_sel_t gyrooutsel;
+ /**
+ * @brief LSM6DS0 gyroscope subsystem high pass filter.
+ */
+ lsm6ds0_gyro_hp_t gyrohpfenable;
+ /**
+ * @brief LSM6DS0 gyroscope subsystem high pass filter configuration.
+ */
+ lsm6ds0_gyro_hpcf_t gyrohpcfg;
+ /**
+ * @brief LSM6DS0 block data update
+ */
+ lsm6ds0_bdu_t blockdataupdate;
+ /**
+ * @brief LSM6DS0 endianness
+ */
+ lsm6ds0_end_t endianness;
+#endif /* LSM6DS0_USE_ADVANCED */
+} LSM6DS0Config;
+
+/**
+ * @brief @p LSM6DS0 specific methods.
+ */
+#define _lsm6ds0_methods_alone \
+ /* Change full scale value of LSM6DS0 accelerometer subsystem .*/ \
+ msg_t (*acc_set_full_scale)(LSM6DS0Driver *devp, lsm6ds0_acc_fs_t fs); \
+ /* Change full scale value of LSM6DS0 gyroscope subsystem .*/ \
+ msg_t (*gyro_set_full_scale)(LSM6DS0Driver *devp, lsm6ds0_gyro_fs_t fs);
+
+/**
+ * @brief @p LSM6DS0 specific methods with inherited ones.
+ */
+#define _lsm6ds0_methods \
+ _base_object_methods \
+ _lsm6ds0_methods_alone
+
+/**
+ * @extends BaseObjectVMT
+ *
+ * @brief @p LSM6DS0 virtual methods table.
+ */
+struct LSM6DS0VMT {
+ _lsm6ds0_methods
+};
+
+/**
+ * @brief @p LSM6DS0Driver specific data.
+ */
+#define _lsm6ds0_data \
+ _base_sensor_data \
+ /* Driver state.*/ \
+ lsm6ds0_state_t state; \
+ /* Current configuration data.*/ \
+ const LSM6DS0Config *config; \
+ /* Accelerometer subsystem axes number.*/ \
+ size_t accaxes; \
+ /* Accelerometer subsystem current sensitivity.*/ \
+ float accsensitivity[LSM6DS0_ACC_NUMBER_OF_AXES]; \
+ /* Accelerometer subsystem current bias .*/ \
+ float accbias[LSM6DS0_ACC_NUMBER_OF_AXES]; \
+ /* Accelerometer subsystem current full scale value.*/ \
+ float accfullscale; \
+ /* Gyroscope subsystem axes number.*/ \
+ size_t gyroaxes; \
+ /* Gyroscope subsystem current sensitivity.*/ \
+ float gyrosensitivity[LSM6DS0_GYRO_NUMBER_OF_AXES]; \
+ /* Gyroscope subsystem current Bias.*/ \
+ float gyrobias[LSM6DS0_GYRO_NUMBER_OF_AXES]; \
+ /* Gyroscope subsystem current full scale value.*/ \
+ float gyrofullscale;
+
+/**
+ * @brief LSM6DS0 6-axis accelerometer/gyroscope class.
+ */
+struct LSM6DS0Driver {
+ /** @brief Virtual Methods Table.*/
+ const struct LSM6DS0VMT *vmt;
+ /** @brief Base accelerometer interface.*/
+ BaseAccelerometer acc_if;
+ /** @brief Base gyroscope interface.*/
+ BaseGyroscope gyro_if;
+ _lsm6ds0_data
+};
+/** @} */
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Return the number of axes of the BaseAccelerometer.
+ *
+ * @param[in] devp pointer to @p LSM6DS0Driver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define lsm6ds0AccelerometerGetAxesNumber(devp) \
+ accelerometerGetAxesNumber(&((devp)->acc_if))
+
+/**
+ * @brief Retrieves raw data from the BaseAccelerometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LSM6DS0Driver.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lsm6ds0AccelerometerReadRaw(devp, axes) \
+ accelerometerReadRaw(&((devp)->acc_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseAccelerometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as milli-G.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LSM6DS0Driver.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lsm6ds0AccelerometerReadCooked(devp, axes) \
+ accelerometerReadCooked(&((devp)->acc_if), axes)
+
+/**
+ * @brief Set bias values for the BaseAccelerometer.
+ * @note Bias must be expressed as milli-G.
+ * @note The bias buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LSM6DS0Driver.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm6ds0AccelerometerSetBias(devp, bp) \
+ accelerometerSetBias(&((devp)->acc_if), bp)
+
+/**
+ * @brief Reset bias values for the BaseAccelerometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] devp pointer to @p LSM6DS0Driver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm6ds0AccelerometerResetBias(devp) \
+ accelerometerResetBias(&((devp)->acc_if))
+
+/**
+ * @brief Set sensitivity values for the BaseAccelerometer.
+ * @note Sensitivity must be expressed as milli-G/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LSM6DS0Driver.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm6ds0AccelerometerSetSensitivity(devp, sp) \
+ accelerometerSetSensitivity(&((devp)->acc_if), sp)
+
+/**
+ * @brief Reset sensitivity values for the BaseAccelerometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] devp pointer to @p LSM6DS0Driver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lsm6ds0AccelerometerResetSensitivity(devp) \
+ accelerometerResetSensitivity(&((devp)->acc_if))
+
+/**
+ * @brief Changes the LSM6DS0Driver accelerometer fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p LSM6DS0Driver.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lsm6ds0AccelerometerSetFullScale(devp, fs) \
+ (devp)->vmt->acc_set_full_scale(devp, fs)
+
+/**
+ * @brief Return the number of axes of the BaseGyroscope.
+ *
+ * @param[in] devp pointer to @p LSM6DS0Driver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define lsm6ds0GyroscopeGetAxesNumber(devp) \
+ gyroscopeGetAxesNumber(&((devp)->gyro_if))
+
+/**
+ * @brief Retrieves raw data from the BaseGyroscope.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseGyroscope axes number.
+ *
+ * @param[in] devp pointer to @p LSM6DS0Driver.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lsm6ds0GyroscopeReadRaw(devp, axes) \
+ gyroscopeReadRaw(&((devp)->gyro_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseGyroscope.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as DPS.
+ * @note The axes array must be at least the same size of the
+ * BaseGyroscope axes number.
+ *
+ * @param[in] devp pointer to @p LSM6DS0Driver.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lsm6ds0GyroscopeReadCooked(devp, axes) \
+ gyroscopeReadCooked(&((devp)->gyro_if), axes)
+
+/**
+ * @brief Samples bias values for the BaseGyroscope.
+ * @note The LSM6DS0 shall not be moved during the whole procedure.
+ * @note After this function internal bias is automatically updated.
+ * @note The behavior of this function depends on @p LSM6DS0_BIAS_ACQ_TIMES
+ * and @p LSM6DS0_BIAS_SETTLING_US.
+ *
+ * @param[in] devp pointer to @p LSM6DS0Driver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lsm6ds0GyroscopeSampleBias(devp) \
+ gyroscopeSampleBias(&((devp)->gyro_if))
+
+/**
+ * @brief Set bias values for the BaseGyroscope.
+ * @note Bias must be expressed as DPS.
+ * @note The bias buffer must be at least the same size of the BaseGyroscope
+ * axes number.
+ *
+ * @param[in] devp pointer to @p LSM6DS0Driver.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm6ds0GyroscopeSetBias(devp, bp) \
+ gyroscopeSetBias(&((devp)->gyro_if), bp)
+
+/**
+ * @brief Reset bias values for the BaseGyroscope.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] devp pointer to @p LSM6DS0Driver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm6ds0GyroscopeResetBias(devp) \
+ gyroscopeResetBias(&((devp)->gyro_if))
+
+/**
+ * @brief Set sensitivity values for the BaseGyroscope.
+ * @note Sensitivity must be expressed as DPS/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseGyroscope axes number.
+ *
+ * @param[in] devp pointer to @p LSM6DS0Driver.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm6ds0GyroscopeSetSensitivity(devp, sp) \
+ gyroscopeSetSensitivity(&((devp)->gyro_if), sp)
+
+/**
+ * @brief Reset sensitivity values for the BaseGyroscope.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] devp pointer to @p LSM6DS0Driver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lsm6ds0GyroscopeResetSensitivity(devp) \
+ gyroscopeResetSensitivity(&((devp)->gyro_if))
+
+/**
+ * @brief Changes the LSM6DS0Driver gyroscope fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p LSM6DS0Driver.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lsm6ds0GyroscopeSetFullScale(devp, fs) \
+ (devp)->vmt->acc_set_full_scale(devp, fs)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void lsm6ds0ObjectInit(LSM6DS0Driver *devp);
+ void lsm6ds0Start(LSM6DS0Driver *devp, const LSM6DS0Config *config);
+ void lsm6ds0Stop(LSM6DS0Driver *devp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LSM6DS0_H_ */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lsm6ds0.mk b/ChibiOS_20.3.2/os/ex/devices/ST/lsm6ds0.mk
new file mode 100644
index 0000000..f3da344
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lsm6ds0.mk
@@ -0,0 +1,10 @@
+# List of all the LSM6DS0 device files.
+LSM6DS0SRC := $(CHIBIOS)/os/ex/devices/ST/lsm6ds0.c
+
+# Required include directories
+LSM6DS0INC := $(CHIBIOS)/os/ex/include \
+ $(CHIBIOS)/os/ex/devices/ST
+
+# Shared variables
+ALLCSRC += $(LSM6DS0SRC)
+ALLINC += $(LSM6DS0INC)
\ No newline at end of file
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lsm6dsl.c b/ChibiOS_20.3.2/os/ex/devices/ST/lsm6dsl.c
new file mode 100644
index 0000000..56bc10c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lsm6dsl.c
@@ -0,0 +1,1119 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file lsm6dsl.c
+ * @brief LSM6DSL MEMS interface module code.
+ *
+ * @addtogroup LSM6DSL
+ * @ingroup EX_ST
+ * @{
+ */
+
+#include "hal.h"
+#include "lsm6dsl.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#if (LSM6DSL_USE_I2C) || defined(__DOXYGEN__)
+/**
+ * @brief Reads registers value using I2C.
+ * @pre The I2C interface must be initialized and the driver started.
+ * @note IF_ADD_INC bit must be 1 in CTRL_REG8
+ *
+ * @param[in] i2cp pointer to the I2C interface
+ * @param[in] sad slave address without R bit
+ * @param[in] reg first sub-register address
+ * @param[out] rxbuf pointer to an output buffer
+ * @param[in] n number of consecutive register to read
+ * @return the operation status.
+ * @notapi
+ */
+msg_t lsm6dslI2CReadRegister(I2CDriver *i2cp, lsm6dsl_sad_t sad, uint8_t reg,
+ uint8_t* rxbuf, size_t n) {
+
+ return i2cMasterTransmitTimeout(i2cp, sad, ®, 1, rxbuf, n,
+ TIME_INFINITE);
+}
+
+/**
+ * @brief Writes a value into a register using I2C.
+ * @pre The I2C interface must be initialized and the driver started.
+ *
+ * @param[in] i2cp pointer to the I2C interface
+ * @param[in] sad slave address without R bit
+ * @param[in] txbuf buffer containing sub-address value in first position
+ * and values to write
+ * @param[in] n size of txbuf less one (not considering the first
+ * element)
+ * @return the operation status.
+ * @notapi
+ */
+#define lsm6dslI2CWriteRegister(i2cp, sad, txbuf, n) \
+ i2cMasterTransmitTimeout(i2cp, sad, txbuf, n + 1, NULL, 0, \
+ TIME_INFINITE)
+#endif /* LSM6DSL_USE_I2C */
+
+/**
+ * @brief Return the number of axes of the BaseAccelerometer.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ *
+ * @return the number of axes.
+ */
+static size_t acc_get_axes_number(void *ip) {
+ (void)ip;
+
+ return LSM6DSL_ACC_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Retrieves raw data from the BaseAccelerometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t acc_read_raw(void *ip, int32_t axes[]) {
+ LSM6DSLDriver* devp;
+ uint8_t buff [LSM6DSL_ACC_NUMBER_OF_AXES * 2], i;
+ int16_t tmp;
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DSLDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM6DSL_READY),
+ "acc_read_raw(), invalid state");
+#if LSM6DSL_USE_I2C
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "acc_read_raw(), channel not ready");
+
+#if LSM6DSL_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LSM6DSL_SHARED_I2C */
+
+ msg = lsm6dslI2CReadRegister(devp->config->i2cp, devp->config->slaveaddress,
+ LSM6DSL_AD_OUTX_L_XL, buff,
+ LSM6DSL_ACC_NUMBER_OF_AXES * 2);
+
+#if LSM6DSL_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DSL_SHARED_I2C */
+#endif /* LSM6DSL_USE_I2C */
+ if(msg == MSG_OK)
+ for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++) {
+ tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
+ axes[i] = (int32_t)tmp;
+ }
+ return msg;
+}
+
+/**
+ * @brief Retrieves cooked data from the BaseAccelerometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as milli-G.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t acc_read_cooked(void *ip, float axes[]) {
+ LSM6DSLDriver* devp;
+ uint32_t i;
+ int32_t raw[LSM6DSL_ACC_NUMBER_OF_AXES];
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DSLDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM6DSL_READY),
+ "acc_read_cooked(), invalid state");
+
+ msg = acc_read_raw(ip, raw);
+ for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++) {
+ axes[i] = (raw[i] * devp->accsensitivity[i]) - devp->accbias[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Set bias values for the BaseAccelerometer.
+ * @note Bias must be expressed as milli-G.
+ * @note The bias buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t acc_set_bias(void *ip, float *bp) {
+ LSM6DSLDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (bp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DSLDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM6DSL_READY),
+ "acc_set_bias(), invalid state");
+
+ for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++) {
+ devp->accbias[i] = bp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset bias values for the BaseAccelerometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t acc_reset_bias(void *ip) {
+ LSM6DSLDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DSLDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM6DSL_READY),
+ "acc_reset_bias(), invalid state");
+
+ for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++)
+ devp->accbias[i] = LSM6DSL_ACC_BIAS;
+ return msg;
+}
+
+/**
+ * @brief Set sensitivity values for the BaseAccelerometer.
+ * @note Sensitivity must be expressed as milli-G/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t acc_set_sensivity(void *ip, float *sp) {
+ LSM6DSLDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DSLDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgCheck((ip != NULL) && (sp != NULL));
+
+ osalDbgAssert((devp->state == LSM6DSL_READY),
+ "acc_set_sensivity(), invalid state");
+
+ for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++) {
+ devp->accsensitivity[i] = sp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset sensitivity values for the BaseAccelerometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] ip pointer to @p BaseAccelerometer interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t acc_reset_sensivity(void *ip) {
+ LSM6DSLDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DSLDriver*, (BaseAccelerometer*)ip);
+
+ osalDbgAssert((devp->state == LSM6DSL_READY),
+ "acc_reset_sensivity(), invalid state");
+
+ if(devp->config->accfullscale == LSM6DSL_ACC_FS_2G)
+ for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LSM6DSL_ACC_SENS_2G;
+ else if(devp->config->accfullscale == LSM6DSL_ACC_FS_4G)
+ for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LSM6DSL_ACC_SENS_4G;
+ else if(devp->config->accfullscale == LSM6DSL_ACC_FS_8G)
+ for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LSM6DSL_ACC_SENS_8G;
+ else if(devp->config->accfullscale == LSM6DSL_ACC_FS_16G)
+ for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++)
+ devp->accsensitivity[i] = LSM6DSL_ACC_SENS_16G;
+ else {
+ osalDbgAssert(FALSE, "reset_sensivity(), accelerometer full scale issue");
+ msg = MSG_RESET;
+ }
+ return msg;
+}
+
+/**
+ * @brief Changes the LSM6DSLDriver accelerometer fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p LSM6DSLDriver interface.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t acc_set_full_scale(LSM6DSLDriver *devp, lsm6dsl_acc_fs_t fs) {
+ float newfs, scale;
+ uint8_t i, buff[2];
+ msg_t msg;
+
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LSM6DSL_READY),
+ "acc_set_full_scale(), invalid state");
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "acc_set_full_scale(), channel not ready");
+
+ /* Computing new fullscale value.*/
+ if(fs == LSM6DSL_ACC_FS_2G) {
+ newfs = LSM6DSL_ACC_2G;
+ }
+ else if(fs == LSM6DSL_ACC_FS_4G) {
+ newfs = LSM6DSL_ACC_4G;
+ }
+ else if(fs == LSM6DSL_ACC_FS_8G) {
+ newfs = LSM6DSL_ACC_8G;
+ }
+ else if(fs == LSM6DSL_ACC_FS_16G) {
+ newfs = LSM6DSL_ACC_16G;
+ }
+ else {
+ msg = MSG_RESET;
+ return msg;
+ }
+
+ if(newfs != devp->accfullscale) {
+ /* Computing scale value.*/
+ scale = newfs / devp->accfullscale;
+ devp->accfullscale = newfs;
+
+#if LSM6DSL_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LSM6DSL_SHARED_I2C */
+
+ /* Updating register.*/
+ msg = lsm6dslI2CReadRegister(devp->config->i2cp,
+ devp->config->slaveaddress,
+ LSM6DSL_AD_CTRL1_XL, &buff[1], 1);
+
+#if LSM6DSL_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DSL_SHARED_I2C */
+
+ if(msg != MSG_OK)
+ return msg;
+
+ buff[1] &= ~(LSMDSL_CTRL1_XL_FS_MASK);
+ buff[1] |= fs;
+ buff[0] = LSM6DSL_AD_CTRL1_XL;
+
+#if LSM6DSL_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+#endif /* LSM6DSL_SHARED_I2C */
+
+ msg = lsm6dslI2CWriteRegister(devp->config->i2cp,
+ devp->config->slaveaddress, buff, 1);
+
+#if LSM6DSL_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DSL_SHARED_I2C */
+
+ if(msg != MSG_OK)
+ return msg;
+
+ /* Scaling sensitivity and bias. Re-calibration is suggested anyway.*/
+ for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++) {
+ devp->accsensitivity[i] *= scale;
+ devp->accbias[i] *= scale;
+ }
+ }
+ return msg;
+}
+
+/**
+ * @brief Return the number of axes of the BaseGyroscope.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ *
+ * @return the number of axes.
+ */
+static size_t gyro_get_axes_number(void *ip) {
+ (void)ip;
+
+ return LSM6DSL_GYRO_NUMBER_OF_AXES;
+}
+
+/**
+ * @brief Retrieves raw data from the BaseGyroscope.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseGyroscope axes number.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t gyro_read_raw(void *ip, int32_t axes[LSM6DSL_GYRO_NUMBER_OF_AXES]) {
+ LSM6DSLDriver* devp;
+ int16_t tmp;
+ uint8_t i, buff [2 * LSM6DSL_GYRO_NUMBER_OF_AXES];
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DSLDriver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == LSM6DSL_READY),
+ "gyro_read_raw(), invalid state");
+#if LSM6DSL_USE_I2C
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "gyro_read_raw(), channel not ready");
+
+#if LSM6DSL_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LSM6DSL_SHARED_I2C */
+
+ msg = lsm6dslI2CReadRegister(devp->config->i2cp, devp->config->slaveaddress,
+ LSM6DSL_AD_OUTX_L_G, buff,
+ LSM6DSL_GYRO_NUMBER_OF_AXES * 2);
+
+#if LSM6DSL_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DSL_SHARED_I2C */
+#endif /* LSM6DSL_USE_I2C */
+
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++) {
+ tmp = buff[2 * i] + (buff[2 * i + 1] << 8);
+ axes[i] = (int32_t)tmp;
+ }
+ return msg;
+}
+
+/**
+ * @brief Retrieves cooked data from the BaseGyroscope.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as DPS.
+ * @note The axes array must be at least the same size of the
+ * BaseGyroscope axes number.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ */
+static msg_t gyro_read_cooked(void *ip, float axes[]) {
+ LSM6DSLDriver* devp;
+ uint32_t i;
+ int32_t raw[LSM6DSL_GYRO_NUMBER_OF_AXES];
+ msg_t msg;
+
+ osalDbgCheck((ip != NULL) && (axes != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DSLDriver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == LSM6DSL_READY),
+ "gyro_read_cooked(), invalid state");
+
+ msg = gyro_read_raw(ip, raw);
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++){
+ axes[i] = (raw[i] * devp->gyrosensitivity[i]) - devp->gyrobias[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Samples bias values for the BaseGyroscope.
+ * @note The LSM6DSL shall not be moved during the whole procedure.
+ * @note After this function internal bias is automatically updated.
+ * @note The behavior of this function depends on @p LSM6DSL_BIAS_ACQ_TIMES
+ * and @p LSM6DSL_BIAS_SETTLING_US.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t gyro_sample_bias(void *ip) {
+ LSM6DSLDriver* devp;
+ uint32_t i, j;
+ int32_t raw[LSM6DSL_GYRO_NUMBER_OF_AXES];
+ int32_t buff[LSM6DSL_GYRO_NUMBER_OF_AXES] = {0, 0, 0};
+ msg_t msg;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DSLDriver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == LSM6DSL_READY),
+ "gyro_sample_bias(), invalid state");
+#if LSM6DSL_USE_I2C
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "gyro_sample_bias(), channel not ready");
+#endif
+
+ for(i = 0; i < LSM6DSL_GYRO_BIAS_ACQ_TIMES; i++){
+ msg = gyro_read_raw(ip, raw);
+ if(msg != MSG_OK)
+ return msg;
+ for(j = 0; j < LSM6DSL_GYRO_NUMBER_OF_AXES; j++){
+ buff[j] += raw[j];
+ }
+ osalThreadSleepMicroseconds(LSM6DSL_GYRO_BIAS_SETTLING_US);
+ }
+
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++){
+ devp->gyrobias[i] = (buff[i] / LSM6DSL_GYRO_BIAS_ACQ_TIMES);
+ devp->gyrobias[i] *= devp->gyrosensitivity[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Set bias values for the BaseGyroscope.
+ * @note Bias must be expressed as DPS.
+ * @note The bias buffer must be at least the same size of the BaseGyroscope
+ * axes number.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t gyro_set_bias(void *ip, float *bp) {
+ LSM6DSLDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (bp != NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DSLDriver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == LSM6DSL_READY),
+ "gyro_set_bias(), invalid state");
+
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++) {
+ devp->gyrobias[i] = bp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset bias values for the BaseGyroscope.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t gyro_reset_bias(void *ip) {
+ LSM6DSLDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DSLDriver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == LSM6DSL_READY),
+ "gyro_reset_bias(), invalid state");
+
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrobias[i] = LSM6DSL_GYRO_BIAS;
+ return msg;
+}
+
+/**
+ * @brief Set sensitivity values for the BaseGyroscope.
+ * @note Sensitivity must be expressed as DPS/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseGyroscope axes number.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ */
+static msg_t gyro_set_sensivity(void *ip, float *sp) {
+ LSM6DSLDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck((ip != NULL) && (sp !=NULL));
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DSLDriver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == LSM6DSL_READY),
+ "gyro_set_sensivity(), invalid state");
+
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++) {
+ devp->gyrosensitivity[i] = sp[i];
+ }
+ return msg;
+}
+
+/**
+ * @brief Reset sensitivity values for the BaseGyroscope.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] ip pointer to @p BaseGyroscope interface.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t gyro_reset_sensivity(void *ip) {
+ LSM6DSLDriver* devp;
+ uint32_t i;
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(ip != NULL);
+
+ /* Getting parent instance pointer.*/
+ devp = objGetInstance(LSM6DSLDriver*, (BaseGyroscope*)ip);
+
+ osalDbgAssert((devp->state == LSM6DSL_READY),
+ "gyro_reset_sensivity(), invalid state");
+ if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_125DPS)
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_125DPS;
+ else if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_250DPS)
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_250DPS;
+ else if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_500DPS)
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_500DPS;
+ else if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_1000DPS)
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_1000DPS;
+ else if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_2000DPS)
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_2000DPS;
+ else {
+ osalDbgAssert(FALSE, "gyro_reset_sensivity(), full scale issue");
+ return MSG_RESET;
+ }
+ return msg;
+}
+
+/**
+ * @brief Changes the LSM6DSLDriver gyroscope fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p BaseGyroscope interface.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ */
+static msg_t gyro_set_full_scale(LSM6DSLDriver *devp, lsm6dsl_gyro_fs_t fs) {
+ float newfs, scale;
+ uint8_t i, buff[2];
+ msg_t msg = MSG_OK;
+
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LSM6DSL_READY),
+ "gyro_set_full_scale(), invalid state");
+#if LSM6DSL_USE_I2C
+ osalDbgAssert((devp->config->i2cp->state == I2C_READY),
+ "gyro_set_full_scale(), channel not ready");
+#endif
+
+ if(fs == LSM6DSL_GYRO_FS_125DPS) {
+ newfs = LSM6DSL_GYRO_125DPS;
+ }
+ else if(fs == LSM6DSL_GYRO_FS_250DPS) {
+ newfs = LSM6DSL_GYRO_250DPS;
+ }
+ else if(fs == LSM6DSL_GYRO_FS_500DPS) {
+ newfs = LSM6DSL_GYRO_500DPS;
+ }
+ else if(fs == LSM6DSL_GYRO_FS_1000DPS) {
+ newfs = LSM6DSL_GYRO_1000DPS;
+ }
+ else if(fs == LSM6DSL_GYRO_FS_2000DPS) {
+ newfs = LSM6DSL_GYRO_2000DPS;
+ }
+ else {
+ return MSG_RESET;
+ }
+
+ if(newfs != devp->gyrofullscale) {
+ scale = newfs / devp->gyrofullscale;
+ devp->gyrofullscale = newfs;
+
+#if LSM6DSL_USE_I2C
+#if LSM6DSL_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LSM6DSL_SHARED_I2C */
+
+ /* Updating register.*/
+ msg = lsm6dslI2CReadRegister(devp->config->i2cp,
+ devp->config->slaveaddress,
+ LSM6DSL_AD_CTRL2_G, &buff[1], 1);
+
+#if LSM6DSL_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DSL_SHARED_I2C */
+#endif /* LSM6DSL_USE_I2C */
+
+ buff[1] &= ~(LSMDSL_CTRL2_G_FS_MASK);
+ buff[1] |= fs;
+ buff[0] = LSM6DSL_AD_CTRL2_G;
+
+#if LSM6DSL_USE_I2C
+#if LSM6DSL_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp,
+ devp->config->i2ccfg);
+#endif /* LSM6DSL_SHARED_I2C */
+
+ lsm6dslI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
+ buff, 1);
+
+#if LSM6DSL_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DSL_SHARED_I2C */
+#endif /* LSM6DSL_USE_I2C */
+
+ /* Scaling sensitivity and bias. Re-calibration is suggested anyway. */
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++) {
+ devp->gyrosensitivity[i] *= scale;
+ devp->gyrobias[i] *= scale;
+ }
+ }
+ return msg;
+}
+
+static const struct LSM6DSLVMT vmt_device = {
+ (size_t)0,
+ acc_set_full_scale, gyro_set_full_scale
+};
+
+static const struct BaseAccelerometerVMT vmt_accelerometer = {
+ sizeof(struct LSM6DSLVMT*),
+ acc_get_axes_number, acc_read_raw, acc_read_cooked,
+ acc_set_bias, acc_reset_bias, acc_set_sensivity, acc_reset_sensivity
+};
+
+static const struct BaseGyroscopeVMT vmt_gyroscope = {
+ sizeof(struct LSM6DSLVMT*) + sizeof(BaseAccelerometer),
+ gyro_get_axes_number, gyro_read_raw, gyro_read_cooked,
+ gyro_sample_bias, gyro_set_bias, gyro_reset_bias,
+ gyro_set_sensivity, gyro_reset_sensivity
+};
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes an instance.
+ *
+ * @param[out] devp pointer to the @p LSM6DSLDriver object
+ *
+ * @init
+ */
+void lsm6dslObjectInit(LSM6DSLDriver *devp) {
+ devp->vmt = &vmt_device;
+ devp->acc_if.vmt = &vmt_accelerometer;
+ devp->gyro_if.vmt = &vmt_gyroscope;
+
+ devp->config = NULL;
+
+ devp->accaxes = LSM6DSL_ACC_NUMBER_OF_AXES;
+ devp->gyroaxes = LSM6DSL_GYRO_NUMBER_OF_AXES;
+
+ devp->state = LSM6DSL_STOP;
+}
+
+/**
+ * @brief Configures and activates LSM6DSL Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p LSM6DSLDriver object
+ * @param[in] config pointer to the @p LSM6DSLConfig object
+ *
+ * @api
+ */
+void lsm6dslStart(LSM6DSLDriver *devp, const LSM6DSLConfig *config) {
+ uint32_t i;
+ uint8_t cr[11];
+ osalDbgCheck((devp != NULL) && (config != NULL));
+
+ osalDbgAssert((devp->state == LSM6DSL_STOP) ||
+ (devp->state == LSM6DSL_READY),
+ "lsm6dslStart(), invalid state");
+
+ devp->config = config;
+
+ /* Enforcing multiple write configuration.*/
+ {
+ cr[0] = LSM6DSL_AD_CTRL3_C;
+ cr[1] = LSMDSL_CTRL3_C_IF_INC;
+ }
+#if LSM6DSL_USE_I2C
+#if LSM6DSL_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+#endif /* LSM6DSL_SHARED_I2C */
+
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+ lsm6dslI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
+ cr, 1);
+
+#if LSM6DSL_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DSL_SHARED_I2C */
+#endif /* LSM6DSL_USE_I2C */
+
+ /* Configuring all the control registers.*/
+ /* Multiple write starting address.*/
+ cr[0] = LSM6DSL_AD_CTRL1_XL;
+ /* Control register 1 configuration block.*/
+ {
+ cr[1] = devp->config->accoutdatarate |
+ devp->config->accfullscale;
+ }
+ /* Control register 2 configuration block.*/
+ {
+ cr[2] = devp->config->gyrooutdatarate |
+ devp->config->gyrofullscale;
+ }
+ /* Control register 3 configuration block.*/
+ {
+ cr[3] = LSMDSL_CTRL3_C_IF_INC;
+#if LSM6DSL_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[3] |= devp->config->endianness | devp->config->blockdataupdate;
+#endif
+ }
+ /* Control register 4 configuration block.*/
+ {
+ cr[4] = 0;
+#if LSM6DSL_USE_ADVANCED || defined(__DOXYGEN__)
+ if(devp->config->gyrolowpassfilter != LSM6DSL_GYRO_LPF_DISABLED) {
+ cr[4] |= LSMDSL_CTRL4_C_LPF1_SEL_G;
+ }
+ else {
+ /* Nothing to do. */
+ }
+#endif
+ }
+ /* Control register 5 configuration block.*/
+ {
+ cr[5] = 0;
+ }
+ /* Control register 6 configuration block.*/
+ {
+ cr[6] = 0;
+#if LSM6DSL_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[6] |= devp->config->acclpmode;
+
+#endif
+#if LSM6DSL_USE_ADVANCED || defined(__DOXYGEN__)
+ if(devp->config->gyrolowpassfilter != LSM6DSL_GYRO_LPF_DISABLED) {
+ cr[6] |= devp->config->gyrolowpassfilter;
+ }
+ else {
+ /* Nothing to do. */
+ }
+#endif
+ }
+ /* Control register 7 configuration block.*/
+ {
+ cr[7] = 0;
+#if LSM6DSL_USE_ADVANCED || defined(__DOXYGEN__)
+ cr[7] |= devp->config->gyrolpmode;
+
+#endif
+ }
+ /* Control register 8 configuration block.*/
+ {
+ cr[8] = 0;
+ }
+ /* Control register 9 configuration block.*/
+ {
+ cr[9] = 0;
+ }
+ /* Control register 10 configuration block.*/
+ {
+ cr[10] = 0;
+ }
+
+#if LSM6DSL_USE_I2C
+#if LSM6DSL_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+#endif /* LSM6DSL_SHARED_I2C */
+
+ lsm6dslI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
+ cr, 10);
+
+#if LSM6DSL_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DSL_SHARED_I2C */
+#endif /* LSM6DSL_USE_I2C */
+
+ /* Storing sensitivity according to user settings */
+ if(devp->config->accfullscale == LSM6DSL_ACC_FS_2G) {
+ for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++) {
+ if(devp->config->accsensitivity == NULL)
+ devp->accsensitivity[i] = LSM6DSL_ACC_SENS_2G;
+ else
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ devp->accfullscale = LSM6DSL_ACC_2G;
+ }
+ else if(devp->config->accfullscale == LSM6DSL_ACC_FS_4G) {
+ for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++) {
+ if(devp->config->accsensitivity == NULL)
+ devp->accsensitivity[i] = LSM6DSL_ACC_SENS_4G;
+ else
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ devp->accfullscale = LSM6DSL_ACC_4G;
+ }
+ else if(devp->config->accfullscale == LSM6DSL_ACC_FS_8G) {
+ for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++) {
+ if(devp->config->accsensitivity == NULL)
+ devp->accsensitivity[i] = LSM6DSL_ACC_SENS_8G;
+ else
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ devp->accfullscale = LSM6DSL_ACC_8G;
+ }
+ else if(devp->config->accfullscale == LSM6DSL_ACC_FS_16G) {
+ for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++) {
+ if(devp->config->accsensitivity == NULL)
+ devp->accsensitivity[i] = LSM6DSL_ACC_SENS_16G;
+ else
+ devp->accsensitivity[i] = devp->config->accsensitivity[i];
+ }
+ devp->accfullscale = LSM6DSL_ACC_16G;
+ }
+ else
+ osalDbgAssert(FALSE, "lsm6dslStart(), accelerometer full scale issue");
+
+ /* Storing bias information */
+ if(devp->config->accbias != NULL)
+ for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++)
+ devp->accbias[i] = devp->config->accbias[i];
+ else
+ for(i = 0; i < LSM6DSL_ACC_NUMBER_OF_AXES; i++)
+ devp->accbias[i] = LSM6DSL_ACC_BIAS;
+
+ if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_125DPS) {
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++) {
+ if(devp->config->gyrosensitivity == NULL)
+ devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_125DPS;
+ else
+ devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
+ }
+ devp->gyrofullscale = LSM6DSL_GYRO_125DPS;
+ }
+ else if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_250DPS) {
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++) {
+ if(devp->config->gyrosensitivity == NULL)
+ devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_250DPS;
+ else
+ devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
+ }
+ devp->gyrofullscale = LSM6DSL_GYRO_250DPS;
+ }
+ else if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_500DPS) {
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++) {
+ if(devp->config->gyrosensitivity == NULL)
+ devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_500DPS;
+ else
+ devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
+ }
+ devp->gyrofullscale = LSM6DSL_GYRO_500DPS;
+ }
+ else if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_1000DPS) {
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++) {
+ if(devp->config->gyrosensitivity == NULL)
+ devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_1000DPS;
+ else
+ devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
+ }
+ devp->gyrofullscale = LSM6DSL_GYRO_1000DPS;
+ }
+ else if(devp->config->gyrofullscale == LSM6DSL_GYRO_FS_2000DPS) {
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++) {
+ if(devp->config->gyrosensitivity == NULL)
+ devp->gyrosensitivity[i] = LSM6DSL_GYRO_SENS_2000DPS;
+ else
+ devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i];
+ }
+ devp->gyrofullscale = LSM6DSL_GYRO_2000DPS;
+ }
+ else
+ osalDbgAssert(FALSE, "lsm6dslStart(), gyroscope full scale issue");
+
+ /* Storing bias information */
+ if(devp->config->gyrobias != NULL)
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrobias[i] = devp->config->gyrobias[i];
+ else
+ for(i = 0; i < LSM6DSL_GYRO_NUMBER_OF_AXES; i++)
+ devp->gyrobias[i] = LSM6DSL_GYRO_BIAS;
+
+ /* This is the MEMS transient recovery time */
+ osalThreadSleepMilliseconds(5);
+
+ devp->state = LSM6DSL_READY;
+}
+
+/**
+ * @brief Deactivates the LSM6DSL Complex Driver peripheral.
+ *
+ * @param[in] devp pointer to the @p LSM6DSLDriver object
+ *
+ * @api
+ */
+void lsm6dslStop(LSM6DSLDriver *devp) {
+ uint8_t cr[2];
+
+ osalDbgCheck(devp != NULL);
+
+ osalDbgAssert((devp->state == LSM6DSL_STOP) || (devp->state == LSM6DSL_READY),
+ "lsm6dslStop(), invalid state");
+
+ if (devp->state == LSM6DSL_READY) {
+#if LSM6DSL_USE_I2C
+#if LSM6DSL_SHARED_I2C
+ i2cAcquireBus(devp->config->i2cp);
+ i2cStart(devp->config->i2cp, devp->config->i2ccfg);
+#endif /* LSM6DSL_SHARED_I2C */
+
+
+ cr[0] = LSM6DSL_AD_CTRL1_XL;
+ /* Disabling accelerometer.*/
+ cr[1] = LSM6DSL_ACC_ODR_PD;
+ /* Disabling gyroscope.*/
+ cr[2] = LSM6DSL_GYRO_ODR_PD;
+ lsm6dslI2CWriteRegister(devp->config->i2cp, devp->config->slaveaddress,
+ cr, 2);
+
+ i2cStop(devp->config->i2cp);
+#if LSM6DSL_SHARED_I2C
+ i2cReleaseBus(devp->config->i2cp);
+#endif /* LSM6DSL_SHARED_I2C */
+#endif /* LSM6DSL_USE_I2C */
+ }
+ devp->state = LSM6DSL_STOP;
+}
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lsm6dsl.h b/ChibiOS_20.3.2/os/ex/devices/ST/lsm6dsl.h
new file mode 100644
index 0000000..4cffd78
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lsm6dsl.h
@@ -0,0 +1,1055 @@
+/*
+ ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file lsm6dsl.h
+ * @brief LSM6DSL MEMS interface module header.
+ *
+ * @addtogroup LSM6DSL
+ * @ingroup EX_ST
+ * @{
+ */
+#ifndef _LSM6DSL_H_
+#define _LSM6DSL_H_
+
+#include "ex_accelerometer.h"
+#include "ex_gyroscope.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Version identification
+ * @{
+ */
+/**
+ * @brief LSM6DSL driver version string.
+ */
+#define EX_LSM6DSL_VERSION "1.0.1"
+
+/**
+ * @brief LSM6DSL driver version major number.
+ */
+#define EX_LSM6DSL_MAJOR 1
+
+/**
+ * @brief LSM6DSL driver version minor number.
+ */
+#define EX_LSM6DSL_MINOR 0
+
+/**
+ * @brief LSM6DSL driver version patch number.
+ */
+#define EX_LSM6DSL_PATCH 1
+/** @} */
+
+/**
+ * @brief LSM6DSL accelerometer subsystem characteristics.
+ * @note Sensitivity is expressed as milli-G/LSB whereas
+ * 1 milli-G = 0.00980665 m/s^2.
+ * @note Bias is expressed as milli-G.
+ *
+ * @{
+ */
+#define LSM6DSL_ACC_NUMBER_OF_AXES 3U
+
+#define LSM6DSL_ACC_2G 2.0f
+#define LSM6DSL_ACC_4G 4.0f
+#define LSM6DSL_ACC_8G 8.0f
+#define LSM6DSL_ACC_16G 16.0f
+
+#define LSM6DSL_ACC_SENS_2G 0.061f
+#define LSM6DSL_ACC_SENS_4G 0.122f
+#define LSM6DSL_ACC_SENS_8G 0.244f
+#define LSM6DSL_ACC_SENS_16G 0.488f
+
+#define LSM6DSL_ACC_BIAS 0.0f
+/** @} */
+
+/**
+ * @brief L3GD20 gyroscope system characteristics.
+ * @note Sensitivity is expressed as DPS/LSB whereas DPS stand for Degree
+ * per second [�/s].
+ * @note Bias is expressed as DPS.
+ *
+ * @{
+ */
+#define LSM6DSL_GYRO_NUMBER_OF_AXES 3U
+
+#define LSM6DSL_GYRO_125DPS 125.0f
+#define LSM6DSL_GYRO_250DPS 250.0f
+#define LSM6DSL_GYRO_500DPS 500.0f
+#define LSM6DSL_GYRO_1000DPS 1000.0f
+#define LSM6DSL_GYRO_2000DPS 2000.0f
+
+#define LSM6DSL_GYRO_SENS_125DPS 0.004375f
+#define LSM6DSL_GYRO_SENS_250DPS 0.008750f
+#define LSM6DSL_GYRO_SENS_500DPS 0.017500f
+#define LSM6DSL_GYRO_SENS_1000DPS 0.035000f
+#define LSM6DSL_GYRO_SENS_2000DPS 0.070000f
+
+#define LSM6DSL_GYRO_BIAS 0.0f
+/** @} */
+
+/**
+ * @name LSM6DSL communication interfaces related bit masks
+ * @{
+ */
+#define LSM6DSL_DI_MASK 0xFF
+#define LSM6DSL_DI(n) (1 << n)
+#define LSM6DSL_AD_MASK 0x7F
+#define LSM6DSL_AD(n) (1 << n)
+#define LSM6DSL_MS (1 << 7)
+/** @} */
+
+/**
+ * @name LSM6DSL register addresses
+ * @{
+ */
+#define LSM6DSL_AD_FUNC_CFG_ACCESS 0x01
+#define LSM6DSL_AD_SENSOR_SYNC_TIME_FRAME 0x04
+#define LSM6DSL_AD_SENSOR_SYNC_RES_RATIO 0x05
+#define LSM6DSL_AD_FIFO_CTRL1 0x06
+#define LSM6DSL_AD_FIFO_CTRL2 0x07
+#define LSM6DSL_AD_FIFO_CTRL3 0x08
+#define LSM6DSL_AD_FIFO_CTRL4 0x09
+#define LSM6DSL_AD_FIFO_CTRL5 0x0A
+#define LSM6DSL_AD_DRDY_PULSE_CFG_G 0x0B
+#define LSM6DSL_AD_INT1_CTRL 0x0D
+#define LSM6DSL_AD_INT2_CTRL 0x0E
+#define LSM6DSL_AD_WHO_AM_I 0x0F
+#define LSM6DSL_AD_CTRL1_XL 0x10
+#define LSM6DSL_AD_CTRL2_G 0x11
+#define LSM6DSL_AD_CTRL3_C 0x12
+#define LSM6DSL_AD_CTRL4_C 0x13
+#define LSM6DSL_AD_CTRL5_C 0x14
+#define LSM6DSL_AD_CTRL6_C 0x15
+#define LSM6DSL_AD_CTRL7_G 0x16
+#define LSM6DSL_AD_CTRL8_XL 0x17
+#define LSM6DSL_AD_CTRL9_XL 0x18
+#define LSM6DSL_AD_CTRL10_C 0x19
+#define LSM6DSL_AD_MASTER_CONFIG 0x1A
+#define LSM6DSL_AD_WAKE_UP_SRC 0x1B
+#define LSM6DSL_AD_TAP_SRC 0x1C
+#define LSM6DSL_AD_D6D_SRC 0x1D
+#define LSM6DSL_AD_STATUS_REG 0x1E
+#define LSM6DSL_AD_OUT_TEMP_L 0x20
+#define LSM6DSL_AD_OUT_TEMP_H 0x21
+#define LSM6DSL_AD_OUTX_L_G 0x22
+#define LSM6DSL_AD_OUTX_H_G 0x23
+#define LSM6DSL_AD_OUTY_L_G 0x24
+#define LSM6DSL_AD_OUTY_H_G 0x25
+#define LSM6DSL_AD_OUTZ_L_G 0x26
+#define LSM6DSL_AD_OUTZ_H_G 0x27
+#define LSM6DSL_AD_OUTX_L_XL 0x28
+#define LSM6DSL_AD_OUTX_H_XL 0x29
+#define LSM6DSL_AD_OUTY_L_XL 0x2A
+#define LSM6DSL_AD_OUTY_H_XL 0x2B
+#define LSM6DSL_AD_OUTZ_L_XL 0x2C
+#define LSM6DSL_AD_OUTZ_H_XL 0x2D
+#define LSM6DSL_AD_SENSORHUB1_REG 0x2E
+#define LSM6DSL_AD_SENSORHUB2_REG 0x2F
+#define LSM6DSL_AD_SENSORHUB3_REG 0x30
+#define LSM6DSL_AD_SENSORHUB4_REG 0x31
+#define LSM6DSL_AD_SENSORHUB5_REG 0x32
+#define LSM6DSL_AD_SENSORHUB6_REG 0x33
+#define LSM6DSL_AD_SENSORHUB7_REG 0x34
+#define LSM6DSL_AD_SENSORHUB8_REG 0x35
+#define LSM6DSL_AD_SENSORHUB9_REG 0x36
+#define LSM6DSL_AD_SENSORHUB10_REG 0x37
+#define LSM6DSL_AD_SENSORHUB11_REG 0x38
+#define LSM6DSL_AD_SENSORHUB12_REG 0x39
+#define LSM6DSL_AD_FIFO_STATUS1 0x3A
+#define LSM6DSL_AD_FIFO_STATUS2 0x3B
+#define LSM6DSL_AD_FIFO_STATUS3 0x3C
+#define LSM6DSL_AD_FIFO_STATUS4 0x3D
+#define LSM6DSL_AD_FIFO_DATA_OUT_L 0x3E
+#define LSM6DSL_AD_FIFO_DATA_OUT_H 0x3F
+#define LSM6DSL_AD_TIMESTAMP0_REG 0x40
+#define LSM6DSL_AD_TIMESTAMP1_REG 0x41
+#define LSM6DSL_AD_TIMESTAMP2_REG 0x42
+#define LSM6DSL_AD_STEP_TIMESTAMP_L 0x49
+#define LSM6DSL_AD_STEP_TIMESTAMP_H 0x4A
+#define LSM6DSL_AD_STEP_COUNTER_L 0x4B
+#define LSM6DSL_AD_STEP_COUNTER_H 0x4C
+#define LSM6DSL_AD_SENSORHUB13_REG 0x4D
+#define LSM6DSL_AD_SENSORHUB14_REG 0x4E
+#define LSM6DSL_AD_SENSORHUB15_REG 0x4F
+#define LSM6DSL_AD_SENSORHUB16_REG 0x50
+#define LSM6DSL_AD_SENSORHUB17_REG 0x51
+#define LSM6DSL_AD_SENSORHUB18_REG 0x52
+#define LSM6DSL_AD_FUNC_SRC1 0x53
+#define LSM6DSL_AD_FUNC_SRC2 0x54
+#define LSM6DSL_AD_WRIST_TILT_IA 0x55
+#define LSM6DSL_AD_TAP_CFG 0x58
+#define LSM6DSL_AD_TAP_THS_6D 0x59
+#define LSM6DSL_AD_INT_DUR2 0x5A
+#define LSM6DSL_AD_WAKE_UP_THS 0x5B
+#define LSM6DSL_AD_WAKE_UP_DUR 0x5C
+#define LSM6DSL_AD_FREE_FALL 0x5D
+#define LSM6DSL_AD_MD1_CFG 0x5E
+#define LSM6DSL_AD_MD2_CFG 0x5F
+#define LSM6DSL_AD_MASTER_CMD_CODE 0x60
+#define LSM6DSL_AD_SENS_SYNC_SPI_ERROR_CODE 0x61
+#define LSM6DSL_AD_OUT_MAG_RAW_X_L 0x66
+#define LSM6DSL_AD_OUT_MAG_RAW_X_H 0x67
+#define LSM6DSL_AD_OUT_MAG_RAW_Y_L 0x68
+#define LSM6DSL_AD_OUT_MAG_RAW_Y_H 0x69
+#define LSM6DSL_AD_OUT_MAG_RAW_Z_L 0x6A
+#define LSM6DSL_AD_OUT_MAG_RAW_Z_H 0x6B
+#define LSM6DSL_AD_X_OFS_USR 0x73
+#define LSM6DSL_AD_Y_OFS_USR 0x74
+#define LSM6DSL_AD_Z_OFS_USR 0x75
+/** @} */
+
+/**
+ * @name LSM6DSL_AD_CTRL1_XL register bits definitions
+ * @{
+ */
+#define LSMDSL_CTRL1_XL_BW0_XL (1 << 0)
+#define LSMDSL_CTRL1_XL_LPF1_BW_SEL (1 << 1)
+#define LSMDSL_CTRL1_XL_FS_MASK 0x0C
+#define LSMDSL_CTRL1_XL_FS_XL0 (1 << 2)
+#define LSMDSL_CTRL1_XL_FS_XL1 (1 << 3)
+#define LSMDSL_CTRL1_XL_ODR_XL0 (1 << 4)
+#define LSMDSL_CTRL1_XL_ODR_XL1 (1 << 5)
+#define LSMDSL_CTRL1_XL_ODR_XL2 (1 << 6)
+#define LSMDSL_CTRL1_XL_ODR_XL3 (1 << 7)
+/** @} */
+
+/**
+ * @name LSM6DSL_AD_CTRL2_G register bits definitions
+ * @{
+ */
+#define LSMDSL_CTRL2_G_FS_MASK 0x0E
+#define LSMDSL_CTRL2_G_FS_125 (1 << 1)
+#define LSMDSL_CTRL2_G_FS_G0 (1 << 2)
+#define LSMDSL_CTRL2_G_FS_G1 (1 << 3)
+#define LSMDSL_CTRL2_G_ODR_G0 (1 << 4)
+#define LSMDSL_CTRL2_G_ODR_G1 (1 << 5)
+#define LSMDSL_CTRL2_G_ODR_G2 (1 << 6)
+#define LSMDSL_CTRL2_G_ODR_G3 (1 << 7)
+/** @} */
+
+/**
+ * @name LSM6DSL_AD_CTRL3_C register bits definitions
+ * @{
+ */
+#define LSMDSL_CTRL3_C_SW_RESET (1 << 0)
+#define LSMDSL_CTRL3_C_BLE (1 << 1)
+#define LSMDSL_CTRL3_C_IF_INC (1 << 2)
+#define LSMDSL_CTRL3_C_SIM (1 << 3)
+#define LSMDSL_CTRL3_C_PP_OD (1 << 4)
+#define LSMDSL_CTRL3_C_H_LACTIVE (1 << 5)
+#define LSMDSL_CTRL3_C_BDU (1 << 6)
+#define LSMDSL_CTRL3_C_BOOT (1 << 7)
+/** @} */
+
+/**
+ * @name LSM6DSL_AD_CTRL4_C register bits definitions
+ * @{
+ */
+#define LSMDSL_CTRL4_C_NOT_USED_01 (1 << 0)
+#define LSMDSL_CTRL4_C_LPF1_SEL_G (1 << 1)
+#define LSMDSL_CTRL4_C_I2C_DISABLE (1 << 2)
+#define LSMDSL_CTRL4_C_DRDY_MASK (1 << 3)
+#define LSMDSL_CTRL4_C_DEN_DRDY_IN (1 << 4)
+#define LSMDSL_CTRL4_C_INT2_ON_INT (1 << 5)
+#define LSMDSL_CTRL4_C_SLEEP (1 << 6)
+#define LSMDSL_CTRL4_C_DEN_XL_EN (1 << 7)
+/** @} */
+
+/**
+ * @name LSM6DSL_AD_CTRL5_C register bits definitions
+ * @{
+ */
+#define LSMDSL_CTRL5_C_ST0_XL (1 << 0)
+#define LSMDSL_CTRL5_C_ST1_XL (1 << 1)
+#define LSMDSL_CTRL5_C_ST0_G (1 << 2)
+#define LSMDSL_CTRL5_C_ST1_G (1 << 3)
+#define LSMDSL_CTRL5_C_DEN_LH (1 << 4)
+#define LSMDSL_CTRL5_C_ROUNDING0 (1 << 5)
+#define LSMDSL_CTRL5_C_ROUNDING1 (1 << 6)
+#define LSMDSL_CTRL5_C_ROUNDING2 (1 << 7)
+/** @} */
+
+/**
+ * @name LSM6DSL_AD_CTRL6_C register bits definitions
+ * @{
+ */
+#define LSMDSL_CTRL6_C_FTYPE_0 (1 << 0)
+#define LSMDSL_CTRL6_C_FTYPE_1 (1 << 1)
+#define LSMDSL_CTRL6_C_USR_OFF_W (1 << 3)
+#define LSMDSL_CTRL6_C_XL_HM_MODE (1 << 4)
+#define LSMDSL_CTRL6_C_LVL2_EN (1 << 5)
+#define LSMDSL_CTRL6_C_LVL_EN (1 << 6)
+#define LSMDSL_CTRL6_C_TRIG_EN (1 << 7)
+/** @} */
+
+/**
+ * @name LSM6DSL_AD_CTRL7_G register bits definitions
+ * @{
+ */
+#define LSMDSL_CTRL7_G_ROUNDING_ST (1 << 2)
+#define LSMDSL_CTRL7_G_HPM0_G (1 << 4)
+#define LSMDSL_CTRL7_G_HPM1_G (1 << 5)
+#define LSMDSL_CTRL7_G_HP_EN_G (1 << 6)
+#define LSMDSL_CTRL7_G_G_HM_MODE (1 << 7)
+/** @} */
+
+/**
+ * @name LSM6DSL_AD_CTRL8_XL register bits definitions
+ * @{
+ */
+#define LSMDSL_CTRL8_XL_LOW_PASS_ON (1 << 0)
+#define LSMDSL_CTRL8_XL_HP_SLOPE_XL (1 << 2)
+#define LSMDSL_CTRL8_XL_INPUT_COMPO (1 << 3)
+#define LSMDSL_CTRL8_XL_HP_REF_MODE (1 << 4)
+#define LSMDSL_CTRL8_XL_HPCF_XL0 (1 << 5)
+#define LSMDSL_CTRL8_XL_HPCF_XL1 (1 << 6)
+#define LSMDSL_CTRL8_XL_LPF2_XL_EN (1 << 7)
+/** @} */
+
+/**
+ * @name LSM6DSL_AD_CTRL9_XL register bits definitions
+ * @{
+ */
+#define LSMDSL_CTRL9_XL_SOFT_EN (1 << 2)
+#define LSMDSL_CTRL9_XL_DEN_XL_G (1 << 4)
+#define LSMDSL_CTRL9_XL_DEN_Z (1 << 5)
+#define LSMDSL_CTRL9_XL_DEN_Y (1 << 6)
+#define LSMDSL_CTRL9_XL_DEN_X (1 << 7)
+/** @} */
+
+/**
+ * @name LSM6DSL_AD_CTRL10_C register bits definitions
+ * @{
+ */
+#define LSMDSL_CTRL10_C_SIGN_MOTION (1 << 0)
+#define LSMDSL_CTRL10_C_PEDO_RST_ST (1 << 1)
+#define LSMDSL_CTRL10_C_FUNC_EN (1 << 2)
+#define LSMDSL_CTRL10_C_TILT_EN (1 << 3)
+#define LSMDSL_CTRL10_C_PEDO_EN (1 << 4)
+#define LSMDSL_CTRL10_C_TIMER_EN (1 << 5)
+#define LSMDSL_CTRL10_C_WRIST_TILT (1 << 7)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief LSM6DSL SPI interface switch.
+ * @details If set to @p TRUE the support for SPI is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(LSM6DSL_USE_SPI) || defined(__DOXYGEN__)
+#define LSM6DSL_USE_SPI FALSE
+#endif
+
+/**
+ * @brief LSM6DSL shared SPI switch.
+ * @details If set to @p TRUE the device acquires SPI bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires SPI_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(LSM6DSL_SHARED_SPI) || defined(__DOXYGEN__)
+#define LSM6DSL_SHARED_SPI FALSE
+#endif
+
+/**
+ * @brief LSM6DSL I2C interface switch.
+ * @details If set to @p TRUE the support for I2C is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(LSM6DSL_USE_I2C) || defined(__DOXYGEN__)
+#define LSM6DSL_USE_I2C TRUE
+#endif
+
+/**
+ * @brief LSM6DSL shared I2C switch.
+ * @details If set to @p TRUE the device acquires I2C bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(LSM6DSL_SHARED_I2C) || defined(__DOXYGEN__)
+#define LSM6DSL_SHARED_I2C FALSE
+#endif
+
+/**
+ * @brief LSM6DSL advanced configurations switch.
+ * @details If set to @p TRUE more configurations are available.
+ * @note The default is @p FALSE.
+ */
+#if !defined(LSM6DSL_USE_ADVANCED) || defined(__DOXYGEN__)
+#define LSM6DSL_USE_ADVANCED FALSE
+#endif
+
+/**
+ * @brief Number of acquisitions for gyroscope bias removal.
+ * @details This is the number of acquisitions performed to compute the
+ * bias. A repetition is required in order to remove noise.
+ */
+#if !defined(LSM6DSL_GYRO_BIAS_ACQ_TIMES) || defined(__DOXYGEN__)
+#define LSM6DSL_GYRO_BIAS_ACQ_TIMES 50
+#endif
+
+/**
+ * @brief Settling time for gyroscope bias removal.
+ * @details This is the time between each bias acquisition.
+ */
+#if !defined(LSM6DSL_GYRO_BIAS_SETTLING_US) || defined(__DOXYGEN__)
+#define LSM6DSL_GYRO_BIAS_SETTLING_US 5000
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !(LSM6DSL_USE_SPI ^ LSM6DSL_USE_I2C)
+#error "LSM6DSL_USE_SPI and LSM6DSL_USE_I2C cannot be both true or both false"
+#endif
+
+#if LSM6DSL_USE_SPI && !HAL_USE_SPI
+#error "LSM6DSL_USE_SPI requires HAL_USE_SPI"
+#endif
+
+#if LSM6DSL_SHARED_SPI && !SPI_USE_MUTUAL_EXCLUSION
+#error "LSM6DSL_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
+#endif
+
+#if LSM6DSL_USE_I2C && !HAL_USE_I2C
+#error "LSM6DSL_USE_I2C requires HAL_USE_I2C"
+#endif
+
+#if LSM6DSL_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
+#error "LSM6DSL_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
+#endif
+
+/*
+ * CHTODO: Add support for LSM6DSL over SPI.
+ */
+#if LSM6DSL_USE_SPI
+#error "LSM6DSL over SPI still not supported"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @name LSM6DSL data structures and types.
+ * @{
+ */
+/**
+ * @brief Structure representing a LSM6DSL driver.
+ */
+typedef struct LSM6DSLDriver LSM6DSLDriver;
+
+/**
+ * @brief Accelerometer and Gyroscope Slave Address.
+ */
+typedef enum {
+ LSM6DSL_SAD_GND = 0x6A, /**< SAD pin connected to GND. */
+ LSM6DSL_SAD_VCC = 0x6B /**< SAD pin connected to VCC. */
+} lsm6dsl_sad_t;
+
+/**
+ * @brief LSM6DSL accelerometer subsystem full scale.
+ */
+typedef enum {
+ LSM6DSL_ACC_FS_2G = 0x00, /**< Full scale �2g. */
+ LSM6DSL_ACC_FS_4G = 0x40, /**< Full scale �4g. */
+ LSM6DSL_ACC_FS_8G = 0x80, /**< Full scale �8g. */
+ LSM6DSL_ACC_FS_16G = 0xC0 /**< Full scale �16g. */
+} lsm6dsl_acc_fs_t;
+
+/**
+ * @brief LSM6DSL accelerometer subsystem output data rate.
+ */
+typedef enum {
+ LSM6DSL_ACC_ODR_PD = 0x00, /**< Power down */
+ LSM6DSL_ACC_ODR_1P6Hz = 0xB0, /**< ODR 1.6 Hz (Low Power only) */
+ LSM6DSL_ACC_ODR_12P5Hz = 0x10, /**< ODR 12.5 Hz */
+ LSM6DSL_ACC_ODR_26Hz = 0x20, /**< ODR 26 Hz */
+ LSM6DSL_ACC_ODR_52Hz = 0x30, /**< ODR 52 Hz */
+ LSM6DSL_ACC_ODR_104Hz = 0x40, /**< ODR 104 Hz */
+ LSM6DSL_ACC_ODR_208Hz = 0x50, /**< ODR 208 Hz */
+ LSM6DSL_ACC_ODR_416Hz = 0x60, /**< ODR 416 Hz */
+ LSM6DSL_ACC_ODR_833Hz = 0x70, /**< ODR 833 Hz */
+ LSM6DSL_ACC_ODR_1P66Hz = 0x80, /**< ODR 1.66 kHz */
+ LSM6DSL_ACC_ODR_3P33Hz = 0x90, /**< ODR 3.33 kHz */
+ LSM6DSL_ACC_ODR_6P66Hz = 0xA0 /**< ODR 6.66 kHz */
+} lsm6dsl_acc_odr_t;
+
+/**
+ * @brief LSM6DSL accelerometer subsystem output data rate.
+ */
+typedef enum {
+ LSM6DSL_ACC_LP_DISABLED = 0x00, /**< Low power disabled */
+ LSM6DSL_ACC_LP_ENABLED = 0x10 /**< Low power enabled */
+} lsm6dsl_acc_lp_t;
+
+/**
+ * @brief LSM6DSL gyroscope subsystem full scale.
+ */
+typedef enum {
+ LSM6DSL_GYRO_FS_125DPS = 0x02, /**< Full scale �125 degree per second */
+ LSM6DSL_GYRO_FS_250DPS = 0x00, /**< Full scale �250 degree per second */
+ LSM6DSL_GYRO_FS_500DPS = 0x04, /**< Full scale �500 degree per second */
+ LSM6DSL_GYRO_FS_1000DPS = 0x08, /**< Full scale �1000 degree per second */
+ LSM6DSL_GYRO_FS_2000DPS = 0x0C /**< Full scale �2000 degree per second */
+} lsm6dsl_gyro_fs_t;
+
+/**
+ * @brief LSM6DSL gyroscope subsystem output data rate.
+ */
+typedef enum {
+ LSM6DSL_GYRO_ODR_PD = 0x00, /**< Power down */
+ LSM6DSL_GYRO_ODR_12P5Hz = 0x10, /**< ODR 12.5 Hz */
+ LSM6DSL_GYRO_ODR_26Hz = 0x20, /**< ODR 26 Hz */
+ LSM6DSL_GYRO_ODR_52Hz = 0x30, /**< ODR 52 Hz */
+ LSM6DSL_GYRO_ODR_104Hz = 0x40, /**< ODR 104 Hz */
+ LSM6DSL_GYRO_ODR_208Hz = 0x50, /**< ODR 208 Hz */
+ LSM6DSL_GYRO_ODR_416Hz = 0x60, /**< ODR 416 Hz */
+ LSM6DSL_GYRO_ODR_833Hz = 0x70, /**< ODR 833 Hz */
+ LSM6DSL_GYRO_ODR_1P66Hz = 0x80, /**< ODR 1.66 kHz */
+ LSM6DSL_GYRO_ODR_3P33Hz = 0x90, /**< ODR 3.33 kHz */
+ LSM6DSL_GYRO_ODR_6P66Hz = 0xA0 /**< ODR 6.66 kHz */
+} lsm6dsl_gyro_odr_t;
+
+/**
+ * @brief LSM6DSL gyroscope subsystem low mode configuration.
+ */
+typedef enum {
+ LSM6DSL_GYRO_LP_DISABLED = 0x00, /**< Low power mode disabled. */
+ LSM6DSL_GYRO_LP_ENABLED = 0x80 /**< Low power mode enabled. */
+} lsm6dsl_gyro_lp_t;
+
+/**
+ * @brief LSM6DSL gyroscope subsystem output selection.
+ */
+typedef enum {
+ LSM6DSL_GYRO_LPF_DISABLED = -1, /**< Low pass filter disabled. */
+ LSM6DSL_GYRO_LPF_FTYPE0 = 0x00, /**< Refer to table 68 of Datasheet. */
+ LSM6DSL_GYRO_LPF_FTYPE1 = 0x01, /**< Refer to table 68 of Datasheet. */
+ LSM6DSL_GYRO_LPF_FTYPE2 = 0x10, /**< Refer to table 68 of Datasheet. */
+ LSM6DSL_GYRO_LPF_FTYPE3 = 0x11 /**< Refer to table 68 of Datasheet. */
+} lsm6dsl_gyro_lpf_t;
+
+/**
+ * @brief LSM6DSL block data update.
+ */
+typedef enum {
+ LSM6DSL_BDU_CONTINUOUS = 0x00, /**< Block data continuously updated. */
+ LSM6DSL_BDU_BLOCKED = 0x40 /**< Block data updated after reading. */
+} lsm6dsl_bdu_t;
+
+/**
+ * @brief LSM6DSL endianness.
+ */
+typedef enum {
+ LSM6DSL_END_LITTLE = 0x00, /**< Little endian. */
+ LSM6DSL_END_BIG = 0x20 /**< Big endian. */
+} lsm6dsl_end_t;
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ LSM6DSL_UNINIT = 0, /**< Not initialized. */
+ LSM6DSL_STOP = 1, /**< Stopped. */
+ LSM6DSL_READY = 2, /**< Ready. */
+} lsm6dsl_state_t;
+
+/**
+ * @brief LSM6DSL configuration structure.
+ */
+typedef struct {
+#if (LSM6DSL_USE_SPI) || defined(__DOXYGEN__)
+ /**
+ * @brief SPI driver associated to this LSM6DSL.
+ */
+ SPIDriver *spip;
+ /**
+ * @brief SPI configuration associated to this LSM6DSL accelerometer
+ * subsystem.
+ */
+ const SPIConfig *accspicfg;
+#endif /* LSM6DSL_USE_SPI */
+#if (LSM6DSL_USE_I2C) || defined(__DOXYGEN__)
+ /**
+ * @brief I2C driver associated to this LSM6DSL.
+ */
+ I2CDriver *i2cp;
+ /**
+ * @brief I2C configuration associated to this LSM6DSL accelerometer
+ * subsystem.
+ */
+ const I2CConfig *i2ccfg;
+ /**
+ * @brief LSM6DSL Slave Address
+ */
+ lsm6dsl_sad_t slaveaddress;
+#endif /* LSM6DSL_USE_I2C */
+ /**
+ * @brief LSM6DSL accelerometer subsystem initial sensitivity.
+ */
+ float *accsensitivity;
+ /**
+ * @brief LSM6DSL accelerometer subsystem initial bias.
+ */
+ float *accbias;
+ /**
+ * @brief LSM6DSL accelerometer subsystem full scale.
+ */
+ lsm6dsl_acc_fs_t accfullscale;
+ /**
+ * @brief LSM6DSL accelerometer subsystem output data rate.
+ */
+ lsm6dsl_acc_odr_t accoutdatarate;
+#if LSM6DSL_USE_ADVANCED || defined(__DOXYGEN__)
+ /**
+ * @brief LSM6DSL accelerometer subsystem low power mode.
+ */
+ lsm6dsl_acc_lp_t acclpmode;
+#endif /* LSM6DSL_USE_ADVANCED */
+ /**
+ * @brief LSM6DSL gyroscope subsystem initial sensitivity.
+ */
+ float *gyrosensitivity;
+ /**
+ * @brief LSM6DSL gyroscope subsystem initial bias.
+ */
+ float *gyrobias;
+ /**
+ * @brief LSM6DSL gyroscope subsystem full scale.
+ */
+ lsm6dsl_gyro_fs_t gyrofullscale;
+ /**
+ * @brief LSM6DSL gyroscope subsystem output data rate.
+ */
+ lsm6dsl_gyro_odr_t gyrooutdatarate;
+#if LSM6DSL_USE_ADVANCED || defined(__DOXYGEN__)
+ /**
+ * @brief LSM6DSL gyroscope subsystem low mode configuration.
+ */
+ lsm6dsl_gyro_lp_t gyrolpmode;
+ /**
+ * @brief LSM6DSL gyroscope subsystem low pass filter configuration.
+ */
+ lsm6dsl_gyro_lpf_t gyrolowpassfilter;
+ /**
+ * @brief LSM6DSL block data update
+ */
+ lsm6dsl_bdu_t blockdataupdate;
+ /**
+ * @brief LSM6DSL endianness
+ */
+ lsm6dsl_end_t endianness;
+#endif /* LSM6DSL_USE_ADVANCED */
+} LSM6DSLConfig;
+
+/**
+ * @brief @p LSM6DSL specific methods.
+ */
+#define _lsm6dsl_methods_alone \
+ /* Change full scale value of LSM6DSL accelerometer subsystem .*/ \
+ msg_t (*acc_set_full_scale)(LSM6DSLDriver *devp, lsm6dsl_acc_fs_t fs); \
+ /* Change full scale value of LSM6DSL gyroscope subsystem .*/ \
+ msg_t (*gyro_set_full_scale)(LSM6DSLDriver *devp, lsm6dsl_gyro_fs_t fs);
+
+/**
+ * @brief @p LSM6DSL specific methods with inherited ones.
+ */
+#define _lsm6dsl_methods \
+ _base_object_methods \
+ _lsm6dsl_methods_alone
+
+/**
+ * @extends BaseObjectVMT
+ *
+ * @brief @p LSM6DSL virtual methods table.
+ */
+struct LSM6DSLVMT {
+ _lsm6dsl_methods
+};
+
+/**
+ * @brief @p LSM6DSLDriver specific data.
+ */
+#define _lsm6dsl_data \
+ _base_sensor_data \
+ /* Driver state.*/ \
+ lsm6dsl_state_t state; \
+ /* Current configuration data.*/ \
+ const LSM6DSLConfig *config; \
+ /* Accelerometer subsystem axes number.*/ \
+ size_t accaxes; \
+ /* Accelerometer subsystem current sensitivity.*/ \
+ float accsensitivity[LSM6DSL_ACC_NUMBER_OF_AXES]; \
+ /* Accelerometer subsystem current bias .*/ \
+ float accbias[LSM6DSL_ACC_NUMBER_OF_AXES]; \
+ /* Accelerometer subsystem current full scale value.*/ \
+ float accfullscale; \
+ /* Gyroscope subsystem axes number.*/ \
+ size_t gyroaxes; \
+ /* Gyroscope subsystem current sensitivity.*/ \
+ float gyrosensitivity[LSM6DSL_GYRO_NUMBER_OF_AXES]; \
+ /* Gyroscope subsystem current Bias.*/ \
+ float gyrobias[LSM6DSL_GYRO_NUMBER_OF_AXES]; \
+ /* Gyroscope subsystem current full scale value.*/ \
+ float gyrofullscale;
+
+/**
+ * @brief LSM6DSL 6-axis accelerometer/gyroscope class.
+ */
+struct LSM6DSLDriver {
+ /** @brief Virtual Methods Table.*/
+ const struct LSM6DSLVMT *vmt;
+ /** @brief Base accelerometer interface.*/
+ BaseAccelerometer acc_if;
+ /** @brief Base gyroscope interface.*/
+ BaseGyroscope gyro_if;
+ _lsm6dsl_data
+};
+/** @} */
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Return the number of axes of the BaseAccelerometer.
+ *
+ * @param[in] devp pointer to @p LSM6DSLDriver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define lsm6dslAccelerometerGetAxesNumber(devp) \
+ accelerometerGetAxesNumber(&((devp)->acc_if))
+
+/**
+ * @brief Retrieves raw data from the BaseAccelerometer.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LSM6DSLDriver.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lsm6dslAccelerometerReadRaw(devp, axes) \
+ accelerometerReadRaw(&((devp)->acc_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseAccelerometer.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as milli-G.
+ * @note The axes array must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LSM6DSLDriver.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lsm6dslAccelerometerReadCooked(devp, axes) \
+ accelerometerReadCooked(&((devp)->acc_if), axes)
+
+/**
+ * @brief Set bias values for the BaseAccelerometer.
+ * @note Bias must be expressed as milli-G.
+ * @note The bias buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LSM6DSLDriver.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm6dslAccelerometerSetBias(devp, bp) \
+ accelerometerSetBias(&((devp)->acc_if), bp)
+
+/**
+ * @brief Reset bias values for the BaseAccelerometer.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] devp pointer to @p LSM6DSLDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm6dslAccelerometerResetBias(devp) \
+ accelerometerResetBias(&((devp)->acc_if))
+
+/**
+ * @brief Set sensitivity values for the BaseAccelerometer.
+ * @note Sensitivity must be expressed as milli-G/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseAccelerometer axes number.
+ *
+ * @param[in] devp pointer to @p LSM6DSLDriver.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm6dslAccelerometerSetSensitivity(devp, sp) \
+ accelerometerSetSensitivity(&((devp)->acc_if), sp)
+
+/**
+ * @brief Reset sensitivity values for the BaseAccelerometer.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] devp pointer to @p LSM6DSLDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lsm6dslAccelerometerResetSensitivity(devp) \
+ accelerometerResetSensitivity(&((devp)->acc_if))
+
+/**
+ * @brief Changes the LSM6DSLDriver accelerometer fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p LSM6DSLDriver.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lsm6dslAccelerometerSetFullScale(devp, fs) \
+ (devp)->vmt->acc_set_full_scale(devp, fs)
+
+/**
+ * @brief Return the number of axes of the BaseGyroscope.
+ *
+ * @param[in] devp pointer to @p LSM6DSLDriver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define lsm6dslGyroscopeGetAxesNumber(devp) \
+ gyroscopeGetAxesNumber(&((devp)->gyro_if))
+
+/**
+ * @brief Retrieves raw data from the BaseGyroscope.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseGyroscope axes number.
+ *
+ * @param[in] devp pointer to @p LSM6DSLDriver.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lsm6dslGyroscopeReadRaw(devp, axes) \
+ gyroscopeReadRaw(&((devp)->gyro_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseGyroscope.
+ * @note This data is manipulated according to the formula
+ * cooked = (raw * sensitivity) - bias.
+ * @note Final data is expressed as DPS.
+ * @note The axes array must be at least the same size of the
+ * BaseGyroscope axes number.
+ *
+ * @param[in] devp pointer to @p LSM6DSLDriver.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lsm6dslGyroscopeReadCooked(devp, axes) \
+ gyroscopeReadCooked(&((devp)->gyro_if), axes)
+
+/**
+ * @brief Samples bias values for the BaseGyroscope.
+ * @note The LSM6DSL shall not be moved during the whole procedure.
+ * @note After this function internal bias is automatically updated.
+ * @note The behavior of this function depends on @p LSM6DSL_BIAS_ACQ_TIMES
+ * and @p LSM6DSL_BIAS_SETTLING_US.
+ *
+ * @param[in] devp pointer to @p LSM6DSLDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define lsm6dslGyroscopeSampleBias(devp) \
+ gyroscopeSampleBias(&((devp)->gyro_if))
+
+/**
+ * @brief Set bias values for the BaseGyroscope.
+ * @note Bias must be expressed as DPS.
+ * @note The bias buffer must be at least the same size of the BaseGyroscope
+ * axes number.
+ *
+ * @param[in] devp pointer to @p LSM6DSLDriver.
+ * @param[in] bp a buffer which contains biases.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm6dslGyroscopeSetBias(devp, bp) \
+ gyroscopeSetBias(&((devp)->gyro_if), bp)
+
+/**
+ * @brief Reset bias values for the BaseGyroscope.
+ * @note Default biases value are obtained from device datasheet when
+ * available otherwise they are considered zero.
+ *
+ * @param[in] devp pointer to @p LSM6DSLDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm6dslGyroscopeResetBias(devp) \
+ gyroscopeResetBias(&((devp)->gyro_if))
+
+/**
+ * @brief Set sensitivity values for the BaseGyroscope.
+ * @note Sensitivity must be expressed as DPS/LSB.
+ * @note The sensitivity buffer must be at least the same size of the
+ * BaseGyroscope axes number.
+ *
+ * @param[in] devp pointer to @p LSM6DSLDriver.
+ * @param[in] sp a buffer which contains sensitivities.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ *
+ * @api
+ */
+#define lsm6dslGyroscopeSetSensitivity(devp, sp) \
+ gyroscopeSetSensitivity(&((devp)->gyro_if), sp)
+
+/**
+ * @brief Reset sensitivity values for the BaseGyroscope.
+ * @note Default sensitivities value are obtained from device datasheet.
+ *
+ * @param[in] devp pointer to @p LSM6DSLDriver.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lsm6dslGyroscopeResetSensitivity(devp) \
+ gyroscopeResetSensitivity(&((devp)->gyro_if))
+
+/**
+ * @brief Changes the LSM6DSLDriver gyroscope fullscale value.
+ * @note This function also rescale sensitivities and biases based on
+ * previous and next fullscale value.
+ * @note A recalibration is highly suggested after calling this function.
+ *
+ * @param[in] devp pointer to @p LSM6DSLDriver.
+ * @param[in] fs new fullscale value.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET otherwise.
+ *
+ * @api
+ */
+#define lsm6dslGyroscopeSetFullScale(devp, fs) \
+ (devp)->vmt->acc_set_full_scale(devp, fs)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void lsm6dslObjectInit(LSM6DSLDriver *devp);
+ void lsm6dslStart(LSM6DSLDriver *devp, const LSM6DSLConfig *config);
+ void lsm6dslStop(LSM6DSLDriver *devp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LSM6DSL_H_ */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/lsm6dsl.mk b/ChibiOS_20.3.2/os/ex/devices/ST/lsm6dsl.mk
new file mode 100644
index 0000000..0605f06
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/lsm6dsl.mk
@@ -0,0 +1,10 @@
+# List of all the LSM6DSL device files.
+LSM6DSLSRC := $(CHIBIOS)/os/ex/devices/ST/lsm6dsl.c
+
+# Required include directories
+LSM6DSLINC := $(CHIBIOS)/os/ex/include \
+ $(CHIBIOS)/os/ex/devices/ST
+
+# Shared variables
+ALLCSRC += $(LSM6DSLSRC)
+ALLINC += $(LSM6DSLINC)
\ No newline at end of file
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/vl53l0x.h b/ChibiOS_20.3.2/os/ex/devices/ST/vl53l0x.h
new file mode 100644
index 0000000..1fc8f9b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/vl53l0x.h
@@ -0,0 +1,443 @@
+/*
+ ChibiOS - Copyright (C) 2016..2018 Edoardo Lombardi, Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+*/
+
+/**
+ * @file vl53l0x.h
+ * @brief VL53L0X MEMS interface module header.
+ *
+ * @addtogroup VL53L0X
+ * @ingroup EX_ST
+ * @{
+ */
+#ifndef _VL53L0X_H_
+#define _VL53L0X_H_
+
+#include "ex_rangefinder.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Version identification
+ * @{
+ */
+/**
+ * @brief VL53L0X driver version string.
+ */
+#define EX_VL53L0X_VERSION "1.0.0"
+
+/**
+ * @brief VL53L0X driver version major number.
+ */
+#define EX_VL53L0X_MAJOR 1
+
+/**
+ * @brief VL53L0X driver version minor number.
+ */
+#define EX_VL53L0X_MINOR 0
+
+/**
+ * @brief VL53L0X driver version patch number.
+ */
+#define EX_VL53L0X_PATCH 0
+/** @} */
+
+/**
+ * @brief VL53L0X rangefinder subsystem characteristics.
+ * @note Sensitivity is expressed as hPa/LSB whereas hPa stand for
+ * hectopascal.
+ * @note Bias is expressed as hPa.
+ *
+ * @{
+ */
+#define VL53L0X_RANGE_NUMBER_OF_AXES 1U
+
+/* CHTODO: Check this. */
+#define VL53L0X_RANGE_SENS 0.00024414f
+#define VL53L0X_RANGE_BIAS 0.0f
+/** @} */
+
+/**
+ * @name VL53L0X register addresses
+ * @{
+ */
+#define VL53L0X_REG_SYSRANGE_START 0x00
+#define VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG 0x01
+#define VL53L0X_REG_SYSTEM_INTERMEASUREMENT_PERIOD 0x04
+#define VL53L0X_REG_SYSTEM_RANGE_CONFIG 0x09
+#define VL53L0X_REG_SYSTEM_INTERRUPT_CONFIG_GPIO 0x0A
+#define VL53L0X_REG_SYSTEM_INTERRUPT_CLEAR 0x0B
+#define VL53L0X_REG_SYSTEM_THRESH_HIGH 0x0C
+#define VL53L0X_REG_SYSTEM_THRESH_LOW 0x0E
+
+#define VL53L0X_REG_RESULT_INTERRUPT_STATUS 0x13
+#define VL53L0X_REG_RESULT_RANGE_STATUS 0x14
+
+#define VL53L0X_REG_CROSSTALK_COMPENSATION_PEAK_RATE_MCPS 0x20
+#define VL53L0X_REG_PRE_RANGE_CONFIG_MIN_SNR 0x27
+#define VL53L0X_REG_ALGO_PART_TO_PART_RANGE_OFFSET_MM 0x28
+#define VL53L0X_REG_ALGO_PHASECAL_LIM 0x30
+#define VL53L0X_REG_ALGO_PHASECAL_CONFIG_TIMEOUT 0x30
+#define VL53L0X_REG_GLOBAL_CONFIG_VCSEL_WIDTH 0x32
+#define VL53L0X_REG_HISTOGRAM_CONFIG_INITIAL_PHASE_SELECT 0x33
+
+#define VL53L0X_REG_FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT 0x44
+#define VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_LOW 0x47
+#define VL53L0X_REG_FINAL_RANGE_CONFIG_VALID_PHASE_HIGH 0x48
+#define VL53L0X_REG_DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD 0x4E
+#define VL53L0X_REG_DYNAMIC_SPAD_REF_EN_START_OFFSET 0x4F
+
+#define VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD 0x50
+#define VL53L0X_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_HI 0x51
+#define VL53L0X_REG_PRE_RANGE_CONFIG_TIMEOUT_MACROP_LO 0x52
+#define VL53L0X_REG_HISTOGRAM_CONFIG_READOUT_CTRL 0x55
+#define VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_LOW 0x56
+#define VL53L0X_REG_PRE_RANGE_CONFIG_VALID_PHASE_HIGH 0x57
+
+#define VL53L0X_REG_MSRC_CONFIG_CONTROL 0x60
+#define VL53L0X_REG_PRE_RANGE_CONFIG_SIGMA_THRESH_HI 0x61
+#define VL53L0X_REG_PRE_RANGE_CONFIG_SIGMA_THRESH_LO 0x62
+#define VL53L0X_REG_PRE_RANGE_MIN_COUNT_RATE_RTN_LIMIT 0x64
+#define VL53L0X_REG_FINAL_RANGE_CONFIG_MIN_SNR 0x67
+
+#define VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD 0x70
+#define VL53L0X_REG_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_HI 0x71
+#define VL53L0X_REG_FINAL_RANGE_CONFIG_TIMEOUT_MACROP_LO 0x72
+
+#define VL53L0X_REG_POWER_MANAGEMENT_GO1_POWER_FORCE 0x80
+#define VL53L0X_REG_SYSTEM_HISTOGRAM_BIN 0x81
+#define VL53L0X_REG_GPIO_HV_MUX_ACTIVE_HIGH 0x84
+#define VL53L0X_REG_VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV 0x89
+#define VL53L0X_REG_I2C_SLAVE_DEVICE_ADDRESS 0x8A
+
+#define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_0 0xB0
+#define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_1 0xB1
+#define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_2 0xB2
+#define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_3 0xB3
+#define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_4 0xB4
+#define VL53L0X_REG_GLOBAL_CONFIG_SPAD_ENABLES_REF_5 0xB5
+#define VL53L0X_REG_GLOBAL_CONFIG_REF_EN_START_SELECT 0xB6
+#define VL53L0X_REG_RESULT_PEAK_SIGNAL_RATE_REF 0xB6
+#define VL53L0X_REG_RESULT_CORE_AMBIENT_WINDOW_EVENTS_RTN 0xBC
+#define VL53L0X_REG_SOFT_RESET_GO2_SOFT_RESET_N 0xBF
+
+#define VL53L0X_REG_RESULT_CORE_RANGING_TOTAL_EVENTS_RTN 0xC0
+#define VL53L0X_REG_IDENTIFICATION_MODEL_ID 0xC0
+#define VL53L0X_REG_IDENTIFICATION_REVISION_ID 0xC2
+
+#define VL53L0X_REG_RESULT_CORE_AMBIENT_WINDOW_EVENTS_REF 0xD0
+#define VL53L0X_REG_RESULT_CORE_RANGING_TOTAL_EVENTS_REF 0xD4
+
+#define VL53L0X_REG_OSC_CALIBRATE_VAL 0xF8
+/** @} */
+
+/**
+ * @name VL53L0X_INT_CFG register bits definitions
+ * @{
+ */
+#define VL53L0X_INT_CFG_MASK 0xFF
+#define VL53L0X_INT_CFG_PHE (1 << 0)
+#define VL53L0X_INT_CFG_PLE (1 << 1)
+#define VL53L0X_INT_CFG_LIR (1 << 2)
+#define VL53L0X_INT_CFG_DIFF_EN (1 << 3)
+#define VL53L0X_INT_CFG_RESET_AZ (1 << 4)
+#define VL53L0X_INT_CFG_AUTOZERO (1 << 5)
+#define VL53L0X_INT_CFG_RESET_ARP (1 << 6)
+#define VL53L0X_INT_CFG_AUTORIFP (1 << 7)
+/** @} */
+
+/**
+ * @name VL53L0X_CTRL_REG1 register bits definitions
+ * @{
+ */
+#define VL53L0X_CTRL_REG1_MASK 0x7F
+#define VL53L0X_CTRL_REG1_SIM (1 << 0)
+#define VL53L0X_CTRL_REG1_BDU (1 << 1)
+#define VL53L0X_CTRL_REG1_LPFP_CFG (1 << 2)
+#define VL53L0X_CTRL_REG1_LPFP_EN (1 << 3)
+#define VL53L0X_CTRL_REG1_ODR0 (1 << 4)
+#define VL53L0X_CTRL_REG1_ODR1 (1 << 5)
+#define VL53L0X_CTRL_REG1_ODR2 (1 << 6)
+/** @} */
+
+/**
+ * @name VL53L0X_CTRL_REG2 register bits definitions
+ * @{
+ */
+#define VL53L0X_CTRL_REG2_MASK 0xFD
+#define VL53L0X_CTRL_REG2_ONE_SHOT (1 << 0)
+#define VL53L0X_CTRL_REG2_SWRESET (1 << 2)
+#define VL53L0X_CTRL_REG2_I2C_DIS (1 << 3)
+#define VL53L0X_CTRL_REG2_IF_ADD_INC (1 << 4)
+#define VL53L0X_CTRL_REG2_STOP_ON_FTH (1 << 5)
+#define VL53L0X_CTRL_REG2_FIFO_EN (1 << 6)
+#define VL53L0X_CTRL_REG2_BOOT (1 << 7)
+/** @} */
+
+/**
+ * @name VL53L0X_CTRL_REG3 register bits definitions
+ * @{
+ */
+#define VL53L0X_CTRL_REG3_MASK 0xFF
+#define VL53L0X_CTRL_REG3_INT_S1 (1 << 0)
+#define VL53L0X_CTRL_REG3_INT_S2 (1 << 1)
+#define VL53L0X_CTRL_REG3_DRDY (1 << 2)
+#define VL53L0X_CTRL_REG3_F_OVR (1 << 3)
+#define VL53L0X_CTRL_REG3_F_FTH (1 << 4)
+#define VL53L0X_CTRL_REG3_F_FSS5 (1 << 5)
+#define VL53L0X_CTRL_REG3_PP_OD (1 << 6)
+#define VL53L0X_CTRL_REG3_INT_H_L (1 << 7)
+/** @} */
+
+/**
+ * @name VL53L0X_INT_SRC register bits definitions
+ * @{
+ */
+#define VL53L0X_INT_SRC_MASK 0x87
+#define VL53L0X_INT_SRC_PH (1 << 0)
+#define VL53L0X_INT_SRC_PL (1 << 1)
+#define VL53L0X_INT_SRC_IA (1 << 2)
+#define VL53L0X_INT_SRC_BOOT_STATUS (1 << 8)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief VL53L0X I2C interface switch.
+ * @details If set to @p TRUE the support for I2C is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(VL53L0X_USE_I2C) || defined(__DOXYGEN__)
+#define VL53L0X_USE_I2C TRUE
+#endif
+
+/**
+ * @brief VL53L0X shared I2C switch.
+ * @details If set to @p TRUE the device acquires I2C bus ownership
+ * on each transaction.
+ * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(VL53L0X_SHARED_I2C) || defined(__DOXYGEN__)
+#define VL53L0X_SHARED_I2C FALSE
+#endif
+
+/**
+ * @brief VL53L0X advanced configurations switch.
+ * @details If set to @p TRUE more configurations are available.
+ * @note The default is @p FALSE.
+ */
+#if !defined(VL53L0X_USE_ADVANCED) || defined(__DOXYGEN__)
+#define VL53L0X_USE_ADVANCED FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if VL53L0X_USE_I2C && !HAL_USE_I2C
+#error "VL53L0X_USE_I2C requires HAL_USE_I2C"
+#endif
+
+#if VL53L0X_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION
+#error "VL53L0X_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @name VL53L0X data structures and types.
+ * @{
+ */
+/**
+ * @brief Structure representing a VL53L0X driver.
+ */
+typedef struct VL53L0XDriver VL53L0XDriver;
+
+/**
+ * @brief VL53L0X slave address
+ */
+typedef enum {
+ VL53L0X_SAD_DEFAULT = 0x29, /**< Default slave address */
+}vl53l0x_sad_t;
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ VL53L0X_UNINIT = 0, /**< Not initialized. */
+ VL53L0X_STOP = 1, /**< Stopped. */
+ VL53L0X_READY = 2, /**< Ready. */
+} vl53l0x_state_t;
+
+/**
+ * @brief VL53L0X configuration structure.
+ */
+typedef struct {
+#if VL53L0X_USE_I2C || defined(__DOXYGEN__)
+ /**
+ * @brief I2C driver associated to this VL53L0X.
+ */
+ I2CDriver *i2cp;
+ /**
+ * @brief I2C configuration associated to this VL53L0X.
+ */
+ const I2CConfig *i2ccfg;
+ /**
+ * @brief VL53L0X slave address
+ */
+ vl53l0x_sad_t slaveaddress;
+#endif /* VL53L0X_USE_I2C */
+#if VL53L0X_USE_ADVANCED || defined(__DOXYGEN__)
+ /**
+ * @brief Dummy placeholder
+ */
+#endif
+} VL53L0XConfig;
+
+/**
+ * @brief @p VL53L0X specific methods.
+ * @note No methods so far, just a common ancestor interface.
+ */
+#define _vl53l0x_methods_alone
+
+/**
+ * @brief @p VL53L0X specific methods with inherited ones.
+ */
+#define _vl53l0x_methods \
+ _base_object_methods \
+ _vl53l0x_methods_alone
+
+/**
+ * @extends BaseObjectVMT
+ *
+ * @brief @p VL53L0X virtual methods table.
+ */
+struct VL53L0XVMT {
+ _vl53l0x_methods
+};
+
+/**
+ * @brief @p VL53L0XDriver specific data.
+ */
+#define _vl53l0x_data \
+ /* Driver state.*/ \
+ vl53l0x_state_t state; \
+ /* Current configuration data.*/ \
+ const VL53L0XConfig *config; \
+ /* RangeFinder subsystem axes number.*/ \
+ size_t rangeaxes;
+
+/**
+ * @brief VL53L0X 2-axis rangemeter/thermometer class.
+ */
+struct VL53L0XDriver {
+ /** @brief Virtual Methods Table.*/
+ const struct VL53L0XVMT *vmt;
+ /** @brief Base rangemeter interface.*/
+ BaseRangeFinder range_if;
+ _vl53l0x_data
+};
+/** @} */
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Return the number of axes of the BaseRangeFinder.
+ *
+ * @param[in] devp pointer to @p VL53L0XDriver.
+ *
+ * @return the number of axes.
+ *
+ * @api
+ */
+#define vl53l0xRangeFinderGetAxesNumber(devp) \
+ rangemeterGetAxesNumber(&((devp)->range_if))
+
+/**
+ * @brief Retrieves raw data from the BaseRangeFinder.
+ * @note This data is retrieved from MEMS register without any algebraical
+ * manipulation.
+ * @note The axes array must be at least the same size of the
+ * BaseRangeFinder axes number.
+ *
+ * @param[in] devp pointer to @p VL53L0XDriver.
+ * @param[out] axes a buffer which would be filled with raw data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define vl53l0xRangeFinderReadRaw(devp, axes) \
+ rangemeterReadRaw(&((devp)->range_if), axes)
+
+/**
+ * @brief Retrieves cooked data from the BaseRangeFinder.
+ * @note Final data is expressed as mm.
+ * @note The axes array must be at least the same size of the
+ * BaseRangeFinder axes number.
+ *
+ * @param[in] devp pointer to @p VL53L0XDriver.
+ * @param[out] axes a buffer which would be filled with cooked data.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+#define vl53l0xRangeFinderReadCooked(devp, axes) \
+ rangemeterReadCooked(&((devp)->range_if), axes)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void vl53l0xObjectInit(VL53L0XDriver *devp);
+ void vl53l0xStart(VL53L0XDriver *devp, const VL53L0XConfig *config);
+ void vl53l0xStop(VL53L0XDriver *devp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VL53L0X_H_ */
+
+/** @} */
+
diff --git a/ChibiOS_20.3.2/os/ex/devices/ST/vl53l0x.mk b/ChibiOS_20.3.2/os/ex/devices/ST/vl53l0x.mk
new file mode 100644
index 0000000..de22649
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/devices/ST/vl53l0x.mk
@@ -0,0 +1,10 @@
+# List of all the VL53L0X device files.
+VL53L0XSRC := $(CHIBIOS)/os/ex/devices/ST/vl53l0x.c
+
+# Required include directories
+VL53L0XINC := $(CHIBIOS)/os/ex/include \
+ $(CHIBIOS)/os/ex/devices/ST
+
+# Shared variables
+ALLCSRC += $(VL53L0XSRC)
+ALLINC += $(VL53L0XINC)
\ No newline at end of file
diff --git a/ChibiOS_20.3.2/os/ex/dox/ex_accelerometer.dox b/ChibiOS_20.3.2/os/ex/dox/ex_accelerometer.dox
new file mode 100644
index 0000000..8ac9c79
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/dox/ex_accelerometer.dox
@@ -0,0 +1,22 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup EX_ACCELEROMETER Generic Accelerometer Interface
+ * @brief EX Generic Accelerometer Interface.
+ *
+ * @ingroup EX_ABSTRACT_PERIPHERALS
+ */
diff --git a/ChibiOS_20.3.2/os/ex/dox/ex_barometer.dox b/ChibiOS_20.3.2/os/ex/dox/ex_barometer.dox
new file mode 100644
index 0000000..ed9a2ab
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/dox/ex_barometer.dox
@@ -0,0 +1,22 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup EX_BAROMETER Generic Barometer Interface
+ * @brief EX Generic Barometer Interface.
+ *
+ * @ingroup EX_ABSTRACT_PERIPHERALS
+ */
diff --git a/ChibiOS_20.3.2/os/ex/dox/ex_compass.dox b/ChibiOS_20.3.2/os/ex/dox/ex_compass.dox
new file mode 100644
index 0000000..967008c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/dox/ex_compass.dox
@@ -0,0 +1,22 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup EX_COMPASS Generic Compass Interface
+ * @brief EX Generic Compass Interface.
+ *
+ * @ingroup EX_ABSTRACT_PERIPHERALS
+ */
diff --git a/ChibiOS_20.3.2/os/ex/dox/ex_displays.dox b/ChibiOS_20.3.2/os/ex/dox/ex_displays.dox
new file mode 100644
index 0000000..fdd77ee
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/dox/ex_displays.dox
@@ -0,0 +1,22 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup EX_RANGEFINDER Generic Range Finder Interface
+ * @brief EX Generic Range Finder Interface.
+ *
+ * @ingroup EX_ABSTRACT_PERIPHERALS
+ */
diff --git a/ChibiOS_20.3.2/os/ex/dox/ex_gyro.dox b/ChibiOS_20.3.2/os/ex/dox/ex_gyro.dox
new file mode 100644
index 0000000..3827183
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/dox/ex_gyro.dox
@@ -0,0 +1,22 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup EX_GYROSCOPE Generic Gyroscope Interface
+ * @brief EX Generic Gyroscope Interface.
+ *
+ * @ingroup EX_ABSTRACT_PERIPHERALS
+ */
diff --git a/ChibiOS_20.3.2/os/ex/dox/ex_hygrometer.dox b/ChibiOS_20.3.2/os/ex/dox/ex_hygrometer.dox
new file mode 100644
index 0000000..9387112
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/dox/ex_hygrometer.dox
@@ -0,0 +1,22 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup EX_HYGROMETER Generic Hygrometer Interface
+ * @brief EX Generic Hygrometer Interface.
+ *
+ * @ingroup EX_ABSTRACT_PERIPHERALS
+ */
diff --git a/ChibiOS_20.3.2/os/ex/dox/ex_rangefinder.dox b/ChibiOS_20.3.2/os/ex/dox/ex_rangefinder.dox
new file mode 100644
index 0000000..06786f3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/dox/ex_rangefinder.dox
@@ -0,0 +1,22 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup EX_DISPLAYS Generic Display Interface
+ * @brief EX Generic Display Interface.
+ *
+ * @ingroup EX_ABSTRACT_PERIPHERALS
+ */
diff --git a/ChibiOS_20.3.2/os/ex/dox/ex_sensor.dox b/ChibiOS_20.3.2/os/ex/dox/ex_sensor.dox
new file mode 100644
index 0000000..8b09b6a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/dox/ex_sensor.dox
@@ -0,0 +1,22 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup EX_SENSORS Generic Sensor Interface
+ * @brief EX Generic Sensor Interface.
+ *
+ * @ingroup EX_ABSTRACT_PERIPHERALS
+ */
diff --git a/ChibiOS_20.3.2/os/ex/dox/ex_thermometer.dox b/ChibiOS_20.3.2/os/ex/dox/ex_thermometer.dox
new file mode 100644
index 0000000..77f4bda
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/dox/ex_thermometer.dox
@@ -0,0 +1,22 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup EX_THERMOMETER Generic Thermometer Interface
+ * @brief EX Generic Thermometer Interface.
+ *
+ * @ingroup EX_ABSTRACT_PERIPHERALS
+ */
diff --git a/ChibiOS_20.3.2/os/ex/dox/main.dox b/ChibiOS_20.3.2/os/ex/dox/main.dox
new file mode 100644
index 0000000..a02193d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/dox/main.dox
@@ -0,0 +1,92 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup EX EX
+ * @brief EXternal peripherals.
+ * @details Under ChibiOS the set of the complex device driver interfaces
+ * dedicated to external peripherals is called the EX subsystem. The EX resides
+ * on top of EX and is actually a set of libraries for external devices like
+ * MEMS, Displays, Flash memories and so on. These libraries are the
+ * implementation of one or more Abstract Interfaces brought by EX subsystem.
+ * EX also relies on EX normal drivers to interface the peripherals.
+ *
+ * @section ex_complex_drivers_architecture EX Complex Drivers Architecture
+ * Each EX driver can be considered as a standalone Complex Device Driver. For
+ * ease of use these drivers are grouped by vendor:
+ * - Bosch Devices
+ * - STMicroelectronics Devices
+ * .
+ *
+ * @section bosch_devices Bosch Devices
+ * This section contains all the drivers of devices produced by Bosch.
+ * Devices currently supported are MEMS and are:
+ * - @b BMP085: Digital pressure sensor;
+ * .
+ *
+ * @section stmicroelectronics_devices STMicroelectronics Devices
+ * This section contains all the drivers of devices produced by
+ * STMicroelectronics. Devices currently supported are MEMS and are:
+ * - @b HTS221: Capacitive digital humidity sensor;
+ * - @b L3GD20: 3-axis digital gyroscope;
+ * - @b LIS3DSH: 3-axis digital motion sensor;
+ * - @b LIS3MDL: Ultra low power, high performances 3-axis magnetometer;
+ * - @b LIS302DL: 3-axis motion sensor;
+ * - @b LPS25H: Piezoresistive 260-1260 hPa pressure sensor;
+ * - @b LSM6DS0: 6-axis iNEMO inertial module;
+ * - @b LSM303DLHC: Ultra compact high performance e-compass;
+ * .
+ */
+ *
+ * @section hal_peripheral interfaces EX Peripheral Interfaces
+ * These are a particular case of EX Interfaces since they are an abstraction
+ * of a hardware.
+ */
+
+/**
+ * @defgroup EX_INFO Info
+ * @brief EX information.
+ *
+ * @ingroup EX
+ */
+
+/**
+ * @defgroup EX_ABSTRACT_PERIPHERALS Peripheral Interfaces
+ * @brief EX Abstract Peripheral Interfaces.
+ *
+ * @ingroup EX
+ */
+
+/**
+ * @defgroup EX_DEVICES Devices
+ * @brief EX devices organized per vendor.
+ *
+ * @ingroup EX
+ */
+
+/**
+ * @defgroup EX_BOSCH Bosch Devices
+ * @brief Bosch Devices.
+ *
+ * @ingroup EX_DEVICES
+ */
+
+/**
+ * @defgroup EX_ST STMicroelectronics Devices
+ * @brief STMicroelectronics Devices.
+ *
+ * @ingroup EX_DEVICES
+ */
diff --git a/ChibiOS_20.3.2/os/ex/include/ex.h b/ChibiOS_20.3.2/os/ex/include/ex.h
new file mode 100644
index 0000000..8c521c4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/include/ex.h
@@ -0,0 +1,107 @@
+/*
+ ChibiOS - Copyright (C) 2016..2018 Rocco Marco Guglielmi
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file ex.h
+ * @brief EX main include file.
+ *
+ * @addtogroup EX_INFO
+ * @details EX related info.
+ * @{
+ */
+
+#ifndef EX_H
+#define EX_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @brief ChibiOS/EX identification macro.
+ */
+#define _CHIBIOS_EX_
+
+/**
+ * @brief Stable release flag.
+ */
+#define CH_EX_STABLE 1
+
+/**
+ * @name ChibiOS/EX version identification
+ * @{
+ */
+/**
+ * @brief EX version string.
+ */
+#define CH_EX_VERSION "1.2.0"
+
+/**
+ * @brief EX version major number.
+ */
+#define CH_EX_MAJOR 1
+
+/**
+ * @brief EX version minor number.
+ */
+#define CH_EX_MINOR 2
+
+/**
+ * @brief EX version patch number.
+ */
+#define CH_EX_PATCH 0
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Late inclusions. */
+/*===========================================================================*/
+
+#include "ex_sensors.h"
+#include "ex_accelerometer.h"
+#include "ex_barometer.h"
+#include "ex_compass.h"
+#include "ex_displays.h"
+#include "ex_gyroscope.h"
+#include "ex_hygrometer.h"
+#include "ex_rangefinder.h"
+#include "ex_thermometer.h"
+
+#endif /* EX_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/include/ex_accelerometer.h b/ChibiOS_20.3.2/os/ex/include/ex_accelerometer.h
new file mode 100644
index 0000000..4520ce0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/include/ex_accelerometer.h
@@ -0,0 +1,219 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Rocco Marco Guglielmi
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ex_accelerometer.h
+ * @brief Generic accelerometer interface header.
+ *
+ * @addtogroup EX_ACCELEROMETER
+ * @{
+ */
+
+#ifndef EX_ACCELEROMETER_H
+#define EX_ACCELEROMETER_H
+
+#include "ex_sensors.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief BaseAccelerometer specific methods.
+ */
+#define _base_accelerometer_methods_alone \
+ /* Invoke the set bias procedure.*/ \
+ msg_t (*set_bias)(void *instance, float biases[]); \
+ /* Remove bias stored data.*/ \
+ msg_t (*reset_bias)(void *instance); \
+ /* Invoke the set sensitivity procedure.*/ \
+ msg_t (*set_sensitivity)(void *instance, float sensitivities[]); \
+ /* Restore sensitivity stored data to default.*/ \
+ msg_t (*reset_sensitivity)(void *instance);
+
+/**
+ * @brief BaseAccelerometer specific methods with inherited ones.
+ */
+#define _base_accelerometer_methods \
+ _base_sensor_methods \
+ _base_accelerometer_methods_alone
+
+/**
+ * @brief @p BaseAccelerometer virtual methods table.
+ */
+struct BaseAccelerometerVMT {
+ _base_accelerometer_methods
+};
+
+/**
+ * @brief @p BaseAccelerometer specific data.
+ */
+#define _base_accelerometer_data \
+ _base_sensor_data
+
+/**
+ * @extends BaseSensor
+ *
+ * @brief Base accelerometer class.
+ * @details This class represents a generic a generic accelerometer.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct BaseAccelerometerVMT *vmt;
+ _base_accelerometer_data
+} BaseAccelerometer;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions (BaseAccelerometer)
+ * @{
+ */
+/**
+ * @brief Accelerometer get axes number.
+ *
+ * @param[in] ip pointer to a @p BaseAccelerometer class.
+ * @return The number of axes of the BaseAccelerometer
+ *
+ * @api
+ */
+#define accelerometerGetAxesNumber(ip) \
+ (ip)->vmt->get_channels_number(ip)
+
+/**
+ * @brief Accelerometer read raw data.
+ *
+ * @param[in] ip pointer to a @p BaseAccelerometer class.
+ * @param[in] dp pointer to a data array.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define accelerometerReadRaw(ip, dp) \
+ (ip)->vmt->read_raw(ip, dp)
+
+/**
+ * @brief Accelerometer read cooked data.
+ *
+ * @param[in] ip pointer to a @p BaseAccelerometer class.
+ * @param[in] dp pointer to a data array.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define accelerometerReadCooked(ip, dp) \
+ (ip)->vmt->read_cooked(ip, dp)
+
+/**
+ * @brief Updates accelerometer bias data from received buffer.
+ * @note The bias buffer must have the same length of the
+ * the accelerometer axes number.
+ *
+ *
+ * @param[in] ip pointer to a @p BaseAccelerometer class.
+ * @param[in] bp pointer to a buffer of bias values.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define accelerometerSetBias(ip, bp) \
+ (ip)->vmt->set_bias(ip, bp)
+
+/**
+ * @brief Reset accelerometer bias data restoring it to zero.
+ *
+ * @param[in] ip pointer to a @p BaseAccelerometer class.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define accelerometerResetBias(ip) \
+ (ip)->vmt->reset_bias(ip)
+
+/**
+ * @brief Updates accelerometer sensitivity data from received buffer.
+ * @note The sensitivity buffer must have the same length of the
+ * the accelerometer axes number.
+ *
+ * @param[in] ip pointer to a @p BaseAccelerometer class.
+ * @param[in] sp pointer to a buffer of sensitivity values.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define accelerometerSetSensitivity(ip, sp) \
+ (ip)->vmt->set_sensitivity(ip, sp)
+
+/**
+ * @brief Reset accelerometer sensitivity data restoring it to its typical
+ * value.
+ *
+ * @param[in] ip pointer to a @p BaseAccelerometer class.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define accelerometerResetSensitivity(ip) \
+ (ip)->vmt->reset_sensitivity(ip)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EX_ACCELEROMETER_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/include/ex_barometer.h b/ChibiOS_20.3.2/os/ex/include/ex_barometer.h
new file mode 100644
index 0000000..b45f08c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/include/ex_barometer.h
@@ -0,0 +1,218 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Rocco Marco Guglielmi
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ex_barometer.h
+ * @brief Generic barometer interface header.
+ *
+ * @addtogroup EX_BAROMETER
+ * @{
+ */
+
+#ifndef EX_BAROMETER_H
+#define EX_BAROMETER_H
+
+#include "ex_sensors.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief BaseBarometer specific methods.
+ */
+#define _base_barometer_methods_alone \
+ /* Invoke the set bias procedure.*/ \
+ msg_t (*set_bias)(void *instance, float biases[]); \
+ /* Remove bias stored data.*/ \
+ msg_t (*reset_bias)(void *instance); \
+ /* Invoke the set sensitivity procedure.*/ \
+ msg_t (*set_sensitivity)(void *instance, float sensitivities[]); \
+ /* Restore sensitivity stored data to default.*/ \
+ msg_t (*reset_sensitivity)(void *instance);
+
+
+/**
+ * @brief BaseBarometer specific methods with inherited ones.
+ */
+#define _base_barometer_methods \
+ _base_sensor_methods \
+ _base_barometer_methods_alone
+
+/**
+ * @brief @p BaseBarometer virtual methods table.
+ */
+struct BaseBarometerVMT {
+ _base_barometer_methods
+};
+
+/**
+ * @brief @p BaseBarometer specific data.
+ */
+#define _base_barometer_data \
+ _base_sensor_data
+
+/**
+ * @extends BaseSensor
+ *
+ * @brief Base barometer class.
+ * @details This class represents a generic barometer.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct BaseBarometerVMT *vmt;
+ _base_barometer_data
+} BaseBarometer;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+/**
+ * @name Macro Functions (BaseBarometer)
+ * @{
+ */
+/**
+ * @brief Barometer get channels number.
+ *
+ * @param[in] ip pointer to a @p BaseBarometer class.
+ * @return The number of channels of the BaseBarometer
+ *
+ * @api
+ */
+#define barometerGetChannelsNumber(ip) \
+ (ip)->vmt->get_channels_number(ip)
+
+/**
+ * @brief Barometer read raw data.
+ *
+ * @param[in] ip pointer to a @p BaseBarometer class.
+ * @param[in] dp pointer to a data array.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define barometerReadRaw(ip, dp) \
+ (ip)->vmt->read_raw(ip, dp)
+
+/**
+ * @brief Barometer read cooked data.
+ *
+ * @param[in] ip pointer to a @p BaseBarometer class.
+ * @param[in] dp pointer to a data array.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define barometerReadCooked(ip, dp) \
+ (ip)->vmt->read_cooked(ip, dp)
+
+/**
+ * @brief Updates barometer bias data from received buffer.
+ * @note The bias buffer must have the same length of the
+ * the barometer channels number.
+ *
+ * @param[in] ip pointer to a @p BaseBarometer class.
+ * @param[in] bp pointer to a buffer of bias values.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define barometerSetBias(ip, bp) \
+ (ip)->vmt->set_bias(ip, bp)
+
+/**
+ * @brief Reset barometer bias data restoring it to zero.
+ *
+ * @param[in] ip pointer to a @p BaseBarometer class.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define barometerResetBias(ip) \
+ (ip)->vmt->reset_bias(ip)
+
+/**
+ * @brief Updates barometer sensitivity data from received buffer.
+ * @note The sensitivity buffer must have the same length of the
+ * the barometer channels number.
+ *
+ * @param[in] ip pointer to a @p BaseBarometer class.
+ * @param[in] sp pointer to a buffer of sensitivity values.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define barometerSetSensitivity(ip, sp) \
+ (ip)->vmt->set_sensitivity(ip, sp)
+
+/**
+ * @brief Reset barometer sensitivity data restoring it to its typical
+ * value.
+ *
+ * @param[in] ip pointer to a @p BaseBarometer class.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define barometerResetSensitivity(ip) \
+ (ip)->vmt->reset_sensitivity(ip)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EX_BAROMETER_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/include/ex_compass.h b/ChibiOS_20.3.2/os/ex/include/ex_compass.h
new file mode 100644
index 0000000..ddd38f2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/include/ex_compass.h
@@ -0,0 +1,218 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Rocco Marco Guglielmi
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ex_compass.h
+ * @brief Generic compass interface header.
+ *
+ * @addtogroup EX_COMPASS
+ * @{
+ */
+
+#ifndef EX_COMPASS_H
+#define EX_COMPASS_H
+
+#include "ex_sensors.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief BaseCompass specific methods.
+ */
+#define _base_compass_methods_alone \
+ /* Invoke the set bias procedure.*/ \
+ msg_t (*set_bias)(void *instance, float biases[]); \
+ /* Remove bias stored data.*/ \
+ msg_t (*reset_bias)(void *instance); \
+ /* Invoke the set sensitivity procedure.*/ \
+ msg_t (*set_sensitivity)(void *instance, float sensitivities[]); \
+ /* Restore sensitivity stored data to default.*/ \
+ msg_t (*reset_sensitivity)(void *instance);
+
+
+/**
+ * @brief BaseCompass specific methods with inherited ones.
+ */
+#define _base_compass_methods \
+ _base_sensor_methods \
+ _base_compass_methods_alone
+
+/**
+ * @brief @p BaseCompass virtual methods table.
+ */
+struct BaseCompassVMT {
+ _base_compass_methods
+};
+
+/**
+ * @brief @p BaseCompass specific data.
+ */
+#define _base_compass_data \
+ _base_sensor_data
+
+/**
+ * @extends BaseSensor
+ *
+ * @brief Base compass class.
+ * @details This class represents a generic compass.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct BaseCompassVMT *vmt;
+ _base_compass_data
+} BaseCompass;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+/**
+ * @name Macro Functions (BaseCompass)
+ * @{
+ */
+/**
+ * @brief Compass get axes number.
+ *
+ * @param[in] ip pointer to a @p BaseCompass class.
+ * @return The number of axes of the BaseCompass
+ *
+ * @api
+ */
+#define compassGetAxesNumber(ip) \
+ (ip)->vmt->get_channels_number(ip)
+
+/**
+ * @brief Compass read raw data.
+ *
+ * @param[in] ip pointer to a @p BaseCompass class.
+ * @param[in] dp pointer to a data array.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define compassReadRaw(ip, dp) \
+ (ip)->vmt->read_raw(ip, dp)
+
+/**
+ * @brief Compass read cooked data.
+ *
+ * @param[in] ip pointer to a @p BaseCompass class.
+ * @param[in] dp pointer to a data array.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define compassReadCooked(ip, dp) \
+ (ip)->vmt->read_cooked(ip, dp)
+
+/**
+ * @brief Updates compass bias data from received buffer.
+ * @note The bias buffer must have the same length of the
+ * the compass axes number.
+ *
+ * @param[in] ip pointer to a @p BaseCompass class.
+ * @param[in] bp pointer to a buffer of bias values.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define compassSetBias(ip, bp) \
+ (ip)->vmt->set_bias(ip, bp)
+
+/**
+ * @brief Reset compass bias data restoring it to zero.
+ *
+ * @param[in] ip pointer to a @p BaseCompass class.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define compassResetBias(ip) \
+ (ip)->vmt->reset_bias(ip)
+
+/**
+ * @brief Updates compass sensitivity data from received buffer.
+ * @note The sensitivity buffer must have the same length of the
+ * the compass axes number.
+ *
+ * @param[in] ip pointer to a @p BaseCompass class.
+ * @param[in] sp pointer to a buffer of sensitivity values.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define compassSetSensitivity(ip, sp) \
+ (ip)->vmt->set_sensitivity(ip, sp)
+
+/**
+ * @brief Reset compass sensitivity data restoring it to its typical
+ * value.
+ *
+ * @param[in] ip pointer to a @p BaseCompass class.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define compassResetSensitivity(ip) \
+ (ip)->vmt->reset_sensitivity(ip)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EX_COMPASS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/include/ex_displays.h b/ChibiOS_20.3.2/os/ex/include/ex_displays.h
new file mode 100644
index 0000000..81e3334
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/include/ex_displays.h
@@ -0,0 +1,112 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Rocco Marco Guglielmi
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ex_displays.h
+ * @brief Generic display interface header.
+ *
+ * @addtogroup EX_DISPLAYS
+ * @{
+ */
+
+#ifndef EX_DISPLAYS_H
+#define EX_DISPLAYS_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief @p BaseDisplay specific methods.
+ * @note No methods so far, just a common ancestor interface.
+ */
+#define _base_display_methods_alone
+
+/**
+ * @brief @p BaseDisplay specific methods with inherited ones.
+ */
+#define _base_display_methods \
+ _base_display_methods_alone
+
+/**
+ * @brief @p BaseDisplay virtual methods table.
+ */
+struct BaseDisplayVMT {
+ _base_display_methods
+};
+
+/**
+ * @brief @p BaseDisplay specific data.
+ * @note It is empty because @p BaseDisplay is only an interface
+ * without implementation.
+ */
+#define _base_display_data
+
+/**
+ * @brief Base display class.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct BaseDisplayVMT *vmt_basedisplay;
+ _base_display_data
+} BaseDisplay;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions (BaseDisplay)
+ * @{
+ */
+/**
+ * @brief Sensors get axes number.
+ *
+ * @param[in] ip pointer to a @p BaseDisplay or derived class.
+ * @return The number of axes of the BaseDisplay
+ *
+ * @api
+ */
+#define displayGetType(ip) (ip)->vmt_basedisplay->get_type(ip)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EX_DISPLAYS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/include/ex_gyroscope.h b/ChibiOS_20.3.2/os/ex/include/ex_gyroscope.h
new file mode 100644
index 0000000..5f04dc2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/include/ex_gyroscope.h
@@ -0,0 +1,238 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Rocco Marco Guglielmi
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ex_gyroscope.h
+ * @brief Generic gyroscope interface header.
+ *
+ * @addtogroup EX_GYROSCOPE
+ * @{
+ */
+
+#ifndef EX_GYROSCOPE_H
+#define EX_GYROSCOPE_H
+
+#include "ex_sensors.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief BaseGyroscope specific methods.
+ */
+#define _base_gyroscope_methods_alone \
+ /* Invoke the sample bias procedure.*/ \
+ msg_t (*sample_bias)(void *instance); \
+ /* Invoke the set bias procedure.*/ \
+ msg_t (*set_bias)(void *instance, float biases[]); \
+ /* Remove bias stored data.*/ \
+ msg_t (*reset_bias)(void *instance); \
+ /* Invoke the set sensitivity procedure.*/ \
+ msg_t (*set_sensitivity)(void *instance, float sensitivities[]); \
+ /* Restore sensitivity stored data to default.*/ \
+ msg_t (*reset_sensitivity)(void *instance);
+
+
+/**
+ * @brief BaseGyroscope specific methods with inherited ones.
+ */
+#define _base_gyroscope_methods \
+ _base_sensor_methods \
+ _base_gyroscope_methods_alone
+
+/**
+ * @brief @p BaseGyroscope virtual methods table.
+ */
+struct BaseGyroscopeVMT {
+ _base_gyroscope_methods
+};
+
+/**
+ * @brief @p BaseGyroscope specific data.
+ */
+#define _base_gyroscope_data \
+ _base_sensor_data
+
+/**
+ * @extends BaseSensor
+ *
+ * @brief Base gyroscope class.
+ * @details This class represents a generic gyroscope.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct BaseGyroscopeVMT *vmt;
+ _base_gyroscope_data
+} BaseGyroscope;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions (BaseGyroscope)
+ * @{
+ */
+/**
+ * @brief Gyroscope get axes number.
+ *
+ * @param[in] ip pointer to a @p BaseGyroscope class.
+ * @return The number of axes of the BaseGyroscope
+ *
+ * @api
+ */
+#define gyroscopeGetAxesNumber(ip) \
+ (ip)->vmt->get_channels_number(ip)
+
+/**
+ * @brief Gyroscope read raw data.
+ *
+ * @param[in] ip pointer to a @p BaseGyroscope class.
+ * @param[in] dp pointer to a data array.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define gyroscopeReadRaw(ip, dp) \
+ (ip)->vmt->read_raw(ip, dp)
+
+/**
+ * @brief Gyroscope read cooked data.
+ *
+ * @param[in] ip pointer to a @p BaseGyroscope class.
+ * @param[in] dp pointer to a data array.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define gyroscopeReadCooked(ip, dp) \
+ (ip)->vmt->read_cooked(ip, dp)
+
+/**
+ * @brief Gyroscope bias sampling procedure.
+ * @note During this procedure gyroscope must be kept hold in the rest
+ * position. Sampled bias will be automatically removed after
+ * calling this procedure.
+ *
+ * @param[in] ip pointer to a @p BaseGyroscope class.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define gyroscopeSampleBias(ip) \
+ (ip)->vmt->sample_bias(ip)
+
+/**
+ * @brief Updates gyroscope bias data from received buffer.
+ * @note The bias buffer must have the same length of the
+ * the gyroscope axes number.
+ *
+ * @param[in] ip pointer to a @p BaseGyroscope class.
+ * @param[in] bp pointer to a buffer of bias values.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define gyroscopeSetBias(ip, bp) \
+ (ip)->vmt->set_bias(ip, bp)
+
+/**
+ * @brief Reset gyroscope bias data restoring it to zero.
+ *
+ * @param[in] ip pointer to a @p BaseGyroscope class.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define gyroscopeResetBias(ip) \
+ (ip)->vmt->reset_bias(ip)
+
+/**
+ * @brief Updates gyroscope sensitivity data from received buffer.
+ * @note The sensitivity buffer must have the same length of the
+ * the gyroscope axes number.
+ *
+ * @param[in] ip pointer to a @p BaseGyroscope class.
+ * @param[in] sp pointer to a buffer of sensitivity values.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define gyroscopeSetSensitivity(ip, sp) \
+ (ip)->vmt->set_sensitivity(ip, sp)
+
+/**
+ * @brief Reset gyroscope sensitivity data restoring it to its typical
+ * value.
+ *
+ * @param[in] ip pointer to a @p BaseGyroscope class.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define gyroscopeResetSensitivity(ip) \
+ (ip)->vmt->reset_sensitivity(ip)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EX_GYROSCOPE_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/include/ex_hygrometer.h b/ChibiOS_20.3.2/os/ex/include/ex_hygrometer.h
new file mode 100644
index 0000000..47b76a6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/include/ex_hygrometer.h
@@ -0,0 +1,218 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Rocco Marco Guglielmi
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ex_hygrometer.h
+ * @brief Generic hygrometer interface header.
+ *
+ * @addtogroup EX_HYGROMETER
+ * @{
+ */
+
+#ifndef EX_HYGROMETER_H
+#define EX_HYGROMETER_H
+
+#include "ex_sensors.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief BaseHygrometer specific methods.
+ */
+#define _base_hygrometer_methods_alone \
+ /* Invoke the set bias procedure.*/ \
+ msg_t (*set_bias)(void *instance, float biases[]); \
+ /* Remove bias stored data.*/ \
+ msg_t (*reset_bias)(void *instance); \
+ /* Invoke the set sensitivity procedure.*/ \
+ msg_t (*set_sensitivity)(void *instance, float sensitivities[]); \
+ /* Restore sensitivity stored data to default.*/ \
+ msg_t (*reset_sensitivity)(void *instance);
+
+
+/**
+ * @brief BaseHygrometer specific methods with inherited ones.
+ */
+#define _base_hygrometer_methods \
+ _base_sensor_methods \
+ _base_hygrometer_methods_alone
+
+/**
+ * @brief @p BaseHygrometer virtual methods table.
+ */
+struct BaseHygrometerVMT {
+ _base_hygrometer_methods
+};
+
+/**
+ * @brief @p BaseHygrometer specific data.
+ */
+#define _base_hygrometer_data \
+ _base_sensor_data
+
+/**
+ * @extends BaseSensor
+ *
+ * @brief Base hygrometer class.
+ * @details This class represents a generic hygrometer.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct BaseHygrometerVMT *vmt;
+ _base_hygrometer_data
+} BaseHygrometer;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+/**
+ * @name Macro Functions (BaseHygrometer)
+ * @{
+ */
+/**
+ * @brief Hygrometer get channels number.
+ *
+ * @param[in] ip pointer to a @p BaseHygrometer class.
+ * @return The number of channels of the BaseHygrometer
+ *
+ * @api
+ */
+#define hygrometerGetChannelsNumber(ip) \
+ (ip)->vmt->get_channels_number(ip)
+
+/**
+ * @brief Hygrometer read raw data.
+ *
+ * @param[in] ip pointer to a @p BaseHygrometer class.
+ * @param[in] dp pointer to a data array.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define hygrometerReadRaw(ip, dp) \
+ (ip)->vmt->read_raw(ip, dp)
+
+/**
+ * @brief Hygrometer read cooked data.
+ *
+ * @param[in] ip pointer to a @p BaseHygrometer class.
+ * @param[in] dp pointer to a data array.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define hygrometerReadCooked(ip, dp) \
+ (ip)->vmt->read_cooked(ip, dp)
+
+/**
+ * @brief Updates hygrometer bias data from received buffer.
+ * @note The bias buffer must have the same length of the
+ * the hygrometer channels number.
+ *
+ * @param[in] ip pointer to a @p BaseHygrometer class.
+ * @param[in] bp pointer to a buffer of bias values.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define hygrometerSetBias(ip, bp) \
+ (ip)->vmt->set_bias(ip, bp)
+
+/**
+ * @brief Reset hygrometer bias data restoring it to zero.
+ *
+ * @param[in] ip pointer to a @p BaseHygrometer class.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define hygrometerResetBias(ip) \
+ (ip)->vmt->reset_bias(ip)
+
+/**
+ * @brief Updates hygrometer sensitivity data from received buffer.
+ * @note The sensitivity buffer must have the same length of the
+ * the hygrometer channels number.
+ *
+ * @param[in] ip pointer to a @p BaseHygrometer class.
+ * @param[in] sp pointer to a buffer of sensitivity values.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define hygrometerSetSensitivity(ip, sp) \
+ (ip)->vmt->set_sensitivity(ip, sp)
+
+/**
+ * @brief Reset hygrometer sensitivity data restoring it to its typical
+ * value.
+ *
+ * @param[in] ip pointer to a @p BaseHygrometer class.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define hygrometerResetSensitivity(ip) \
+ (ip)->vmt->reset_sensitivity(ip)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EX_HYGROMETER_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/include/ex_rangefinder.h b/ChibiOS_20.3.2/os/ex/include/ex_rangefinder.h
new file mode 100644
index 0000000..e6ae33a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/include/ex_rangefinder.h
@@ -0,0 +1,218 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Rocco Marco Guglielmi
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ex_rangefinder.h
+ * @brief Generic rangefinder interface header.
+ *
+ * @addtogroup EX_RANGEFINDER
+ * @{
+ */
+
+#ifndef EX_RANGEFINDER_H
+#define EX_RANGEFINDER_H
+
+#include "ex_sensors.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief BaseRangeFinder specific methods.
+ */
+#define _base_rangefinder_methods_alone \
+ /* Invoke the set bias procedure.*/ \
+ msg_t (*set_bias)(void *instance, float biases[]); \
+ /* Remove bias stored data.*/ \
+ msg_t (*reset_bias)(void *instance); \
+ /* Invoke the set sensitivity procedure.*/ \
+ msg_t (*set_sensitivity)(void *instance, float sensitivities[]); \
+ /* Restore sensitivity stored data to default.*/ \
+ msg_t (*reset_sensitivity)(void *instance);
+
+
+/**
+ * @brief BaseRangeFinder specific methods with inherited ones.
+ */
+#define _base_rangefinder_methods \
+ _base_sensor_methods \
+ _base_rangefinder_methods_alone
+
+/**
+ * @brief @p BaseRangeFinder virtual methods table.
+ */
+struct BaseRangeFinderVMT {
+ _base_rangefinder_methods
+};
+
+/**
+ * @brief @p BaseRangeFinder specific data.
+ */
+#define _base_rangefinder_data \
+ _base_sensor_data
+
+/**
+ * @extends BaseSensor
+ *
+ * @brief Base rangefinder class.
+ * @details This class represents a generic rangefinder.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct BaseRangeFinderVMT *vmt;
+ _base_rangefinder_data
+} BaseRangeFinder;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+/**
+ * @name Macro Functions (BaseRangeFinder)
+ * @{
+ */
+/**
+ * @brief RangeFinder get channels number.
+ *
+ * @param[in] ip pointer to a @p BaseRangeFinder class.
+ * @return The number of channels of the BaseRangeFinder
+ *
+ * @api
+ */
+#define rangefinderGetChannelsNumber(ip) \
+ (ip)->vmt->get_channels_number(ip)
+
+/**
+ * @brief RangeFinder read raw data.
+ *
+ * @param[in] ip pointer to a @p BaseRangeFinder class.
+ * @param[in] dp pointer to a data array.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define rangefinderReadRaw(ip, dp) \
+ (ip)->vmt->read_raw(ip, dp)
+
+/**
+ * @brief RangeFinder read cooked data.
+ *
+ * @param[in] ip pointer to a @p BaseRangeFinder class.
+ * @param[in] dp pointer to a data array.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define rangefinderReadCooked(ip, dp) \
+ (ip)->vmt->read_cooked(ip, dp)
+
+/**
+ * @brief Updates rangefinder bias data from received buffer.
+ * @note The bias buffer must have the same length of the
+ * the rangefinder channels number.
+ *
+ * @param[in] ip pointer to a @p BaseRangeFinder class.
+ * @param[in] bp pointer to a buffer of bias values.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define rangefinderSetBias(ip, bp) \
+ (ip)->vmt->set_bias(ip, bp)
+
+/**
+ * @brief Reset rangefinder bias data restoring it to zero.
+ *
+ * @param[in] ip pointer to a @p BaseRangeFinder class.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define rangefinderResetBias(ip) \
+ (ip)->vmt->reset_bias(ip)
+
+/**
+ * @brief Updates rangefinder sensitivity data from received buffer.
+ * @note The sensitivity buffer must have the same length of the
+ * the rangefinder channels number.
+ *
+ * @param[in] ip pointer to a @p BaseRangeFinder class.
+ * @param[in] sp pointer to a buffer of sensitivity values.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define rangefinderSetSensitivity(ip, sp) \
+ (ip)->vmt->set_sensitivity(ip, sp)
+
+/**
+ * @brief Reset rangefinder sensitivity data restoring it to its typical
+ * value.
+ *
+ * @param[in] ip pointer to a @p BaseRangeFinder class.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define rangefinderResetSensitivity(ip) \
+ (ip)->vmt->reset_sensitivity(ip)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EX_RANGEFINDER_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/include/ex_sensors.h b/ChibiOS_20.3.2/os/ex/include/ex_sensors.h
new file mode 100644
index 0000000..3a0ef92
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/include/ex_sensors.h
@@ -0,0 +1,151 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Rocco Marco Guglielmi
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ex_sensors.h
+ * @brief Generic sensors interface header.
+ *
+ * @addtogroup EX_SENSORS
+ * @{
+ */
+
+#ifndef EX_SENSORS_H
+#define EX_SENSORS_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief BaseSensor specific methods.
+ */
+#define _base_sensor_methods_alone \
+ /* Get number of channels.*/ \
+ size_t (*get_channels_number)(void *instance); \
+ /* Reads the sensor raw data.*/ \
+ msg_t (*read_raw)(void *instance, int32_t axes[]); \
+ /* Reads the sensor returning normalized data.*/ \
+ msg_t (*read_cooked)(void *instance, float axes[]);
+
+/**
+ * @brief BaseSensor specific methods with inherited ones.
+ */
+#define _base_sensor_methods \
+ _base_object_methods \
+ _base_sensor_methods_alone
+
+/**
+ * @brief @p BaseSensor virtual methods table.
+ */
+struct BaseSensorVMT {
+ _base_sensor_methods
+};
+
+/**
+ * @brief @p BaseSensor specific data.
+ * @note It is empty because @p BaseSensor is only an interface
+ * without implementation.
+ */
+#define _base_sensor_data
+ _base_object_data \
+
+/**
+ * @extends BaseObject
+ *
+ * @brief Base stream class.
+ * @details This class represents a generic blocking unbuffered sequential
+ * data stream.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct BaseSensorVMT *vmt;
+ _base_sensor_data
+} BaseSensor;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions (BaseSensor)
+ * @{
+ */
+/**
+ * @brief Sensors get channels number.
+ *
+ * @param[in] ip pointer to a @p BaseSensor or derived class.
+ * @return The number of channels of the BaseSensor
+ *
+ * @api
+ */
+#define sensorGetChannelNumber(ip) (ip)->vmt->get_channels_number(ip)
+
+/**
+ * @brief Sensors read raw data.
+ *
+ * @param[in] ip pointer to a @p BaseSensor or derived class.
+ * @param[in] dp pointer to a data array.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define sensorReadRaw(ip, dp) (ip)->vmt->read_raw(ip, dp)
+
+/**
+ * @brief Sensors read cooked data.
+ *
+ * @param[in] ip pointer to a @p BaseSensor or derived class.
+ * @param[in] dp pointer to a data array.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define sensorReadCooked(ip, dp) (ip)->vmt->read_cooked(ip, dp)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EX_SENSORS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/ex/include/ex_thermometer.h b/ChibiOS_20.3.2/os/ex/include/ex_thermometer.h
new file mode 100644
index 0000000..83af697
--- /dev/null
+++ b/ChibiOS_20.3.2/os/ex/include/ex_thermometer.h
@@ -0,0 +1,218 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Rocco Marco Guglielmi
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ex_thermometer.h
+ * @brief Generic thermometer interface header.
+ *
+ * @addtogroup EX_THERMOMETER
+ * @{
+ */
+
+#ifndef EX_THERMOMETER_H
+#define EX_THERMOMETER_H
+
+#include "ex_sensors.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief BaseThermometer specific methods.
+ */
+#define _base_thermometer_methods_alone \
+ /* Invoke the set bias procedure.*/ \
+ msg_t (*set_bias)(void *instance, float biases[]); \
+ /* Remove bias stored data.*/ \
+ msg_t (*reset_bias)(void *instance); \
+ /* Invoke the set sensitivity procedure.*/ \
+ msg_t (*set_sensitivity)(void *instance, float sensitivities[]); \
+ /* Restore sensitivity stored data to default.*/ \
+ msg_t (*reset_sensitivity)(void *instance);
+
+
+/**
+ * @brief BaseThermometer specific methods with inherited ones.
+ */
+#define _base_thermometer_methods \
+ _base_sensor_methods \
+ _base_thermometer_methods_alone
+
+/**
+ * @brief @p BaseThermometer virtual methods table.
+ */
+struct BaseThermometerVMT {
+ _base_thermometer_methods
+};
+
+/**
+ * @brief @p BaseThermometer specific data.
+ */
+#define _base_thermometer_data \
+ _base_sensor_data
+
+/**
+ * @extends BaseSensor
+ *
+ * @brief Base thermometer class.
+ * @details This class represents a generic thermometer.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct BaseThermometerVMT *vmt;
+ _base_thermometer_data
+} BaseThermometer;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+/**
+ * @name Macro Functions (BaseThermometer)
+ * @{
+ */
+/**
+ * @brief Thermometer get channels number.
+ *
+ * @param[in] ip pointer to a @p BaseThermometer class.
+ * @return The number of channels of the BaseThermometer
+ *
+ * @api
+ */
+#define thermometerGetChannelsNumber(ip) \
+ (ip)->vmt->get_channels_number(ip)
+
+/**
+ * @brief Thermometer read raw data.
+ *
+ * @param[in] ip pointer to a @p BaseThermometer class.
+ * @param[in] dp pointer to a data array.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define thermometerReadRaw(ip, dp) \
+ (ip)->vmt->read_raw(ip, dp)
+
+/**
+ * @brief Thermometer read cooked data.
+ *
+ * @param[in] ip pointer to a @p BaseThermometer class.
+ * @param[in] dp pointer to a data array.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define thermometerReadCooked(ip, dp) \
+ (ip)->vmt->read_cooked(ip, dp)
+
+/**
+ * @brief Updates thermometer bias data from received buffer.
+ * @note The bias buffer must have the same length of the
+ * the thermometer channels number.
+ *
+ * @param[in] ip pointer to a @p BaseThermometer class.
+ * @param[in] bp pointer to a buffer of bias values.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define thermometerSetBias(ip, bp) \
+ (ip)->vmt->set_bias(ip, bp)
+
+/**
+ * @brief Reset thermometer bias data restoring it to zero.
+ *
+ * @param[in] ip pointer to a @p BaseThermometer class.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define thermometerResetBias(ip) \
+ (ip)->vmt->reset_bias(ip)
+
+/**
+ * @brief Updates thermometer sensitivity data from received buffer.
+ * @note The sensitivity buffer must have the same length of the
+ * the thermometer channels number.
+ *
+ * @param[in] ip pointer to a @p BaseThermometer class.
+ * @param[in] sp pointer to a buffer of sensitivity values.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define thermometerSetSensitivity(ip, sp) \
+ (ip)->vmt->set_sensitivity(ip, sp)
+
+/**
+ * @brief Reset thermometer sensitivity data restoring it to its typical
+ * value.
+ *
+ * @param[in] ip pointer to a @p BaseThermometer class.
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more errors occurred.
+ *
+ * @api
+ */
+#define thermometerResetSensitivity(ip) \
+ (ip)->vmt->reset_sensitivity(ip)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EX_THERMOMETER_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H743ZI/board.c b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H743ZI/board.c
new file mode 100644
index 0000000..2868726
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H743ZI/board.c
@@ -0,0 +1,266 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#include "hal.h"
+#include "stm32_gpio.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of STM32 GPIO port setup.
+ */
+typedef struct {
+ uint32_t moder;
+ uint32_t otyper;
+ uint32_t ospeedr;
+ uint32_t pupdr;
+ uint32_t odr;
+ uint32_t afrl;
+ uint32_t afrh;
+} gpio_setup_t;
+
+/**
+ * @brief Type of STM32 GPIO initialization data.
+ */
+typedef struct {
+#if STM32_HAS_GPIOA || defined(__DOXYGEN__)
+ gpio_setup_t PAData;
+#endif
+#if STM32_HAS_GPIOB || defined(__DOXYGEN__)
+ gpio_setup_t PBData;
+#endif
+#if STM32_HAS_GPIOC || defined(__DOXYGEN__)
+ gpio_setup_t PCData;
+#endif
+#if STM32_HAS_GPIOD || defined(__DOXYGEN__)
+ gpio_setup_t PDData;
+#endif
+#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
+ gpio_setup_t PEData;
+#endif
+#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
+ gpio_setup_t PFData;
+#endif
+#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
+ gpio_setup_t PGData;
+#endif
+#if STM32_HAS_GPIOH || defined(__DOXYGEN__)
+ gpio_setup_t PHData;
+#endif
+#if STM32_HAS_GPIOI || defined(__DOXYGEN__)
+ gpio_setup_t PIData;
+#endif
+#if STM32_HAS_GPIOJ || defined(__DOXYGEN__)
+ gpio_setup_t PJData;
+#endif
+#if STM32_HAS_GPIOK || defined(__DOXYGEN__)
+ gpio_setup_t PKData;
+#endif
+} gpio_config_t;
+
+/**
+ * @brief STM32 GPIO static initialization data.
+ */
+static const gpio_config_t gpio_default_config = {
+#if STM32_HAS_GPIOA
+ {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
+ VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH},
+#endif
+#if STM32_HAS_GPIOB
+ {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR,
+ VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH},
+#endif
+#if STM32_HAS_GPIOC
+ {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR,
+ VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH},
+#endif
+#if STM32_HAS_GPIOD
+ {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR,
+ VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH},
+#endif
+#if STM32_HAS_GPIOE
+ {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR,
+ VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH},
+#endif
+#if STM32_HAS_GPIOF
+ {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR,
+ VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH},
+#endif
+#if STM32_HAS_GPIOG
+ {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR,
+ VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH},
+#endif
+#if STM32_HAS_GPIOH
+ {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR,
+ VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH},
+#endif
+#if STM32_HAS_GPIOI
+ {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
+ VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH},
+#endif
+#if STM32_HAS_GPIOJ
+ {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR,
+ VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH},
+#endif
+#if STM32_HAS_GPIOK
+ {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR,
+ VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH}
+#endif
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) {
+
+ gpiop->OTYPER = config->otyper;
+ gpiop->OSPEEDR = config->ospeedr;
+ gpiop->PUPDR = config->pupdr;
+ gpiop->ODR = config->odr;
+ gpiop->AFRL = config->afrl;
+ gpiop->AFRH = config->afrh;
+ gpiop->MODER = config->moder;
+}
+
+static void stm32_gpio_init(void) {
+
+ /* Enabling GPIO-related clocks, the mask comes from the
+ registry header file.*/
+ rccResetAHB4(STM32_GPIO_EN_MASK);
+ rccEnableAHB4(STM32_GPIO_EN_MASK, true);
+
+ /* Initializing all the defined GPIO ports.*/
+#if STM32_HAS_GPIOA
+ gpio_init(GPIOA, &gpio_default_config.PAData);
+#endif
+#if STM32_HAS_GPIOB
+ gpio_init(GPIOB, &gpio_default_config.PBData);
+#endif
+#if STM32_HAS_GPIOC
+ gpio_init(GPIOC, &gpio_default_config.PCData);
+#endif
+#if STM32_HAS_GPIOD
+ gpio_init(GPIOD, &gpio_default_config.PDData);
+#endif
+#if STM32_HAS_GPIOE
+ gpio_init(GPIOE, &gpio_default_config.PEData);
+#endif
+#if STM32_HAS_GPIOF
+ gpio_init(GPIOF, &gpio_default_config.PFData);
+#endif
+#if STM32_HAS_GPIOG
+ gpio_init(GPIOG, &gpio_default_config.PGData);
+#endif
+#if STM32_HAS_GPIOH
+ gpio_init(GPIOH, &gpio_default_config.PHData);
+#endif
+#if STM32_HAS_GPIOI
+ gpio_init(GPIOI, &gpio_default_config.PIData);
+#endif
+#if STM32_HAS_GPIOJ
+ gpio_init(GPIOJ, &gpio_default_config.PJData);
+#endif
+#if STM32_HAS_GPIOK
+ gpio_init(GPIOK, &gpio_default_config.PKData);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Early initialization code.
+ * @details GPIO ports and system clocks are initialized before everything
+ * else.
+ */
+void __early_init(void) {
+
+ stm32_gpio_init();
+ stm32_clock_init();
+}
+
+#if HAL_USE_SDC || defined(__DOXYGEN__)
+/**
+ * @brief SDC card detection.
+ */
+bool sdc_lld_is_card_inserted(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief SDC card write protection detection.
+ */
+bool sdc_lld_is_write_protected(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif /* HAL_USE_SDC */
+
+#if HAL_USE_MMC_SPI || defined(__DOXYGEN__)
+/**
+ * @brief MMC_SPI card detection.
+ */
+bool mmc_lld_is_card_inserted(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief MMC_SPI card write protection detection.
+ */
+bool mmc_lld_is_write_protected(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif
+
+/**
+ * @brief Board-specific initialization code.
+ * @note You can add your board-specific code here.
+ */
+void boardInit(void) {
+
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H743ZI/board.h b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H743ZI/board.h
new file mode 100644
index 0000000..aea5c80
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H743ZI/board.h
@@ -0,0 +1,1642 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#ifndef BOARD_H
+#define BOARD_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*
+ * Setup for STMicroelectronics STM32 Nucleo144-H743ZI board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_ST_NUCLEO144_H743ZI
+#define BOARD_NAME "STMicroelectronics STM32 Nucleo144-H743ZI"
+
+/*
+ * Ethernet PHY type.
+ */
+#define BOARD_PHY_ID MII_LAN8742A_ID
+#define BOARD_PHY_RMII
+
+/*
+ * Board oscillators-related settings.
+ */
+#if !defined(STM32_LSECLK)
+#define STM32_LSECLK 32768U
+#endif
+
+#define STM32_LSEDRV (3U << 3U)
+
+#if !defined(STM32_HSECLK)
+#define STM32_HSECLK 8000000U
+#endif
+
+#define STM32_HSE_BYPASS
+
+/*
+ * MCU type as defined in the ST header.
+ */
+#define STM32H743xx
+
+/*
+ * IO pins assignments.
+ */
+#define GPIOA_PIN0 0U
+#define GPIOA_RMII_REF_CLK 1U
+#define GPIOA_RMII_MDIO 2U
+#define GPIOA_PIN3 3U
+#define GPIOA_PIN4 4U
+#define GPIOA_PIN5 5U
+#define GPIOA_PIN6 6U
+#define GPIOA_RMII_CRS_DV 7U
+#define GPIOA_USB_SOF 8U
+#define GPIOA_MCO1 8U
+#define GPIOA_USB_VBUS 9U
+#define GPIOA_USB_ID 10U
+#define GPIOA_USB_DM 11U
+#define GPIOA_USB_DP 12U
+#define GPIOA_SWDIO 13U
+#define GPIOA_SWCLK 14U
+#define GPIOA_T_JTDI 15U
+
+#define GPIOB_LED1 0U
+#define GPIOB_LED_GREEN 0U
+#define GPIOB_LED 0U
+#define GPIOB_PIN1 1U
+#define GPIOB_PIN2 2U
+#define GPIOB_SWO 3U
+#define GPIOB_PIN4 4U
+#define GPIOB_PIN5 5U
+#define GPIOB_PIN6 6U
+#define GPIOB_LED2 7U
+#define GPIOB_LED_BLUE 7U
+#define GPIOB_PIN8 8U
+#define GPIOB_PIN9 9U
+#define GPIOB_PIN10 10U
+#define GPIOB_PIN11 11U
+#define GPIOB_PIN12 12U
+#define GPIOB_RMII_TXD1 13U
+#define GPIOB_LED3 14U
+#define GPIOB_LED_RED 14U
+#define GPIOB_PIN15 15U
+
+#define GPIOC_PIN0 0U
+#define GPIOC_RMII_MDC 1U
+#define GPIOC_PIN2 2U
+#define GPIOC_PIN3 3U
+#define GPIOC_RMII_RXD0 4U
+#define GPIOC_RMII_RXD1 5U
+#define GPIOC_PIN6 6U
+#define GPIOC_PIN7 7U
+#define GPIOC_PIN8 8U
+#define GPIOC_PIN9 9U
+#define GPIOC_PIN10 10U
+#define GPIOC_PIN11 11U
+#define GPIOC_PIN12 12U
+#define GPIOC_BUTTON 13U
+#define GPIOC_OSC32_IN 14U
+#define GPIOC_OSC32_OUT 15U
+
+#define GPIOD_PIN0 0U
+#define GPIOD_PIN1 1U
+#define GPIOD_PIN2 2U
+#define GPIOD_PIN3 3U
+#define GPIOD_PIN4 4U
+#define GPIOD_PIN5 5U
+#define GPIOD_PIN6 6U
+#define GPIOD_PIN7 7U
+#define GPIOD_USART3_RX 8U
+#define GPIOD_STLK_RX 8U
+#define GPIOD_USART3_TX 9U
+#define GPIOD_STLK_TX 9U
+#define GPIOD_PIN10 10U
+#define GPIOD_PIN11 11U
+#define GPIOD_PIN12 12U
+#define GPIOD_PIN13 13U
+#define GPIOD_PIN14 14U
+#define GPIOD_PIN15 15U
+
+#define GPIOE_PIN0 0U
+#define GPIOE_PIN1 1U
+#define GPIOE_PIN2 2U
+#define GPIOE_PIN3 3U
+#define GPIOE_PIN4 4U
+#define GPIOE_PIN5 5U
+#define GPIOE_PIN6 6U
+#define GPIOE_PIN7 7U
+#define GPIOE_PIN8 8U
+#define GPIOE_PIN9 9U
+#define GPIOE_PIN10 10U
+#define GPIOE_PIN11 11U
+#define GPIOE_PIN12 12U
+#define GPIOE_PIN13 13U
+#define GPIOE_PIN14 14U
+#define GPIOE_PIN15 15U
+
+#define GPIOF_PIN0 0U
+#define GPIOF_PIN1 1U
+#define GPIOF_PIN2 2U
+#define GPIOF_PIN3 3U
+#define GPIOF_PIN4 4U
+#define GPIOF_PIN5 5U
+#define GPIOF_PIN6 6U
+#define GPIOF_PIN7 7U
+#define GPIOF_PIN8 8U
+#define GPIOF_PIN9 9U
+#define GPIOF_PIN10 10U
+#define GPIOF_PIN11 11U
+#define GPIOF_PIN12 12U
+#define GPIOF_PIN13 13U
+#define GPIOF_PIN14 14U
+#define GPIOF_PIN15 15U
+
+#define GPIOG_PIN0 0U
+#define GPIOG_PIN1 1U
+#define GPIOG_PIN2 2U
+#define GPIOG_PIN3 3U
+#define GPIOG_PIN4 4U
+#define GPIOG_PIN5 5U
+#define GPIOG_USB_FS_PWR_EN 6U
+#define GPIOG_USB_FS_OVCR 7U
+#define GPIOG_PIN8 8U
+#define GPIOG_PIN9 9U
+#define GPIOG_PIN10 10U
+#define GPIOG_RMII_TX_EN 11U
+#define GPIOG_PIN12 12U
+#define GPIOG_RMII_TXD0 13U
+#define GPIOG_PIN14 14U
+#define GPIOG_PIN15 15U
+
+#define GPIOH_OSC_IN 0U
+#define GPIOH_OSC_OUT 1U
+#define GPIOH_PIN2 2U
+#define GPIOH_PIN3 3U
+#define GPIOH_PIN4 4U
+#define GPIOH_PIN5 5U
+#define GPIOH_PIN6 6U
+#define GPIOH_PIN7 7U
+#define GPIOH_PIN8 8U
+#define GPIOH_PIN9 9U
+#define GPIOH_PIN10 10U
+#define GPIOH_PIN11 11U
+#define GPIOH_PIN12 12U
+#define GPIOH_PIN13 13U
+#define GPIOH_PIN14 14U
+#define GPIOH_PIN15 15U
+
+#define GPIOI_PIN0 0U
+#define GPIOI_PIN1 1U
+#define GPIOI_PIN2 2U
+#define GPIOI_PIN3 3U
+#define GPIOI_PIN4 4U
+#define GPIOI_PIN5 5U
+#define GPIOI_PIN6 6U
+#define GPIOI_PIN7 7U
+#define GPIOI_PIN8 8U
+#define GPIOI_PIN9 9U
+#define GPIOI_PIN10 10U
+#define GPIOI_PIN11 11U
+#define GPIOI_PIN12 12U
+#define GPIOI_PIN13 13U
+#define GPIOI_PIN14 14U
+#define GPIOI_PIN15 15U
+
+#define GPIOJ_PIN0 0U
+#define GPIOJ_PIN1 1U
+#define GPIOJ_PIN2 2U
+#define GPIOJ_PIN3 3U
+#define GPIOJ_PIN4 4U
+#define GPIOJ_PIN5 5U
+#define GPIOJ_PIN6 6U
+#define GPIOJ_PIN7 7U
+#define GPIOJ_PIN8 8U
+#define GPIOJ_PIN9 9U
+#define GPIOJ_PIN10 10U
+#define GPIOJ_PIN11 11U
+#define GPIOJ_PIN12 12U
+#define GPIOJ_PIN13 13U
+#define GPIOJ_PIN14 14U
+#define GPIOJ_PIN15 15U
+
+#define GPIOK_PIN0 0U
+#define GPIOK_PIN1 1U
+#define GPIOK_PIN2 2U
+#define GPIOK_PIN3 3U
+#define GPIOK_PIN4 4U
+#define GPIOK_PIN5 5U
+#define GPIOK_PIN6 6U
+#define GPIOK_PIN7 7U
+#define GPIOK_PIN8 8U
+#define GPIOK_PIN9 9U
+#define GPIOK_PIN10 10U
+#define GPIOK_PIN11 11U
+#define GPIOK_PIN12 12U
+#define GPIOK_PIN13 13U
+#define GPIOK_PIN14 14U
+#define GPIOK_PIN15 15U
+
+/*
+ * IO lines assignments.
+ */
+#define LINE_RMII_REF_CLK PAL_LINE(GPIOA, 1U)
+#define LINE_RMII_MDIO PAL_LINE(GPIOA, 2U)
+#define LINE_RMII_CRS_DV PAL_LINE(GPIOA, 7U)
+#define LINE_USB_SOF PAL_LINE(GPIOA, 8U)
+#define LINE_MCO1 PAL_LINE(GPIOA, 8U)
+#define LINE_USB_VBUS PAL_LINE(GPIOA, 9U)
+#define LINE_USB_ID PAL_LINE(GPIOA, 10U)
+#define LINE_USB_DM PAL_LINE(GPIOA, 11U)
+#define LINE_USB_DP PAL_LINE(GPIOA, 12U)
+#define LINE_SWDIO PAL_LINE(GPIOA, 13U)
+#define LINE_SWCLK PAL_LINE(GPIOA, 14U)
+#define LINE_T_JTDI PAL_LINE(GPIOA, 15U)
+#define LINE_LED1 PAL_LINE(GPIOB, 0U)
+#define LINE_LED_GREEN PAL_LINE(GPIOB, 0U)
+#define LINE_LED PAL_LINE(GPIOB, 0U)
+#define LINE_SWO PAL_LINE(GPIOB, 3U)
+#define LINE_LED2 PAL_LINE(GPIOB, 7U)
+#define LINE_LED_BLUE PAL_LINE(GPIOB, 7U)
+#define LINE_RMII_TXD1 PAL_LINE(GPIOB, 13U)
+#define LINE_LED3 PAL_LINE(GPIOB, 14U)
+#define LINE_LED_RED PAL_LINE(GPIOB, 14U)
+#define LINE_RMII_MDC PAL_LINE(GPIOC, 1U)
+#define LINE_RMII_RXD0 PAL_LINE(GPIOC, 4U)
+#define LINE_RMII_RXD1 PAL_LINE(GPIOC, 5U)
+#define LINE_BUTTON PAL_LINE(GPIOC, 13U)
+#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U)
+#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U)
+#define LINE_USART3_RX PAL_LINE(GPIOD, 8U)
+#define LINE_STLK_RX PAL_LINE(GPIOD, 8U)
+#define LINE_USART3_TX PAL_LINE(GPIOD, 9U)
+#define LINE_STLK_TX PAL_LINE(GPIOD, 9U)
+#define LINE_USB_FS_PWR_EN PAL_LINE(GPIOG, 6U)
+#define LINE_USB_FS_OVCR PAL_LINE(GPIOG, 7U)
+#define LINE_RMII_TX_EN PAL_LINE(GPIOG, 11U)
+#define LINE_RMII_TXD0 PAL_LINE(GPIOG, 13U)
+#define LINE_OSC_IN PAL_LINE(GPIOH, 0U)
+#define LINE_OSC_OUT PAL_LINE(GPIOH, 1U)
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*
+ * I/O ports initial setup, this configuration is established soon after reset
+ * in the initialization code.
+ * Please refer to the STM32 Reference Manual for details.
+ */
+#define PIN_MODE_INPUT(n) (0U << ((n) * 2U))
+#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U))
+#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U))
+#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U))
+#define PIN_ODR_LOW(n) (0U << (n))
+#define PIN_ODR_HIGH(n) (1U << (n))
+#define PIN_OTYPE_PUSHPULL(n) (0U << (n))
+#define PIN_OTYPE_OPENDRAIN(n) (1U << (n))
+#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U))
+#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U))
+#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U))
+#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U))
+#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U))
+#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U))
+#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U))
+#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U))
+
+/*
+ * GPIOA setup:
+ *
+ * PA0 - PIN0 (input pullup).
+ * PA1 - RMII_REF_CLK (alternate 11).
+ * PA2 - RMII_MDIO (alternate 11).
+ * PA3 - PIN3 (input pullup).
+ * PA4 - PIN4 (input pullup).
+ * PA5 - PIN5 (input pullup).
+ * PA6 - PIN6 (input pullup).
+ * PA7 - RMII_CRS_DV (alternate 11).
+ * PA8 - USB_SOF MCO1 (alternate 10).
+ * PA9 - USB_VBUS (analog).
+ * PA10 - USB_ID (alternate 10).
+ * PA11 - USB_DM (alternate 10).
+ * PA12 - USB_DP (alternate 10).
+ * PA13 - SWDIO (alternate 0).
+ * PA14 - SWCLK (alternate 0).
+ * PA15 - T_JTDI (alternate 0).
+ */
+#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_PIN0) | \
+ PIN_MODE_ALTERNATE(GPIOA_RMII_REF_CLK) |\
+ PIN_MODE_ALTERNATE(GPIOA_RMII_MDIO) | \
+ PIN_MODE_INPUT(GPIOA_PIN3) | \
+ PIN_MODE_INPUT(GPIOA_PIN4) | \
+ PIN_MODE_INPUT(GPIOA_PIN5) | \
+ PIN_MODE_INPUT(GPIOA_PIN6) | \
+ PIN_MODE_ALTERNATE(GPIOA_RMII_CRS_DV) |\
+ PIN_MODE_ALTERNATE(GPIOA_USB_SOF) | \
+ PIN_MODE_ANALOG(GPIOA_USB_VBUS) | \
+ PIN_MODE_ALTERNATE(GPIOA_USB_ID) | \
+ PIN_MODE_ALTERNATE(GPIOA_USB_DM) | \
+ PIN_MODE_ALTERNATE(GPIOA_USB_DP) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \
+ PIN_MODE_ALTERNATE(GPIOA_T_JTDI))
+#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_RMII_REF_CLK) |\
+ PIN_OTYPE_PUSHPULL(GPIOA_RMII_MDIO) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_RMII_CRS_DV) |\
+ PIN_OTYPE_PUSHPULL(GPIOA_USB_SOF) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_USB_VBUS) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_USB_ID) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_USB_DM) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_USB_DP) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_T_JTDI))
+#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOA_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOA_RMII_REF_CLK) | \
+ PIN_OSPEED_HIGH(GPIOA_RMII_MDIO) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOA_RMII_CRS_DV) | \
+ PIN_OSPEED_HIGH(GPIOA_USB_SOF) | \
+ PIN_OSPEED_HIGH(GPIOA_USB_VBUS) | \
+ PIN_OSPEED_HIGH(GPIOA_USB_ID) | \
+ PIN_OSPEED_HIGH(GPIOA_USB_DM) | \
+ PIN_OSPEED_HIGH(GPIOA_USB_DP) | \
+ PIN_OSPEED_HIGH(GPIOA_SWDIO) | \
+ PIN_OSPEED_HIGH(GPIOA_SWCLK) | \
+ PIN_OSPEED_HIGH(GPIOA_T_JTDI))
+#define VAL_GPIOA_PUPDR (PIN_PUPDR_PULLUP(GPIOA_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOA_RMII_REF_CLK) |\
+ PIN_PUPDR_PULLUP(GPIOA_RMII_MDIO) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOA_RMII_CRS_DV) | \
+ PIN_PUPDR_FLOATING(GPIOA_USB_SOF) | \
+ PIN_PUPDR_FLOATING(GPIOA_USB_VBUS) | \
+ PIN_PUPDR_FLOATING(GPIOA_USB_ID) | \
+ PIN_PUPDR_FLOATING(GPIOA_USB_DM) | \
+ PIN_PUPDR_FLOATING(GPIOA_USB_DP) | \
+ PIN_PUPDR_FLOATING(GPIOA_SWDIO) | \
+ PIN_PUPDR_FLOATING(GPIOA_SWCLK) | \
+ PIN_PUPDR_PULLUP(GPIOA_T_JTDI))
+#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_PIN0) | \
+ PIN_ODR_HIGH(GPIOA_RMII_REF_CLK) | \
+ PIN_ODR_HIGH(GPIOA_RMII_MDIO) | \
+ PIN_ODR_HIGH(GPIOA_PIN3) | \
+ PIN_ODR_HIGH(GPIOA_PIN4) | \
+ PIN_ODR_HIGH(GPIOA_PIN5) | \
+ PIN_ODR_HIGH(GPIOA_PIN6) | \
+ PIN_ODR_HIGH(GPIOA_RMII_CRS_DV) | \
+ PIN_ODR_HIGH(GPIOA_USB_SOF) | \
+ PIN_ODR_HIGH(GPIOA_USB_VBUS) | \
+ PIN_ODR_HIGH(GPIOA_USB_ID) | \
+ PIN_ODR_HIGH(GPIOA_USB_DM) | \
+ PIN_ODR_HIGH(GPIOA_USB_DP) | \
+ PIN_ODR_HIGH(GPIOA_SWDIO) | \
+ PIN_ODR_HIGH(GPIOA_SWCLK) | \
+ PIN_ODR_HIGH(GPIOA_T_JTDI))
+#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOA_RMII_REF_CLK, 11U) | \
+ PIN_AFIO_AF(GPIOA_RMII_MDIO, 11U) | \
+ PIN_AFIO_AF(GPIOA_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOA_RMII_CRS_DV, 11U))
+#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_USB_SOF, 10U) | \
+ PIN_AFIO_AF(GPIOA_USB_VBUS, 0U) | \
+ PIN_AFIO_AF(GPIOA_USB_ID, 10U) | \
+ PIN_AFIO_AF(GPIOA_USB_DM, 10U) | \
+ PIN_AFIO_AF(GPIOA_USB_DP, 10U) | \
+ PIN_AFIO_AF(GPIOA_SWDIO, 0U) | \
+ PIN_AFIO_AF(GPIOA_SWCLK, 0U) | \
+ PIN_AFIO_AF(GPIOA_T_JTDI, 0U))
+
+/*
+ * GPIOB setup:
+ *
+ * PB0 - LED1 LED_GREEN LED (output pushpull maximum).
+ * PB1 - PIN1 (input pullup).
+ * PB2 - PIN2 (input pullup).
+ * PB3 - SWO (alternate 0).
+ * PB4 - PIN4 (input pullup).
+ * PB5 - PIN5 (input pullup).
+ * PB6 - PIN6 (input pullup).
+ * PB7 - LED2 LED_BLUE (output pushpull maximum).
+ * PB8 - PIN8 (input pullup).
+ * PB9 - PIN9 (input pullup).
+ * PB10 - PIN10 (input pullup).
+ * PB11 - PIN11 (input pullup).
+ * PB12 - PIN12 (input pullup).
+ * PB13 - RMII_TXD1 (alternate 11).
+ * PB14 - LED3 LED_RED (output pushpull maximum).
+ * PB15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOB_MODER (PIN_MODE_OUTPUT(GPIOB_LED1) | \
+ PIN_MODE_INPUT(GPIOB_PIN1) | \
+ PIN_MODE_INPUT(GPIOB_PIN2) | \
+ PIN_MODE_ALTERNATE(GPIOB_SWO) | \
+ PIN_MODE_INPUT(GPIOB_PIN4) | \
+ PIN_MODE_INPUT(GPIOB_PIN5) | \
+ PIN_MODE_INPUT(GPIOB_PIN6) | \
+ PIN_MODE_OUTPUT(GPIOB_LED2) | \
+ PIN_MODE_INPUT(GPIOB_PIN8) | \
+ PIN_MODE_INPUT(GPIOB_PIN9) | \
+ PIN_MODE_INPUT(GPIOB_PIN10) | \
+ PIN_MODE_INPUT(GPIOB_PIN11) | \
+ PIN_MODE_INPUT(GPIOB_PIN12) | \
+ PIN_MODE_ALTERNATE(GPIOB_RMII_TXD1) | \
+ PIN_MODE_OUTPUT(GPIOB_LED3) | \
+ PIN_MODE_INPUT(GPIOB_PIN15))
+#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_LED1) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_SWO) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_LED2) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_RMII_TXD1) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_LED3) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN15))
+#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_LED1) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOB_SWO) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOB_LED2) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOB_RMII_TXD1) | \
+ PIN_OSPEED_HIGH(GPIOB_LED3) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN15))
+#define VAL_GPIOB_PUPDR (PIN_PUPDR_FLOATING(GPIOB_LED1) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOB_SWO) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOB_LED2) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOB_RMII_TXD1) | \
+ PIN_PUPDR_FLOATING(GPIOB_LED3) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN15))
+#define VAL_GPIOB_ODR (PIN_ODR_LOW(GPIOB_LED1) | \
+ PIN_ODR_HIGH(GPIOB_PIN1) | \
+ PIN_ODR_HIGH(GPIOB_PIN2) | \
+ PIN_ODR_HIGH(GPIOB_SWO) | \
+ PIN_ODR_HIGH(GPIOB_PIN4) | \
+ PIN_ODR_HIGH(GPIOB_PIN5) | \
+ PIN_ODR_HIGH(GPIOB_PIN6) | \
+ PIN_ODR_LOW(GPIOB_LED2) | \
+ PIN_ODR_HIGH(GPIOB_PIN8) | \
+ PIN_ODR_HIGH(GPIOB_PIN9) | \
+ PIN_ODR_HIGH(GPIOB_PIN10) | \
+ PIN_ODR_HIGH(GPIOB_PIN11) | \
+ PIN_ODR_HIGH(GPIOB_PIN12) | \
+ PIN_ODR_HIGH(GPIOB_RMII_TXD1) | \
+ PIN_ODR_LOW(GPIOB_LED3) | \
+ PIN_ODR_HIGH(GPIOB_PIN15))
+#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_LED1, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOB_SWO, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOB_LED2, 0U))
+#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOB_RMII_TXD1, 11U) | \
+ PIN_AFIO_AF(GPIOB_LED3, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN15, 0U))
+
+/*
+ * GPIOC setup:
+ *
+ * PC0 - PIN0 (input pullup).
+ * PC1 - RMII_MDC (alternate 11).
+ * PC2 - PIN2 (input pullup).
+ * PC3 - PIN3 (input pullup).
+ * PC4 - RMII_RXD0 (alternate 11).
+ * PC5 - RMII_RXD1 (alternate 11).
+ * PC6 - PIN6 (input pullup).
+ * PC7 - PIN7 (input pullup).
+ * PC8 - PIN8 (input pullup).
+ * PC9 - PIN9 (input pullup).
+ * PC10 - PIN10 (input pullup).
+ * PC11 - PIN11 (input pullup).
+ * PC12 - PIN12 (input pullup).
+ * PC13 - BUTTON (input floating).
+ * PC14 - OSC32_IN (input floating).
+ * PC15 - OSC32_OUT (input floating).
+ */
+#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_PIN0) | \
+ PIN_MODE_ALTERNATE(GPIOC_RMII_MDC) | \
+ PIN_MODE_INPUT(GPIOC_PIN2) | \
+ PIN_MODE_INPUT(GPIOC_PIN3) | \
+ PIN_MODE_ALTERNATE(GPIOC_RMII_RXD0) | \
+ PIN_MODE_ALTERNATE(GPIOC_RMII_RXD1) | \
+ PIN_MODE_INPUT(GPIOC_PIN6) | \
+ PIN_MODE_INPUT(GPIOC_PIN7) | \
+ PIN_MODE_INPUT(GPIOC_PIN8) | \
+ PIN_MODE_INPUT(GPIOC_PIN9) | \
+ PIN_MODE_INPUT(GPIOC_PIN10) | \
+ PIN_MODE_INPUT(GPIOC_PIN11) | \
+ PIN_MODE_INPUT(GPIOC_PIN12) | \
+ PIN_MODE_INPUT(GPIOC_BUTTON) | \
+ PIN_MODE_INPUT(GPIOC_OSC32_IN) | \
+ PIN_MODE_INPUT(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_RMII_MDC) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_RMII_RXD0) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_RMII_RXD1) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_BUTTON) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOC_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOC_RMII_MDC) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOC_RMII_RXD0) | \
+ PIN_OSPEED_HIGH(GPIOC_RMII_RXD1) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOC_BUTTON) | \
+ PIN_OSPEED_VERYLOW(GPIOC_OSC32_IN) | \
+ PIN_OSPEED_VERYLOW(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOC_RMII_MDC) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOC_RMII_RXD0) | \
+ PIN_PUPDR_FLOATING(GPIOC_RMII_RXD1) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOC_BUTTON) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_PIN0) | \
+ PIN_ODR_HIGH(GPIOC_RMII_MDC) | \
+ PIN_ODR_HIGH(GPIOC_PIN2) | \
+ PIN_ODR_HIGH(GPIOC_PIN3) | \
+ PIN_ODR_HIGH(GPIOC_RMII_RXD0) | \
+ PIN_ODR_HIGH(GPIOC_RMII_RXD1) | \
+ PIN_ODR_HIGH(GPIOC_PIN6) | \
+ PIN_ODR_HIGH(GPIOC_PIN7) | \
+ PIN_ODR_HIGH(GPIOC_PIN8) | \
+ PIN_ODR_HIGH(GPIOC_PIN9) | \
+ PIN_ODR_HIGH(GPIOC_PIN10) | \
+ PIN_ODR_HIGH(GPIOC_PIN11) | \
+ PIN_ODR_HIGH(GPIOC_PIN12) | \
+ PIN_ODR_HIGH(GPIOC_BUTTON) | \
+ PIN_ODR_HIGH(GPIOC_OSC32_IN) | \
+ PIN_ODR_HIGH(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOC_RMII_MDC, 11U) | \
+ PIN_AFIO_AF(GPIOC_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOC_RMII_RXD0, 11U) | \
+ PIN_AFIO_AF(GPIOC_RMII_RXD1, 11U) | \
+ PIN_AFIO_AF(GPIOC_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN7, 0U))
+#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOC_BUTTON, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U))
+
+/*
+ * GPIOD setup:
+ *
+ * PD0 - PIN0 (input pullup).
+ * PD1 - PIN1 (input pullup).
+ * PD2 - PIN2 (input pullup).
+ * PD3 - PIN3 (input pullup).
+ * PD4 - PIN4 (input pullup).
+ * PD5 - PIN5 (input pullup).
+ * PD6 - PIN6 (input pullup).
+ * PD7 - PIN7 (input pullup).
+ * PD8 - USART3_RX STLK_RX (alternate 7).
+ * PD9 - USART3_TX STLK_TX (alternate 7).
+ * PD10 - PIN10 (input pullup).
+ * PD11 - PIN11 (input pullup).
+ * PD12 - PIN12 (input pullup).
+ * PD13 - PIN13 (input pullup).
+ * PD14 - PIN14 (input pullup).
+ * PD15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | \
+ PIN_MODE_INPUT(GPIOD_PIN1) | \
+ PIN_MODE_INPUT(GPIOD_PIN2) | \
+ PIN_MODE_INPUT(GPIOD_PIN3) | \
+ PIN_MODE_INPUT(GPIOD_PIN4) | \
+ PIN_MODE_INPUT(GPIOD_PIN5) | \
+ PIN_MODE_INPUT(GPIOD_PIN6) | \
+ PIN_MODE_INPUT(GPIOD_PIN7) | \
+ PIN_MODE_ALTERNATE(GPIOD_USART3_RX) | \
+ PIN_MODE_ALTERNATE(GPIOD_USART3_TX) | \
+ PIN_MODE_INPUT(GPIOD_PIN10) | \
+ PIN_MODE_INPUT(GPIOD_PIN11) | \
+ PIN_MODE_INPUT(GPIOD_PIN12) | \
+ PIN_MODE_INPUT(GPIOD_PIN13) | \
+ PIN_MODE_INPUT(GPIOD_PIN14) | \
+ PIN_MODE_INPUT(GPIOD_PIN15))
+#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_USART3_RX) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_USART3_TX) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN15))
+#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOD_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOD_USART3_RX) | \
+ PIN_OSPEED_HIGH(GPIOD_USART3_TX) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN15))
+#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOD_USART3_RX) | \
+ PIN_PUPDR_FLOATING(GPIOD_USART3_TX) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN15))
+#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \
+ PIN_ODR_HIGH(GPIOD_PIN1) | \
+ PIN_ODR_HIGH(GPIOD_PIN2) | \
+ PIN_ODR_HIGH(GPIOD_PIN3) | \
+ PIN_ODR_HIGH(GPIOD_PIN4) | \
+ PIN_ODR_HIGH(GPIOD_PIN5) | \
+ PIN_ODR_HIGH(GPIOD_PIN6) | \
+ PIN_ODR_HIGH(GPIOD_PIN7) | \
+ PIN_ODR_HIGH(GPIOD_USART3_RX) | \
+ PIN_ODR_HIGH(GPIOD_USART3_TX) | \
+ PIN_ODR_HIGH(GPIOD_PIN10) | \
+ PIN_ODR_HIGH(GPIOD_PIN11) | \
+ PIN_ODR_HIGH(GPIOD_PIN12) | \
+ PIN_ODR_HIGH(GPIOD_PIN13) | \
+ PIN_ODR_HIGH(GPIOD_PIN14) | \
+ PIN_ODR_HIGH(GPIOD_PIN15))
+#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN7, 0U))
+#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_USART3_RX, 7U) | \
+ PIN_AFIO_AF(GPIOD_USART3_TX, 7U) | \
+ PIN_AFIO_AF(GPIOD_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN15, 0U))
+
+/*
+ * GPIOE setup:
+ *
+ * PE0 - PIN0 (input pullup).
+ * PE1 - PIN1 (input pullup).
+ * PE2 - PIN2 (input pullup).
+ * PE3 - PIN3 (input pullup).
+ * PE4 - PIN4 (input pullup).
+ * PE5 - PIN5 (input pullup).
+ * PE6 - PIN6 (input pullup).
+ * PE7 - PIN7 (input pullup).
+ * PE8 - PIN8 (input pullup).
+ * PE9 - PIN9 (input pullup).
+ * PE10 - PIN10 (input pullup).
+ * PE11 - PIN11 (input pullup).
+ * PE12 - PIN12 (input pullup).
+ * PE13 - PIN13 (input pullup).
+ * PE14 - PIN14 (input pullup).
+ * PE15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_PIN0) | \
+ PIN_MODE_INPUT(GPIOE_PIN1) | \
+ PIN_MODE_INPUT(GPIOE_PIN2) | \
+ PIN_MODE_INPUT(GPIOE_PIN3) | \
+ PIN_MODE_INPUT(GPIOE_PIN4) | \
+ PIN_MODE_INPUT(GPIOE_PIN5) | \
+ PIN_MODE_INPUT(GPIOE_PIN6) | \
+ PIN_MODE_INPUT(GPIOE_PIN7) | \
+ PIN_MODE_INPUT(GPIOE_PIN8) | \
+ PIN_MODE_INPUT(GPIOE_PIN9) | \
+ PIN_MODE_INPUT(GPIOE_PIN10) | \
+ PIN_MODE_INPUT(GPIOE_PIN11) | \
+ PIN_MODE_INPUT(GPIOE_PIN12) | \
+ PIN_MODE_INPUT(GPIOE_PIN13) | \
+ PIN_MODE_INPUT(GPIOE_PIN14) | \
+ PIN_MODE_INPUT(GPIOE_PIN15))
+#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN15))
+#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOE_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN15))
+#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN15))
+#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | \
+ PIN_ODR_HIGH(GPIOE_PIN1) | \
+ PIN_ODR_HIGH(GPIOE_PIN2) | \
+ PIN_ODR_HIGH(GPIOE_PIN3) | \
+ PIN_ODR_HIGH(GPIOE_PIN4) | \
+ PIN_ODR_HIGH(GPIOE_PIN5) | \
+ PIN_ODR_HIGH(GPIOE_PIN6) | \
+ PIN_ODR_HIGH(GPIOE_PIN7) | \
+ PIN_ODR_HIGH(GPIOE_PIN8) | \
+ PIN_ODR_HIGH(GPIOE_PIN9) | \
+ PIN_ODR_HIGH(GPIOE_PIN10) | \
+ PIN_ODR_HIGH(GPIOE_PIN11) | \
+ PIN_ODR_HIGH(GPIOE_PIN12) | \
+ PIN_ODR_HIGH(GPIOE_PIN13) | \
+ PIN_ODR_HIGH(GPIOE_PIN14) | \
+ PIN_ODR_HIGH(GPIOE_PIN15))
+#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN7, 0U))
+#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN15, 0U))
+
+/*
+ * GPIOF setup:
+ *
+ * PF0 - PIN0 (input pullup).
+ * PF1 - PIN1 (input pullup).
+ * PF2 - PIN2 (input pullup).
+ * PF3 - PIN3 (input pullup).
+ * PF4 - PIN4 (input pullup).
+ * PF5 - PIN5 (input pullup).
+ * PF6 - PIN6 (input pullup).
+ * PF7 - PIN7 (input pullup).
+ * PF8 - PIN8 (input pullup).
+ * PF9 - PIN9 (input pullup).
+ * PF10 - PIN10 (input pullup).
+ * PF11 - PIN11 (input pullup).
+ * PF12 - PIN12 (input pullup).
+ * PF13 - PIN13 (input pullup).
+ * PF14 - PIN14 (input pullup).
+ * PF15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_PIN0) | \
+ PIN_MODE_INPUT(GPIOF_PIN1) | \
+ PIN_MODE_INPUT(GPIOF_PIN2) | \
+ PIN_MODE_INPUT(GPIOF_PIN3) | \
+ PIN_MODE_INPUT(GPIOF_PIN4) | \
+ PIN_MODE_INPUT(GPIOF_PIN5) | \
+ PIN_MODE_INPUT(GPIOF_PIN6) | \
+ PIN_MODE_INPUT(GPIOF_PIN7) | \
+ PIN_MODE_INPUT(GPIOF_PIN8) | \
+ PIN_MODE_INPUT(GPIOF_PIN9) | \
+ PIN_MODE_INPUT(GPIOF_PIN10) | \
+ PIN_MODE_INPUT(GPIOF_PIN11) | \
+ PIN_MODE_INPUT(GPIOF_PIN12) | \
+ PIN_MODE_INPUT(GPIOF_PIN13) | \
+ PIN_MODE_INPUT(GPIOF_PIN14) | \
+ PIN_MODE_INPUT(GPIOF_PIN15))
+#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN15))
+#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOF_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN15))
+#define VAL_GPIOF_PUPDR (PIN_PUPDR_PULLUP(GPIOF_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN15))
+#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_PIN0) | \
+ PIN_ODR_HIGH(GPIOF_PIN1) | \
+ PIN_ODR_HIGH(GPIOF_PIN2) | \
+ PIN_ODR_HIGH(GPIOF_PIN3) | \
+ PIN_ODR_HIGH(GPIOF_PIN4) | \
+ PIN_ODR_HIGH(GPIOF_PIN5) | \
+ PIN_ODR_HIGH(GPIOF_PIN6) | \
+ PIN_ODR_HIGH(GPIOF_PIN7) | \
+ PIN_ODR_HIGH(GPIOF_PIN8) | \
+ PIN_ODR_HIGH(GPIOF_PIN9) | \
+ PIN_ODR_HIGH(GPIOF_PIN10) | \
+ PIN_ODR_HIGH(GPIOF_PIN11) | \
+ PIN_ODR_HIGH(GPIOF_PIN12) | \
+ PIN_ODR_HIGH(GPIOF_PIN13) | \
+ PIN_ODR_HIGH(GPIOF_PIN14) | \
+ PIN_ODR_HIGH(GPIOF_PIN15))
+#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN7, 0U))
+#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN15, 0U))
+
+/*
+ * GPIOG setup:
+ *
+ * PG0 - PIN0 (input pullup).
+ * PG1 - PIN1 (input pullup).
+ * PG2 - PIN2 (input pullup).
+ * PG3 - PIN3 (input pullup).
+ * PG4 - PIN4 (input pullup).
+ * PG5 - PIN5 (input pullup).
+ * PG6 - USB_FS_PWR_EN (output pushpull minimum).
+ * PG7 - USB_FS_OVCR (input floating).
+ * PG8 - PIN8 (input pullup).
+ * PG9 - PIN9 (input pullup).
+ * PG10 - PIN10 (input pullup).
+ * PG11 - RMII_TX_EN (alternate 11).
+ * PG12 - PIN12 (input pullup).
+ * PG13 - RMII_TXD0 (alternate 11).
+ * PG14 - PIN14 (input pullup).
+ * PG15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOG_MODER (PIN_MODE_INPUT(GPIOG_PIN0) | \
+ PIN_MODE_INPUT(GPIOG_PIN1) | \
+ PIN_MODE_INPUT(GPIOG_PIN2) | \
+ PIN_MODE_INPUT(GPIOG_PIN3) | \
+ PIN_MODE_INPUT(GPIOG_PIN4) | \
+ PIN_MODE_INPUT(GPIOG_PIN5) | \
+ PIN_MODE_OUTPUT(GPIOG_USB_FS_PWR_EN) | \
+ PIN_MODE_INPUT(GPIOG_USB_FS_OVCR) | \
+ PIN_MODE_INPUT(GPIOG_PIN8) | \
+ PIN_MODE_INPUT(GPIOG_PIN9) | \
+ PIN_MODE_INPUT(GPIOG_PIN10) | \
+ PIN_MODE_ALTERNATE(GPIOG_RMII_TX_EN) | \
+ PIN_MODE_INPUT(GPIOG_PIN12) | \
+ PIN_MODE_ALTERNATE(GPIOG_RMII_TXD0) | \
+ PIN_MODE_INPUT(GPIOG_PIN14) | \
+ PIN_MODE_INPUT(GPIOG_PIN15))
+#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_USB_FS_PWR_EN) |\
+ PIN_OTYPE_PUSHPULL(GPIOG_USB_FS_OVCR) |\
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_RMII_TX_EN) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_RMII_TXD0) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN15))
+#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOG_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOG_USB_FS_PWR_EN) |\
+ PIN_OSPEED_VERYLOW(GPIOG_USB_FS_OVCR) |\
+ PIN_OSPEED_VERYLOW(GPIOG_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOG_RMII_TX_EN) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOG_RMII_TXD0) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN15))
+#define VAL_GPIOG_PUPDR (PIN_PUPDR_PULLUP(GPIOG_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOG_USB_FS_PWR_EN) |\
+ PIN_PUPDR_FLOATING(GPIOG_USB_FS_OVCR) |\
+ PIN_PUPDR_PULLUP(GPIOG_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOG_RMII_TX_EN) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOG_RMII_TXD0) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN15))
+#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_PIN0) | \
+ PIN_ODR_HIGH(GPIOG_PIN1) | \
+ PIN_ODR_HIGH(GPIOG_PIN2) | \
+ PIN_ODR_HIGH(GPIOG_PIN3) | \
+ PIN_ODR_HIGH(GPIOG_PIN4) | \
+ PIN_ODR_HIGH(GPIOG_PIN5) | \
+ PIN_ODR_LOW(GPIOG_USB_FS_PWR_EN) | \
+ PIN_ODR_HIGH(GPIOG_USB_FS_OVCR) | \
+ PIN_ODR_HIGH(GPIOG_PIN8) | \
+ PIN_ODR_HIGH(GPIOG_PIN9) | \
+ PIN_ODR_HIGH(GPIOG_PIN10) | \
+ PIN_ODR_HIGH(GPIOG_RMII_TX_EN) | \
+ PIN_ODR_HIGH(GPIOG_PIN12) | \
+ PIN_ODR_HIGH(GPIOG_RMII_TXD0) | \
+ PIN_ODR_HIGH(GPIOG_PIN14) | \
+ PIN_ODR_HIGH(GPIOG_PIN15))
+#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOG_USB_FS_PWR_EN, 0U) | \
+ PIN_AFIO_AF(GPIOG_USB_FS_OVCR, 0U))
+#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOG_RMII_TX_EN, 11U) | \
+ PIN_AFIO_AF(GPIOG_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOG_RMII_TXD0, 11U) | \
+ PIN_AFIO_AF(GPIOG_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN15, 0U))
+
+/*
+ * GPIOH setup:
+ *
+ * PH0 - OSC_IN (input floating).
+ * PH1 - OSC_OUT (input floating).
+ * PH2 - PIN2 (input pullup).
+ * PH3 - PIN3 (input pullup).
+ * PH4 - PIN4 (input pullup).
+ * PH5 - PIN5 (input pullup).
+ * PH6 - PIN6 (input pullup).
+ * PH7 - PIN7 (input pullup).
+ * PH8 - PIN8 (input pullup).
+ * PH9 - PIN9 (input pullup).
+ * PH10 - PIN10 (input pullup).
+ * PH11 - PIN11 (input pullup).
+ * PH12 - PIN12 (input pullup).
+ * PH13 - PIN13 (input pullup).
+ * PH14 - PIN14 (input pullup).
+ * PH15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_OSC_IN) | \
+ PIN_MODE_INPUT(GPIOH_OSC_OUT) | \
+ PIN_MODE_INPUT(GPIOH_PIN2) | \
+ PIN_MODE_INPUT(GPIOH_PIN3) | \
+ PIN_MODE_INPUT(GPIOH_PIN4) | \
+ PIN_MODE_INPUT(GPIOH_PIN5) | \
+ PIN_MODE_INPUT(GPIOH_PIN6) | \
+ PIN_MODE_INPUT(GPIOH_PIN7) | \
+ PIN_MODE_INPUT(GPIOH_PIN8) | \
+ PIN_MODE_INPUT(GPIOH_PIN9) | \
+ PIN_MODE_INPUT(GPIOH_PIN10) | \
+ PIN_MODE_INPUT(GPIOH_PIN11) | \
+ PIN_MODE_INPUT(GPIOH_PIN12) | \
+ PIN_MODE_INPUT(GPIOH_PIN13) | \
+ PIN_MODE_INPUT(GPIOH_PIN14) | \
+ PIN_MODE_INPUT(GPIOH_PIN15))
+#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_OSC_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_OSC_OUT) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN15))
+#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_HIGH(GPIOH_OSC_IN) | \
+ PIN_OSPEED_HIGH(GPIOH_OSC_OUT) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN15))
+#define VAL_GPIOH_PUPDR (PIN_PUPDR_FLOATING(GPIOH_OSC_IN) | \
+ PIN_PUPDR_FLOATING(GPIOH_OSC_OUT) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN15))
+#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_OSC_IN) | \
+ PIN_ODR_HIGH(GPIOH_OSC_OUT) | \
+ PIN_ODR_HIGH(GPIOH_PIN2) | \
+ PIN_ODR_HIGH(GPIOH_PIN3) | \
+ PIN_ODR_HIGH(GPIOH_PIN4) | \
+ PIN_ODR_HIGH(GPIOH_PIN5) | \
+ PIN_ODR_HIGH(GPIOH_PIN6) | \
+ PIN_ODR_HIGH(GPIOH_PIN7) | \
+ PIN_ODR_HIGH(GPIOH_PIN8) | \
+ PIN_ODR_HIGH(GPIOH_PIN9) | \
+ PIN_ODR_HIGH(GPIOH_PIN10) | \
+ PIN_ODR_HIGH(GPIOH_PIN11) | \
+ PIN_ODR_HIGH(GPIOH_PIN12) | \
+ PIN_ODR_HIGH(GPIOH_PIN13) | \
+ PIN_ODR_HIGH(GPIOH_PIN14) | \
+ PIN_ODR_HIGH(GPIOH_PIN15))
+#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_OSC_IN, 0U) | \
+ PIN_AFIO_AF(GPIOH_OSC_OUT, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN7, 0U))
+#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN15, 0U))
+
+/*
+ * GPIOI setup:
+ *
+ * PI0 - PIN0 (input pullup).
+ * PI1 - PIN1 (input pullup).
+ * PI2 - PIN2 (input pullup).
+ * PI3 - PIN3 (input pullup).
+ * PI4 - PIN4 (input pullup).
+ * PI5 - PIN5 (input pullup).
+ * PI6 - PIN6 (input pullup).
+ * PI7 - PIN7 (input pullup).
+ * PI8 - PIN8 (input pullup).
+ * PI9 - PIN9 (input pullup).
+ * PI10 - PIN10 (input pullup).
+ * PI11 - PIN11 (input pullup).
+ * PI12 - PIN12 (input pullup).
+ * PI13 - PIN13 (input pullup).
+ * PI14 - PIN14 (input pullup).
+ * PI15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOI_MODER (PIN_MODE_INPUT(GPIOI_PIN0) | \
+ PIN_MODE_INPUT(GPIOI_PIN1) | \
+ PIN_MODE_INPUT(GPIOI_PIN2) | \
+ PIN_MODE_INPUT(GPIOI_PIN3) | \
+ PIN_MODE_INPUT(GPIOI_PIN4) | \
+ PIN_MODE_INPUT(GPIOI_PIN5) | \
+ PIN_MODE_INPUT(GPIOI_PIN6) | \
+ PIN_MODE_INPUT(GPIOI_PIN7) | \
+ PIN_MODE_INPUT(GPIOI_PIN8) | \
+ PIN_MODE_INPUT(GPIOI_PIN9) | \
+ PIN_MODE_INPUT(GPIOI_PIN10) | \
+ PIN_MODE_INPUT(GPIOI_PIN11) | \
+ PIN_MODE_INPUT(GPIOI_PIN12) | \
+ PIN_MODE_INPUT(GPIOI_PIN13) | \
+ PIN_MODE_INPUT(GPIOI_PIN14) | \
+ PIN_MODE_INPUT(GPIOI_PIN15))
+#define VAL_GPIOI_OTYPER (PIN_OTYPE_PUSHPULL(GPIOI_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN15))
+#define VAL_GPIOI_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOI_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN15))
+#define VAL_GPIOI_PUPDR (PIN_PUPDR_PULLUP(GPIOI_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN15))
+#define VAL_GPIOI_ODR (PIN_ODR_HIGH(GPIOI_PIN0) | \
+ PIN_ODR_HIGH(GPIOI_PIN1) | \
+ PIN_ODR_HIGH(GPIOI_PIN2) | \
+ PIN_ODR_HIGH(GPIOI_PIN3) | \
+ PIN_ODR_HIGH(GPIOI_PIN4) | \
+ PIN_ODR_HIGH(GPIOI_PIN5) | \
+ PIN_ODR_HIGH(GPIOI_PIN6) | \
+ PIN_ODR_HIGH(GPIOI_PIN7) | \
+ PIN_ODR_HIGH(GPIOI_PIN8) | \
+ PIN_ODR_HIGH(GPIOI_PIN9) | \
+ PIN_ODR_HIGH(GPIOI_PIN10) | \
+ PIN_ODR_HIGH(GPIOI_PIN11) | \
+ PIN_ODR_HIGH(GPIOI_PIN12) | \
+ PIN_ODR_HIGH(GPIOI_PIN13) | \
+ PIN_ODR_HIGH(GPIOI_PIN14) | \
+ PIN_ODR_HIGH(GPIOI_PIN15))
+#define VAL_GPIOI_AFRL (PIN_AFIO_AF(GPIOI_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN7, 0U))
+#define VAL_GPIOI_AFRH (PIN_AFIO_AF(GPIOI_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN15, 0U))
+
+/*
+ * GPIOJ setup:
+ *
+ * PJ0 - PIN0 (input pullup).
+ * PJ1 - PIN1 (input pullup).
+ * PJ2 - PIN2 (input pullup).
+ * PJ3 - PIN3 (input pullup).
+ * PJ4 - PIN4 (input pullup).
+ * PJ5 - PIN5 (input pullup).
+ * PJ6 - PIN6 (input pullup).
+ * PJ7 - PIN7 (input pullup).
+ * PJ8 - PIN8 (input pullup).
+ * PJ9 - PIN9 (input pullup).
+ * PJ10 - PIN10 (input pullup).
+ * PJ11 - PIN11 (input pullup).
+ * PJ12 - PIN12 (input pullup).
+ * PJ13 - PIN13 (input pullup).
+ * PJ14 - PIN14 (input pullup).
+ * PJ15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOJ_MODER (PIN_MODE_INPUT(GPIOJ_PIN0) | \
+ PIN_MODE_INPUT(GPIOJ_PIN1) | \
+ PIN_MODE_INPUT(GPIOJ_PIN2) | \
+ PIN_MODE_INPUT(GPIOJ_PIN3) | \
+ PIN_MODE_INPUT(GPIOJ_PIN4) | \
+ PIN_MODE_INPUT(GPIOJ_PIN5) | \
+ PIN_MODE_INPUT(GPIOJ_PIN6) | \
+ PIN_MODE_INPUT(GPIOJ_PIN7) | \
+ PIN_MODE_INPUT(GPIOJ_PIN8) | \
+ PIN_MODE_INPUT(GPIOJ_PIN9) | \
+ PIN_MODE_INPUT(GPIOJ_PIN10) | \
+ PIN_MODE_INPUT(GPIOJ_PIN11) | \
+ PIN_MODE_INPUT(GPIOJ_PIN12) | \
+ PIN_MODE_INPUT(GPIOJ_PIN13) | \
+ PIN_MODE_INPUT(GPIOJ_PIN14) | \
+ PIN_MODE_INPUT(GPIOJ_PIN15))
+#define VAL_GPIOJ_OTYPER (PIN_OTYPE_PUSHPULL(GPIOJ_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN15))
+#define VAL_GPIOJ_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOJ_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN15))
+#define VAL_GPIOJ_PUPDR (PIN_PUPDR_PULLUP(GPIOJ_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN15))
+#define VAL_GPIOJ_ODR (PIN_ODR_HIGH(GPIOJ_PIN0) | \
+ PIN_ODR_HIGH(GPIOJ_PIN1) | \
+ PIN_ODR_HIGH(GPIOJ_PIN2) | \
+ PIN_ODR_HIGH(GPIOJ_PIN3) | \
+ PIN_ODR_HIGH(GPIOJ_PIN4) | \
+ PIN_ODR_HIGH(GPIOJ_PIN5) | \
+ PIN_ODR_HIGH(GPIOJ_PIN6) | \
+ PIN_ODR_HIGH(GPIOJ_PIN7) | \
+ PIN_ODR_HIGH(GPIOJ_PIN8) | \
+ PIN_ODR_HIGH(GPIOJ_PIN9) | \
+ PIN_ODR_HIGH(GPIOJ_PIN10) | \
+ PIN_ODR_HIGH(GPIOJ_PIN11) | \
+ PIN_ODR_HIGH(GPIOJ_PIN12) | \
+ PIN_ODR_HIGH(GPIOJ_PIN13) | \
+ PIN_ODR_HIGH(GPIOJ_PIN14) | \
+ PIN_ODR_HIGH(GPIOJ_PIN15))
+#define VAL_GPIOJ_AFRL (PIN_AFIO_AF(GPIOJ_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN7, 0U))
+#define VAL_GPIOJ_AFRH (PIN_AFIO_AF(GPIOJ_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN15, 0U))
+
+/*
+ * GPIOK setup:
+ *
+ * PK0 - PIN0 (input pullup).
+ * PK1 - PIN1 (input pullup).
+ * PK2 - PIN2 (input pullup).
+ * PK3 - PIN3 (input pullup).
+ * PK4 - PIN4 (input pullup).
+ * PK5 - PIN5 (input pullup).
+ * PK6 - PIN6 (input pullup).
+ * PK7 - PIN7 (input pullup).
+ * PK8 - PIN8 (input pullup).
+ * PK9 - PIN9 (input pullup).
+ * PK10 - PIN10 (input pullup).
+ * PK11 - PIN11 (input pullup).
+ * PK12 - PIN12 (input pullup).
+ * PK13 - PIN13 (input pullup).
+ * PK14 - PIN14 (input pullup).
+ * PK15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOK_MODER (PIN_MODE_INPUT(GPIOK_PIN0) | \
+ PIN_MODE_INPUT(GPIOK_PIN1) | \
+ PIN_MODE_INPUT(GPIOK_PIN2) | \
+ PIN_MODE_INPUT(GPIOK_PIN3) | \
+ PIN_MODE_INPUT(GPIOK_PIN4) | \
+ PIN_MODE_INPUT(GPIOK_PIN5) | \
+ PIN_MODE_INPUT(GPIOK_PIN6) | \
+ PIN_MODE_INPUT(GPIOK_PIN7) | \
+ PIN_MODE_INPUT(GPIOK_PIN8) | \
+ PIN_MODE_INPUT(GPIOK_PIN9) | \
+ PIN_MODE_INPUT(GPIOK_PIN10) | \
+ PIN_MODE_INPUT(GPIOK_PIN11) | \
+ PIN_MODE_INPUT(GPIOK_PIN12) | \
+ PIN_MODE_INPUT(GPIOK_PIN13) | \
+ PIN_MODE_INPUT(GPIOK_PIN14) | \
+ PIN_MODE_INPUT(GPIOK_PIN15))
+#define VAL_GPIOK_OTYPER (PIN_OTYPE_PUSHPULL(GPIOK_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN15))
+#define VAL_GPIOK_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOK_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN15))
+#define VAL_GPIOK_PUPDR (PIN_PUPDR_PULLUP(GPIOK_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN15))
+#define VAL_GPIOK_ODR (PIN_ODR_HIGH(GPIOK_PIN0) | \
+ PIN_ODR_HIGH(GPIOK_PIN1) | \
+ PIN_ODR_HIGH(GPIOK_PIN2) | \
+ PIN_ODR_HIGH(GPIOK_PIN3) | \
+ PIN_ODR_HIGH(GPIOK_PIN4) | \
+ PIN_ODR_HIGH(GPIOK_PIN5) | \
+ PIN_ODR_HIGH(GPIOK_PIN6) | \
+ PIN_ODR_HIGH(GPIOK_PIN7) | \
+ PIN_ODR_HIGH(GPIOK_PIN8) | \
+ PIN_ODR_HIGH(GPIOK_PIN9) | \
+ PIN_ODR_HIGH(GPIOK_PIN10) | \
+ PIN_ODR_HIGH(GPIOK_PIN11) | \
+ PIN_ODR_HIGH(GPIOK_PIN12) | \
+ PIN_ODR_HIGH(GPIOK_PIN13) | \
+ PIN_ODR_HIGH(GPIOK_PIN14) | \
+ PIN_ODR_HIGH(GPIOK_PIN15))
+#define VAL_GPIOK_AFRL (PIN_AFIO_AF(GPIOK_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN7, 0U))
+#define VAL_GPIOK_AFRH (PIN_AFIO_AF(GPIOK_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN15, 0U))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* BOARD_H */
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H743ZI/board.mk b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H743ZI/board.mk
new file mode 100644
index 0000000..2b81cfe
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H743ZI/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO144_H743ZI/board.c
+
+# Required include directories
+BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO144_H743ZI
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC += $(BOARDINC)
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H743ZI/cfg/board.chcfg b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H743ZI/cfg/board.chcfg
new file mode 100644
index 0000000..c9948ca
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H743ZI/cfg/board.chcfg
@@ -0,0 +1,1459 @@
+
+
+
+
+ resources/gencfg/processors/boards/stm32h7xx/templates
+ ..
+ 5.0.x
+
+ STMicroelectronics STM32 Nucleo144-H743ZI
+ ST_NUCLEO144_H743ZI
+
+
+
+ MII_LAN8742A_ID
+ RMII
+
+ STM32H743xx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H743ZI/cfg/board.fmpp b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H743ZI/cfg/board.fmpp
new file mode 100644
index 0000000..5003d98
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H743ZI/cfg/board.fmpp
@@ -0,0 +1,15 @@
+sourceRoot: ../../../../../tools/ftl/processors/boards/stm32h7xx/templates
+outputRoot: ..
+dataRoot: .
+
+freemarkerLinks: {
+ lib: ../../../../../tools/ftl/libs
+}
+
+data : {
+ doc1:xml (
+ board.chcfg
+ {
+ }
+ )
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H755ZI/board.c b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H755ZI/board.c
new file mode 100644
index 0000000..2868726
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H755ZI/board.c
@@ -0,0 +1,266 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#include "hal.h"
+#include "stm32_gpio.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of STM32 GPIO port setup.
+ */
+typedef struct {
+ uint32_t moder;
+ uint32_t otyper;
+ uint32_t ospeedr;
+ uint32_t pupdr;
+ uint32_t odr;
+ uint32_t afrl;
+ uint32_t afrh;
+} gpio_setup_t;
+
+/**
+ * @brief Type of STM32 GPIO initialization data.
+ */
+typedef struct {
+#if STM32_HAS_GPIOA || defined(__DOXYGEN__)
+ gpio_setup_t PAData;
+#endif
+#if STM32_HAS_GPIOB || defined(__DOXYGEN__)
+ gpio_setup_t PBData;
+#endif
+#if STM32_HAS_GPIOC || defined(__DOXYGEN__)
+ gpio_setup_t PCData;
+#endif
+#if STM32_HAS_GPIOD || defined(__DOXYGEN__)
+ gpio_setup_t PDData;
+#endif
+#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
+ gpio_setup_t PEData;
+#endif
+#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
+ gpio_setup_t PFData;
+#endif
+#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
+ gpio_setup_t PGData;
+#endif
+#if STM32_HAS_GPIOH || defined(__DOXYGEN__)
+ gpio_setup_t PHData;
+#endif
+#if STM32_HAS_GPIOI || defined(__DOXYGEN__)
+ gpio_setup_t PIData;
+#endif
+#if STM32_HAS_GPIOJ || defined(__DOXYGEN__)
+ gpio_setup_t PJData;
+#endif
+#if STM32_HAS_GPIOK || defined(__DOXYGEN__)
+ gpio_setup_t PKData;
+#endif
+} gpio_config_t;
+
+/**
+ * @brief STM32 GPIO static initialization data.
+ */
+static const gpio_config_t gpio_default_config = {
+#if STM32_HAS_GPIOA
+ {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
+ VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH},
+#endif
+#if STM32_HAS_GPIOB
+ {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR,
+ VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH},
+#endif
+#if STM32_HAS_GPIOC
+ {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR,
+ VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH},
+#endif
+#if STM32_HAS_GPIOD
+ {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR,
+ VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH},
+#endif
+#if STM32_HAS_GPIOE
+ {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR,
+ VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH},
+#endif
+#if STM32_HAS_GPIOF
+ {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR,
+ VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH},
+#endif
+#if STM32_HAS_GPIOG
+ {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR,
+ VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH},
+#endif
+#if STM32_HAS_GPIOH
+ {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR,
+ VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH},
+#endif
+#if STM32_HAS_GPIOI
+ {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
+ VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH},
+#endif
+#if STM32_HAS_GPIOJ
+ {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR,
+ VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH},
+#endif
+#if STM32_HAS_GPIOK
+ {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR,
+ VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH}
+#endif
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) {
+
+ gpiop->OTYPER = config->otyper;
+ gpiop->OSPEEDR = config->ospeedr;
+ gpiop->PUPDR = config->pupdr;
+ gpiop->ODR = config->odr;
+ gpiop->AFRL = config->afrl;
+ gpiop->AFRH = config->afrh;
+ gpiop->MODER = config->moder;
+}
+
+static void stm32_gpio_init(void) {
+
+ /* Enabling GPIO-related clocks, the mask comes from the
+ registry header file.*/
+ rccResetAHB4(STM32_GPIO_EN_MASK);
+ rccEnableAHB4(STM32_GPIO_EN_MASK, true);
+
+ /* Initializing all the defined GPIO ports.*/
+#if STM32_HAS_GPIOA
+ gpio_init(GPIOA, &gpio_default_config.PAData);
+#endif
+#if STM32_HAS_GPIOB
+ gpio_init(GPIOB, &gpio_default_config.PBData);
+#endif
+#if STM32_HAS_GPIOC
+ gpio_init(GPIOC, &gpio_default_config.PCData);
+#endif
+#if STM32_HAS_GPIOD
+ gpio_init(GPIOD, &gpio_default_config.PDData);
+#endif
+#if STM32_HAS_GPIOE
+ gpio_init(GPIOE, &gpio_default_config.PEData);
+#endif
+#if STM32_HAS_GPIOF
+ gpio_init(GPIOF, &gpio_default_config.PFData);
+#endif
+#if STM32_HAS_GPIOG
+ gpio_init(GPIOG, &gpio_default_config.PGData);
+#endif
+#if STM32_HAS_GPIOH
+ gpio_init(GPIOH, &gpio_default_config.PHData);
+#endif
+#if STM32_HAS_GPIOI
+ gpio_init(GPIOI, &gpio_default_config.PIData);
+#endif
+#if STM32_HAS_GPIOJ
+ gpio_init(GPIOJ, &gpio_default_config.PJData);
+#endif
+#if STM32_HAS_GPIOK
+ gpio_init(GPIOK, &gpio_default_config.PKData);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Early initialization code.
+ * @details GPIO ports and system clocks are initialized before everything
+ * else.
+ */
+void __early_init(void) {
+
+ stm32_gpio_init();
+ stm32_clock_init();
+}
+
+#if HAL_USE_SDC || defined(__DOXYGEN__)
+/**
+ * @brief SDC card detection.
+ */
+bool sdc_lld_is_card_inserted(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief SDC card write protection detection.
+ */
+bool sdc_lld_is_write_protected(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif /* HAL_USE_SDC */
+
+#if HAL_USE_MMC_SPI || defined(__DOXYGEN__)
+/**
+ * @brief MMC_SPI card detection.
+ */
+bool mmc_lld_is_card_inserted(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief MMC_SPI card write protection detection.
+ */
+bool mmc_lld_is_write_protected(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif
+
+/**
+ * @brief Board-specific initialization code.
+ * @note You can add your board-specific code here.
+ */
+void boardInit(void) {
+
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H755ZI/board.h b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H755ZI/board.h
new file mode 100644
index 0000000..ab8b5b9
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H755ZI/board.h
@@ -0,0 +1,1642 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#ifndef BOARD_H
+#define BOARD_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*
+ * Setup for STMicroelectronics STM32 Nucleo144-H755ZI board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_ST_NUCLEO144_H755ZI
+#define BOARD_NAME "STMicroelectronics STM32 Nucleo144-H755ZI"
+
+/*
+ * Ethernet PHY type.
+ */
+#define BOARD_PHY_ID MII_LAN8742A_ID
+#define BOARD_PHY_RMII
+
+/*
+ * Board oscillators-related settings.
+ */
+#if !defined(STM32_LSECLK)
+#define STM32_LSECLK 32768U
+#endif
+
+#define STM32_LSEDRV (3U << 3U)
+
+#if !defined(STM32_HSECLK)
+#define STM32_HSECLK 8000000U
+#endif
+
+#define STM32_HSE_BYPASS
+
+/*
+ * MCU type as defined in the ST header.
+ */
+#define STM32H755xx
+
+/*
+ * IO pins assignments.
+ */
+#define GPIOA_PIN0 0U
+#define GPIOA_RMII_REF_CLK 1U
+#define GPIOA_RMII_MDIO 2U
+#define GPIOA_PIN3 3U
+#define GPIOA_PIN4 4U
+#define GPIOA_PIN5 5U
+#define GPIOA_PIN6 6U
+#define GPIOA_RMII_CRS_DV 7U
+#define GPIOA_USB_SOF 8U
+#define GPIOA_MCO1 8U
+#define GPIOA_USB_VBUS 9U
+#define GPIOA_USB_ID 10U
+#define GPIOA_USB_DM 11U
+#define GPIOA_USB_DP 12U
+#define GPIOA_SWDIO 13U
+#define GPIOA_SWCLK 14U
+#define GPIOA_T_JTDI 15U
+
+#define GPIOB_LED1 0U
+#define GPIOB_LED_GREEN 0U
+#define GPIOB_LED 0U
+#define GPIOB_PIN1 1U
+#define GPIOB_PIN2 2U
+#define GPIOB_SWO 3U
+#define GPIOB_PIN4 4U
+#define GPIOB_PIN5 5U
+#define GPIOB_PIN6 6U
+#define GPIOB_PIN7 7U
+#define GPIOB_PIN8 8U
+#define GPIOB_PIN9 9U
+#define GPIOB_PIN10 10U
+#define GPIOB_PIN11 11U
+#define GPIOB_PIN12 12U
+#define GPIOB_RMII_TXD1 13U
+#define GPIOB_LED3 14U
+#define GPIOB_LED_RED 14U
+#define GPIOB_PIN15 15U
+
+#define GPIOC_PIN0 0U
+#define GPIOC_RMII_MDC 1U
+#define GPIOC_PIN2 2U
+#define GPIOC_PIN3 3U
+#define GPIOC_RMII_RXD0 4U
+#define GPIOC_RMII_RXD1 5U
+#define GPIOC_PIN6 6U
+#define GPIOC_PIN7 7U
+#define GPIOC_PIN8 8U
+#define GPIOC_PIN9 9U
+#define GPIOC_PIN10 10U
+#define GPIOC_PIN11 11U
+#define GPIOC_PIN12 12U
+#define GPIOC_BUTTON 13U
+#define GPIOC_OSC32_IN 14U
+#define GPIOC_OSC32_OUT 15U
+
+#define GPIOD_PIN0 0U
+#define GPIOD_PIN1 1U
+#define GPIOD_PIN2 2U
+#define GPIOD_PIN3 3U
+#define GPIOD_PIN4 4U
+#define GPIOD_PIN5 5U
+#define GPIOD_PIN6 6U
+#define GPIOD_PIN7 7U
+#define GPIOD_USART3_RX 8U
+#define GPIOD_STLK_RX 8U
+#define GPIOD_USART3_TX 9U
+#define GPIOD_STLK_TX 9U
+#define GPIOD_USB_FS_PWR_EN 10U
+#define GPIOD_PIN11 11U
+#define GPIOD_PIN12 12U
+#define GPIOD_PIN13 13U
+#define GPIOD_PIN14 14U
+#define GPIOD_PIN15 15U
+
+#define GPIOE_PIN0 0U
+#define GPIOE_LED2 1U
+#define GPIOE_LED_YELLOW 1U
+#define GPIOE_PIN2 2U
+#define GPIOE_PIN3 3U
+#define GPIOE_PIN4 4U
+#define GPIOE_PIN5 5U
+#define GPIOE_PIN6 6U
+#define GPIOE_PIN7 7U
+#define GPIOE_PIN8 8U
+#define GPIOE_PIN9 9U
+#define GPIOE_PIN10 10U
+#define GPIOE_PIN11 11U
+#define GPIOE_PIN12 12U
+#define GPIOE_PIN13 13U
+#define GPIOE_PIN14 14U
+#define GPIOE_PIN15 15U
+
+#define GPIOF_PIN0 0U
+#define GPIOF_PIN1 1U
+#define GPIOF_PIN2 2U
+#define GPIOF_PIN3 3U
+#define GPIOF_PIN4 4U
+#define GPIOF_PIN5 5U
+#define GPIOF_PIN6 6U
+#define GPIOF_PIN7 7U
+#define GPIOF_PIN8 8U
+#define GPIOF_PIN9 9U
+#define GPIOF_PIN10 10U
+#define GPIOF_PIN11 11U
+#define GPIOF_PIN12 12U
+#define GPIOF_PIN13 13U
+#define GPIOF_PIN14 14U
+#define GPIOF_PIN15 15U
+
+#define GPIOG_PIN0 0U
+#define GPIOG_PIN1 1U
+#define GPIOG_PIN2 2U
+#define GPIOG_PIN3 3U
+#define GPIOG_PIN4 4U
+#define GPIOG_PIN5 5U
+#define GPIOG_PIN6 6U
+#define GPIOG_USB_FS_OVCR 7U
+#define GPIOG_PIN8 8U
+#define GPIOG_PIN9 9U
+#define GPIOG_PIN10 10U
+#define GPIOG_RMII_TX_EN 11U
+#define GPIOG_PIN12 12U
+#define GPIOG_RMII_TXD0 13U
+#define GPIOG_PIN14 14U
+#define GPIOG_PIN15 15U
+
+#define GPIOH_OSC_IN 0U
+#define GPIOH_OSC_OUT 1U
+#define GPIOH_PIN2 2U
+#define GPIOH_PIN3 3U
+#define GPIOH_PIN4 4U
+#define GPIOH_PIN5 5U
+#define GPIOH_PIN6 6U
+#define GPIOH_PIN7 7U
+#define GPIOH_PIN8 8U
+#define GPIOH_PIN9 9U
+#define GPIOH_PIN10 10U
+#define GPIOH_PIN11 11U
+#define GPIOH_PIN12 12U
+#define GPIOH_PIN13 13U
+#define GPIOH_PIN14 14U
+#define GPIOH_PIN15 15U
+
+#define GPIOI_PIN0 0U
+#define GPIOI_PIN1 1U
+#define GPIOI_PIN2 2U
+#define GPIOI_PIN3 3U
+#define GPIOI_PIN4 4U
+#define GPIOI_PIN5 5U
+#define GPIOI_PIN6 6U
+#define GPIOI_PIN7 7U
+#define GPIOI_PIN8 8U
+#define GPIOI_PIN9 9U
+#define GPIOI_PIN10 10U
+#define GPIOI_PIN11 11U
+#define GPIOI_PIN12 12U
+#define GPIOI_PIN13 13U
+#define GPIOI_PIN14 14U
+#define GPIOI_PIN15 15U
+
+#define GPIOJ_PIN0 0U
+#define GPIOJ_PIN1 1U
+#define GPIOJ_PIN2 2U
+#define GPIOJ_PIN3 3U
+#define GPIOJ_PIN4 4U
+#define GPIOJ_PIN5 5U
+#define GPIOJ_PIN6 6U
+#define GPIOJ_PIN7 7U
+#define GPIOJ_PIN8 8U
+#define GPIOJ_PIN9 9U
+#define GPIOJ_PIN10 10U
+#define GPIOJ_PIN11 11U
+#define GPIOJ_PIN12 12U
+#define GPIOJ_PIN13 13U
+#define GPIOJ_PIN14 14U
+#define GPIOJ_PIN15 15U
+
+#define GPIOK_PIN0 0U
+#define GPIOK_PIN1 1U
+#define GPIOK_PIN2 2U
+#define GPIOK_PIN3 3U
+#define GPIOK_PIN4 4U
+#define GPIOK_PIN5 5U
+#define GPIOK_PIN6 6U
+#define GPIOK_PIN7 7U
+#define GPIOK_PIN8 8U
+#define GPIOK_PIN9 9U
+#define GPIOK_PIN10 10U
+#define GPIOK_PIN11 11U
+#define GPIOK_PIN12 12U
+#define GPIOK_PIN13 13U
+#define GPIOK_PIN14 14U
+#define GPIOK_PIN15 15U
+
+/*
+ * IO lines assignments.
+ */
+#define LINE_RMII_REF_CLK PAL_LINE(GPIOA, 1U)
+#define LINE_RMII_MDIO PAL_LINE(GPIOA, 2U)
+#define LINE_RMII_CRS_DV PAL_LINE(GPIOA, 7U)
+#define LINE_USB_SOF PAL_LINE(GPIOA, 8U)
+#define LINE_MCO1 PAL_LINE(GPIOA, 8U)
+#define LINE_USB_VBUS PAL_LINE(GPIOA, 9U)
+#define LINE_USB_ID PAL_LINE(GPIOA, 10U)
+#define LINE_USB_DM PAL_LINE(GPIOA, 11U)
+#define LINE_USB_DP PAL_LINE(GPIOA, 12U)
+#define LINE_SWDIO PAL_LINE(GPIOA, 13U)
+#define LINE_SWCLK PAL_LINE(GPIOA, 14U)
+#define LINE_T_JTDI PAL_LINE(GPIOA, 15U)
+#define LINE_LED1 PAL_LINE(GPIOB, 0U)
+#define LINE_LED_GREEN PAL_LINE(GPIOB, 0U)
+#define LINE_LED PAL_LINE(GPIOB, 0U)
+#define LINE_SWO PAL_LINE(GPIOB, 3U)
+#define LINE_RMII_TXD1 PAL_LINE(GPIOB, 13U)
+#define LINE_LED3 PAL_LINE(GPIOB, 14U)
+#define LINE_LED_RED PAL_LINE(GPIOB, 14U)
+#define LINE_RMII_MDC PAL_LINE(GPIOC, 1U)
+#define LINE_RMII_RXD0 PAL_LINE(GPIOC, 4U)
+#define LINE_RMII_RXD1 PAL_LINE(GPIOC, 5U)
+#define LINE_BUTTON PAL_LINE(GPIOC, 13U)
+#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U)
+#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U)
+#define LINE_USART3_RX PAL_LINE(GPIOD, 8U)
+#define LINE_STLK_RX PAL_LINE(GPIOD, 8U)
+#define LINE_USART3_TX PAL_LINE(GPIOD, 9U)
+#define LINE_STLK_TX PAL_LINE(GPIOD, 9U)
+#define LINE_USB_FS_PWR_EN PAL_LINE(GPIOD, 10U)
+#define LINE_LED2 PAL_LINE(GPIOE, 1U)
+#define LINE_LED_YELLOW PAL_LINE(GPIOE, 1U)
+#define LINE_USB_FS_OVCR PAL_LINE(GPIOG, 7U)
+#define LINE_RMII_TX_EN PAL_LINE(GPIOG, 11U)
+#define LINE_RMII_TXD0 PAL_LINE(GPIOG, 13U)
+#define LINE_OSC_IN PAL_LINE(GPIOH, 0U)
+#define LINE_OSC_OUT PAL_LINE(GPIOH, 1U)
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*
+ * I/O ports initial setup, this configuration is established soon after reset
+ * in the initialization code.
+ * Please refer to the STM32 Reference Manual for details.
+ */
+#define PIN_MODE_INPUT(n) (0U << ((n) * 2U))
+#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U))
+#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U))
+#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U))
+#define PIN_ODR_LOW(n) (0U << (n))
+#define PIN_ODR_HIGH(n) (1U << (n))
+#define PIN_OTYPE_PUSHPULL(n) (0U << (n))
+#define PIN_OTYPE_OPENDRAIN(n) (1U << (n))
+#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U))
+#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U))
+#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U))
+#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U))
+#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U))
+#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U))
+#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U))
+#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U))
+
+/*
+ * GPIOA setup:
+ *
+ * PA0 - PIN0 (input pullup).
+ * PA1 - RMII_REF_CLK (alternate 11).
+ * PA2 - RMII_MDIO (alternate 11).
+ * PA3 - PIN3 (input pullup).
+ * PA4 - PIN4 (input pullup).
+ * PA5 - PIN5 (input pullup).
+ * PA6 - PIN6 (input pullup).
+ * PA7 - RMII_CRS_DV (alternate 11).
+ * PA8 - USB_SOF MCO1 (alternate 10).
+ * PA9 - USB_VBUS (analog).
+ * PA10 - USB_ID (alternate 10).
+ * PA11 - USB_DM (alternate 10).
+ * PA12 - USB_DP (alternate 10).
+ * PA13 - SWDIO (alternate 0).
+ * PA14 - SWCLK (alternate 0).
+ * PA15 - T_JTDI (alternate 0).
+ */
+#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_PIN0) | \
+ PIN_MODE_ALTERNATE(GPIOA_RMII_REF_CLK) |\
+ PIN_MODE_ALTERNATE(GPIOA_RMII_MDIO) | \
+ PIN_MODE_INPUT(GPIOA_PIN3) | \
+ PIN_MODE_INPUT(GPIOA_PIN4) | \
+ PIN_MODE_INPUT(GPIOA_PIN5) | \
+ PIN_MODE_INPUT(GPIOA_PIN6) | \
+ PIN_MODE_ALTERNATE(GPIOA_RMII_CRS_DV) |\
+ PIN_MODE_ALTERNATE(GPIOA_USB_SOF) | \
+ PIN_MODE_ANALOG(GPIOA_USB_VBUS) | \
+ PIN_MODE_ALTERNATE(GPIOA_USB_ID) | \
+ PIN_MODE_ALTERNATE(GPIOA_USB_DM) | \
+ PIN_MODE_ALTERNATE(GPIOA_USB_DP) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \
+ PIN_MODE_ALTERNATE(GPIOA_T_JTDI))
+#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_RMII_REF_CLK) |\
+ PIN_OTYPE_PUSHPULL(GPIOA_RMII_MDIO) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_RMII_CRS_DV) |\
+ PIN_OTYPE_PUSHPULL(GPIOA_USB_SOF) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_USB_VBUS) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_USB_ID) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_USB_DM) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_USB_DP) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_T_JTDI))
+#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOA_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOA_RMII_REF_CLK) | \
+ PIN_OSPEED_HIGH(GPIOA_RMII_MDIO) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOA_RMII_CRS_DV) | \
+ PIN_OSPEED_HIGH(GPIOA_USB_SOF) | \
+ PIN_OSPEED_HIGH(GPIOA_USB_VBUS) | \
+ PIN_OSPEED_HIGH(GPIOA_USB_ID) | \
+ PIN_OSPEED_HIGH(GPIOA_USB_DM) | \
+ PIN_OSPEED_HIGH(GPIOA_USB_DP) | \
+ PIN_OSPEED_HIGH(GPIOA_SWDIO) | \
+ PIN_OSPEED_HIGH(GPIOA_SWCLK) | \
+ PIN_OSPEED_HIGH(GPIOA_T_JTDI))
+#define VAL_GPIOA_PUPDR (PIN_PUPDR_PULLUP(GPIOA_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOA_RMII_REF_CLK) |\
+ PIN_PUPDR_PULLUP(GPIOA_RMII_MDIO) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOA_RMII_CRS_DV) | \
+ PIN_PUPDR_FLOATING(GPIOA_USB_SOF) | \
+ PIN_PUPDR_FLOATING(GPIOA_USB_VBUS) | \
+ PIN_PUPDR_FLOATING(GPIOA_USB_ID) | \
+ PIN_PUPDR_FLOATING(GPIOA_USB_DM) | \
+ PIN_PUPDR_FLOATING(GPIOA_USB_DP) | \
+ PIN_PUPDR_FLOATING(GPIOA_SWDIO) | \
+ PIN_PUPDR_FLOATING(GPIOA_SWCLK) | \
+ PIN_PUPDR_PULLUP(GPIOA_T_JTDI))
+#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_PIN0) | \
+ PIN_ODR_HIGH(GPIOA_RMII_REF_CLK) | \
+ PIN_ODR_HIGH(GPIOA_RMII_MDIO) | \
+ PIN_ODR_HIGH(GPIOA_PIN3) | \
+ PIN_ODR_HIGH(GPIOA_PIN4) | \
+ PIN_ODR_HIGH(GPIOA_PIN5) | \
+ PIN_ODR_HIGH(GPIOA_PIN6) | \
+ PIN_ODR_HIGH(GPIOA_RMII_CRS_DV) | \
+ PIN_ODR_HIGH(GPIOA_USB_SOF) | \
+ PIN_ODR_HIGH(GPIOA_USB_VBUS) | \
+ PIN_ODR_HIGH(GPIOA_USB_ID) | \
+ PIN_ODR_HIGH(GPIOA_USB_DM) | \
+ PIN_ODR_HIGH(GPIOA_USB_DP) | \
+ PIN_ODR_HIGH(GPIOA_SWDIO) | \
+ PIN_ODR_HIGH(GPIOA_SWCLK) | \
+ PIN_ODR_HIGH(GPIOA_T_JTDI))
+#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOA_RMII_REF_CLK, 11U) | \
+ PIN_AFIO_AF(GPIOA_RMII_MDIO, 11U) | \
+ PIN_AFIO_AF(GPIOA_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOA_RMII_CRS_DV, 11U))
+#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_USB_SOF, 10U) | \
+ PIN_AFIO_AF(GPIOA_USB_VBUS, 0U) | \
+ PIN_AFIO_AF(GPIOA_USB_ID, 10U) | \
+ PIN_AFIO_AF(GPIOA_USB_DM, 10U) | \
+ PIN_AFIO_AF(GPIOA_USB_DP, 10U) | \
+ PIN_AFIO_AF(GPIOA_SWDIO, 0U) | \
+ PIN_AFIO_AF(GPIOA_SWCLK, 0U) | \
+ PIN_AFIO_AF(GPIOA_T_JTDI, 0U))
+
+/*
+ * GPIOB setup:
+ *
+ * PB0 - LED1 LED_GREEN LED (output pushpull maximum).
+ * PB1 - PIN1 (input pullup).
+ * PB2 - PIN2 (input pullup).
+ * PB3 - SWO (alternate 0).
+ * PB4 - PIN4 (input pullup).
+ * PB5 - PIN5 (input pullup).
+ * PB6 - PIN6 (input pullup).
+ * PB7 - PIN7 (input pullup).
+ * PB8 - PIN8 (input pullup).
+ * PB9 - PIN9 (input pullup).
+ * PB10 - PIN10 (input pullup).
+ * PB11 - PIN11 (input pullup).
+ * PB12 - PIN12 (input pullup).
+ * PB13 - RMII_TXD1 (alternate 11).
+ * PB14 - LED3 LED_RED (output pushpull maximum).
+ * PB15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOB_MODER (PIN_MODE_OUTPUT(GPIOB_LED1) | \
+ PIN_MODE_INPUT(GPIOB_PIN1) | \
+ PIN_MODE_INPUT(GPIOB_PIN2) | \
+ PIN_MODE_ALTERNATE(GPIOB_SWO) | \
+ PIN_MODE_INPUT(GPIOB_PIN4) | \
+ PIN_MODE_INPUT(GPIOB_PIN5) | \
+ PIN_MODE_INPUT(GPIOB_PIN6) | \
+ PIN_MODE_INPUT(GPIOB_PIN7) | \
+ PIN_MODE_INPUT(GPIOB_PIN8) | \
+ PIN_MODE_INPUT(GPIOB_PIN9) | \
+ PIN_MODE_INPUT(GPIOB_PIN10) | \
+ PIN_MODE_INPUT(GPIOB_PIN11) | \
+ PIN_MODE_INPUT(GPIOB_PIN12) | \
+ PIN_MODE_ALTERNATE(GPIOB_RMII_TXD1) | \
+ PIN_MODE_OUTPUT(GPIOB_LED3) | \
+ PIN_MODE_INPUT(GPIOB_PIN15))
+#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_LED1) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_SWO) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_RMII_TXD1) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_LED3) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN15))
+#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_LED1) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOB_SWO) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOB_RMII_TXD1) | \
+ PIN_OSPEED_HIGH(GPIOB_LED3) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN15))
+#define VAL_GPIOB_PUPDR (PIN_PUPDR_FLOATING(GPIOB_LED1) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOB_SWO) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOB_RMII_TXD1) | \
+ PIN_PUPDR_FLOATING(GPIOB_LED3) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN15))
+#define VAL_GPIOB_ODR (PIN_ODR_LOW(GPIOB_LED1) | \
+ PIN_ODR_HIGH(GPIOB_PIN1) | \
+ PIN_ODR_HIGH(GPIOB_PIN2) | \
+ PIN_ODR_HIGH(GPIOB_SWO) | \
+ PIN_ODR_HIGH(GPIOB_PIN4) | \
+ PIN_ODR_HIGH(GPIOB_PIN5) | \
+ PIN_ODR_HIGH(GPIOB_PIN6) | \
+ PIN_ODR_HIGH(GPIOB_PIN7) | \
+ PIN_ODR_HIGH(GPIOB_PIN8) | \
+ PIN_ODR_HIGH(GPIOB_PIN9) | \
+ PIN_ODR_HIGH(GPIOB_PIN10) | \
+ PIN_ODR_HIGH(GPIOB_PIN11) | \
+ PIN_ODR_HIGH(GPIOB_PIN12) | \
+ PIN_ODR_HIGH(GPIOB_RMII_TXD1) | \
+ PIN_ODR_LOW(GPIOB_LED3) | \
+ PIN_ODR_HIGH(GPIOB_PIN15))
+#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_LED1, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOB_SWO, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN7, 0U))
+#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOB_RMII_TXD1, 11U) | \
+ PIN_AFIO_AF(GPIOB_LED3, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN15, 0U))
+
+/*
+ * GPIOC setup:
+ *
+ * PC0 - PIN0 (input pullup).
+ * PC1 - RMII_MDC (alternate 11).
+ * PC2 - PIN2 (input pullup).
+ * PC3 - PIN3 (input pullup).
+ * PC4 - RMII_RXD0 (alternate 11).
+ * PC5 - RMII_RXD1 (alternate 11).
+ * PC6 - PIN6 (input pullup).
+ * PC7 - PIN7 (input pullup).
+ * PC8 - PIN8 (input pullup).
+ * PC9 - PIN9 (input pullup).
+ * PC10 - PIN10 (input pullup).
+ * PC11 - PIN11 (input pullup).
+ * PC12 - PIN12 (input pullup).
+ * PC13 - BUTTON (input floating).
+ * PC14 - OSC32_IN (input floating).
+ * PC15 - OSC32_OUT (input floating).
+ */
+#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_PIN0) | \
+ PIN_MODE_ALTERNATE(GPIOC_RMII_MDC) | \
+ PIN_MODE_INPUT(GPIOC_PIN2) | \
+ PIN_MODE_INPUT(GPIOC_PIN3) | \
+ PIN_MODE_ALTERNATE(GPIOC_RMII_RXD0) | \
+ PIN_MODE_ALTERNATE(GPIOC_RMII_RXD1) | \
+ PIN_MODE_INPUT(GPIOC_PIN6) | \
+ PIN_MODE_INPUT(GPIOC_PIN7) | \
+ PIN_MODE_INPUT(GPIOC_PIN8) | \
+ PIN_MODE_INPUT(GPIOC_PIN9) | \
+ PIN_MODE_INPUT(GPIOC_PIN10) | \
+ PIN_MODE_INPUT(GPIOC_PIN11) | \
+ PIN_MODE_INPUT(GPIOC_PIN12) | \
+ PIN_MODE_INPUT(GPIOC_BUTTON) | \
+ PIN_MODE_INPUT(GPIOC_OSC32_IN) | \
+ PIN_MODE_INPUT(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_RMII_MDC) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_RMII_RXD0) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_RMII_RXD1) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_BUTTON) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOC_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOC_RMII_MDC) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOC_RMII_RXD0) | \
+ PIN_OSPEED_HIGH(GPIOC_RMII_RXD1) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOC_BUTTON) | \
+ PIN_OSPEED_VERYLOW(GPIOC_OSC32_IN) | \
+ PIN_OSPEED_VERYLOW(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOC_RMII_MDC) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOC_RMII_RXD0) | \
+ PIN_PUPDR_FLOATING(GPIOC_RMII_RXD1) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOC_BUTTON) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_PIN0) | \
+ PIN_ODR_HIGH(GPIOC_RMII_MDC) | \
+ PIN_ODR_HIGH(GPIOC_PIN2) | \
+ PIN_ODR_HIGH(GPIOC_PIN3) | \
+ PIN_ODR_HIGH(GPIOC_RMII_RXD0) | \
+ PIN_ODR_HIGH(GPIOC_RMII_RXD1) | \
+ PIN_ODR_HIGH(GPIOC_PIN6) | \
+ PIN_ODR_HIGH(GPIOC_PIN7) | \
+ PIN_ODR_HIGH(GPIOC_PIN8) | \
+ PIN_ODR_HIGH(GPIOC_PIN9) | \
+ PIN_ODR_HIGH(GPIOC_PIN10) | \
+ PIN_ODR_HIGH(GPIOC_PIN11) | \
+ PIN_ODR_HIGH(GPIOC_PIN12) | \
+ PIN_ODR_HIGH(GPIOC_BUTTON) | \
+ PIN_ODR_HIGH(GPIOC_OSC32_IN) | \
+ PIN_ODR_HIGH(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOC_RMII_MDC, 11U) | \
+ PIN_AFIO_AF(GPIOC_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOC_RMII_RXD0, 11U) | \
+ PIN_AFIO_AF(GPIOC_RMII_RXD1, 11U) | \
+ PIN_AFIO_AF(GPIOC_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN7, 0U))
+#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOC_BUTTON, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U))
+
+/*
+ * GPIOD setup:
+ *
+ * PD0 - PIN0 (input pullup).
+ * PD1 - PIN1 (input pullup).
+ * PD2 - PIN2 (input pullup).
+ * PD3 - PIN3 (input pullup).
+ * PD4 - PIN4 (input pullup).
+ * PD5 - PIN5 (input pullup).
+ * PD6 - PIN6 (input pullup).
+ * PD7 - PIN7 (input pullup).
+ * PD8 - USART3_RX STLK_RX (alternate 7).
+ * PD9 - USART3_TX STLK_TX (alternate 7).
+ * PD10 - USB_FS_PWR_EN (output opendrain minimum).
+ * PD11 - PIN11 (input pullup).
+ * PD12 - PIN12 (input pullup).
+ * PD13 - PIN13 (input pullup).
+ * PD14 - PIN14 (input pullup).
+ * PD15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | \
+ PIN_MODE_INPUT(GPIOD_PIN1) | \
+ PIN_MODE_INPUT(GPIOD_PIN2) | \
+ PIN_MODE_INPUT(GPIOD_PIN3) | \
+ PIN_MODE_INPUT(GPIOD_PIN4) | \
+ PIN_MODE_INPUT(GPIOD_PIN5) | \
+ PIN_MODE_INPUT(GPIOD_PIN6) | \
+ PIN_MODE_INPUT(GPIOD_PIN7) | \
+ PIN_MODE_ALTERNATE(GPIOD_USART3_RX) | \
+ PIN_MODE_ALTERNATE(GPIOD_USART3_TX) | \
+ PIN_MODE_OUTPUT(GPIOD_USB_FS_PWR_EN) | \
+ PIN_MODE_INPUT(GPIOD_PIN11) | \
+ PIN_MODE_INPUT(GPIOD_PIN12) | \
+ PIN_MODE_INPUT(GPIOD_PIN13) | \
+ PIN_MODE_INPUT(GPIOD_PIN14) | \
+ PIN_MODE_INPUT(GPIOD_PIN15))
+#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_USART3_RX) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_USART3_TX) | \
+ PIN_OTYPE_OPENDRAIN(GPIOD_USB_FS_PWR_EN) |\
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN15))
+#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOD_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOD_USART3_RX) | \
+ PIN_OSPEED_HIGH(GPIOD_USART3_TX) | \
+ PIN_OSPEED_VERYLOW(GPIOD_USB_FS_PWR_EN) |\
+ PIN_OSPEED_VERYLOW(GPIOD_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN15))
+#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOD_USART3_RX) | \
+ PIN_PUPDR_FLOATING(GPIOD_USART3_TX) | \
+ PIN_PUPDR_FLOATING(GPIOD_USB_FS_PWR_EN) |\
+ PIN_PUPDR_PULLUP(GPIOD_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN15))
+#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \
+ PIN_ODR_HIGH(GPIOD_PIN1) | \
+ PIN_ODR_HIGH(GPIOD_PIN2) | \
+ PIN_ODR_HIGH(GPIOD_PIN3) | \
+ PIN_ODR_HIGH(GPIOD_PIN4) | \
+ PIN_ODR_HIGH(GPIOD_PIN5) | \
+ PIN_ODR_HIGH(GPIOD_PIN6) | \
+ PIN_ODR_HIGH(GPIOD_PIN7) | \
+ PIN_ODR_HIGH(GPIOD_USART3_RX) | \
+ PIN_ODR_HIGH(GPIOD_USART3_TX) | \
+ PIN_ODR_HIGH(GPIOD_USB_FS_PWR_EN) | \
+ PIN_ODR_HIGH(GPIOD_PIN11) | \
+ PIN_ODR_HIGH(GPIOD_PIN12) | \
+ PIN_ODR_HIGH(GPIOD_PIN13) | \
+ PIN_ODR_HIGH(GPIOD_PIN14) | \
+ PIN_ODR_HIGH(GPIOD_PIN15))
+#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN7, 0U))
+#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_USART3_RX, 7U) | \
+ PIN_AFIO_AF(GPIOD_USART3_TX, 7U) | \
+ PIN_AFIO_AF(GPIOD_USB_FS_PWR_EN, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN15, 0U))
+
+/*
+ * GPIOE setup:
+ *
+ * PE0 - PIN0 (input pullup).
+ * PE1 - LED2 LED_YELLOW (output pushpull maximum).
+ * PE2 - PIN2 (input pullup).
+ * PE3 - PIN3 (input pullup).
+ * PE4 - PIN4 (input pullup).
+ * PE5 - PIN5 (input pullup).
+ * PE6 - PIN6 (input pullup).
+ * PE7 - PIN7 (input pullup).
+ * PE8 - PIN8 (input pullup).
+ * PE9 - PIN9 (input pullup).
+ * PE10 - PIN10 (input pullup).
+ * PE11 - PIN11 (input pullup).
+ * PE12 - PIN12 (input pullup).
+ * PE13 - PIN13 (input pullup).
+ * PE14 - PIN14 (input pullup).
+ * PE15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_PIN0) | \
+ PIN_MODE_OUTPUT(GPIOE_LED2) | \
+ PIN_MODE_INPUT(GPIOE_PIN2) | \
+ PIN_MODE_INPUT(GPIOE_PIN3) | \
+ PIN_MODE_INPUT(GPIOE_PIN4) | \
+ PIN_MODE_INPUT(GPIOE_PIN5) | \
+ PIN_MODE_INPUT(GPIOE_PIN6) | \
+ PIN_MODE_INPUT(GPIOE_PIN7) | \
+ PIN_MODE_INPUT(GPIOE_PIN8) | \
+ PIN_MODE_INPUT(GPIOE_PIN9) | \
+ PIN_MODE_INPUT(GPIOE_PIN10) | \
+ PIN_MODE_INPUT(GPIOE_PIN11) | \
+ PIN_MODE_INPUT(GPIOE_PIN12) | \
+ PIN_MODE_INPUT(GPIOE_PIN13) | \
+ PIN_MODE_INPUT(GPIOE_PIN14) | \
+ PIN_MODE_INPUT(GPIOE_PIN15))
+#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_LED2) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN15))
+#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOE_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOE_LED2) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN15))
+#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOE_LED2) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN15))
+#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | \
+ PIN_ODR_LOW(GPIOE_LED2) | \
+ PIN_ODR_HIGH(GPIOE_PIN2) | \
+ PIN_ODR_HIGH(GPIOE_PIN3) | \
+ PIN_ODR_HIGH(GPIOE_PIN4) | \
+ PIN_ODR_HIGH(GPIOE_PIN5) | \
+ PIN_ODR_HIGH(GPIOE_PIN6) | \
+ PIN_ODR_HIGH(GPIOE_PIN7) | \
+ PIN_ODR_HIGH(GPIOE_PIN8) | \
+ PIN_ODR_HIGH(GPIOE_PIN9) | \
+ PIN_ODR_HIGH(GPIOE_PIN10) | \
+ PIN_ODR_HIGH(GPIOE_PIN11) | \
+ PIN_ODR_HIGH(GPIOE_PIN12) | \
+ PIN_ODR_HIGH(GPIOE_PIN13) | \
+ PIN_ODR_HIGH(GPIOE_PIN14) | \
+ PIN_ODR_HIGH(GPIOE_PIN15))
+#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOE_LED2, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN7, 0U))
+#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN15, 0U))
+
+/*
+ * GPIOF setup:
+ *
+ * PF0 - PIN0 (input pullup).
+ * PF1 - PIN1 (input pullup).
+ * PF2 - PIN2 (input pullup).
+ * PF3 - PIN3 (input pullup).
+ * PF4 - PIN4 (input pullup).
+ * PF5 - PIN5 (input pullup).
+ * PF6 - PIN6 (input pullup).
+ * PF7 - PIN7 (input pullup).
+ * PF8 - PIN8 (input pullup).
+ * PF9 - PIN9 (input pullup).
+ * PF10 - PIN10 (input pullup).
+ * PF11 - PIN11 (input pullup).
+ * PF12 - PIN12 (input pullup).
+ * PF13 - PIN13 (input pullup).
+ * PF14 - PIN14 (input pullup).
+ * PF15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_PIN0) | \
+ PIN_MODE_INPUT(GPIOF_PIN1) | \
+ PIN_MODE_INPUT(GPIOF_PIN2) | \
+ PIN_MODE_INPUT(GPIOF_PIN3) | \
+ PIN_MODE_INPUT(GPIOF_PIN4) | \
+ PIN_MODE_INPUT(GPIOF_PIN5) | \
+ PIN_MODE_INPUT(GPIOF_PIN6) | \
+ PIN_MODE_INPUT(GPIOF_PIN7) | \
+ PIN_MODE_INPUT(GPIOF_PIN8) | \
+ PIN_MODE_INPUT(GPIOF_PIN9) | \
+ PIN_MODE_INPUT(GPIOF_PIN10) | \
+ PIN_MODE_INPUT(GPIOF_PIN11) | \
+ PIN_MODE_INPUT(GPIOF_PIN12) | \
+ PIN_MODE_INPUT(GPIOF_PIN13) | \
+ PIN_MODE_INPUT(GPIOF_PIN14) | \
+ PIN_MODE_INPUT(GPIOF_PIN15))
+#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN15))
+#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOF_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN15))
+#define VAL_GPIOF_PUPDR (PIN_PUPDR_PULLUP(GPIOF_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN15))
+#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_PIN0) | \
+ PIN_ODR_HIGH(GPIOF_PIN1) | \
+ PIN_ODR_HIGH(GPIOF_PIN2) | \
+ PIN_ODR_HIGH(GPIOF_PIN3) | \
+ PIN_ODR_HIGH(GPIOF_PIN4) | \
+ PIN_ODR_HIGH(GPIOF_PIN5) | \
+ PIN_ODR_HIGH(GPIOF_PIN6) | \
+ PIN_ODR_HIGH(GPIOF_PIN7) | \
+ PIN_ODR_HIGH(GPIOF_PIN8) | \
+ PIN_ODR_HIGH(GPIOF_PIN9) | \
+ PIN_ODR_HIGH(GPIOF_PIN10) | \
+ PIN_ODR_HIGH(GPIOF_PIN11) | \
+ PIN_ODR_HIGH(GPIOF_PIN12) | \
+ PIN_ODR_HIGH(GPIOF_PIN13) | \
+ PIN_ODR_HIGH(GPIOF_PIN14) | \
+ PIN_ODR_HIGH(GPIOF_PIN15))
+#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN7, 0U))
+#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN15, 0U))
+
+/*
+ * GPIOG setup:
+ *
+ * PG0 - PIN0 (input pullup).
+ * PG1 - PIN1 (input pullup).
+ * PG2 - PIN2 (input pullup).
+ * PG3 - PIN3 (input pullup).
+ * PG4 - PIN4 (input pullup).
+ * PG5 - PIN5 (input pullup).
+ * PG6 - PIN6 (input pullup).
+ * PG7 - USB_FS_OVCR (input floating).
+ * PG8 - PIN8 (input pullup).
+ * PG9 - PIN9 (input pullup).
+ * PG10 - PIN10 (input pullup).
+ * PG11 - RMII_TX_EN (alternate 11).
+ * PG12 - PIN12 (input pullup).
+ * PG13 - RMII_TXD0 (alternate 11).
+ * PG14 - PIN14 (input pullup).
+ * PG15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOG_MODER (PIN_MODE_INPUT(GPIOG_PIN0) | \
+ PIN_MODE_INPUT(GPIOG_PIN1) | \
+ PIN_MODE_INPUT(GPIOG_PIN2) | \
+ PIN_MODE_INPUT(GPIOG_PIN3) | \
+ PIN_MODE_INPUT(GPIOG_PIN4) | \
+ PIN_MODE_INPUT(GPIOG_PIN5) | \
+ PIN_MODE_INPUT(GPIOG_PIN6) | \
+ PIN_MODE_INPUT(GPIOG_USB_FS_OVCR) | \
+ PIN_MODE_INPUT(GPIOG_PIN8) | \
+ PIN_MODE_INPUT(GPIOG_PIN9) | \
+ PIN_MODE_INPUT(GPIOG_PIN10) | \
+ PIN_MODE_ALTERNATE(GPIOG_RMII_TX_EN) | \
+ PIN_MODE_INPUT(GPIOG_PIN12) | \
+ PIN_MODE_ALTERNATE(GPIOG_RMII_TXD0) | \
+ PIN_MODE_INPUT(GPIOG_PIN14) | \
+ PIN_MODE_INPUT(GPIOG_PIN15))
+#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_USB_FS_OVCR) |\
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_RMII_TX_EN) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_RMII_TXD0) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN15))
+#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOG_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOG_USB_FS_OVCR) |\
+ PIN_OSPEED_VERYLOW(GPIOG_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOG_RMII_TX_EN) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOG_RMII_TXD0) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN15))
+#define VAL_GPIOG_PUPDR (PIN_PUPDR_PULLUP(GPIOG_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOG_USB_FS_OVCR) |\
+ PIN_PUPDR_PULLUP(GPIOG_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOG_RMII_TX_EN) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOG_RMII_TXD0) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN15))
+#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_PIN0) | \
+ PIN_ODR_HIGH(GPIOG_PIN1) | \
+ PIN_ODR_HIGH(GPIOG_PIN2) | \
+ PIN_ODR_HIGH(GPIOG_PIN3) | \
+ PIN_ODR_HIGH(GPIOG_PIN4) | \
+ PIN_ODR_HIGH(GPIOG_PIN5) | \
+ PIN_ODR_HIGH(GPIOG_PIN6) | \
+ PIN_ODR_HIGH(GPIOG_USB_FS_OVCR) | \
+ PIN_ODR_HIGH(GPIOG_PIN8) | \
+ PIN_ODR_HIGH(GPIOG_PIN9) | \
+ PIN_ODR_HIGH(GPIOG_PIN10) | \
+ PIN_ODR_HIGH(GPIOG_RMII_TX_EN) | \
+ PIN_ODR_HIGH(GPIOG_PIN12) | \
+ PIN_ODR_HIGH(GPIOG_RMII_TXD0) | \
+ PIN_ODR_HIGH(GPIOG_PIN14) | \
+ PIN_ODR_HIGH(GPIOG_PIN15))
+#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOG_USB_FS_OVCR, 0U))
+#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOG_RMII_TX_EN, 11U) | \
+ PIN_AFIO_AF(GPIOG_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOG_RMII_TXD0, 11U) | \
+ PIN_AFIO_AF(GPIOG_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN15, 0U))
+
+/*
+ * GPIOH setup:
+ *
+ * PH0 - OSC_IN (input floating).
+ * PH1 - OSC_OUT (input floating).
+ * PH2 - PIN2 (input pullup).
+ * PH3 - PIN3 (input pullup).
+ * PH4 - PIN4 (input pullup).
+ * PH5 - PIN5 (input pullup).
+ * PH6 - PIN6 (input pullup).
+ * PH7 - PIN7 (input pullup).
+ * PH8 - PIN8 (input pullup).
+ * PH9 - PIN9 (input pullup).
+ * PH10 - PIN10 (input pullup).
+ * PH11 - PIN11 (input pullup).
+ * PH12 - PIN12 (input pullup).
+ * PH13 - PIN13 (input pullup).
+ * PH14 - PIN14 (input pullup).
+ * PH15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_OSC_IN) | \
+ PIN_MODE_INPUT(GPIOH_OSC_OUT) | \
+ PIN_MODE_INPUT(GPIOH_PIN2) | \
+ PIN_MODE_INPUT(GPIOH_PIN3) | \
+ PIN_MODE_INPUT(GPIOH_PIN4) | \
+ PIN_MODE_INPUT(GPIOH_PIN5) | \
+ PIN_MODE_INPUT(GPIOH_PIN6) | \
+ PIN_MODE_INPUT(GPIOH_PIN7) | \
+ PIN_MODE_INPUT(GPIOH_PIN8) | \
+ PIN_MODE_INPUT(GPIOH_PIN9) | \
+ PIN_MODE_INPUT(GPIOH_PIN10) | \
+ PIN_MODE_INPUT(GPIOH_PIN11) | \
+ PIN_MODE_INPUT(GPIOH_PIN12) | \
+ PIN_MODE_INPUT(GPIOH_PIN13) | \
+ PIN_MODE_INPUT(GPIOH_PIN14) | \
+ PIN_MODE_INPUT(GPIOH_PIN15))
+#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_OSC_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_OSC_OUT) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN15))
+#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_HIGH(GPIOH_OSC_IN) | \
+ PIN_OSPEED_HIGH(GPIOH_OSC_OUT) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN15))
+#define VAL_GPIOH_PUPDR (PIN_PUPDR_FLOATING(GPIOH_OSC_IN) | \
+ PIN_PUPDR_FLOATING(GPIOH_OSC_OUT) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN15))
+#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_OSC_IN) | \
+ PIN_ODR_HIGH(GPIOH_OSC_OUT) | \
+ PIN_ODR_HIGH(GPIOH_PIN2) | \
+ PIN_ODR_HIGH(GPIOH_PIN3) | \
+ PIN_ODR_HIGH(GPIOH_PIN4) | \
+ PIN_ODR_HIGH(GPIOH_PIN5) | \
+ PIN_ODR_HIGH(GPIOH_PIN6) | \
+ PIN_ODR_HIGH(GPIOH_PIN7) | \
+ PIN_ODR_HIGH(GPIOH_PIN8) | \
+ PIN_ODR_HIGH(GPIOH_PIN9) | \
+ PIN_ODR_HIGH(GPIOH_PIN10) | \
+ PIN_ODR_HIGH(GPIOH_PIN11) | \
+ PIN_ODR_HIGH(GPIOH_PIN12) | \
+ PIN_ODR_HIGH(GPIOH_PIN13) | \
+ PIN_ODR_HIGH(GPIOH_PIN14) | \
+ PIN_ODR_HIGH(GPIOH_PIN15))
+#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_OSC_IN, 0U) | \
+ PIN_AFIO_AF(GPIOH_OSC_OUT, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN7, 0U))
+#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN15, 0U))
+
+/*
+ * GPIOI setup:
+ *
+ * PI0 - PIN0 (input pullup).
+ * PI1 - PIN1 (input pullup).
+ * PI2 - PIN2 (input pullup).
+ * PI3 - PIN3 (input pullup).
+ * PI4 - PIN4 (input pullup).
+ * PI5 - PIN5 (input pullup).
+ * PI6 - PIN6 (input pullup).
+ * PI7 - PIN7 (input pullup).
+ * PI8 - PIN8 (input pullup).
+ * PI9 - PIN9 (input pullup).
+ * PI10 - PIN10 (input pullup).
+ * PI11 - PIN11 (input pullup).
+ * PI12 - PIN12 (input pullup).
+ * PI13 - PIN13 (input pullup).
+ * PI14 - PIN14 (input pullup).
+ * PI15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOI_MODER (PIN_MODE_INPUT(GPIOI_PIN0) | \
+ PIN_MODE_INPUT(GPIOI_PIN1) | \
+ PIN_MODE_INPUT(GPIOI_PIN2) | \
+ PIN_MODE_INPUT(GPIOI_PIN3) | \
+ PIN_MODE_INPUT(GPIOI_PIN4) | \
+ PIN_MODE_INPUT(GPIOI_PIN5) | \
+ PIN_MODE_INPUT(GPIOI_PIN6) | \
+ PIN_MODE_INPUT(GPIOI_PIN7) | \
+ PIN_MODE_INPUT(GPIOI_PIN8) | \
+ PIN_MODE_INPUT(GPIOI_PIN9) | \
+ PIN_MODE_INPUT(GPIOI_PIN10) | \
+ PIN_MODE_INPUT(GPIOI_PIN11) | \
+ PIN_MODE_INPUT(GPIOI_PIN12) | \
+ PIN_MODE_INPUT(GPIOI_PIN13) | \
+ PIN_MODE_INPUT(GPIOI_PIN14) | \
+ PIN_MODE_INPUT(GPIOI_PIN15))
+#define VAL_GPIOI_OTYPER (PIN_OTYPE_PUSHPULL(GPIOI_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOI_PIN15))
+#define VAL_GPIOI_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOI_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOI_PIN15))
+#define VAL_GPIOI_PUPDR (PIN_PUPDR_PULLUP(GPIOI_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOI_PIN15))
+#define VAL_GPIOI_ODR (PIN_ODR_HIGH(GPIOI_PIN0) | \
+ PIN_ODR_HIGH(GPIOI_PIN1) | \
+ PIN_ODR_HIGH(GPIOI_PIN2) | \
+ PIN_ODR_HIGH(GPIOI_PIN3) | \
+ PIN_ODR_HIGH(GPIOI_PIN4) | \
+ PIN_ODR_HIGH(GPIOI_PIN5) | \
+ PIN_ODR_HIGH(GPIOI_PIN6) | \
+ PIN_ODR_HIGH(GPIOI_PIN7) | \
+ PIN_ODR_HIGH(GPIOI_PIN8) | \
+ PIN_ODR_HIGH(GPIOI_PIN9) | \
+ PIN_ODR_HIGH(GPIOI_PIN10) | \
+ PIN_ODR_HIGH(GPIOI_PIN11) | \
+ PIN_ODR_HIGH(GPIOI_PIN12) | \
+ PIN_ODR_HIGH(GPIOI_PIN13) | \
+ PIN_ODR_HIGH(GPIOI_PIN14) | \
+ PIN_ODR_HIGH(GPIOI_PIN15))
+#define VAL_GPIOI_AFRL (PIN_AFIO_AF(GPIOI_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN7, 0U))
+#define VAL_GPIOI_AFRH (PIN_AFIO_AF(GPIOI_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOI_PIN15, 0U))
+
+/*
+ * GPIOJ setup:
+ *
+ * PJ0 - PIN0 (input pullup).
+ * PJ1 - PIN1 (input pullup).
+ * PJ2 - PIN2 (input pullup).
+ * PJ3 - PIN3 (input pullup).
+ * PJ4 - PIN4 (input pullup).
+ * PJ5 - PIN5 (input pullup).
+ * PJ6 - PIN6 (input pullup).
+ * PJ7 - PIN7 (input pullup).
+ * PJ8 - PIN8 (input pullup).
+ * PJ9 - PIN9 (input pullup).
+ * PJ10 - PIN10 (input pullup).
+ * PJ11 - PIN11 (input pullup).
+ * PJ12 - PIN12 (input pullup).
+ * PJ13 - PIN13 (input pullup).
+ * PJ14 - PIN14 (input pullup).
+ * PJ15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOJ_MODER (PIN_MODE_INPUT(GPIOJ_PIN0) | \
+ PIN_MODE_INPUT(GPIOJ_PIN1) | \
+ PIN_MODE_INPUT(GPIOJ_PIN2) | \
+ PIN_MODE_INPUT(GPIOJ_PIN3) | \
+ PIN_MODE_INPUT(GPIOJ_PIN4) | \
+ PIN_MODE_INPUT(GPIOJ_PIN5) | \
+ PIN_MODE_INPUT(GPIOJ_PIN6) | \
+ PIN_MODE_INPUT(GPIOJ_PIN7) | \
+ PIN_MODE_INPUT(GPIOJ_PIN8) | \
+ PIN_MODE_INPUT(GPIOJ_PIN9) | \
+ PIN_MODE_INPUT(GPIOJ_PIN10) | \
+ PIN_MODE_INPUT(GPIOJ_PIN11) | \
+ PIN_MODE_INPUT(GPIOJ_PIN12) | \
+ PIN_MODE_INPUT(GPIOJ_PIN13) | \
+ PIN_MODE_INPUT(GPIOJ_PIN14) | \
+ PIN_MODE_INPUT(GPIOJ_PIN15))
+#define VAL_GPIOJ_OTYPER (PIN_OTYPE_PUSHPULL(GPIOJ_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOJ_PIN15))
+#define VAL_GPIOJ_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOJ_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOJ_PIN15))
+#define VAL_GPIOJ_PUPDR (PIN_PUPDR_PULLUP(GPIOJ_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOJ_PIN15))
+#define VAL_GPIOJ_ODR (PIN_ODR_HIGH(GPIOJ_PIN0) | \
+ PIN_ODR_HIGH(GPIOJ_PIN1) | \
+ PIN_ODR_HIGH(GPIOJ_PIN2) | \
+ PIN_ODR_HIGH(GPIOJ_PIN3) | \
+ PIN_ODR_HIGH(GPIOJ_PIN4) | \
+ PIN_ODR_HIGH(GPIOJ_PIN5) | \
+ PIN_ODR_HIGH(GPIOJ_PIN6) | \
+ PIN_ODR_HIGH(GPIOJ_PIN7) | \
+ PIN_ODR_HIGH(GPIOJ_PIN8) | \
+ PIN_ODR_HIGH(GPIOJ_PIN9) | \
+ PIN_ODR_HIGH(GPIOJ_PIN10) | \
+ PIN_ODR_HIGH(GPIOJ_PIN11) | \
+ PIN_ODR_HIGH(GPIOJ_PIN12) | \
+ PIN_ODR_HIGH(GPIOJ_PIN13) | \
+ PIN_ODR_HIGH(GPIOJ_PIN14) | \
+ PIN_ODR_HIGH(GPIOJ_PIN15))
+#define VAL_GPIOJ_AFRL (PIN_AFIO_AF(GPIOJ_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN7, 0U))
+#define VAL_GPIOJ_AFRH (PIN_AFIO_AF(GPIOJ_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOJ_PIN15, 0U))
+
+/*
+ * GPIOK setup:
+ *
+ * PK0 - PIN0 (input pullup).
+ * PK1 - PIN1 (input pullup).
+ * PK2 - PIN2 (input pullup).
+ * PK3 - PIN3 (input pullup).
+ * PK4 - PIN4 (input pullup).
+ * PK5 - PIN5 (input pullup).
+ * PK6 - PIN6 (input pullup).
+ * PK7 - PIN7 (input pullup).
+ * PK8 - PIN8 (input pullup).
+ * PK9 - PIN9 (input pullup).
+ * PK10 - PIN10 (input pullup).
+ * PK11 - PIN11 (input pullup).
+ * PK12 - PIN12 (input pullup).
+ * PK13 - PIN13 (input pullup).
+ * PK14 - PIN14 (input pullup).
+ * PK15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOK_MODER (PIN_MODE_INPUT(GPIOK_PIN0) | \
+ PIN_MODE_INPUT(GPIOK_PIN1) | \
+ PIN_MODE_INPUT(GPIOK_PIN2) | \
+ PIN_MODE_INPUT(GPIOK_PIN3) | \
+ PIN_MODE_INPUT(GPIOK_PIN4) | \
+ PIN_MODE_INPUT(GPIOK_PIN5) | \
+ PIN_MODE_INPUT(GPIOK_PIN6) | \
+ PIN_MODE_INPUT(GPIOK_PIN7) | \
+ PIN_MODE_INPUT(GPIOK_PIN8) | \
+ PIN_MODE_INPUT(GPIOK_PIN9) | \
+ PIN_MODE_INPUT(GPIOK_PIN10) | \
+ PIN_MODE_INPUT(GPIOK_PIN11) | \
+ PIN_MODE_INPUT(GPIOK_PIN12) | \
+ PIN_MODE_INPUT(GPIOK_PIN13) | \
+ PIN_MODE_INPUT(GPIOK_PIN14) | \
+ PIN_MODE_INPUT(GPIOK_PIN15))
+#define VAL_GPIOK_OTYPER (PIN_OTYPE_PUSHPULL(GPIOK_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOK_PIN15))
+#define VAL_GPIOK_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOK_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOK_PIN15))
+#define VAL_GPIOK_PUPDR (PIN_PUPDR_PULLUP(GPIOK_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOK_PIN15))
+#define VAL_GPIOK_ODR (PIN_ODR_HIGH(GPIOK_PIN0) | \
+ PIN_ODR_HIGH(GPIOK_PIN1) | \
+ PIN_ODR_HIGH(GPIOK_PIN2) | \
+ PIN_ODR_HIGH(GPIOK_PIN3) | \
+ PIN_ODR_HIGH(GPIOK_PIN4) | \
+ PIN_ODR_HIGH(GPIOK_PIN5) | \
+ PIN_ODR_HIGH(GPIOK_PIN6) | \
+ PIN_ODR_HIGH(GPIOK_PIN7) | \
+ PIN_ODR_HIGH(GPIOK_PIN8) | \
+ PIN_ODR_HIGH(GPIOK_PIN9) | \
+ PIN_ODR_HIGH(GPIOK_PIN10) | \
+ PIN_ODR_HIGH(GPIOK_PIN11) | \
+ PIN_ODR_HIGH(GPIOK_PIN12) | \
+ PIN_ODR_HIGH(GPIOK_PIN13) | \
+ PIN_ODR_HIGH(GPIOK_PIN14) | \
+ PIN_ODR_HIGH(GPIOK_PIN15))
+#define VAL_GPIOK_AFRL (PIN_AFIO_AF(GPIOK_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN7, 0U))
+#define VAL_GPIOK_AFRH (PIN_AFIO_AF(GPIOK_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOK_PIN15, 0U))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* BOARD_H */
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H755ZI/board.mk b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H755ZI/board.mk
new file mode 100644
index 0000000..f37066e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H755ZI/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO144_H755ZI/board.c
+
+# Required include directories
+BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO144_H755ZI
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC += $(BOARDINC)
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H755ZI/cfg/board.chcfg b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H755ZI/cfg/board.chcfg
new file mode 100644
index 0000000..6aa144f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H755ZI/cfg/board.chcfg
@@ -0,0 +1,1459 @@
+
+
+
+
+ resources/gencfg/processors/boards/stm32h7xx/templates
+ ..
+ 5.0.x
+
+ STMicroelectronics STM32 Nucleo144-H755ZI
+ ST_NUCLEO144_H755ZI
+
+
+
+ MII_LAN8742A_ID
+ RMII
+
+ STM32H755xx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H755ZI/cfg/board.fmpp b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H755ZI/cfg/board.fmpp
new file mode 100644
index 0000000..5003d98
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO144_H755ZI/cfg/board.fmpp
@@ -0,0 +1,15 @@
+sourceRoot: ../../../../../tools/ftl/processors/boards/stm32h7xx/templates
+outputRoot: ..
+dataRoot: .
+
+freemarkerLinks: {
+ lib: ../../../../../tools/ftl/libs
+}
+
+data : {
+ doc1:xml (
+ board.chcfg
+ {
+ }
+ )
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G071RB/board.c b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G071RB/board.c
new file mode 100644
index 0000000..54ad8c3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G071RB/board.c
@@ -0,0 +1,266 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#include "hal.h"
+#include "stm32_gpio.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of STM32 GPIO port setup.
+ */
+typedef struct {
+ uint32_t moder;
+ uint32_t otyper;
+ uint32_t ospeedr;
+ uint32_t pupdr;
+ uint32_t odr;
+ uint32_t afrl;
+ uint32_t afrh;
+} gpio_setup_t;
+
+/**
+ * @brief Type of STM32 GPIO initialization data.
+ */
+typedef struct {
+#if STM32_HAS_GPIOA || defined(__DOXYGEN__)
+ gpio_setup_t PAData;
+#endif
+#if STM32_HAS_GPIOB || defined(__DOXYGEN__)
+ gpio_setup_t PBData;
+#endif
+#if STM32_HAS_GPIOC || defined(__DOXYGEN__)
+ gpio_setup_t PCData;
+#endif
+#if STM32_HAS_GPIOD || defined(__DOXYGEN__)
+ gpio_setup_t PDData;
+#endif
+#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
+ gpio_setup_t PEData;
+#endif
+#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
+ gpio_setup_t PFData;
+#endif
+#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
+ gpio_setup_t PGData;
+#endif
+#if STM32_HAS_GPIOH || defined(__DOXYGEN__)
+ gpio_setup_t PHData;
+#endif
+#if STM32_HAS_GPIOI || defined(__DOXYGEN__)
+ gpio_setup_t PIData;
+#endif
+#if STM32_HAS_GPIOJ || defined(__DOXYGEN__)
+ gpio_setup_t PJData;
+#endif
+#if STM32_HAS_GPIOK || defined(__DOXYGEN__)
+ gpio_setup_t PKData;
+#endif
+} gpio_config_t;
+
+/**
+ * @brief STM32 GPIO static initialization data.
+ */
+static const gpio_config_t gpio_default_config = {
+#if STM32_HAS_GPIOA
+ {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
+ VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH},
+#endif
+#if STM32_HAS_GPIOB
+ {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR,
+ VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH},
+#endif
+#if STM32_HAS_GPIOC
+ {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR,
+ VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH},
+#endif
+#if STM32_HAS_GPIOD
+ {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR,
+ VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH},
+#endif
+#if STM32_HAS_GPIOE
+ {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR,
+ VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH},
+#endif
+#if STM32_HAS_GPIOF
+ {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR,
+ VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH},
+#endif
+#if STM32_HAS_GPIOG
+ {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR,
+ VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH},
+#endif
+#if STM32_HAS_GPIOH
+ {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR,
+ VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH},
+#endif
+#if STM32_HAS_GPIOI
+ {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
+ VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH},
+#endif
+#if STM32_HAS_GPIOJ
+ {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR,
+ VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH},
+#endif
+#if STM32_HAS_GPIOK
+ {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR,
+ VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH}
+#endif
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) {
+
+ gpiop->OTYPER = config->otyper;
+ gpiop->OSPEEDR = config->ospeedr;
+ gpiop->PUPDR = config->pupdr;
+ gpiop->ODR = config->odr;
+ gpiop->AFRL = config->afrl;
+ gpiop->AFRH = config->afrh;
+ gpiop->MODER = config->moder;
+}
+
+static void stm32_gpio_init(void) {
+
+ /* Enabling GPIO-related clocks, the mask comes from the
+ registry header file.*/
+ rccResetIOP(STM32_GPIO_EN_MASK);
+ rccEnableIOP(STM32_GPIO_EN_MASK, true);
+
+ /* Initializing all the defined GPIO ports.*/
+#if STM32_HAS_GPIOA
+ gpio_init(GPIOA, &gpio_default_config.PAData);
+#endif
+#if STM32_HAS_GPIOB
+ gpio_init(GPIOB, &gpio_default_config.PBData);
+#endif
+#if STM32_HAS_GPIOC
+ gpio_init(GPIOC, &gpio_default_config.PCData);
+#endif
+#if STM32_HAS_GPIOD
+ gpio_init(GPIOD, &gpio_default_config.PDData);
+#endif
+#if STM32_HAS_GPIOE
+ gpio_init(GPIOE, &gpio_default_config.PEData);
+#endif
+#if STM32_HAS_GPIOF
+ gpio_init(GPIOF, &gpio_default_config.PFData);
+#endif
+#if STM32_HAS_GPIOG
+ gpio_init(GPIOG, &gpio_default_config.PGData);
+#endif
+#if STM32_HAS_GPIOH
+ gpio_init(GPIOH, &gpio_default_config.PHData);
+#endif
+#if STM32_HAS_GPIOI
+ gpio_init(GPIOI, &gpio_default_config.PIData);
+#endif
+#if STM32_HAS_GPIOJ
+ gpio_init(GPIOJ, &gpio_default_config.PJData);
+#endif
+#if STM32_HAS_GPIOK
+ gpio_init(GPIOK, &gpio_default_config.PKData);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Early initialization code.
+ * @details GPIO ports and system clocks are initialized before everything
+ * else.
+ */
+void __early_init(void) {
+
+ stm32_gpio_init();
+ stm32_clock_init();
+}
+
+#if HAL_USE_SDC || defined(__DOXYGEN__)
+/**
+ * @brief SDC card detection.
+ */
+bool sdc_lld_is_card_inserted(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief SDC card write protection detection.
+ */
+bool sdc_lld_is_write_protected(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif /* HAL_USE_SDC */
+
+#if HAL_USE_MMC_SPI || defined(__DOXYGEN__)
+/**
+ * @brief MMC_SPI card detection.
+ */
+bool mmc_lld_is_card_inserted(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief MMC_SPI card write protection detection.
+ */
+bool mmc_lld_is_write_protected(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif
+
+/**
+ * @brief Board-specific initialization code.
+ * @note Add your board-specific code, if any.
+ */
+void boardInit(void) {
+
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G071RB/board.h b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G071RB/board.h
new file mode 100644
index 0000000..2ae23b2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G071RB/board.h
@@ -0,0 +1,796 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#ifndef BOARD_H
+#define BOARD_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*
+ * Setup for STMicroelectronics STM32 Nucleo64-G071RB board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_ST_NUCLEO64_G071RB
+#define BOARD_NAME "STMicroelectronics STM32 Nucleo64-G071RB"
+
+/*
+ * Board oscillators-related settings.
+ */
+#if !defined(STM32_LSECLK)
+#define STM32_LSECLK 32768U
+#endif
+
+#define STM32_LSEDRV (3U << 11U)
+
+#if !defined(STM32_HSECLK)
+#define STM32_HSECLK 8000000U
+#endif
+
+/*
+ * MCU type as defined in the ST header.
+ */
+#define STM32G071xx
+
+/*
+ * IO pins assignments.
+ */
+#define GPIOA_PIN0 0U
+#define GPIOA_PIN1 1U
+#define GPIOA_STLK_RX 2U
+#define GPIOA_STLK_TX 3U
+#define GPIOA_PIN4 4U
+#define GPIOA_LED_GREEN 5U
+#define GPIOA_PIN6 6U
+#define GPIOA_PIN7 7U
+#define GPIOA_PIN8 8U
+#define GPIOA_PIN9 9U
+#define GPIOA_PIN10 10U
+#define GPIOA_PIN11 11U
+#define GPIOA_PIN12 12U
+#define GPIOA_SWDIO 13U
+#define GPIOA_SWCLK 14U
+#define GPIOA_PIN15 15U
+
+#define GPIOB_PIN0 0U
+#define GPIOB_PIN1 1U
+#define GPIOB_PIN2 2U
+#define GPIOB_PIN3 3U
+#define GPIOB_PIN4 4U
+#define GPIOB_PIN5 5U
+#define GPIOB_PIN6 6U
+#define GPIOB_PIN7 7U
+#define GPIOB_PIN8 8U
+#define GPIOB_PIN9 9U
+#define GPIOB_PIN10 10U
+#define GPIOB_PIN11 11U
+#define GPIOB_PIN12 12U
+#define GPIOB_PIN13 13U
+#define GPIOB_PIN14 14U
+#define GPIOB_PIN15 15U
+
+#define GPIOC_PIN0 0U
+#define GPIOC_PIN1 1U
+#define GPIOC_PIN2 2U
+#define GPIOC_PIN3 3U
+#define GPIOC_PIN4 4U
+#define GPIOC_PIN5 5U
+#define GPIOC_PIN6 6U
+#define GPIOC_PIN7 7U
+#define GPIOC_PIN8 8U
+#define GPIOC_PIN9 9U
+#define GPIOC_PIN10 10U
+#define GPIOC_PIN11 11U
+#define GPIOC_PIN12 12U
+#define GPIOC_BUTTON 13U
+#define GPIOC_OSC32_IN 14U
+#define GPIOC_OSC32_OUT 15U
+
+#define GPIOD_PIN0 0U
+#define GPIOD_PIN1 1U
+#define GPIOD_PIN2 2U
+#define GPIOD_PIN3 3U
+#define GPIOD_PIN4 4U
+#define GPIOD_PIN5 5U
+#define GPIOD_PIN6 6U
+#define GPIOD_PIN7 7U
+#define GPIOD_PIN8 8U
+#define GPIOD_PIN9 9U
+#define GPIOD_PIN10 10U
+#define GPIOD_PIN11 11U
+#define GPIOD_PIN12 12U
+#define GPIOD_PIN13 13U
+#define GPIOD_PIN14 14U
+#define GPIOD_PIN15 15U
+
+#define GPIOF_OSC_IN 0U
+#define GPIOF_OSC_OUT 1U
+#define GPIOF_PIN2 2U
+#define GPIOF_PIN3 3U
+#define GPIOF_PIN4 4U
+#define GPIOF_PIN5 5U
+#define GPIOF_PIN6 6U
+#define GPIOF_PIN7 7U
+#define GPIOF_PIN8 8U
+#define GPIOF_PIN9 9U
+#define GPIOF_PIN10 10U
+#define GPIOF_PIN11 11U
+#define GPIOF_PIN12 12U
+#define GPIOF_PIN13 13U
+#define GPIOF_PIN14 14U
+#define GPIOF_PIN15 15U
+
+/*
+ * IO lines assignments.
+ */
+#define LINE_STLK_RX PAL_LINE(GPIOA, 2U)
+#define LINE_STLK_TX PAL_LINE(GPIOA, 3U)
+#define LINE_LED_GREEN PAL_LINE(GPIOA, 5U)
+#define LINE_SWDIO PAL_LINE(GPIOA, 13U)
+#define LINE_SWCLK PAL_LINE(GPIOA, 14U)
+#define LINE_BUTTON PAL_LINE(GPIOC, 13U)
+#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U)
+#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U)
+#define LINE_OSC_IN PAL_LINE(GPIOF, 0U)
+#define LINE_OSC_OUT PAL_LINE(GPIOF, 1U)
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*
+ * I/O ports initial setup, this configuration is established soon after reset
+ * in the initialization code.
+ * Please refer to the STM32 Reference Manual for details.
+ */
+#define PIN_MODE_INPUT(n) (0U << ((n) * 2U))
+#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U))
+#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U))
+#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U))
+#define PIN_ODR_LOW(n) (0U << (n))
+#define PIN_ODR_HIGH(n) (1U << (n))
+#define PIN_OTYPE_PUSHPULL(n) (0U << (n))
+#define PIN_OTYPE_OPENDRAIN(n) (1U << (n))
+#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U))
+#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U))
+#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U))
+#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U))
+#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U))
+#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U))
+#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U))
+#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U))
+
+/*
+ * GPIOA setup:
+ *
+ * PA0 - PIN0 (input pullup).
+ * PA1 - PIN1 (input pullup).
+ * PA2 - STLK_RX (alternate 1).
+ * PA3 - STLK_TX (alternate 1).
+ * PA4 - PIN4 (input pullup).
+ * PA5 - LED_GREEN (output pushpull maximum).
+ * PA6 - PIN6 (input pullup).
+ * PA7 - PIN7 (input pullup).
+ * PA8 - PIN8 (input pullup).
+ * PA9 - PIN9 (input pullup).
+ * PA10 - PIN10 (input pullup).
+ * PA11 - PIN11 (input pullup).
+ * PA12 - PIN12 (input pullup).
+ * PA13 - SWDIO (alternate 0).
+ * PA14 - SWCLK (alternate 0).
+ * PA15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_PIN0) | \
+ PIN_MODE_INPUT(GPIOA_PIN1) | \
+ PIN_MODE_ALTERNATE(GPIOA_STLK_RX) | \
+ PIN_MODE_ALTERNATE(GPIOA_STLK_TX) | \
+ PIN_MODE_INPUT(GPIOA_PIN4) | \
+ PIN_MODE_OUTPUT(GPIOA_LED_GREEN) | \
+ PIN_MODE_INPUT(GPIOA_PIN6) | \
+ PIN_MODE_INPUT(GPIOA_PIN7) | \
+ PIN_MODE_INPUT(GPIOA_PIN8) | \
+ PIN_MODE_INPUT(GPIOA_PIN9) | \
+ PIN_MODE_INPUT(GPIOA_PIN10) | \
+ PIN_MODE_INPUT(GPIOA_PIN11) | \
+ PIN_MODE_INPUT(GPIOA_PIN12) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \
+ PIN_MODE_INPUT(GPIOA_PIN15))
+#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_STLK_RX) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_STLK_TX) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_LED_GREEN) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN15))
+#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_HIGH(GPIOA_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN1) | \
+ PIN_OSPEED_MEDIUM(GPIOA_STLK_RX) | \
+ PIN_OSPEED_MEDIUM(GPIOA_STLK_TX) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOA_LED_GREEN) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOA_SWDIO) | \
+ PIN_OSPEED_HIGH(GPIOA_SWCLK) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN15))
+#define VAL_GPIOA_PUPDR (PIN_PUPDR_PULLUP(GPIOA_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOA_STLK_RX) | \
+ PIN_PUPDR_FLOATING(GPIOA_STLK_TX) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOA_LED_GREEN) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOA_SWDIO) | \
+ PIN_PUPDR_PULLDOWN(GPIOA_SWCLK) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN15))
+#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_PIN0) | \
+ PIN_ODR_HIGH(GPIOA_PIN1) | \
+ PIN_ODR_HIGH(GPIOA_STLK_RX) | \
+ PIN_ODR_HIGH(GPIOA_STLK_TX) | \
+ PIN_ODR_HIGH(GPIOA_PIN4) | \
+ PIN_ODR_LOW(GPIOA_LED_GREEN) | \
+ PIN_ODR_HIGH(GPIOA_PIN6) | \
+ PIN_ODR_HIGH(GPIOA_PIN7) | \
+ PIN_ODR_HIGH(GPIOA_PIN8) | \
+ PIN_ODR_HIGH(GPIOA_PIN9) | \
+ PIN_ODR_HIGH(GPIOA_PIN10) | \
+ PIN_ODR_HIGH(GPIOA_PIN11) | \
+ PIN_ODR_HIGH(GPIOA_PIN12) | \
+ PIN_ODR_HIGH(GPIOA_SWDIO) | \
+ PIN_ODR_HIGH(GPIOA_SWCLK) | \
+ PIN_ODR_HIGH(GPIOA_PIN15))
+#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOA_STLK_RX, 1U) | \
+ PIN_AFIO_AF(GPIOA_STLK_TX, 1U) | \
+ PIN_AFIO_AF(GPIOA_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOA_LED_GREEN, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN7, 0U))
+#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOA_SWDIO, 0U) | \
+ PIN_AFIO_AF(GPIOA_SWCLK, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN15, 0U))
+
+/*
+ * GPIOB setup:
+ *
+ * PB0 - PIN0 (input pullup).
+ * PB1 - PIN1 (input pullup).
+ * PB2 - PIN2 (input pullup).
+ * PB3 - PIN3 (input pullup).
+ * PB4 - PIN4 (input pullup).
+ * PB5 - PIN5 (input pullup).
+ * PB6 - PIN6 (input pullup).
+ * PB7 - PIN7 (input pullup).
+ * PB8 - PIN8 (input pullup).
+ * PB9 - PIN9 (input pullup).
+ * PB10 - PIN10 (input pullup).
+ * PB11 - PIN11 (input pullup).
+ * PB12 - PIN12 (input pullup).
+ * PB13 - PIN13 (input pullup).
+ * PB14 - PIN14 (input pullup).
+ * PB15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOB_MODER (PIN_MODE_INPUT(GPIOB_PIN0) | \
+ PIN_MODE_INPUT(GPIOB_PIN1) | \
+ PIN_MODE_INPUT(GPIOB_PIN2) | \
+ PIN_MODE_INPUT(GPIOB_PIN3) | \
+ PIN_MODE_INPUT(GPIOB_PIN4) | \
+ PIN_MODE_INPUT(GPIOB_PIN5) | \
+ PIN_MODE_INPUT(GPIOB_PIN6) | \
+ PIN_MODE_INPUT(GPIOB_PIN7) | \
+ PIN_MODE_INPUT(GPIOB_PIN8) | \
+ PIN_MODE_INPUT(GPIOB_PIN9) | \
+ PIN_MODE_INPUT(GPIOB_PIN10) | \
+ PIN_MODE_INPUT(GPIOB_PIN11) | \
+ PIN_MODE_INPUT(GPIOB_PIN12) | \
+ PIN_MODE_INPUT(GPIOB_PIN13) | \
+ PIN_MODE_INPUT(GPIOB_PIN14) | \
+ PIN_MODE_INPUT(GPIOB_PIN15))
+#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN15))
+#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN1) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN15))
+#define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(GPIOB_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN15))
+#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_PIN0) | \
+ PIN_ODR_HIGH(GPIOB_PIN1) | \
+ PIN_ODR_HIGH(GPIOB_PIN2) | \
+ PIN_ODR_HIGH(GPIOB_PIN3) | \
+ PIN_ODR_HIGH(GPIOB_PIN4) | \
+ PIN_ODR_HIGH(GPIOB_PIN5) | \
+ PIN_ODR_HIGH(GPIOB_PIN6) | \
+ PIN_ODR_HIGH(GPIOB_PIN7) | \
+ PIN_ODR_HIGH(GPIOB_PIN8) | \
+ PIN_ODR_HIGH(GPIOB_PIN9) | \
+ PIN_ODR_HIGH(GPIOB_PIN10) | \
+ PIN_ODR_HIGH(GPIOB_PIN11) | \
+ PIN_ODR_HIGH(GPIOB_PIN12) | \
+ PIN_ODR_HIGH(GPIOB_PIN13) | \
+ PIN_ODR_HIGH(GPIOB_PIN14) | \
+ PIN_ODR_HIGH(GPIOB_PIN15))
+#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN7, 0U))
+#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN15, 0U))
+
+/*
+ * GPIOC setup:
+ *
+ * PC0 - PIN0 (input pullup).
+ * PC1 - PIN1 (input pullup).
+ * PC2 - PIN2 (input pullup).
+ * PC3 - PIN3 (input pullup).
+ * PC4 - PIN4 (input pullup).
+ * PC5 - PIN5 (input pullup).
+ * PC6 - PIN6 (input pullup).
+ * PC7 - PIN7 (input pullup).
+ * PC8 - PIN8 (input pullup).
+ * PC9 - PIN9 (input pullup).
+ * PC10 - PIN10 (input pullup).
+ * PC11 - PIN11 (input pullup).
+ * PC12 - PIN12 (input pullup).
+ * PC13 - BUTTON (input floating).
+ * PC14 - OSC32_IN (input floating).
+ * PC15 - OSC32_OUT (input floating).
+ */
+#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_PIN0) | \
+ PIN_MODE_INPUT(GPIOC_PIN1) | \
+ PIN_MODE_INPUT(GPIOC_PIN2) | \
+ PIN_MODE_INPUT(GPIOC_PIN3) | \
+ PIN_MODE_INPUT(GPIOC_PIN4) | \
+ PIN_MODE_INPUT(GPIOC_PIN5) | \
+ PIN_MODE_INPUT(GPIOC_PIN6) | \
+ PIN_MODE_INPUT(GPIOC_PIN7) | \
+ PIN_MODE_INPUT(GPIOC_PIN8) | \
+ PIN_MODE_INPUT(GPIOC_PIN9) | \
+ PIN_MODE_INPUT(GPIOC_PIN10) | \
+ PIN_MODE_INPUT(GPIOC_PIN11) | \
+ PIN_MODE_INPUT(GPIOC_PIN12) | \
+ PIN_MODE_INPUT(GPIOC_BUTTON) | \
+ PIN_MODE_INPUT(GPIOC_OSC32_IN) | \
+ PIN_MODE_INPUT(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_BUTTON) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN1) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOC_BUTTON) | \
+ PIN_OSPEED_HIGH(GPIOC_OSC32_IN) | \
+ PIN_OSPEED_HIGH(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOC_BUTTON) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_PIN0) | \
+ PIN_ODR_HIGH(GPIOC_PIN1) | \
+ PIN_ODR_HIGH(GPIOC_PIN2) | \
+ PIN_ODR_HIGH(GPIOC_PIN3) | \
+ PIN_ODR_HIGH(GPIOC_PIN4) | \
+ PIN_ODR_HIGH(GPIOC_PIN5) | \
+ PIN_ODR_HIGH(GPIOC_PIN6) | \
+ PIN_ODR_HIGH(GPIOC_PIN7) | \
+ PIN_ODR_HIGH(GPIOC_PIN8) | \
+ PIN_ODR_HIGH(GPIOC_PIN9) | \
+ PIN_ODR_HIGH(GPIOC_PIN10) | \
+ PIN_ODR_HIGH(GPIOC_PIN11) | \
+ PIN_ODR_HIGH(GPIOC_PIN12) | \
+ PIN_ODR_HIGH(GPIOC_BUTTON) | \
+ PIN_ODR_HIGH(GPIOC_OSC32_IN) | \
+ PIN_ODR_HIGH(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN7, 0U))
+#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOC_BUTTON, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U))
+
+/*
+ * GPIOD setup:
+ *
+ * PD0 - PIN0 (input pullup).
+ * PD1 - PIN1 (input pullup).
+ * PD2 - PIN2 (input pullup).
+ * PD3 - PIN3 (input pullup).
+ * PD4 - PIN4 (input pullup).
+ * PD5 - PIN5 (input pullup).
+ * PD6 - PIN6 (input pullup).
+ * PD7 - PIN7 (input pullup).
+ * PD8 - PIN8 (input pullup).
+ * PD9 - PIN9 (input pullup).
+ * PD10 - PIN10 (input pullup).
+ * PD11 - PIN11 (input pullup).
+ * PD12 - PIN12 (input pullup).
+ * PD13 - PIN13 (input pullup).
+ * PD14 - PIN14 (input pullup).
+ * PD15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | \
+ PIN_MODE_INPUT(GPIOD_PIN1) | \
+ PIN_MODE_INPUT(GPIOD_PIN2) | \
+ PIN_MODE_INPUT(GPIOD_PIN3) | \
+ PIN_MODE_INPUT(GPIOD_PIN4) | \
+ PIN_MODE_INPUT(GPIOD_PIN5) | \
+ PIN_MODE_INPUT(GPIOD_PIN6) | \
+ PIN_MODE_INPUT(GPIOD_PIN7) | \
+ PIN_MODE_INPUT(GPIOD_PIN8) | \
+ PIN_MODE_INPUT(GPIOD_PIN9) | \
+ PIN_MODE_INPUT(GPIOD_PIN10) | \
+ PIN_MODE_INPUT(GPIOD_PIN11) | \
+ PIN_MODE_INPUT(GPIOD_PIN12) | \
+ PIN_MODE_INPUT(GPIOD_PIN13) | \
+ PIN_MODE_INPUT(GPIOD_PIN14) | \
+ PIN_MODE_INPUT(GPIOD_PIN15))
+#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN15))
+#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_HIGH(GPIOD_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN1) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN15))
+#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN15))
+#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \
+ PIN_ODR_HIGH(GPIOD_PIN1) | \
+ PIN_ODR_HIGH(GPIOD_PIN2) | \
+ PIN_ODR_HIGH(GPIOD_PIN3) | \
+ PIN_ODR_HIGH(GPIOD_PIN4) | \
+ PIN_ODR_HIGH(GPIOD_PIN5) | \
+ PIN_ODR_HIGH(GPIOD_PIN6) | \
+ PIN_ODR_HIGH(GPIOD_PIN7) | \
+ PIN_ODR_HIGH(GPIOD_PIN8) | \
+ PIN_ODR_HIGH(GPIOD_PIN9) | \
+ PIN_ODR_HIGH(GPIOD_PIN10) | \
+ PIN_ODR_HIGH(GPIOD_PIN11) | \
+ PIN_ODR_HIGH(GPIOD_PIN12) | \
+ PIN_ODR_HIGH(GPIOD_PIN13) | \
+ PIN_ODR_HIGH(GPIOD_PIN14) | \
+ PIN_ODR_HIGH(GPIOD_PIN15))
+#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN7, 0U))
+#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN15, 0U))
+
+/*
+ * GPIOF setup:
+ *
+ * PF0 - OSC_IN (input floating).
+ * PF1 - OSC_OUT (input floating).
+ * PF2 - PIN2 (input pullup).
+ * PF3 - PIN3 (input pullup).
+ * PF4 - PIN4 (input pullup).
+ * PF5 - PIN5 (input pullup).
+ * PF6 - PIN6 (input pullup).
+ * PF7 - PIN7 (input pullup).
+ * PF8 - PIN8 (input pullup).
+ * PF9 - PIN9 (input pullup).
+ * PF10 - PIN10 (input pullup).
+ * PF11 - PIN11 (input pullup).
+ * PF12 - PIN12 (input pullup).
+ * PF13 - PIN13 (input pullup).
+ * PF14 - PIN14 (input pullup).
+ * PF15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_OSC_IN) | \
+ PIN_MODE_INPUT(GPIOF_OSC_OUT) | \
+ PIN_MODE_INPUT(GPIOF_PIN2) | \
+ PIN_MODE_INPUT(GPIOF_PIN3) | \
+ PIN_MODE_INPUT(GPIOF_PIN4) | \
+ PIN_MODE_INPUT(GPIOF_PIN5) | \
+ PIN_MODE_INPUT(GPIOF_PIN6) | \
+ PIN_MODE_INPUT(GPIOF_PIN7) | \
+ PIN_MODE_INPUT(GPIOF_PIN8) | \
+ PIN_MODE_INPUT(GPIOF_PIN9) | \
+ PIN_MODE_INPUT(GPIOF_PIN10) | \
+ PIN_MODE_INPUT(GPIOF_PIN11) | \
+ PIN_MODE_INPUT(GPIOF_PIN12) | \
+ PIN_MODE_INPUT(GPIOF_PIN13) | \
+ PIN_MODE_INPUT(GPIOF_PIN14) | \
+ PIN_MODE_INPUT(GPIOF_PIN15))
+#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_OSC_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_OSC_OUT) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN15))
+#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_HIGH(GPIOF_OSC_IN) | \
+ PIN_OSPEED_HIGH(GPIOF_OSC_OUT) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN15))
+#define VAL_GPIOF_PUPDR (PIN_PUPDR_FLOATING(GPIOF_OSC_IN) | \
+ PIN_PUPDR_FLOATING(GPIOF_OSC_OUT) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN15))
+#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_OSC_IN) | \
+ PIN_ODR_HIGH(GPIOF_OSC_OUT) | \
+ PIN_ODR_HIGH(GPIOF_PIN2) | \
+ PIN_ODR_HIGH(GPIOF_PIN3) | \
+ PIN_ODR_HIGH(GPIOF_PIN4) | \
+ PIN_ODR_HIGH(GPIOF_PIN5) | \
+ PIN_ODR_HIGH(GPIOF_PIN6) | \
+ PIN_ODR_HIGH(GPIOF_PIN7) | \
+ PIN_ODR_HIGH(GPIOF_PIN8) | \
+ PIN_ODR_HIGH(GPIOF_PIN9) | \
+ PIN_ODR_HIGH(GPIOF_PIN10) | \
+ PIN_ODR_HIGH(GPIOF_PIN11) | \
+ PIN_ODR_HIGH(GPIOF_PIN12) | \
+ PIN_ODR_HIGH(GPIOF_PIN13) | \
+ PIN_ODR_HIGH(GPIOF_PIN14) | \
+ PIN_ODR_HIGH(GPIOF_PIN15))
+#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_OSC_IN, 0U) | \
+ PIN_AFIO_AF(GPIOF_OSC_OUT, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN7, 0U))
+#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN15, 0U))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* BOARD_H */
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G071RB/board.mk b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G071RB/board.mk
new file mode 100644
index 0000000..a6f1329
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G071RB/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_G071RB/board.c
+
+# Required include directories
+BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_G071RB
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC += $(BOARDINC)
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G071RB/cfg/board.chcfg b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G071RB/cfg/board.chcfg
new file mode 100644
index 0000000..817dfc6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G071RB/cfg/board.chcfg
@@ -0,0 +1,669 @@
+
+
+
+
+ resources/gencfg/processors/boards/stm32g0xx/templates
+ ..
+ 5.0.x
+
+ STMicroelectronics STM32 Nucleo64-G071RB
+ ST_NUCLEO64_G071RB
+
+ STM32G071xx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G071RB/cfg/board.fmpp b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G071RB/cfg/board.fmpp
new file mode 100644
index 0000000..b24df35
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G071RB/cfg/board.fmpp
@@ -0,0 +1,15 @@
+sourceRoot: ../../../../../tools/ftl/processors/boards/stm32g0xx/templates
+outputRoot: ..
+dataRoot: .
+
+freemarkerLinks: {
+ lib: ../../../../../tools/ftl/libs
+}
+
+data : {
+ doc1:xml (
+ board.chcfg
+ {
+ }
+ )
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G431RB/board.c b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G431RB/board.c
new file mode 100644
index 0000000..568c450
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G431RB/board.c
@@ -0,0 +1,266 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#include "hal.h"
+#include "stm32_gpio.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of STM32 GPIO port setup.
+ */
+typedef struct {
+ uint32_t moder;
+ uint32_t otyper;
+ uint32_t ospeedr;
+ uint32_t pupdr;
+ uint32_t odr;
+ uint32_t afrl;
+ uint32_t afrh;
+} gpio_setup_t;
+
+/**
+ * @brief Type of STM32 GPIO initialization data.
+ */
+typedef struct {
+#if STM32_HAS_GPIOA || defined(__DOXYGEN__)
+ gpio_setup_t PAData;
+#endif
+#if STM32_HAS_GPIOB || defined(__DOXYGEN__)
+ gpio_setup_t PBData;
+#endif
+#if STM32_HAS_GPIOC || defined(__DOXYGEN__)
+ gpio_setup_t PCData;
+#endif
+#if STM32_HAS_GPIOD || defined(__DOXYGEN__)
+ gpio_setup_t PDData;
+#endif
+#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
+ gpio_setup_t PEData;
+#endif
+#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
+ gpio_setup_t PFData;
+#endif
+#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
+ gpio_setup_t PGData;
+#endif
+#if STM32_HAS_GPIOH || defined(__DOXYGEN__)
+ gpio_setup_t PHData;
+#endif
+#if STM32_HAS_GPIOI || defined(__DOXYGEN__)
+ gpio_setup_t PIData;
+#endif
+#if STM32_HAS_GPIOJ || defined(__DOXYGEN__)
+ gpio_setup_t PJData;
+#endif
+#if STM32_HAS_GPIOK || defined(__DOXYGEN__)
+ gpio_setup_t PKData;
+#endif
+} gpio_config_t;
+
+/**
+ * @brief STM32 GPIO static initialization data.
+ */
+static const gpio_config_t gpio_default_config = {
+#if STM32_HAS_GPIOA
+ {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
+ VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH},
+#endif
+#if STM32_HAS_GPIOB
+ {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR,
+ VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH},
+#endif
+#if STM32_HAS_GPIOC
+ {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR,
+ VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH},
+#endif
+#if STM32_HAS_GPIOD
+ {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR,
+ VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH},
+#endif
+#if STM32_HAS_GPIOE
+ {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR,
+ VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH},
+#endif
+#if STM32_HAS_GPIOF
+ {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR,
+ VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH},
+#endif
+#if STM32_HAS_GPIOG
+ {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR,
+ VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH},
+#endif
+#if STM32_HAS_GPIOH
+ {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR,
+ VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH},
+#endif
+#if STM32_HAS_GPIOI
+ {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
+ VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH},
+#endif
+#if STM32_HAS_GPIOJ
+ {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR,
+ VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH},
+#endif
+#if STM32_HAS_GPIOK
+ {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR,
+ VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH}
+#endif
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) {
+
+ gpiop->OTYPER = config->otyper;
+ gpiop->OSPEEDR = config->ospeedr;
+ gpiop->PUPDR = config->pupdr;
+ gpiop->ODR = config->odr;
+ gpiop->AFRL = config->afrl;
+ gpiop->AFRH = config->afrh;
+ gpiop->MODER = config->moder;
+}
+
+static void stm32_gpio_init(void) {
+
+ /* Enabling GPIO-related clocks, the mask comes from the
+ registry header file.*/
+ rccResetAHB2(STM32_GPIO_EN_MASK);
+ rccEnableAHB2(STM32_GPIO_EN_MASK, true);
+
+ /* Initializing all the defined GPIO ports.*/
+#if STM32_HAS_GPIOA
+ gpio_init(GPIOA, &gpio_default_config.PAData);
+#endif
+#if STM32_HAS_GPIOB
+ gpio_init(GPIOB, &gpio_default_config.PBData);
+#endif
+#if STM32_HAS_GPIOC
+ gpio_init(GPIOC, &gpio_default_config.PCData);
+#endif
+#if STM32_HAS_GPIOD
+ gpio_init(GPIOD, &gpio_default_config.PDData);
+#endif
+#if STM32_HAS_GPIOE
+ gpio_init(GPIOE, &gpio_default_config.PEData);
+#endif
+#if STM32_HAS_GPIOF
+ gpio_init(GPIOF, &gpio_default_config.PFData);
+#endif
+#if STM32_HAS_GPIOG
+ gpio_init(GPIOG, &gpio_default_config.PGData);
+#endif
+#if STM32_HAS_GPIOH
+ gpio_init(GPIOH, &gpio_default_config.PHData);
+#endif
+#if STM32_HAS_GPIOI
+ gpio_init(GPIOI, &gpio_default_config.PIData);
+#endif
+#if STM32_HAS_GPIOJ
+ gpio_init(GPIOJ, &gpio_default_config.PJData);
+#endif
+#if STM32_HAS_GPIOK
+ gpio_init(GPIOK, &gpio_default_config.PKData);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Early initialization code.
+ * @details GPIO ports and system clocks are initialized before everything
+ * else.
+ */
+void __early_init(void) {
+
+ stm32_gpio_init();
+ stm32_clock_init();
+}
+
+#if HAL_USE_SDC || defined(__DOXYGEN__)
+/**
+ * @brief SDC card detection.
+ */
+bool sdc_lld_is_card_inserted(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief SDC card write protection detection.
+ */
+bool sdc_lld_is_write_protected(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif /* HAL_USE_SDC */
+
+#if HAL_USE_MMC_SPI || defined(__DOXYGEN__)
+/**
+ * @brief MMC_SPI card detection.
+ */
+bool mmc_lld_is_card_inserted(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief MMC_SPI card write protection detection.
+ */
+bool mmc_lld_is_write_protected(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif
+
+/**
+ * @brief Board-specific initialization code.
+ * @note You can add your board-specific code here.
+ */
+void boardInit(void) {
+
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G431RB/board.h b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G431RB/board.h
new file mode 100644
index 0000000..09924a6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G431RB/board.h
@@ -0,0 +1,1078 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#ifndef BOARD_H
+#define BOARD_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*
+ * Setup for STMicroelectronics STM32 Nucleo64-G431RB board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_ST_NUCLEO64_G431RB
+#define BOARD_NAME "STMicroelectronics STM32 Nucleo64-G431RB"
+
+/*
+ * Board oscillators-related settings.
+ */
+#if !defined(STM32_LSECLK)
+#define STM32_LSECLK 32768U
+#endif
+
+#define STM32_LSEDRV (3U << 3U)
+
+#if !defined(STM32_HSECLK)
+#define STM32_HSECLK 24000000U
+#endif
+
+/*
+ * Board voltages.
+ * Required for performance limits calculation.
+ */
+#define STM32_VDD 300U
+
+/*
+ * MCU type as defined in the ST header.
+ */
+#define STM32G431xx
+
+/*
+ * IO pins assignments.
+ */
+#define GPIOA_PIN0 0U
+#define GPIOA_PIN1 1U
+#define GPIOA_STLINK_TX 2U
+#define GPIOA_STLINK_RX 3U
+#define GPIOA_PIN4 4U
+#define GPIOA_LED 5U
+#define GPIOA_LED_GREEN 5U
+#define GPIOA_PIN6 6U
+#define GPIOA_PIN7 7U
+#define GPIOA_PIN8 8U
+#define GPIOA_PIN9 9U
+#define GPIOA_PIN10 10U
+#define GPIOA_PIN11 11U
+#define GPIOA_PIN12 12U
+#define GPIOA_SWDIO 13U
+#define GPIOA_SWCLK 14U
+#define GPIOA_PIN15 15U
+
+#define GPIOB_PIN0 0U
+#define GPIOB_PIN1 1U
+#define GPIOB_BOOT1 2U
+#define GPIOB_TRACESWO 3U
+#define GPIOB_PIN4 4U
+#define GPIOB_PIN5 5U
+#define GPIOB_PIN6 6U
+#define GPIOB_PIN7 7U
+#define GPIOB_PIN8 8U
+#define GPIOB_PIN9 9U
+#define GPIOB_PIN10 10U
+#define GPIOB_PIN11 11U
+#define GPIOB_PIN12 12U
+#define GPIOB_PIN13 13U
+#define GPIOB_PIN14 14U
+#define GPIOB_PIN15 15U
+
+#define GPIOC_PIN0 0U
+#define GPIOC_PIN1 1U
+#define GPIOC_PIN2 2U
+#define GPIOC_PIN3 3U
+#define GPIOC_PIN4 4U
+#define GPIOC_PIN5 5U
+#define GPIOC_PIN6 6U
+#define GPIOC_PIN7 7U
+#define GPIOC_PIN8 8U
+#define GPIOC_PIN9 9U
+#define GPIOC_PIN10 10U
+#define GPIOC_PIN11 11U
+#define GPIOC_PIN12 12U
+#define GPIOC_BUTTON 13U
+#define GPIOC_USER_BUTTON 13U
+#define GPIOC_OSC32_IN 14U
+#define GPIOC_OSC32_OUT 15U
+
+#define GPIOD_PIN0 0U
+#define GPIOD_PIN1 1U
+#define GPIOD_PIN2 2U
+#define GPIOD_PIN3 3U
+#define GPIOD_PIN4 4U
+#define GPIOD_PIN5 5U
+#define GPIOD_PIN6 6U
+#define GPIOD_PIN7 7U
+#define GPIOD_PIN8 8U
+#define GPIOD_PIN9 9U
+#define GPIOD_PIN10 10U
+#define GPIOD_PIN11 11U
+#define GPIOD_PIN12 12U
+#define GPIOD_PIN13 13U
+#define GPIOD_PIN14 14U
+#define GPIOD_PIN15 15U
+
+#define GPIOE_PIN0 0U
+#define GPIOE_PIN1 1U
+#define GPIOE_PIN2 2U
+#define GPIOE_PIN3 3U
+#define GPIOE_PIN4 4U
+#define GPIOE_PIN5 5U
+#define GPIOE_PIN6 6U
+#define GPIOE_PIN7 7U
+#define GPIOE_PIN8 8U
+#define GPIOE_PIN9 9U
+#define GPIOE_PIN10 10U
+#define GPIOE_PIN11 11U
+#define GPIOE_PIN12 12U
+#define GPIOE_PIN13 13U
+#define GPIOE_PIN14 14U
+#define GPIOE_PIN15 15U
+
+#define GPIOF_OSC_IN 0U
+#define GPIOF_OSC_OUT 1U
+#define GPIOF_PIN2 2U
+#define GPIOF_PIN3 3U
+#define GPIOF_PIN4 4U
+#define GPIOF_PIN5 5U
+#define GPIOF_PIN6 6U
+#define GPIOF_PIN7 7U
+#define GPIOF_PIN8 8U
+#define GPIOF_PIN9 9U
+#define GPIOF_PIN10 10U
+#define GPIOF_PIN11 11U
+#define GPIOF_PIN12 12U
+#define GPIOF_PIN13 13U
+#define GPIOF_PIN14 14U
+#define GPIOF_PIN15 15U
+
+#define GPIOG_PIN0 0U
+#define GPIOG_PIN1 1U
+#define GPIOG_PIN2 2U
+#define GPIOG_PIN3 3U
+#define GPIOG_PIN4 4U
+#define GPIOG_PIN5 5U
+#define GPIOG_PIN6 6U
+#define GPIOG_PIN7 7U
+#define GPIOG_PIN8 8U
+#define GPIOG_PIN9 9U
+#define GPIOG_PIN10 10U
+#define GPIOG_PIN11 11U
+#define GPIOG_PIN12 12U
+#define GPIOG_PIN13 13U
+#define GPIOG_PIN14 14U
+#define GPIOG_PIN15 15U
+
+/*
+ * IO lines assignments.
+ */
+#define LINE_STLINK_TX PAL_LINE(GPIOA, 2U)
+#define LINE_STLINK_RX PAL_LINE(GPIOA, 3U)
+#define LINE_LED PAL_LINE(GPIOA, 5U)
+#define LINE_LED_GREEN PAL_LINE(GPIOA, 5U)
+#define LINE_SWDIO PAL_LINE(GPIOA, 13U)
+#define LINE_SWCLK PAL_LINE(GPIOA, 14U)
+#define LINE_BOOT1 PAL_LINE(GPIOB, 2U)
+#define LINE_TRACESWO PAL_LINE(GPIOB, 3U)
+#define LINE_BUTTON PAL_LINE(GPIOC, 13U)
+#define LINE_USER_BUTTON PAL_LINE(GPIOC, 13U)
+#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U)
+#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U)
+#define LINE_OSC_IN PAL_LINE(GPIOF, 0U)
+#define LINE_OSC_OUT PAL_LINE(GPIOF, 1U)
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*
+ * I/O ports initial setup, this configuration is established soon after reset
+ * in the initialization code.
+ * Please refer to the STM32 Reference Manual for details.
+ */
+#define PIN_MODE_INPUT(n) (0U << ((n) * 2U))
+#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U))
+#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U))
+#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U))
+#define PIN_ODR_LOW(n) (0U << (n))
+#define PIN_ODR_HIGH(n) (1U << (n))
+#define PIN_OTYPE_PUSHPULL(n) (0U << (n))
+#define PIN_OTYPE_OPENDRAIN(n) (1U << (n))
+#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U))
+#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U))
+#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U))
+#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U))
+#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U))
+#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U))
+#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U))
+#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U))
+#define PIN_LOCKR_DISABLED(n) (0U << (n))
+#define PIN_LOCKR_ENABLED(n) (1U << (n))
+
+/*
+ * GPIOA setup:
+ *
+ * PA0 - PIN0 (analog).
+ * PA1 - PIN1 (analog).
+ * PA2 - STLINK_TX (alternate 12).
+ * PA3 - STLINK_RX (alternate 12).
+ * PA4 - PIN4 (analog).
+ * PA5 - LED LED_GREEN (output pushpull maximum).
+ * PA6 - PIN6 (analog).
+ * PA7 - PIN7 (analog).
+ * PA8 - PIN8 (analog).
+ * PA9 - PIN9 (analog).
+ * PA10 - PIN10 (analog).
+ * PA11 - PIN11 (analog).
+ * PA12 - PIN12 (analog).
+ * PA13 - SWDIO (alternate 0).
+ * PA14 - SWCLK (alternate 0).
+ * PA15 - PIN15 (analog).
+ */
+#define VAL_GPIOA_MODER (PIN_MODE_ANALOG(GPIOA_PIN0) | \
+ PIN_MODE_ANALOG(GPIOA_PIN1) | \
+ PIN_MODE_ALTERNATE(GPIOA_STLINK_TX) | \
+ PIN_MODE_ALTERNATE(GPIOA_STLINK_RX) | \
+ PIN_MODE_ANALOG(GPIOA_PIN4) | \
+ PIN_MODE_OUTPUT(GPIOA_LED) | \
+ PIN_MODE_ANALOG(GPIOA_PIN6) | \
+ PIN_MODE_ANALOG(GPIOA_PIN7) | \
+ PIN_MODE_ANALOG(GPIOA_PIN8) | \
+ PIN_MODE_ANALOG(GPIOA_PIN9) | \
+ PIN_MODE_ANALOG(GPIOA_PIN10) | \
+ PIN_MODE_ANALOG(GPIOA_PIN11) | \
+ PIN_MODE_ANALOG(GPIOA_PIN12) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \
+ PIN_MODE_ANALOG(GPIOA_PIN15))
+#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_STLINK_TX) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_STLINK_RX) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_LED) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN15))
+#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOA_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOA_STLINK_TX) | \
+ PIN_OSPEED_VERYLOW(GPIOA_STLINK_RX) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOA_LED) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOA_SWDIO) | \
+ PIN_OSPEED_HIGH(GPIOA_SWCLK) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN15))
+#define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOA_STLINK_TX) | \
+ PIN_PUPDR_FLOATING(GPIOA_STLINK_RX) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOA_LED) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOA_SWDIO) | \
+ PIN_PUPDR_PULLDOWN(GPIOA_SWCLK) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN15))
+#define VAL_GPIOA_ODR (PIN_ODR_LOW(GPIOA_PIN0) | \
+ PIN_ODR_LOW(GPIOA_PIN1) | \
+ PIN_ODR_LOW(GPIOA_STLINK_TX) | \
+ PIN_ODR_LOW(GPIOA_STLINK_RX) | \
+ PIN_ODR_LOW(GPIOA_PIN4) | \
+ PIN_ODR_LOW(GPIOA_LED) | \
+ PIN_ODR_LOW(GPIOA_PIN6) | \
+ PIN_ODR_LOW(GPIOA_PIN7) | \
+ PIN_ODR_LOW(GPIOA_PIN8) | \
+ PIN_ODR_LOW(GPIOA_PIN9) | \
+ PIN_ODR_LOW(GPIOA_PIN10) | \
+ PIN_ODR_LOW(GPIOA_PIN11) | \
+ PIN_ODR_LOW(GPIOA_PIN12) | \
+ PIN_ODR_LOW(GPIOA_SWDIO) | \
+ PIN_ODR_LOW(GPIOA_SWCLK) | \
+ PIN_ODR_LOW(GPIOA_PIN15))
+#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOA_STLINK_TX, 12U) | \
+ PIN_AFIO_AF(GPIOA_STLINK_RX, 12U) | \
+ PIN_AFIO_AF(GPIOA_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOA_LED, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN7, 0U))
+#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOA_SWDIO, 0U) | \
+ PIN_AFIO_AF(GPIOA_SWCLK, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN15, 0U))
+
+/*
+ * GPIOB setup:
+ *
+ * PB0 - PIN0 (analog).
+ * PB1 - PIN1 (analog).
+ * PB2 - BOOT1 (analog).
+ * PB3 - TRACESWO (alternate 0).
+ * PB4 - PIN4 (analog).
+ * PB5 - PIN5 (analog).
+ * PB6 - PIN6 (analog).
+ * PB7 - PIN7 (analog).
+ * PB8 - PIN8 (analog).
+ * PB9 - PIN9 (analog).
+ * PB10 - PIN10 (analog).
+ * PB11 - PIN11 (analog).
+ * PB12 - PIN12 (analog).
+ * PB13 - PIN13 (analog).
+ * PB14 - PIN14 (analog).
+ * PB15 - PIN15 (analog).
+ */
+#define VAL_GPIOB_MODER (PIN_MODE_ANALOG(GPIOB_PIN0) | \
+ PIN_MODE_ANALOG(GPIOB_PIN1) | \
+ PIN_MODE_ANALOG(GPIOB_BOOT1) | \
+ PIN_MODE_ALTERNATE(GPIOB_TRACESWO) | \
+ PIN_MODE_ANALOG(GPIOB_PIN4) | \
+ PIN_MODE_ANALOG(GPIOB_PIN5) | \
+ PIN_MODE_ANALOG(GPIOB_PIN6) | \
+ PIN_MODE_ANALOG(GPIOB_PIN7) | \
+ PIN_MODE_ANALOG(GPIOB_PIN8) | \
+ PIN_MODE_ANALOG(GPIOB_PIN9) | \
+ PIN_MODE_ANALOG(GPIOB_PIN10) | \
+ PIN_MODE_ANALOG(GPIOB_PIN11) | \
+ PIN_MODE_ANALOG(GPIOB_PIN12) | \
+ PIN_MODE_ANALOG(GPIOB_PIN13) | \
+ PIN_MODE_ANALOG(GPIOB_PIN14) | \
+ PIN_MODE_ANALOG(GPIOB_PIN15))
+#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_BOOT1) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_TRACESWO) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN15))
+#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOB_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOB_BOOT1) | \
+ PIN_OSPEED_HIGH(GPIOB_TRACESWO) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN15))
+#define VAL_GPIOB_PUPDR (PIN_PUPDR_FLOATING(GPIOB_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOB_BOOT1) | \
+ PIN_PUPDR_FLOATING(GPIOB_TRACESWO) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN15))
+#define VAL_GPIOB_ODR (PIN_ODR_LOW(GPIOB_PIN0) | \
+ PIN_ODR_LOW(GPIOB_PIN1) | \
+ PIN_ODR_LOW(GPIOB_BOOT1) | \
+ PIN_ODR_LOW(GPIOB_TRACESWO) | \
+ PIN_ODR_LOW(GPIOB_PIN4) | \
+ PIN_ODR_LOW(GPIOB_PIN5) | \
+ PIN_ODR_LOW(GPIOB_PIN6) | \
+ PIN_ODR_LOW(GPIOB_PIN7) | \
+ PIN_ODR_LOW(GPIOB_PIN8) | \
+ PIN_ODR_LOW(GPIOB_PIN9) | \
+ PIN_ODR_LOW(GPIOB_PIN10) | \
+ PIN_ODR_LOW(GPIOB_PIN11) | \
+ PIN_ODR_LOW(GPIOB_PIN12) | \
+ PIN_ODR_LOW(GPIOB_PIN13) | \
+ PIN_ODR_LOW(GPIOB_PIN14) | \
+ PIN_ODR_LOW(GPIOB_PIN15))
+#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOB_BOOT1, 0U) | \
+ PIN_AFIO_AF(GPIOB_TRACESWO, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN7, 0U))
+#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN15, 0U))
+
+/*
+ * GPIOC setup:
+ *
+ * PC0 - PIN0 (analog).
+ * PC1 - PIN1 (analog).
+ * PC2 - PIN2 (analog).
+ * PC3 - PIN3 (analog).
+ * PC4 - PIN4 (analog).
+ * PC5 - PIN5 (analog).
+ * PC6 - PIN6 (analog).
+ * PC7 - PIN7 (analog).
+ * PC8 - PIN8 (analog).
+ * PC9 - PIN9 (analog).
+ * PC10 - PIN10 (analog).
+ * PC11 - PIN11 (analog).
+ * PC12 - PIN12 (analog).
+ * PC13 - BUTTON USER_BUTTON (input floating).
+ * PC14 - OSC32_IN (analog).
+ * PC15 - OSC32_OUT (analog).
+ */
+#define VAL_GPIOC_MODER (PIN_MODE_ANALOG(GPIOC_PIN0) | \
+ PIN_MODE_ANALOG(GPIOC_PIN1) | \
+ PIN_MODE_ANALOG(GPIOC_PIN2) | \
+ PIN_MODE_ANALOG(GPIOC_PIN3) | \
+ PIN_MODE_ANALOG(GPIOC_PIN4) | \
+ PIN_MODE_ANALOG(GPIOC_PIN5) | \
+ PIN_MODE_ANALOG(GPIOC_PIN6) | \
+ PIN_MODE_ANALOG(GPIOC_PIN7) | \
+ PIN_MODE_ANALOG(GPIOC_PIN8) | \
+ PIN_MODE_ANALOG(GPIOC_PIN9) | \
+ PIN_MODE_ANALOG(GPIOC_PIN10) | \
+ PIN_MODE_ANALOG(GPIOC_PIN11) | \
+ PIN_MODE_ANALOG(GPIOC_PIN12) | \
+ PIN_MODE_INPUT(GPIOC_BUTTON) | \
+ PIN_MODE_ANALOG(GPIOC_OSC32_IN) | \
+ PIN_MODE_ANALOG(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_BUTTON) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOC_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOC_BUTTON) | \
+ PIN_OSPEED_VERYLOW(GPIOC_OSC32_IN) | \
+ PIN_OSPEED_VERYLOW(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_PUPDR (PIN_PUPDR_FLOATING(GPIOC_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOC_BUTTON) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_ODR (PIN_ODR_LOW(GPIOC_PIN0) | \
+ PIN_ODR_LOW(GPIOC_PIN1) | \
+ PIN_ODR_LOW(GPIOC_PIN2) | \
+ PIN_ODR_LOW(GPIOC_PIN3) | \
+ PIN_ODR_LOW(GPIOC_PIN4) | \
+ PIN_ODR_LOW(GPIOC_PIN5) | \
+ PIN_ODR_LOW(GPIOC_PIN6) | \
+ PIN_ODR_LOW(GPIOC_PIN7) | \
+ PIN_ODR_LOW(GPIOC_PIN8) | \
+ PIN_ODR_LOW(GPIOC_PIN9) | \
+ PIN_ODR_LOW(GPIOC_PIN10) | \
+ PIN_ODR_LOW(GPIOC_PIN11) | \
+ PIN_ODR_LOW(GPIOC_PIN12) | \
+ PIN_ODR_LOW(GPIOC_BUTTON) | \
+ PIN_ODR_LOW(GPIOC_OSC32_IN) | \
+ PIN_ODR_LOW(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN7, 0U))
+#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOC_BUTTON, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U))
+
+/*
+ * GPIOD setup:
+ *
+ * PD0 - PIN0 (analog).
+ * PD1 - PIN1 (analog).
+ * PD2 - PIN2 (analog).
+ * PD3 - PIN3 (analog).
+ * PD4 - PIN4 (analog).
+ * PD5 - PIN5 (analog).
+ * PD6 - PIN6 (analog).
+ * PD7 - PIN7 (analog).
+ * PD8 - PIN8 (analog).
+ * PD9 - PIN9 (analog).
+ * PD10 - PIN10 (analog).
+ * PD11 - PIN11 (analog).
+ * PD12 - PIN12 (analog).
+ * PD13 - PIN13 (analog).
+ * PD14 - PIN14 (analog).
+ * PD15 - PIN15 (analog).
+ */
+#define VAL_GPIOD_MODER (PIN_MODE_ANALOG(GPIOD_PIN0) | \
+ PIN_MODE_ANALOG(GPIOD_PIN1) | \
+ PIN_MODE_ANALOG(GPIOD_PIN2) | \
+ PIN_MODE_ANALOG(GPIOD_PIN3) | \
+ PIN_MODE_ANALOG(GPIOD_PIN4) | \
+ PIN_MODE_ANALOG(GPIOD_PIN5) | \
+ PIN_MODE_ANALOG(GPIOD_PIN6) | \
+ PIN_MODE_ANALOG(GPIOD_PIN7) | \
+ PIN_MODE_ANALOG(GPIOD_PIN8) | \
+ PIN_MODE_ANALOG(GPIOD_PIN9) | \
+ PIN_MODE_ANALOG(GPIOD_PIN10) | \
+ PIN_MODE_ANALOG(GPIOD_PIN11) | \
+ PIN_MODE_ANALOG(GPIOD_PIN12) | \
+ PIN_MODE_ANALOG(GPIOD_PIN13) | \
+ PIN_MODE_ANALOG(GPIOD_PIN14) | \
+ PIN_MODE_ANALOG(GPIOD_PIN15))
+#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN15))
+#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOD_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN15))
+#define VAL_GPIOD_PUPDR (PIN_PUPDR_FLOATING(GPIOD_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN15))
+#define VAL_GPIOD_ODR (PIN_ODR_LOW(GPIOD_PIN0) | \
+ PIN_ODR_LOW(GPIOD_PIN1) | \
+ PIN_ODR_LOW(GPIOD_PIN2) | \
+ PIN_ODR_LOW(GPIOD_PIN3) | \
+ PIN_ODR_LOW(GPIOD_PIN4) | \
+ PIN_ODR_LOW(GPIOD_PIN5) | \
+ PIN_ODR_LOW(GPIOD_PIN6) | \
+ PIN_ODR_LOW(GPIOD_PIN7) | \
+ PIN_ODR_LOW(GPIOD_PIN8) | \
+ PIN_ODR_LOW(GPIOD_PIN9) | \
+ PIN_ODR_LOW(GPIOD_PIN10) | \
+ PIN_ODR_LOW(GPIOD_PIN11) | \
+ PIN_ODR_LOW(GPIOD_PIN12) | \
+ PIN_ODR_LOW(GPIOD_PIN13) | \
+ PIN_ODR_LOW(GPIOD_PIN14) | \
+ PIN_ODR_LOW(GPIOD_PIN15))
+#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN7, 0U))
+#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN15, 0U))
+
+/*
+ * GPIOE setup:
+ *
+ * PE0 - PIN0 (analog).
+ * PE1 - PIN1 (analog).
+ * PE2 - PIN2 (analog).
+ * PE3 - PIN3 (analog).
+ * PE4 - PIN4 (analog).
+ * PE5 - PIN5 (analog).
+ * PE6 - PIN6 (analog).
+ * PE7 - PIN7 (analog).
+ * PE8 - PIN8 (analog).
+ * PE9 - PIN9 (analog).
+ * PE10 - PIN10 (analog).
+ * PE11 - PIN11 (analog).
+ * PE12 - PIN12 (analog).
+ * PE13 - PIN13 (analog).
+ * PE14 - PIN14 (analog).
+ * PE15 - PIN15 (analog).
+ */
+#define VAL_GPIOE_MODER (PIN_MODE_ANALOG(GPIOE_PIN0) | \
+ PIN_MODE_ANALOG(GPIOE_PIN1) | \
+ PIN_MODE_ANALOG(GPIOE_PIN2) | \
+ PIN_MODE_ANALOG(GPIOE_PIN3) | \
+ PIN_MODE_ANALOG(GPIOE_PIN4) | \
+ PIN_MODE_ANALOG(GPIOE_PIN5) | \
+ PIN_MODE_ANALOG(GPIOE_PIN6) | \
+ PIN_MODE_ANALOG(GPIOE_PIN7) | \
+ PIN_MODE_ANALOG(GPIOE_PIN8) | \
+ PIN_MODE_ANALOG(GPIOE_PIN9) | \
+ PIN_MODE_ANALOG(GPIOE_PIN10) | \
+ PIN_MODE_ANALOG(GPIOE_PIN11) | \
+ PIN_MODE_ANALOG(GPIOE_PIN12) | \
+ PIN_MODE_ANALOG(GPIOE_PIN13) | \
+ PIN_MODE_ANALOG(GPIOE_PIN14) | \
+ PIN_MODE_ANALOG(GPIOE_PIN15))
+#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN15))
+#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOE_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN15))
+#define VAL_GPIOE_PUPDR (PIN_PUPDR_FLOATING(GPIOE_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN15))
+#define VAL_GPIOE_ODR (PIN_ODR_LOW(GPIOE_PIN0) | \
+ PIN_ODR_LOW(GPIOE_PIN1) | \
+ PIN_ODR_LOW(GPIOE_PIN2) | \
+ PIN_ODR_LOW(GPIOE_PIN3) | \
+ PIN_ODR_LOW(GPIOE_PIN4) | \
+ PIN_ODR_LOW(GPIOE_PIN5) | \
+ PIN_ODR_LOW(GPIOE_PIN6) | \
+ PIN_ODR_LOW(GPIOE_PIN7) | \
+ PIN_ODR_LOW(GPIOE_PIN8) | \
+ PIN_ODR_LOW(GPIOE_PIN9) | \
+ PIN_ODR_LOW(GPIOE_PIN10) | \
+ PIN_ODR_LOW(GPIOE_PIN11) | \
+ PIN_ODR_LOW(GPIOE_PIN12) | \
+ PIN_ODR_LOW(GPIOE_PIN13) | \
+ PIN_ODR_LOW(GPIOE_PIN14) | \
+ PIN_ODR_LOW(GPIOE_PIN15))
+#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN7, 0U))
+#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN15, 0U))
+
+/*
+ * GPIOF setup:
+ *
+ * PF0 - OSC_IN (analog).
+ * PF1 - OSC_OUT (analog).
+ * PF2 - PIN2 (analog).
+ * PF3 - PIN3 (analog).
+ * PF4 - PIN4 (analog).
+ * PF5 - PIN5 (analog).
+ * PF6 - PIN6 (analog).
+ * PF7 - PIN7 (analog).
+ * PF8 - PIN8 (analog).
+ * PF9 - PIN9 (analog).
+ * PF10 - PIN10 (analog).
+ * PF11 - PIN11 (analog).
+ * PF12 - PIN12 (analog).
+ * PF13 - PIN13 (analog).
+ * PF14 - PIN14 (analog).
+ * PF15 - PIN15 (analog).
+ */
+#define VAL_GPIOF_MODER (PIN_MODE_ANALOG(GPIOF_OSC_IN) | \
+ PIN_MODE_ANALOG(GPIOF_OSC_OUT) | \
+ PIN_MODE_ANALOG(GPIOF_PIN2) | \
+ PIN_MODE_ANALOG(GPIOF_PIN3) | \
+ PIN_MODE_ANALOG(GPIOF_PIN4) | \
+ PIN_MODE_ANALOG(GPIOF_PIN5) | \
+ PIN_MODE_ANALOG(GPIOF_PIN6) | \
+ PIN_MODE_ANALOG(GPIOF_PIN7) | \
+ PIN_MODE_ANALOG(GPIOF_PIN8) | \
+ PIN_MODE_ANALOG(GPIOF_PIN9) | \
+ PIN_MODE_ANALOG(GPIOF_PIN10) | \
+ PIN_MODE_ANALOG(GPIOF_PIN11) | \
+ PIN_MODE_ANALOG(GPIOF_PIN12) | \
+ PIN_MODE_ANALOG(GPIOF_PIN13) | \
+ PIN_MODE_ANALOG(GPIOF_PIN14) | \
+ PIN_MODE_ANALOG(GPIOF_PIN15))
+#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_OSC_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_OSC_OUT) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN15))
+#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOF_OSC_IN) | \
+ PIN_OSPEED_VERYLOW(GPIOF_OSC_OUT) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN15))
+#define VAL_GPIOF_PUPDR (PIN_PUPDR_FLOATING(GPIOF_OSC_IN) | \
+ PIN_PUPDR_FLOATING(GPIOF_OSC_OUT) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN15))
+#define VAL_GPIOF_ODR (PIN_ODR_LOW(GPIOF_OSC_IN) | \
+ PIN_ODR_LOW(GPIOF_OSC_OUT) | \
+ PIN_ODR_LOW(GPIOF_PIN2) | \
+ PIN_ODR_LOW(GPIOF_PIN3) | \
+ PIN_ODR_LOW(GPIOF_PIN4) | \
+ PIN_ODR_LOW(GPIOF_PIN5) | \
+ PIN_ODR_LOW(GPIOF_PIN6) | \
+ PIN_ODR_LOW(GPIOF_PIN7) | \
+ PIN_ODR_LOW(GPIOF_PIN8) | \
+ PIN_ODR_LOW(GPIOF_PIN9) | \
+ PIN_ODR_LOW(GPIOF_PIN10) | \
+ PIN_ODR_LOW(GPIOF_PIN11) | \
+ PIN_ODR_LOW(GPIOF_PIN12) | \
+ PIN_ODR_LOW(GPIOF_PIN13) | \
+ PIN_ODR_LOW(GPIOF_PIN14) | \
+ PIN_ODR_LOW(GPIOF_PIN15))
+#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_OSC_IN, 0U) | \
+ PIN_AFIO_AF(GPIOF_OSC_OUT, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN7, 0U))
+#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN15, 0U))
+
+/*
+ * GPIOG setup:
+ *
+ * PG0 - PIN0 (analog).
+ * PG1 - PIN1 (analog).
+ * PG2 - PIN2 (analog).
+ * PG3 - PIN3 (analog).
+ * PG4 - PIN4 (analog).
+ * PG5 - PIN5 (analog).
+ * PG6 - PIN6 (analog).
+ * PG7 - PIN7 (analog).
+ * PG8 - PIN8 (analog).
+ * PG9 - PIN9 (analog).
+ * PG10 - PIN10 (analog).
+ * PG11 - PIN11 (analog).
+ * PG12 - PIN12 (analog).
+ * PG13 - PIN13 (analog).
+ * PG14 - PIN14 (analog).
+ * PG15 - PIN15 (analog).
+ */
+#define VAL_GPIOG_MODER (PIN_MODE_ANALOG(GPIOG_PIN0) | \
+ PIN_MODE_ANALOG(GPIOG_PIN1) | \
+ PIN_MODE_ANALOG(GPIOG_PIN2) | \
+ PIN_MODE_ANALOG(GPIOG_PIN3) | \
+ PIN_MODE_ANALOG(GPIOG_PIN4) | \
+ PIN_MODE_ANALOG(GPIOG_PIN5) | \
+ PIN_MODE_ANALOG(GPIOG_PIN6) | \
+ PIN_MODE_ANALOG(GPIOG_PIN7) | \
+ PIN_MODE_ANALOG(GPIOG_PIN8) | \
+ PIN_MODE_ANALOG(GPIOG_PIN9) | \
+ PIN_MODE_ANALOG(GPIOG_PIN10) | \
+ PIN_MODE_ANALOG(GPIOG_PIN11) | \
+ PIN_MODE_ANALOG(GPIOG_PIN12) | \
+ PIN_MODE_ANALOG(GPIOG_PIN13) | \
+ PIN_MODE_ANALOG(GPIOG_PIN14) | \
+ PIN_MODE_ANALOG(GPIOG_PIN15))
+#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN15))
+#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOG_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN15))
+#define VAL_GPIOG_PUPDR (PIN_PUPDR_FLOATING(GPIOG_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN15))
+#define VAL_GPIOG_ODR (PIN_ODR_LOW(GPIOG_PIN0) | \
+ PIN_ODR_LOW(GPIOG_PIN1) | \
+ PIN_ODR_LOW(GPIOG_PIN2) | \
+ PIN_ODR_LOW(GPIOG_PIN3) | \
+ PIN_ODR_LOW(GPIOG_PIN4) | \
+ PIN_ODR_LOW(GPIOG_PIN5) | \
+ PIN_ODR_LOW(GPIOG_PIN6) | \
+ PIN_ODR_LOW(GPIOG_PIN7) | \
+ PIN_ODR_LOW(GPIOG_PIN8) | \
+ PIN_ODR_LOW(GPIOG_PIN9) | \
+ PIN_ODR_LOW(GPIOG_PIN10) | \
+ PIN_ODR_LOW(GPIOG_PIN11) | \
+ PIN_ODR_LOW(GPIOG_PIN12) | \
+ PIN_ODR_LOW(GPIOG_PIN13) | \
+ PIN_ODR_LOW(GPIOG_PIN14) | \
+ PIN_ODR_LOW(GPIOG_PIN15))
+#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN7, 0U))
+#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN15, 0U))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* BOARD_H */
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G431RB/board.mk b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G431RB/board.mk
new file mode 100644
index 0000000..b837794
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G431RB/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_G431RB/board.c
+
+# Required include directories
+BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_G431RB
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC += $(BOARDINC)
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G431RB/cfg/board.chcfg b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G431RB/cfg/board.chcfg
new file mode 100644
index 0000000..2f96088
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G431RB/cfg/board.chcfg
@@ -0,0 +1,929 @@
+
+
+
+
+ resources/gencfg/processors/boards/stm32g4xx/templates
+ ..
+ 5.0.x
+
+ STMicroelectronics STM32 Nucleo64-G431RB
+ ST_NUCLEO64_G431RB
+
+ STM32G431xx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G431RB/cfg/board.fmpp b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G431RB/cfg/board.fmpp
new file mode 100644
index 0000000..f48751c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G431RB/cfg/board.fmpp
@@ -0,0 +1,15 @@
+sourceRoot: ../../../../../tools/ftl/processors/boards/stm32g4xx/templates
+outputRoot: ..
+dataRoot: .
+
+freemarkerLinks: {
+ lib: ../../../../../tools/ftl/libs
+}
+
+data : {
+ doc1:xml (
+ board.chcfg
+ {
+ }
+ )
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G474RE/board.c b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G474RE/board.c
new file mode 100644
index 0000000..568c450
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G474RE/board.c
@@ -0,0 +1,266 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#include "hal.h"
+#include "stm32_gpio.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of STM32 GPIO port setup.
+ */
+typedef struct {
+ uint32_t moder;
+ uint32_t otyper;
+ uint32_t ospeedr;
+ uint32_t pupdr;
+ uint32_t odr;
+ uint32_t afrl;
+ uint32_t afrh;
+} gpio_setup_t;
+
+/**
+ * @brief Type of STM32 GPIO initialization data.
+ */
+typedef struct {
+#if STM32_HAS_GPIOA || defined(__DOXYGEN__)
+ gpio_setup_t PAData;
+#endif
+#if STM32_HAS_GPIOB || defined(__DOXYGEN__)
+ gpio_setup_t PBData;
+#endif
+#if STM32_HAS_GPIOC || defined(__DOXYGEN__)
+ gpio_setup_t PCData;
+#endif
+#if STM32_HAS_GPIOD || defined(__DOXYGEN__)
+ gpio_setup_t PDData;
+#endif
+#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
+ gpio_setup_t PEData;
+#endif
+#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
+ gpio_setup_t PFData;
+#endif
+#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
+ gpio_setup_t PGData;
+#endif
+#if STM32_HAS_GPIOH || defined(__DOXYGEN__)
+ gpio_setup_t PHData;
+#endif
+#if STM32_HAS_GPIOI || defined(__DOXYGEN__)
+ gpio_setup_t PIData;
+#endif
+#if STM32_HAS_GPIOJ || defined(__DOXYGEN__)
+ gpio_setup_t PJData;
+#endif
+#if STM32_HAS_GPIOK || defined(__DOXYGEN__)
+ gpio_setup_t PKData;
+#endif
+} gpio_config_t;
+
+/**
+ * @brief STM32 GPIO static initialization data.
+ */
+static const gpio_config_t gpio_default_config = {
+#if STM32_HAS_GPIOA
+ {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
+ VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH},
+#endif
+#if STM32_HAS_GPIOB
+ {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR,
+ VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH},
+#endif
+#if STM32_HAS_GPIOC
+ {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR,
+ VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH},
+#endif
+#if STM32_HAS_GPIOD
+ {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR,
+ VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH},
+#endif
+#if STM32_HAS_GPIOE
+ {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR,
+ VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH},
+#endif
+#if STM32_HAS_GPIOF
+ {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR,
+ VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH},
+#endif
+#if STM32_HAS_GPIOG
+ {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR,
+ VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH},
+#endif
+#if STM32_HAS_GPIOH
+ {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR,
+ VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH},
+#endif
+#if STM32_HAS_GPIOI
+ {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
+ VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH},
+#endif
+#if STM32_HAS_GPIOJ
+ {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR,
+ VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH},
+#endif
+#if STM32_HAS_GPIOK
+ {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR,
+ VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH}
+#endif
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) {
+
+ gpiop->OTYPER = config->otyper;
+ gpiop->OSPEEDR = config->ospeedr;
+ gpiop->PUPDR = config->pupdr;
+ gpiop->ODR = config->odr;
+ gpiop->AFRL = config->afrl;
+ gpiop->AFRH = config->afrh;
+ gpiop->MODER = config->moder;
+}
+
+static void stm32_gpio_init(void) {
+
+ /* Enabling GPIO-related clocks, the mask comes from the
+ registry header file.*/
+ rccResetAHB2(STM32_GPIO_EN_MASK);
+ rccEnableAHB2(STM32_GPIO_EN_MASK, true);
+
+ /* Initializing all the defined GPIO ports.*/
+#if STM32_HAS_GPIOA
+ gpio_init(GPIOA, &gpio_default_config.PAData);
+#endif
+#if STM32_HAS_GPIOB
+ gpio_init(GPIOB, &gpio_default_config.PBData);
+#endif
+#if STM32_HAS_GPIOC
+ gpio_init(GPIOC, &gpio_default_config.PCData);
+#endif
+#if STM32_HAS_GPIOD
+ gpio_init(GPIOD, &gpio_default_config.PDData);
+#endif
+#if STM32_HAS_GPIOE
+ gpio_init(GPIOE, &gpio_default_config.PEData);
+#endif
+#if STM32_HAS_GPIOF
+ gpio_init(GPIOF, &gpio_default_config.PFData);
+#endif
+#if STM32_HAS_GPIOG
+ gpio_init(GPIOG, &gpio_default_config.PGData);
+#endif
+#if STM32_HAS_GPIOH
+ gpio_init(GPIOH, &gpio_default_config.PHData);
+#endif
+#if STM32_HAS_GPIOI
+ gpio_init(GPIOI, &gpio_default_config.PIData);
+#endif
+#if STM32_HAS_GPIOJ
+ gpio_init(GPIOJ, &gpio_default_config.PJData);
+#endif
+#if STM32_HAS_GPIOK
+ gpio_init(GPIOK, &gpio_default_config.PKData);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Early initialization code.
+ * @details GPIO ports and system clocks are initialized before everything
+ * else.
+ */
+void __early_init(void) {
+
+ stm32_gpio_init();
+ stm32_clock_init();
+}
+
+#if HAL_USE_SDC || defined(__DOXYGEN__)
+/**
+ * @brief SDC card detection.
+ */
+bool sdc_lld_is_card_inserted(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief SDC card write protection detection.
+ */
+bool sdc_lld_is_write_protected(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif /* HAL_USE_SDC */
+
+#if HAL_USE_MMC_SPI || defined(__DOXYGEN__)
+/**
+ * @brief MMC_SPI card detection.
+ */
+bool mmc_lld_is_card_inserted(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief MMC_SPI card write protection detection.
+ */
+bool mmc_lld_is_write_protected(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif
+
+/**
+ * @brief Board-specific initialization code.
+ * @note You can add your board-specific code here.
+ */
+void boardInit(void) {
+
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G474RE/board.h b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G474RE/board.h
new file mode 100644
index 0000000..75c25f6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G474RE/board.h
@@ -0,0 +1,1078 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#ifndef BOARD_H
+#define BOARD_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*
+ * Setup for STMicroelectronics STM32 Nucleo64-G474RE board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_ST_NUCLEO64_G474RE
+#define BOARD_NAME "STMicroelectronics STM32 Nucleo64-G474RE"
+
+/*
+ * Board oscillators-related settings.
+ */
+#if !defined(STM32_LSECLK)
+#define STM32_LSECLK 32768U
+#endif
+
+#define STM32_LSEDRV (3U << 3U)
+
+#if !defined(STM32_HSECLK)
+#define STM32_HSECLK 24000000U
+#endif
+
+/*
+ * Board voltages.
+ * Required for performance limits calculation.
+ */
+#define STM32_VDD 300U
+
+/*
+ * MCU type as defined in the ST header.
+ */
+#define STM32G474xx
+
+/*
+ * IO pins assignments.
+ */
+#define GPIOA_PIN0 0U
+#define GPIOA_PIN1 1U
+#define GPIOA_STLINK_TX 2U
+#define GPIOA_STLINK_RX 3U
+#define GPIOA_PIN4 4U
+#define GPIOA_LED 5U
+#define GPIOA_LED_GREEN 5U
+#define GPIOA_PIN6 6U
+#define GPIOA_PIN7 7U
+#define GPIOA_PIN8 8U
+#define GPIOA_PIN9 9U
+#define GPIOA_PIN10 10U
+#define GPIOA_PIN11 11U
+#define GPIOA_PIN12 12U
+#define GPIOA_SWDIO 13U
+#define GPIOA_SWCLK 14U
+#define GPIOA_PIN15 15U
+
+#define GPIOB_PIN0 0U
+#define GPIOB_PIN1 1U
+#define GPIOB_BOOT1 2U
+#define GPIOB_TRACESWO 3U
+#define GPIOB_PIN4 4U
+#define GPIOB_PIN5 5U
+#define GPIOB_PIN6 6U
+#define GPIOB_PIN7 7U
+#define GPIOB_PIN8 8U
+#define GPIOB_PIN9 9U
+#define GPIOB_PIN10 10U
+#define GPIOB_PIN11 11U
+#define GPIOB_PIN12 12U
+#define GPIOB_PIN13 13U
+#define GPIOB_PIN14 14U
+#define GPIOB_PIN15 15U
+
+#define GPIOC_PIN0 0U
+#define GPIOC_PIN1 1U
+#define GPIOC_PIN2 2U
+#define GPIOC_PIN3 3U
+#define GPIOC_PIN4 4U
+#define GPIOC_PIN5 5U
+#define GPIOC_PIN6 6U
+#define GPIOC_PIN7 7U
+#define GPIOC_PIN8 8U
+#define GPIOC_PIN9 9U
+#define GPIOC_PIN10 10U
+#define GPIOC_PIN11 11U
+#define GPIOC_PIN12 12U
+#define GPIOC_BUTTON 13U
+#define GPIOC_USER_BUTTON 13U
+#define GPIOC_OSC32_IN 14U
+#define GPIOC_OSC32_OUT 15U
+
+#define GPIOD_PIN0 0U
+#define GPIOD_PIN1 1U
+#define GPIOD_PIN2 2U
+#define GPIOD_PIN3 3U
+#define GPIOD_PIN4 4U
+#define GPIOD_PIN5 5U
+#define GPIOD_PIN6 6U
+#define GPIOD_PIN7 7U
+#define GPIOD_PIN8 8U
+#define GPIOD_PIN9 9U
+#define GPIOD_PIN10 10U
+#define GPIOD_PIN11 11U
+#define GPIOD_PIN12 12U
+#define GPIOD_PIN13 13U
+#define GPIOD_PIN14 14U
+#define GPIOD_PIN15 15U
+
+#define GPIOE_PIN0 0U
+#define GPIOE_PIN1 1U
+#define GPIOE_PIN2 2U
+#define GPIOE_PIN3 3U
+#define GPIOE_PIN4 4U
+#define GPIOE_PIN5 5U
+#define GPIOE_PIN6 6U
+#define GPIOE_PIN7 7U
+#define GPIOE_PIN8 8U
+#define GPIOE_PIN9 9U
+#define GPIOE_PIN10 10U
+#define GPIOE_PIN11 11U
+#define GPIOE_PIN12 12U
+#define GPIOE_PIN13 13U
+#define GPIOE_PIN14 14U
+#define GPIOE_PIN15 15U
+
+#define GPIOF_OSC_IN 0U
+#define GPIOF_OSC_OUT 1U
+#define GPIOF_PIN2 2U
+#define GPIOF_PIN3 3U
+#define GPIOF_PIN4 4U
+#define GPIOF_PIN5 5U
+#define GPIOF_PIN6 6U
+#define GPIOF_PIN7 7U
+#define GPIOF_PIN8 8U
+#define GPIOF_PIN9 9U
+#define GPIOF_PIN10 10U
+#define GPIOF_PIN11 11U
+#define GPIOF_PIN12 12U
+#define GPIOF_PIN13 13U
+#define GPIOF_PIN14 14U
+#define GPIOF_PIN15 15U
+
+#define GPIOG_PIN0 0U
+#define GPIOG_PIN1 1U
+#define GPIOG_PIN2 2U
+#define GPIOG_PIN3 3U
+#define GPIOG_PIN4 4U
+#define GPIOG_PIN5 5U
+#define GPIOG_PIN6 6U
+#define GPIOG_PIN7 7U
+#define GPIOG_PIN8 8U
+#define GPIOG_PIN9 9U
+#define GPIOG_PIN10 10U
+#define GPIOG_PIN11 11U
+#define GPIOG_PIN12 12U
+#define GPIOG_PIN13 13U
+#define GPIOG_PIN14 14U
+#define GPIOG_PIN15 15U
+
+/*
+ * IO lines assignments.
+ */
+#define LINE_STLINK_TX PAL_LINE(GPIOA, 2U)
+#define LINE_STLINK_RX PAL_LINE(GPIOA, 3U)
+#define LINE_LED PAL_LINE(GPIOA, 5U)
+#define LINE_LED_GREEN PAL_LINE(GPIOA, 5U)
+#define LINE_SWDIO PAL_LINE(GPIOA, 13U)
+#define LINE_SWCLK PAL_LINE(GPIOA, 14U)
+#define LINE_BOOT1 PAL_LINE(GPIOB, 2U)
+#define LINE_TRACESWO PAL_LINE(GPIOB, 3U)
+#define LINE_BUTTON PAL_LINE(GPIOC, 13U)
+#define LINE_USER_BUTTON PAL_LINE(GPIOC, 13U)
+#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U)
+#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U)
+#define LINE_OSC_IN PAL_LINE(GPIOF, 0U)
+#define LINE_OSC_OUT PAL_LINE(GPIOF, 1U)
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*
+ * I/O ports initial setup, this configuration is established soon after reset
+ * in the initialization code.
+ * Please refer to the STM32 Reference Manual for details.
+ */
+#define PIN_MODE_INPUT(n) (0U << ((n) * 2U))
+#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U))
+#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U))
+#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U))
+#define PIN_ODR_LOW(n) (0U << (n))
+#define PIN_ODR_HIGH(n) (1U << (n))
+#define PIN_OTYPE_PUSHPULL(n) (0U << (n))
+#define PIN_OTYPE_OPENDRAIN(n) (1U << (n))
+#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U))
+#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U))
+#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U))
+#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U))
+#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U))
+#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U))
+#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U))
+#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U))
+#define PIN_LOCKR_DISABLED(n) (0U << (n))
+#define PIN_LOCKR_ENABLED(n) (1U << (n))
+
+/*
+ * GPIOA setup:
+ *
+ * PA0 - PIN0 (analog).
+ * PA1 - PIN1 (analog).
+ * PA2 - STLINK_TX (alternate 12).
+ * PA3 - STLINK_RX (alternate 12).
+ * PA4 - PIN4 (analog).
+ * PA5 - LED LED_GREEN (output pushpull maximum).
+ * PA6 - PIN6 (analog).
+ * PA7 - PIN7 (analog).
+ * PA8 - PIN8 (analog).
+ * PA9 - PIN9 (analog).
+ * PA10 - PIN10 (analog).
+ * PA11 - PIN11 (analog).
+ * PA12 - PIN12 (analog).
+ * PA13 - SWDIO (alternate 0).
+ * PA14 - SWCLK (alternate 0).
+ * PA15 - PIN15 (analog).
+ */
+#define VAL_GPIOA_MODER (PIN_MODE_ANALOG(GPIOA_PIN0) | \
+ PIN_MODE_ANALOG(GPIOA_PIN1) | \
+ PIN_MODE_ALTERNATE(GPIOA_STLINK_TX) | \
+ PIN_MODE_ALTERNATE(GPIOA_STLINK_RX) | \
+ PIN_MODE_ANALOG(GPIOA_PIN4) | \
+ PIN_MODE_OUTPUT(GPIOA_LED) | \
+ PIN_MODE_ANALOG(GPIOA_PIN6) | \
+ PIN_MODE_ANALOG(GPIOA_PIN7) | \
+ PIN_MODE_ANALOG(GPIOA_PIN8) | \
+ PIN_MODE_ANALOG(GPIOA_PIN9) | \
+ PIN_MODE_ANALOG(GPIOA_PIN10) | \
+ PIN_MODE_ANALOG(GPIOA_PIN11) | \
+ PIN_MODE_ANALOG(GPIOA_PIN12) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \
+ PIN_MODE_ANALOG(GPIOA_PIN15))
+#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_STLINK_TX) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_STLINK_RX) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_LED) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN15))
+#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOA_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOA_STLINK_TX) | \
+ PIN_OSPEED_VERYLOW(GPIOA_STLINK_RX) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOA_LED) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOA_SWDIO) | \
+ PIN_OSPEED_HIGH(GPIOA_SWCLK) | \
+ PIN_OSPEED_VERYLOW(GPIOA_PIN15))
+#define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOA_STLINK_TX) | \
+ PIN_PUPDR_FLOATING(GPIOA_STLINK_RX) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOA_LED) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOA_SWDIO) | \
+ PIN_PUPDR_PULLDOWN(GPIOA_SWCLK) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN15))
+#define VAL_GPIOA_ODR (PIN_ODR_LOW(GPIOA_PIN0) | \
+ PIN_ODR_LOW(GPIOA_PIN1) | \
+ PIN_ODR_LOW(GPIOA_STLINK_TX) | \
+ PIN_ODR_LOW(GPIOA_STLINK_RX) | \
+ PIN_ODR_LOW(GPIOA_PIN4) | \
+ PIN_ODR_LOW(GPIOA_LED) | \
+ PIN_ODR_LOW(GPIOA_PIN6) | \
+ PIN_ODR_LOW(GPIOA_PIN7) | \
+ PIN_ODR_LOW(GPIOA_PIN8) | \
+ PIN_ODR_LOW(GPIOA_PIN9) | \
+ PIN_ODR_LOW(GPIOA_PIN10) | \
+ PIN_ODR_LOW(GPIOA_PIN11) | \
+ PIN_ODR_LOW(GPIOA_PIN12) | \
+ PIN_ODR_LOW(GPIOA_SWDIO) | \
+ PIN_ODR_LOW(GPIOA_SWCLK) | \
+ PIN_ODR_LOW(GPIOA_PIN15))
+#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOA_STLINK_TX, 12U) | \
+ PIN_AFIO_AF(GPIOA_STLINK_RX, 12U) | \
+ PIN_AFIO_AF(GPIOA_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOA_LED, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN7, 0U))
+#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOA_SWDIO, 0U) | \
+ PIN_AFIO_AF(GPIOA_SWCLK, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN15, 0U))
+
+/*
+ * GPIOB setup:
+ *
+ * PB0 - PIN0 (analog).
+ * PB1 - PIN1 (analog).
+ * PB2 - BOOT1 (analog).
+ * PB3 - TRACESWO (alternate 0).
+ * PB4 - PIN4 (analog).
+ * PB5 - PIN5 (analog).
+ * PB6 - PIN6 (analog).
+ * PB7 - PIN7 (analog).
+ * PB8 - PIN8 (analog).
+ * PB9 - PIN9 (analog).
+ * PB10 - PIN10 (analog).
+ * PB11 - PIN11 (analog).
+ * PB12 - PIN12 (analog).
+ * PB13 - PIN13 (analog).
+ * PB14 - PIN14 (analog).
+ * PB15 - PIN15 (analog).
+ */
+#define VAL_GPIOB_MODER (PIN_MODE_ANALOG(GPIOB_PIN0) | \
+ PIN_MODE_ANALOG(GPIOB_PIN1) | \
+ PIN_MODE_ANALOG(GPIOB_BOOT1) | \
+ PIN_MODE_ALTERNATE(GPIOB_TRACESWO) | \
+ PIN_MODE_ANALOG(GPIOB_PIN4) | \
+ PIN_MODE_ANALOG(GPIOB_PIN5) | \
+ PIN_MODE_ANALOG(GPIOB_PIN6) | \
+ PIN_MODE_ANALOG(GPIOB_PIN7) | \
+ PIN_MODE_ANALOG(GPIOB_PIN8) | \
+ PIN_MODE_ANALOG(GPIOB_PIN9) | \
+ PIN_MODE_ANALOG(GPIOB_PIN10) | \
+ PIN_MODE_ANALOG(GPIOB_PIN11) | \
+ PIN_MODE_ANALOG(GPIOB_PIN12) | \
+ PIN_MODE_ANALOG(GPIOB_PIN13) | \
+ PIN_MODE_ANALOG(GPIOB_PIN14) | \
+ PIN_MODE_ANALOG(GPIOB_PIN15))
+#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_BOOT1) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_TRACESWO) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN15))
+#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOB_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOB_BOOT1) | \
+ PIN_OSPEED_HIGH(GPIOB_TRACESWO) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOB_PIN15))
+#define VAL_GPIOB_PUPDR (PIN_PUPDR_FLOATING(GPIOB_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOB_BOOT1) | \
+ PIN_PUPDR_FLOATING(GPIOB_TRACESWO) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN15))
+#define VAL_GPIOB_ODR (PIN_ODR_LOW(GPIOB_PIN0) | \
+ PIN_ODR_LOW(GPIOB_PIN1) | \
+ PIN_ODR_LOW(GPIOB_BOOT1) | \
+ PIN_ODR_LOW(GPIOB_TRACESWO) | \
+ PIN_ODR_LOW(GPIOB_PIN4) | \
+ PIN_ODR_LOW(GPIOB_PIN5) | \
+ PIN_ODR_LOW(GPIOB_PIN6) | \
+ PIN_ODR_LOW(GPIOB_PIN7) | \
+ PIN_ODR_LOW(GPIOB_PIN8) | \
+ PIN_ODR_LOW(GPIOB_PIN9) | \
+ PIN_ODR_LOW(GPIOB_PIN10) | \
+ PIN_ODR_LOW(GPIOB_PIN11) | \
+ PIN_ODR_LOW(GPIOB_PIN12) | \
+ PIN_ODR_LOW(GPIOB_PIN13) | \
+ PIN_ODR_LOW(GPIOB_PIN14) | \
+ PIN_ODR_LOW(GPIOB_PIN15))
+#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOB_BOOT1, 0U) | \
+ PIN_AFIO_AF(GPIOB_TRACESWO, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN7, 0U))
+#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN15, 0U))
+
+/*
+ * GPIOC setup:
+ *
+ * PC0 - PIN0 (analog).
+ * PC1 - PIN1 (analog).
+ * PC2 - PIN2 (analog).
+ * PC3 - PIN3 (analog).
+ * PC4 - PIN4 (analog).
+ * PC5 - PIN5 (analog).
+ * PC6 - PIN6 (analog).
+ * PC7 - PIN7 (analog).
+ * PC8 - PIN8 (analog).
+ * PC9 - PIN9 (analog).
+ * PC10 - PIN10 (analog).
+ * PC11 - PIN11 (analog).
+ * PC12 - PIN12 (analog).
+ * PC13 - BUTTON USER_BUTTON (input floating).
+ * PC14 - OSC32_IN (analog).
+ * PC15 - OSC32_OUT (analog).
+ */
+#define VAL_GPIOC_MODER (PIN_MODE_ANALOG(GPIOC_PIN0) | \
+ PIN_MODE_ANALOG(GPIOC_PIN1) | \
+ PIN_MODE_ANALOG(GPIOC_PIN2) | \
+ PIN_MODE_ANALOG(GPIOC_PIN3) | \
+ PIN_MODE_ANALOG(GPIOC_PIN4) | \
+ PIN_MODE_ANALOG(GPIOC_PIN5) | \
+ PIN_MODE_ANALOG(GPIOC_PIN6) | \
+ PIN_MODE_ANALOG(GPIOC_PIN7) | \
+ PIN_MODE_ANALOG(GPIOC_PIN8) | \
+ PIN_MODE_ANALOG(GPIOC_PIN9) | \
+ PIN_MODE_ANALOG(GPIOC_PIN10) | \
+ PIN_MODE_ANALOG(GPIOC_PIN11) | \
+ PIN_MODE_ANALOG(GPIOC_PIN12) | \
+ PIN_MODE_INPUT(GPIOC_BUTTON) | \
+ PIN_MODE_ANALOG(GPIOC_OSC32_IN) | \
+ PIN_MODE_ANALOG(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_BUTTON) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOC_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOC_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOC_BUTTON) | \
+ PIN_OSPEED_VERYLOW(GPIOC_OSC32_IN) | \
+ PIN_OSPEED_VERYLOW(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_PUPDR (PIN_PUPDR_FLOATING(GPIOC_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOC_BUTTON) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_ODR (PIN_ODR_LOW(GPIOC_PIN0) | \
+ PIN_ODR_LOW(GPIOC_PIN1) | \
+ PIN_ODR_LOW(GPIOC_PIN2) | \
+ PIN_ODR_LOW(GPIOC_PIN3) | \
+ PIN_ODR_LOW(GPIOC_PIN4) | \
+ PIN_ODR_LOW(GPIOC_PIN5) | \
+ PIN_ODR_LOW(GPIOC_PIN6) | \
+ PIN_ODR_LOW(GPIOC_PIN7) | \
+ PIN_ODR_LOW(GPIOC_PIN8) | \
+ PIN_ODR_LOW(GPIOC_PIN9) | \
+ PIN_ODR_LOW(GPIOC_PIN10) | \
+ PIN_ODR_LOW(GPIOC_PIN11) | \
+ PIN_ODR_LOW(GPIOC_PIN12) | \
+ PIN_ODR_LOW(GPIOC_BUTTON) | \
+ PIN_ODR_LOW(GPIOC_OSC32_IN) | \
+ PIN_ODR_LOW(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN7, 0U))
+#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOC_BUTTON, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U))
+
+/*
+ * GPIOD setup:
+ *
+ * PD0 - PIN0 (analog).
+ * PD1 - PIN1 (analog).
+ * PD2 - PIN2 (analog).
+ * PD3 - PIN3 (analog).
+ * PD4 - PIN4 (analog).
+ * PD5 - PIN5 (analog).
+ * PD6 - PIN6 (analog).
+ * PD7 - PIN7 (analog).
+ * PD8 - PIN8 (analog).
+ * PD9 - PIN9 (analog).
+ * PD10 - PIN10 (analog).
+ * PD11 - PIN11 (analog).
+ * PD12 - PIN12 (analog).
+ * PD13 - PIN13 (analog).
+ * PD14 - PIN14 (analog).
+ * PD15 - PIN15 (analog).
+ */
+#define VAL_GPIOD_MODER (PIN_MODE_ANALOG(GPIOD_PIN0) | \
+ PIN_MODE_ANALOG(GPIOD_PIN1) | \
+ PIN_MODE_ANALOG(GPIOD_PIN2) | \
+ PIN_MODE_ANALOG(GPIOD_PIN3) | \
+ PIN_MODE_ANALOG(GPIOD_PIN4) | \
+ PIN_MODE_ANALOG(GPIOD_PIN5) | \
+ PIN_MODE_ANALOG(GPIOD_PIN6) | \
+ PIN_MODE_ANALOG(GPIOD_PIN7) | \
+ PIN_MODE_ANALOG(GPIOD_PIN8) | \
+ PIN_MODE_ANALOG(GPIOD_PIN9) | \
+ PIN_MODE_ANALOG(GPIOD_PIN10) | \
+ PIN_MODE_ANALOG(GPIOD_PIN11) | \
+ PIN_MODE_ANALOG(GPIOD_PIN12) | \
+ PIN_MODE_ANALOG(GPIOD_PIN13) | \
+ PIN_MODE_ANALOG(GPIOD_PIN14) | \
+ PIN_MODE_ANALOG(GPIOD_PIN15))
+#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN15))
+#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOD_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN15))
+#define VAL_GPIOD_PUPDR (PIN_PUPDR_FLOATING(GPIOD_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN15))
+#define VAL_GPIOD_ODR (PIN_ODR_LOW(GPIOD_PIN0) | \
+ PIN_ODR_LOW(GPIOD_PIN1) | \
+ PIN_ODR_LOW(GPIOD_PIN2) | \
+ PIN_ODR_LOW(GPIOD_PIN3) | \
+ PIN_ODR_LOW(GPIOD_PIN4) | \
+ PIN_ODR_LOW(GPIOD_PIN5) | \
+ PIN_ODR_LOW(GPIOD_PIN6) | \
+ PIN_ODR_LOW(GPIOD_PIN7) | \
+ PIN_ODR_LOW(GPIOD_PIN8) | \
+ PIN_ODR_LOW(GPIOD_PIN9) | \
+ PIN_ODR_LOW(GPIOD_PIN10) | \
+ PIN_ODR_LOW(GPIOD_PIN11) | \
+ PIN_ODR_LOW(GPIOD_PIN12) | \
+ PIN_ODR_LOW(GPIOD_PIN13) | \
+ PIN_ODR_LOW(GPIOD_PIN14) | \
+ PIN_ODR_LOW(GPIOD_PIN15))
+#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN7, 0U))
+#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN15, 0U))
+
+/*
+ * GPIOE setup:
+ *
+ * PE0 - PIN0 (analog).
+ * PE1 - PIN1 (analog).
+ * PE2 - PIN2 (analog).
+ * PE3 - PIN3 (analog).
+ * PE4 - PIN4 (analog).
+ * PE5 - PIN5 (analog).
+ * PE6 - PIN6 (analog).
+ * PE7 - PIN7 (analog).
+ * PE8 - PIN8 (analog).
+ * PE9 - PIN9 (analog).
+ * PE10 - PIN10 (analog).
+ * PE11 - PIN11 (analog).
+ * PE12 - PIN12 (analog).
+ * PE13 - PIN13 (analog).
+ * PE14 - PIN14 (analog).
+ * PE15 - PIN15 (analog).
+ */
+#define VAL_GPIOE_MODER (PIN_MODE_ANALOG(GPIOE_PIN0) | \
+ PIN_MODE_ANALOG(GPIOE_PIN1) | \
+ PIN_MODE_ANALOG(GPIOE_PIN2) | \
+ PIN_MODE_ANALOG(GPIOE_PIN3) | \
+ PIN_MODE_ANALOG(GPIOE_PIN4) | \
+ PIN_MODE_ANALOG(GPIOE_PIN5) | \
+ PIN_MODE_ANALOG(GPIOE_PIN6) | \
+ PIN_MODE_ANALOG(GPIOE_PIN7) | \
+ PIN_MODE_ANALOG(GPIOE_PIN8) | \
+ PIN_MODE_ANALOG(GPIOE_PIN9) | \
+ PIN_MODE_ANALOG(GPIOE_PIN10) | \
+ PIN_MODE_ANALOG(GPIOE_PIN11) | \
+ PIN_MODE_ANALOG(GPIOE_PIN12) | \
+ PIN_MODE_ANALOG(GPIOE_PIN13) | \
+ PIN_MODE_ANALOG(GPIOE_PIN14) | \
+ PIN_MODE_ANALOG(GPIOE_PIN15))
+#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN15))
+#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOE_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN15))
+#define VAL_GPIOE_PUPDR (PIN_PUPDR_FLOATING(GPIOE_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN15))
+#define VAL_GPIOE_ODR (PIN_ODR_LOW(GPIOE_PIN0) | \
+ PIN_ODR_LOW(GPIOE_PIN1) | \
+ PIN_ODR_LOW(GPIOE_PIN2) | \
+ PIN_ODR_LOW(GPIOE_PIN3) | \
+ PIN_ODR_LOW(GPIOE_PIN4) | \
+ PIN_ODR_LOW(GPIOE_PIN5) | \
+ PIN_ODR_LOW(GPIOE_PIN6) | \
+ PIN_ODR_LOW(GPIOE_PIN7) | \
+ PIN_ODR_LOW(GPIOE_PIN8) | \
+ PIN_ODR_LOW(GPIOE_PIN9) | \
+ PIN_ODR_LOW(GPIOE_PIN10) | \
+ PIN_ODR_LOW(GPIOE_PIN11) | \
+ PIN_ODR_LOW(GPIOE_PIN12) | \
+ PIN_ODR_LOW(GPIOE_PIN13) | \
+ PIN_ODR_LOW(GPIOE_PIN14) | \
+ PIN_ODR_LOW(GPIOE_PIN15))
+#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN7, 0U))
+#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN15, 0U))
+
+/*
+ * GPIOF setup:
+ *
+ * PF0 - OSC_IN (analog).
+ * PF1 - OSC_OUT (analog).
+ * PF2 - PIN2 (analog).
+ * PF3 - PIN3 (analog).
+ * PF4 - PIN4 (analog).
+ * PF5 - PIN5 (analog).
+ * PF6 - PIN6 (analog).
+ * PF7 - PIN7 (analog).
+ * PF8 - PIN8 (analog).
+ * PF9 - PIN9 (analog).
+ * PF10 - PIN10 (analog).
+ * PF11 - PIN11 (analog).
+ * PF12 - PIN12 (analog).
+ * PF13 - PIN13 (analog).
+ * PF14 - PIN14 (analog).
+ * PF15 - PIN15 (analog).
+ */
+#define VAL_GPIOF_MODER (PIN_MODE_ANALOG(GPIOF_OSC_IN) | \
+ PIN_MODE_ANALOG(GPIOF_OSC_OUT) | \
+ PIN_MODE_ANALOG(GPIOF_PIN2) | \
+ PIN_MODE_ANALOG(GPIOF_PIN3) | \
+ PIN_MODE_ANALOG(GPIOF_PIN4) | \
+ PIN_MODE_ANALOG(GPIOF_PIN5) | \
+ PIN_MODE_ANALOG(GPIOF_PIN6) | \
+ PIN_MODE_ANALOG(GPIOF_PIN7) | \
+ PIN_MODE_ANALOG(GPIOF_PIN8) | \
+ PIN_MODE_ANALOG(GPIOF_PIN9) | \
+ PIN_MODE_ANALOG(GPIOF_PIN10) | \
+ PIN_MODE_ANALOG(GPIOF_PIN11) | \
+ PIN_MODE_ANALOG(GPIOF_PIN12) | \
+ PIN_MODE_ANALOG(GPIOF_PIN13) | \
+ PIN_MODE_ANALOG(GPIOF_PIN14) | \
+ PIN_MODE_ANALOG(GPIOF_PIN15))
+#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_OSC_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_OSC_OUT) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN15))
+#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOF_OSC_IN) | \
+ PIN_OSPEED_VERYLOW(GPIOF_OSC_OUT) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN15))
+#define VAL_GPIOF_PUPDR (PIN_PUPDR_FLOATING(GPIOF_OSC_IN) | \
+ PIN_PUPDR_FLOATING(GPIOF_OSC_OUT) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN15))
+#define VAL_GPIOF_ODR (PIN_ODR_LOW(GPIOF_OSC_IN) | \
+ PIN_ODR_LOW(GPIOF_OSC_OUT) | \
+ PIN_ODR_LOW(GPIOF_PIN2) | \
+ PIN_ODR_LOW(GPIOF_PIN3) | \
+ PIN_ODR_LOW(GPIOF_PIN4) | \
+ PIN_ODR_LOW(GPIOF_PIN5) | \
+ PIN_ODR_LOW(GPIOF_PIN6) | \
+ PIN_ODR_LOW(GPIOF_PIN7) | \
+ PIN_ODR_LOW(GPIOF_PIN8) | \
+ PIN_ODR_LOW(GPIOF_PIN9) | \
+ PIN_ODR_LOW(GPIOF_PIN10) | \
+ PIN_ODR_LOW(GPIOF_PIN11) | \
+ PIN_ODR_LOW(GPIOF_PIN12) | \
+ PIN_ODR_LOW(GPIOF_PIN13) | \
+ PIN_ODR_LOW(GPIOF_PIN14) | \
+ PIN_ODR_LOW(GPIOF_PIN15))
+#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_OSC_IN, 0U) | \
+ PIN_AFIO_AF(GPIOF_OSC_OUT, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN7, 0U))
+#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN15, 0U))
+
+/*
+ * GPIOG setup:
+ *
+ * PG0 - PIN0 (analog).
+ * PG1 - PIN1 (analog).
+ * PG2 - PIN2 (analog).
+ * PG3 - PIN3 (analog).
+ * PG4 - PIN4 (analog).
+ * PG5 - PIN5 (analog).
+ * PG6 - PIN6 (analog).
+ * PG7 - PIN7 (analog).
+ * PG8 - PIN8 (analog).
+ * PG9 - PIN9 (analog).
+ * PG10 - PIN10 (analog).
+ * PG11 - PIN11 (analog).
+ * PG12 - PIN12 (analog).
+ * PG13 - PIN13 (analog).
+ * PG14 - PIN14 (analog).
+ * PG15 - PIN15 (analog).
+ */
+#define VAL_GPIOG_MODER (PIN_MODE_ANALOG(GPIOG_PIN0) | \
+ PIN_MODE_ANALOG(GPIOG_PIN1) | \
+ PIN_MODE_ANALOG(GPIOG_PIN2) | \
+ PIN_MODE_ANALOG(GPIOG_PIN3) | \
+ PIN_MODE_ANALOG(GPIOG_PIN4) | \
+ PIN_MODE_ANALOG(GPIOG_PIN5) | \
+ PIN_MODE_ANALOG(GPIOG_PIN6) | \
+ PIN_MODE_ANALOG(GPIOG_PIN7) | \
+ PIN_MODE_ANALOG(GPIOG_PIN8) | \
+ PIN_MODE_ANALOG(GPIOG_PIN9) | \
+ PIN_MODE_ANALOG(GPIOG_PIN10) | \
+ PIN_MODE_ANALOG(GPIOG_PIN11) | \
+ PIN_MODE_ANALOG(GPIOG_PIN12) | \
+ PIN_MODE_ANALOG(GPIOG_PIN13) | \
+ PIN_MODE_ANALOG(GPIOG_PIN14) | \
+ PIN_MODE_ANALOG(GPIOG_PIN15))
+#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN15))
+#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOG_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN15))
+#define VAL_GPIOG_PUPDR (PIN_PUPDR_FLOATING(GPIOG_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN15))
+#define VAL_GPIOG_ODR (PIN_ODR_LOW(GPIOG_PIN0) | \
+ PIN_ODR_LOW(GPIOG_PIN1) | \
+ PIN_ODR_LOW(GPIOG_PIN2) | \
+ PIN_ODR_LOW(GPIOG_PIN3) | \
+ PIN_ODR_LOW(GPIOG_PIN4) | \
+ PIN_ODR_LOW(GPIOG_PIN5) | \
+ PIN_ODR_LOW(GPIOG_PIN6) | \
+ PIN_ODR_LOW(GPIOG_PIN7) | \
+ PIN_ODR_LOW(GPIOG_PIN8) | \
+ PIN_ODR_LOW(GPIOG_PIN9) | \
+ PIN_ODR_LOW(GPIOG_PIN10) | \
+ PIN_ODR_LOW(GPIOG_PIN11) | \
+ PIN_ODR_LOW(GPIOG_PIN12) | \
+ PIN_ODR_LOW(GPIOG_PIN13) | \
+ PIN_ODR_LOW(GPIOG_PIN14) | \
+ PIN_ODR_LOW(GPIOG_PIN15))
+#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN7, 0U))
+#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN15, 0U))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* BOARD_H */
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G474RE/board.mk b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G474RE/board.mk
new file mode 100644
index 0000000..61c8e1a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G474RE/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_G474RE/board.c
+
+# Required include directories
+BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_G474RE
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC += $(BOARDINC)
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G474RE/cfg/board.chcfg b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G474RE/cfg/board.chcfg
new file mode 100644
index 0000000..3e9fdea
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G474RE/cfg/board.chcfg
@@ -0,0 +1,929 @@
+
+
+
+
+ resources/gencfg/processors/boards/stm32g4xx/templates
+ ..
+ 5.0.x
+
+ STMicroelectronics STM32 Nucleo64-G474RE
+ ST_NUCLEO64_G474RE
+
+ STM32G474xx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G474RE/cfg/board.fmpp b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G474RE/cfg/board.fmpp
new file mode 100644
index 0000000..f48751c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_G474RE/cfg/board.fmpp
@@ -0,0 +1,15 @@
+sourceRoot: ../../../../../tools/ftl/processors/boards/stm32g4xx/templates
+outputRoot: ..
+dataRoot: .
+
+freemarkerLinks: {
+ lib: ../../../../../tools/ftl/libs
+}
+
+data : {
+ doc1:xml (
+ board.chcfg
+ {
+ }
+ )
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L053R8/board.c b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L053R8/board.c
new file mode 100644
index 0000000..fbea4c4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L053R8/board.c
@@ -0,0 +1,266 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#include "hal.h"
+#include "stm32_gpio.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of STM32 GPIO port setup.
+ */
+typedef struct {
+ uint32_t moder;
+ uint32_t otyper;
+ uint32_t ospeedr;
+ uint32_t pupdr;
+ uint32_t odr;
+ uint32_t afrl;
+ uint32_t afrh;
+} gpio_setup_t;
+
+/**
+ * @brief Type of STM32 GPIO initialization data.
+ */
+typedef struct {
+#if STM32_HAS_GPIOA || defined(__DOXYGEN__)
+ gpio_setup_t PAData;
+#endif
+#if STM32_HAS_GPIOB || defined(__DOXYGEN__)
+ gpio_setup_t PBData;
+#endif
+#if STM32_HAS_GPIOC || defined(__DOXYGEN__)
+ gpio_setup_t PCData;
+#endif
+#if STM32_HAS_GPIOD || defined(__DOXYGEN__)
+ gpio_setup_t PDData;
+#endif
+#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
+ gpio_setup_t PEData;
+#endif
+#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
+ gpio_setup_t PFData;
+#endif
+#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
+ gpio_setup_t PGData;
+#endif
+#if STM32_HAS_GPIOH || defined(__DOXYGEN__)
+ gpio_setup_t PHData;
+#endif
+#if STM32_HAS_GPIOI || defined(__DOXYGEN__)
+ gpio_setup_t PIData;
+#endif
+#if STM32_HAS_GPIOJ || defined(__DOXYGEN__)
+ gpio_setup_t PJData;
+#endif
+#if STM32_HAS_GPIOK || defined(__DOXYGEN__)
+ gpio_setup_t PKData;
+#endif
+} gpio_config_t;
+
+/**
+ * @brief STM32 GPIO static initialization data.
+ */
+static const gpio_config_t gpio_default_config = {
+#if STM32_HAS_GPIOA
+ {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
+ VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH},
+#endif
+#if STM32_HAS_GPIOB
+ {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR,
+ VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH},
+#endif
+#if STM32_HAS_GPIOC
+ {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR,
+ VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH},
+#endif
+#if STM32_HAS_GPIOD
+ {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR,
+ VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH},
+#endif
+#if STM32_HAS_GPIOE
+ {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR,
+ VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH},
+#endif
+#if STM32_HAS_GPIOF
+ {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR,
+ VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH},
+#endif
+#if STM32_HAS_GPIOG
+ {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR,
+ VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH},
+#endif
+#if STM32_HAS_GPIOH
+ {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR,
+ VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH},
+#endif
+#if STM32_HAS_GPIOI
+ {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
+ VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH},
+#endif
+#if STM32_HAS_GPIOJ
+ {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR,
+ VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH},
+#endif
+#if STM32_HAS_GPIOK
+ {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR,
+ VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH}
+#endif
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) {
+
+ gpiop->OTYPER = config->otyper;
+ gpiop->OSPEEDR = config->ospeedr;
+ gpiop->PUPDR = config->pupdr;
+ gpiop->ODR = config->odr;
+ gpiop->AFRL = config->afrl;
+ gpiop->AFRH = config->afrh;
+ gpiop->MODER = config->moder;
+}
+
+static void stm32_gpio_init(void) {
+
+ /* Enabling GPIO-related clocks, the mask comes from the
+ registry header file.*/
+ rccResetIOP(STM32_GPIO_EN_MASK);
+ rccEnableIOP(STM32_GPIO_EN_MASK, true);
+
+ /* Initializing all the defined GPIO ports.*/
+#if STM32_HAS_GPIOA
+ gpio_init(GPIOA, &gpio_default_config.PAData);
+#endif
+#if STM32_HAS_GPIOB
+ gpio_init(GPIOB, &gpio_default_config.PBData);
+#endif
+#if STM32_HAS_GPIOC
+ gpio_init(GPIOC, &gpio_default_config.PCData);
+#endif
+#if STM32_HAS_GPIOD
+ gpio_init(GPIOD, &gpio_default_config.PDData);
+#endif
+#if STM32_HAS_GPIOE
+ gpio_init(GPIOE, &gpio_default_config.PEData);
+#endif
+#if STM32_HAS_GPIOF
+ gpio_init(GPIOF, &gpio_default_config.PFData);
+#endif
+#if STM32_HAS_GPIOG
+ gpio_init(GPIOG, &gpio_default_config.PGData);
+#endif
+#if STM32_HAS_GPIOH
+ gpio_init(GPIOH, &gpio_default_config.PHData);
+#endif
+#if STM32_HAS_GPIOI
+ gpio_init(GPIOI, &gpio_default_config.PIData);
+#endif
+#if STM32_HAS_GPIOJ
+ gpio_init(GPIOJ, &gpio_default_config.PJData);
+#endif
+#if STM32_HAS_GPIOK
+ gpio_init(GPIOK, &gpio_default_config.PKData);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Early initialization code.
+ * @details GPIO ports and system clocks are initialized before everything
+ * else.
+ */
+void __early_init(void) {
+
+ stm32_gpio_init();
+ stm32_clock_init();
+}
+
+#if HAL_USE_SDC || defined(__DOXYGEN__)
+/**
+ * @brief SDC card detection.
+ */
+bool sdc_lld_is_card_inserted(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief SDC card write protection detection.
+ */
+bool sdc_lld_is_write_protected(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif /* HAL_USE_SDC */
+
+#if HAL_USE_MMC_SPI || defined(__DOXYGEN__)
+/**
+ * @brief MMC_SPI card detection.
+ */
+bool mmc_lld_is_card_inserted(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief MMC_SPI card write protection detection.
+ */
+bool mmc_lld_is_write_protected(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif
+
+/**
+ * @brief Board-specific initialization code.
+ * @note You can add your board-specific code here.
+ */
+void boardInit(void) {
+
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L053R8/board.h b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L053R8/board.h
new file mode 100644
index 0000000..dc3fe15
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L053R8/board.h
@@ -0,0 +1,837 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#ifndef BOARD_H
+#define BOARD_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*
+ * Setup for STMicroelectronics STM32 Nucleo64-L053R8 board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_ST_NUCLEO64_L053R8
+#define BOARD_NAME "STMicroelectronics STM32 Nucleo64-L053R8"
+
+/*
+ * Board oscillators-related settings.
+ */
+#if !defined(STM32_LSECLK)
+#define STM32_LSECLK 32768U
+#endif
+
+#define STM32_LSEDRV (3U << 11U)
+
+#if !defined(STM32_HSECLK)
+#define STM32_HSECLK 8000000U
+#endif
+
+#define STM32_HSE_BYPASS
+
+/*
+ * MCU type as defined in the ST header.
+ */
+#define STM32L053xx
+
+/*
+ * IO pins assignments.
+ */
+#define GPIOA_ARD_A0 0U
+#define GPIOA_ACD1_IN0 0U
+#define GPIOA_ARD_A1 1U
+#define GPIOA_ACD1_IN1 1U
+#define GPIOA_ARD_D1 2U
+#define GPIOA_USART2_TX 2U
+#define GPIOA_ARD_D0 3U
+#define GPIOA_USART2_RX 3U
+#define GPIOA_ARD_A2 4U
+#define GPIOA_ACD1_IN4 4U
+#define GPIOA_LED_GREEN 5U
+#define GPIOA_ARD_D13 5U
+#define GPIOA_ARD_D12 6U
+#define GPIOA_ARD_D11 7U
+#define GPIOA_ARD_D7 8U
+#define GPIOA_ARD_D8 9U
+#define GPIOA_ARD_D2 10U
+#define GPIOA_PIN11 11U
+#define GPIOA_PIN12 12U
+#define GPIOA_SWDIO 13U
+#define GPIOA_SWCLK 14U
+#define GPIOA_PIN15 15U
+
+#define GPIOB_ARD_A3 0U
+#define GPIOB_ACD1_IN8 0U
+#define GPIOB_PIN1 1U
+#define GPIOB_PIN2 2U
+#define GPIOB_SWO 3U
+#define GPIOB_ARD_D3 3U
+#define GPIOB_ARD_D5 4U
+#define GPIOB_ARD_D4 5U
+#define GPIOB_ARD_D10 6U
+#define GPIOB_PIN7 7U
+#define GPIOB_ARD_D15 8U
+#define GPIOB_ARD_D14 9U
+#define GPIOB_ARD_D6 10U
+#define GPIOB_PIN11 11U
+#define GPIOB_PIN12 12U
+#define GPIOB_PIN13 13U
+#define GPIOB_PIN14 14U
+#define GPIOB_PIN15 15U
+
+#define GPIOC_ARD_A5 0U
+#define GPIOC_ACD1_IN10 0U
+#define GPIOC_ARD_A4 1U
+#define GPIOC_ACD1_IN11 1U
+#define GPIOC_PIN2 2U
+#define GPIOC_PIN3 3U
+#define GPIOC_PIN4 4U
+#define GPIOC_PIN5 5U
+#define GPIOC_PIN6 6U
+#define GPIOC_ARD_D9 7U
+#define GPIOC_PIN8 8U
+#define GPIOC_PIN9 9U
+#define GPIOC_PIN10 10U
+#define GPIOC_PIN11 11U
+#define GPIOC_PIN12 12U
+#define GPIOC_BUTTON 13U
+#define GPIOC_OSC32_IN 14U
+#define GPIOC_OSC32_OUT 15U
+
+#define GPIOD_PIN0 0U
+#define GPIOD_PIN1 1U
+#define GPIOD_PIN2 2U
+#define GPIOD_PIN3 3U
+#define GPIOD_PIN4 4U
+#define GPIOD_PIN5 5U
+#define GPIOD_PIN6 6U
+#define GPIOD_PIN7 7U
+#define GPIOD_PIN8 8U
+#define GPIOD_PIN9 9U
+#define GPIOD_PIN10 10U
+#define GPIOD_PIN11 11U
+#define GPIOD_PIN12 12U
+#define GPIOD_PIN13 13U
+#define GPIOD_PIN14 14U
+#define GPIOD_PIN15 15U
+
+#define GPIOH_OSC_IN 0U
+#define GPIOH_OSC_OUT 1U
+#define GPIOH_PIN2 2U
+#define GPIOH_PIN3 3U
+#define GPIOH_PIN4 4U
+#define GPIOH_PIN5 5U
+#define GPIOH_PIN6 6U
+#define GPIOH_PIN7 7U
+#define GPIOH_PIN8 8U
+#define GPIOH_PIN9 9U
+#define GPIOH_PIN10 10U
+#define GPIOH_PIN11 11U
+#define GPIOH_PIN12 12U
+#define GPIOH_PIN13 13U
+#define GPIOH_PIN14 14U
+#define GPIOH_PIN15 15U
+
+/*
+ * IO lines assignments.
+ */
+#define LINE_ARD_A0 PAL_LINE(GPIOA, 0U)
+#define LINE_ACD1_IN0 PAL_LINE(GPIOA, 0U)
+#define LINE_ARD_A1 PAL_LINE(GPIOA, 1U)
+#define LINE_ACD1_IN1 PAL_LINE(GPIOA, 1U)
+#define LINE_ARD_D1 PAL_LINE(GPIOA, 2U)
+#define LINE_USART2_TX PAL_LINE(GPIOA, 2U)
+#define LINE_ARD_D0 PAL_LINE(GPIOA, 3U)
+#define LINE_USART2_RX PAL_LINE(GPIOA, 3U)
+#define LINE_ARD_A2 PAL_LINE(GPIOA, 4U)
+#define LINE_ACD1_IN4 PAL_LINE(GPIOA, 4U)
+#define LINE_LED_GREEN PAL_LINE(GPIOA, 5U)
+#define LINE_ARD_D13 PAL_LINE(GPIOA, 5U)
+#define LINE_ARD_D12 PAL_LINE(GPIOA, 6U)
+#define LINE_ARD_D11 PAL_LINE(GPIOA, 7U)
+#define LINE_ARD_D7 PAL_LINE(GPIOA, 8U)
+#define LINE_ARD_D8 PAL_LINE(GPIOA, 9U)
+#define LINE_ARD_D2 PAL_LINE(GPIOA, 10U)
+#define LINE_SWDIO PAL_LINE(GPIOA, 13U)
+#define LINE_SWCLK PAL_LINE(GPIOA, 14U)
+#define LINE_ARD_A3 PAL_LINE(GPIOB, 0U)
+#define LINE_ACD1_IN8 PAL_LINE(GPIOB, 0U)
+#define LINE_SWO PAL_LINE(GPIOB, 3U)
+#define LINE_ARD_D3 PAL_LINE(GPIOB, 3U)
+#define LINE_ARD_D5 PAL_LINE(GPIOB, 4U)
+#define LINE_ARD_D4 PAL_LINE(GPIOB, 5U)
+#define LINE_ARD_D10 PAL_LINE(GPIOB, 6U)
+#define LINE_ARD_D15 PAL_LINE(GPIOB, 8U)
+#define LINE_ARD_D14 PAL_LINE(GPIOB, 9U)
+#define LINE_ARD_D6 PAL_LINE(GPIOB, 10U)
+#define LINE_ARD_A5 PAL_LINE(GPIOC, 0U)
+#define LINE_ACD1_IN10 PAL_LINE(GPIOC, 0U)
+#define LINE_ARD_A4 PAL_LINE(GPIOC, 1U)
+#define LINE_ACD1_IN11 PAL_LINE(GPIOC, 1U)
+#define LINE_ARD_D9 PAL_LINE(GPIOC, 7U)
+#define LINE_BUTTON PAL_LINE(GPIOC, 13U)
+#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U)
+#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U)
+#define LINE_OSC_IN PAL_LINE(GPIOH, 0U)
+#define LINE_OSC_OUT PAL_LINE(GPIOH, 1U)
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*
+ * I/O ports initial setup, this configuration is established soon after reset
+ * in the initialization code.
+ * Please refer to the STM32 Reference Manual for details.
+ */
+#define PIN_MODE_INPUT(n) (0U << ((n) * 2U))
+#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U))
+#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U))
+#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U))
+#define PIN_ODR_LOW(n) (0U << (n))
+#define PIN_ODR_HIGH(n) (1U << (n))
+#define PIN_OTYPE_PUSHPULL(n) (0U << (n))
+#define PIN_OTYPE_OPENDRAIN(n) (1U << (n))
+#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U))
+#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U))
+#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U))
+#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U))
+#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U))
+#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U))
+#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U))
+#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U))
+
+/*
+ * GPIOA setup:
+ *
+ * PA0 - ARD_A0 ACD1_IN0 (input pullup).
+ * PA1 - ARD_A1 ACD1_IN1 (input pullup).
+ * PA2 - ARD_D1 USART2_TX (alternate 4).
+ * PA3 - ARD_D0 USART2_RX (alternate 4).
+ * PA4 - ARD_A2 ACD1_IN4 (input pullup).
+ * PA5 - LED_GREEN ARD_D13 (output pushpull maximum).
+ * PA6 - ARD_D12 (input pullup).
+ * PA7 - ARD_D11 (input pullup).
+ * PA8 - ARD_D7 (input pullup).
+ * PA9 - ARD_D8 (input pullup).
+ * PA10 - ARD_D2 (input pullup).
+ * PA11 - PIN11 (input pullup).
+ * PA12 - PIN12 (input pullup).
+ * PA13 - SWDIO (alternate 0).
+ * PA14 - SWCLK (alternate 0).
+ * PA15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_ARD_A0) | \
+ PIN_MODE_INPUT(GPIOA_ARD_A1) | \
+ PIN_MODE_ALTERNATE(GPIOA_ARD_D1) | \
+ PIN_MODE_ALTERNATE(GPIOA_ARD_D0) | \
+ PIN_MODE_INPUT(GPIOA_ARD_A2) | \
+ PIN_MODE_OUTPUT(GPIOA_LED_GREEN) | \
+ PIN_MODE_INPUT(GPIOA_ARD_D12) | \
+ PIN_MODE_INPUT(GPIOA_ARD_D11) | \
+ PIN_MODE_INPUT(GPIOA_ARD_D7) | \
+ PIN_MODE_INPUT(GPIOA_ARD_D8) | \
+ PIN_MODE_INPUT(GPIOA_ARD_D2) | \
+ PIN_MODE_INPUT(GPIOA_PIN11) | \
+ PIN_MODE_INPUT(GPIOA_PIN12) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \
+ PIN_MODE_INPUT(GPIOA_PIN15))
+#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_ARD_A0) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_A1) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D1) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D0) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_A2) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_LED_GREEN) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D12) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D11) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D7) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D8) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D2) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN15))
+#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_HIGH(GPIOA_ARD_A0) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_A1) | \
+ PIN_OSPEED_MEDIUM(GPIOA_ARD_D1) | \
+ PIN_OSPEED_MEDIUM(GPIOA_ARD_D0) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_A2) | \
+ PIN_OSPEED_HIGH(GPIOA_LED_GREEN) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D12) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D11) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D7) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D8) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D2) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOA_SWDIO) | \
+ PIN_OSPEED_HIGH(GPIOA_SWCLK) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN15))
+#define VAL_GPIOA_PUPDR (PIN_PUPDR_PULLUP(GPIOA_ARD_A0) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_A1) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D1) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D0) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_A2) | \
+ PIN_PUPDR_FLOATING(GPIOA_LED_GREEN) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_D12) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_D11) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_D7) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_D8) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_D2) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOA_SWDIO) | \
+ PIN_PUPDR_PULLDOWN(GPIOA_SWCLK) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN15))
+#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_ARD_A0) | \
+ PIN_ODR_HIGH(GPIOA_ARD_A1) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D1) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D0) | \
+ PIN_ODR_HIGH(GPIOA_ARD_A2) | \
+ PIN_ODR_LOW(GPIOA_LED_GREEN) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D12) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D11) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D7) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D8) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D2) | \
+ PIN_ODR_HIGH(GPIOA_PIN11) | \
+ PIN_ODR_HIGH(GPIOA_PIN12) | \
+ PIN_ODR_HIGH(GPIOA_SWDIO) | \
+ PIN_ODR_HIGH(GPIOA_SWCLK) | \
+ PIN_ODR_HIGH(GPIOA_PIN15))
+#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_ARD_A0, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_A1, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D1, 4U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D0, 4U) | \
+ PIN_AFIO_AF(GPIOA_ARD_A2, 0U) | \
+ PIN_AFIO_AF(GPIOA_LED_GREEN, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D12, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D11, 0U))
+#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_ARD_D7, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D8, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D2, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOA_SWDIO, 0U) | \
+ PIN_AFIO_AF(GPIOA_SWCLK, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN15, 0U))
+
+/*
+ * GPIOB setup:
+ *
+ * PB0 - ARD_A3 ACD1_IN8 (input pullup).
+ * PB1 - PIN1 (input pullup).
+ * PB2 - PIN2 (input pullup).
+ * PB3 - SWO ARD_D3 (alternate 0).
+ * PB4 - ARD_D5 (input pullup).
+ * PB5 - ARD_D4 (input pullup).
+ * PB6 - ARD_D10 (input pullup).
+ * PB7 - PIN7 (input pullup).
+ * PB8 - ARD_D15 (input pullup).
+ * PB9 - ARD_D14 (input pullup).
+ * PB10 - ARD_D6 (input pullup).
+ * PB11 - PIN11 (input pullup).
+ * PB12 - PIN12 (input pullup).
+ * PB13 - PIN13 (input pullup).
+ * PB14 - PIN14 (input pullup).
+ * PB15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOB_MODER (PIN_MODE_INPUT(GPIOB_ARD_A3) | \
+ PIN_MODE_INPUT(GPIOB_PIN1) | \
+ PIN_MODE_INPUT(GPIOB_PIN2) | \
+ PIN_MODE_ALTERNATE(GPIOB_SWO) | \
+ PIN_MODE_INPUT(GPIOB_ARD_D5) | \
+ PIN_MODE_INPUT(GPIOB_ARD_D4) | \
+ PIN_MODE_INPUT(GPIOB_ARD_D10) | \
+ PIN_MODE_INPUT(GPIOB_PIN7) | \
+ PIN_MODE_INPUT(GPIOB_ARD_D15) | \
+ PIN_MODE_INPUT(GPIOB_ARD_D14) | \
+ PIN_MODE_INPUT(GPIOB_ARD_D6) | \
+ PIN_MODE_INPUT(GPIOB_PIN11) | \
+ PIN_MODE_INPUT(GPIOB_PIN12) | \
+ PIN_MODE_INPUT(GPIOB_PIN13) | \
+ PIN_MODE_INPUT(GPIOB_PIN14) | \
+ PIN_MODE_INPUT(GPIOB_PIN15))
+#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_ARD_A3) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_SWO) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D5) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D4) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D10) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D15) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D14) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D6) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN15))
+#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_ARD_A3) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN1) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOB_SWO) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D5) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D4) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D10) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D15) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D14) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D6) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN15))
+#define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(GPIOB_ARD_A3) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOB_SWO) | \
+ PIN_PUPDR_PULLUP(GPIOB_ARD_D5) | \
+ PIN_PUPDR_PULLUP(GPIOB_ARD_D4) | \
+ PIN_PUPDR_PULLUP(GPIOB_ARD_D10) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOB_ARD_D15) | \
+ PIN_PUPDR_PULLUP(GPIOB_ARD_D14) | \
+ PIN_PUPDR_PULLUP(GPIOB_ARD_D6) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN15))
+#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_ARD_A3) | \
+ PIN_ODR_HIGH(GPIOB_PIN1) | \
+ PIN_ODR_HIGH(GPIOB_PIN2) | \
+ PIN_ODR_HIGH(GPIOB_SWO) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D5) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D4) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D10) | \
+ PIN_ODR_HIGH(GPIOB_PIN7) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D15) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D14) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D6) | \
+ PIN_ODR_HIGH(GPIOB_PIN11) | \
+ PIN_ODR_HIGH(GPIOB_PIN12) | \
+ PIN_ODR_HIGH(GPIOB_PIN13) | \
+ PIN_ODR_HIGH(GPIOB_PIN14) | \
+ PIN_ODR_HIGH(GPIOB_PIN15))
+#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_ARD_A3, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOB_SWO, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D5, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D4, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D10, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN7, 0U))
+#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_ARD_D15, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D14, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D6, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN15, 0U))
+
+/*
+ * GPIOC setup:
+ *
+ * PC0 - ARD_A5 ACD1_IN10 (input pullup).
+ * PC1 - ARD_A4 ACD1_IN11 (input pullup).
+ * PC2 - PIN2 (input pullup).
+ * PC3 - PIN3 (input pullup).
+ * PC4 - PIN4 (input pullup).
+ * PC5 - PIN5 (input pullup).
+ * PC6 - PIN6 (input pullup).
+ * PC7 - ARD_D9 (input pullup).
+ * PC8 - PIN8 (input pullup).
+ * PC9 - PIN9 (input pullup).
+ * PC10 - PIN10 (input pullup).
+ * PC11 - PIN11 (input pullup).
+ * PC12 - PIN12 (input pullup).
+ * PC13 - BUTTON (input floating).
+ * PC14 - OSC32_IN (input floating).
+ * PC15 - OSC32_OUT (input floating).
+ */
+#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_ARD_A5) | \
+ PIN_MODE_INPUT(GPIOC_ARD_A4) | \
+ PIN_MODE_INPUT(GPIOC_PIN2) | \
+ PIN_MODE_INPUT(GPIOC_PIN3) | \
+ PIN_MODE_INPUT(GPIOC_PIN4) | \
+ PIN_MODE_INPUT(GPIOC_PIN5) | \
+ PIN_MODE_INPUT(GPIOC_PIN6) | \
+ PIN_MODE_INPUT(GPIOC_ARD_D9) | \
+ PIN_MODE_INPUT(GPIOC_PIN8) | \
+ PIN_MODE_INPUT(GPIOC_PIN9) | \
+ PIN_MODE_INPUT(GPIOC_PIN10) | \
+ PIN_MODE_INPUT(GPIOC_PIN11) | \
+ PIN_MODE_INPUT(GPIOC_PIN12) | \
+ PIN_MODE_INPUT(GPIOC_BUTTON) | \
+ PIN_MODE_INPUT(GPIOC_OSC32_IN) | \
+ PIN_MODE_INPUT(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_ARD_A5) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_ARD_A4) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_ARD_D9) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_BUTTON) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_ARD_A5) | \
+ PIN_OSPEED_HIGH(GPIOC_ARD_A4) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOC_ARD_D9) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOC_BUTTON) | \
+ PIN_OSPEED_HIGH(GPIOC_OSC32_IN) | \
+ PIN_OSPEED_HIGH(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_ARD_A5) | \
+ PIN_PUPDR_PULLUP(GPIOC_ARD_A4) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOC_ARD_D9) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOC_BUTTON) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_ARD_A5) | \
+ PIN_ODR_HIGH(GPIOC_ARD_A4) | \
+ PIN_ODR_HIGH(GPIOC_PIN2) | \
+ PIN_ODR_HIGH(GPIOC_PIN3) | \
+ PIN_ODR_HIGH(GPIOC_PIN4) | \
+ PIN_ODR_HIGH(GPIOC_PIN5) | \
+ PIN_ODR_HIGH(GPIOC_PIN6) | \
+ PIN_ODR_HIGH(GPIOC_ARD_D9) | \
+ PIN_ODR_HIGH(GPIOC_PIN8) | \
+ PIN_ODR_HIGH(GPIOC_PIN9) | \
+ PIN_ODR_HIGH(GPIOC_PIN10) | \
+ PIN_ODR_HIGH(GPIOC_PIN11) | \
+ PIN_ODR_HIGH(GPIOC_PIN12) | \
+ PIN_ODR_HIGH(GPIOC_BUTTON) | \
+ PIN_ODR_HIGH(GPIOC_OSC32_IN) | \
+ PIN_ODR_HIGH(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_ARD_A5, 0U) | \
+ PIN_AFIO_AF(GPIOC_ARD_A4, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOC_ARD_D9, 0U))
+#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOC_BUTTON, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U))
+
+/*
+ * GPIOD setup:
+ *
+ * PD0 - PIN0 (input pullup).
+ * PD1 - PIN1 (input pullup).
+ * PD2 - PIN2 (input pullup).
+ * PD3 - PIN3 (input pullup).
+ * PD4 - PIN4 (input pullup).
+ * PD5 - PIN5 (input pullup).
+ * PD6 - PIN6 (input pullup).
+ * PD7 - PIN7 (input pullup).
+ * PD8 - PIN8 (input pullup).
+ * PD9 - PIN9 (input pullup).
+ * PD10 - PIN10 (input pullup).
+ * PD11 - PIN11 (input pullup).
+ * PD12 - PIN12 (input pullup).
+ * PD13 - PIN13 (input pullup).
+ * PD14 - PIN14 (input pullup).
+ * PD15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | \
+ PIN_MODE_INPUT(GPIOD_PIN1) | \
+ PIN_MODE_INPUT(GPIOD_PIN2) | \
+ PIN_MODE_INPUT(GPIOD_PIN3) | \
+ PIN_MODE_INPUT(GPIOD_PIN4) | \
+ PIN_MODE_INPUT(GPIOD_PIN5) | \
+ PIN_MODE_INPUT(GPIOD_PIN6) | \
+ PIN_MODE_INPUT(GPIOD_PIN7) | \
+ PIN_MODE_INPUT(GPIOD_PIN8) | \
+ PIN_MODE_INPUT(GPIOD_PIN9) | \
+ PIN_MODE_INPUT(GPIOD_PIN10) | \
+ PIN_MODE_INPUT(GPIOD_PIN11) | \
+ PIN_MODE_INPUT(GPIOD_PIN12) | \
+ PIN_MODE_INPUT(GPIOD_PIN13) | \
+ PIN_MODE_INPUT(GPIOD_PIN14) | \
+ PIN_MODE_INPUT(GPIOD_PIN15))
+#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN15))
+#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_HIGH(GPIOD_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN1) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN15))
+#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN15))
+#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \
+ PIN_ODR_HIGH(GPIOD_PIN1) | \
+ PIN_ODR_HIGH(GPIOD_PIN2) | \
+ PIN_ODR_HIGH(GPIOD_PIN3) | \
+ PIN_ODR_HIGH(GPIOD_PIN4) | \
+ PIN_ODR_HIGH(GPIOD_PIN5) | \
+ PIN_ODR_HIGH(GPIOD_PIN6) | \
+ PIN_ODR_HIGH(GPIOD_PIN7) | \
+ PIN_ODR_HIGH(GPIOD_PIN8) | \
+ PIN_ODR_HIGH(GPIOD_PIN9) | \
+ PIN_ODR_HIGH(GPIOD_PIN10) | \
+ PIN_ODR_HIGH(GPIOD_PIN11) | \
+ PIN_ODR_HIGH(GPIOD_PIN12) | \
+ PIN_ODR_HIGH(GPIOD_PIN13) | \
+ PIN_ODR_HIGH(GPIOD_PIN14) | \
+ PIN_ODR_HIGH(GPIOD_PIN15))
+#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN7, 0U))
+#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN15, 0U))
+
+/*
+ * GPIOH setup:
+ *
+ * PH0 - OSC_IN (input floating).
+ * PH1 - OSC_OUT (input floating).
+ * PH2 - PIN2 (input pullup).
+ * PH3 - PIN3 (input pullup).
+ * PH4 - PIN4 (input pullup).
+ * PH5 - PIN5 (input pullup).
+ * PH6 - PIN6 (input pullup).
+ * PH7 - PIN7 (input pullup).
+ * PH8 - PIN8 (input pullup).
+ * PH9 - PIN9 (input pullup).
+ * PH10 - PIN10 (input pullup).
+ * PH11 - PIN11 (input pullup).
+ * PH12 - PIN12 (input pullup).
+ * PH13 - PIN13 (input pullup).
+ * PH14 - PIN14 (input pullup).
+ * PH15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_OSC_IN) | \
+ PIN_MODE_INPUT(GPIOH_OSC_OUT) | \
+ PIN_MODE_INPUT(GPIOH_PIN2) | \
+ PIN_MODE_INPUT(GPIOH_PIN3) | \
+ PIN_MODE_INPUT(GPIOH_PIN4) | \
+ PIN_MODE_INPUT(GPIOH_PIN5) | \
+ PIN_MODE_INPUT(GPIOH_PIN6) | \
+ PIN_MODE_INPUT(GPIOH_PIN7) | \
+ PIN_MODE_INPUT(GPIOH_PIN8) | \
+ PIN_MODE_INPUT(GPIOH_PIN9) | \
+ PIN_MODE_INPUT(GPIOH_PIN10) | \
+ PIN_MODE_INPUT(GPIOH_PIN11) | \
+ PIN_MODE_INPUT(GPIOH_PIN12) | \
+ PIN_MODE_INPUT(GPIOH_PIN13) | \
+ PIN_MODE_INPUT(GPIOH_PIN14) | \
+ PIN_MODE_INPUT(GPIOH_PIN15))
+#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_OSC_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_OSC_OUT) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN15))
+#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_HIGH(GPIOH_OSC_IN) | \
+ PIN_OSPEED_HIGH(GPIOH_OSC_OUT) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN15))
+#define VAL_GPIOH_PUPDR (PIN_PUPDR_FLOATING(GPIOH_OSC_IN) | \
+ PIN_PUPDR_FLOATING(GPIOH_OSC_OUT) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN15))
+#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_OSC_IN) | \
+ PIN_ODR_HIGH(GPIOH_OSC_OUT) | \
+ PIN_ODR_HIGH(GPIOH_PIN2) | \
+ PIN_ODR_HIGH(GPIOH_PIN3) | \
+ PIN_ODR_HIGH(GPIOH_PIN4) | \
+ PIN_ODR_HIGH(GPIOH_PIN5) | \
+ PIN_ODR_HIGH(GPIOH_PIN6) | \
+ PIN_ODR_HIGH(GPIOH_PIN7) | \
+ PIN_ODR_HIGH(GPIOH_PIN8) | \
+ PIN_ODR_HIGH(GPIOH_PIN9) | \
+ PIN_ODR_HIGH(GPIOH_PIN10) | \
+ PIN_ODR_HIGH(GPIOH_PIN11) | \
+ PIN_ODR_HIGH(GPIOH_PIN12) | \
+ PIN_ODR_HIGH(GPIOH_PIN13) | \
+ PIN_ODR_HIGH(GPIOH_PIN14) | \
+ PIN_ODR_HIGH(GPIOH_PIN15))
+#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_OSC_IN, 0U) | \
+ PIN_AFIO_AF(GPIOH_OSC_OUT, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN7, 0U))
+#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN15, 0U))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* BOARD_H */
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L053R8/board.mk b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L053R8/board.mk
new file mode 100644
index 0000000..2a8d78c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L053R8/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_L053R8/board.c
+
+# Required include directories
+BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_L053R8
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC += $(BOARDINC)
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L053R8/cfg/board.chcfg b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L053R8/cfg/board.chcfg
new file mode 100644
index 0000000..4a3bfc4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L053R8/cfg/board.chcfg
@@ -0,0 +1,669 @@
+
+
+
+
+ resources/gencfg/processors/boards/stm32l0xx/templates
+ ..
+ 5.0.x
+
+ STMicroelectronics STM32 Nucleo64-L053R8
+ ST_NUCLEO64_L053R8
+
+ STM32L053xx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L053R8/cfg/board.fmpp b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L053R8/cfg/board.fmpp
new file mode 100644
index 0000000..b3ba947
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L053R8/cfg/board.fmpp
@@ -0,0 +1,15 @@
+sourceRoot: ../../../../../tools/ftl/processors/boards/stm32l0xx/templates
+outputRoot: ..
+dataRoot: .
+
+freemarkerLinks: {
+ lib: ../../../../../tools/ftl/libs
+}
+
+data : {
+ doc1:xml (
+ board.chcfg
+ {
+ }
+ )
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L073RZ/board.c b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L073RZ/board.c
new file mode 100644
index 0000000..fbea4c4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L073RZ/board.c
@@ -0,0 +1,266 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#include "hal.h"
+#include "stm32_gpio.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of STM32 GPIO port setup.
+ */
+typedef struct {
+ uint32_t moder;
+ uint32_t otyper;
+ uint32_t ospeedr;
+ uint32_t pupdr;
+ uint32_t odr;
+ uint32_t afrl;
+ uint32_t afrh;
+} gpio_setup_t;
+
+/**
+ * @brief Type of STM32 GPIO initialization data.
+ */
+typedef struct {
+#if STM32_HAS_GPIOA || defined(__DOXYGEN__)
+ gpio_setup_t PAData;
+#endif
+#if STM32_HAS_GPIOB || defined(__DOXYGEN__)
+ gpio_setup_t PBData;
+#endif
+#if STM32_HAS_GPIOC || defined(__DOXYGEN__)
+ gpio_setup_t PCData;
+#endif
+#if STM32_HAS_GPIOD || defined(__DOXYGEN__)
+ gpio_setup_t PDData;
+#endif
+#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
+ gpio_setup_t PEData;
+#endif
+#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
+ gpio_setup_t PFData;
+#endif
+#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
+ gpio_setup_t PGData;
+#endif
+#if STM32_HAS_GPIOH || defined(__DOXYGEN__)
+ gpio_setup_t PHData;
+#endif
+#if STM32_HAS_GPIOI || defined(__DOXYGEN__)
+ gpio_setup_t PIData;
+#endif
+#if STM32_HAS_GPIOJ || defined(__DOXYGEN__)
+ gpio_setup_t PJData;
+#endif
+#if STM32_HAS_GPIOK || defined(__DOXYGEN__)
+ gpio_setup_t PKData;
+#endif
+} gpio_config_t;
+
+/**
+ * @brief STM32 GPIO static initialization data.
+ */
+static const gpio_config_t gpio_default_config = {
+#if STM32_HAS_GPIOA
+ {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
+ VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH},
+#endif
+#if STM32_HAS_GPIOB
+ {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR,
+ VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH},
+#endif
+#if STM32_HAS_GPIOC
+ {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR,
+ VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH},
+#endif
+#if STM32_HAS_GPIOD
+ {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR,
+ VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH},
+#endif
+#if STM32_HAS_GPIOE
+ {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR,
+ VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH},
+#endif
+#if STM32_HAS_GPIOF
+ {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR,
+ VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH},
+#endif
+#if STM32_HAS_GPIOG
+ {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR,
+ VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH},
+#endif
+#if STM32_HAS_GPIOH
+ {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR,
+ VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH},
+#endif
+#if STM32_HAS_GPIOI
+ {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
+ VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH},
+#endif
+#if STM32_HAS_GPIOJ
+ {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR,
+ VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH},
+#endif
+#if STM32_HAS_GPIOK
+ {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR,
+ VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH}
+#endif
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) {
+
+ gpiop->OTYPER = config->otyper;
+ gpiop->OSPEEDR = config->ospeedr;
+ gpiop->PUPDR = config->pupdr;
+ gpiop->ODR = config->odr;
+ gpiop->AFRL = config->afrl;
+ gpiop->AFRH = config->afrh;
+ gpiop->MODER = config->moder;
+}
+
+static void stm32_gpio_init(void) {
+
+ /* Enabling GPIO-related clocks, the mask comes from the
+ registry header file.*/
+ rccResetIOP(STM32_GPIO_EN_MASK);
+ rccEnableIOP(STM32_GPIO_EN_MASK, true);
+
+ /* Initializing all the defined GPIO ports.*/
+#if STM32_HAS_GPIOA
+ gpio_init(GPIOA, &gpio_default_config.PAData);
+#endif
+#if STM32_HAS_GPIOB
+ gpio_init(GPIOB, &gpio_default_config.PBData);
+#endif
+#if STM32_HAS_GPIOC
+ gpio_init(GPIOC, &gpio_default_config.PCData);
+#endif
+#if STM32_HAS_GPIOD
+ gpio_init(GPIOD, &gpio_default_config.PDData);
+#endif
+#if STM32_HAS_GPIOE
+ gpio_init(GPIOE, &gpio_default_config.PEData);
+#endif
+#if STM32_HAS_GPIOF
+ gpio_init(GPIOF, &gpio_default_config.PFData);
+#endif
+#if STM32_HAS_GPIOG
+ gpio_init(GPIOG, &gpio_default_config.PGData);
+#endif
+#if STM32_HAS_GPIOH
+ gpio_init(GPIOH, &gpio_default_config.PHData);
+#endif
+#if STM32_HAS_GPIOI
+ gpio_init(GPIOI, &gpio_default_config.PIData);
+#endif
+#if STM32_HAS_GPIOJ
+ gpio_init(GPIOJ, &gpio_default_config.PJData);
+#endif
+#if STM32_HAS_GPIOK
+ gpio_init(GPIOK, &gpio_default_config.PKData);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Early initialization code.
+ * @details GPIO ports and system clocks are initialized before everything
+ * else.
+ */
+void __early_init(void) {
+
+ stm32_gpio_init();
+ stm32_clock_init();
+}
+
+#if HAL_USE_SDC || defined(__DOXYGEN__)
+/**
+ * @brief SDC card detection.
+ */
+bool sdc_lld_is_card_inserted(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief SDC card write protection detection.
+ */
+bool sdc_lld_is_write_protected(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif /* HAL_USE_SDC */
+
+#if HAL_USE_MMC_SPI || defined(__DOXYGEN__)
+/**
+ * @brief MMC_SPI card detection.
+ */
+bool mmc_lld_is_card_inserted(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief MMC_SPI card write protection detection.
+ */
+bool mmc_lld_is_write_protected(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif
+
+/**
+ * @brief Board-specific initialization code.
+ * @note You can add your board-specific code here.
+ */
+void boardInit(void) {
+
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L073RZ/board.h b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L073RZ/board.h
new file mode 100644
index 0000000..668e727
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L073RZ/board.h
@@ -0,0 +1,971 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#ifndef BOARD_H
+#define BOARD_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*
+ * Setup for STMicroelectronics STM32 Nucleo64-L073RZ board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_ST_NUCLEO64_L073RZ
+#define BOARD_NAME "STMicroelectronics STM32 Nucleo64-L073RZ"
+
+/*
+ * Board oscillators-related settings.
+ */
+#if !defined(STM32_LSECLK)
+#define STM32_LSECLK 32768U
+#endif
+
+#define STM32_LSEDRV (3U << 11U)
+
+#if !defined(STM32_HSECLK)
+#define STM32_HSECLK 8000000U
+#endif
+
+#define STM32_HSE_BYPASS
+
+/*
+ * MCU type as defined in the ST header.
+ */
+#define STM32L073xx
+
+/*
+ * IO pins assignments.
+ */
+#define GPIOA_ARD_A0 0U
+#define GPIOA_ACD1_IN0 0U
+#define GPIOA_ARD_A1 1U
+#define GPIOA_ACD1_IN1 1U
+#define GPIOA_ARD_D1 2U
+#define GPIOA_USART2_TX 2U
+#define GPIOA_ARD_D0 3U
+#define GPIOA_USART2_RX 3U
+#define GPIOA_ARD_A2 4U
+#define GPIOA_ACD1_IN4 4U
+#define GPIOA_LED_GREEN 5U
+#define GPIOA_ARD_D13 5U
+#define GPIOA_ARD_D12 6U
+#define GPIOA_ARD_D11 7U
+#define GPIOA_ARD_D7 8U
+#define GPIOA_ARD_D8 9U
+#define GPIOA_ARD_D2 10U
+#define GPIOA_PIN11 11U
+#define GPIOA_PIN12 12U
+#define GPIOA_SWDIO 13U
+#define GPIOA_SWCLK 14U
+#define GPIOA_PIN15 15U
+
+#define GPIOB_ARD_A3 0U
+#define GPIOB_ACD1_IN8 0U
+#define GPIOB_PIN1 1U
+#define GPIOB_PIN2 2U
+#define GPIOB_SWO 3U
+#define GPIOB_ARD_D3 3U
+#define GPIOB_ARD_D5 4U
+#define GPIOB_ARD_D4 5U
+#define GPIOB_ARD_D10 6U
+#define GPIOB_PIN7 7U
+#define GPIOB_ARD_D15 8U
+#define GPIOB_ARD_D14 9U
+#define GPIOB_ARD_D6 10U
+#define GPIOB_PIN11 11U
+#define GPIOB_PIN12 12U
+#define GPIOB_PIN13 13U
+#define GPIOB_PIN14 14U
+#define GPIOB_PIN15 15U
+
+#define GPIOC_ARD_A5 0U
+#define GPIOC_ACD1_IN10 0U
+#define GPIOC_ARD_A4 1U
+#define GPIOC_ACD1_IN11 1U
+#define GPIOC_PIN2 2U
+#define GPIOC_PIN3 3U
+#define GPIOC_PIN4 4U
+#define GPIOC_PIN5 5U
+#define GPIOC_PIN6 6U
+#define GPIOC_ARD_D9 7U
+#define GPIOC_PIN8 8U
+#define GPIOC_PIN9 9U
+#define GPIOC_PIN10 10U
+#define GPIOC_PIN11 11U
+#define GPIOC_PIN12 12U
+#define GPIOC_BUTTON 13U
+#define GPIOC_OSC32_IN 14U
+#define GPIOC_OSC32_OUT 15U
+
+#define GPIOD_PIN0 0U
+#define GPIOD_PIN1 1U
+#define GPIOD_PIN2 2U
+#define GPIOD_PIN3 3U
+#define GPIOD_PIN4 4U
+#define GPIOD_PIN5 5U
+#define GPIOD_PIN6 6U
+#define GPIOD_PIN7 7U
+#define GPIOD_PIN8 8U
+#define GPIOD_PIN9 9U
+#define GPIOD_PIN10 10U
+#define GPIOD_PIN11 11U
+#define GPIOD_PIN12 12U
+#define GPIOD_PIN13 13U
+#define GPIOD_PIN14 14U
+#define GPIOD_PIN15 15U
+
+#define GPIOE_PIN0 0U
+#define GPIOE_PIN1 1U
+#define GPIOE_PIN2 2U
+#define GPIOE_PIN3 3U
+#define GPIOE_PIN4 4U
+#define GPIOE_PIN5 5U
+#define GPIOE_PIN6 6U
+#define GPIOE_PIN7 7U
+#define GPIOE_PIN8 8U
+#define GPIOE_PIN9 9U
+#define GPIOE_PIN10 10U
+#define GPIOE_PIN11 11U
+#define GPIOE_PIN12 12U
+#define GPIOE_PIN13 13U
+#define GPIOE_PIN14 14U
+#define GPIOE_PIN15 15U
+
+#define GPIOH_OSC_IN 0U
+#define GPIOH_OSC_OUT 1U
+#define GPIOH_PIN2 2U
+#define GPIOH_PIN3 3U
+#define GPIOH_PIN4 4U
+#define GPIOH_PIN5 5U
+#define GPIOH_PIN6 6U
+#define GPIOH_PIN7 7U
+#define GPIOH_PIN8 8U
+#define GPIOH_PIN9 9U
+#define GPIOH_PIN10 10U
+#define GPIOH_PIN11 11U
+#define GPIOH_PIN12 12U
+#define GPIOH_PIN13 13U
+#define GPIOH_PIN14 14U
+#define GPIOH_PIN15 15U
+
+/*
+ * IO lines assignments.
+ */
+#define LINE_ARD_A0 PAL_LINE(GPIOA, 0U)
+#define LINE_ACD1_IN0 PAL_LINE(GPIOA, 0U)
+#define LINE_ARD_A1 PAL_LINE(GPIOA, 1U)
+#define LINE_ACD1_IN1 PAL_LINE(GPIOA, 1U)
+#define LINE_ARD_D1 PAL_LINE(GPIOA, 2U)
+#define LINE_USART2_TX PAL_LINE(GPIOA, 2U)
+#define LINE_ARD_D0 PAL_LINE(GPIOA, 3U)
+#define LINE_USART2_RX PAL_LINE(GPIOA, 3U)
+#define LINE_ARD_A2 PAL_LINE(GPIOA, 4U)
+#define LINE_ACD1_IN4 PAL_LINE(GPIOA, 4U)
+#define LINE_LED_GREEN PAL_LINE(GPIOA, 5U)
+#define LINE_ARD_D13 PAL_LINE(GPIOA, 5U)
+#define LINE_ARD_D12 PAL_LINE(GPIOA, 6U)
+#define LINE_ARD_D11 PAL_LINE(GPIOA, 7U)
+#define LINE_ARD_D7 PAL_LINE(GPIOA, 8U)
+#define LINE_ARD_D8 PAL_LINE(GPIOA, 9U)
+#define LINE_ARD_D2 PAL_LINE(GPIOA, 10U)
+#define LINE_SWDIO PAL_LINE(GPIOA, 13U)
+#define LINE_SWCLK PAL_LINE(GPIOA, 14U)
+#define LINE_ARD_A3 PAL_LINE(GPIOB, 0U)
+#define LINE_ACD1_IN8 PAL_LINE(GPIOB, 0U)
+#define LINE_SWO PAL_LINE(GPIOB, 3U)
+#define LINE_ARD_D3 PAL_LINE(GPIOB, 3U)
+#define LINE_ARD_D5 PAL_LINE(GPIOB, 4U)
+#define LINE_ARD_D4 PAL_LINE(GPIOB, 5U)
+#define LINE_ARD_D10 PAL_LINE(GPIOB, 6U)
+#define LINE_ARD_D15 PAL_LINE(GPIOB, 8U)
+#define LINE_ARD_D14 PAL_LINE(GPIOB, 9U)
+#define LINE_ARD_D6 PAL_LINE(GPIOB, 10U)
+#define LINE_ARD_A5 PAL_LINE(GPIOC, 0U)
+#define LINE_ACD1_IN10 PAL_LINE(GPIOC, 0U)
+#define LINE_ARD_A4 PAL_LINE(GPIOC, 1U)
+#define LINE_ACD1_IN11 PAL_LINE(GPIOC, 1U)
+#define LINE_ARD_D9 PAL_LINE(GPIOC, 7U)
+#define LINE_BUTTON PAL_LINE(GPIOC, 13U)
+#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U)
+#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U)
+#define LINE_OSC_IN PAL_LINE(GPIOH, 0U)
+#define LINE_OSC_OUT PAL_LINE(GPIOH, 1U)
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*
+ * I/O ports initial setup, this configuration is established soon after reset
+ * in the initialization code.
+ * Please refer to the STM32 Reference Manual for details.
+ */
+#define PIN_MODE_INPUT(n) (0U << ((n) * 2U))
+#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U))
+#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U))
+#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U))
+#define PIN_ODR_LOW(n) (0U << (n))
+#define PIN_ODR_HIGH(n) (1U << (n))
+#define PIN_OTYPE_PUSHPULL(n) (0U << (n))
+#define PIN_OTYPE_OPENDRAIN(n) (1U << (n))
+#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U))
+#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U))
+#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U))
+#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U))
+#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U))
+#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U))
+#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U))
+#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U))
+
+/*
+ * GPIOA setup:
+ *
+ * PA0 - ARD_A0 ACD1_IN0 (input pullup).
+ * PA1 - ARD_A1 ACD1_IN1 (input pullup).
+ * PA2 - ARD_D1 USART2_TX (alternate 4).
+ * PA3 - ARD_D0 USART2_RX (alternate 4).
+ * PA4 - ARD_A2 ACD1_IN4 (input pullup).
+ * PA5 - LED_GREEN ARD_D13 (output pushpull maximum).
+ * PA6 - ARD_D12 (input pullup).
+ * PA7 - ARD_D11 (input pullup).
+ * PA8 - ARD_D7 (input pullup).
+ * PA9 - ARD_D8 (input pullup).
+ * PA10 - ARD_D2 (input pullup).
+ * PA11 - PIN11 (input pullup).
+ * PA12 - PIN12 (input pullup).
+ * PA13 - SWDIO (alternate 0).
+ * PA14 - SWCLK (alternate 0).
+ * PA15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_ARD_A0) | \
+ PIN_MODE_INPUT(GPIOA_ARD_A1) | \
+ PIN_MODE_ALTERNATE(GPIOA_ARD_D1) | \
+ PIN_MODE_ALTERNATE(GPIOA_ARD_D0) | \
+ PIN_MODE_INPUT(GPIOA_ARD_A2) | \
+ PIN_MODE_OUTPUT(GPIOA_LED_GREEN) | \
+ PIN_MODE_INPUT(GPIOA_ARD_D12) | \
+ PIN_MODE_INPUT(GPIOA_ARD_D11) | \
+ PIN_MODE_INPUT(GPIOA_ARD_D7) | \
+ PIN_MODE_INPUT(GPIOA_ARD_D8) | \
+ PIN_MODE_INPUT(GPIOA_ARD_D2) | \
+ PIN_MODE_INPUT(GPIOA_PIN11) | \
+ PIN_MODE_INPUT(GPIOA_PIN12) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \
+ PIN_MODE_INPUT(GPIOA_PIN15))
+#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_ARD_A0) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_A1) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D1) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D0) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_A2) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_LED_GREEN) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D12) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D11) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D7) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D8) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D2) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN15))
+#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_HIGH(GPIOA_ARD_A0) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_A1) | \
+ PIN_OSPEED_MEDIUM(GPIOA_ARD_D1) | \
+ PIN_OSPEED_MEDIUM(GPIOA_ARD_D0) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_A2) | \
+ PIN_OSPEED_HIGH(GPIOA_LED_GREEN) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D12) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D11) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D7) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D8) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D2) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOA_SWDIO) | \
+ PIN_OSPEED_HIGH(GPIOA_SWCLK) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN15))
+#define VAL_GPIOA_PUPDR (PIN_PUPDR_PULLUP(GPIOA_ARD_A0) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_A1) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D1) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D0) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_A2) | \
+ PIN_PUPDR_FLOATING(GPIOA_LED_GREEN) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_D12) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_D11) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_D7) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_D8) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_D2) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOA_SWDIO) | \
+ PIN_PUPDR_PULLDOWN(GPIOA_SWCLK) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN15))
+#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_ARD_A0) | \
+ PIN_ODR_HIGH(GPIOA_ARD_A1) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D1) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D0) | \
+ PIN_ODR_HIGH(GPIOA_ARD_A2) | \
+ PIN_ODR_LOW(GPIOA_LED_GREEN) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D12) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D11) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D7) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D8) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D2) | \
+ PIN_ODR_HIGH(GPIOA_PIN11) | \
+ PIN_ODR_HIGH(GPIOA_PIN12) | \
+ PIN_ODR_HIGH(GPIOA_SWDIO) | \
+ PIN_ODR_HIGH(GPIOA_SWCLK) | \
+ PIN_ODR_HIGH(GPIOA_PIN15))
+#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_ARD_A0, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_A1, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D1, 4U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D0, 4U) | \
+ PIN_AFIO_AF(GPIOA_ARD_A2, 0U) | \
+ PIN_AFIO_AF(GPIOA_LED_GREEN, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D12, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D11, 0U))
+#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_ARD_D7, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D8, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D2, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOA_SWDIO, 0U) | \
+ PIN_AFIO_AF(GPIOA_SWCLK, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN15, 0U))
+
+/*
+ * GPIOB setup:
+ *
+ * PB0 - ARD_A3 ACD1_IN8 (input pullup).
+ * PB1 - PIN1 (input pullup).
+ * PB2 - PIN2 (input pullup).
+ * PB3 - SWO ARD_D3 (alternate 0).
+ * PB4 - ARD_D5 (input pullup).
+ * PB5 - ARD_D4 (input pullup).
+ * PB6 - ARD_D10 (input pullup).
+ * PB7 - PIN7 (input pullup).
+ * PB8 - ARD_D15 (input pullup).
+ * PB9 - ARD_D14 (input pullup).
+ * PB10 - ARD_D6 (input pullup).
+ * PB11 - PIN11 (input pullup).
+ * PB12 - PIN12 (input pullup).
+ * PB13 - PIN13 (input pullup).
+ * PB14 - PIN14 (input pullup).
+ * PB15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOB_MODER (PIN_MODE_INPUT(GPIOB_ARD_A3) | \
+ PIN_MODE_INPUT(GPIOB_PIN1) | \
+ PIN_MODE_INPUT(GPIOB_PIN2) | \
+ PIN_MODE_ALTERNATE(GPIOB_SWO) | \
+ PIN_MODE_INPUT(GPIOB_ARD_D5) | \
+ PIN_MODE_INPUT(GPIOB_ARD_D4) | \
+ PIN_MODE_INPUT(GPIOB_ARD_D10) | \
+ PIN_MODE_INPUT(GPIOB_PIN7) | \
+ PIN_MODE_INPUT(GPIOB_ARD_D15) | \
+ PIN_MODE_INPUT(GPIOB_ARD_D14) | \
+ PIN_MODE_INPUT(GPIOB_ARD_D6) | \
+ PIN_MODE_INPUT(GPIOB_PIN11) | \
+ PIN_MODE_INPUT(GPIOB_PIN12) | \
+ PIN_MODE_INPUT(GPIOB_PIN13) | \
+ PIN_MODE_INPUT(GPIOB_PIN14) | \
+ PIN_MODE_INPUT(GPIOB_PIN15))
+#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_ARD_A3) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_SWO) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D5) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D4) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D10) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D15) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D14) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D6) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN15))
+#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_ARD_A3) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN1) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOB_SWO) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D5) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D4) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D10) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D15) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D14) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D6) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN15))
+#define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(GPIOB_ARD_A3) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOB_SWO) | \
+ PIN_PUPDR_PULLUP(GPIOB_ARD_D5) | \
+ PIN_PUPDR_PULLUP(GPIOB_ARD_D4) | \
+ PIN_PUPDR_PULLUP(GPIOB_ARD_D10) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOB_ARD_D15) | \
+ PIN_PUPDR_PULLUP(GPIOB_ARD_D14) | \
+ PIN_PUPDR_PULLUP(GPIOB_ARD_D6) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN15))
+#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_ARD_A3) | \
+ PIN_ODR_HIGH(GPIOB_PIN1) | \
+ PIN_ODR_HIGH(GPIOB_PIN2) | \
+ PIN_ODR_HIGH(GPIOB_SWO) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D5) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D4) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D10) | \
+ PIN_ODR_HIGH(GPIOB_PIN7) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D15) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D14) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D6) | \
+ PIN_ODR_HIGH(GPIOB_PIN11) | \
+ PIN_ODR_HIGH(GPIOB_PIN12) | \
+ PIN_ODR_HIGH(GPIOB_PIN13) | \
+ PIN_ODR_HIGH(GPIOB_PIN14) | \
+ PIN_ODR_HIGH(GPIOB_PIN15))
+#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_ARD_A3, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOB_SWO, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D5, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D4, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D10, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN7, 0U))
+#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_ARD_D15, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D14, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D6, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN15, 0U))
+
+/*
+ * GPIOC setup:
+ *
+ * PC0 - ARD_A5 ACD1_IN10 (input pullup).
+ * PC1 - ARD_A4 ACD1_IN11 (input pullup).
+ * PC2 - PIN2 (input pullup).
+ * PC3 - PIN3 (input pullup).
+ * PC4 - PIN4 (input pullup).
+ * PC5 - PIN5 (input pullup).
+ * PC6 - PIN6 (input pullup).
+ * PC7 - ARD_D9 (input pullup).
+ * PC8 - PIN8 (input pullup).
+ * PC9 - PIN9 (input pullup).
+ * PC10 - PIN10 (input pullup).
+ * PC11 - PIN11 (input pullup).
+ * PC12 - PIN12 (input pullup).
+ * PC13 - BUTTON (input floating).
+ * PC14 - OSC32_IN (input floating).
+ * PC15 - OSC32_OUT (input floating).
+ */
+#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_ARD_A5) | \
+ PIN_MODE_INPUT(GPIOC_ARD_A4) | \
+ PIN_MODE_INPUT(GPIOC_PIN2) | \
+ PIN_MODE_INPUT(GPIOC_PIN3) | \
+ PIN_MODE_INPUT(GPIOC_PIN4) | \
+ PIN_MODE_INPUT(GPIOC_PIN5) | \
+ PIN_MODE_INPUT(GPIOC_PIN6) | \
+ PIN_MODE_INPUT(GPIOC_ARD_D9) | \
+ PIN_MODE_INPUT(GPIOC_PIN8) | \
+ PIN_MODE_INPUT(GPIOC_PIN9) | \
+ PIN_MODE_INPUT(GPIOC_PIN10) | \
+ PIN_MODE_INPUT(GPIOC_PIN11) | \
+ PIN_MODE_INPUT(GPIOC_PIN12) | \
+ PIN_MODE_INPUT(GPIOC_BUTTON) | \
+ PIN_MODE_INPUT(GPIOC_OSC32_IN) | \
+ PIN_MODE_INPUT(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_ARD_A5) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_ARD_A4) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_ARD_D9) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_BUTTON) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_ARD_A5) | \
+ PIN_OSPEED_HIGH(GPIOC_ARD_A4) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOC_ARD_D9) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOC_BUTTON) | \
+ PIN_OSPEED_HIGH(GPIOC_OSC32_IN) | \
+ PIN_OSPEED_HIGH(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_ARD_A5) | \
+ PIN_PUPDR_PULLUP(GPIOC_ARD_A4) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOC_ARD_D9) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOC_BUTTON) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_ARD_A5) | \
+ PIN_ODR_HIGH(GPIOC_ARD_A4) | \
+ PIN_ODR_HIGH(GPIOC_PIN2) | \
+ PIN_ODR_HIGH(GPIOC_PIN3) | \
+ PIN_ODR_HIGH(GPIOC_PIN4) | \
+ PIN_ODR_HIGH(GPIOC_PIN5) | \
+ PIN_ODR_HIGH(GPIOC_PIN6) | \
+ PIN_ODR_HIGH(GPIOC_ARD_D9) | \
+ PIN_ODR_HIGH(GPIOC_PIN8) | \
+ PIN_ODR_HIGH(GPIOC_PIN9) | \
+ PIN_ODR_HIGH(GPIOC_PIN10) | \
+ PIN_ODR_HIGH(GPIOC_PIN11) | \
+ PIN_ODR_HIGH(GPIOC_PIN12) | \
+ PIN_ODR_HIGH(GPIOC_BUTTON) | \
+ PIN_ODR_HIGH(GPIOC_OSC32_IN) | \
+ PIN_ODR_HIGH(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_ARD_A5, 0U) | \
+ PIN_AFIO_AF(GPIOC_ARD_A4, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOC_ARD_D9, 0U))
+#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOC_BUTTON, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U))
+
+/*
+ * GPIOD setup:
+ *
+ * PD0 - PIN0 (input pullup).
+ * PD1 - PIN1 (input pullup).
+ * PD2 - PIN2 (input pullup).
+ * PD3 - PIN3 (input pullup).
+ * PD4 - PIN4 (input pullup).
+ * PD5 - PIN5 (input pullup).
+ * PD6 - PIN6 (input pullup).
+ * PD7 - PIN7 (input pullup).
+ * PD8 - PIN8 (input pullup).
+ * PD9 - PIN9 (input pullup).
+ * PD10 - PIN10 (input pullup).
+ * PD11 - PIN11 (input pullup).
+ * PD12 - PIN12 (input pullup).
+ * PD13 - PIN13 (input pullup).
+ * PD14 - PIN14 (input pullup).
+ * PD15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | \
+ PIN_MODE_INPUT(GPIOD_PIN1) | \
+ PIN_MODE_INPUT(GPIOD_PIN2) | \
+ PIN_MODE_INPUT(GPIOD_PIN3) | \
+ PIN_MODE_INPUT(GPIOD_PIN4) | \
+ PIN_MODE_INPUT(GPIOD_PIN5) | \
+ PIN_MODE_INPUT(GPIOD_PIN6) | \
+ PIN_MODE_INPUT(GPIOD_PIN7) | \
+ PIN_MODE_INPUT(GPIOD_PIN8) | \
+ PIN_MODE_INPUT(GPIOD_PIN9) | \
+ PIN_MODE_INPUT(GPIOD_PIN10) | \
+ PIN_MODE_INPUT(GPIOD_PIN11) | \
+ PIN_MODE_INPUT(GPIOD_PIN12) | \
+ PIN_MODE_INPUT(GPIOD_PIN13) | \
+ PIN_MODE_INPUT(GPIOD_PIN14) | \
+ PIN_MODE_INPUT(GPIOD_PIN15))
+#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN15))
+#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_HIGH(GPIOD_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN1) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN15))
+#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN15))
+#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \
+ PIN_ODR_HIGH(GPIOD_PIN1) | \
+ PIN_ODR_HIGH(GPIOD_PIN2) | \
+ PIN_ODR_HIGH(GPIOD_PIN3) | \
+ PIN_ODR_HIGH(GPIOD_PIN4) | \
+ PIN_ODR_HIGH(GPIOD_PIN5) | \
+ PIN_ODR_HIGH(GPIOD_PIN6) | \
+ PIN_ODR_HIGH(GPIOD_PIN7) | \
+ PIN_ODR_HIGH(GPIOD_PIN8) | \
+ PIN_ODR_HIGH(GPIOD_PIN9) | \
+ PIN_ODR_HIGH(GPIOD_PIN10) | \
+ PIN_ODR_HIGH(GPIOD_PIN11) | \
+ PIN_ODR_HIGH(GPIOD_PIN12) | \
+ PIN_ODR_HIGH(GPIOD_PIN13) | \
+ PIN_ODR_HIGH(GPIOD_PIN14) | \
+ PIN_ODR_HIGH(GPIOD_PIN15))
+#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN7, 0U))
+#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN15, 0U))
+
+/*
+ * GPIOE setup:
+ *
+ * PE0 - PIN0 (input pullup).
+ * PE1 - PIN1 (input pullup).
+ * PE2 - PIN2 (input pullup).
+ * PE3 - PIN3 (input pullup).
+ * PE4 - PIN4 (input pullup).
+ * PE5 - PIN5 (input pullup).
+ * PE6 - PIN6 (input pullup).
+ * PE7 - PIN7 (input pullup).
+ * PE8 - PIN8 (input pullup).
+ * PE9 - PIN9 (input pullup).
+ * PE10 - PIN10 (input pullup).
+ * PE11 - PIN11 (input pullup).
+ * PE12 - PIN12 (input pullup).
+ * PE13 - PIN13 (input pullup).
+ * PE14 - PIN14 (input pullup).
+ * PE15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_PIN0) | \
+ PIN_MODE_INPUT(GPIOE_PIN1) | \
+ PIN_MODE_INPUT(GPIOE_PIN2) | \
+ PIN_MODE_INPUT(GPIOE_PIN3) | \
+ PIN_MODE_INPUT(GPIOE_PIN4) | \
+ PIN_MODE_INPUT(GPIOE_PIN5) | \
+ PIN_MODE_INPUT(GPIOE_PIN6) | \
+ PIN_MODE_INPUT(GPIOE_PIN7) | \
+ PIN_MODE_INPUT(GPIOE_PIN8) | \
+ PIN_MODE_INPUT(GPIOE_PIN9) | \
+ PIN_MODE_INPUT(GPIOE_PIN10) | \
+ PIN_MODE_INPUT(GPIOE_PIN11) | \
+ PIN_MODE_INPUT(GPIOE_PIN12) | \
+ PIN_MODE_INPUT(GPIOE_PIN13) | \
+ PIN_MODE_INPUT(GPIOE_PIN14) | \
+ PIN_MODE_INPUT(GPIOE_PIN15))
+#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN15))
+#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_HIGH(GPIOE_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN1) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN15))
+#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN15))
+#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | \
+ PIN_ODR_HIGH(GPIOE_PIN1) | \
+ PIN_ODR_HIGH(GPIOE_PIN2) | \
+ PIN_ODR_HIGH(GPIOE_PIN3) | \
+ PIN_ODR_HIGH(GPIOE_PIN4) | \
+ PIN_ODR_HIGH(GPIOE_PIN5) | \
+ PIN_ODR_HIGH(GPIOE_PIN6) | \
+ PIN_ODR_HIGH(GPIOE_PIN7) | \
+ PIN_ODR_HIGH(GPIOE_PIN8) | \
+ PIN_ODR_HIGH(GPIOE_PIN9) | \
+ PIN_ODR_HIGH(GPIOE_PIN10) | \
+ PIN_ODR_HIGH(GPIOE_PIN11) | \
+ PIN_ODR_HIGH(GPIOE_PIN12) | \
+ PIN_ODR_HIGH(GPIOE_PIN13) | \
+ PIN_ODR_HIGH(GPIOE_PIN14) | \
+ PIN_ODR_HIGH(GPIOE_PIN15))
+#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN7, 0U))
+#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN15, 0U))
+
+/*
+ * GPIOH setup:
+ *
+ * PH0 - OSC_IN (input floating).
+ * PH1 - OSC_OUT (input floating).
+ * PH2 - PIN2 (input pullup).
+ * PH3 - PIN3 (input pullup).
+ * PH4 - PIN4 (input pullup).
+ * PH5 - PIN5 (input pullup).
+ * PH6 - PIN6 (input pullup).
+ * PH7 - PIN7 (input pullup).
+ * PH8 - PIN8 (input pullup).
+ * PH9 - PIN9 (input pullup).
+ * PH10 - PIN10 (input pullup).
+ * PH11 - PIN11 (input pullup).
+ * PH12 - PIN12 (input pullup).
+ * PH13 - PIN13 (input pullup).
+ * PH14 - PIN14 (input pullup).
+ * PH15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_OSC_IN) | \
+ PIN_MODE_INPUT(GPIOH_OSC_OUT) | \
+ PIN_MODE_INPUT(GPIOH_PIN2) | \
+ PIN_MODE_INPUT(GPIOH_PIN3) | \
+ PIN_MODE_INPUT(GPIOH_PIN4) | \
+ PIN_MODE_INPUT(GPIOH_PIN5) | \
+ PIN_MODE_INPUT(GPIOH_PIN6) | \
+ PIN_MODE_INPUT(GPIOH_PIN7) | \
+ PIN_MODE_INPUT(GPIOH_PIN8) | \
+ PIN_MODE_INPUT(GPIOH_PIN9) | \
+ PIN_MODE_INPUT(GPIOH_PIN10) | \
+ PIN_MODE_INPUT(GPIOH_PIN11) | \
+ PIN_MODE_INPUT(GPIOH_PIN12) | \
+ PIN_MODE_INPUT(GPIOH_PIN13) | \
+ PIN_MODE_INPUT(GPIOH_PIN14) | \
+ PIN_MODE_INPUT(GPIOH_PIN15))
+#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_OSC_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_OSC_OUT) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN15))
+#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_HIGH(GPIOH_OSC_IN) | \
+ PIN_OSPEED_HIGH(GPIOH_OSC_OUT) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOH_PIN15))
+#define VAL_GPIOH_PUPDR (PIN_PUPDR_FLOATING(GPIOH_OSC_IN) | \
+ PIN_PUPDR_FLOATING(GPIOH_OSC_OUT) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN15))
+#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_OSC_IN) | \
+ PIN_ODR_HIGH(GPIOH_OSC_OUT) | \
+ PIN_ODR_HIGH(GPIOH_PIN2) | \
+ PIN_ODR_HIGH(GPIOH_PIN3) | \
+ PIN_ODR_HIGH(GPIOH_PIN4) | \
+ PIN_ODR_HIGH(GPIOH_PIN5) | \
+ PIN_ODR_HIGH(GPIOH_PIN6) | \
+ PIN_ODR_HIGH(GPIOH_PIN7) | \
+ PIN_ODR_HIGH(GPIOH_PIN8) | \
+ PIN_ODR_HIGH(GPIOH_PIN9) | \
+ PIN_ODR_HIGH(GPIOH_PIN10) | \
+ PIN_ODR_HIGH(GPIOH_PIN11) | \
+ PIN_ODR_HIGH(GPIOH_PIN12) | \
+ PIN_ODR_HIGH(GPIOH_PIN13) | \
+ PIN_ODR_HIGH(GPIOH_PIN14) | \
+ PIN_ODR_HIGH(GPIOH_PIN15))
+#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_OSC_IN, 0U) | \
+ PIN_AFIO_AF(GPIOH_OSC_OUT, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN7, 0U))
+#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN15, 0U))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* BOARD_H */
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L073RZ/board.mk b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L073RZ/board.mk
new file mode 100644
index 0000000..d99e2a4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L073RZ/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_L073RZ/board.c
+
+# Required include directories
+BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_L073RZ
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC += $(BOARDINC)
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L073RZ/cfg/board.chcfg b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L073RZ/cfg/board.chcfg
new file mode 100644
index 0000000..6e8dfc6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L073RZ/cfg/board.chcfg
@@ -0,0 +1,799 @@
+
+
+
+
+ resources/gencfg/processors/boards/stm32l0xx/templates
+ ..
+ 5.0.x
+
+ STMicroelectronics STM32 Nucleo64-L073RZ
+ ST_NUCLEO64_L073RZ
+
+ STM32L073xx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L073RZ/cfg/board.fmpp b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L073RZ/cfg/board.fmpp
new file mode 100644
index 0000000..b3ba947
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L073RZ/cfg/board.fmpp
@@ -0,0 +1,15 @@
+sourceRoot: ../../../../../tools/ftl/processors/boards/stm32l0xx/templates
+outputRoot: ..
+dataRoot: .
+
+freemarkerLinks: {
+ lib: ../../../../../tools/ftl/libs
+}
+
+data : {
+ doc1:xml (
+ board.chcfg
+ {
+ }
+ )
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L152RE/board.c b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L152RE/board.c
new file mode 100644
index 0000000..29d73fe
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L152RE/board.c
@@ -0,0 +1,266 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#include "hal.h"
+#include "stm32_gpio.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of STM32 GPIO port setup.
+ */
+typedef struct {
+ uint32_t moder;
+ uint32_t otyper;
+ uint32_t ospeedr;
+ uint32_t pupdr;
+ uint32_t odr;
+ uint32_t afrl;
+ uint32_t afrh;
+} gpio_setup_t;
+
+/**
+ * @brief Type of STM32 GPIO initialization data.
+ */
+typedef struct {
+#if STM32_HAS_GPIOA || defined(__DOXYGEN__)
+ gpio_setup_t PAData;
+#endif
+#if STM32_HAS_GPIOB || defined(__DOXYGEN__)
+ gpio_setup_t PBData;
+#endif
+#if STM32_HAS_GPIOC || defined(__DOXYGEN__)
+ gpio_setup_t PCData;
+#endif
+#if STM32_HAS_GPIOD || defined(__DOXYGEN__)
+ gpio_setup_t PDData;
+#endif
+#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
+ gpio_setup_t PEData;
+#endif
+#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
+ gpio_setup_t PFData;
+#endif
+#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
+ gpio_setup_t PGData;
+#endif
+#if STM32_HAS_GPIOH || defined(__DOXYGEN__)
+ gpio_setup_t PHData;
+#endif
+#if STM32_HAS_GPIOI || defined(__DOXYGEN__)
+ gpio_setup_t PIData;
+#endif
+#if STM32_HAS_GPIOJ || defined(__DOXYGEN__)
+ gpio_setup_t PJData;
+#endif
+#if STM32_HAS_GPIOK || defined(__DOXYGEN__)
+ gpio_setup_t PKData;
+#endif
+} gpio_config_t;
+
+/**
+ * @brief STM32 GPIO static initialization data.
+ */
+static const gpio_config_t gpio_default_config = {
+#if STM32_HAS_GPIOA
+ {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
+ VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH},
+#endif
+#if STM32_HAS_GPIOB
+ {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR,
+ VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH},
+#endif
+#if STM32_HAS_GPIOC
+ {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR,
+ VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH},
+#endif
+#if STM32_HAS_GPIOD
+ {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR,
+ VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH},
+#endif
+#if STM32_HAS_GPIOE
+ {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR,
+ VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH},
+#endif
+#if STM32_HAS_GPIOF
+ {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR,
+ VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH},
+#endif
+#if STM32_HAS_GPIOG
+ {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR,
+ VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH},
+#endif
+#if STM32_HAS_GPIOH
+ {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR,
+ VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH},
+#endif
+#if STM32_HAS_GPIOI
+ {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
+ VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH},
+#endif
+#if STM32_HAS_GPIOJ
+ {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR,
+ VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH},
+#endif
+#if STM32_HAS_GPIOK
+ {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR,
+ VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH}
+#endif
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) {
+
+ gpiop->OTYPER = config->otyper;
+ gpiop->OSPEEDR = config->ospeedr;
+ gpiop->PUPDR = config->pupdr;
+ gpiop->ODR = config->odr;
+ gpiop->AFRL = config->afrl;
+ gpiop->AFRH = config->afrh;
+ gpiop->MODER = config->moder;
+}
+
+static void stm32_gpio_init(void) {
+
+ /* Enabling GPIO-related clocks, the mask comes from the
+ registry header file.*/
+ rccResetAHB(STM32_GPIO_EN_MASK);
+ rccEnableAHB(STM32_GPIO_EN_MASK, true);
+
+ /* Initializing all the defined GPIO ports.*/
+#if STM32_HAS_GPIOA
+ gpio_init(GPIOA, &gpio_default_config.PAData);
+#endif
+#if STM32_HAS_GPIOB
+ gpio_init(GPIOB, &gpio_default_config.PBData);
+#endif
+#if STM32_HAS_GPIOC
+ gpio_init(GPIOC, &gpio_default_config.PCData);
+#endif
+#if STM32_HAS_GPIOD
+ gpio_init(GPIOD, &gpio_default_config.PDData);
+#endif
+#if STM32_HAS_GPIOE
+ gpio_init(GPIOE, &gpio_default_config.PEData);
+#endif
+#if STM32_HAS_GPIOF
+ gpio_init(GPIOF, &gpio_default_config.PFData);
+#endif
+#if STM32_HAS_GPIOG
+ gpio_init(GPIOG, &gpio_default_config.PGData);
+#endif
+#if STM32_HAS_GPIOH
+ gpio_init(GPIOH, &gpio_default_config.PHData);
+#endif
+#if STM32_HAS_GPIOI
+ gpio_init(GPIOI, &gpio_default_config.PIData);
+#endif
+#if STM32_HAS_GPIOJ
+ gpio_init(GPIOJ, &gpio_default_config.PJData);
+#endif
+#if STM32_HAS_GPIOK
+ gpio_init(GPIOK, &gpio_default_config.PKData);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Early initialization code.
+ * @details GPIO ports and system clocks are initialized before everything
+ * else.
+ */
+void __early_init(void) {
+
+ stm32_gpio_init();
+ stm32_clock_init();
+}
+
+#if HAL_USE_SDC || defined(__DOXYGEN__)
+/**
+ * @brief SDC card detection.
+ */
+bool sdc_lld_is_card_inserted(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief SDC card write protection detection.
+ */
+bool sdc_lld_is_write_protected(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif /* HAL_USE_SDC */
+
+#if HAL_USE_MMC_SPI || defined(__DOXYGEN__)
+/**
+ * @brief MMC_SPI card detection.
+ */
+bool mmc_lld_is_card_inserted(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief MMC_SPI card write protection detection.
+ */
+bool mmc_lld_is_write_protected(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif
+
+/**
+ * @brief Board-specific initialization code.
+ * @note You can add your board-specific code here.
+ */
+void boardInit(void) {
+
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L152RE/board.h b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L152RE/board.h
new file mode 100644
index 0000000..2f598a2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L152RE/board.h
@@ -0,0 +1,1237 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#ifndef BOARD_H
+#define BOARD_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*
+ * Setup for STMicroelectronics STM32 Nucleo64-L152RE board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_ST_NUCLEO64_L152RE
+#define BOARD_NAME "STMicroelectronics STM32 Nucleo64-L152RE"
+
+/*
+ * Board oscillators-related settings.
+ */
+#if !defined(STM32_LSECLK)
+#define STM32_LSECLK 32768U
+#endif
+
+#if !defined(STM32_HSECLK)
+#define STM32_HSECLK 8000000U
+#endif
+
+#define STM32_HSE_BYPASS
+
+/*
+ * MCU type as defined in the ST header.
+ */
+#define STM32L152xE
+
+/*
+ * IO pins assignments.
+ */
+#define GPIOA_ARD_A0 0U
+#define GPIOA_ACD1_IN0 0U
+#define GPIOA_ARD_A1 1U
+#define GPIOA_ACD1_IN1 1U
+#define GPIOA_ARD_D1 2U
+#define GPIOA_USART2_TX 2U
+#define GPIOA_ARD_D0 3U
+#define GPIOA_USART2_RX 3U
+#define GPIOA_ARD_A2 4U
+#define GPIOA_ACD1_IN4 4U
+#define GPIOA_LED_GREEN 5U
+#define GPIOA_ARD_D13 5U
+#define GPIOA_ARD_D12 6U
+#define GPIOA_ARD_D11 7U
+#define GPIOA_ARD_D7 8U
+#define GPIOA_ARD_D8 9U
+#define GPIOA_ARD_D2 10U
+#define GPIOA_PIN11 11U
+#define GPIOA_PIN12 12U
+#define GPIOA_SWDIO 13U
+#define GPIOA_SWCLK 14U
+#define GPIOA_PIN15 15U
+
+#define GPIOB_ARD_A3 0U
+#define GPIOB_ACD1_IN8 0U
+#define GPIOB_PIN1 1U
+#define GPIOB_PIN2 2U
+#define GPIOB_SWO 3U
+#define GPIOB_ARD_D3 3U
+#define GPIOB_ARD_D5 4U
+#define GPIOB_ARD_D4 5U
+#define GPIOB_ARD_D10 6U
+#define GPIOB_PIN7 7U
+#define GPIOB_ARD_D15 8U
+#define GPIOB_ARD_D14 9U
+#define GPIOB_ARD_D6 10U
+#define GPIOB_PIN11 11U
+#define GPIOB_PIN12 12U
+#define GPIOB_PIN13 13U
+#define GPIOB_PIN14 14U
+#define GPIOB_PIN15 15U
+
+#define GPIOC_ARD_A5 0U
+#define GPIOC_ACD1_IN10 0U
+#define GPIOC_ARD_A4 1U
+#define GPIOC_ACD1_IN11 1U
+#define GPIOC_PIN2 2U
+#define GPIOC_PIN3 3U
+#define GPIOC_PIN4 4U
+#define GPIOC_PIN5 5U
+#define GPIOC_PIN6 6U
+#define GPIOC_ARD_D9 7U
+#define GPIOC_PIN8 8U
+#define GPIOC_PIN9 9U
+#define GPIOC_PIN10 10U
+#define GPIOC_PIN11 11U
+#define GPIOC_PIN12 12U
+#define GPIOC_BUTTON 13U
+#define GPIOC_OSC32_IN 14U
+#define GPIOC_OSC32_OUT 15U
+
+#define GPIOD_PIN0 0U
+#define GPIOD_PIN1 1U
+#define GPIOD_PIN2 2U
+#define GPIOD_PIN3 3U
+#define GPIOD_PIN4 4U
+#define GPIOD_PIN5 5U
+#define GPIOD_PIN6 6U
+#define GPIOD_PIN7 7U
+#define GPIOD_PIN8 8U
+#define GPIOD_PIN9 9U
+#define GPIOD_PIN10 10U
+#define GPIOD_PIN11 11U
+#define GPIOD_PIN12 12U
+#define GPIOD_PIN13 13U
+#define GPIOD_PIN14 14U
+#define GPIOD_PIN15 15U
+
+#define GPIOE_PIN0 0U
+#define GPIOE_PIN1 1U
+#define GPIOE_PIN2 2U
+#define GPIOE_PIN3 3U
+#define GPIOE_PIN4 4U
+#define GPIOE_PIN5 5U
+#define GPIOE_PIN6 6U
+#define GPIOE_PIN7 7U
+#define GPIOE_PIN8 8U
+#define GPIOE_PIN9 9U
+#define GPIOE_PIN10 10U
+#define GPIOE_PIN11 11U
+#define GPIOE_PIN12 12U
+#define GPIOE_PIN13 13U
+#define GPIOE_PIN14 14U
+#define GPIOE_PIN15 15U
+
+#define GPIOF_PIN0 0U
+#define GPIOF_PIN1 1U
+#define GPIOF_PIN2 2U
+#define GPIOF_PIN3 3U
+#define GPIOF_PIN4 4U
+#define GPIOF_PIN5 5U
+#define GPIOF_PIN6 6U
+#define GPIOF_PIN7 7U
+#define GPIOF_PIN8 8U
+#define GPIOF_PIN9 9U
+#define GPIOF_PIN10 10U
+#define GPIOF_PIN11 11U
+#define GPIOF_PIN12 12U
+#define GPIOF_PIN13 13U
+#define GPIOF_PIN14 14U
+#define GPIOF_PIN15 15U
+
+#define GPIOG_PIN0 0U
+#define GPIOG_PIN1 1U
+#define GPIOG_PIN2 2U
+#define GPIOG_PIN3 3U
+#define GPIOG_PIN4 4U
+#define GPIOG_PIN5 5U
+#define GPIOG_PIN6 6U
+#define GPIOG_PIN7 7U
+#define GPIOG_PIN8 8U
+#define GPIOG_PIN9 9U
+#define GPIOG_PIN10 10U
+#define GPIOG_PIN11 11U
+#define GPIOG_PIN12 12U
+#define GPIOG_PIN13 13U
+#define GPIOG_PIN14 14U
+#define GPIOG_PIN15 15U
+
+#define GPIOH_OSC_IN 0U
+#define GPIOH_OSC_OUT 1U
+#define GPIOH_PIN2 2U
+#define GPIOH_PIN3 3U
+#define GPIOH_PIN4 4U
+#define GPIOH_PIN5 5U
+#define GPIOH_PIN6 6U
+#define GPIOH_PIN7 7U
+#define GPIOH_PIN8 8U
+#define GPIOH_PIN9 9U
+#define GPIOH_PIN10 10U
+#define GPIOH_PIN11 11U
+#define GPIOH_PIN12 12U
+#define GPIOH_PIN13 13U
+#define GPIOH_PIN14 14U
+#define GPIOH_PIN15 15U
+
+/*
+ * IO lines assignments.
+ */
+#define LINE_ARD_A0 PAL_LINE(GPIOA, 0U)
+#define LINE_ACD1_IN0 PAL_LINE(GPIOA, 0U)
+#define LINE_ARD_A1 PAL_LINE(GPIOA, 1U)
+#define LINE_ACD1_IN1 PAL_LINE(GPIOA, 1U)
+#define LINE_ARD_D1 PAL_LINE(GPIOA, 2U)
+#define LINE_USART2_TX PAL_LINE(GPIOA, 2U)
+#define LINE_ARD_D0 PAL_LINE(GPIOA, 3U)
+#define LINE_USART2_RX PAL_LINE(GPIOA, 3U)
+#define LINE_ARD_A2 PAL_LINE(GPIOA, 4U)
+#define LINE_ACD1_IN4 PAL_LINE(GPIOA, 4U)
+#define LINE_LED_GREEN PAL_LINE(GPIOA, 5U)
+#define LINE_ARD_D13 PAL_LINE(GPIOA, 5U)
+#define LINE_ARD_D12 PAL_LINE(GPIOA, 6U)
+#define LINE_ARD_D11 PAL_LINE(GPIOA, 7U)
+#define LINE_ARD_D7 PAL_LINE(GPIOA, 8U)
+#define LINE_ARD_D8 PAL_LINE(GPIOA, 9U)
+#define LINE_ARD_D2 PAL_LINE(GPIOA, 10U)
+#define LINE_SWDIO PAL_LINE(GPIOA, 13U)
+#define LINE_SWCLK PAL_LINE(GPIOA, 14U)
+#define LINE_ARD_A3 PAL_LINE(GPIOB, 0U)
+#define LINE_ACD1_IN8 PAL_LINE(GPIOB, 0U)
+#define LINE_SWO PAL_LINE(GPIOB, 3U)
+#define LINE_ARD_D3 PAL_LINE(GPIOB, 3U)
+#define LINE_ARD_D5 PAL_LINE(GPIOB, 4U)
+#define LINE_ARD_D4 PAL_LINE(GPIOB, 5U)
+#define LINE_ARD_D10 PAL_LINE(GPIOB, 6U)
+#define LINE_ARD_D15 PAL_LINE(GPIOB, 8U)
+#define LINE_ARD_D14 PAL_LINE(GPIOB, 9U)
+#define LINE_ARD_D6 PAL_LINE(GPIOB, 10U)
+#define LINE_ARD_A5 PAL_LINE(GPIOC, 0U)
+#define LINE_ACD1_IN10 PAL_LINE(GPIOC, 0U)
+#define LINE_ARD_A4 PAL_LINE(GPIOC, 1U)
+#define LINE_ACD1_IN11 PAL_LINE(GPIOC, 1U)
+#define LINE_ARD_D9 PAL_LINE(GPIOC, 7U)
+#define LINE_BUTTON PAL_LINE(GPIOC, 13U)
+#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U)
+#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U)
+#define LINE_OSC_IN PAL_LINE(GPIOH, 0U)
+#define LINE_OSC_OUT PAL_LINE(GPIOH, 1U)
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*
+ * I/O ports initial setup, this configuration is established soon after reset
+ * in the initialization code.
+ * Please refer to the STM32 Reference Manual for details.
+ */
+#define PIN_MODE_INPUT(n) (0U << ((n) * 2U))
+#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U))
+#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U))
+#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U))
+#define PIN_ODR_LOW(n) (0U << (n))
+#define PIN_ODR_HIGH(n) (1U << (n))
+#define PIN_OTYPE_PUSHPULL(n) (0U << (n))
+#define PIN_OTYPE_OPENDRAIN(n) (1U << (n))
+#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U))
+#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U))
+#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U))
+#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U))
+#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U))
+#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U))
+#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U))
+#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U))
+
+/*
+ * GPIOA setup:
+ *
+ * PA0 - ARD_A0 ACD1_IN0 (input pullup).
+ * PA1 - ARD_A1 ACD1_IN1 (input pullup).
+ * PA2 - ARD_D1 USART2_TX (alternate 7).
+ * PA3 - ARD_D0 USART2_RX (alternate 7).
+ * PA4 - ARD_A2 ACD1_IN4 (input pullup).
+ * PA5 - LED_GREEN ARD_D13 (output pushpull high).
+ * PA6 - ARD_D12 (input pullup).
+ * PA7 - ARD_D11 (input pullup).
+ * PA8 - ARD_D7 (input pullup).
+ * PA9 - ARD_D8 (input pullup).
+ * PA10 - ARD_D2 (input pullup).
+ * PA11 - PIN11 (input pullup).
+ * PA12 - PIN12 (input pullup).
+ * PA13 - SWDIO (alternate 0).
+ * PA14 - SWCLK (alternate 0).
+ * PA15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_ARD_A0) | \
+ PIN_MODE_INPUT(GPIOA_ARD_A1) | \
+ PIN_MODE_ALTERNATE(GPIOA_ARD_D1) | \
+ PIN_MODE_ALTERNATE(GPIOA_ARD_D0) | \
+ PIN_MODE_INPUT(GPIOA_ARD_A2) | \
+ PIN_MODE_OUTPUT(GPIOA_LED_GREEN) | \
+ PIN_MODE_INPUT(GPIOA_ARD_D12) | \
+ PIN_MODE_INPUT(GPIOA_ARD_D11) | \
+ PIN_MODE_INPUT(GPIOA_ARD_D7) | \
+ PIN_MODE_INPUT(GPIOA_ARD_D8) | \
+ PIN_MODE_INPUT(GPIOA_ARD_D2) | \
+ PIN_MODE_INPUT(GPIOA_PIN11) | \
+ PIN_MODE_INPUT(GPIOA_PIN12) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \
+ PIN_MODE_INPUT(GPIOA_PIN15))
+#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_ARD_A0) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_A1) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D1) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D0) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_A2) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_LED_GREEN) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D12) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D11) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D7) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D8) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D2) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN15))
+#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_HIGH(GPIOA_ARD_A0) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_A1) | \
+ PIN_OSPEED_MEDIUM(GPIOA_ARD_D1) | \
+ PIN_OSPEED_MEDIUM(GPIOA_ARD_D0) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_A2) | \
+ PIN_OSPEED_MEDIUM(GPIOA_LED_GREEN) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D12) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D11) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D7) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D8) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D2) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOA_SWDIO) | \
+ PIN_OSPEED_HIGH(GPIOA_SWCLK) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN15))
+#define VAL_GPIOA_PUPDR (PIN_PUPDR_PULLUP(GPIOA_ARD_A0) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_A1) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D1) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D0) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_A2) | \
+ PIN_PUPDR_FLOATING(GPIOA_LED_GREEN) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_D12) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_D11) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_D7) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_D8) | \
+ PIN_PUPDR_PULLUP(GPIOA_ARD_D2) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOA_SWDIO) | \
+ PIN_PUPDR_PULLDOWN(GPIOA_SWCLK) | \
+ PIN_PUPDR_PULLUP(GPIOA_PIN15))
+#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_ARD_A0) | \
+ PIN_ODR_HIGH(GPIOA_ARD_A1) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D1) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D0) | \
+ PIN_ODR_HIGH(GPIOA_ARD_A2) | \
+ PIN_ODR_LOW(GPIOA_LED_GREEN) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D12) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D11) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D7) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D8) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D2) | \
+ PIN_ODR_HIGH(GPIOA_PIN11) | \
+ PIN_ODR_HIGH(GPIOA_PIN12) | \
+ PIN_ODR_HIGH(GPIOA_SWDIO) | \
+ PIN_ODR_HIGH(GPIOA_SWCLK) | \
+ PIN_ODR_HIGH(GPIOA_PIN15))
+#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_ARD_A0, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_A1, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D1, 7U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D0, 7U) | \
+ PIN_AFIO_AF(GPIOA_ARD_A2, 0U) | \
+ PIN_AFIO_AF(GPIOA_LED_GREEN, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D12, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D11, 0U))
+#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_ARD_D7, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D8, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D2, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOA_SWDIO, 0U) | \
+ PIN_AFIO_AF(GPIOA_SWCLK, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN15, 0U))
+
+/*
+ * GPIOB setup:
+ *
+ * PB0 - ARD_A3 ACD1_IN8 (input pullup).
+ * PB1 - PIN1 (input pullup).
+ * PB2 - PIN2 (input pullup).
+ * PB3 - SWO ARD_D3 (alternate 0).
+ * PB4 - ARD_D5 (input pullup).
+ * PB5 - ARD_D4 (input pullup).
+ * PB6 - ARD_D10 (input pullup).
+ * PB7 - PIN7 (input pullup).
+ * PB8 - ARD_D15 (input pullup).
+ * PB9 - ARD_D14 (input pullup).
+ * PB10 - ARD_D6 (input pullup).
+ * PB11 - PIN11 (input pullup).
+ * PB12 - PIN12 (input pullup).
+ * PB13 - PIN13 (input pullup).
+ * PB14 - PIN14 (input pullup).
+ * PB15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOB_MODER (PIN_MODE_INPUT(GPIOB_ARD_A3) | \
+ PIN_MODE_INPUT(GPIOB_PIN1) | \
+ PIN_MODE_INPUT(GPIOB_PIN2) | \
+ PIN_MODE_ALTERNATE(GPIOB_SWO) | \
+ PIN_MODE_INPUT(GPIOB_ARD_D5) | \
+ PIN_MODE_INPUT(GPIOB_ARD_D4) | \
+ PIN_MODE_INPUT(GPIOB_ARD_D10) | \
+ PIN_MODE_INPUT(GPIOB_PIN7) | \
+ PIN_MODE_INPUT(GPIOB_ARD_D15) | \
+ PIN_MODE_INPUT(GPIOB_ARD_D14) | \
+ PIN_MODE_INPUT(GPIOB_ARD_D6) | \
+ PIN_MODE_INPUT(GPIOB_PIN11) | \
+ PIN_MODE_INPUT(GPIOB_PIN12) | \
+ PIN_MODE_INPUT(GPIOB_PIN13) | \
+ PIN_MODE_INPUT(GPIOB_PIN14) | \
+ PIN_MODE_INPUT(GPIOB_PIN15))
+#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_ARD_A3) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_SWO) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D5) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D4) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D10) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D15) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D14) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D6) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN15))
+#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_ARD_A3) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN1) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOB_SWO) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D5) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D4) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D10) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D15) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D14) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D6) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN15))
+#define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(GPIOB_ARD_A3) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOB_SWO) | \
+ PIN_PUPDR_PULLUP(GPIOB_ARD_D5) | \
+ PIN_PUPDR_PULLUP(GPIOB_ARD_D4) | \
+ PIN_PUPDR_PULLUP(GPIOB_ARD_D10) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOB_ARD_D15) | \
+ PIN_PUPDR_PULLUP(GPIOB_ARD_D14) | \
+ PIN_PUPDR_PULLUP(GPIOB_ARD_D6) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOB_PIN15))
+#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_ARD_A3) | \
+ PIN_ODR_HIGH(GPIOB_PIN1) | \
+ PIN_ODR_HIGH(GPIOB_PIN2) | \
+ PIN_ODR_HIGH(GPIOB_SWO) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D5) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D4) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D10) | \
+ PIN_ODR_HIGH(GPIOB_PIN7) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D15) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D14) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D6) | \
+ PIN_ODR_HIGH(GPIOB_PIN11) | \
+ PIN_ODR_HIGH(GPIOB_PIN12) | \
+ PIN_ODR_HIGH(GPIOB_PIN13) | \
+ PIN_ODR_HIGH(GPIOB_PIN14) | \
+ PIN_ODR_HIGH(GPIOB_PIN15))
+#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_ARD_A3, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOB_SWO, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D5, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D4, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D10, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN7, 0U))
+#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_ARD_D15, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D14, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D6, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN15, 0U))
+
+/*
+ * GPIOC setup:
+ *
+ * PC0 - ARD_A5 ACD1_IN10 (input pullup).
+ * PC1 - ARD_A4 ACD1_IN11 (input pullup).
+ * PC2 - PIN2 (input pullup).
+ * PC3 - PIN3 (input pullup).
+ * PC4 - PIN4 (input pullup).
+ * PC5 - PIN5 (input pullup).
+ * PC6 - PIN6 (input pullup).
+ * PC7 - ARD_D9 (input pullup).
+ * PC8 - PIN8 (input pullup).
+ * PC9 - PIN9 (input pullup).
+ * PC10 - PIN10 (input pullup).
+ * PC11 - PIN11 (input pullup).
+ * PC12 - PIN12 (input pullup).
+ * PC13 - BUTTON (input floating).
+ * PC14 - OSC32_IN (input floating).
+ * PC15 - OSC32_OUT (input floating).
+ */
+#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_ARD_A5) | \
+ PIN_MODE_INPUT(GPIOC_ARD_A4) | \
+ PIN_MODE_INPUT(GPIOC_PIN2) | \
+ PIN_MODE_INPUT(GPIOC_PIN3) | \
+ PIN_MODE_INPUT(GPIOC_PIN4) | \
+ PIN_MODE_INPUT(GPIOC_PIN5) | \
+ PIN_MODE_INPUT(GPIOC_PIN6) | \
+ PIN_MODE_INPUT(GPIOC_ARD_D9) | \
+ PIN_MODE_INPUT(GPIOC_PIN8) | \
+ PIN_MODE_INPUT(GPIOC_PIN9) | \
+ PIN_MODE_INPUT(GPIOC_PIN10) | \
+ PIN_MODE_INPUT(GPIOC_PIN11) | \
+ PIN_MODE_INPUT(GPIOC_PIN12) | \
+ PIN_MODE_INPUT(GPIOC_BUTTON) | \
+ PIN_MODE_INPUT(GPIOC_OSC32_IN) | \
+ PIN_MODE_INPUT(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_ARD_A5) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_ARD_A4) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_ARD_D9) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_BUTTON) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_ARD_A5) | \
+ PIN_OSPEED_HIGH(GPIOC_ARD_A4) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOC_ARD_D9) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOC_BUTTON) | \
+ PIN_OSPEED_HIGH(GPIOC_OSC32_IN) | \
+ PIN_OSPEED_HIGH(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_ARD_A5) | \
+ PIN_PUPDR_PULLUP(GPIOC_ARD_A4) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOC_ARD_D9) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOC_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOC_BUTTON) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_ARD_A5) | \
+ PIN_ODR_HIGH(GPIOC_ARD_A4) | \
+ PIN_ODR_HIGH(GPIOC_PIN2) | \
+ PIN_ODR_HIGH(GPIOC_PIN3) | \
+ PIN_ODR_HIGH(GPIOC_PIN4) | \
+ PIN_ODR_HIGH(GPIOC_PIN5) | \
+ PIN_ODR_HIGH(GPIOC_PIN6) | \
+ PIN_ODR_HIGH(GPIOC_ARD_D9) | \
+ PIN_ODR_HIGH(GPIOC_PIN8) | \
+ PIN_ODR_HIGH(GPIOC_PIN9) | \
+ PIN_ODR_HIGH(GPIOC_PIN10) | \
+ PIN_ODR_HIGH(GPIOC_PIN11) | \
+ PIN_ODR_HIGH(GPIOC_PIN12) | \
+ PIN_ODR_HIGH(GPIOC_BUTTON) | \
+ PIN_ODR_HIGH(GPIOC_OSC32_IN) | \
+ PIN_ODR_HIGH(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_ARD_A5, 0U) | \
+ PIN_AFIO_AF(GPIOC_ARD_A4, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOC_ARD_D9, 0U))
+#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOC_BUTTON, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U))
+
+/*
+ * GPIOD setup:
+ *
+ * PD0 - PIN0 (input pullup).
+ * PD1 - PIN1 (input pullup).
+ * PD2 - PIN2 (input pullup).
+ * PD3 - PIN3 (input pullup).
+ * PD4 - PIN4 (input pullup).
+ * PD5 - PIN5 (input pullup).
+ * PD6 - PIN6 (input pullup).
+ * PD7 - PIN7 (input pullup).
+ * PD8 - PIN8 (input pullup).
+ * PD9 - PIN9 (input pullup).
+ * PD10 - PIN10 (input pullup).
+ * PD11 - PIN11 (input pullup).
+ * PD12 - PIN12 (input pullup).
+ * PD13 - PIN13 (input pullup).
+ * PD14 - PIN14 (input pullup).
+ * PD15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | \
+ PIN_MODE_INPUT(GPIOD_PIN1) | \
+ PIN_MODE_INPUT(GPIOD_PIN2) | \
+ PIN_MODE_INPUT(GPIOD_PIN3) | \
+ PIN_MODE_INPUT(GPIOD_PIN4) | \
+ PIN_MODE_INPUT(GPIOD_PIN5) | \
+ PIN_MODE_INPUT(GPIOD_PIN6) | \
+ PIN_MODE_INPUT(GPIOD_PIN7) | \
+ PIN_MODE_INPUT(GPIOD_PIN8) | \
+ PIN_MODE_INPUT(GPIOD_PIN9) | \
+ PIN_MODE_INPUT(GPIOD_PIN10) | \
+ PIN_MODE_INPUT(GPIOD_PIN11) | \
+ PIN_MODE_INPUT(GPIOD_PIN12) | \
+ PIN_MODE_INPUT(GPIOD_PIN13) | \
+ PIN_MODE_INPUT(GPIOD_PIN14) | \
+ PIN_MODE_INPUT(GPIOD_PIN15))
+#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN15))
+#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOD_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOD_PIN15))
+#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOD_PIN15))
+#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \
+ PIN_ODR_HIGH(GPIOD_PIN1) | \
+ PIN_ODR_HIGH(GPIOD_PIN2) | \
+ PIN_ODR_HIGH(GPIOD_PIN3) | \
+ PIN_ODR_HIGH(GPIOD_PIN4) | \
+ PIN_ODR_HIGH(GPIOD_PIN5) | \
+ PIN_ODR_HIGH(GPIOD_PIN6) | \
+ PIN_ODR_HIGH(GPIOD_PIN7) | \
+ PIN_ODR_HIGH(GPIOD_PIN8) | \
+ PIN_ODR_HIGH(GPIOD_PIN9) | \
+ PIN_ODR_HIGH(GPIOD_PIN10) | \
+ PIN_ODR_HIGH(GPIOD_PIN11) | \
+ PIN_ODR_HIGH(GPIOD_PIN12) | \
+ PIN_ODR_HIGH(GPIOD_PIN13) | \
+ PIN_ODR_HIGH(GPIOD_PIN14) | \
+ PIN_ODR_HIGH(GPIOD_PIN15))
+#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN7, 0U))
+#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN15, 0U))
+
+/*
+ * GPIOE setup:
+ *
+ * PE0 - PIN0 (input pullup).
+ * PE1 - PIN1 (input pullup).
+ * PE2 - PIN2 (input pullup).
+ * PE3 - PIN3 (input pullup).
+ * PE4 - PIN4 (input pullup).
+ * PE5 - PIN5 (input pullup).
+ * PE6 - PIN6 (input pullup).
+ * PE7 - PIN7 (input pullup).
+ * PE8 - PIN8 (input pullup).
+ * PE9 - PIN9 (input pullup).
+ * PE10 - PIN10 (input pullup).
+ * PE11 - PIN11 (input pullup).
+ * PE12 - PIN12 (input pullup).
+ * PE13 - PIN13 (input pullup).
+ * PE14 - PIN14 (input pullup).
+ * PE15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_PIN0) | \
+ PIN_MODE_INPUT(GPIOE_PIN1) | \
+ PIN_MODE_INPUT(GPIOE_PIN2) | \
+ PIN_MODE_INPUT(GPIOE_PIN3) | \
+ PIN_MODE_INPUT(GPIOE_PIN4) | \
+ PIN_MODE_INPUT(GPIOE_PIN5) | \
+ PIN_MODE_INPUT(GPIOE_PIN6) | \
+ PIN_MODE_INPUT(GPIOE_PIN7) | \
+ PIN_MODE_INPUT(GPIOE_PIN8) | \
+ PIN_MODE_INPUT(GPIOE_PIN9) | \
+ PIN_MODE_INPUT(GPIOE_PIN10) | \
+ PIN_MODE_INPUT(GPIOE_PIN11) | \
+ PIN_MODE_INPUT(GPIOE_PIN12) | \
+ PIN_MODE_INPUT(GPIOE_PIN13) | \
+ PIN_MODE_INPUT(GPIOE_PIN14) | \
+ PIN_MODE_INPUT(GPIOE_PIN15))
+#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN15))
+#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOE_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOE_PIN15))
+#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOE_PIN15))
+#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | \
+ PIN_ODR_HIGH(GPIOE_PIN1) | \
+ PIN_ODR_HIGH(GPIOE_PIN2) | \
+ PIN_ODR_HIGH(GPIOE_PIN3) | \
+ PIN_ODR_HIGH(GPIOE_PIN4) | \
+ PIN_ODR_HIGH(GPIOE_PIN5) | \
+ PIN_ODR_HIGH(GPIOE_PIN6) | \
+ PIN_ODR_HIGH(GPIOE_PIN7) | \
+ PIN_ODR_HIGH(GPIOE_PIN8) | \
+ PIN_ODR_HIGH(GPIOE_PIN9) | \
+ PIN_ODR_HIGH(GPIOE_PIN10) | \
+ PIN_ODR_HIGH(GPIOE_PIN11) | \
+ PIN_ODR_HIGH(GPIOE_PIN12) | \
+ PIN_ODR_HIGH(GPIOE_PIN13) | \
+ PIN_ODR_HIGH(GPIOE_PIN14) | \
+ PIN_ODR_HIGH(GPIOE_PIN15))
+#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN7, 0U))
+#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN15, 0U))
+
+/*
+ * GPIOF setup:
+ *
+ * PF0 - PIN0 (input pullup).
+ * PF1 - PIN1 (input pullup).
+ * PF2 - PIN2 (input pullup).
+ * PF3 - PIN3 (input pullup).
+ * PF4 - PIN4 (input pullup).
+ * PF5 - PIN5 (input pullup).
+ * PF6 - PIN6 (input pullup).
+ * PF7 - PIN7 (input pullup).
+ * PF8 - PIN8 (input pullup).
+ * PF9 - PIN9 (input pullup).
+ * PF10 - PIN10 (input pullup).
+ * PF11 - PIN11 (input pullup).
+ * PF12 - PIN12 (input pullup).
+ * PF13 - PIN13 (input pullup).
+ * PF14 - PIN14 (input pullup).
+ * PF15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_PIN0) | \
+ PIN_MODE_INPUT(GPIOF_PIN1) | \
+ PIN_MODE_INPUT(GPIOF_PIN2) | \
+ PIN_MODE_INPUT(GPIOF_PIN3) | \
+ PIN_MODE_INPUT(GPIOF_PIN4) | \
+ PIN_MODE_INPUT(GPIOF_PIN5) | \
+ PIN_MODE_INPUT(GPIOF_PIN6) | \
+ PIN_MODE_INPUT(GPIOF_PIN7) | \
+ PIN_MODE_INPUT(GPIOF_PIN8) | \
+ PIN_MODE_INPUT(GPIOF_PIN9) | \
+ PIN_MODE_INPUT(GPIOF_PIN10) | \
+ PIN_MODE_INPUT(GPIOF_PIN11) | \
+ PIN_MODE_INPUT(GPIOF_PIN12) | \
+ PIN_MODE_INPUT(GPIOF_PIN13) | \
+ PIN_MODE_INPUT(GPIOF_PIN14) | \
+ PIN_MODE_INPUT(GPIOF_PIN15))
+#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN15))
+#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOF_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOF_PIN15))
+#define VAL_GPIOF_PUPDR (PIN_PUPDR_PULLUP(GPIOF_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOF_PIN15))
+#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_PIN0) | \
+ PIN_ODR_HIGH(GPIOF_PIN1) | \
+ PIN_ODR_HIGH(GPIOF_PIN2) | \
+ PIN_ODR_HIGH(GPIOF_PIN3) | \
+ PIN_ODR_HIGH(GPIOF_PIN4) | \
+ PIN_ODR_HIGH(GPIOF_PIN5) | \
+ PIN_ODR_HIGH(GPIOF_PIN6) | \
+ PIN_ODR_HIGH(GPIOF_PIN7) | \
+ PIN_ODR_HIGH(GPIOF_PIN8) | \
+ PIN_ODR_HIGH(GPIOF_PIN9) | \
+ PIN_ODR_HIGH(GPIOF_PIN10) | \
+ PIN_ODR_HIGH(GPIOF_PIN11) | \
+ PIN_ODR_HIGH(GPIOF_PIN12) | \
+ PIN_ODR_HIGH(GPIOF_PIN13) | \
+ PIN_ODR_HIGH(GPIOF_PIN14) | \
+ PIN_ODR_HIGH(GPIOF_PIN15))
+#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN7, 0U))
+#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN15, 0U))
+
+/*
+ * GPIOG setup:
+ *
+ * PG0 - PIN0 (input pullup).
+ * PG1 - PIN1 (input pullup).
+ * PG2 - PIN2 (input pullup).
+ * PG3 - PIN3 (input pullup).
+ * PG4 - PIN4 (input pullup).
+ * PG5 - PIN5 (input pullup).
+ * PG6 - PIN6 (input pullup).
+ * PG7 - PIN7 (input pullup).
+ * PG8 - PIN8 (input pullup).
+ * PG9 - PIN9 (input pullup).
+ * PG10 - PIN10 (input pullup).
+ * PG11 - PIN11 (input pullup).
+ * PG12 - PIN12 (input pullup).
+ * PG13 - PIN13 (input pullup).
+ * PG14 - PIN14 (input pullup).
+ * PG15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOG_MODER (PIN_MODE_INPUT(GPIOG_PIN0) | \
+ PIN_MODE_INPUT(GPIOG_PIN1) | \
+ PIN_MODE_INPUT(GPIOG_PIN2) | \
+ PIN_MODE_INPUT(GPIOG_PIN3) | \
+ PIN_MODE_INPUT(GPIOG_PIN4) | \
+ PIN_MODE_INPUT(GPIOG_PIN5) | \
+ PIN_MODE_INPUT(GPIOG_PIN6) | \
+ PIN_MODE_INPUT(GPIOG_PIN7) | \
+ PIN_MODE_INPUT(GPIOG_PIN8) | \
+ PIN_MODE_INPUT(GPIOG_PIN9) | \
+ PIN_MODE_INPUT(GPIOG_PIN10) | \
+ PIN_MODE_INPUT(GPIOG_PIN11) | \
+ PIN_MODE_INPUT(GPIOG_PIN12) | \
+ PIN_MODE_INPUT(GPIOG_PIN13) | \
+ PIN_MODE_INPUT(GPIOG_PIN14) | \
+ PIN_MODE_INPUT(GPIOG_PIN15))
+#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN15))
+#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOG_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN15))
+#define VAL_GPIOG_PUPDR (PIN_PUPDR_PULLUP(GPIOG_PIN0) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN1) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOG_PIN15))
+#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_PIN0) | \
+ PIN_ODR_HIGH(GPIOG_PIN1) | \
+ PIN_ODR_HIGH(GPIOG_PIN2) | \
+ PIN_ODR_HIGH(GPIOG_PIN3) | \
+ PIN_ODR_HIGH(GPIOG_PIN4) | \
+ PIN_ODR_HIGH(GPIOG_PIN5) | \
+ PIN_ODR_HIGH(GPIOG_PIN6) | \
+ PIN_ODR_HIGH(GPIOG_PIN7) | \
+ PIN_ODR_HIGH(GPIOG_PIN8) | \
+ PIN_ODR_HIGH(GPIOG_PIN9) | \
+ PIN_ODR_HIGH(GPIOG_PIN10) | \
+ PIN_ODR_HIGH(GPIOG_PIN11) | \
+ PIN_ODR_HIGH(GPIOG_PIN12) | \
+ PIN_ODR_HIGH(GPIOG_PIN13) | \
+ PIN_ODR_HIGH(GPIOG_PIN14) | \
+ PIN_ODR_HIGH(GPIOG_PIN15))
+#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN7, 0U))
+#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN15, 0U))
+
+/*
+ * GPIOH setup:
+ *
+ * PH0 - OSC_IN (input floating).
+ * PH1 - OSC_OUT (input floating).
+ * PH2 - PIN2 (input pullup).
+ * PH3 - PIN3 (input pullup).
+ * PH4 - PIN4 (input pullup).
+ * PH5 - PIN5 (input pullup).
+ * PH6 - PIN6 (input pullup).
+ * PH7 - PIN7 (input pullup).
+ * PH8 - PIN8 (input pullup).
+ * PH9 - PIN9 (input pullup).
+ * PH10 - PIN10 (input pullup).
+ * PH11 - PIN11 (input pullup).
+ * PH12 - PIN12 (input pullup).
+ * PH13 - PIN13 (input pullup).
+ * PH14 - PIN14 (input pullup).
+ * PH15 - PIN15 (input pullup).
+ */
+#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_OSC_IN) | \
+ PIN_MODE_INPUT(GPIOH_OSC_OUT) | \
+ PIN_MODE_INPUT(GPIOH_PIN2) | \
+ PIN_MODE_INPUT(GPIOH_PIN3) | \
+ PIN_MODE_INPUT(GPIOH_PIN4) | \
+ PIN_MODE_INPUT(GPIOH_PIN5) | \
+ PIN_MODE_INPUT(GPIOH_PIN6) | \
+ PIN_MODE_INPUT(GPIOH_PIN7) | \
+ PIN_MODE_INPUT(GPIOH_PIN8) | \
+ PIN_MODE_INPUT(GPIOH_PIN9) | \
+ PIN_MODE_INPUT(GPIOH_PIN10) | \
+ PIN_MODE_INPUT(GPIOH_PIN11) | \
+ PIN_MODE_INPUT(GPIOH_PIN12) | \
+ PIN_MODE_INPUT(GPIOH_PIN13) | \
+ PIN_MODE_INPUT(GPIOH_PIN14) | \
+ PIN_MODE_INPUT(GPIOH_PIN15))
+#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_OSC_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_OSC_OUT) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN15))
+#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_HIGH(GPIOH_OSC_IN) | \
+ PIN_OSPEED_HIGH(GPIOH_OSC_OUT) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN15))
+#define VAL_GPIOH_PUPDR (PIN_PUPDR_FLOATING(GPIOH_OSC_IN) | \
+ PIN_PUPDR_FLOATING(GPIOH_OSC_OUT) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN2) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN3) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN4) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN5) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN6) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN7) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN8) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN9) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN10) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN11) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN13) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN14) | \
+ PIN_PUPDR_PULLUP(GPIOH_PIN15))
+#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_OSC_IN) | \
+ PIN_ODR_HIGH(GPIOH_OSC_OUT) | \
+ PIN_ODR_HIGH(GPIOH_PIN2) | \
+ PIN_ODR_HIGH(GPIOH_PIN3) | \
+ PIN_ODR_HIGH(GPIOH_PIN4) | \
+ PIN_ODR_HIGH(GPIOH_PIN5) | \
+ PIN_ODR_HIGH(GPIOH_PIN6) | \
+ PIN_ODR_HIGH(GPIOH_PIN7) | \
+ PIN_ODR_HIGH(GPIOH_PIN8) | \
+ PIN_ODR_HIGH(GPIOH_PIN9) | \
+ PIN_ODR_HIGH(GPIOH_PIN10) | \
+ PIN_ODR_HIGH(GPIOH_PIN11) | \
+ PIN_ODR_HIGH(GPIOH_PIN12) | \
+ PIN_ODR_HIGH(GPIOH_PIN13) | \
+ PIN_ODR_HIGH(GPIOH_PIN14) | \
+ PIN_ODR_HIGH(GPIOH_PIN15))
+#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_OSC_IN, 0U) | \
+ PIN_AFIO_AF(GPIOH_OSC_OUT, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN7, 0U))
+#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN15, 0U))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* BOARD_H */
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L152RE/board.mk b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L152RE/board.mk
new file mode 100644
index 0000000..8535ad1
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L152RE/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_L152RE/board.c
+
+# Required include directories
+BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_L152RE
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC += $(BOARDINC)
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L152RE/cfg/board.chcfg b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L152RE/cfg/board.chcfg
new file mode 100644
index 0000000..fd034a6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L152RE/cfg/board.chcfg
@@ -0,0 +1,1063 @@
+
+
+
+
+ resources/gencfg/processors/boards/stm32l1xx/templates
+ ..
+ 5.0.x
+
+ STMicroelectronics STM32 Nucleo64-L152RE
+ ST_NUCLEO64_L152RE
+
+ STM32L152xE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L152RE/cfg/board.fmpp b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L152RE/cfg/board.fmpp
new file mode 100644
index 0000000..029da4f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L152RE/cfg/board.fmpp
@@ -0,0 +1,15 @@
+sourceRoot: ../../../../../tools/ftl/processors/boards/stm32l1xx/templates
+outputRoot: ..
+dataRoot: .
+
+freemarkerLinks: {
+ lib: ../../../../../tools/ftl/libs
+}
+
+data : {
+ doc1:xml (
+ board.chcfg
+ {
+ }
+ )
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L452RE_P/board.c b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L452RE_P/board.c
new file mode 100644
index 0000000..cd16e43
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L452RE_P/board.c
@@ -0,0 +1,281 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#include "hal.h"
+#include "stm32_gpio.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of STM32 GPIO port setup.
+ */
+typedef struct {
+ uint32_t moder;
+ uint32_t otyper;
+ uint32_t ospeedr;
+ uint32_t pupdr;
+ uint32_t odr;
+ uint32_t afrl;
+ uint32_t afrh;
+ uint32_t ascr;
+ uint32_t lockr;
+} gpio_setup_t;
+
+/**
+ * @brief Type of STM32 GPIO initialization data.
+ */
+typedef struct {
+#if STM32_HAS_GPIOA || defined(__DOXYGEN__)
+ gpio_setup_t PAData;
+#endif
+#if STM32_HAS_GPIOB || defined(__DOXYGEN__)
+ gpio_setup_t PBData;
+#endif
+#if STM32_HAS_GPIOC || defined(__DOXYGEN__)
+ gpio_setup_t PCData;
+#endif
+#if STM32_HAS_GPIOD || defined(__DOXYGEN__)
+ gpio_setup_t PDData;
+#endif
+#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
+ gpio_setup_t PEData;
+#endif
+#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
+ gpio_setup_t PFData;
+#endif
+#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
+ gpio_setup_t PGData;
+#endif
+#if STM32_HAS_GPIOH || defined(__DOXYGEN__)
+ gpio_setup_t PHData;
+#endif
+#if STM32_HAS_GPIOI || defined(__DOXYGEN__)
+ gpio_setup_t PIData;
+#endif
+#if STM32_HAS_GPIOJ || defined(__DOXYGEN__)
+ gpio_setup_t PJData;
+#endif
+#if STM32_HAS_GPIOK || defined(__DOXYGEN__)
+ gpio_setup_t PKData;
+#endif
+} gpio_config_t;
+
+/**
+ * @brief STM32 GPIO static initialization data.
+ */
+static const gpio_config_t gpio_default_config = {
+#if STM32_HAS_GPIOA
+ {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
+ VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH, VAL_GPIOA_ASCR,
+ VAL_GPIOA_LOCKR},
+#endif
+#if STM32_HAS_GPIOB
+ {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR,
+ VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH, VAL_GPIOB_ASCR,
+ VAL_GPIOB_LOCKR},
+#endif
+#if STM32_HAS_GPIOC
+ {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR,
+ VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH, VAL_GPIOC_ASCR,
+ VAL_GPIOC_LOCKR},
+#endif
+#if STM32_HAS_GPIOD
+ {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR,
+ VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH, VAL_GPIOD_ASCR,
+ VAL_GPIOD_LOCKR},
+#endif
+#if STM32_HAS_GPIOE
+ {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR,
+ VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH, VAL_GPIOE_ASCR,
+ VAL_GPIOE_LOCKR},
+#endif
+#if STM32_HAS_GPIOF
+ {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR,
+ VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH, VAL_GPIOF_ASCR,
+ VAL_GPIOF_LOCKR},
+#endif
+#if STM32_HAS_GPIOG
+ {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR,
+ VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH, VAL_GPIOG_ASCR,
+ VAL_GPIOG_LOCKR},
+#endif
+#if STM32_HAS_GPIOH
+ {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR,
+ VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH, VAL_GPIOH_ASCR,
+ VAL_GPIOH_LOCKR},
+#endif
+#if STM32_HAS_GPIOI
+ {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
+ VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH, VAL_GPIOI_ASCR,
+ VAL_GPIOI_LOCKR},
+#endif
+#if STM32_HAS_GPIOJ
+ {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR,
+ VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH, VAL_GPIOJ_ASCR,
+ VAL_GPIOJ_LOCKR},
+#endif
+#if STM32_HAS_GPIOK
+ {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR,
+ VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH, VAL_GPIOK_ASCR,
+ VAL_GPIOK_LOCKR}
+#endif
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) {
+
+ gpiop->OTYPER = config->otyper;
+ gpiop->ASCR = config->ascr;
+ gpiop->OSPEEDR = config->ospeedr;
+ gpiop->PUPDR = config->pupdr;
+ gpiop->ODR = config->odr;
+ gpiop->AFRL = config->afrl;
+ gpiop->AFRH = config->afrh;
+ gpiop->MODER = config->moder;
+ gpiop->LOCKR = config->lockr;
+}
+
+static void stm32_gpio_init(void) {
+
+ /* Enabling GPIO-related clocks, the mask comes from the
+ registry header file.*/
+ rccResetAHB2(STM32_GPIO_EN_MASK);
+ rccEnableAHB2(STM32_GPIO_EN_MASK, true);
+
+ /* Initializing all the defined GPIO ports.*/
+#if STM32_HAS_GPIOA
+ gpio_init(GPIOA, &gpio_default_config.PAData);
+#endif
+#if STM32_HAS_GPIOB
+ gpio_init(GPIOB, &gpio_default_config.PBData);
+#endif
+#if STM32_HAS_GPIOC
+ gpio_init(GPIOC, &gpio_default_config.PCData);
+#endif
+#if STM32_HAS_GPIOD
+ gpio_init(GPIOD, &gpio_default_config.PDData);
+#endif
+#if STM32_HAS_GPIOE
+ gpio_init(GPIOE, &gpio_default_config.PEData);
+#endif
+#if STM32_HAS_GPIOF
+ gpio_init(GPIOF, &gpio_default_config.PFData);
+#endif
+#if STM32_HAS_GPIOG
+ gpio_init(GPIOG, &gpio_default_config.PGData);
+#endif
+#if STM32_HAS_GPIOH
+ gpio_init(GPIOH, &gpio_default_config.PHData);
+#endif
+#if STM32_HAS_GPIOI
+ gpio_init(GPIOI, &gpio_default_config.PIData);
+#endif
+#if STM32_HAS_GPIOJ
+ gpio_init(GPIOJ, &gpio_default_config.PJData);
+#endif
+#if STM32_HAS_GPIOK
+ gpio_init(GPIOK, &gpio_default_config.PKData);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Early initialization code.
+ * @details GPIO ports and system clocks are initialized before everything
+ * else.
+ */
+void __early_init(void) {
+
+ stm32_gpio_init();
+ stm32_clock_init();
+}
+
+#if HAL_USE_SDC || defined(__DOXYGEN__)
+/**
+ * @brief SDC card detection.
+ */
+bool sdc_lld_is_card_inserted(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief SDC card write protection detection.
+ */
+bool sdc_lld_is_write_protected(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif /* HAL_USE_SDC */
+
+#if HAL_USE_MMC_SPI || defined(__DOXYGEN__)
+/**
+ * @brief MMC_SPI card detection.
+ */
+bool mmc_lld_is_card_inserted(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief MMC_SPI card write protection detection.
+ */
+bool mmc_lld_is_write_protected(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif
+
+/**
+ * @brief Board-specific initialization code.
+ * @note You can add your board-specific code here.
+ */
+void boardInit(void) {
+
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L452RE_P/board.h b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L452RE_P/board.h
new file mode 100644
index 0000000..43c5350
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L452RE_P/board.h
@@ -0,0 +1,1505 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#ifndef BOARD_H
+#define BOARD_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*
+ * Setup for STMicroelectronics STM32 Nucleo64-L452RE-P board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_ST_NUCLEO64_L452RE_P
+#define BOARD_NAME "STMicroelectronics STM32 Nucleo64-L452RE-P"
+
+/*
+ * Board oscillators-related settings.
+ */
+#if !defined(STM32_LSECLK)
+#define STM32_LSECLK 32768U
+#endif
+
+#define STM32_LSEDRV (3U << 3U)
+
+#if !defined(STM32_HSECLK)
+#define STM32_HSECLK 8000000U
+#endif
+
+#define STM32_HSE_BYPASS
+
+/*
+ * Board voltages.
+ * Required for performance limits calculation.
+ */
+#define STM32_VDD 300U
+
+/*
+ * MCU type as defined in the ST header.
+ */
+#define STM32L452xx
+
+/*
+ * IO pins assignments.
+ */
+#define GPIOA_ARD_A0 0U
+#define GPIOA_ADC1_IN5 0U
+#define GPIOA_ARD_A1 1U
+#define GPIOA_ADC1_IN6 1U
+#define GPIOA_STLINK_TX 2U
+#define GPIOA_STLINK_RX 3U
+#define GPIOA_SMPS_EN 4U
+#define GPIOA_SMPS_V1 5U
+#define GPIOA_SMPS_PG 6U
+#define GPIOA_SMPS_SW 7U
+#define GPIOA_ARD_D9 8U
+#define GPIOA_ARD_D1_TX 9U
+#define GPIOA_ARD_D0_RX 10U
+#define GPIOA_ARD_D10 11U
+#define GPIOA_ARD_D2 12U
+#define GPIOA_SWDIO 13U
+#define GPIOA_SWCLK 14U
+#define GPIOA_ARD_D5 15U
+
+#define GPIOB_PIN0 0U
+#define GPIOB_PIN1 1U
+#define GPIOB_PIN2 2U
+#define GPIOB_ARD_D3 3U
+#define GPIOB_PIN4 4U
+#define GPIOB_ARD_D4 5U
+#define GPIOB_ARD_D8 6U
+#define GPIOB_ARD_D14 7U
+#define GPIOB_ARD_D15 8U
+#define GPIOB_PIN9 9U
+#define GPIOB_ARD_D6 10U
+#define GPIOB_PIN11 11U
+#define GPIOB_PIN12 12U
+#define GPIOB_ARD_D13 13U
+#define GPIOB_LED_GREEN 13U
+#define GPIOB_ARD_D12 14U
+#define GPIOB_ARD_D11 15U
+
+#define GPIOC_ARD_A5 0U
+#define GPIOC_ADC1_IN1 0U
+#define GPIOC_ARD_A4 1U
+#define GPIOC_ADC1_IN2 1U
+#define GPIOC_ARD_A3 2U
+#define GPIOC_ADC1_IN3 2U
+#define GPIOC_ARD_A2 3U
+#define GPIOC_ADC1_IN4 3U
+#define GPIOC_PIN4 4U
+#define GPIOC_PIN5 5U
+#define GPIOC_PIN6 6U
+#define GPIOC_ARD_D7 7U
+#define GPIOC_PIN8 8U
+#define GPIOC_PIN9 9U
+#define GPIOC_PIN10 10U
+#define GPIOC_PIN11 11U
+#define GPIOC_PIN12 12U
+#define GPIOC_BUTTON 13U
+#define GPIOC_OSC32_IN 14U
+#define GPIOC_OSC32_OUT 15U
+
+#define GPIOD_PIN0 0U
+#define GPIOD_PIN1 1U
+#define GPIOD_PIN2 2U
+#define GPIOD_PIN3 3U
+#define GPIOD_PIN4 4U
+#define GPIOD_PIN5 5U
+#define GPIOD_PIN6 6U
+#define GPIOD_PIN7 7U
+#define GPIOD_PIN8 8U
+#define GPIOD_PIN9 9U
+#define GPIOD_PIN10 10U
+#define GPIOD_PIN11 11U
+#define GPIOD_PIN12 12U
+#define GPIOD_PIN13 13U
+#define GPIOD_PIN14 14U
+#define GPIOD_PIN15 15U
+
+#define GPIOE_PIN0 0U
+#define GPIOE_PIN1 1U
+#define GPIOE_PIN2 2U
+#define GPIOE_PIN3 3U
+#define GPIOE_PIN4 4U
+#define GPIOE_PIN5 5U
+#define GPIOE_PIN6 6U
+#define GPIOE_PIN7 7U
+#define GPIOE_PIN8 8U
+#define GPIOE_PIN9 9U
+#define GPIOE_PIN10 10U
+#define GPIOE_PIN11 11U
+#define GPIOE_PIN12 12U
+#define GPIOE_PIN13 13U
+#define GPIOE_PIN14 14U
+#define GPIOE_PIN15 15U
+
+#define GPIOF_PIN0 0U
+#define GPIOF_PIN1 1U
+#define GPIOF_PIN2 2U
+#define GPIOF_PIN3 3U
+#define GPIOF_PIN4 4U
+#define GPIOF_PIN5 5U
+#define GPIOF_PIN6 6U
+#define GPIOF_PIN7 7U
+#define GPIOF_PIN8 8U
+#define GPIOF_PIN9 9U
+#define GPIOF_PIN10 10U
+#define GPIOF_PIN11 11U
+#define GPIOF_PIN12 12U
+#define GPIOF_PIN13 13U
+#define GPIOF_PIN14 14U
+#define GPIOF_PIN15 15U
+
+#define GPIOG_PIN0 0U
+#define GPIOG_PIN1 1U
+#define GPIOG_PIN2 2U
+#define GPIOG_PIN3 3U
+#define GPIOG_PIN4 4U
+#define GPIOG_PIN5 5U
+#define GPIOG_PIN6 6U
+#define GPIOG_PIN7 7U
+#define GPIOG_PIN8 8U
+#define GPIOG_PIN9 9U
+#define GPIOG_PIN10 10U
+#define GPIOG_PIN11 11U
+#define GPIOG_PIN12 12U
+#define GPIOG_PIN13 13U
+#define GPIOG_PIN14 14U
+#define GPIOG_PIN15 15U
+
+#define GPIOH_OSC_IN 0U
+#define GPIOH_OSC_OUT 1U
+#define GPIOH_PIN2 2U
+#define GPIOH_PIN3 3U
+#define GPIOH_PIN4 4U
+#define GPIOH_PIN5 5U
+#define GPIOH_PIN6 6U
+#define GPIOH_PIN7 7U
+#define GPIOH_PIN8 8U
+#define GPIOH_PIN9 9U
+#define GPIOH_PIN10 10U
+#define GPIOH_PIN11 11U
+#define GPIOH_PIN12 12U
+#define GPIOH_PIN13 13U
+#define GPIOH_PIN14 14U
+#define GPIOH_PIN15 15U
+
+/*
+ * IO lines assignments.
+ */
+#define LINE_ARD_A0 PAL_LINE(GPIOA, 0U)
+#define LINE_ADC1_IN5 PAL_LINE(GPIOA, 0U)
+#define LINE_ARD_A1 PAL_LINE(GPIOA, 1U)
+#define LINE_ADC1_IN6 PAL_LINE(GPIOA, 1U)
+#define LINE_STLINK_TX PAL_LINE(GPIOA, 2U)
+#define LINE_STLINK_RX PAL_LINE(GPIOA, 3U)
+#define LINE_SMPS_EN PAL_LINE(GPIOA, 4U)
+#define LINE_SMPS_V1 PAL_LINE(GPIOA, 5U)
+#define LINE_SMPS_PG PAL_LINE(GPIOA, 6U)
+#define LINE_SMPS_SW PAL_LINE(GPIOA, 7U)
+#define LINE_ARD_D9 PAL_LINE(GPIOA, 8U)
+#define LINE_ARD_D1_TX PAL_LINE(GPIOA, 9U)
+#define LINE_ARD_D0_RX PAL_LINE(GPIOA, 10U)
+#define LINE_ARD_D10 PAL_LINE(GPIOA, 11U)
+#define LINE_ARD_D2 PAL_LINE(GPIOA, 12U)
+#define LINE_SWDIO PAL_LINE(GPIOA, 13U)
+#define LINE_SWCLK PAL_LINE(GPIOA, 14U)
+#define LINE_ARD_D5 PAL_LINE(GPIOA, 15U)
+#define LINE_ARD_D3 PAL_LINE(GPIOB, 3U)
+#define LINE_ARD_D4 PAL_LINE(GPIOB, 5U)
+#define LINE_ARD_D8 PAL_LINE(GPIOB, 6U)
+#define LINE_ARD_D14 PAL_LINE(GPIOB, 7U)
+#define LINE_ARD_D15 PAL_LINE(GPIOB, 8U)
+#define LINE_ARD_D6 PAL_LINE(GPIOB, 10U)
+#define LINE_ARD_D13 PAL_LINE(GPIOB, 13U)
+#define LINE_LED_GREEN PAL_LINE(GPIOB, 13U)
+#define LINE_ARD_D12 PAL_LINE(GPIOB, 14U)
+#define LINE_ARD_D11 PAL_LINE(GPIOB, 15U)
+#define LINE_ARD_A5 PAL_LINE(GPIOC, 0U)
+#define LINE_ADC1_IN1 PAL_LINE(GPIOC, 0U)
+#define LINE_ARD_A4 PAL_LINE(GPIOC, 1U)
+#define LINE_ADC1_IN2 PAL_LINE(GPIOC, 1U)
+#define LINE_ARD_A3 PAL_LINE(GPIOC, 2U)
+#define LINE_ADC1_IN3 PAL_LINE(GPIOC, 2U)
+#define LINE_ARD_A2 PAL_LINE(GPIOC, 3U)
+#define LINE_ADC1_IN4 PAL_LINE(GPIOC, 3U)
+#define LINE_ARD_D7 PAL_LINE(GPIOC, 7U)
+#define LINE_BUTTON PAL_LINE(GPIOC, 13U)
+#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U)
+#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U)
+#define LINE_OSC_IN PAL_LINE(GPIOH, 0U)
+#define LINE_OSC_OUT PAL_LINE(GPIOH, 1U)
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*
+ * I/O ports initial setup, this configuration is established soon after reset
+ * in the initialization code.
+ * Please refer to the STM32 Reference Manual for details.
+ */
+#define PIN_MODE_INPUT(n) (0U << ((n) * 2U))
+#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U))
+#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U))
+#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U))
+#define PIN_ODR_LOW(n) (0U << (n))
+#define PIN_ODR_HIGH(n) (1U << (n))
+#define PIN_OTYPE_PUSHPULL(n) (0U << (n))
+#define PIN_OTYPE_OPENDRAIN(n) (1U << (n))
+#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U))
+#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U))
+#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U))
+#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U))
+#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U))
+#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U))
+#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U))
+#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U))
+#define PIN_ASCR_DISABLED(n) (0U << (n))
+#define PIN_ASCR_ENABLED(n) (1U << (n))
+#define PIN_LOCKR_DISABLED(n) (0U << (n))
+#define PIN_LOCKR_ENABLED(n) (1U << (n))
+
+/*
+ * GPIOA setup:
+ *
+ * PA0 - ARD_A0 ADC1_IN5 (analog).
+ * PA1 - ARD_A1 ADC1_IN6 (analog).
+ * PA2 - STLINK_TX (alternate 8).
+ * PA3 - STLINK_RX (alternate 8).
+ * PA4 - SMPS_EN (analog).
+ * PA5 - SMPS_V1 (analog).
+ * PA6 - SMPS_PG (analog).
+ * PA7 - SMPS_SW (analog).
+ * PA8 - ARD_D9 (analog).
+ * PA9 - ARD_D1_TX (analog).
+ * PA10 - ARD_D0_RX (analog).
+ * PA11 - ARD_D10 (analog).
+ * PA12 - ARD_D2 (analog).
+ * PA13 - SWDIO (alternate 0).
+ * PA14 - SWCLK (alternate 0).
+ * PA15 - ARD_D5 (analog).
+ */
+#define VAL_GPIOA_MODER (PIN_MODE_ANALOG(GPIOA_ARD_A0) | \
+ PIN_MODE_ANALOG(GPIOA_ARD_A1) | \
+ PIN_MODE_ALTERNATE(GPIOA_STLINK_TX) | \
+ PIN_MODE_ALTERNATE(GPIOA_STLINK_RX) | \
+ PIN_MODE_ANALOG(GPIOA_SMPS_EN) | \
+ PIN_MODE_ANALOG(GPIOA_SMPS_V1) | \
+ PIN_MODE_ANALOG(GPIOA_SMPS_PG) | \
+ PIN_MODE_ANALOG(GPIOA_SMPS_SW) | \
+ PIN_MODE_ANALOG(GPIOA_ARD_D9) | \
+ PIN_MODE_ANALOG(GPIOA_ARD_D1_TX) | \
+ PIN_MODE_ANALOG(GPIOA_ARD_D0_RX) | \
+ PIN_MODE_ANALOG(GPIOA_ARD_D10) | \
+ PIN_MODE_ANALOG(GPIOA_ARD_D2) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \
+ PIN_MODE_ANALOG(GPIOA_ARD_D5))
+#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_ARD_A0) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_A1) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_STLINK_TX) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_STLINK_RX) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SMPS_EN) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SMPS_V1) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SMPS_PG) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SMPS_SW) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D9) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D1_TX) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D0_RX) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D10) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D2) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D5))
+#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_HIGH(GPIOA_ARD_A0) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_A1) | \
+ PIN_OSPEED_MEDIUM(GPIOA_STLINK_TX) | \
+ PIN_OSPEED_MEDIUM(GPIOA_STLINK_RX) | \
+ PIN_OSPEED_HIGH(GPIOA_SMPS_EN) | \
+ PIN_OSPEED_HIGH(GPIOA_SMPS_V1) | \
+ PIN_OSPEED_HIGH(GPIOA_SMPS_PG) | \
+ PIN_OSPEED_HIGH(GPIOA_SMPS_SW) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D9) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D1_TX) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D0_RX) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D10) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D2) | \
+ PIN_OSPEED_HIGH(GPIOA_SWDIO) | \
+ PIN_OSPEED_HIGH(GPIOA_SWCLK) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D5))
+#define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_ARD_A0) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_A1) | \
+ PIN_PUPDR_FLOATING(GPIOA_STLINK_TX) | \
+ PIN_PUPDR_FLOATING(GPIOA_STLINK_RX) | \
+ PIN_PUPDR_FLOATING(GPIOA_SMPS_EN) | \
+ PIN_PUPDR_FLOATING(GPIOA_SMPS_V1) | \
+ PIN_PUPDR_FLOATING(GPIOA_SMPS_PG) | \
+ PIN_PUPDR_FLOATING(GPIOA_SMPS_SW) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D9) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D1_TX) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D0_RX) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D10) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D2) | \
+ PIN_PUPDR_PULLUP(GPIOA_SWDIO) | \
+ PIN_PUPDR_PULLDOWN(GPIOA_SWCLK) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D5))
+#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_ARD_A0) | \
+ PIN_ODR_HIGH(GPIOA_ARD_A1) | \
+ PIN_ODR_HIGH(GPIOA_STLINK_TX) | \
+ PIN_ODR_HIGH(GPIOA_STLINK_RX) | \
+ PIN_ODR_HIGH(GPIOA_SMPS_EN) | \
+ PIN_ODR_HIGH(GPIOA_SMPS_V1) | \
+ PIN_ODR_HIGH(GPIOA_SMPS_PG) | \
+ PIN_ODR_HIGH(GPIOA_SMPS_SW) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D9) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D1_TX) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D0_RX) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D10) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D2) | \
+ PIN_ODR_HIGH(GPIOA_SWDIO) | \
+ PIN_ODR_HIGH(GPIOA_SWCLK) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D5))
+#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_ARD_A0, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_A1, 0U) | \
+ PIN_AFIO_AF(GPIOA_STLINK_TX, 8U) | \
+ PIN_AFIO_AF(GPIOA_STLINK_RX, 8U) | \
+ PIN_AFIO_AF(GPIOA_SMPS_EN, 0U) | \
+ PIN_AFIO_AF(GPIOA_SMPS_V1, 0U) | \
+ PIN_AFIO_AF(GPIOA_SMPS_PG, 0U) | \
+ PIN_AFIO_AF(GPIOA_SMPS_SW, 0U))
+#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_ARD_D9, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D1_TX, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D0_RX, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D10, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D2, 0U) | \
+ PIN_AFIO_AF(GPIOA_SWDIO, 0U) | \
+ PIN_AFIO_AF(GPIOA_SWCLK, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D5, 0U))
+#define VAL_GPIOA_ASCR (PIN_ASCR_DISABLED(GPIOA_ARD_A0) | \
+ PIN_ASCR_DISABLED(GPIOA_ARD_A1) | \
+ PIN_ASCR_DISABLED(GPIOA_STLINK_TX) | \
+ PIN_ASCR_DISABLED(GPIOA_STLINK_RX) | \
+ PIN_ASCR_DISABLED(GPIOA_SMPS_EN) | \
+ PIN_ASCR_DISABLED(GPIOA_SMPS_V1) | \
+ PIN_ASCR_DISABLED(GPIOA_SMPS_PG) | \
+ PIN_ASCR_DISABLED(GPIOA_SMPS_SW) | \
+ PIN_ASCR_DISABLED(GPIOA_ARD_D9) | \
+ PIN_ASCR_DISABLED(GPIOA_ARD_D1_TX) | \
+ PIN_ASCR_DISABLED(GPIOA_ARD_D0_RX) | \
+ PIN_ASCR_DISABLED(GPIOA_ARD_D10) | \
+ PIN_ASCR_DISABLED(GPIOA_ARD_D2) | \
+ PIN_ASCR_DISABLED(GPIOA_SWDIO) | \
+ PIN_ASCR_DISABLED(GPIOA_SWCLK) | \
+ PIN_ASCR_DISABLED(GPIOA_ARD_D5))
+#define VAL_GPIOA_LOCKR (PIN_LOCKR_DISABLED(GPIOA_ARD_A0) | \
+ PIN_LOCKR_DISABLED(GPIOA_ARD_A1) | \
+ PIN_LOCKR_DISABLED(GPIOA_STLINK_TX) | \
+ PIN_LOCKR_DISABLED(GPIOA_STLINK_RX) | \
+ PIN_LOCKR_DISABLED(GPIOA_SMPS_EN) | \
+ PIN_LOCKR_DISABLED(GPIOA_SMPS_V1) | \
+ PIN_LOCKR_DISABLED(GPIOA_SMPS_PG) | \
+ PIN_LOCKR_DISABLED(GPIOA_SMPS_SW) | \
+ PIN_LOCKR_DISABLED(GPIOA_ARD_D9) | \
+ PIN_LOCKR_DISABLED(GPIOA_ARD_D1_TX) | \
+ PIN_LOCKR_DISABLED(GPIOA_ARD_D0_RX) | \
+ PIN_LOCKR_DISABLED(GPIOA_ARD_D10) | \
+ PIN_LOCKR_DISABLED(GPIOA_ARD_D2) | \
+ PIN_LOCKR_DISABLED(GPIOA_SWDIO) | \
+ PIN_LOCKR_DISABLED(GPIOA_SWCLK) | \
+ PIN_LOCKR_DISABLED(GPIOA_ARD_D5))
+
+/*
+ * GPIOB setup:
+ *
+ * PB0 - PIN0 (analog).
+ * PB1 - PIN1 (analog).
+ * PB2 - PIN2 (analog).
+ * PB3 - ARD_D3 (analog).
+ * PB4 - PIN4 (analog).
+ * PB5 - ARD_D4 (analog).
+ * PB6 - ARD_D8 (analog).
+ * PB7 - ARD_D14 (analog).
+ * PB8 - ARD_D15 (analog).
+ * PB9 - PIN9 (analog).
+ * PB10 - ARD_D6 (analog).
+ * PB11 - PIN11 (analog).
+ * PB12 - PIN12 (analog).
+ * PB13 - ARD_D13 LED_GREEN (output pushpull maximum).
+ * PB14 - ARD_D12 (analog).
+ * PB15 - ARD_D11 (analog).
+ */
+#define VAL_GPIOB_MODER (PIN_MODE_ANALOG(GPIOB_PIN0) | \
+ PIN_MODE_ANALOG(GPIOB_PIN1) | \
+ PIN_MODE_ANALOG(GPIOB_PIN2) | \
+ PIN_MODE_ANALOG(GPIOB_ARD_D3) | \
+ PIN_MODE_ANALOG(GPIOB_PIN4) | \
+ PIN_MODE_ANALOG(GPIOB_ARD_D4) | \
+ PIN_MODE_ANALOG(GPIOB_ARD_D8) | \
+ PIN_MODE_ANALOG(GPIOB_ARD_D14) | \
+ PIN_MODE_ANALOG(GPIOB_ARD_D15) | \
+ PIN_MODE_ANALOG(GPIOB_PIN9) | \
+ PIN_MODE_ANALOG(GPIOB_ARD_D6) | \
+ PIN_MODE_ANALOG(GPIOB_PIN11) | \
+ PIN_MODE_ANALOG(GPIOB_PIN12) | \
+ PIN_MODE_OUTPUT(GPIOB_ARD_D13) | \
+ PIN_MODE_ANALOG(GPIOB_ARD_D12) | \
+ PIN_MODE_ANALOG(GPIOB_ARD_D11))
+#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D3) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D4) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D8) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D14) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D15) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D6) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D13) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D12) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D11))
+#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN1) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D3) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D4) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D8) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D14) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D15) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D6) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D13) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D12) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D11))
+#define VAL_GPIOB_PUPDR (PIN_PUPDR_FLOATING(GPIOB_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOB_ARD_D3) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOB_ARD_D4) | \
+ PIN_PUPDR_FLOATING(GPIOB_ARD_D8) | \
+ PIN_PUPDR_FLOATING(GPIOB_ARD_D14) | \
+ PIN_PUPDR_FLOATING(GPIOB_ARD_D15) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOB_ARD_D6) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOB_ARD_D13) | \
+ PIN_PUPDR_FLOATING(GPIOB_ARD_D12) | \
+ PIN_PUPDR_FLOATING(GPIOB_ARD_D11))
+#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_PIN0) | \
+ PIN_ODR_HIGH(GPIOB_PIN1) | \
+ PIN_ODR_HIGH(GPIOB_PIN2) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D3) | \
+ PIN_ODR_HIGH(GPIOB_PIN4) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D4) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D8) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D14) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D15) | \
+ PIN_ODR_HIGH(GPIOB_PIN9) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D6) | \
+ PIN_ODR_HIGH(GPIOB_PIN11) | \
+ PIN_ODR_HIGH(GPIOB_PIN12) | \
+ PIN_ODR_LOW(GPIOB_ARD_D13) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D12) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D11))
+#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D3, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D4, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D8, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D14, 0U))
+#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_ARD_D15, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D6, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D13, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D12, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D11, 0U))
+#define VAL_GPIOB_ASCR (PIN_ASCR_DISABLED(GPIOB_PIN0) | \
+ PIN_ASCR_DISABLED(GPIOB_PIN1) | \
+ PIN_ASCR_DISABLED(GPIOB_PIN2) | \
+ PIN_ASCR_DISABLED(GPIOB_ARD_D3) | \
+ PIN_ASCR_DISABLED(GPIOB_PIN4) | \
+ PIN_ASCR_DISABLED(GPIOB_ARD_D4) | \
+ PIN_ASCR_DISABLED(GPIOB_ARD_D8) | \
+ PIN_ASCR_DISABLED(GPIOB_ARD_D14) | \
+ PIN_ASCR_DISABLED(GPIOB_ARD_D15) | \
+ PIN_ASCR_DISABLED(GPIOB_PIN9) | \
+ PIN_ASCR_DISABLED(GPIOB_ARD_D6) | \
+ PIN_ASCR_DISABLED(GPIOB_PIN11) | \
+ PIN_ASCR_DISABLED(GPIOB_PIN12) | \
+ PIN_ASCR_DISABLED(GPIOB_ARD_D13) | \
+ PIN_ASCR_DISABLED(GPIOB_ARD_D12) | \
+ PIN_ASCR_DISABLED(GPIOB_ARD_D11))
+#define VAL_GPIOB_LOCKR (PIN_LOCKR_DISABLED(GPIOB_PIN0) | \
+ PIN_LOCKR_DISABLED(GPIOB_PIN1) | \
+ PIN_LOCKR_DISABLED(GPIOB_PIN2) | \
+ PIN_LOCKR_DISABLED(GPIOB_ARD_D3) | \
+ PIN_LOCKR_DISABLED(GPIOB_PIN4) | \
+ PIN_LOCKR_DISABLED(GPIOB_ARD_D4) | \
+ PIN_LOCKR_DISABLED(GPIOB_ARD_D8) | \
+ PIN_LOCKR_DISABLED(GPIOB_ARD_D14) | \
+ PIN_LOCKR_DISABLED(GPIOB_ARD_D15) | \
+ PIN_LOCKR_DISABLED(GPIOB_PIN9) | \
+ PIN_LOCKR_DISABLED(GPIOB_ARD_D6) | \
+ PIN_LOCKR_DISABLED(GPIOB_PIN11) | \
+ PIN_LOCKR_DISABLED(GPIOB_PIN12) | \
+ PIN_LOCKR_DISABLED(GPIOB_ARD_D13) | \
+ PIN_LOCKR_DISABLED(GPIOB_ARD_D12) | \
+ PIN_LOCKR_DISABLED(GPIOB_ARD_D11))
+
+/*
+ * GPIOC setup:
+ *
+ * PC0 - ARD_A5 ADC1_IN1 (analog).
+ * PC1 - ARD_A4 ADC1_IN2 (analog).
+ * PC2 - ARD_A3 ADC1_IN3 (analog).
+ * PC3 - ARD_A2 ADC1_IN4 (analog).
+ * PC4 - PIN4 (analog).
+ * PC5 - PIN5 (analog).
+ * PC6 - PIN6 (analog).
+ * PC7 - ARD_D7 (analog).
+ * PC8 - PIN8 (analog).
+ * PC9 - PIN9 (analog).
+ * PC10 - PIN10 (analog).
+ * PC11 - PIN11 (analog).
+ * PC12 - PIN12 (analog).
+ * PC13 - BUTTON (input floating).
+ * PC14 - OSC32_IN (input floating).
+ * PC15 - OSC32_OUT (input floating).
+ */
+#define VAL_GPIOC_MODER (PIN_MODE_ANALOG(GPIOC_ARD_A5) | \
+ PIN_MODE_ANALOG(GPIOC_ARD_A4) | \
+ PIN_MODE_ANALOG(GPIOC_ARD_A3) | \
+ PIN_MODE_ANALOG(GPIOC_ARD_A2) | \
+ PIN_MODE_ANALOG(GPIOC_PIN4) | \
+ PIN_MODE_ANALOG(GPIOC_PIN5) | \
+ PIN_MODE_ANALOG(GPIOC_PIN6) | \
+ PIN_MODE_ANALOG(GPIOC_ARD_D7) | \
+ PIN_MODE_ANALOG(GPIOC_PIN8) | \
+ PIN_MODE_ANALOG(GPIOC_PIN9) | \
+ PIN_MODE_ANALOG(GPIOC_PIN10) | \
+ PIN_MODE_ANALOG(GPIOC_PIN11) | \
+ PIN_MODE_ANALOG(GPIOC_PIN12) | \
+ PIN_MODE_INPUT(GPIOC_BUTTON) | \
+ PIN_MODE_INPUT(GPIOC_OSC32_IN) | \
+ PIN_MODE_INPUT(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_ARD_A5) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_ARD_A4) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_ARD_A3) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_ARD_A2) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_ARD_D7) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_BUTTON) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_ARD_A5) | \
+ PIN_OSPEED_HIGH(GPIOC_ARD_A4) | \
+ PIN_OSPEED_HIGH(GPIOC_ARD_A3) | \
+ PIN_OSPEED_HIGH(GPIOC_ARD_A2) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOC_ARD_D7) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOC_BUTTON) | \
+ PIN_OSPEED_HIGH(GPIOC_OSC32_IN) | \
+ PIN_OSPEED_HIGH(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_PUPDR (PIN_PUPDR_FLOATING(GPIOC_ARD_A5) | \
+ PIN_PUPDR_FLOATING(GPIOC_ARD_A4) | \
+ PIN_PUPDR_FLOATING(GPIOC_ARD_A3) | \
+ PIN_PUPDR_FLOATING(GPIOC_ARD_A2) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOC_ARD_D7) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOC_BUTTON) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_ARD_A5) | \
+ PIN_ODR_HIGH(GPIOC_ARD_A4) | \
+ PIN_ODR_HIGH(GPIOC_ARD_A3) | \
+ PIN_ODR_HIGH(GPIOC_ARD_A2) | \
+ PIN_ODR_HIGH(GPIOC_PIN4) | \
+ PIN_ODR_HIGH(GPIOC_PIN5) | \
+ PIN_ODR_HIGH(GPIOC_PIN6) | \
+ PIN_ODR_HIGH(GPIOC_ARD_D7) | \
+ PIN_ODR_HIGH(GPIOC_PIN8) | \
+ PIN_ODR_HIGH(GPIOC_PIN9) | \
+ PIN_ODR_HIGH(GPIOC_PIN10) | \
+ PIN_ODR_HIGH(GPIOC_PIN11) | \
+ PIN_ODR_HIGH(GPIOC_PIN12) | \
+ PIN_ODR_HIGH(GPIOC_BUTTON) | \
+ PIN_ODR_HIGH(GPIOC_OSC32_IN) | \
+ PIN_ODR_HIGH(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_ARD_A5, 0U) | \
+ PIN_AFIO_AF(GPIOC_ARD_A4, 0U) | \
+ PIN_AFIO_AF(GPIOC_ARD_A3, 0U) | \
+ PIN_AFIO_AF(GPIOC_ARD_A2, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOC_ARD_D7, 0U))
+#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOC_BUTTON, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U))
+#define VAL_GPIOC_ASCR (PIN_ASCR_DISABLED(GPIOC_ARD_A5) | \
+ PIN_ASCR_DISABLED(GPIOC_ARD_A4) | \
+ PIN_ASCR_DISABLED(GPIOC_ARD_A3) | \
+ PIN_ASCR_DISABLED(GPIOC_ARD_A2) | \
+ PIN_ASCR_DISABLED(GPIOC_PIN4) | \
+ PIN_ASCR_DISABLED(GPIOC_PIN5) | \
+ PIN_ASCR_DISABLED(GPIOC_PIN6) | \
+ PIN_ASCR_DISABLED(GPIOC_ARD_D7) | \
+ PIN_ASCR_DISABLED(GPIOC_PIN8) | \
+ PIN_ASCR_DISABLED(GPIOC_PIN9) | \
+ PIN_ASCR_DISABLED(GPIOC_PIN10) | \
+ PIN_ASCR_DISABLED(GPIOC_PIN11) | \
+ PIN_ASCR_DISABLED(GPIOC_PIN12) | \
+ PIN_ASCR_DISABLED(GPIOC_BUTTON) | \
+ PIN_ASCR_DISABLED(GPIOC_OSC32_IN) | \
+ PIN_ASCR_DISABLED(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_LOCKR (PIN_LOCKR_DISABLED(GPIOC_ARD_A5) | \
+ PIN_LOCKR_DISABLED(GPIOC_ARD_A4) | \
+ PIN_LOCKR_DISABLED(GPIOC_ARD_A3) | \
+ PIN_LOCKR_DISABLED(GPIOC_ARD_A2) | \
+ PIN_LOCKR_DISABLED(GPIOC_PIN4) | \
+ PIN_LOCKR_DISABLED(GPIOC_PIN5) | \
+ PIN_LOCKR_DISABLED(GPIOC_PIN6) | \
+ PIN_LOCKR_DISABLED(GPIOC_ARD_D7) | \
+ PIN_LOCKR_DISABLED(GPIOC_PIN8) | \
+ PIN_LOCKR_DISABLED(GPIOC_PIN9) | \
+ PIN_LOCKR_DISABLED(GPIOC_PIN10) | \
+ PIN_LOCKR_DISABLED(GPIOC_PIN11) | \
+ PIN_LOCKR_DISABLED(GPIOC_PIN12) | \
+ PIN_LOCKR_DISABLED(GPIOC_BUTTON) | \
+ PIN_LOCKR_DISABLED(GPIOC_OSC32_IN) | \
+ PIN_LOCKR_DISABLED(GPIOC_OSC32_OUT))
+
+/*
+ * GPIOD setup:
+ *
+ * PD0 - PIN0 (analog).
+ * PD1 - PIN1 (analog).
+ * PD2 - PIN2 (analog).
+ * PD3 - PIN3 (analog).
+ * PD4 - PIN4 (analog).
+ * PD5 - PIN5 (analog).
+ * PD6 - PIN6 (analog).
+ * PD7 - PIN7 (analog).
+ * PD8 - PIN8 (analog).
+ * PD9 - PIN9 (analog).
+ * PD10 - PIN10 (analog).
+ * PD11 - PIN11 (analog).
+ * PD12 - PIN12 (analog).
+ * PD13 - PIN13 (analog).
+ * PD14 - PIN14 (analog).
+ * PD15 - PIN15 (analog).
+ */
+#define VAL_GPIOD_MODER (PIN_MODE_ANALOG(GPIOD_PIN0) | \
+ PIN_MODE_ANALOG(GPIOD_PIN1) | \
+ PIN_MODE_ANALOG(GPIOD_PIN2) | \
+ PIN_MODE_ANALOG(GPIOD_PIN3) | \
+ PIN_MODE_ANALOG(GPIOD_PIN4) | \
+ PIN_MODE_ANALOG(GPIOD_PIN5) | \
+ PIN_MODE_ANALOG(GPIOD_PIN6) | \
+ PIN_MODE_ANALOG(GPIOD_PIN7) | \
+ PIN_MODE_ANALOG(GPIOD_PIN8) | \
+ PIN_MODE_ANALOG(GPIOD_PIN9) | \
+ PIN_MODE_ANALOG(GPIOD_PIN10) | \
+ PIN_MODE_ANALOG(GPIOD_PIN11) | \
+ PIN_MODE_ANALOG(GPIOD_PIN12) | \
+ PIN_MODE_ANALOG(GPIOD_PIN13) | \
+ PIN_MODE_ANALOG(GPIOD_PIN14) | \
+ PIN_MODE_ANALOG(GPIOD_PIN15))
+#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN15))
+#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_HIGH(GPIOD_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN1) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN15))
+#define VAL_GPIOD_PUPDR (PIN_PUPDR_FLOATING(GPIOD_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN15))
+#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \
+ PIN_ODR_HIGH(GPIOD_PIN1) | \
+ PIN_ODR_HIGH(GPIOD_PIN2) | \
+ PIN_ODR_HIGH(GPIOD_PIN3) | \
+ PIN_ODR_HIGH(GPIOD_PIN4) | \
+ PIN_ODR_HIGH(GPIOD_PIN5) | \
+ PIN_ODR_HIGH(GPIOD_PIN6) | \
+ PIN_ODR_HIGH(GPIOD_PIN7) | \
+ PIN_ODR_HIGH(GPIOD_PIN8) | \
+ PIN_ODR_HIGH(GPIOD_PIN9) | \
+ PIN_ODR_HIGH(GPIOD_PIN10) | \
+ PIN_ODR_HIGH(GPIOD_PIN11) | \
+ PIN_ODR_HIGH(GPIOD_PIN12) | \
+ PIN_ODR_HIGH(GPIOD_PIN13) | \
+ PIN_ODR_HIGH(GPIOD_PIN14) | \
+ PIN_ODR_HIGH(GPIOD_PIN15))
+#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN7, 0U))
+#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN15, 0U))
+#define VAL_GPIOD_ASCR (PIN_ASCR_DISABLED(GPIOD_PIN0) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN1) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN2) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN3) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN4) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN5) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN6) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN7) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN8) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN9) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN10) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN11) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN12) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN13) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN14) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN15))
+#define VAL_GPIOD_LOCKR (PIN_LOCKR_DISABLED(GPIOD_PIN0) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN1) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN2) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN3) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN4) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN5) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN6) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN7) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN8) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN9) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN10) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN11) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN12) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN13) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN14) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN15))
+
+/*
+ * GPIOE setup:
+ *
+ * PE0 - PIN0 (analog).
+ * PE1 - PIN1 (analog).
+ * PE2 - PIN2 (analog).
+ * PE3 - PIN3 (analog).
+ * PE4 - PIN4 (analog).
+ * PE5 - PIN5 (analog).
+ * PE6 - PIN6 (analog).
+ * PE7 - PIN7 (analog).
+ * PE8 - PIN8 (analog).
+ * PE9 - PIN9 (analog).
+ * PE10 - PIN10 (analog).
+ * PE11 - PIN11 (analog).
+ * PE12 - PIN12 (analog).
+ * PE13 - PIN13 (analog).
+ * PE14 - PIN14 (analog).
+ * PE15 - PIN15 (analog).
+ */
+#define VAL_GPIOE_MODER (PIN_MODE_ANALOG(GPIOE_PIN0) | \
+ PIN_MODE_ANALOG(GPIOE_PIN1) | \
+ PIN_MODE_ANALOG(GPIOE_PIN2) | \
+ PIN_MODE_ANALOG(GPIOE_PIN3) | \
+ PIN_MODE_ANALOG(GPIOE_PIN4) | \
+ PIN_MODE_ANALOG(GPIOE_PIN5) | \
+ PIN_MODE_ANALOG(GPIOE_PIN6) | \
+ PIN_MODE_ANALOG(GPIOE_PIN7) | \
+ PIN_MODE_ANALOG(GPIOE_PIN8) | \
+ PIN_MODE_ANALOG(GPIOE_PIN9) | \
+ PIN_MODE_ANALOG(GPIOE_PIN10) | \
+ PIN_MODE_ANALOG(GPIOE_PIN11) | \
+ PIN_MODE_ANALOG(GPIOE_PIN12) | \
+ PIN_MODE_ANALOG(GPIOE_PIN13) | \
+ PIN_MODE_ANALOG(GPIOE_PIN14) | \
+ PIN_MODE_ANALOG(GPIOE_PIN15))
+#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN15))
+#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_HIGH(GPIOE_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN1) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN15))
+#define VAL_GPIOE_PUPDR (PIN_PUPDR_FLOATING(GPIOE_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN15))
+#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | \
+ PIN_ODR_HIGH(GPIOE_PIN1) | \
+ PIN_ODR_HIGH(GPIOE_PIN2) | \
+ PIN_ODR_HIGH(GPIOE_PIN3) | \
+ PIN_ODR_HIGH(GPIOE_PIN4) | \
+ PIN_ODR_HIGH(GPIOE_PIN5) | \
+ PIN_ODR_HIGH(GPIOE_PIN6) | \
+ PIN_ODR_HIGH(GPIOE_PIN7) | \
+ PIN_ODR_HIGH(GPIOE_PIN8) | \
+ PIN_ODR_HIGH(GPIOE_PIN9) | \
+ PIN_ODR_HIGH(GPIOE_PIN10) | \
+ PIN_ODR_HIGH(GPIOE_PIN11) | \
+ PIN_ODR_HIGH(GPIOE_PIN12) | \
+ PIN_ODR_HIGH(GPIOE_PIN13) | \
+ PIN_ODR_HIGH(GPIOE_PIN14) | \
+ PIN_ODR_HIGH(GPIOE_PIN15))
+#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN7, 0U))
+#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN15, 0U))
+#define VAL_GPIOE_ASCR (PIN_ASCR_DISABLED(GPIOE_PIN0) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN1) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN2) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN3) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN4) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN5) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN6) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN7) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN8) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN9) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN10) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN11) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN12) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN13) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN14) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN15))
+#define VAL_GPIOE_LOCKR (PIN_LOCKR_DISABLED(GPIOE_PIN0) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN1) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN2) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN3) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN4) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN5) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN6) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN7) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN8) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN9) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN10) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN11) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN12) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN13) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN14) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN15))
+
+/*
+ * GPIOF setup:
+ *
+ * PF0 - PIN0 (analog).
+ * PF1 - PIN1 (analog).
+ * PF2 - PIN2 (analog).
+ * PF3 - PIN3 (analog).
+ * PF4 - PIN4 (analog).
+ * PF5 - PIN5 (analog).
+ * PF6 - PIN6 (analog).
+ * PF7 - PIN7 (analog).
+ * PF8 - PIN8 (analog).
+ * PF9 - PIN9 (analog).
+ * PF10 - PIN10 (analog).
+ * PF11 - PIN11 (analog).
+ * PF12 - PIN12 (analog).
+ * PF13 - PIN13 (analog).
+ * PF14 - PIN14 (analog).
+ * PF15 - PIN15 (analog).
+ */
+#define VAL_GPIOF_MODER (PIN_MODE_ANALOG(GPIOF_PIN0) | \
+ PIN_MODE_ANALOG(GPIOF_PIN1) | \
+ PIN_MODE_ANALOG(GPIOF_PIN2) | \
+ PIN_MODE_ANALOG(GPIOF_PIN3) | \
+ PIN_MODE_ANALOG(GPIOF_PIN4) | \
+ PIN_MODE_ANALOG(GPIOF_PIN5) | \
+ PIN_MODE_ANALOG(GPIOF_PIN6) | \
+ PIN_MODE_ANALOG(GPIOF_PIN7) | \
+ PIN_MODE_ANALOG(GPIOF_PIN8) | \
+ PIN_MODE_ANALOG(GPIOF_PIN9) | \
+ PIN_MODE_ANALOG(GPIOF_PIN10) | \
+ PIN_MODE_ANALOG(GPIOF_PIN11) | \
+ PIN_MODE_ANALOG(GPIOF_PIN12) | \
+ PIN_MODE_ANALOG(GPIOF_PIN13) | \
+ PIN_MODE_ANALOG(GPIOF_PIN14) | \
+ PIN_MODE_ANALOG(GPIOF_PIN15))
+#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN15))
+#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_HIGH(GPIOF_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN1) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN15))
+#define VAL_GPIOF_PUPDR (PIN_PUPDR_FLOATING(GPIOF_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN15))
+#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_PIN0) | \
+ PIN_ODR_HIGH(GPIOF_PIN1) | \
+ PIN_ODR_HIGH(GPIOF_PIN2) | \
+ PIN_ODR_HIGH(GPIOF_PIN3) | \
+ PIN_ODR_HIGH(GPIOF_PIN4) | \
+ PIN_ODR_HIGH(GPIOF_PIN5) | \
+ PIN_ODR_HIGH(GPIOF_PIN6) | \
+ PIN_ODR_HIGH(GPIOF_PIN7) | \
+ PIN_ODR_HIGH(GPIOF_PIN8) | \
+ PIN_ODR_HIGH(GPIOF_PIN9) | \
+ PIN_ODR_HIGH(GPIOF_PIN10) | \
+ PIN_ODR_HIGH(GPIOF_PIN11) | \
+ PIN_ODR_HIGH(GPIOF_PIN12) | \
+ PIN_ODR_HIGH(GPIOF_PIN13) | \
+ PIN_ODR_HIGH(GPIOF_PIN14) | \
+ PIN_ODR_HIGH(GPIOF_PIN15))
+#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN7, 0U))
+#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN15, 0U))
+#define VAL_GPIOF_ASCR (PIN_ASCR_DISABLED(GPIOF_PIN0) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN1) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN2) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN3) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN4) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN5) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN6) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN7) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN8) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN9) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN10) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN11) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN12) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN13) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN14) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN15))
+#define VAL_GPIOF_LOCKR (PIN_LOCKR_DISABLED(GPIOF_PIN0) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN1) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN2) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN3) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN4) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN5) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN6) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN7) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN8) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN9) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN10) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN11) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN12) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN13) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN14) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN15))
+
+/*
+ * GPIOG setup:
+ *
+ * PG0 - PIN0 (analog).
+ * PG1 - PIN1 (analog).
+ * PG2 - PIN2 (analog).
+ * PG3 - PIN3 (analog).
+ * PG4 - PIN4 (analog).
+ * PG5 - PIN5 (analog).
+ * PG6 - PIN6 (analog).
+ * PG7 - PIN7 (analog).
+ * PG8 - PIN8 (analog).
+ * PG9 - PIN9 (analog).
+ * PG10 - PIN10 (analog).
+ * PG11 - PIN11 (analog).
+ * PG12 - PIN12 (analog).
+ * PG13 - PIN13 (analog).
+ * PG14 - PIN14 (analog).
+ * PG15 - PIN15 (analog).
+ */
+#define VAL_GPIOG_MODER (PIN_MODE_ANALOG(GPIOG_PIN0) | \
+ PIN_MODE_ANALOG(GPIOG_PIN1) | \
+ PIN_MODE_ANALOG(GPIOG_PIN2) | \
+ PIN_MODE_ANALOG(GPIOG_PIN3) | \
+ PIN_MODE_ANALOG(GPIOG_PIN4) | \
+ PIN_MODE_ANALOG(GPIOG_PIN5) | \
+ PIN_MODE_ANALOG(GPIOG_PIN6) | \
+ PIN_MODE_ANALOG(GPIOG_PIN7) | \
+ PIN_MODE_ANALOG(GPIOG_PIN8) | \
+ PIN_MODE_ANALOG(GPIOG_PIN9) | \
+ PIN_MODE_ANALOG(GPIOG_PIN10) | \
+ PIN_MODE_ANALOG(GPIOG_PIN11) | \
+ PIN_MODE_ANALOG(GPIOG_PIN12) | \
+ PIN_MODE_ANALOG(GPIOG_PIN13) | \
+ PIN_MODE_ANALOG(GPIOG_PIN14) | \
+ PIN_MODE_ANALOG(GPIOG_PIN15))
+#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN15))
+#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOG_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN15))
+#define VAL_GPIOG_PUPDR (PIN_PUPDR_FLOATING(GPIOG_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN15))
+#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_PIN0) | \
+ PIN_ODR_HIGH(GPIOG_PIN1) | \
+ PIN_ODR_HIGH(GPIOG_PIN2) | \
+ PIN_ODR_HIGH(GPIOG_PIN3) | \
+ PIN_ODR_HIGH(GPIOG_PIN4) | \
+ PIN_ODR_HIGH(GPIOG_PIN5) | \
+ PIN_ODR_HIGH(GPIOG_PIN6) | \
+ PIN_ODR_HIGH(GPIOG_PIN7) | \
+ PIN_ODR_HIGH(GPIOG_PIN8) | \
+ PIN_ODR_HIGH(GPIOG_PIN9) | \
+ PIN_ODR_HIGH(GPIOG_PIN10) | \
+ PIN_ODR_HIGH(GPIOG_PIN11) | \
+ PIN_ODR_HIGH(GPIOG_PIN12) | \
+ PIN_ODR_HIGH(GPIOG_PIN13) | \
+ PIN_ODR_HIGH(GPIOG_PIN14) | \
+ PIN_ODR_HIGH(GPIOG_PIN15))
+#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN7, 0U))
+#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN15, 0U))
+#define VAL_GPIOG_ASCR (PIN_ASCR_DISABLED(GPIOG_PIN0) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN1) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN2) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN3) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN4) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN5) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN6) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN7) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN8) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN9) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN10) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN11) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN12) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN13) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN14) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN15))
+#define VAL_GPIOG_LOCKR (PIN_LOCKR_DISABLED(GPIOG_PIN0) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN1) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN2) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN3) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN4) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN5) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN6) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN7) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN8) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN9) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN10) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN11) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN12) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN13) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN14) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN15))
+
+/*
+ * GPIOH setup:
+ *
+ * PH0 - OSC_IN (input floating).
+ * PH1 - OSC_OUT (input floating).
+ * PH2 - PIN2 (analog).
+ * PH3 - PIN3 (analog).
+ * PH4 - PIN4 (analog).
+ * PH5 - PIN5 (analog).
+ * PH6 - PIN6 (analog).
+ * PH7 - PIN7 (analog).
+ * PH8 - PIN8 (analog).
+ * PH9 - PIN9 (analog).
+ * PH10 - PIN10 (analog).
+ * PH11 - PIN11 (analog).
+ * PH12 - PIN12 (analog).
+ * PH13 - PIN13 (analog).
+ * PH14 - PIN14 (analog).
+ * PH15 - PIN15 (analog).
+ */
+#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_OSC_IN) | \
+ PIN_MODE_INPUT(GPIOH_OSC_OUT) | \
+ PIN_MODE_ANALOG(GPIOH_PIN2) | \
+ PIN_MODE_ANALOG(GPIOH_PIN3) | \
+ PIN_MODE_ANALOG(GPIOH_PIN4) | \
+ PIN_MODE_ANALOG(GPIOH_PIN5) | \
+ PIN_MODE_ANALOG(GPIOH_PIN6) | \
+ PIN_MODE_ANALOG(GPIOH_PIN7) | \
+ PIN_MODE_ANALOG(GPIOH_PIN8) | \
+ PIN_MODE_ANALOG(GPIOH_PIN9) | \
+ PIN_MODE_ANALOG(GPIOH_PIN10) | \
+ PIN_MODE_ANALOG(GPIOH_PIN11) | \
+ PIN_MODE_ANALOG(GPIOH_PIN12) | \
+ PIN_MODE_ANALOG(GPIOH_PIN13) | \
+ PIN_MODE_ANALOG(GPIOH_PIN14) | \
+ PIN_MODE_ANALOG(GPIOH_PIN15))
+#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_OSC_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_OSC_OUT) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN15))
+#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_HIGH(GPIOH_OSC_IN) | \
+ PIN_OSPEED_HIGH(GPIOH_OSC_OUT) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN15))
+#define VAL_GPIOH_PUPDR (PIN_PUPDR_FLOATING(GPIOH_OSC_IN) | \
+ PIN_PUPDR_FLOATING(GPIOH_OSC_OUT) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN15))
+#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_OSC_IN) | \
+ PIN_ODR_HIGH(GPIOH_OSC_OUT) | \
+ PIN_ODR_HIGH(GPIOH_PIN2) | \
+ PIN_ODR_HIGH(GPIOH_PIN3) | \
+ PIN_ODR_HIGH(GPIOH_PIN4) | \
+ PIN_ODR_HIGH(GPIOH_PIN5) | \
+ PIN_ODR_HIGH(GPIOH_PIN6) | \
+ PIN_ODR_HIGH(GPIOH_PIN7) | \
+ PIN_ODR_HIGH(GPIOH_PIN8) | \
+ PIN_ODR_HIGH(GPIOH_PIN9) | \
+ PIN_ODR_HIGH(GPIOH_PIN10) | \
+ PIN_ODR_HIGH(GPIOH_PIN11) | \
+ PIN_ODR_HIGH(GPIOH_PIN12) | \
+ PIN_ODR_HIGH(GPIOH_PIN13) | \
+ PIN_ODR_HIGH(GPIOH_PIN14) | \
+ PIN_ODR_HIGH(GPIOH_PIN15))
+#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_OSC_IN, 0U) | \
+ PIN_AFIO_AF(GPIOH_OSC_OUT, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN7, 0U))
+#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN15, 0U))
+#define VAL_GPIOH_ASCR (PIN_ASCR_DISABLED(GPIOH_OSC_IN) | \
+ PIN_ASCR_DISABLED(GPIOH_OSC_OUT) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN2) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN3) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN4) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN5) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN6) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN7) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN8) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN9) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN10) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN11) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN12) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN13) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN14) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN15))
+#define VAL_GPIOH_LOCKR (PIN_LOCKR_DISABLED(GPIOH_OSC_IN) | \
+ PIN_LOCKR_DISABLED(GPIOH_OSC_OUT) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN2) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN3) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN4) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN5) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN6) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN7) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN8) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN9) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN10) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN11) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN12) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN13) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN14) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN15))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* BOARD_H */
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L452RE_P/board.mk b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L452RE_P/board.mk
new file mode 100644
index 0000000..500dd00
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L452RE_P/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_L452RE_P/board.c
+
+# Required include directories
+BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_L452RE_P
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC += $(BOARDINC)
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L452RE_P/cfg/board.chcfg b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L452RE_P/cfg/board.chcfg
new file mode 100644
index 0000000..aef8ac3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L452RE_P/cfg/board.chcfg
@@ -0,0 +1,1320 @@
+
+
+
+
+ resources/gencfg/processors/boards/stm32l4xx/templates
+ ..
+ 5.0.x
+
+ STMicroelectronics STM32 Nucleo64-L452RE-P
+ ST_NUCLEO64_L452RE_P
+
+ STM32L452xx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L452RE_P/cfg/board.fmpp b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L452RE_P/cfg/board.fmpp
new file mode 100644
index 0000000..3c311d3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L452RE_P/cfg/board.fmpp
@@ -0,0 +1,15 @@
+sourceRoot: ../../../../../tools/ftl/processors/boards/stm32l4xx/templates
+outputRoot: ..
+dataRoot: .
+
+freemarkerLinks: {
+ lib: ../../../../../tools/ftl/libs
+}
+
+data : {
+ doc1:xml (
+ board.chcfg
+ {
+ }
+ )
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L476RG/board.c b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L476RG/board.c
new file mode 100644
index 0000000..cd16e43
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L476RG/board.c
@@ -0,0 +1,281 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#include "hal.h"
+#include "stm32_gpio.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of STM32 GPIO port setup.
+ */
+typedef struct {
+ uint32_t moder;
+ uint32_t otyper;
+ uint32_t ospeedr;
+ uint32_t pupdr;
+ uint32_t odr;
+ uint32_t afrl;
+ uint32_t afrh;
+ uint32_t ascr;
+ uint32_t lockr;
+} gpio_setup_t;
+
+/**
+ * @brief Type of STM32 GPIO initialization data.
+ */
+typedef struct {
+#if STM32_HAS_GPIOA || defined(__DOXYGEN__)
+ gpio_setup_t PAData;
+#endif
+#if STM32_HAS_GPIOB || defined(__DOXYGEN__)
+ gpio_setup_t PBData;
+#endif
+#if STM32_HAS_GPIOC || defined(__DOXYGEN__)
+ gpio_setup_t PCData;
+#endif
+#if STM32_HAS_GPIOD || defined(__DOXYGEN__)
+ gpio_setup_t PDData;
+#endif
+#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
+ gpio_setup_t PEData;
+#endif
+#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
+ gpio_setup_t PFData;
+#endif
+#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
+ gpio_setup_t PGData;
+#endif
+#if STM32_HAS_GPIOH || defined(__DOXYGEN__)
+ gpio_setup_t PHData;
+#endif
+#if STM32_HAS_GPIOI || defined(__DOXYGEN__)
+ gpio_setup_t PIData;
+#endif
+#if STM32_HAS_GPIOJ || defined(__DOXYGEN__)
+ gpio_setup_t PJData;
+#endif
+#if STM32_HAS_GPIOK || defined(__DOXYGEN__)
+ gpio_setup_t PKData;
+#endif
+} gpio_config_t;
+
+/**
+ * @brief STM32 GPIO static initialization data.
+ */
+static const gpio_config_t gpio_default_config = {
+#if STM32_HAS_GPIOA
+ {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
+ VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH, VAL_GPIOA_ASCR,
+ VAL_GPIOA_LOCKR},
+#endif
+#if STM32_HAS_GPIOB
+ {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR,
+ VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH, VAL_GPIOB_ASCR,
+ VAL_GPIOB_LOCKR},
+#endif
+#if STM32_HAS_GPIOC
+ {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR,
+ VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH, VAL_GPIOC_ASCR,
+ VAL_GPIOC_LOCKR},
+#endif
+#if STM32_HAS_GPIOD
+ {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR,
+ VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH, VAL_GPIOD_ASCR,
+ VAL_GPIOD_LOCKR},
+#endif
+#if STM32_HAS_GPIOE
+ {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR,
+ VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH, VAL_GPIOE_ASCR,
+ VAL_GPIOE_LOCKR},
+#endif
+#if STM32_HAS_GPIOF
+ {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR,
+ VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH, VAL_GPIOF_ASCR,
+ VAL_GPIOF_LOCKR},
+#endif
+#if STM32_HAS_GPIOG
+ {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR,
+ VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH, VAL_GPIOG_ASCR,
+ VAL_GPIOG_LOCKR},
+#endif
+#if STM32_HAS_GPIOH
+ {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR,
+ VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH, VAL_GPIOH_ASCR,
+ VAL_GPIOH_LOCKR},
+#endif
+#if STM32_HAS_GPIOI
+ {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
+ VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH, VAL_GPIOI_ASCR,
+ VAL_GPIOI_LOCKR},
+#endif
+#if STM32_HAS_GPIOJ
+ {VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR,
+ VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH, VAL_GPIOJ_ASCR,
+ VAL_GPIOJ_LOCKR},
+#endif
+#if STM32_HAS_GPIOK
+ {VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR,
+ VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH, VAL_GPIOK_ASCR,
+ VAL_GPIOK_LOCKR}
+#endif
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) {
+
+ gpiop->OTYPER = config->otyper;
+ gpiop->ASCR = config->ascr;
+ gpiop->OSPEEDR = config->ospeedr;
+ gpiop->PUPDR = config->pupdr;
+ gpiop->ODR = config->odr;
+ gpiop->AFRL = config->afrl;
+ gpiop->AFRH = config->afrh;
+ gpiop->MODER = config->moder;
+ gpiop->LOCKR = config->lockr;
+}
+
+static void stm32_gpio_init(void) {
+
+ /* Enabling GPIO-related clocks, the mask comes from the
+ registry header file.*/
+ rccResetAHB2(STM32_GPIO_EN_MASK);
+ rccEnableAHB2(STM32_GPIO_EN_MASK, true);
+
+ /* Initializing all the defined GPIO ports.*/
+#if STM32_HAS_GPIOA
+ gpio_init(GPIOA, &gpio_default_config.PAData);
+#endif
+#if STM32_HAS_GPIOB
+ gpio_init(GPIOB, &gpio_default_config.PBData);
+#endif
+#if STM32_HAS_GPIOC
+ gpio_init(GPIOC, &gpio_default_config.PCData);
+#endif
+#if STM32_HAS_GPIOD
+ gpio_init(GPIOD, &gpio_default_config.PDData);
+#endif
+#if STM32_HAS_GPIOE
+ gpio_init(GPIOE, &gpio_default_config.PEData);
+#endif
+#if STM32_HAS_GPIOF
+ gpio_init(GPIOF, &gpio_default_config.PFData);
+#endif
+#if STM32_HAS_GPIOG
+ gpio_init(GPIOG, &gpio_default_config.PGData);
+#endif
+#if STM32_HAS_GPIOH
+ gpio_init(GPIOH, &gpio_default_config.PHData);
+#endif
+#if STM32_HAS_GPIOI
+ gpio_init(GPIOI, &gpio_default_config.PIData);
+#endif
+#if STM32_HAS_GPIOJ
+ gpio_init(GPIOJ, &gpio_default_config.PJData);
+#endif
+#if STM32_HAS_GPIOK
+ gpio_init(GPIOK, &gpio_default_config.PKData);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Early initialization code.
+ * @details GPIO ports and system clocks are initialized before everything
+ * else.
+ */
+void __early_init(void) {
+
+ stm32_gpio_init();
+ stm32_clock_init();
+}
+
+#if HAL_USE_SDC || defined(__DOXYGEN__)
+/**
+ * @brief SDC card detection.
+ */
+bool sdc_lld_is_card_inserted(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief SDC card write protection detection.
+ */
+bool sdc_lld_is_write_protected(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif /* HAL_USE_SDC */
+
+#if HAL_USE_MMC_SPI || defined(__DOXYGEN__)
+/**
+ * @brief MMC_SPI card detection.
+ */
+bool mmc_lld_is_card_inserted(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return true;
+}
+
+/**
+ * @brief MMC_SPI card write protection detection.
+ */
+bool mmc_lld_is_write_protected(MMCDriver *mmcp) {
+
+ (void)mmcp;
+ /* CHTODO: Fill the implementation.*/
+ return false;
+}
+#endif
+
+/**
+ * @brief Board-specific initialization code.
+ * @note You can add your board-specific code here.
+ */
+void boardInit(void) {
+
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L476RG/board.h b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L476RG/board.h
new file mode 100644
index 0000000..ff42cd1
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L476RG/board.h
@@ -0,0 +1,1505 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * This file has been automatically generated using ChibiStudio board
+ * generator plugin. Do not edit manually.
+ */
+
+#ifndef BOARD_H
+#define BOARD_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*
+ * Setup for STMicroelectronics STM32 Nucleo64-L476RG board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_ST_NUCLEO64_L476RG
+#define BOARD_NAME "STMicroelectronics STM32 Nucleo64-L476RG"
+
+/*
+ * Board oscillators-related settings.
+ */
+#if !defined(STM32_LSECLK)
+#define STM32_LSECLK 32768U
+#endif
+
+#define STM32_LSEDRV (3U << 3U)
+
+#if !defined(STM32_HSECLK)
+#define STM32_HSECLK 8000000U
+#endif
+
+#define STM32_HSE_BYPASS
+
+/*
+ * Board voltages.
+ * Required for performance limits calculation.
+ */
+#define STM32_VDD 300U
+
+/*
+ * MCU type as defined in the ST header.
+ */
+#define STM32L476xx
+
+/*
+ * IO pins assignments.
+ */
+#define GPIOA_ARD_A0 0U
+#define GPIOA_ACD12_IN5 0U
+#define GPIOA_ARD_A1 1U
+#define GPIOA_ACD12_IN6 1U
+#define GPIOA_ARD_D1 2U
+#define GPIOA_USART2_TX 2U
+#define GPIOA_ARD_D0 3U
+#define GPIOA_USART2_RX 3U
+#define GPIOA_ARD_A2 4U
+#define GPIOA_ACD12_IN9 4U
+#define GPIOA_ARD_D13 5U
+#define GPIOA_LED_GREEN 5U
+#define GPIOA_ARD_D12 6U
+#define GPIOA_ARD_D11 7U
+#define GPIOA_ARD_D7 8U
+#define GPIOA_ARD_D8 9U
+#define GPIOA_ARD_D2 10U
+#define GPIOA_PIN11 11U
+#define GPIOA_PIN12 12U
+#define GPIOA_SWDIO 13U
+#define GPIOA_SWCLK 14U
+#define GPIOA_PIN15 15U
+
+#define GPIOB_ARD_A3 0U
+#define GPIOB_ACD12_IN15 0U
+#define GPIOB_PIN1 1U
+#define GPIOB_PIN2 2U
+#define GPIOB_ARD_D3 3U
+#define GPIOB_SWO 3U
+#define GPIOB_ARD_D5 4U
+#define GPIOB_ARD_D4 5U
+#define GPIOB_ARD_D10 6U
+#define GPIOB_PIN7 7U
+#define GPIOB_ARD_D15 8U
+#define GPIOB_ARD_D14 9U
+#define GPIOB_ARD_D6 10U
+#define GPIOB_PIN11 11U
+#define GPIOB_PIN12 12U
+#define GPIOB_PIN13 13U
+#define GPIOB_PIN14 14U
+#define GPIOB_PIN15 15U
+
+#define GPIOC_ARD_A5 0U
+#define GPIOC_ACD123_IN1 0U
+#define GPIOC_ARD_A4 1U
+#define GPIOC_ACD123_IN2 1U
+#define GPIOC_PIN2 2U
+#define GPIOC_PIN3 3U
+#define GPIOC_PIN4 4U
+#define GPIOC_PIN5 5U
+#define GPIOC_PIN6 6U
+#define GPIOC_ARD_D9 7U
+#define GPIOC_PIN8 8U
+#define GPIOC_PIN9 9U
+#define GPIOC_PIN10 10U
+#define GPIOC_PIN11 11U
+#define GPIOC_PIN12 12U
+#define GPIOC_BUTTON 13U
+#define GPIOC_OSC32_IN 14U
+#define GPIOC_OSC32_OUT 15U
+
+#define GPIOD_PIN0 0U
+#define GPIOD_PIN1 1U
+#define GPIOD_PIN2 2U
+#define GPIOD_PIN3 3U
+#define GPIOD_PIN4 4U
+#define GPIOD_PIN5 5U
+#define GPIOD_PIN6 6U
+#define GPIOD_PIN7 7U
+#define GPIOD_PIN8 8U
+#define GPIOD_PIN9 9U
+#define GPIOD_PIN10 10U
+#define GPIOD_PIN11 11U
+#define GPIOD_PIN12 12U
+#define GPIOD_PIN13 13U
+#define GPIOD_PIN14 14U
+#define GPIOD_PIN15 15U
+
+#define GPIOE_PIN0 0U
+#define GPIOE_PIN1 1U
+#define GPIOE_PIN2 2U
+#define GPIOE_PIN3 3U
+#define GPIOE_PIN4 4U
+#define GPIOE_PIN5 5U
+#define GPIOE_PIN6 6U
+#define GPIOE_PIN7 7U
+#define GPIOE_PIN8 8U
+#define GPIOE_PIN9 9U
+#define GPIOE_PIN10 10U
+#define GPIOE_PIN11 11U
+#define GPIOE_PIN12 12U
+#define GPIOE_PIN13 13U
+#define GPIOE_PIN14 14U
+#define GPIOE_PIN15 15U
+
+#define GPIOF_PIN0 0U
+#define GPIOF_PIN1 1U
+#define GPIOF_PIN2 2U
+#define GPIOF_PIN3 3U
+#define GPIOF_PIN4 4U
+#define GPIOF_PIN5 5U
+#define GPIOF_PIN6 6U
+#define GPIOF_PIN7 7U
+#define GPIOF_PIN8 8U
+#define GPIOF_PIN9 9U
+#define GPIOF_PIN10 10U
+#define GPIOF_PIN11 11U
+#define GPIOF_PIN12 12U
+#define GPIOF_PIN13 13U
+#define GPIOF_PIN14 14U
+#define GPIOF_PIN15 15U
+
+#define GPIOG_PIN0 0U
+#define GPIOG_PIN1 1U
+#define GPIOG_PIN2 2U
+#define GPIOG_PIN3 3U
+#define GPIOG_PIN4 4U
+#define GPIOG_PIN5 5U
+#define GPIOG_PIN6 6U
+#define GPIOG_PIN7 7U
+#define GPIOG_PIN8 8U
+#define GPIOG_PIN9 9U
+#define GPIOG_PIN10 10U
+#define GPIOG_PIN11 11U
+#define GPIOG_PIN12 12U
+#define GPIOG_PIN13 13U
+#define GPIOG_PIN14 14U
+#define GPIOG_PIN15 15U
+
+#define GPIOH_OSC_IN 0U
+#define GPIOH_OSC_OUT 1U
+#define GPIOH_PIN2 2U
+#define GPIOH_PIN3 3U
+#define GPIOH_PIN4 4U
+#define GPIOH_PIN5 5U
+#define GPIOH_PIN6 6U
+#define GPIOH_PIN7 7U
+#define GPIOH_PIN8 8U
+#define GPIOH_PIN9 9U
+#define GPIOH_PIN10 10U
+#define GPIOH_PIN11 11U
+#define GPIOH_PIN12 12U
+#define GPIOH_PIN13 13U
+#define GPIOH_PIN14 14U
+#define GPIOH_PIN15 15U
+
+/*
+ * IO lines assignments.
+ */
+#define LINE_ARD_A0 PAL_LINE(GPIOA, 0U)
+#define LINE_ACD12_IN5 PAL_LINE(GPIOA, 0U)
+#define LINE_ARD_A1 PAL_LINE(GPIOA, 1U)
+#define LINE_ACD12_IN6 PAL_LINE(GPIOA, 1U)
+#define LINE_ARD_D1 PAL_LINE(GPIOA, 2U)
+#define LINE_USART2_TX PAL_LINE(GPIOA, 2U)
+#define LINE_ARD_D0 PAL_LINE(GPIOA, 3U)
+#define LINE_USART2_RX PAL_LINE(GPIOA, 3U)
+#define LINE_ARD_A2 PAL_LINE(GPIOA, 4U)
+#define LINE_ACD12_IN9 PAL_LINE(GPIOA, 4U)
+#define LINE_ARD_D13 PAL_LINE(GPIOA, 5U)
+#define LINE_LED_GREEN PAL_LINE(GPIOA, 5U)
+#define LINE_ARD_D12 PAL_LINE(GPIOA, 6U)
+#define LINE_ARD_D11 PAL_LINE(GPIOA, 7U)
+#define LINE_ARD_D7 PAL_LINE(GPIOA, 8U)
+#define LINE_ARD_D8 PAL_LINE(GPIOA, 9U)
+#define LINE_ARD_D2 PAL_LINE(GPIOA, 10U)
+#define LINE_SWDIO PAL_LINE(GPIOA, 13U)
+#define LINE_SWCLK PAL_LINE(GPIOA, 14U)
+#define LINE_ARD_A3 PAL_LINE(GPIOB, 0U)
+#define LINE_ACD12_IN15 PAL_LINE(GPIOB, 0U)
+#define LINE_ARD_D3 PAL_LINE(GPIOB, 3U)
+#define LINE_SWO PAL_LINE(GPIOB, 3U)
+#define LINE_ARD_D5 PAL_LINE(GPIOB, 4U)
+#define LINE_ARD_D4 PAL_LINE(GPIOB, 5U)
+#define LINE_ARD_D10 PAL_LINE(GPIOB, 6U)
+#define LINE_ARD_D15 PAL_LINE(GPIOB, 8U)
+#define LINE_ARD_D14 PAL_LINE(GPIOB, 9U)
+#define LINE_ARD_D6 PAL_LINE(GPIOB, 10U)
+#define LINE_ARD_A5 PAL_LINE(GPIOC, 0U)
+#define LINE_ACD123_IN1 PAL_LINE(GPIOC, 0U)
+#define LINE_ARD_A4 PAL_LINE(GPIOC, 1U)
+#define LINE_ACD123_IN2 PAL_LINE(GPIOC, 1U)
+#define LINE_ARD_D9 PAL_LINE(GPIOC, 7U)
+#define LINE_BUTTON PAL_LINE(GPIOC, 13U)
+#define LINE_OSC32_IN PAL_LINE(GPIOC, 14U)
+#define LINE_OSC32_OUT PAL_LINE(GPIOC, 15U)
+#define LINE_OSC_IN PAL_LINE(GPIOH, 0U)
+#define LINE_OSC_OUT PAL_LINE(GPIOH, 1U)
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*
+ * I/O ports initial setup, this configuration is established soon after reset
+ * in the initialization code.
+ * Please refer to the STM32 Reference Manual for details.
+ */
+#define PIN_MODE_INPUT(n) (0U << ((n) * 2U))
+#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U))
+#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U))
+#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U))
+#define PIN_ODR_LOW(n) (0U << (n))
+#define PIN_ODR_HIGH(n) (1U << (n))
+#define PIN_OTYPE_PUSHPULL(n) (0U << (n))
+#define PIN_OTYPE_OPENDRAIN(n) (1U << (n))
+#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U))
+#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U))
+#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U))
+#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U))
+#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U))
+#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U))
+#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U))
+#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U))
+#define PIN_ASCR_DISABLED(n) (0U << (n))
+#define PIN_ASCR_ENABLED(n) (1U << (n))
+#define PIN_LOCKR_DISABLED(n) (0U << (n))
+#define PIN_LOCKR_ENABLED(n) (1U << (n))
+
+/*
+ * GPIOA setup:
+ *
+ * PA0 - ARD_A0 ACD12_IN5 (analog).
+ * PA1 - ARD_A1 ACD12_IN6 (analog).
+ * PA2 - ARD_D1 USART2_TX (alternate 7).
+ * PA3 - ARD_D0 USART2_RX (alternate 7).
+ * PA4 - ARD_A2 ACD12_IN9 (analog).
+ * PA5 - ARD_D13 LED_GREEN (output pushpull maximum).
+ * PA6 - ARD_D12 (analog).
+ * PA7 - ARD_D11 (analog).
+ * PA8 - ARD_D7 (analog).
+ * PA9 - ARD_D8 (analog).
+ * PA10 - ARD_D2 (analog).
+ * PA11 - PIN11 (analog).
+ * PA12 - PIN12 (analog).
+ * PA13 - SWDIO (alternate 0).
+ * PA14 - SWCLK (alternate 0).
+ * PA15 - PIN15 (analog).
+ */
+#define VAL_GPIOA_MODER (PIN_MODE_ANALOG(GPIOA_ARD_A0) | \
+ PIN_MODE_ANALOG(GPIOA_ARD_A1) | \
+ PIN_MODE_ALTERNATE(GPIOA_ARD_D1) | \
+ PIN_MODE_ALTERNATE(GPIOA_ARD_D0) | \
+ PIN_MODE_ANALOG(GPIOA_ARD_A2) | \
+ PIN_MODE_OUTPUT(GPIOA_ARD_D13) | \
+ PIN_MODE_ANALOG(GPIOA_ARD_D12) | \
+ PIN_MODE_ANALOG(GPIOA_ARD_D11) | \
+ PIN_MODE_ANALOG(GPIOA_ARD_D7) | \
+ PIN_MODE_ANALOG(GPIOA_ARD_D8) | \
+ PIN_MODE_ANALOG(GPIOA_ARD_D2) | \
+ PIN_MODE_ANALOG(GPIOA_PIN11) | \
+ PIN_MODE_ANALOG(GPIOA_PIN12) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \
+ PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \
+ PIN_MODE_ANALOG(GPIOA_PIN15))
+#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_ARD_A0) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_A1) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D1) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D0) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_A2) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D13) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D12) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D11) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D7) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D8) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_ARD_D2) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \
+ PIN_OTYPE_PUSHPULL(GPIOA_PIN15))
+#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_HIGH(GPIOA_ARD_A0) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_A1) | \
+ PIN_OSPEED_MEDIUM(GPIOA_ARD_D1) | \
+ PIN_OSPEED_MEDIUM(GPIOA_ARD_D0) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_A2) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D13) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D12) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D11) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D7) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D8) | \
+ PIN_OSPEED_HIGH(GPIOA_ARD_D2) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOA_SWDIO) | \
+ PIN_OSPEED_HIGH(GPIOA_SWCLK) | \
+ PIN_OSPEED_HIGH(GPIOA_PIN15))
+#define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_ARD_A0) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_A1) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D1) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D0) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_A2) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D13) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D12) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D11) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D7) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D8) | \
+ PIN_PUPDR_FLOATING(GPIOA_ARD_D2) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN12) | \
+ PIN_PUPDR_PULLUP(GPIOA_SWDIO) | \
+ PIN_PUPDR_PULLDOWN(GPIOA_SWCLK) | \
+ PIN_PUPDR_FLOATING(GPIOA_PIN15))
+#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_ARD_A0) | \
+ PIN_ODR_HIGH(GPIOA_ARD_A1) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D1) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D0) | \
+ PIN_ODR_HIGH(GPIOA_ARD_A2) | \
+ PIN_ODR_LOW(GPIOA_ARD_D13) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D12) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D11) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D7) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D8) | \
+ PIN_ODR_HIGH(GPIOA_ARD_D2) | \
+ PIN_ODR_HIGH(GPIOA_PIN11) | \
+ PIN_ODR_HIGH(GPIOA_PIN12) | \
+ PIN_ODR_HIGH(GPIOA_SWDIO) | \
+ PIN_ODR_HIGH(GPIOA_SWCLK) | \
+ PIN_ODR_HIGH(GPIOA_PIN15))
+#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_ARD_A0, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_A1, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D1, 7U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D0, 7U) | \
+ PIN_AFIO_AF(GPIOA_ARD_A2, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D13, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D12, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D11, 0U))
+#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_ARD_D7, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D8, 0U) | \
+ PIN_AFIO_AF(GPIOA_ARD_D2, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOA_SWDIO, 0U) | \
+ PIN_AFIO_AF(GPIOA_SWCLK, 0U) | \
+ PIN_AFIO_AF(GPIOA_PIN15, 0U))
+#define VAL_GPIOA_ASCR (PIN_ASCR_DISABLED(GPIOA_ARD_A0) | \
+ PIN_ASCR_DISABLED(GPIOA_ARD_A1) | \
+ PIN_ASCR_DISABLED(GPIOA_ARD_D1) | \
+ PIN_ASCR_DISABLED(GPIOA_ARD_D0) | \
+ PIN_ASCR_DISABLED(GPIOA_ARD_A2) | \
+ PIN_ASCR_DISABLED(GPIOA_ARD_D13) | \
+ PIN_ASCR_DISABLED(GPIOA_ARD_D12) | \
+ PIN_ASCR_DISABLED(GPIOA_ARD_D11) | \
+ PIN_ASCR_DISABLED(GPIOA_ARD_D7) | \
+ PIN_ASCR_DISABLED(GPIOA_ARD_D8) | \
+ PIN_ASCR_DISABLED(GPIOA_ARD_D2) | \
+ PIN_ASCR_DISABLED(GPIOA_PIN11) | \
+ PIN_ASCR_DISABLED(GPIOA_PIN12) | \
+ PIN_ASCR_DISABLED(GPIOA_SWDIO) | \
+ PIN_ASCR_DISABLED(GPIOA_SWCLK) | \
+ PIN_ASCR_DISABLED(GPIOA_PIN15))
+#define VAL_GPIOA_LOCKR (PIN_LOCKR_DISABLED(GPIOA_ARD_A0) | \
+ PIN_LOCKR_DISABLED(GPIOA_ARD_A1) | \
+ PIN_LOCKR_DISABLED(GPIOA_ARD_D1) | \
+ PIN_LOCKR_DISABLED(GPIOA_ARD_D0) | \
+ PIN_LOCKR_DISABLED(GPIOA_ARD_A2) | \
+ PIN_LOCKR_DISABLED(GPIOA_ARD_D13) | \
+ PIN_LOCKR_DISABLED(GPIOA_ARD_D12) | \
+ PIN_LOCKR_DISABLED(GPIOA_ARD_D11) | \
+ PIN_LOCKR_DISABLED(GPIOA_ARD_D7) | \
+ PIN_LOCKR_DISABLED(GPIOA_ARD_D8) | \
+ PIN_LOCKR_DISABLED(GPIOA_ARD_D2) | \
+ PIN_LOCKR_DISABLED(GPIOA_PIN11) | \
+ PIN_LOCKR_DISABLED(GPIOA_PIN12) | \
+ PIN_LOCKR_DISABLED(GPIOA_SWDIO) | \
+ PIN_LOCKR_DISABLED(GPIOA_SWCLK) | \
+ PIN_LOCKR_DISABLED(GPIOA_PIN15))
+
+/*
+ * GPIOB setup:
+ *
+ * PB0 - ARD_A3 ACD12_IN15 (analog).
+ * PB1 - PIN1 (analog).
+ * PB2 - PIN2 (analog).
+ * PB3 - ARD_D3 SWO (analog).
+ * PB4 - ARD_D5 (analog).
+ * PB5 - ARD_D4 (analog).
+ * PB6 - ARD_D10 (analog).
+ * PB7 - PIN7 (analog).
+ * PB8 - ARD_D15 (analog).
+ * PB9 - ARD_D14 (analog).
+ * PB10 - ARD_D6 (analog).
+ * PB11 - PIN11 (analog).
+ * PB12 - PIN12 (analog).
+ * PB13 - PIN13 (analog).
+ * PB14 - PIN14 (analog).
+ * PB15 - PIN15 (analog).
+ */
+#define VAL_GPIOB_MODER (PIN_MODE_ANALOG(GPIOB_ARD_A3) | \
+ PIN_MODE_ANALOG(GPIOB_PIN1) | \
+ PIN_MODE_ANALOG(GPIOB_PIN2) | \
+ PIN_MODE_ANALOG(GPIOB_ARD_D3) | \
+ PIN_MODE_ANALOG(GPIOB_ARD_D5) | \
+ PIN_MODE_ANALOG(GPIOB_ARD_D4) | \
+ PIN_MODE_ANALOG(GPIOB_ARD_D10) | \
+ PIN_MODE_ANALOG(GPIOB_PIN7) | \
+ PIN_MODE_ANALOG(GPIOB_ARD_D15) | \
+ PIN_MODE_ANALOG(GPIOB_ARD_D14) | \
+ PIN_MODE_ANALOG(GPIOB_ARD_D6) | \
+ PIN_MODE_ANALOG(GPIOB_PIN11) | \
+ PIN_MODE_ANALOG(GPIOB_PIN12) | \
+ PIN_MODE_ANALOG(GPIOB_PIN13) | \
+ PIN_MODE_ANALOG(GPIOB_PIN14) | \
+ PIN_MODE_ANALOG(GPIOB_PIN15))
+#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_ARD_A3) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D3) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D5) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D4) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D10) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D15) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D14) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_ARD_D6) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOB_PIN15))
+#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_HIGH(GPIOB_ARD_A3) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN1) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D3) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D5) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D4) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D10) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D15) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D14) | \
+ PIN_OSPEED_HIGH(GPIOB_ARD_D6) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOB_PIN15))
+#define VAL_GPIOB_PUPDR (PIN_PUPDR_FLOATING(GPIOB_ARD_A3) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOB_ARD_D3) | \
+ PIN_PUPDR_FLOATING(GPIOB_ARD_D5) | \
+ PIN_PUPDR_FLOATING(GPIOB_ARD_D4) | \
+ PIN_PUPDR_FLOATING(GPIOB_ARD_D10) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOB_ARD_D15) | \
+ PIN_PUPDR_FLOATING(GPIOB_ARD_D14) | \
+ PIN_PUPDR_FLOATING(GPIOB_ARD_D6) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOB_PIN15))
+#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_ARD_A3) | \
+ PIN_ODR_HIGH(GPIOB_PIN1) | \
+ PIN_ODR_HIGH(GPIOB_PIN2) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D3) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D5) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D4) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D10) | \
+ PIN_ODR_HIGH(GPIOB_PIN7) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D15) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D14) | \
+ PIN_ODR_HIGH(GPIOB_ARD_D6) | \
+ PIN_ODR_HIGH(GPIOB_PIN11) | \
+ PIN_ODR_HIGH(GPIOB_PIN12) | \
+ PIN_ODR_HIGH(GPIOB_PIN13) | \
+ PIN_ODR_HIGH(GPIOB_PIN14) | \
+ PIN_ODR_HIGH(GPIOB_PIN15))
+#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_ARD_A3, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D3, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D5, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D4, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D10, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN7, 0U))
+#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_ARD_D15, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D14, 0U) | \
+ PIN_AFIO_AF(GPIOB_ARD_D6, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOB_PIN15, 0U))
+#define VAL_GPIOB_ASCR (PIN_ASCR_DISABLED(GPIOB_ARD_A3) | \
+ PIN_ASCR_DISABLED(GPIOB_PIN1) | \
+ PIN_ASCR_DISABLED(GPIOB_PIN2) | \
+ PIN_ASCR_DISABLED(GPIOB_ARD_D3) | \
+ PIN_ASCR_DISABLED(GPIOB_ARD_D5) | \
+ PIN_ASCR_DISABLED(GPIOB_ARD_D4) | \
+ PIN_ASCR_DISABLED(GPIOB_ARD_D10) | \
+ PIN_ASCR_DISABLED(GPIOB_PIN7) | \
+ PIN_ASCR_DISABLED(GPIOB_ARD_D15) | \
+ PIN_ASCR_DISABLED(GPIOB_ARD_D14) | \
+ PIN_ASCR_DISABLED(GPIOB_ARD_D6) | \
+ PIN_ASCR_DISABLED(GPIOB_PIN11) | \
+ PIN_ASCR_DISABLED(GPIOB_PIN12) | \
+ PIN_ASCR_DISABLED(GPIOB_PIN13) | \
+ PIN_ASCR_DISABLED(GPIOB_PIN14) | \
+ PIN_ASCR_DISABLED(GPIOB_PIN15))
+#define VAL_GPIOB_LOCKR (PIN_LOCKR_DISABLED(GPIOB_ARD_A3) | \
+ PIN_LOCKR_DISABLED(GPIOB_PIN1) | \
+ PIN_LOCKR_DISABLED(GPIOB_PIN2) | \
+ PIN_LOCKR_DISABLED(GPIOB_ARD_D3) | \
+ PIN_LOCKR_DISABLED(GPIOB_ARD_D5) | \
+ PIN_LOCKR_DISABLED(GPIOB_ARD_D4) | \
+ PIN_LOCKR_DISABLED(GPIOB_ARD_D10) | \
+ PIN_LOCKR_DISABLED(GPIOB_PIN7) | \
+ PIN_LOCKR_DISABLED(GPIOB_ARD_D15) | \
+ PIN_LOCKR_DISABLED(GPIOB_ARD_D14) | \
+ PIN_LOCKR_DISABLED(GPIOB_ARD_D6) | \
+ PIN_LOCKR_DISABLED(GPIOB_PIN11) | \
+ PIN_LOCKR_DISABLED(GPIOB_PIN12) | \
+ PIN_LOCKR_DISABLED(GPIOB_PIN13) | \
+ PIN_LOCKR_DISABLED(GPIOB_PIN14) | \
+ PIN_LOCKR_DISABLED(GPIOB_PIN15))
+
+/*
+ * GPIOC setup:
+ *
+ * PC0 - ARD_A5 ACD123_IN1 (analog).
+ * PC1 - ARD_A4 ACD123_IN2 (analog).
+ * PC2 - PIN2 (analog).
+ * PC3 - PIN3 (analog).
+ * PC4 - PIN4 (analog).
+ * PC5 - PIN5 (analog).
+ * PC6 - PIN6 (analog).
+ * PC7 - ARD_D9 (analog).
+ * PC8 - PIN8 (analog).
+ * PC9 - PIN9 (analog).
+ * PC10 - PIN10 (analog).
+ * PC11 - PIN11 (analog).
+ * PC12 - PIN12 (analog).
+ * PC13 - BUTTON (input floating).
+ * PC14 - OSC32_IN (input floating).
+ * PC15 - OSC32_OUT (input floating).
+ */
+#define VAL_GPIOC_MODER (PIN_MODE_ANALOG(GPIOC_ARD_A5) | \
+ PIN_MODE_ANALOG(GPIOC_ARD_A4) | \
+ PIN_MODE_ANALOG(GPIOC_PIN2) | \
+ PIN_MODE_ANALOG(GPIOC_PIN3) | \
+ PIN_MODE_ANALOG(GPIOC_PIN4) | \
+ PIN_MODE_ANALOG(GPIOC_PIN5) | \
+ PIN_MODE_ANALOG(GPIOC_PIN6) | \
+ PIN_MODE_ANALOG(GPIOC_ARD_D9) | \
+ PIN_MODE_ANALOG(GPIOC_PIN8) | \
+ PIN_MODE_ANALOG(GPIOC_PIN9) | \
+ PIN_MODE_ANALOG(GPIOC_PIN10) | \
+ PIN_MODE_ANALOG(GPIOC_PIN11) | \
+ PIN_MODE_ANALOG(GPIOC_PIN12) | \
+ PIN_MODE_INPUT(GPIOC_BUTTON) | \
+ PIN_MODE_INPUT(GPIOC_OSC32_IN) | \
+ PIN_MODE_INPUT(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_ARD_A5) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_ARD_A4) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_ARD_D9) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_BUTTON) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_HIGH(GPIOC_ARD_A5) | \
+ PIN_OSPEED_HIGH(GPIOC_ARD_A4) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOC_ARD_D9) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOC_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOC_BUTTON) | \
+ PIN_OSPEED_HIGH(GPIOC_OSC32_IN) | \
+ PIN_OSPEED_HIGH(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_PUPDR (PIN_PUPDR_FLOATING(GPIOC_ARD_A5) | \
+ PIN_PUPDR_FLOATING(GPIOC_ARD_A4) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOC_ARD_D9) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOC_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOC_BUTTON) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_IN) | \
+ PIN_PUPDR_FLOATING(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_ARD_A5) | \
+ PIN_ODR_HIGH(GPIOC_ARD_A4) | \
+ PIN_ODR_HIGH(GPIOC_PIN2) | \
+ PIN_ODR_HIGH(GPIOC_PIN3) | \
+ PIN_ODR_HIGH(GPIOC_PIN4) | \
+ PIN_ODR_HIGH(GPIOC_PIN5) | \
+ PIN_ODR_HIGH(GPIOC_PIN6) | \
+ PIN_ODR_HIGH(GPIOC_ARD_D9) | \
+ PIN_ODR_HIGH(GPIOC_PIN8) | \
+ PIN_ODR_HIGH(GPIOC_PIN9) | \
+ PIN_ODR_HIGH(GPIOC_PIN10) | \
+ PIN_ODR_HIGH(GPIOC_PIN11) | \
+ PIN_ODR_HIGH(GPIOC_PIN12) | \
+ PIN_ODR_HIGH(GPIOC_BUTTON) | \
+ PIN_ODR_HIGH(GPIOC_OSC32_IN) | \
+ PIN_ODR_HIGH(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_ARD_A5, 0U) | \
+ PIN_AFIO_AF(GPIOC_ARD_A4, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOC_ARD_D9, 0U))
+#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOC_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOC_BUTTON, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_IN, 0U) | \
+ PIN_AFIO_AF(GPIOC_OSC32_OUT, 0U))
+#define VAL_GPIOC_ASCR (PIN_ASCR_DISABLED(GPIOC_ARD_A5) | \
+ PIN_ASCR_DISABLED(GPIOC_ARD_A4) | \
+ PIN_ASCR_DISABLED(GPIOC_PIN2) | \
+ PIN_ASCR_DISABLED(GPIOC_PIN3) | \
+ PIN_ASCR_DISABLED(GPIOC_PIN4) | \
+ PIN_ASCR_DISABLED(GPIOC_PIN5) | \
+ PIN_ASCR_DISABLED(GPIOC_PIN6) | \
+ PIN_ASCR_DISABLED(GPIOC_ARD_D9) | \
+ PIN_ASCR_DISABLED(GPIOC_PIN8) | \
+ PIN_ASCR_DISABLED(GPIOC_PIN9) | \
+ PIN_ASCR_DISABLED(GPIOC_PIN10) | \
+ PIN_ASCR_DISABLED(GPIOC_PIN11) | \
+ PIN_ASCR_DISABLED(GPIOC_PIN12) | \
+ PIN_ASCR_DISABLED(GPIOC_BUTTON) | \
+ PIN_ASCR_DISABLED(GPIOC_OSC32_IN) | \
+ PIN_ASCR_DISABLED(GPIOC_OSC32_OUT))
+#define VAL_GPIOC_LOCKR (PIN_LOCKR_DISABLED(GPIOC_ARD_A5) | \
+ PIN_LOCKR_DISABLED(GPIOC_ARD_A4) | \
+ PIN_LOCKR_DISABLED(GPIOC_PIN2) | \
+ PIN_LOCKR_DISABLED(GPIOC_PIN3) | \
+ PIN_LOCKR_DISABLED(GPIOC_PIN4) | \
+ PIN_LOCKR_DISABLED(GPIOC_PIN5) | \
+ PIN_LOCKR_DISABLED(GPIOC_PIN6) | \
+ PIN_LOCKR_DISABLED(GPIOC_ARD_D9) | \
+ PIN_LOCKR_DISABLED(GPIOC_PIN8) | \
+ PIN_LOCKR_DISABLED(GPIOC_PIN9) | \
+ PIN_LOCKR_DISABLED(GPIOC_PIN10) | \
+ PIN_LOCKR_DISABLED(GPIOC_PIN11) | \
+ PIN_LOCKR_DISABLED(GPIOC_PIN12) | \
+ PIN_LOCKR_DISABLED(GPIOC_BUTTON) | \
+ PIN_LOCKR_DISABLED(GPIOC_OSC32_IN) | \
+ PIN_LOCKR_DISABLED(GPIOC_OSC32_OUT))
+
+/*
+ * GPIOD setup:
+ *
+ * PD0 - PIN0 (analog).
+ * PD1 - PIN1 (analog).
+ * PD2 - PIN2 (analog).
+ * PD3 - PIN3 (analog).
+ * PD4 - PIN4 (analog).
+ * PD5 - PIN5 (analog).
+ * PD6 - PIN6 (analog).
+ * PD7 - PIN7 (analog).
+ * PD8 - PIN8 (analog).
+ * PD9 - PIN9 (analog).
+ * PD10 - PIN10 (analog).
+ * PD11 - PIN11 (analog).
+ * PD12 - PIN12 (analog).
+ * PD13 - PIN13 (analog).
+ * PD14 - PIN14 (analog).
+ * PD15 - PIN15 (analog).
+ */
+#define VAL_GPIOD_MODER (PIN_MODE_ANALOG(GPIOD_PIN0) | \
+ PIN_MODE_ANALOG(GPIOD_PIN1) | \
+ PIN_MODE_ANALOG(GPIOD_PIN2) | \
+ PIN_MODE_ANALOG(GPIOD_PIN3) | \
+ PIN_MODE_ANALOG(GPIOD_PIN4) | \
+ PIN_MODE_ANALOG(GPIOD_PIN5) | \
+ PIN_MODE_ANALOG(GPIOD_PIN6) | \
+ PIN_MODE_ANALOG(GPIOD_PIN7) | \
+ PIN_MODE_ANALOG(GPIOD_PIN8) | \
+ PIN_MODE_ANALOG(GPIOD_PIN9) | \
+ PIN_MODE_ANALOG(GPIOD_PIN10) | \
+ PIN_MODE_ANALOG(GPIOD_PIN11) | \
+ PIN_MODE_ANALOG(GPIOD_PIN12) | \
+ PIN_MODE_ANALOG(GPIOD_PIN13) | \
+ PIN_MODE_ANALOG(GPIOD_PIN14) | \
+ PIN_MODE_ANALOG(GPIOD_PIN15))
+#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOD_PIN15))
+#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_HIGH(GPIOD_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN1) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOD_PIN15))
+#define VAL_GPIOD_PUPDR (PIN_PUPDR_FLOATING(GPIOD_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOD_PIN15))
+#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \
+ PIN_ODR_HIGH(GPIOD_PIN1) | \
+ PIN_ODR_HIGH(GPIOD_PIN2) | \
+ PIN_ODR_HIGH(GPIOD_PIN3) | \
+ PIN_ODR_HIGH(GPIOD_PIN4) | \
+ PIN_ODR_HIGH(GPIOD_PIN5) | \
+ PIN_ODR_HIGH(GPIOD_PIN6) | \
+ PIN_ODR_HIGH(GPIOD_PIN7) | \
+ PIN_ODR_HIGH(GPIOD_PIN8) | \
+ PIN_ODR_HIGH(GPIOD_PIN9) | \
+ PIN_ODR_HIGH(GPIOD_PIN10) | \
+ PIN_ODR_HIGH(GPIOD_PIN11) | \
+ PIN_ODR_HIGH(GPIOD_PIN12) | \
+ PIN_ODR_HIGH(GPIOD_PIN13) | \
+ PIN_ODR_HIGH(GPIOD_PIN14) | \
+ PIN_ODR_HIGH(GPIOD_PIN15))
+#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN7, 0U))
+#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOD_PIN15, 0U))
+#define VAL_GPIOD_ASCR (PIN_ASCR_DISABLED(GPIOD_PIN0) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN1) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN2) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN3) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN4) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN5) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN6) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN7) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN8) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN9) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN10) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN11) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN12) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN13) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN14) | \
+ PIN_ASCR_DISABLED(GPIOD_PIN15))
+#define VAL_GPIOD_LOCKR (PIN_LOCKR_DISABLED(GPIOD_PIN0) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN1) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN2) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN3) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN4) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN5) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN6) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN7) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN8) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN9) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN10) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN11) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN12) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN13) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN14) | \
+ PIN_LOCKR_DISABLED(GPIOD_PIN15))
+
+/*
+ * GPIOE setup:
+ *
+ * PE0 - PIN0 (analog).
+ * PE1 - PIN1 (analog).
+ * PE2 - PIN2 (analog).
+ * PE3 - PIN3 (analog).
+ * PE4 - PIN4 (analog).
+ * PE5 - PIN5 (analog).
+ * PE6 - PIN6 (analog).
+ * PE7 - PIN7 (analog).
+ * PE8 - PIN8 (analog).
+ * PE9 - PIN9 (analog).
+ * PE10 - PIN10 (analog).
+ * PE11 - PIN11 (analog).
+ * PE12 - PIN12 (analog).
+ * PE13 - PIN13 (analog).
+ * PE14 - PIN14 (analog).
+ * PE15 - PIN15 (analog).
+ */
+#define VAL_GPIOE_MODER (PIN_MODE_ANALOG(GPIOE_PIN0) | \
+ PIN_MODE_ANALOG(GPIOE_PIN1) | \
+ PIN_MODE_ANALOG(GPIOE_PIN2) | \
+ PIN_MODE_ANALOG(GPIOE_PIN3) | \
+ PIN_MODE_ANALOG(GPIOE_PIN4) | \
+ PIN_MODE_ANALOG(GPIOE_PIN5) | \
+ PIN_MODE_ANALOG(GPIOE_PIN6) | \
+ PIN_MODE_ANALOG(GPIOE_PIN7) | \
+ PIN_MODE_ANALOG(GPIOE_PIN8) | \
+ PIN_MODE_ANALOG(GPIOE_PIN9) | \
+ PIN_MODE_ANALOG(GPIOE_PIN10) | \
+ PIN_MODE_ANALOG(GPIOE_PIN11) | \
+ PIN_MODE_ANALOG(GPIOE_PIN12) | \
+ PIN_MODE_ANALOG(GPIOE_PIN13) | \
+ PIN_MODE_ANALOG(GPIOE_PIN14) | \
+ PIN_MODE_ANALOG(GPIOE_PIN15))
+#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOE_PIN15))
+#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_HIGH(GPIOE_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN1) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOE_PIN15))
+#define VAL_GPIOE_PUPDR (PIN_PUPDR_FLOATING(GPIOE_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOE_PIN15))
+#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | \
+ PIN_ODR_HIGH(GPIOE_PIN1) | \
+ PIN_ODR_HIGH(GPIOE_PIN2) | \
+ PIN_ODR_HIGH(GPIOE_PIN3) | \
+ PIN_ODR_HIGH(GPIOE_PIN4) | \
+ PIN_ODR_HIGH(GPIOE_PIN5) | \
+ PIN_ODR_HIGH(GPIOE_PIN6) | \
+ PIN_ODR_HIGH(GPIOE_PIN7) | \
+ PIN_ODR_HIGH(GPIOE_PIN8) | \
+ PIN_ODR_HIGH(GPIOE_PIN9) | \
+ PIN_ODR_HIGH(GPIOE_PIN10) | \
+ PIN_ODR_HIGH(GPIOE_PIN11) | \
+ PIN_ODR_HIGH(GPIOE_PIN12) | \
+ PIN_ODR_HIGH(GPIOE_PIN13) | \
+ PIN_ODR_HIGH(GPIOE_PIN14) | \
+ PIN_ODR_HIGH(GPIOE_PIN15))
+#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN7, 0U))
+#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOE_PIN15, 0U))
+#define VAL_GPIOE_ASCR (PIN_ASCR_DISABLED(GPIOE_PIN0) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN1) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN2) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN3) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN4) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN5) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN6) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN7) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN8) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN9) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN10) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN11) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN12) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN13) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN14) | \
+ PIN_ASCR_DISABLED(GPIOE_PIN15))
+#define VAL_GPIOE_LOCKR (PIN_LOCKR_DISABLED(GPIOE_PIN0) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN1) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN2) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN3) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN4) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN5) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN6) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN7) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN8) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN9) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN10) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN11) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN12) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN13) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN14) | \
+ PIN_LOCKR_DISABLED(GPIOE_PIN15))
+
+/*
+ * GPIOF setup:
+ *
+ * PF0 - PIN0 (analog).
+ * PF1 - PIN1 (analog).
+ * PF2 - PIN2 (analog).
+ * PF3 - PIN3 (analog).
+ * PF4 - PIN4 (analog).
+ * PF5 - PIN5 (analog).
+ * PF6 - PIN6 (analog).
+ * PF7 - PIN7 (analog).
+ * PF8 - PIN8 (analog).
+ * PF9 - PIN9 (analog).
+ * PF10 - PIN10 (analog).
+ * PF11 - PIN11 (analog).
+ * PF12 - PIN12 (analog).
+ * PF13 - PIN13 (analog).
+ * PF14 - PIN14 (analog).
+ * PF15 - PIN15 (analog).
+ */
+#define VAL_GPIOF_MODER (PIN_MODE_ANALOG(GPIOF_PIN0) | \
+ PIN_MODE_ANALOG(GPIOF_PIN1) | \
+ PIN_MODE_ANALOG(GPIOF_PIN2) | \
+ PIN_MODE_ANALOG(GPIOF_PIN3) | \
+ PIN_MODE_ANALOG(GPIOF_PIN4) | \
+ PIN_MODE_ANALOG(GPIOF_PIN5) | \
+ PIN_MODE_ANALOG(GPIOF_PIN6) | \
+ PIN_MODE_ANALOG(GPIOF_PIN7) | \
+ PIN_MODE_ANALOG(GPIOF_PIN8) | \
+ PIN_MODE_ANALOG(GPIOF_PIN9) | \
+ PIN_MODE_ANALOG(GPIOF_PIN10) | \
+ PIN_MODE_ANALOG(GPIOF_PIN11) | \
+ PIN_MODE_ANALOG(GPIOF_PIN12) | \
+ PIN_MODE_ANALOG(GPIOF_PIN13) | \
+ PIN_MODE_ANALOG(GPIOF_PIN14) | \
+ PIN_MODE_ANALOG(GPIOF_PIN15))
+#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOF_PIN15))
+#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_HIGH(GPIOF_PIN0) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN1) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN2) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN3) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN4) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN5) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN6) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN7) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN8) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN9) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN10) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN11) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN12) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN13) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN14) | \
+ PIN_OSPEED_HIGH(GPIOF_PIN15))
+#define VAL_GPIOF_PUPDR (PIN_PUPDR_FLOATING(GPIOF_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOF_PIN15))
+#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_PIN0) | \
+ PIN_ODR_HIGH(GPIOF_PIN1) | \
+ PIN_ODR_HIGH(GPIOF_PIN2) | \
+ PIN_ODR_HIGH(GPIOF_PIN3) | \
+ PIN_ODR_HIGH(GPIOF_PIN4) | \
+ PIN_ODR_HIGH(GPIOF_PIN5) | \
+ PIN_ODR_HIGH(GPIOF_PIN6) | \
+ PIN_ODR_HIGH(GPIOF_PIN7) | \
+ PIN_ODR_HIGH(GPIOF_PIN8) | \
+ PIN_ODR_HIGH(GPIOF_PIN9) | \
+ PIN_ODR_HIGH(GPIOF_PIN10) | \
+ PIN_ODR_HIGH(GPIOF_PIN11) | \
+ PIN_ODR_HIGH(GPIOF_PIN12) | \
+ PIN_ODR_HIGH(GPIOF_PIN13) | \
+ PIN_ODR_HIGH(GPIOF_PIN14) | \
+ PIN_ODR_HIGH(GPIOF_PIN15))
+#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN7, 0U))
+#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOF_PIN15, 0U))
+#define VAL_GPIOF_ASCR (PIN_ASCR_DISABLED(GPIOF_PIN0) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN1) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN2) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN3) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN4) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN5) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN6) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN7) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN8) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN9) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN10) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN11) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN12) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN13) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN14) | \
+ PIN_ASCR_DISABLED(GPIOF_PIN15))
+#define VAL_GPIOF_LOCKR (PIN_LOCKR_DISABLED(GPIOF_PIN0) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN1) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN2) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN3) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN4) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN5) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN6) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN7) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN8) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN9) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN10) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN11) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN12) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN13) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN14) | \
+ PIN_LOCKR_DISABLED(GPIOF_PIN15))
+
+/*
+ * GPIOG setup:
+ *
+ * PG0 - PIN0 (analog).
+ * PG1 - PIN1 (analog).
+ * PG2 - PIN2 (analog).
+ * PG3 - PIN3 (analog).
+ * PG4 - PIN4 (analog).
+ * PG5 - PIN5 (analog).
+ * PG6 - PIN6 (analog).
+ * PG7 - PIN7 (analog).
+ * PG8 - PIN8 (analog).
+ * PG9 - PIN9 (analog).
+ * PG10 - PIN10 (analog).
+ * PG11 - PIN11 (analog).
+ * PG12 - PIN12 (analog).
+ * PG13 - PIN13 (analog).
+ * PG14 - PIN14 (analog).
+ * PG15 - PIN15 (analog).
+ */
+#define VAL_GPIOG_MODER (PIN_MODE_ANALOG(GPIOG_PIN0) | \
+ PIN_MODE_ANALOG(GPIOG_PIN1) | \
+ PIN_MODE_ANALOG(GPIOG_PIN2) | \
+ PIN_MODE_ANALOG(GPIOG_PIN3) | \
+ PIN_MODE_ANALOG(GPIOG_PIN4) | \
+ PIN_MODE_ANALOG(GPIOG_PIN5) | \
+ PIN_MODE_ANALOG(GPIOG_PIN6) | \
+ PIN_MODE_ANALOG(GPIOG_PIN7) | \
+ PIN_MODE_ANALOG(GPIOG_PIN8) | \
+ PIN_MODE_ANALOG(GPIOG_PIN9) | \
+ PIN_MODE_ANALOG(GPIOG_PIN10) | \
+ PIN_MODE_ANALOG(GPIOG_PIN11) | \
+ PIN_MODE_ANALOG(GPIOG_PIN12) | \
+ PIN_MODE_ANALOG(GPIOG_PIN13) | \
+ PIN_MODE_ANALOG(GPIOG_PIN14) | \
+ PIN_MODE_ANALOG(GPIOG_PIN15))
+#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_PIN0) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN1) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOG_PIN15))
+#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOG_PIN0) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN1) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOG_PIN15))
+#define VAL_GPIOG_PUPDR (PIN_PUPDR_FLOATING(GPIOG_PIN0) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN1) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOG_PIN15))
+#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_PIN0) | \
+ PIN_ODR_HIGH(GPIOG_PIN1) | \
+ PIN_ODR_HIGH(GPIOG_PIN2) | \
+ PIN_ODR_HIGH(GPIOG_PIN3) | \
+ PIN_ODR_HIGH(GPIOG_PIN4) | \
+ PIN_ODR_HIGH(GPIOG_PIN5) | \
+ PIN_ODR_HIGH(GPIOG_PIN6) | \
+ PIN_ODR_HIGH(GPIOG_PIN7) | \
+ PIN_ODR_HIGH(GPIOG_PIN8) | \
+ PIN_ODR_HIGH(GPIOG_PIN9) | \
+ PIN_ODR_HIGH(GPIOG_PIN10) | \
+ PIN_ODR_HIGH(GPIOG_PIN11) | \
+ PIN_ODR_HIGH(GPIOG_PIN12) | \
+ PIN_ODR_HIGH(GPIOG_PIN13) | \
+ PIN_ODR_HIGH(GPIOG_PIN14) | \
+ PIN_ODR_HIGH(GPIOG_PIN15))
+#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_PIN0, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN1, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN7, 0U))
+#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOG_PIN15, 0U))
+#define VAL_GPIOG_ASCR (PIN_ASCR_DISABLED(GPIOG_PIN0) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN1) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN2) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN3) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN4) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN5) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN6) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN7) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN8) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN9) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN10) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN11) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN12) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN13) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN14) | \
+ PIN_ASCR_DISABLED(GPIOG_PIN15))
+#define VAL_GPIOG_LOCKR (PIN_LOCKR_DISABLED(GPIOG_PIN0) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN1) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN2) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN3) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN4) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN5) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN6) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN7) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN8) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN9) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN10) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN11) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN12) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN13) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN14) | \
+ PIN_LOCKR_DISABLED(GPIOG_PIN15))
+
+/*
+ * GPIOH setup:
+ *
+ * PH0 - OSC_IN (input floating).
+ * PH1 - OSC_OUT (input floating).
+ * PH2 - PIN2 (analog).
+ * PH3 - PIN3 (analog).
+ * PH4 - PIN4 (analog).
+ * PH5 - PIN5 (analog).
+ * PH6 - PIN6 (analog).
+ * PH7 - PIN7 (analog).
+ * PH8 - PIN8 (analog).
+ * PH9 - PIN9 (analog).
+ * PH10 - PIN10 (analog).
+ * PH11 - PIN11 (analog).
+ * PH12 - PIN12 (analog).
+ * PH13 - PIN13 (analog).
+ * PH14 - PIN14 (analog).
+ * PH15 - PIN15 (analog).
+ */
+#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_OSC_IN) | \
+ PIN_MODE_INPUT(GPIOH_OSC_OUT) | \
+ PIN_MODE_ANALOG(GPIOH_PIN2) | \
+ PIN_MODE_ANALOG(GPIOH_PIN3) | \
+ PIN_MODE_ANALOG(GPIOH_PIN4) | \
+ PIN_MODE_ANALOG(GPIOH_PIN5) | \
+ PIN_MODE_ANALOG(GPIOH_PIN6) | \
+ PIN_MODE_ANALOG(GPIOH_PIN7) | \
+ PIN_MODE_ANALOG(GPIOH_PIN8) | \
+ PIN_MODE_ANALOG(GPIOH_PIN9) | \
+ PIN_MODE_ANALOG(GPIOH_PIN10) | \
+ PIN_MODE_ANALOG(GPIOH_PIN11) | \
+ PIN_MODE_ANALOG(GPIOH_PIN12) | \
+ PIN_MODE_ANALOG(GPIOH_PIN13) | \
+ PIN_MODE_ANALOG(GPIOH_PIN14) | \
+ PIN_MODE_ANALOG(GPIOH_PIN15))
+#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_OSC_IN) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_OSC_OUT) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \
+ PIN_OTYPE_PUSHPULL(GPIOH_PIN15))
+#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_HIGH(GPIOH_OSC_IN) | \
+ PIN_OSPEED_HIGH(GPIOH_OSC_OUT) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN2) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN3) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN4) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN5) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN6) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN7) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN8) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN9) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN10) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN11) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN12) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN13) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN14) | \
+ PIN_OSPEED_VERYLOW(GPIOH_PIN15))
+#define VAL_GPIOH_PUPDR (PIN_PUPDR_FLOATING(GPIOH_OSC_IN) | \
+ PIN_PUPDR_FLOATING(GPIOH_OSC_OUT) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN2) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN3) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN4) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN5) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN6) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN7) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN8) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN9) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN10) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN11) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN12) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN13) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN14) | \
+ PIN_PUPDR_FLOATING(GPIOH_PIN15))
+#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_OSC_IN) | \
+ PIN_ODR_HIGH(GPIOH_OSC_OUT) | \
+ PIN_ODR_HIGH(GPIOH_PIN2) | \
+ PIN_ODR_HIGH(GPIOH_PIN3) | \
+ PIN_ODR_HIGH(GPIOH_PIN4) | \
+ PIN_ODR_HIGH(GPIOH_PIN5) | \
+ PIN_ODR_HIGH(GPIOH_PIN6) | \
+ PIN_ODR_HIGH(GPIOH_PIN7) | \
+ PIN_ODR_HIGH(GPIOH_PIN8) | \
+ PIN_ODR_HIGH(GPIOH_PIN9) | \
+ PIN_ODR_HIGH(GPIOH_PIN10) | \
+ PIN_ODR_HIGH(GPIOH_PIN11) | \
+ PIN_ODR_HIGH(GPIOH_PIN12) | \
+ PIN_ODR_HIGH(GPIOH_PIN13) | \
+ PIN_ODR_HIGH(GPIOH_PIN14) | \
+ PIN_ODR_HIGH(GPIOH_PIN15))
+#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_OSC_IN, 0U) | \
+ PIN_AFIO_AF(GPIOH_OSC_OUT, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN2, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN3, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN4, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN5, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN6, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN7, 0U))
+#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN9, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN10, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN11, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN12, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN13, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN14, 0U) | \
+ PIN_AFIO_AF(GPIOH_PIN15, 0U))
+#define VAL_GPIOH_ASCR (PIN_ASCR_DISABLED(GPIOH_OSC_IN) | \
+ PIN_ASCR_DISABLED(GPIOH_OSC_OUT) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN2) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN3) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN4) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN5) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN6) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN7) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN8) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN9) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN10) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN11) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN12) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN13) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN14) | \
+ PIN_ASCR_DISABLED(GPIOH_PIN15))
+#define VAL_GPIOH_LOCKR (PIN_LOCKR_DISABLED(GPIOH_OSC_IN) | \
+ PIN_LOCKR_DISABLED(GPIOH_OSC_OUT) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN2) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN3) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN4) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN5) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN6) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN7) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN8) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN9) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN10) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN11) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN12) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN13) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN14) | \
+ PIN_LOCKR_DISABLED(GPIOH_PIN15))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* BOARD_H */
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L476RG/board.mk b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L476RG/board.mk
new file mode 100644
index 0000000..3938fc5
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L476RG/board.mk
@@ -0,0 +1,9 @@
+# List of all the board related files.
+BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_L476RG/board.c
+
+# Required include directories
+BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO64_L476RG
+
+# Shared variables
+ALLCSRC += $(BOARDSRC)
+ALLINC += $(BOARDINC)
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L476RG/cfg/board.chcfg b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L476RG/cfg/board.chcfg
new file mode 100644
index 0000000..5cdbd96
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L476RG/cfg/board.chcfg
@@ -0,0 +1,1320 @@
+
+
+
+
+ resources/gencfg/processors/boards/stm32l4xx/templates
+ ..
+ 5.0.x
+
+ STMicroelectronics STM32 Nucleo64-L476RG
+ ST_NUCLEO64_L476RG
+
+ STM32L476xx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L476RG/cfg/board.fmpp b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L476RG/cfg/board.fmpp
new file mode 100644
index 0000000..3c311d3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/ST_NUCLEO64_L476RG/cfg/board.fmpp
@@ -0,0 +1,15 @@
+sourceRoot: ../../../../../tools/ftl/processors/boards/stm32l4xx/templates
+outputRoot: ..
+dataRoot: .
+
+freemarkerLinks: {
+ lib: ../../../../../tools/ftl/libs
+}
+
+data : {
+ doc1:xml (
+ board.chcfg
+ {
+ }
+ )
+}
diff --git a/ChibiOS_20.3.2/os/hal/boards/genboard.sh b/ChibiOS_20.3.2/os/hal/boards/genboard.sh
new file mode 100644
index 0000000..8e8a112
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/genboard.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+if [ $# -eq 1 ]
+then
+ echo "Processing: $1"
+ if ! fmpp -q -C $1/cfg/board.fmpp
+ then
+ echo
+ echo "aborted"
+ exit 1
+ else
+ echo
+ echo "done"
+ exit 0
+ fi
+else
+ echo "Usage: genboard "
+fi
diff --git a/ChibiOS_20.3.2/os/hal/boards/genboards.sh b/ChibiOS_20.3.2/os/hal/boards/genboards.sh
new file mode 100644
index 0000000..91b6cc6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/genboards.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+if [ $# -eq 0 ]
+then
+ find . -name board.fmpp -exec bash genboards.sh '{}' \;
+elif [ $# -eq 1 ]
+then
+ path=$(readlink -f $(dirname $1))
+ echo "Processing: $1"
+ cd $path
+ if ! fmpp -q -C board.fmpp
+ then
+ echo
+ echo "aborted"
+ exit 1
+ fi
+else
+ echo "illegal number of arguments"
+fi
diff --git a/ChibiOS_20.3.2/os/hal/boards/readme.txt b/ChibiOS_20.3.2/os/hal/boards/readme.txt
new file mode 100644
index 0000000..c033834
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/boards/readme.txt
@@ -0,0 +1,17 @@
+This directory contains the support files for various board models. If you
+want to support a new board:
+- Create a new directory under ./os/hal/boards, give it the name of your board.
+- Copy inside the new directory the files from a similar board.
+- Customize board.c, board.h and board.mk in order to correctly initialize
+ your board.
+
+The files in those board directories containing:
+- /cfg/board.chcfg
+- /cfg/board.fmpp
+are generated automatically, just run the "fmpp" tool from within /cfg,
+the download is available here: http://fmpp.sourceforge.net, note, it
+requires Java.
+
+All board files can be batch-regenerated automatically by running the
+genboards.sh script in this same directory.
+
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal.dox b/ChibiOS_20.3.2/os/hal/dox/hal.dox
new file mode 100644
index 0000000..5c1ac3d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal.dox
@@ -0,0 +1,32 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup HAL HAL Driver
+ * @brief Hardware Abstraction Layer.
+ * @details The HAL (Hardware Abstraction Layer) driver performs the system
+ * initialization and includes the platform support code shared by
+ * the other drivers. This driver does contain any API function
+ * except for a general initialization function @p halInit() that
+ * must be invoked before any HAL service can be used, usually the
+ * HAL initialization should be performed immediately before the
+ * kernel initialization.
+ * Some HAL driver implementations also offer a custom early clock
+ * setup function that can be invoked before the C runtime
+ * initialization in order to accelerate the startup time.
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_adc.dox b/ChibiOS_20.3.2/os/hal/dox/hal_adc.dox
new file mode 100644
index 0000000..c80a0b4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_adc.dox
@@ -0,0 +1,141 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup ADC ADC Driver
+ * @brief Generic ADC Driver.
+ * @details This module implements a generic ADC (Analog to Digital Converter)
+ * driver supporting a variety of buffer and conversion modes.
+ * @pre In order to use the ADC driver the @p HAL_USE_ADC option
+ * must be enabled in @p halconf.h.
+ *
+ * @section adc_1 Driver State Machine
+ * The driver implements a state machine internally, not all the driver
+ * functionalities can be used in any moment, any transition not explicitly
+ * shown in the following diagram has to be considered an error and shall
+ * be captured by an assertion (if enabled).
+ * @if LATEX_PDF
+ * @dot
+ digraph example {
+ rankdir="LR";
+ size="5, 7";
+
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ stop [label="ADC_STOP\nLow Power"];
+ uninit [label="ADC_UNINIT", style="bold"];
+ ready [label="ADC_READY\nClock Enabled"];
+ active [label="ADC_ACTIVE\nConverting"];
+ error [label="ADC_ERROR\nError"];
+ complete [label="ADC_COMPLETE\nComplete"];
+
+ uninit -> stop [label="\n adcInit()", constraint=false];
+ stop -> ready [label="\nadcStart()"];
+ ready -> ready [label="\nadcStart()\nadcStopConversion()"];
+ ready -> stop [label="\nadcStop()"];
+ stop -> stop [label="\nadcStop()"];
+ ready -> active [label="\nadcStartConversion() (async)\nadcConvert() (sync)"];
+ active -> ready [label="\nadcStopConversion()\nsync return"];
+ active -> active [label="\nasync callback (half buffer, circular)\nasync callback (full buffer)\n>acg_endcb<"];
+ active -> complete [label="\n\nasync callback (full buffer)\n>end_cb<"];
+ active -> error [label="\n\nasync callback (error)\n>error_cb<"];
+ complete -> active [label="\nadcStartConversionI()\nthen\ncallback return"];
+ complete -> ready [label="\ncallback return"];
+ error -> active [label="\nadcStartConversionI()\nthen\ncallback return"];
+ error -> ready [label="\ncallback return"];
+ }
+ * @enddot
+ * @else
+ * @dot
+ digraph example {
+ rankdir="LR";
+
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ stop [label="ADC_STOP\nLow Power"];
+ uninit [label="ADC_UNINIT", style="bold"];
+ ready [label="ADC_READY\nClock Enabled"];
+ active [label="ADC_ACTIVE\nConverting"];
+ error [label="ADC_ERROR\nError"];
+ complete [label="ADC_COMPLETE\nComplete"];
+
+ uninit -> stop [label="\n adcInit()", constraint=false];
+ stop -> ready [label="\nadcStart()"];
+ ready -> ready [label="\nadcStart()\nadcStopConversion()"];
+ ready -> stop [label="\nadcStop()"];
+ stop -> stop [label="\nadcStop()"];
+ ready -> active [label="\nadcStartConversion() (async)\nadcConvert() (sync)"];
+ active -> ready [label="\nadcStopConversion()\nsync return"];
+ active -> active [label="\nasync callback (half buffer, circular)\nasync callback (full buffer)\n>acg_endcb<"];
+ active -> complete [label="\n\nasync callback (full buffer)\n>end_cb<"];
+ active -> error [label="\n\nasync callback (error)\n>error_cb<"];
+ complete -> active [label="\nadcStartConversionI()\nthen\ncallback return"];
+ complete -> ready [label="\ncallback return"];
+ error -> active [label="\nadcStartConversionI()\nthen\ncallback return"];
+ error -> ready [label="\ncallback return"];
+ }
+ * @enddot
+ * @endif
+ *
+ * @section adc_2 ADC Operations
+ * The ADC driver is quite complex, an explanation of the terminology and of
+ * the operational details follows.
+ *
+ * @subsection adc_2_1 ADC Conversion Groups
+ * The @p ADCConversionGroup is the objects that specifies a physical
+ * conversion operation. This structure contains some standard fields and
+ * several implementation-dependent fields.
+ * The standard fields define the CG mode, the number of channels belonging
+ * to the CG and the optional callbacks.
+ * The implementation-dependent fields specify the physical ADC operation
+ * mode, the analog channels belonging to the group and any other
+ * implementation-specific setting. Usually the extra fields just mirror
+ * the physical ADC registers, please refer to the vendor's MCU Reference
+ * Manual for details about the available settings. Details are also available
+ * into the documentation of the ADC low level drivers and in the various
+ * sample applications.
+ *
+ * @subsection adc_2_2 ADC Conversion Modes
+ * The driver supports several conversion modes:
+ * - One Shot, the driver performs a single group conversion then stops.
+ * - Linear Buffer, the driver performs a series of group conversions
+ * then stops. This mode is like a one shot conversion repeated N times,
+ * the buffer pointer increases after each conversion. The buffer is
+ * organized as an S(CG)*N samples matrix, when S(CG) is the conversion
+ * group size (number of channels) and N is the buffer depth (number of
+ * repeated conversions).
+ * - Circular Buffer, much like the linear mode but the operation does
+ * not stop when the buffer is filled, it is automatically restarted
+ * with the buffer pointer wrapping back to the buffer base.
+ * .
+ * @subsection adc_2_3 ADC Callbacks
+ * The driver is able to invoke callbacks during the conversion process. A
+ * callback is invoked when the operation has been completed or, in circular
+ * mode, when the buffer has been filled and the operation is restarted. In
+ * circular mode a callback is also invoked when the buffer is half filled.
+ * The "half filled" and "filled" callbacks in circular mode allow to
+ * implement "streaming processing" of the sampled data, while the driver is
+ * busy filling one half of the buffer the application can process the
+ * other half, this allows for continuous interleaved operations.
+ *
+ * The driver is not thread safe for performance reasons, if you need to access
+ * the ADC bus from multiple threads then use the @p adcAcquireBus() and
+ * @p adcReleaseBus() APIs in order to gain exclusive access.
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_buffers.dox b/ChibiOS_20.3.2/os/hal/dox/hal_buffers.dox
new file mode 100644
index 0000000..c5da714
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_buffers.dox
@@ -0,0 +1,20 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup HAL_BUFFERS I/O Buffers Queues
+ * @ingroup HAL_INNER_CODE
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_can.dox b/ChibiOS_20.3.2/os/hal/dox/hal_can.dox
new file mode 100644
index 0000000..5dd8104
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_can.dox
@@ -0,0 +1,87 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup CAN CAN Driver
+ * @brief Generic CAN Driver.
+ * @details This module implements a generic CAN (Controller Area Network)
+ * driver allowing the exchange of information at frame level.
+ * @pre In order to use the CAN driver the @p HAL_USE_CAN option
+ * must be enabled in @p halconf.h.
+ *
+ * @section can_1 Driver State Machine
+ * The driver implements a state machine internally, not all the driver
+ * functionalities can be used in any moment, any transition not explicitly
+ * shown in the following diagram has to be considered an error and shall
+ * be captured by an assertion (if enabled).
+ * @if LATEX_PDF
+ * @dot
+ digraph example {
+ size="5, 7";
+ rankdir="LR";
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ stop [label="CAN_STOP\nLow Power"];
+ uninit [label="CAN_UNINIT", style="bold"];
+ starting [label="CAN_STARTING\nInitializing"];
+ ready [label="CAN_READY\nClock Enabled"];
+ sleep [label="CAN_SLEEP\nLow Power"];
+
+ uninit -> stop [label=" canInit()", constraint=false];
+ stop -> stop [label="\ncanStop()"];
+ stop -> ready [label="\ncanStart()\n(fast implementation)"];
+ stop -> starting [label="\ncanStart()\n(slow implementation)"];
+ starting -> ready [label="\ninitialization complete\n(all threads)"];
+ ready -> stop [label="\ncanStop()"];
+ ready -> ready [label="\ncanReceive()\ncanTransmit()"];
+ ready -> sleep [label="\ncanSleep()"];
+ sleep -> sleep [label="\ncanSleep()"];
+ sleep -> ready [label="\ncanWakeup()"];
+ sleep -> ready [label="\nhardware\nwakeup event"];
+ }
+ * @enddot
+ * @else
+ * @dot
+ digraph example {
+ rankdir="LR";
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ stop [label="CAN_STOP\nLow Power"];
+ uninit [label="CAN_UNINIT", style="bold"];
+ starting [label="CAN_STARTING\nInitializing"];
+ ready [label="CAN_READY\nClock Enabled"];
+ sleep [label="CAN_SLEEP\nLow Power"];
+
+ uninit -> stop [label=" canInit()", constraint=false];
+ stop -> stop [label="\ncanStop()"];
+ stop -> ready [label="\ncanStart()\n(fast implementation)"];
+ stop -> starting [label="\ncanStart()\n(slow implementation)"];
+ starting -> starting [label="\ncanStart()\n(other thread)"];
+ starting -> ready [label="\ninitialization complete\n(all threads)"];
+ ready -> stop [label="\ncanStop()"];
+ ready -> ready [label="\ncanStart()\ncanReceive()\ncanTransmit()"];
+ ready -> sleep [label="\ncanSleep()"];
+ sleep -> sleep [label="\ncanSleep()"];
+ sleep -> ready [label="\ncanWakeup()"];
+ sleep -> ready [label="\nhardware\nwakeup event"];
+ }
+ * @enddot
+ * @endif
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_crypto.dox b/ChibiOS_20.3.2/os/hal/dox/hal_crypto.dox
new file mode 100644
index 0000000..b9ad2b1
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_crypto.dox
@@ -0,0 +1,25 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup CRYPTO Crypto Driver
+ * @brief Generic Crypto Driver.
+ * @details This module implements a generic Cryptography driver.
+ * @pre In order to use the crypto driver the @p HAL_USE_CRY option
+ * must be enabled in @p halconf.h.
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_dac.dox b/ChibiOS_20.3.2/os/hal/dox/hal_dac.dox
new file mode 100644
index 0000000..381e201
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_dac.dox
@@ -0,0 +1,26 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup DAC DAC Driver
+ * @brief Generic DAC Driver.
+ * @details This module implements a generic DAC (Digital to Analog Converter)
+ * driver.
+ * @pre In order to use the DAC driver the @p HAL_USE_DAC option
+ * must be enabled in @p halconf.h.
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_efl.dox b/ChibiOS_20.3.2/os/hal/dox/hal_efl.dox
new file mode 100644
index 0000000..02d8471
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_efl.dox
@@ -0,0 +1,25 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup HAL_EFL EFL Driver
+ * @brief Generic Embedded Flash Driver.
+ * @details This module implements a generic embedded flash driver.
+ * @pre In order to use the EFL driver the @p HAL_USE_EFL option
+ * must be enabled in @p halconf.h.
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_flash.dox b/ChibiOS_20.3.2/os/hal/dox/hal_flash.dox
new file mode 100644
index 0000000..7488944
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_flash.dox
@@ -0,0 +1,52 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup HAL_FLASH Generic Flash Interface
+ * @brief HAL Generic Flash Driver Interface.
+ *
+ * @section flash_1 Driver State Machine
+ * The flash driver implements a state machine internally, not all the driver
+ * functionalities can be used in any moment, any transition not explicitly
+ * shown in the following diagram has to be considered an error and shall
+ * be captured by an assertion (if enabled).
+ * @dot
+ digraph example {
+ rankdir="LR";
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+ stop [label="FLS_STOP\nLow Power"];
+ uninit [label="FLS_UNINIT", style="bold"];
+ ready [label="FLS_READY\nClock Enabled"];
+ read [label="FLS_READ\nReading"];
+ pgm [label="FLS_PGM\nProgramming"];
+ erase [label="FLS_ERASE\nErasing"];
+ uninit -> stop [label=" xxxInit()", constraint=false];
+ stop -> stop [label=" xxxStop()"];
+ stop -> ready [label=" xxxStart()"];
+ ready -> stop [label=" xStop()"];
+ ready -> read [label=" flashRead()\nflashVerifyErase()"];
+ read -> ready [label=" return"];
+ ready -> pgm [label=" flashProgram()"];
+ pgm -> ready [label=" return"];
+ ready -> erase [label=" \n\nflashEraseAll()\nflashEraseSector()"];
+ erase -> ready [label=" flashQueryErase()\nFLASH_NO_ERROR\nFLASH_ERROR_*"];
+ erase -> erase [label=" flashQueryErase()\nflashProgram()\nflashRead()\nFLASH_BUSY_ERASING"];
+ }
+ * @enddot
+ *
+ * @ingroup HAL_ABSTRACT_PERIPHERALS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_gpt.dox b/ChibiOS_20.3.2/os/hal/dox/hal_gpt.dox
new file mode 100644
index 0000000..d75dab2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_gpt.dox
@@ -0,0 +1,74 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup GPT GPT Driver
+ * @brief Generic GPT Driver.
+ * @details This module implements a generic GPT (General Purpose Timer)
+ * driver. The timer can be programmed in order to trigger callbacks
+ * after a specified time period or continuously with a specified
+ * interval.
+ * @pre In order to use the GPT driver the @p HAL_USE_GPT option
+ * must be enabled in @p halconf.h.
+ *
+ * @section gpt_1 Driver State Machine
+ * The driver implements a state machine internally, not all the driver
+ * functionalities can be used in any moment, any transition not explicitly
+ * shown in the following diagram has to be considered an error and shall
+ * be captured by an assertion (if enabled).
+ * @dot
+ digraph example {
+ rankdir="LR";
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true",
+ width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ stop [label="GPT_STOP\nLow Power"];
+ uninit [label="GPT_UNINIT", style="bold"];
+ ready [label="GPT_READY\nClock Enabled"];
+ continuous [label="GPT_CONT..S\nContinuous\nMode"];
+ oneshot [label="GPT_ONESHOT\nOne Shot\nMode"];
+
+ uninit -> stop [label=" gptInit()", constraint=false];
+ stop -> stop [label="\ngptStop()"];
+ stop -> ready [label="\ngptStart()"];
+ ready -> stop [label="\ngptStop()"];
+ ready -> ready [label="\ngptStart()"];
+ ready -> continuous [label="\ngptStartContinuous()"];
+ continuous -> ready [label="\ngptStopTimer()"];
+ continuous -> continuous [label=">callback<"];
+ ready -> oneshot [label="\ngptStartOneShot()\ngptPolledDelay()"];
+ oneshot -> ready [label="\n>callback<\nor\nDelay Over"];
+ }
+ * @enddot
+ *
+ * @section gpt_2 GPT Operations.
+ * This driver abstracts a generic timer composed of:
+ * - A clock prescaler.
+ * - A main up counter.
+ * - A comparator register that resets the main counter to zero when the limit
+ * is reached. A callback is invoked when this happens.
+ * .
+ * The timer can operate in three different modes:
+ * - Continuous Mode, a periodic callback is invoked until the driver
+ * is explicitly stopped.
+ * - One Shot Mode, a callback is invoked after the programmed period
+ * and then the timer automatically stops.
+ * - Delay Mode, the timer is used for inserting a brief delay into
+ * the execution flow, no callback is invoked in this mode.
+ * .
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_i2c.dox b/ChibiOS_20.3.2/os/hal/dox/hal_i2c.dox
new file mode 100644
index 0000000..c5a39f3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_i2c.dox
@@ -0,0 +1,98 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup I2C I2C Driver
+ * @brief Generic I2C Driver.
+ * @details This module implements a generic I2C (Inter-Integrated Circuit)
+ * driver.
+ * @pre In order to use the I2C driver the @p HAL_USE_I2C option
+ * must be enabled in @p halconf.h.
+ *
+ * @section i2c_1 Driver State Machine
+ * The driver implements a state machine internally, not all the driver
+ * functionalities can be used in any moment, any transition not explicitly
+ * shown in the following diagram has to be considered an error and shall
+ * be captured by an assertion (if enabled).
+ * @if LATEX_PDF
+ * @dot
+ digraph example {
+ size="5, 7";
+ rankdir="LR";
+
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true",
+ width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ stop [label="I2C_STOP\nLow Power"];
+ uninit [label="I2C_UNINIT", style="bold"];
+ ready [label="I2C_READY\nClock Enabled"];
+ active_tx [label="I2C_ACTIVE_TX\nBus TX Active"];
+ active_rx [label="I2C_ACTIVE_RX\nBus RX Active"];
+ locked [label="I2C_LOCKED\nBus Locked"];
+
+ uninit -> stop [label="i2cInit()", constraint=false];
+ stop -> stop [label="i2cStop()"];
+ stop -> ready [label="i2cStart()"];
+ ready -> ready [label="i2cStart()"];
+ ready -> stop [label="i2cStop()"];
+ ready -> active_tx [label="i2cMasterTransmit()"];
+ ready -> active_rx [label="i2cMasterReceive()"];
+ active_tx -> ready [label="completed"];
+ active_rx -> ready [label="completed"];
+ active_tx -> locked [label="RDY_TIMEOUT"];
+ active_rx -> locked [label="RDY_TIMEOUT"];
+ locked -> stop [label="i2cStop()"];
+ locked -> ready [label="i2cStart()"];
+ }
+ * @else
+ * @dot
+ digraph example {
+ rankdir="LR";
+
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true",
+ width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ stop [label="I2C_STOP\nLow Power"];
+ uninit [label="I2C_UNINIT", style="bold"];
+ ready [label="I2C_READY\nClock Enabled"];
+ active_tx [label="I2C_ACTIVE_TX\nBus TX Active"];
+ active_rx [label="I2C_ACTIVE_RX\nBus RX Active"];
+ locked [label="I2C_LOCKED\nBus Locked"];
+
+ uninit -> stop [label="i2cInit()", constraint=false];
+ stop -> stop [label="i2cStop()"];
+ stop -> ready [label="i2cStart()"];
+ ready -> ready [label="i2cStart()"];
+ ready -> stop [label="i2cStop()"];
+ ready -> active_tx [label="i2cMasterTransmit()"];
+ ready -> active_rx [label="i2cMasterReceive()"];
+ active_tx -> ready [label="completed"];
+ active_rx -> ready [label="completed"];
+ active_tx -> locked [label="RDY_TIMEOUT"];
+ active_rx -> locked [label="RDY_TIMEOUT"];
+ locked -> stop [label="i2cStop()"];
+ locked -> ready [label="i2cStart()"];
+ }
+ * @enddot
+ * @endif
+ * The driver is not thread safe for performance reasons, if you need to access
+ * the I2C bus from multiple threads then use the @p i2cAcquireBus() and
+ * @p i2cReleaseBus() APIs in order to gain exclusive access.
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_i2s.dox b/ChibiOS_20.3.2/os/hal/dox/hal_i2s.dox
new file mode 100644
index 0000000..629b5e9
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_i2s.dox
@@ -0,0 +1,27 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup I2S I2S Driver
+ * @brief Generic I2S Driver.
+ * @details This module implements a generic I2S driver.
+ * @pre In order to use the I2S driver the @p HAL_USE_I2S option
+ * must be enabled in @p halconf.h.
+ *
+ * @section i2s_1 Driver State Machine
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_icu.dox b/ChibiOS_20.3.2/os/hal/dox/hal_icu.dox
new file mode 100644
index 0000000..710c388
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_icu.dox
@@ -0,0 +1,107 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup ICU ICU Driver
+ * @brief Generic ICU Driver.
+ * @details This module implements a generic ICU (Input Capture Unit) driver.
+ * The purpose of the driver is to measure period and duty cycle of
+ * an input digital signal (PWM input).
+ * @pre In order to use the ICU driver the @p HAL_USE_ICU option
+ * must be enabled in @p halconf.h.
+ *
+ * @section icu_1 Driver State Machine
+ * The driver implements a state machine internally, not all the driver
+ * functionalities can be used in any moment, any transition not explicitly
+ * shown in the following diagram has to be considered an error and shall
+ * be captured by an assertion (if enabled).
+ * @if LATEX_PDF
+ * @dot
+ digraph example {
+ size="5, 7";
+ rankdir="LR";
+
+ node [shape=circle, fontname=Sans, fontsize=8, fixedsize="true", width="0.9", height="0.9"];
+ edge [fontname=Sans, fontsize=8];
+
+ stop [label="ICU_STOP\nLow Power"];
+ uninit [label="ICU_UNINIT", style="bold"];
+ ready [label="ICU_READY\nClock Enabled"];
+ waiting [label="ICU_WAITING"];
+ active [label="ICU_ACTIVE"];
+
+ uninit -> stop [label=" icuInit()", constraint=false];
+ stop -> stop [label="\nicuStop()"];
+ stop -> ready [label="\nicuStart()"];
+ ready -> stop [label="\nicuStop()"];
+ ready -> ready [label="\nicuStart()\nicuStopCapture()"];
+ ready -> waiting [label="\nicuStartCapture()"];
+ waiting -> active [label="\nFirst Activation Edge\nicuWaitCapture()"];
+ waiting -> ready [label="\nicuStopCapture()"];
+ active -> ready [label="\nicuStopCapture()"];
+ active -> active [label="\nActivation Edge\n>period_cb<"];
+ active -> active [label="\nDe-activation Edge\n>width_cb<"];
+ }
+ * @enddot
+ * @else
+ * @dot
+ digraph example {
+ rankdir="LR";
+
+ node [shape=circle, fontname=Sans, fontsize=8, fixedsize="true", width="0.9", height="0.9"];
+ edge [fontname=Sans, fontsize=8];
+
+ stop [label="ICU_STOP\nLow Power"];
+ uninit [label="ICU_UNINIT", style="bold"];
+ ready [label="ICU_READY\nClock Enabled"];
+ waiting [label="ICU_WAITING"];
+ active [label="ICU_ACTIVE"];
+
+ uninit -> stop [label=" icuInit()", constraint=false];
+ stop -> stop [label="\nicuStop()"];
+ stop -> ready [label="\nicuStart()"];
+ ready -> stop [label="\nicuStop()"];
+ ready -> ready [label="\nicuStart()\nicuStopCapture()"];
+ ready -> waiting [label="\nicuStartCapture()"];
+ waiting -> active [label="\nFirst Activation Edge\nicuWaitCapture()"];
+ waiting -> ready [label="\nicuStopCapture()"];
+ active -> ready [label="\nicuStopCapture()"];
+ active -> active [label="\nActivation Edge\n>period_cb<"];
+ active -> active [label="\nDe-activation Edge\n>width_cb<"];
+ }
+ * @enddot
+ * @endif
+ *
+ * @section icu_2 ICU Operations.
+ * This driver abstracts a generic Input Capture Unit composed of:
+ * - A clock prescaler.
+ * - A main up counter.
+ * - Two capture registers triggered by the rising and falling edges on
+ * the sampled input.
+ * .
+ * The ICU unit can be programmed to synchronize on the rising or falling
+ * edge of the sample input:
+ * - ICU_INPUT_ACTIVE_HIGH, a rising edge is the start signal.
+ * - ICU_INPUT_ACTIVE_LOW, a falling edge is the start signal.
+ * .
+ * Callbacks are optionally invoked when:
+ * - On the PWM de-activation edge.
+ * - On the PWM activation edge, measurements for the previous cycle are
+ * available from this callback and can be retrieved using
+ * @p icuGetPeriodX() and @p icuGetWidthX().
+ * .
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_interfaces.dox b/ChibiOS_20.3.2/os/hal/dox/hal_interfaces.dox
new file mode 100644
index 0000000..c27305a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_interfaces.dox
@@ -0,0 +1,60 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup HAL_BLOCKS Blocks
+ * @ingroup HAL_INTERFACES_CLASSES
+ */
+
+/**
+ * @defgroup HAL_INTERFACES Streams
+ * @ingroup HAL_INTERFACES_CLASSES
+ */
+
+/**
+ * @defgroup HAL_STREAMS Abstract Streams Interface
+ * @ingroup HAL_INTERFACES
+ */
+
+/**
+ * @defgroup IO_CHANNEL Abstract I/O Channel Interface
+ * @ingroup HAL_INTERFACES
+ */
+
+/**
+ * @defgroup HAL_FILES Abstract Files Interface
+ * @ingroup HAL_INTERFACES
+ */
+
+/**
+ * @defgroup HAL_PERSISTENT Abstract Persistent Storage Interface
+ * @ingroup HAL_INTERFACES
+ */
+
+/**
+ * @defgroup HAL_MEMORY_STREAMS Memory Streams Class
+ * @ingroup HAL_INTERFACES
+ */
+
+/**
+ * @defgroup HAL_NULL_STREAMS Null Streams Class
+ * @ingroup HAL_INTERFACES
+ */
+
+/**
+ * @defgroup HAL_CHPRINTF Output Formatter Utility
+ * @ingroup HAL_INTERFACES
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_ioblock.dox b/ChibiOS_20.3.2/os/hal/dox/hal_ioblock.dox
new file mode 100644
index 0000000..cc83945
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_ioblock.dox
@@ -0,0 +1,100 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup IO_BLOCK Abstract I/O Block Device
+ * @ingroup HAL_BLOCKS
+ *
+ * @section io_block_1 Driver State Machine
+ * The drivers implementing this interface shall implement the following
+ * state machine internally. Not all the driver functionalities can be used
+ * in any moment, any transition not explicitly shown in the following
+ * diagram has to be considered an error and shall be captured by an
+ * assertion (if enabled).
+ * @if LATEX_PDF
+ * @dot
+ digraph example {
+ size="5, 7";
+ rankdir="LR";
+
+ node [shape=circle, fontname=Sans, fontsize=8, fixedsize="true", width="0.9", height="0.9"];
+ edge [fontname=Sans, fontsize=8];
+
+ stop [label="BLK_STOP\nLow Power"];
+ uninit [label="BLK_UNINIT", style="bold"];
+ active [label="BLK_ACTIVE\nClock Enabled"];
+ connecting [label="BLK_CONN.ING\nConnecting"];
+ disconnecting [label="BLK_DISC.ING\nDisconnecting"];
+ ready [label="BLK_READY\nCard Ready"];
+ reading [label="BLK_READING\nReading"];
+ writing [label="BLK_WRITING\nWriting"];
+
+ uninit -> stop [label=" blkInit()", constraint=false];
+ stop -> stop [label="\nblkStop()"];
+ stop -> active [label="\nblkStart()"];
+ active -> stop [label="\nblkStop()"];
+ active -> active [label="\nblkStart()\nblkDisconnect()"];
+ active -> connecting [label="\nblkConnect()"];
+ connecting -> ready [label="\nconnection\nsuccessful"];
+ connecting -> ready [label="\nblkConnect()", dir="back"];
+ connecting -> active [label="\nconnection\nfailed"];
+ disconnecting -> ready [label="\nblkDisconnect()", dir="back"];
+ active -> disconnecting [label="\ndisconnection\nfinished", dir="back"];
+ ready -> reading [label="\nblkRead()"];
+ reading -> ready [label="\nread finished\nread error"];
+ ready -> writing [label="\nblkWrite()"];
+ writing -> ready [label="\nwrite finished\nwrite error"];
+ }
+ * @enddot
+ * @else
+ * @dot
+ digraph example {
+ rankdir="LR";
+
+ node [shape=circle, fontname=Sans, fontsize=8, fixedsize="true", width="0.9", height="0.9"];
+ edge [fontname=Sans, fontsize=8];
+
+ stop [label="BLK_STOP\nLow Power"];
+ uninit [label="BLK_UNINIT", style="bold"];
+ active [label="BLK_ACTIVE\nClock Enabled"];
+ connecting [label="BLK_CONN.ING\nConnecting"];
+ disconnecting [label="BLK_DISC.ING\nDisconnecting"];
+ ready [label="BLK_READY\nCard Ready"];
+ reading [label="BLK_READING\nReading"];
+ writing [label="BLK_WRITING\nWriting"];
+ syncing [label="BLK_SYNCING\nSynchronizing"];
+
+ uninit -> stop [label=" blkInit()", constraint=false];
+ stop -> stop [label="\nblkStop()"];
+ stop -> active [label="\nblkStart()"];
+ active -> stop [label="\nblkStop()"];
+ active -> active [label="\nblkStart()\nblkDisconnect()"];
+ active -> connecting [label="\nblkConnect()"];
+ connecting -> ready [label="\nconnection\nsuccessful"];
+ connecting -> ready [label="\nblkConnect()", dir="back"];
+ connecting -> active [label="\nconnection\nfailed"];
+ disconnecting -> ready [label="\nblkDisconnect()", dir="back"];
+ active -> disconnecting [label="\ndisconnection\nfinished", dir="back"];
+ ready -> reading [label="\nblkRead()"];
+ reading -> ready [label="\nread finished\nread error"];
+ ready -> writing [label="\nblkWrite()"];
+ writing -> ready [label="\nwrite finished\nwrite error"];
+ ready -> syncing [label="\nblkSync()"];
+ syncing -> ready [label="\nsynchronization finished"];
+ }
+ * @enddot
+ * @endif
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_mac.dox b/ChibiOS_20.3.2/os/hal/dox/hal_mac.dox
new file mode 100644
index 0000000..c5e9c64
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_mac.dox
@@ -0,0 +1,26 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup MAC MAC Driver
+ * @brief Generic MAC Driver.
+ * @details This module implements a generic MAC (Media Access Control)
+ * driver for Ethernet controllers.
+ * @pre In order to use the MAC driver the @p HAL_USE_MAC option
+ * must be enabled in @p halconf.h.
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_mfs.dox b/ChibiOS_20.3.2/os/hal/dox/hal_mfs.dox
new file mode 100644
index 0000000..88b8046
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_mfs.dox
@@ -0,0 +1,30 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup HAL_MFS Managed Flash Storage Driver
+ * @brief Managed Flash Storage Driver.
+ * @details This module implements a managed flash storage able to store
+ * a finite number of variable-size records. Records are retrieved
+ * by their index number.
+ * The driver is automatically performs:
+ * - Wear leveling.
+ * - Auto repair after power loss.
+ * - Garbage collection in order to remove erased data.
+ * .
+ *
+ * @ingroup HAL_COMPLEX_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_mii.dox b/ChibiOS_20.3.2/os/hal/dox/hal_mii.dox
new file mode 100644
index 0000000..cfd7a1e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_mii.dox
@@ -0,0 +1,23 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup MII MII/RMII Header
+ * @brief MII/RMII Support Header
+ * @details This header contains definitions and types related to MII/RMII.
+ *
+ * @ingroup HAL_SUPPORT
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_mmc_spi.dox b/ChibiOS_20.3.2/os/hal/dox/hal_mmc_spi.dox
new file mode 100644
index 0000000..1dc4b27
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_mmc_spi.dox
@@ -0,0 +1,35 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup MMC_SPI MMC over SPI Driver
+ * @brief Generic MMC driver.
+ * @details This module implements a portable MMC/SD driver that uses a SPI
+ * driver as physical layer. Hot plugging and removal are supported
+ * through kernel events.
+ * @pre In order to use the MMC_SPI driver the @p HAL_USE_MMC_SPI and
+ * @p HAL_USE_SPI options must be enabled in @p halconf.h.
+ *
+ * @section mmc_spi_1 Driver State Machine
+ * This driver implements a state machine internally, see the @ref IO_BLOCK
+ * module documentation for details.
+ *
+ * @section mmc_spi_2 Driver Operations
+ * This driver allows to read or write single or multiple 512 bytes blocks
+ * on a SD Card.
+ *
+ * @ingroup HAL_COMPLEX_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_mmcsd.dox b/ChibiOS_20.3.2/os/hal/dox/hal_mmcsd.dox
new file mode 100644
index 0000000..3b8017c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_mmcsd.dox
@@ -0,0 +1,24 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup MMCSD MMC/SD Block Device
+ * @details This module implements a common ancestor for all device drivers
+ * accessing MMC or SD cards. This interface inherits the state
+ * machine and the interface from the @ref IO_BLOCK module.
+ *
+ * @ingroup HAL_INNER_CODE
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_norflash.dox b/ChibiOS_20.3.2/os/hal/dox/hal_norflash.dox
new file mode 100644
index 0000000..24f30d9
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_norflash.dox
@@ -0,0 +1,54 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup HAL_SERIAL_NOR Serial NOR Flash Driver
+ * @brief Serial NOR Flash driver.
+ * @details This module implements a generic driver for serial NOR Flash
+ * devices.
+ *
+ * @section snorflash_1 Driver State Machine
+ * The flash driver implements a state machine internally, not all the driver
+ * functionalities can be used in any moment, any transition not explicitly
+ * shown in the following diagram has to be considered an error and shall
+ * be captured by an assertion (if enabled).
+ * @dot
+ digraph example {
+ rankdir="LR";
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+ stop [label="FLS_STOP\nLow Power"];
+ uninit [label="FLS_UNINIT", style="bold"];
+ ready [label="FLS_READY\nClock Enabled"];
+ read [label="FLS_READ\nReading"];
+ pgm [label="FLS_PGM\nProgramming"];
+ erase [label="FLS_ERASE\nErasing"];
+ uninit -> stop [label=" snorInit()", constraint=false];
+ stop -> stop [label=" snorStop()"];
+ stop -> ready [label=" snorStart()"];
+ ready -> stop [label=" snorStop()"];
+ ready -> read [label=" flashRead()\nflashVerifyErase()"];
+ read -> ready [label=" return"];
+ ready -> pgm [label=" flashProgram()"];
+ pgm -> ready [label=" return"];
+ ready -> erase [label=" \n\nflashEraseAll()\nflashEraseSector()"];
+ erase -> ready [label=" flashQueryErase()\nFLASH_NO_ERROR\nFLASH_ERROR_*"];
+ erase -> erase [label=" flashQueryErase()\nflashProgram()\nflashRead()\nFLASH_BUSY_ERASING"];
+ }
+ * @enddot
+ *
+ * @ingroup HAL_COMPLEX_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_objects.dox b/ChibiOS_20.3.2/os/hal/dox/hal_objects.dox
new file mode 100644
index 0000000..140fb3c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_objects.dox
@@ -0,0 +1,20 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup HAL_BASE_OBJECT Base Object
+ * @ingroup HAL_INTERFACES_CLASSES
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_pal.dox b/ChibiOS_20.3.2/os/hal/dox/hal_pal.dox
new file mode 100644
index 0000000..d37fd09
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_pal.dox
@@ -0,0 +1,70 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup PAL PAL Driver
+ * @brief I/O Ports Abstraction Layer
+ * @details This module defines an abstract interface for digital I/O ports.
+ * Note that most I/O ports functions are just macros. The macros
+ * have default software implementations that can be redefined in a
+ * PAL Low Level Driver if the target hardware supports special
+ * features like, for example, atomic bit set/reset/masking. Please
+ * refer to the ports specific documentation for details.
+ * The @ref PAL driver has the advantage to make the access to the I/O
+ * ports platform independent and still be optimized for the specific
+ * architectures.
+ * Note that the PAL Low Level Driver may also offer non standard
+ * macro and functions in order to support specific features but,
+ * of course, the use of such interfaces would not be portable.
+ * Such interfaces shall be marked with the architecture name inside
+ * the function names.
+ * @pre In order to use the PAL driver the @p HAL_USE_PAL option
+ * must be enabled in @p halconf.h.
+ *
+ * @section pal_1 Implementation Rules
+ * In implementing a PAL Low Level Driver there are some rules/behaviors that
+ * should be respected.
+ *
+ * @subsection pal_1_1 Writing on input pads
+ * The behavior is not specified but there are implementations better than
+ * others, this is the list of possible implementations, preferred options
+ * are on top:
+ * -# The written value is not actually output but latched, should the pads
+ * be reprogrammed as outputs the value would be in effect.
+ * -# The write operation is ignored.
+ * -# The write operation has side effects, as example disabling/enabling
+ * pull up/down resistors or changing the pad direction. This scenario is
+ * discouraged, please try to avoid this scenario.
+ * .
+ * @subsection pal_1_2 Reading from output pads
+ * The behavior is not specified but there are implementations better than
+ * others, this is the list of possible implementations, preferred options
+ * are on top:
+ * -# The actual pads states are read (not the output latch).
+ * -# The output latch value is read (regardless of the actual pads states).
+ * -# Unspecified, please try to avoid this scenario.
+ * .
+ * @subsection pal_1_3 Writing unused or unimplemented port bits
+ * The behavior is not specified.
+ *
+ * @subsection pal_1_4 Reading from unused or unimplemented port bits
+ * The behavior is not specified.
+ *
+ * @subsection pal_1_5 Reading or writing on pins associated to other functionalities
+ * The behavior is not specified.
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_peripherals.dox b/ChibiOS_20.3.2/os/hal/dox/hal_peripherals.dox
new file mode 100644
index 0000000..2d8560f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_peripherals.dox
@@ -0,0 +1,22 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup HAL_ABSTRACT_PERIPHERALS Peripheral Interfaces
+ * @brief HAL Abstract Peripheral Interfaces.
+ *
+ * @ingroup IO
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_pwm.dox b/ChibiOS_20.3.2/os/hal/dox/hal_pwm.dox
new file mode 100644
index 0000000..39e0128
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_pwm.dox
@@ -0,0 +1,65 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup PWM PWM Driver
+ * @brief Generic PWM Driver.
+ * @details This module implements a generic PWM (Pulse Width Modulation)
+ * driver.
+ * @pre In order to use the PWM driver the @p HAL_USE_PWM option
+ * must be enabled in @p halconf.h.
+ *
+ * @section pwm_1 Driver State Machine
+ * The driver implements a state machine internally, not all the driver
+ * functionalities can be used in any moment, any transition not explicitly
+ * shown in the following diagram has to be considered an error and shall
+ * be captured by an assertion (if enabled).
+ * @dot
+ digraph example {
+ rankdir="LR";
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+ uninit [label="PWM_UNINIT", style="bold"];
+ stop [label="PWM_STOP\nLow Power"];
+ ready [label="PWM_READY\nClock Enabled"];
+ uninit -> stop [label="pwmInit()"];
+ stop -> stop [label="pwmStop()"];
+ stop -> ready [label="pwmStart()"];
+ ready -> stop [label="pwmStop()"];
+ ready -> ready [label="pwmEnableChannel()\npwmDisableChannel()"];
+ }
+ * @enddot
+ *
+ * @section pwm_2 PWM Operations.
+ * This driver abstracts a generic PWM timer composed of:
+ * - A clock prescaler.
+ * - A main up counter.
+ * - A comparator register that resets the main counter to zero when the limit
+ * is reached. An optional callback can be generated when this happens.
+ * - An array of @p PWM_CHANNELS PWM channels, each channel has an output,
+ * a comparator and is able to invoke an optional callback when a comparator
+ * match with the main counter happens.
+ * .
+ * A PWM channel output can be in two different states:
+ * - IDLE, when the channel is disabled or after a match occurred.
+ * - ACTIVE, when the channel is enabled and a match didn't occur yet
+ * in the current PWM cycle.
+ * .
+ * Note that the two states can be associated to both logical zero or one in
+ * the @p PWMChannelConfig structure.
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_queues.dox b/ChibiOS_20.3.2/os/hal/dox/hal_queues.dox
new file mode 100644
index 0000000..60ce974
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_queues.dox
@@ -0,0 +1,20 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup HAL_QUEUES I/O Bytes Queues
+ * @ingroup HAL_INNER_CODE
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_rtc.dox b/ChibiOS_20.3.2/os/hal/dox/hal_rtc.dox
new file mode 100644
index 0000000..0923e61
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_rtc.dox
@@ -0,0 +1,26 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup RTC RTC Driver
+ * @brief Generic RTC Driver.
+ * @details This module defines an abstract interface for a Real Time Clock
+ * Peripheral.
+ * @pre In order to use the RTC driver the @p HAL_USE_RTC option
+ * must be enabled in @p halconf.h.
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_sdc.dox b/ChibiOS_20.3.2/os/hal/dox/hal_sdc.dox
new file mode 100644
index 0000000..1a26006
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_sdc.dox
@@ -0,0 +1,33 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup SDC SDC Driver
+ * @brief Generic SD Card Driver.
+ * @details This module implements a generic SDC (Secure Digital Card) driver.
+ * @pre In order to use the SDC driver the @p HAL_USE_SDC option
+ * must be enabled in @p halconf.h.
+ *
+ * @section sdc_1 Driver State Machine
+ * This driver implements a state machine internally, see the @ref IO_BLOCK
+ * module documentation for details.
+ *
+ * @section sdc_2 Driver Operations
+ * This driver allows to read or write single or multiple 512 bytes blocks
+ * on a SD Card.
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_serial.dox b/ChibiOS_20.3.2/os/hal/dox/hal_serial.dox
new file mode 100644
index 0000000..9acb0bc
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_serial.dox
@@ -0,0 +1,57 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup SERIAL Serial Driver
+ * @brief Generic Serial Driver.
+ * @details This module implements a generic full duplex serial driver. The
+ * driver implements a @p SerialDriver interface and uses I/O Queues
+ * for communication between the upper and the lower driver. Event
+ * flags are used to notify the application about incoming data,
+ * outgoing data and other I/O events.
+ * The module also contains functions that make the implementation
+ * of the interrupt service routines much easier.
+ * @pre In order to use the SERIAL driver the @p HAL_USE_SERIAL option
+ * must be enabled in @p halconf.h.
+ *
+ *
+ * @section serial_1 Driver State Machine
+ * The driver implements a state machine internally, not all the driver
+ * functionalities can be used in any moment, any transition not explicitly
+ * shown in the following diagram has to be considered an error and shall
+ * be captured by an assertion (if enabled).
+ * @dot
+ digraph example {
+ rankdir="LR";
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true",
+ width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ uninit [label="SD_UNINIT", style="bold"];
+ stop [label="SD_STOP\nLow Power"];
+ ready [label="SD_READY\nClock Enabled"];
+
+ uninit -> stop [label=" sdInit()"];
+ stop -> stop [label="\nsdStop()"];
+ stop -> ready [label="\nsdStart()"];
+ ready -> stop [label="\nsdStop()"];
+ ready -> ready [label="\nsdStart()"];
+ ready -> ready [label="\nAny I/O operation"];
+ }
+ * @enddot
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_serial_usb.dox b/ChibiOS_20.3.2/os/hal/dox/hal_serial_usb.dox
new file mode 100644
index 0000000..028d8bb
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_serial_usb.dox
@@ -0,0 +1,52 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup SERIAL_USB Serial over USB Driver
+ * @brief Serial over USB Driver.
+ * @details This module implements an USB Communication Device Class
+ * (CDC) as a normal serial communication port accessible from
+ * the device application.
+ * @pre In order to use the USB over Serial driver the
+ * @p HAL_USE_SERIAL_USB option must be enabled in @p halconf.h.
+ *
+ * @section usb_serial_1 Driver State Machine
+ * The driver implements a state machine internally, not all the driver
+ * functionalities can be used in any moment, any transition not explicitly
+ * shown in the following diagram has to be considered an error and shall
+ * be captured by an assertion (if enabled).
+ * @dot
+ digraph example {
+ rankdir="LR";
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true",
+ width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ uninit [label="SDU_UNINIT", style="bold"];
+ stop [label="SDU_STOP\nLow Power"];
+ ready [label="SDU_READY\nClock Enabled"];
+
+ uninit -> stop [label=" sduInit()"];
+ stop -> stop [label="\nsduStop()"];
+ stop -> ready [label="\nsduStart()"];
+ ready -> stop [label="\nsduStop()"];
+ ready -> ready [label="\nsduStart()"];
+ ready -> ready [label="\nAny I/O operation"];
+ }
+ * @enddot
+ *
+ * @ingroup HAL_COMPLEX_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_sio.dox b/ChibiOS_20.3.2/os/hal/dox/hal_sio.dox
new file mode 100644
index 0000000..57ff2ba
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_sio.dox
@@ -0,0 +1,58 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup SIO SIO Driver
+ * @brief Generic SIO Driver.
+ * @details This driver abstracts a generic serial communication channel,
+ * usually an UART, this driver is similar to Serial and UART drivers
+ * but follows a different concept:
+ * - Very close to HW.
+ * - No buffering done in SW, the driver relies on the peripheral
+ * internal FIFO, if any.
+ * - Asynchronous, the API is always non blocking.
+ * - Callbacks capable, operations completion and other events are
+ * notified using callbacks.
+ * - Very short code paths, especially in ISRs.
+ * .
+ * @pre In order to use the SIO driver the @p HAL_USE_SIO option
+ * must be enabled in @p halconf.h.
+ *
+ * @section sio_1 Driver State Machine
+ * The driver implements a state machine internally, not all the driver
+ * functionalities can be used in any moment, any transition not explicitly
+ * shown in the following diagram has to be considered an error and shall
+ * be captured by an assertion (if enabled).
+ * @dot
+ digraph example {
+ rankdir="LR";
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ uninit [label="SIO_UNINIT", style="bold"];
+ stop [label="SIO_STOP\nLow Power"];
+ ready [label="SIO_READY\nClock Enabled"];
+
+ uninit -> stop [label="\nsioInit()"];
+ stop -> ready [label="\nsioStart()"];
+ ready -> ready [label="\nsioStart()"];
+ ready -> stop [label="\nsioStop()"];
+ stop -> stop [label="\nsioStop()"];
+ }
+ * @enddot
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_spi.dox b/ChibiOS_20.3.2/os/hal/dox/hal_spi.dox
new file mode 100644
index 0000000..4307bac
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_spi.dox
@@ -0,0 +1,90 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup SPI SPI Driver
+ * @brief Generic SPI Driver.
+ * @details This module implements a generic SPI (Serial Peripheral Interface)
+ * driver allowing bidirectional and monodirectional transfers,
+ * complex atomic transactions are supported as well.
+ * @pre In order to use the SPI driver the @p HAL_USE_SPI option
+ * must be enabled in @p halconf.h.
+ *
+ * @section spi_1 Driver State Machine
+ * The driver implements a state machine internally, not all the driver
+ * functionalities can be used in any moment, any transition not explicitly
+ * shown in the following diagram has to be considered an error and shall
+ * be captured by an assertion (if enabled).
+ * @if LATEX_PDF
+ * @dot
+ digraph example {
+ size="5, 7";
+ rankdir="LR";
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true",
+ width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ stop [label="SPI_STOP\nLow Power"];
+ uninit [label="SPI_UNINIT", style="bold"];
+ ready [label="SPI_READY\nClock Enabled"];
+ active [label="SPI_ACTIVE\nBus Active"];
+ complete [label="SPI_COMPLETE\nComplete"];
+
+ uninit -> stop [label="\n spiInit()", constraint=false];
+ stop -> ready [label="\nspiStart()"];
+ ready -> ready [label="\nspiSelect()\nspiUnselect()\nspiStart()"];
+ ready -> stop [label="\nspiStop()"];
+ stop -> stop [label="\nspiStop()"];
+ ready -> active [label="\nspiStartXXXI() (async)\nspiXXX() (sync)"];
+ active -> ready [label="\nsync return"];
+ active -> complete [label="\nasync callback\n>spc_endcb<"];
+ complete -> active [label="\nspiStartXXXI() (async)\nthen\ncallback return"];
+ complete -> ready [label="\ncallback return"];
+ }
+ * @enddot
+ * @else
+ * @dot
+ digraph example {
+ rankdir="LR";
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ stop [label="SPI_STOP\nLow Power"];
+ uninit [label="SPI_UNINIT", style="bold"];
+ ready [label="SPI_READY\nClock Enabled"];
+ active [label="SPI_ACTIVE\nBus Active"];
+ complete [label="SPI_COMPLETE\nComplete"];
+
+ uninit -> stop [label="\n spiInit()", constraint=false];
+ stop -> ready [label="\nspiStart()"];
+ ready -> ready [label="\nspiSelect()\nspiUnselect()\nspiStart()"];
+ ready -> stop [label="\nspiStop()"];
+ stop -> stop [label="\nspiStop()"];
+ ready -> active [label="\nspiStartXXX() (async)\nspiXXX() (sync)"];
+ active -> ready [label="\nsync return"];
+ active -> complete [label="\nasync callback\n>spc_endcb<"];
+ complete -> active [label="\nspiStartXXXI() (async)\nthen\ncallback return"];
+ complete -> ready [label="\ncallback return"];
+ }
+ * @enddot
+ * @endif
+ *
+ * The driver is not thread safe for performance reasons, if you need to access
+ * the SPI bus from multiple threads then use the @p spiAcquireBus() and
+ * @p spiReleaseBus() APIs in order to gain exclusive access.
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_st.dox b/ChibiOS_20.3.2/os/hal/dox/hal_st.dox
new file mode 100644
index 0000000..c6a8a64
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_st.dox
@@ -0,0 +1,24 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup ST ST Driver
+ * @brief Generic System Tick Driver.
+ * @details This module implements a system tick timer in order to support
+ * the underlying operating system.
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_trng.dox b/ChibiOS_20.3.2/os/hal/dox/hal_trng.dox
new file mode 100644
index 0000000..e28c606
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_trng.dox
@@ -0,0 +1,25 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup TRNG TRNG Driver
+ * @brief Generic True Random Numbers Generator Driver.
+ * @details This module implements a generic TRNG driver.
+ * @pre In order to use the TRNG driver the @p HAL_USE_TRNG option
+ * must be enabled in @p halconf.h.
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_uart.dox b/ChibiOS_20.3.2/os/hal/dox/hal_uart.dox
new file mode 100644
index 0000000..8af3127
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_uart.dox
@@ -0,0 +1,117 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup UART UART Driver
+ * @brief Generic UART Driver.
+ * @details This driver abstracts a generic UART (Universal Asynchronous
+ * Receiver Transmitter) peripheral, the API is designed to be:
+ * - Unbuffered and copy-less, transfers are always directly performed
+ * from/to the application-level buffers without extra copy
+ * operations.
+ * - Asynchronous, the API is always non blocking.
+ * - Callbacks capable, operations completion and other events are
+ * notified using callbacks.
+ * .
+ * Special hardware features like deep hardware buffers, DMA transfers
+ * are hidden to the user but fully supportable by the low level
+ * implementations.
+ * This driver model is best used where communication events are
+ * meant to drive an higher level state machine, as example:
+ * - RS485 drivers.
+ * - Multipoint network drivers.
+ * - Serial protocol decoders.
+ * .
+ * If your application requires a synchronous buffered driver then
+ * the @ref SERIAL should be used instead.
+ * @pre In order to use the UART driver the @p HAL_USE_UART option
+ * must be enabled in @p halconf.h.
+ *
+ * @section uart_1 Driver State Machine
+ * The driver implements a state machine internally, not all the driver
+ * functionalities can be used in any moment, any transition not explicitly
+ * shown in the following diagram has to be considered an error and shall
+ * be captured by an assertion (if enabled).
+ * @dot
+ digraph example {
+ rankdir="LR";
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ uninit [label="UART_UNINIT", style="bold"];
+ stop [label="UART_STOP\nLow Power"];
+ ready [label="UART_READY\nClock Enabled"];
+
+ uninit -> stop [label="\nuartInit()"];
+ stop -> ready [label="\nuartStart()"];
+ ready -> ready [label="\nuartStart()"];
+ ready -> stop [label="\nuartStop()"];
+ stop -> stop [label="\nuartStop()"];
+ }
+ * @enddot
+ *
+ * @subsection uart_1_1 Transmitter sub State Machine
+ * The follow diagram describes the transmitter state machine, this diagram
+ * is valid while the driver is in the @p UART_READY state. This state
+ * machine is automatically reset to the @p TX_IDLE state each time the
+ * driver enters the @p UART_READY state.
+ * @dot
+ digraph example {
+ rankdir="LR";
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ tx_idle [label="TX_IDLE", style="bold"];
+ tx_active [label="TX_ACTIVE"];
+ tx_complete [label="TX_COMPLETE"];
+
+ tx_idle -> tx_active [label="\nuartStartSend()"];
+ tx_idle -> tx_idle [label="\nuartStopSend()\n>txend2_cb<"];
+ tx_active -> tx_complete [label="\nbuffer transmitted\n>txend1_cb<"];
+ tx_active -> tx_idle [label="\nuartStopSend()"];
+ tx_complete -> tx_active [label="\nuartStartSendI()\nthen\ncallback return"];
+ tx_complete -> tx_idle [label="\ncallback return"];
+ }
+ * @enddot
+ *
+ * @subsection uart_1_2 Receiver sub State Machine
+ * The follow diagram describes the receiver state machine, this diagram
+ * is valid while the driver is in the @p UART_READY state. This state
+ * machine is automatically reset to the @p RX_IDLE state each time the
+ * driver enters the @p UART_READY state.
+ * @dot
+ digraph example {
+ rankdir="LR";
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ rx_idle [label="RX_IDLE", style="bold"];
+ rx_active [label="RX_ACTIVE"];
+ rx_complete [label="RX_COMPLETE"];
+
+ rx_idle -> rx_idle [label="\nuartStopReceive()\n>rxchar_cb<\n>rxerr_cb<"];
+ rx_idle -> rx_active [label="\nuartStartReceive()"];
+
+ rx_active -> rx_complete [label="\nbuffer filled\n>rxend_cb<"];
+ rx_active -> rx_idle [label="\nuartStopReceive()"];
+ rx_active -> rx_active [label="\nreceive error\n>rxerr_cb<"];
+ rx_complete -> rx_active [label="\nuartStartReceiveI()"];
+ rx_complete -> rx_idle [label="\ncallback return"];
+ }
+ * @enddot
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_usb.dox b/ChibiOS_20.3.2/os/hal/dox/hal_usb.dox
new file mode 100644
index 0000000..82de6cc
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_usb.dox
@@ -0,0 +1,180 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup USB USB Driver
+ * @brief Generic USB Driver.
+ * @details This module implements a generic USB (Universal Serial Bus) driver
+ * supporting device-mode operations.
+ * @pre In order to use the USB driver the @p HAL_USE_USB option
+ * must be enabled in @p halconf.h.
+ *
+ * @section usb_1 Driver State Machine
+ * The driver implements a state machine internally, not all the driver
+ * functionalities can be used in any moment, any transition not explicitly
+ * shown in the following diagram has to be considered an error and shall
+ * be captured by an assertion (if enabled).
+ * @if LATEX_PDF
+ * @dot
+ digraph example {
+ size="5, 7";
+ rankdir="LR";
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true",
+ width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ stop [label="USB_STOP\nLow Power"];
+ uninit [label="USB_UNINIT", style="bold"];
+ ready [label="USB_READY\nClock Enabled"];
+ selected [label="\nUSB_SELECTED\naddress\nassigned"];
+ active [label="\nUSB_ACTIVE\nconfiguration\nselected"];
+
+ uninit -> stop [label=" usbInit()", constraint=false];
+ stop -> stop [label="\nusbStop()"];
+ stop -> ready [label="\nusbStart()"];
+ ready -> stop [label="\nusbStop()"];
+ ready -> ready [label="\n\nusbStart()"];
+ ready -> ready [label="\nSUSPEND/WAKEUP\n>event_cb<"];
+ ready -> selected [label="\nSET_ADDRESS\n>event_cb<"];
+ selected -> stop [label="\nusbStop()"];
+ selected -> ready [label="\nUSB RESET\n>event_cb<"];
+ selected -> selected [label="\nSUSPEND/WAKEUP\n>event_cb<\n\nValid EP0 Message\n>requests_hook_cb<\n\nGET DESCRIPTOR\n>get_descriptor_cb<"];
+ selected -> active [label="\nSET_CONF(n)\n>event_cb<"];
+ active -> stop [label="\nusbStop()"];
+ active -> selected [label="\nSET_CONF(0)\n>event_cb<"];
+ active -> active [label="\nSUSPEND/WAKEUP\n>event_cb<\n\nValid EP0 Message\n>requests_hook_cb<\n\nGET DESCRIPTOR\n>get_descriptor_cb<\n\nEndpoints Activity\n >in_cb< or >out_cb<"];
+ active -> ready [label="\nUSB RESET\n>event_cb<"];
+ }
+ * @enddot
+ * @else
+ * @dot
+ digraph example {
+ rankdir="LR";
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true",
+ width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ stop [label="USB_STOP\nLow Power"];
+ uninit [label="USB_UNINIT", style="bold"];
+ ready [label="USB_READY\nClock Enabled"];
+ selected [label="\nUSB_SELECTED\naddress\nassigned"];
+ active [label="\nUSB_ACTIVE\nconfiguration\nselected"];
+
+ uninit -> stop [label=" usbInit()", constraint=false];
+ stop -> stop [label="\nusbStop()"];
+ stop -> ready [label="\nusbStart()"];
+ ready -> stop [label="\nusbStop()"];
+ ready -> ready [label="\n\nusbStart()"];
+ ready -> ready [label="\nSUSPEND/WAKEUP\n>event_cb<"];
+ ready -> selected [label="\nSET_ADDRESS\n>event_cb<"];
+ selected -> stop [label="\nusbStop()"];
+ selected -> ready [label="\nUSB RESET\n>event_cb<"];
+ selected -> selected [label="\nSUSPEND/WAKEUP\n>event_cb<\n\nValid EP0 Message\n>requests_hook_cb<\n\nGET DESCRIPTOR\n>get_descriptor_cb<"];
+ selected -> active [label="\nSET_CONF(n)\n>event_cb<"];
+ active -> stop [label="\nusbStop()"];
+ active -> selected [label="\nSET_CONF(0)\n>event_cb<"];
+ active -> active [label="\nSUSPEND/WAKEUP\n>event_cb<\n\nValid EP0 Message\n>requests_hook_cb<\n\nGET DESCRIPTOR\n>get_descriptor_cb<\n\nEndpoints Activity\n >in_cb< or >out_cb<"];
+ active -> ready [label="\nUSB RESET\n>event_cb<"];
+ }
+ * @enddot
+ * @endif
+ *
+ * @section usb_2 USB Operations
+ * The USB driver is quite complex and USB is complex in itself, it is
+ * recommended to study the USB specification before trying to use the
+ * driver.
+ *
+ * @subsection usb_2_1 USB Implementation
+ * The USB driver abstracts the inner details of the underlying USB hardware.
+ * The driver works asynchronously and communicates with the application
+ * using callbacks. The application is responsible of the descriptors and
+ * strings required by the USB device class to be implemented and of the
+ * handling of the specific messages sent over the endpoint zero. Standard
+ * messages are handled internally to the driver. The application can use
+ * hooks in order to handle custom messages or override the handling of the
+ * default handling of standard messages.
+ *
+ * @subsection usb_2_2 USB Endpoints
+ * USB endpoints are the objects that the application uses to exchange
+ * data with the host. There are two kind of endpoints:
+ * - IN endpoints are used by the application to transmit data to
+ * the host.
+ * - OUT endpoints are used by the application to receive data from
+ * the host.
+ * .
+ * The driver invokes a callback after finishing an IN or OUT transaction.
+ * States diagram for OUT endpoints in transaction mode:
+ * @dot
+ digraph example {
+ rankdir="LR";
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true",
+ width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ disabled [label="EP_DISABLED\nDisabled", style="bold"];
+ receiving [label="EP_BUSY\nReceiving"];
+ idle [label="EP_IDLE\nReady"];
+
+ disabled -> idle [label="\nusbInitEndpointI()"];
+ idle -> receiving [label="\nusbPrepareReceive()\nusbStartReceiveI()"];
+ receiving -> receiving [label="\nmore packets"];
+ receiving -> idle [label="\nreception end\n>out_cb<"];
+ receiving -> disabled [label="\nUSB RESET\nusbDisableEndpointsI()"];
+ idle -> disabled [label="\nUSB RESET\nusbDisableEndpointsI()"];
+ }
+ * @enddot
+ *
+ * States diagram for IN endpoints in transaction mode:
+ * @dot
+ digraph example {
+ rankdir="LR";
+ node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true",
+ width="0.9", height="0.9"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ disabled [label="EP_DISABLED\nDisabled", style="bold"];
+ transmitting [label="EP_BUSY\nTransmitting"];
+ idle [label="EP_IDLE\nReady"];
+
+ disabled -> idle [label="\usbInitEndpointI()"];
+ idle -> transmitting [label="\nusbPrepareTransmit()\nusbStartTransmitI()"];
+ transmitting -> transmitting [label="\nmore packets"];
+ transmitting -> idle [label="\ntransmission end\n>in_cb<"];
+ transmitting -> disabled [label="\nUSB RESET\nusbDisableEndpointsI()"];
+ idle -> disabled [label="\nUSB RESET\nusbDisableEndpointsI()"];
+ }
+ * @enddot
+ *
+ *
+ * @subsection usb_2_4 USB Callbacks
+ * The USB driver uses callbacks in order to interact with the application.
+ * There are several kinds of callbacks to be handled:
+ * - Driver events callback. As example errors, suspend event, reset event
+ * etc.
+ * - Messages Hook callback. This hook allows the application to implement
+ * handling of custom messages or to override the default handling of
+ * standard messages on endpoint zero.
+ * - Descriptor Requested callback. When the driver endpoint zero handler
+ * receives a GET DESCRIPTOR message and needs to send a descriptor to
+ * the host it queries the application using this callback.
+ * - Start of Frame callback. This callback is invoked each time a SOF
+ * packet is received.
+ * - Endpoint callbacks. Each endpoint informs the application about I/O
+ * conditions using those callbacks.
+ * .
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_usb_cdc.dox b/ChibiOS_20.3.2/os/hal/dox/hal_usb_cdc.dox
new file mode 100644
index 0000000..c480c95
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_usb_cdc.dox
@@ -0,0 +1,23 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup USB_CDC USB CDC Header
+ * @brief USB CDC Support Header
+ * @details This header contains definitions and types related to USB CDC.
+ *
+ * @ingroup HAL_SUPPORT
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_wdg.dox b/ChibiOS_20.3.2/os/hal/dox/hal_wdg.dox
new file mode 100644
index 0000000..7529320
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_wdg.dox
@@ -0,0 +1,26 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup WDG WDG Driver
+ * @brief Generic WDG Driver
+ * @details This module defines an abstract interface for a watchdog
+ * timer.
+ * @pre In order to use the WDG driver the @p HAL_USE_WDG option
+ * must be enabled in @p halconf.h.
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/hal_wspi.dox b/ChibiOS_20.3.2/os/hal/dox/hal_wspi.dox
new file mode 100755
index 0000000..5cf29d9
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/hal_wspi.dox
@@ -0,0 +1,26 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup WSPI WSPI Driver
+ * @brief Generic WSPI Driver
+ * @details This module defines an abstract interface for an wide SPI
+ * communication interface (Quad SPI, Octal SPI and similar).
+ * @pre In order to use the WSPI driver the @p HAL_USE_WSPI option
+ * must be enabled in @p halconf.h.
+ *
+ * @ingroup HAL_NORMAL_DRIVERS
+ */
diff --git a/ChibiOS_20.3.2/os/hal/dox/main.dox b/ChibiOS_20.3.2/os/hal/dox/main.dox
new file mode 100644
index 0000000..1c543a3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/dox/main.dox
@@ -0,0 +1,195 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup IO HAL
+ * @brief Hardware Abstraction Layer.
+ * @details Under ChibiOS the set of the various device driver interfaces
+ * is called the HAL subsystem: Hardware Abstraction Layer. The HAL is the
+ * abstract interface between ChibiOS applications and hardware.
+ *
+ * @section hal_device_driver_arch HAL Device Drivers Architecture
+ * The HAL contains several kind of modules:
+ * - Normal Device Drivers
+ * - Complex Device Drivers
+ * - Interfaces
+ * - Inner Code
+ * .
+ * @section hal_normal_device_drivers HAL Normal Device Drivers
+ * Normal device are meant to interface the application to the underlying
+ * hardware through an high level API. Normal Device Drivers are split in two
+ * layers:
+ * - High Level Device Driver (HLD). This layer contains the definitions
+ * of the driver's APIs and the platform independent part of the driver.
+ * An HLD is composed by two files:
+ * - @p hal_@.c, the HLD implementation file. This file must be
+ * included in the Makefile in order to use the driver.
+ * - @p hal_@.h, the HLD header file. This file is implicitly
+ * included by the HAL header file @p hal.h.
+ * .
+ * - Low Level Device Driver (LLD). This layer contains the platform
+ * dependent part of the driver.
+ * A LLD is composed by two files:
+ * - @p hal_@_lld.c, the LLD implementation file. This file must be
+ * included in the Makefile in order to use the driver.
+ * - @p hal_@_lld.h, the LLD header file. This file is implicitly
+ * included by the HLD header file.
+ * .
+ * .
+ * @subsection hal_device_driver_diagram Diagram
+ * @dot
+ digraph example {
+ graph [size="5, 7", pad="1.5, 0"];
+ node [shape=rectangle, fontname=Helvetica, fontsize=8,
+ fixedsize="true", width="2.0", height="0.4"];
+ edge [fontname=Helvetica, fontsize=8];
+
+ app [label="Application"];
+ hld [label="High Level Driver"];
+ lld [label="Low Level Driver"];
+ hw [label="Microcontroller Hardware"];
+ hal_lld [label="HAL shared low level code"];
+
+ app->hld;
+ hld->lld;
+ lld-> hw;
+ lld->hal_lld;
+ hal_lld->hw;
+ }
+ * @enddot
+ *
+ * @section hal_complex_device_drivers HAL Complex Device Drivers
+ * It is a class of device drivers that offer an high level API but do not
+ * use the hardware directly. Complex device drivers use other drivers for
+ * accessing the machine resources.
+ *
+ * @section hal_interfaces HAL Interfaces
+ * An interface is a binary structure allowing the access to a service
+ * using virtual functions. This allows to create drivers that can be
+ * accessed using a common interface.
+ * The concept of interface is commonly found in object-oriented languages
+ * like Java or C++, their meaning in ChibiOS/HAL is exactly the same.
+ *
+ * @section hal_inner_code HAL Inner Code
+ * Some modules are shared among multiple device drivers and are not
+ * necessarily meant to be used by the application layer.
+ */
+
+/**
+ * @defgroup HAL_CONF Configuration
+ * @brief HAL Configuration.
+ * @details The file @p halconf.h contains the high level settings for all
+ * the drivers supported by the HAL. The low level, platform dependent,
+ * settings are contained in the @p mcuconf.h file instead and are describe
+ * in the various platforms reference manuals.
+ *
+ * @ingroup IO
+ */
+
+/**
+ * @defgroup HAL_NORMAL_DRIVERS Normal Drivers
+ * @brief HAL Normal Drivers.
+ *
+ * @ingroup IO
+ */
+
+/**
+ * @defgroup HAL_COMPLEX_DRIVERS Complex Drivers
+ * @brief HAL Complex Drivers.
+ *
+ * @ingroup IO
+ */
+
+/**
+ * @defgroup HAL_INTERFACES_CLASSES Interfaces and Classes
+ * @brief HAL Interfaces and Classes.
+ *
+ * @ingroup IO
+ */
+
+/**
+ * @defgroup HAL_INNER_CODE Inner Code
+ * @brief HAL Inner Code.
+ *
+ * @ingroup IO
+ */
+
+/**
+ * @defgroup HAL_SUPPORT Support Code
+ * @brief HAL Support Code.
+ *
+ * @ingroup IO
+ */
+
+/**
+ * @defgroup OSAL OSAL
+ * @brief Operating System Abstraction Layer.
+ * @details The OSAL
+ * The OSAL is the link between ChibiOS/HAL and services
+ * provided by operating systems like:
+ * - Critical Zones handling.
+ * - Interrupts handling.
+ * - Runtime Errors management.
+ * - Inter-task synchronization.
+ * - Task-ISR synchronization.
+ * - Time management.
+ * - Events.
+ * .
+ * ChibiOS/HAL is designed to tightly integrate with the underlying
+ * RTOS in order to provide the best experience to developers and
+ * minimize integration issues.
+ * This section describes the API that OSALs are expected to expose
+ * to the HAL.
+ *
+ * RTOS Requirements
+ * The OSAL API closely resembles the ChibiOS/RT API, for obvious
+ * reasons, however an OSAL module can be implemented for any
+ * reasonably complete RTOS or even a RTOS-less bare metal
+ * machine, if required.
+ * In order to be able to support an HAL an RTOS should support the
+ * following minimal set of features:
+ * - Task-level critical zones API.
+ * - ISR-level critical zones API, only required on those CPU
+ * architectures supporting preemptable ISRs like Cortex-Mx
+ * cores.
+ * - Ability to invoke API functions from inside a task critical
+ * zone. Functions that are required to support this feature are
+ * marked with an "I" or "S" letter at the end of the name.
+ * - Ability to invoke API functions from inside an ISR critical
+ * zone. Functions that are required to support this feature are
+ * marked with an "I" letter at the end of the name.
+ * - Tasks Queues or Counting Semaphores with Timeout capability.
+ * - Ability to suspend a task and wakeup it from ISR with Timeout
+ * capability.
+ * - Event flags, the mechanism can be simulated using callbacks in
+ * case the RTOS does not support it.
+ * - Mutual Exclusion mechanism like Semaphores or Mutexes.
+ * .
+ * All the above requirements can be satisfied even on naked HW with
+ * a very think SW layer. In case that the HAL is required to work
+ * without an RTOS.
+ *
+ * Supported RTOSes
+ * The RTOSes supported out of the box are:
+ * - ChibiOS/RT
+ * - ChibiOS/NIL
+ * .
+ * Implementations have also been successfully created on RTOSes not
+ * belonging to the ChibiOS products family but are not supported
+ * as a core feature of ChibiOS/HAL.
+ *
+ * @ingroup IO
+ */
diff --git a/ChibiOS_20.3.2/os/hal/hal.mk b/ChibiOS_20.3.2/os/hal/hal.mk
new file mode 100644
index 0000000..dfba65c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/hal.mk
@@ -0,0 +1,132 @@
+# List of all the ChibiOS/HAL files, there is no need to remove the files
+# from this list, you can disable parts of the HAL by editing halconf.h.
+ifeq ($(USE_SMART_BUILD),yes)
+
+# Configuration files directory
+ifeq ($(HALCONFDIR),)
+ ifeq ($(CONFDIR),)
+ HALCONFDIR = .
+ else
+ HALCONFDIR := $(CONFDIR)
+ endif
+endif
+
+HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define"))
+
+HALSRC := $(CHIBIOS)/os/hal/src/hal.c \
+ $(CHIBIOS)/os/hal/src/hal_st.c \
+ $(CHIBIOS)/os/hal/src/hal_buffers.c \
+ $(CHIBIOS)/os/hal/src/hal_queues.c \
+ $(CHIBIOS)/os/hal/src/hal_flash.c \
+ $(CHIBIOS)/os/hal/src/hal_mmcsd.c
+ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_adc.c
+endif
+ifneq ($(findstring HAL_USE_CAN TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_can.c
+endif
+ifneq ($(findstring HAL_USE_CRY TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_crypto.c
+endif
+ifneq ($(findstring HAL_USE_DAC TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_dac.c
+endif
+ifneq ($(findstring HAL_USE_EFL TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_efl.c
+endif
+ifneq ($(findstring HAL_USE_GPT TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_gpt.c
+endif
+ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_i2c.c
+endif
+ifneq ($(findstring HAL_USE_I2S TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_i2s.c
+endif
+ifneq ($(findstring HAL_USE_ICU TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_icu.c
+endif
+ifneq ($(findstring HAL_USE_MAC TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_mac.c
+endif
+ifneq ($(findstring HAL_USE_MMC_SPI TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_mmc_spi.c
+endif
+ifneq ($(findstring HAL_USE_PAL TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_pal.c
+endif
+ifneq ($(findstring HAL_USE_PWM TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_pwm.c
+endif
+ifneq ($(findstring HAL_USE_RTC TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_rtc.c
+endif
+ifneq ($(findstring HAL_USE_SDC TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_sdc.c
+endif
+ifneq ($(findstring HAL_USE_SERIAL TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_serial.c
+endif
+ifneq ($(findstring HAL_USE_SERIAL_USB TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_serial_usb.c
+endif
+ifneq ($(findstring HAL_USE_SIO TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_sio.c
+endif
+ifneq ($(findstring HAL_USE_SPI TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_spi.c
+endif
+ifneq ($(findstring HAL_USE_TRNG TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_trng.c
+endif
+ifneq ($(findstring HAL_USE_UART TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_uart.c
+endif
+ifneq ($(findstring HAL_USE_USB TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_usb.c
+endif
+ifneq ($(findstring HAL_USE_WDG TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_wdg.c
+endif
+ifneq ($(findstring HAL_USE_WSPI TRUE,$(HALCONF)),)
+HALSRC += $(CHIBIOS)/os/hal/src/hal_wspi.c
+endif
+else
+HALSRC = $(CHIBIOS)/os/hal/src/hal.c \
+ $(CHIBIOS)/os/hal/src/hal_st.c \
+ $(CHIBIOS)/os/hal/src/hal_buffers.c \
+ $(CHIBIOS)/os/hal/src/hal_queues.c \
+ $(CHIBIOS)/os/hal/src/hal_flash.c \
+ $(CHIBIOS)/os/hal/src/hal_mmcsd.c \
+ $(CHIBIOS)/os/hal/src/hal_adc.c \
+ $(CHIBIOS)/os/hal/src/hal_can.c \
+ $(CHIBIOS)/os/hal/src/hal_crypto.c \
+ $(CHIBIOS)/os/hal/src/hal_dac.c \
+ $(CHIBIOS)/os/hal/src/hal_efl.c \
+ $(CHIBIOS)/os/hal/src/hal_gpt.c \
+ $(CHIBIOS)/os/hal/src/hal_i2c.c \
+ $(CHIBIOS)/os/hal/src/hal_i2s.c \
+ $(CHIBIOS)/os/hal/src/hal_icu.c \
+ $(CHIBIOS)/os/hal/src/hal_mac.c \
+ $(CHIBIOS)/os/hal/src/hal_mmc_spi.c \
+ $(CHIBIOS)/os/hal/src/hal_pal.c \
+ $(CHIBIOS)/os/hal/src/hal_pwm.c \
+ $(CHIBIOS)/os/hal/src/hal_rtc.c \
+ $(CHIBIOS)/os/hal/src/hal_sdc.c \
+ $(CHIBIOS)/os/hal/src/hal_serial.c \
+ $(CHIBIOS)/os/hal/src/hal_serial_usb.c \
+ $(CHIBIOS)/os/hal/src/hal_sio.c \
+ $(CHIBIOS)/os/hal/src/hal_spi.c \
+ $(CHIBIOS)/os/hal/src/hal_trng.c \
+ $(CHIBIOS)/os/hal/src/hal_uart.c \
+ $(CHIBIOS)/os/hal/src/hal_usb.c \
+ $(CHIBIOS)/os/hal/src/hal_wdg.c \
+ $(CHIBIOS)/os/hal/src/hal_wspi.c
+endif
+
+# Required include directories
+HALINC = $(CHIBIOS)/os/hal/include
+
+# Shared variables
+ALLCSRC += $(HALSRC)
+ALLINC += $(HALINC)
diff --git a/ChibiOS_20.3.2/os/hal/include/hal.h b/ChibiOS_20.3.2/os/hal/include/hal.h
new file mode 100644
index 0000000..44f7fe2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal.h
@@ -0,0 +1,267 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal.h
+ * @brief HAL subsystem header.
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#ifndef HAL_H
+#define HAL_H
+
+#include "osal.h"
+#include "board.h"
+#include "halconf.h"
+
+/* Error checks on the configuration header file.*/
+#if !defined(HAL_USE_PAL)
+#define HAL_USE_PAL FALSE
+#endif
+
+#if !defined(HAL_USE_ADC)
+#define HAL_USE_ADC FALSE
+#endif
+
+#if !defined(HAL_USE_CAN)
+#define HAL_USE_CAN FALSE
+#endif
+
+#if !defined(HAL_USE_CRY)
+#define HAL_USE_CRY FALSE
+#endif
+
+#if !defined(HAL_USE_DAC)
+#define HAL_USE_DAC FALSE
+#endif
+
+#if !defined(HAL_USE_EFL)
+#define HAL_USE_EFL FALSE
+#endif
+
+#if !defined(HAL_USE_GPT)
+#define HAL_USE_GPT FALSE
+#endif
+
+#if !defined(HAL_USE_I2C)
+#define HAL_USE_I2C FALSE
+#endif
+
+#if !defined(HAL_USE_I2S)
+#define HAL_USE_I2S FALSE
+#endif
+
+#if !defined(HAL_USE_ICU)
+#define HAL_USE_ICU FALSE
+#endif
+
+#if !defined(HAL_USE_MAC)
+#define HAL_USE_MAC FALSE
+#endif
+
+#if !defined(HAL_USE_PWM)
+#define HAL_USE_PWM FALSE
+#endif
+
+#if !defined(HAL_USE_RTC)
+#define HAL_USE_RTC FALSE
+#endif
+
+#if !defined(HAL_USE_SERIAL)
+#define HAL_USE_SERIAL FALSE
+#endif
+
+#if !defined(HAL_USE_SDC)
+#define HAL_USE_SDC FALSE
+#endif
+
+#if !defined(HAL_USE_SIO)
+#define HAL_USE_SIO FALSE
+#endif
+
+#if !defined(HAL_USE_SPI)
+#define HAL_USE_SPI FALSE
+#endif
+
+#if !defined(HAL_USE_TRNG)
+#define HAL_USE_TRNG FALSE
+#endif
+
+#if !defined(HAL_USE_UART)
+#define HAL_USE_UART FALSE
+#endif
+
+#if !defined(HAL_USE_USB)
+#define HAL_USE_USB FALSE
+#endif
+
+#if !defined(HAL_USE_WDG)
+#define HAL_USE_WDG FALSE
+#endif
+
+#if !defined(HAL_USE_WSPI)
+#define HAL_USE_WSPI FALSE
+#endif
+
+/* Low Level HAL support.*/
+#include "hal_lld.h"
+
+/* Abstract interfaces.*/
+#include "hal_objects.h"
+#include "hal_streams.h"
+#include "hal_channels.h"
+#include "hal_files.h"
+#include "hal_ioblock.h"
+#include "hal_mmcsd.h"
+#include "hal_persistent.h"
+#include "hal_flash.h"
+
+/* Shared headers.*/
+#include "hal_buffers.h"
+#include "hal_queues.h"
+
+/* Normal drivers.*/
+#include "hal_pal.h"
+#include "hal_adc.h"
+#include "hal_can.h"
+#include "hal_crypto.h"
+#include "hal_dac.h"
+#include "hal_efl.h"
+#include "hal_gpt.h"
+#include "hal_i2c.h"
+#include "hal_i2s.h"
+#include "hal_icu.h"
+#include "hal_mac.h"
+#include "hal_pwm.h"
+#include "hal_rtc.h"
+#include "hal_serial.h"
+#include "hal_sdc.h"
+#include "hal_sio.h"
+#include "hal_spi.h"
+#include "hal_trng.h"
+#include "hal_uart.h"
+#include "hal_usb.h"
+#include "hal_wdg.h"
+#include "hal_wspi.h"
+
+/*
+ * The ST driver is a special case, it is only included if the OSAL is
+ * configured to require it.
+ */
+#if OSAL_ST_MODE != OSAL_ST_MODE_NONE
+#include "hal_st.h"
+#endif
+
+/* Complex drivers.*/
+#include "hal_mmc_spi.h"
+#include "hal_serial_usb.h"
+
+/* Community drivers.*/
+#if defined(HAL_USE_COMMUNITY) || defined(__DOXYGEN__)
+#if (HAL_USE_COMMUNITY == TRUE) || defined(__DOXYGEN__)
+#include "hal_community.h"
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief ChibiOS/HAL identification macro.
+ */
+#define _CHIBIOS_HAL_
+
+/**
+ * @brief Stable release flag.
+ */
+#define CH_HAL_STABLE 1
+
+/**
+ * @name ChibiOS/HAL version identification
+ * @{
+ */
+/**
+ * @brief HAL version string.
+ */
+#define HAL_VERSION "7.1.3"
+
+/**
+ * @brief HAL version major number.
+ */
+#define CH_HAL_MAJOR 7
+
+/**
+ * @brief HAL version minor number.
+ */
+#define CH_HAL_MINOR 1
+
+/**
+ * @brief HAL version patch number.
+ */
+#define CH_HAL_PATCH 3
+/** @} */
+
+/**
+ * @name Return codes
+ * @{
+ */
+#define HAL_SUCCESS false
+#define HAL_FAILED true
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Configuration file checks.*/
+#if !defined(_CHIBIOS_HAL_CONF_)
+#error "invalid configuration file"
+#endif
+
+#if !defined(_CHIBIOS_HAL_CONF_VER_7_1_)
+#error "obsolete or unknown configuration file"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void halInit(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_adc.h b/ChibiOS_20.3.2/os/hal/include/hal_adc.h
new file mode 100644
index 0000000..8bc3066
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_adc.h
@@ -0,0 +1,416 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_adc.h
+ * @brief ADC Driver macros and structures.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#ifndef HAL_ADC_H
+#define HAL_ADC_H
+
+#if (HAL_USE_ADC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name ADC configuration options
+ * @{
+ */
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
+#define ADC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define ADC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ ADC_UNINIT = 0, /**< Not initialized. */
+ ADC_STOP = 1, /**< Stopped. */
+ ADC_READY = 2, /**< Ready. */
+ ADC_ACTIVE = 3, /**< Converting. */
+ ADC_COMPLETE = 4, /**< Conversion complete. */
+ ADC_ERROR = 5 /**< Conversion error. */
+} adcstate_t;
+
+/**
+ * @brief Type of a structure representing an ADC driver.
+ */
+typedef struct hal_adc_driver ADCDriver;
+
+/**
+ * @brief Type of a structure representing an ADC driver configuration.
+ */
+typedef struct hal_adc_config ADCConfig;
+
+/**
+ * @brief Conversion group configuration structure.
+ * @details This implementation-dependent structure describes a conversion
+ * operation.
+ * @note The use of this configuration structure requires knowledge of
+ * STM32 ADC cell registers interface, please refer to the STM32
+ * reference manual for details.
+ */
+typedef struct hal_adc_configuration_group ADCConversionGroup;
+
+/* Including the low level driver header, it exports information required
+ for completing types.*/
+#include "hal_adc_lld.h"
+
+/**
+ * @brief Type of an ADC notification callback.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object triggering the
+ * callback
+ */
+typedef void (*adccallback_t)(ADCDriver *adcp);
+
+/**
+ * @brief Type of an ADC error callback.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object triggering the
+ * callback
+ * @param[in] err ADC error code
+ */
+typedef void (*adcerrorcallback_t)(ADCDriver *adcp, adcerror_t err);
+
+/**
+ * @brief Conversion group configuration structure.
+ * @details This implementation-dependent structure describes a conversion
+ * operation.
+ * @note The use of this configuration structure requires knowledge of
+ * STM32 ADC cell registers interface, please refer to the STM32
+ * reference manual for details.
+ */
+struct hal_adc_configuration_group {
+ /**
+ * @brief Enables the circular buffer mode for the group.
+ */
+ bool circular;
+ /**
+ * @brief Number of the analog channels belonging to the conversion group.
+ */
+ adc_channels_num_t num_channels;
+ /**
+ * @brief Callback function associated to the group or @p NULL.
+ */
+ adccallback_t end_cb;
+ /**
+ * @brief Error callback or @p NULL.
+ */
+ adcerrorcallback_t error_cb;
+ /* End of the mandatory fields.*/
+ adc_lld_configuration_group_fields;
+};
+
+/**
+ * @brief Driver configuration structure.
+ */
+struct hal_adc_config {
+ /* End of the mandatory fields.*/
+ adc_lld_config_fields;
+};
+
+/**
+ * @brief Structure representing an ADC driver.
+ */
+struct hal_adc_driver {
+ /**
+ * @brief Driver state.
+ */
+ adcstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const ADCConfig *config;
+ /**
+ * @brief Current samples buffer pointer or @p NULL.
+ */
+ adcsample_t *samples;
+ /**
+ * @brief Current samples buffer depth or @p 0.
+ */
+ size_t depth;
+ /**
+ * @brief Current conversion group pointer or @p NULL.
+ */
+ const ADCConversionGroup *grpp;
+#if (ADC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Waiting thread.
+ */
+ thread_reference_t thread;
+#endif /* ADC_USE_WAIT == TRUE */
+#if (ADC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Mutex protecting the peripheral.
+ */
+ mutex_t mutex;
+#endif /* ADC_USE_MUTUAL_EXCLUSION == TRUE */
+#if defined(ADC_DRIVER_EXT_FIELDS)
+ ADC_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ adc_lld_driver_fields;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Buffer state.
+ * @note This function is meant to be called from the ADC callback only.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ * @return The buffer state.
+ * @retval false if the driver filled/sent the first half of the
+ * buffer.
+ * @retval true if the driver filled/sent the second half of the
+ * buffer.
+ *
+ * @special
+ */
+#define adcIsBufferComplete(adcp) ((bool)((adcp)->state == ADC_COMPLETE))
+/** @} */
+
+/**
+ * @name Low level driver helper macros
+ * @{
+ */
+#if (ADC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Resumes a thread waiting for a conversion completion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+#define _adc_reset_i(adcp) \
+ osalThreadResumeI(&(adcp)->thread, MSG_RESET)
+
+/**
+ * @brief Resumes a thread waiting for a conversion completion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+#define _adc_reset_s(adcp) \
+ osalThreadResumeS(&(adcp)->thread, MSG_RESET)
+
+/**
+ * @brief Wakes up the waiting thread.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+#define _adc_wakeup_isr(adcp) { \
+ osalSysLockFromISR(); \
+ osalThreadResumeI(&(adcp)->thread, MSG_OK); \
+ osalSysUnlockFromISR(); \
+}
+
+/**
+ * @brief Wakes up the waiting thread with a timeout message.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+#define _adc_timeout_isr(adcp) { \
+ osalSysLockFromISR(); \
+ osalThreadResumeI(&(adcp)->thread, MSG_TIMEOUT); \
+ osalSysUnlockFromISR(); \
+}
+
+#else /* !ADC_USE_WAIT */
+#define _adc_reset_i(adcp)
+#define _adc_reset_s(adcp)
+#define _adc_wakeup_isr(adcp)
+#define _adc_timeout_isr(adcp)
+#endif /* !ADC_USE_WAIT */
+
+/**
+ * @brief Common ISR code, half buffer event.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+#define _adc_isr_half_code(adcp) { \
+ if ((adcp)->grpp->end_cb != NULL) { \
+ (adcp)->grpp->end_cb(adcp); \
+ } \
+}
+
+/**
+ * @brief Common ISR code, full buffer event.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Waiting thread wakeup, if any.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+#define _adc_isr_full_code(adcp) { \
+ if ((adcp)->grpp->circular) { \
+ /* Callback handling.*/ \
+ if ((adcp)->grpp->end_cb != NULL) { \
+ (adcp)->state = ADC_COMPLETE; \
+ (adcp)->grpp->end_cb(adcp); \
+ if ((adcp)->state == ADC_COMPLETE) { \
+ (adcp)->state = ADC_ACTIVE; \
+ } \
+ } \
+ } \
+ else { \
+ /* End conversion.*/ \
+ adc_lld_stop_conversion(adcp); \
+ if ((adcp)->grpp->end_cb != NULL) { \
+ (adcp)->state = ADC_COMPLETE; \
+ (adcp)->grpp->end_cb(adcp); \
+ if ((adcp)->state == ADC_COMPLETE) { \
+ (adcp)->state = ADC_READY; \
+ (adcp)->grpp = NULL; \
+ } \
+ } \
+ else { \
+ (adcp)->state = ADC_READY; \
+ (adcp)->grpp = NULL; \
+ } \
+ _adc_wakeup_isr(adcp); \
+ } \
+}
+
+/**
+ * @brief Common ISR code, error event.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Waiting thread timeout signaling, if any.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ * @param[in] err platform dependent error code
+ *
+ * @notapi
+ */
+#define _adc_isr_error_code(adcp, err) { \
+ adc_lld_stop_conversion(adcp); \
+ if ((adcp)->grpp->error_cb != NULL) { \
+ (adcp)->state = ADC_ERROR; \
+ (adcp)->grpp->error_cb(adcp, err); \
+ if ((adcp)->state == ADC_ERROR) { \
+ (adcp)->state = ADC_READY; \
+ (adcp)->grpp = NULL; \
+ } \
+ } \
+ else { \
+ (adcp)->state = ADC_READY; \
+ (adcp)->grpp = NULL; \
+ } \
+ _adc_timeout_isr(adcp); \
+}
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void adcInit(void);
+ void adcObjectInit(ADCDriver *adcp);
+ void adcStart(ADCDriver *adcp, const ADCConfig *config);
+ void adcStop(ADCDriver *adcp);
+ void adcStartConversion(ADCDriver *adcp,
+ const ADCConversionGroup *grpp,
+ adcsample_t *samples,
+ size_t depth);
+ void adcStartConversionI(ADCDriver *adcp,
+ const ADCConversionGroup *grpp,
+ adcsample_t *samples,
+ size_t depth);
+ void adcStopConversion(ADCDriver *adcp);
+ void adcStopConversionI(ADCDriver *adcp);
+#if ADC_USE_WAIT == TRUE
+ msg_t adcConvert(ADCDriver *adcp,
+ const ADCConversionGroup *grpp,
+ adcsample_t *samples,
+ size_t depth);
+#endif
+#if ADC_USE_MUTUAL_EXCLUSION == TRUE
+ void adcAcquireBus(ADCDriver *adcp);
+ void adcReleaseBus(ADCDriver *adcp);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_ADC == TRUE */
+
+#endif /* HAL_ADC_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_buffers.h b/ChibiOS_20.3.2/os/hal/include/hal_buffers.h
new file mode 100644
index 0000000..200c1b2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_buffers.h
@@ -0,0 +1,345 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_buffers.h
+ * @brief I/O Buffers macros and structures.
+ *
+ * @addtogroup HAL_BUFFERS
+ * @{
+ */
+
+#ifndef HAL_BUFFERS_H
+#define HAL_BUFFERS_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Maximum size of blocks copied in critical sections.
+ * @note Increasing this value increases performance at expense of
+ * IRQ servicing efficiency.
+ * @note It must be a power of two.
+ */
+#if !defined(BUFFERS_CHUNKS_SIZE) || defined(__DOXYGEN__)
+#define BUFFERS_CHUNKS_SIZE 64
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*lint -save -e9027 [10.1] It is meant to be this way, not an error.*/
+#if (BUFFERS_CHUNKS_SIZE & (BUFFERS_CHUNKS_SIZE - 1)) != 0
+/*lint -restore*/
+#error "BUFFERS_CHUNKS_SIZE must be a power of two"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a generic queue of buffers.
+ */
+typedef struct io_buffers_queue io_buffers_queue_t;
+
+/**
+ * @brief Double buffer notification callback type.
+ *
+ * @param[in] iodbp the buffers queue pointer
+ */
+typedef void (*bqnotify_t)(io_buffers_queue_t *bqp);
+
+/**
+ * @brief Structure of a generic buffers queue.
+ */
+struct io_buffers_queue {
+ /**
+ * @brief Queue of waiting threads.
+ */
+ threads_queue_t waiting;
+ /**
+ * @brief Queue suspended state flag.
+ */
+ bool suspended;
+ /**
+ * @brief Active buffers counter.
+ */
+ volatile size_t bcounter;
+ /**
+ * @brief Buffer write pointer.
+ */
+ uint8_t *bwrptr;
+ /**
+ * @brief Buffer read pointer.
+ */
+ uint8_t *brdptr;
+ /**
+ * @brief Pointer to the buffers boundary.
+ */
+ uint8_t *btop;
+ /**
+ * @brief Size of buffers.
+ * @note The buffer size must be not lower than sizeof(size_t) + 2
+ * because the first bytes are used to store the used size of the
+ * buffer.
+ */
+ size_t bsize;
+ /**
+ * @brief Number of buffers.
+ */
+ size_t bn;
+ /**
+ * @brief Queue of buffer objects.
+ */
+ uint8_t *buffers;
+ /**
+ * @brief Pointer for R/W sequential access.
+ * @note It is @p NULL if a new buffer must be fetched from the queue.
+ */
+ uint8_t *ptr;
+ /**
+ * @brief Boundary for R/W sequential access.
+ */
+ uint8_t *top;
+ /**
+ * @brief Data notification callback.
+ */
+ bqnotify_t notify;
+ /**
+ * @brief Application defined field.
+ */
+ void *link;
+};
+
+/**
+ * @brief Type of an input buffers queue.
+ */
+typedef io_buffers_queue_t input_buffers_queue_t;
+
+/**
+ * @brief Type of an output buffers queue.
+ */
+typedef io_buffers_queue_t output_buffers_queue_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Computes the size of a buffers queue buffer size.
+ *
+ * @param[in] n number of buffers in the queue
+ * @param[in] size size of the buffers
+ */
+#define BQ_BUFFER_SIZE(n, size) \
+ (((size_t)(size) + sizeof (size_t)) * (size_t)(n))
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Returns the queue's number of buffers.
+ *
+ * @param[in] bqp pointer to an @p io_buffers_queue_t structure
+ * @return The number of buffers.
+ *
+ * @xclass
+ */
+#define bqSizeX(bqp) ((bqp)->bn)
+
+/**
+ * @brief Return the ready buffers number.
+ * @details Returns the number of filled buffers if used on an input queue
+ * or the number of empty buffers if used on an output queue.
+ *
+ * @param[in] bqp pointer to an @p io_buffers_queue_t structure
+ * @return The number of ready buffers.
+ *
+ * @iclass
+ */
+#define bqSpaceI(bqp) ((bqp)->bcounter)
+
+/**
+ * @brief Returns the queue application-defined link.
+ *
+ * @param[in] bqp pointer to an @p io_buffers_queue_t structure
+ * @return The application-defined link.
+ *
+ * @special
+ */
+#define bqGetLinkX(bqp) ((bqp)->link)
+
+/**
+ * @brief Sets the queue application-defined link.
+ *
+ * @param[in] bqp pointer to an @p io_buffers_queue_t structure
+ * @param[in] lk The application-defined link.
+ *
+ * @special
+ */
+#define bqSetLinkX(bqp, lk) ((bqp)->link = lk)
+
+/**
+ * @brief Return the suspended state of the queue.
+ *
+ * @param[in] bqp pointer to an @p io_buffers_queue_t structure
+ * @return The suspended state.
+ * @retval false if blocking access to the queue is enabled.
+ * @retval true if blocking access to the queue is suspended.
+ *
+ * @xclass
+ */
+#define bqIsSuspendedX(bqp) ((bqp)->suspended)
+
+/**
+ * @brief Puts the queue in suspended state.
+ * @details When the queue is put in suspended state all waiting threads are
+ * woken with message @p MSG_RESET and subsequent attempt at waiting
+ * on the queue will result in an immediate return with @p MSG_RESET
+ * message.
+ * @note The content of the queue is not altered, queues can be accessed
+ * is suspended state until a blocking operation is met then a
+ * @p MSG_RESET occurs.
+ *
+ * @param[in] bqp pointer to an @p io_buffers_queue_t structure
+ *
+ * @iclass
+ */
+#define bqSuspendI(bqp) { \
+ (bqp)->suspended = true; \
+ osalThreadDequeueAllI(&(bqp)->waiting, MSG_RESET); \
+}
+
+/**
+ * @brief Resumes normal queue operations.
+ *
+ * @param[in] bqp pointer to an @p io_buffers_queue_t structure
+ *
+ * @xclass
+ */
+#define bqResumeX(bqp) { \
+ (bqp)->suspended = false; \
+}
+
+/**
+ * @brief Evaluates to @p true if the specified input buffers queue is empty.
+ *
+ * @param[in] ibqp pointer to an @p input_buffers_queue_t structure
+ * @return The queue status.
+ * @retval false if the queue is not empty.
+ * @retval true if the queue is empty.
+ *
+ * @iclass
+ */
+#define ibqIsEmptyI(ibqp) ((bool)(bqSpaceI(ibqp) == 0U))
+
+/**
+ * @brief Evaluates to @p true if the specified input buffers queue is full.
+ *
+ * @param[in] ibqp pointer to an @p input_buffers_queue_t structure
+ * @return The queue status.
+ * @retval false if the queue is not full.
+ * @retval true if the queue is full.
+ *
+ * @iclass
+ */
+#define ibqIsFullI(ibqp) \
+ /*lint -save -e9007 [13.5] No side effects, a pointer is passed.*/ \
+ ((bool)(((ibqp)->bwrptr == (ibqp)->brdptr) && ((ibqp)->bcounter != 0U))) \
+ /*lint -restore*/
+
+/**
+ * @brief Evaluates to @p true if the specified output buffers queue is empty.
+ *
+ * @param[in] obqp pointer to an @p output_buffers_queue_t structure
+ * @return The queue status.
+ * @retval false if the queue is not empty.
+ * @retval true if the queue is empty.
+ *
+ * @iclass
+ */
+#define obqIsEmptyI(obqp) \
+ /*lint -save -e9007 [13.5] No side effects, a pointer is passed.*/ \
+ ((bool)(((obqp)->bwrptr == (obqp)->brdptr) && ((obqp)->bcounter != 0U))) \
+ /*lint -restore*/
+
+/**
+ * @brief Evaluates to @p true if the specified output buffers queue is full.
+ *
+ * @param[in] obqp pointer to an @p output_buffers_queue_t structure
+ * @return The queue status.
+ * @retval false if the queue is not full.
+ * @retval true if the queue is full.
+ *
+ * @iclass
+ */
+#define obqIsFullI(obqp) ((bool)(bqSpaceI(obqp) == 0U))
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void ibqObjectInit(input_buffers_queue_t *ibqp, bool suspended, uint8_t *bp,
+ size_t size, size_t n, bqnotify_t infy, void *link);
+ void ibqResetI(input_buffers_queue_t *ibqp);
+ uint8_t *ibqGetEmptyBufferI(input_buffers_queue_t *ibqp);
+ void ibqPostFullBufferI(input_buffers_queue_t *ibqp, size_t size);
+ msg_t ibqGetFullBufferTimeout(input_buffers_queue_t *ibqp,
+ sysinterval_t timeout);
+ msg_t ibqGetFullBufferTimeoutS(input_buffers_queue_t *ibqp,
+ sysinterval_t timeout);
+ void ibqReleaseEmptyBuffer(input_buffers_queue_t *ibqp);
+ void ibqReleaseEmptyBufferS(input_buffers_queue_t *ibqp);
+ msg_t ibqGetTimeout(input_buffers_queue_t *ibqp, sysinterval_t timeout);
+ size_t ibqReadTimeout(input_buffers_queue_t *ibqp, uint8_t *bp,
+ size_t n, sysinterval_t timeout);
+ void obqObjectInit(output_buffers_queue_t *obqp, bool suspended, uint8_t *bp,
+ size_t size, size_t n, bqnotify_t onfy, void *link);
+ void obqResetI(output_buffers_queue_t *obqp);
+ uint8_t *obqGetFullBufferI(output_buffers_queue_t *obqp,
+ size_t *sizep);
+ void obqReleaseEmptyBufferI(output_buffers_queue_t *obqp);
+ msg_t obqGetEmptyBufferTimeout(output_buffers_queue_t *obqp,
+ sysinterval_t timeout);
+ msg_t obqGetEmptyBufferTimeoutS(output_buffers_queue_t *obqp,
+ sysinterval_t timeout);
+ void obqPostFullBuffer(output_buffers_queue_t *obqp, size_t size);
+ void obqPostFullBufferS(output_buffers_queue_t *obqp, size_t size);
+ msg_t obqPutTimeout(output_buffers_queue_t *obqp, uint8_t b,
+ sysinterval_t timeout);
+ size_t obqWriteTimeout(output_buffers_queue_t *obqp, const uint8_t *bp,
+ size_t n, sysinterval_t timeout);
+ bool obqTryFlushI(output_buffers_queue_t *obqp);
+ void obqFlush(output_buffers_queue_t *obqp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_BUFFERS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_can.h b/ChibiOS_20.3.2/os/hal/include/hal_can.h
new file mode 100644
index 0000000..baf5b56
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_can.h
@@ -0,0 +1,257 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_can.h
+ * @brief CAN Driver macros and structures.
+ *
+ * @addtogroup CAN
+ * @{
+ */
+
+#ifndef HAL_CAN_H
+#define HAL_CAN_H
+
+#if (HAL_USE_CAN == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name CAN status flags
+ * @{
+ */
+/**
+ * @brief Errors rate warning.
+ */
+#define CAN_LIMIT_WARNING 1U
+/**
+ * @brief Errors rate error.
+ */
+#define CAN_LIMIT_ERROR 2U
+/**
+ * @brief Bus off condition reached.
+ */
+#define CAN_BUS_OFF_ERROR 4U
+/**
+ * @brief Framing error of some kind on the CAN bus.
+ */
+#define CAN_FRAMING_ERROR 8U
+/**
+ * @brief Overflow in receive queue.
+ */
+#define CAN_OVERFLOW_ERROR 16U
+/** @} */
+
+/**
+ * @brief Special mailbox identifier.
+ */
+#define CAN_ANY_MAILBOX 0U
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name CAN configuration options
+ * @{
+ */
+/**
+ * @brief Sleep mode related APIs inclusion switch.
+ * @details This option can only be enabled if the CAN implementation supports
+ * the sleep mode, see the macro @p CAN_SUPPORTS_SLEEP exported by
+ * the underlying implementation.
+ */
+#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
+#define CAN_USE_SLEEP_MODE TRUE
+#endif
+
+/**
+ * @brief Enforces the driver to use direct callbacks rather than OSAL events.
+ */
+#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__)
+#define CAN_ENFORCE_USE_CALLBACKS FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ CAN_UNINIT = 0, /**< Not initialized. */
+ CAN_STOP = 1, /**< Stopped. */
+ CAN_STARTING = 2, /**< Starting. */
+ CAN_STOPPING = 3, /**< Stopping. */
+ CAN_READY = 4, /**< Ready. */
+ CAN_SLEEP = 5 /**< Sleep state. */
+} canstate_t;
+
+#include "hal_can_lld.h"
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Converts a mailbox index to a bit mask.
+ */
+#define CAN_MAILBOX_TO_MASK(mbx) (1U << ((mbx) - 1U))
+
+/**
+ * @brief Legacy name for @p canTransmitTimeout().
+ *
+ * @deprecated
+ */
+#define canTransmit(canp, mailbox, ctfp, timeout) \
+ canTransmitTimeout(canp, mailbox, ctfp, timeout)
+
+/**
+ * @brief Legacy name for @p canReceiveTimeout().
+ *
+ * @deprecated
+ */
+#define canReceive(canp, mailbox, crfp, timeout) \
+ canReceiveTimeout(canp, mailbox, crfp, timeout)
+/** @} */
+
+/**
+ * @name Low level driver helper macros
+ * @{
+ */
+#if (CAN_ENFORCE_USE_CALLBACKS == FALSE) || defined(__DOXYGEN__)
+/**
+ * @brief TX mailbox empty event.
+ */
+#define _can_tx_empty_isr(canp, flags) { \
+ osalSysLockFromISR(); \
+ osalThreadDequeueAllI(&(canp)->txqueue, MSG_OK); \
+ osalEventBroadcastFlagsI(&(canp)->txempty_event, flags); \
+ osalSysUnlockFromISR(); \
+}
+
+/**
+ * @brief RX mailbox empty full event.
+ */
+#define _can_rx_full_isr(canp, flags) { \
+ osalSysLockFromISR(); \
+ osalThreadDequeueAllI(&(canp)->rxqueue, MSG_OK); \
+ osalEventBroadcastFlagsI(&(canp)->rxfull_event, flags); \
+ osalSysUnlockFromISR(); \
+}
+
+/**
+ * @brief Wakeup event.
+ */
+#define _can_wakeup_isr(canp) { \
+ osalSysLockFromISR(); \
+ osalEventBroadcastFlagsI(&(canp)->wakeup_event, 0U); \
+ osalSysUnlockFromISR(); \
+}
+
+/**
+ * @brief Error event.
+ */
+#define _can_error_isr(canp, flags) { \
+ osalSysLockFromISR(); \
+ osalEventBroadcastFlagsI(&(canp)->error_event, flags); \
+ osalSysUnlockFromISR(); \
+}
+#else /* CAN_ENFORCE_USE_CALLBACKS == TRUE */
+#define _can_tx_empty_isr(canp, flags) { \
+ if ((canp)->txempty_cb != NULL) { \
+ (canp)->txempty_cb(canp, flags); \
+ } \
+ osalSysLockFromISR(); \
+ osalThreadDequeueAllI(&(canp)->txqueue, MSG_OK); \
+ osalSysUnlockFromISR(); \
+}
+
+#define _can_rx_full_isr(canp, flags) { \
+ if ((canp)->rxfull_cb != NULL) { \
+ (canp)->rxfull_cb(canp, flags); \
+ } \
+ osalSysLockFromISR(); \
+ osalThreadDequeueAllI(&(canp)->rxqueue, MSG_OK); \
+ osalSysUnlockFromISR(); \
+}
+
+#define _can_wakeup_isr(canp) { \
+ if ((canp)->wakeup_cb != NULL) { \
+ (canp)->wakeup_cb(canp, 0U); \
+ } \
+}
+
+#define _can_error_isr(canp, flags) { \
+ if ((canp)->error_cb != NULL) { \
+ (canp)->error_cb(canp, flags); \
+ } \
+}
+#endif /* CAN_ENFORCE_USE_CALLBACKS == TRUE */
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void canInit(void);
+ void canObjectInit(CANDriver *canp);
+ void canStart(CANDriver *canp, const CANConfig *config);
+ void canStop(CANDriver *canp);
+ bool canTryTransmitI(CANDriver *canp,
+ canmbx_t mailbox,
+ const CANTxFrame *ctfp);
+ bool canTryReceiveI(CANDriver *canp,
+ canmbx_t mailbox,
+ CANRxFrame *crfp);
+ void canTryAbortX(CANDriver *canp,
+ canmbx_t mailbox);
+ msg_t canTransmitTimeout(CANDriver *canp,
+ canmbx_t mailbox,
+ const CANTxFrame *ctfp,
+ sysinterval_t timeout);
+ msg_t canReceiveTimeout(CANDriver *canp,
+ canmbx_t mailbox,
+ CANRxFrame *crfp,
+ sysinterval_t timeout);
+#if CAN_USE_SLEEP_MODE
+ void canSleep(CANDriver *canp);
+ void canWakeup(CANDriver *canp);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_CAN == TRUE */
+
+#endif /* HAL_CAN_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_channels.h b/ChibiOS_20.3.2/os/hal/include/hal_channels.h
new file mode 100644
index 0000000..1ef25b0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_channels.h
@@ -0,0 +1,315 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_channels.h
+ * @brief I/O channels access.
+ * @details This header defines an abstract interface useful to access generic
+ * I/O serial devices in a standardized way.
+ *
+ * @addtogroup IO_CHANNEL
+ * @details This module defines an abstract interface for I/O channels by
+ * extending the @p BaseSequentialStream interface.
+ * Note that no code is present, I/O channels are just abstract
+ * interface like structures, you should look at the systems as
+ * to a set of abstract C++ classes (even if written in C).
+ * Specific device drivers can use/extend the interface and
+ * implement them.
+ * This system has the advantage to make the access to channels
+ * independent from the implementation logic.
+ * @{
+ */
+
+#ifndef HAL_CHANNELS_H
+#define HAL_CHANNELS_H
+
+/**
+ * @name Default control operation codes.
+ * @{
+ */
+#define CHN_CTL_INVALID 0 /** @brief Invalid operation code. */
+#define CHN_CTL_NOP 1 /** @brief Does nothing. */
+#define CHN_CTL_TX_WAIT 2 /** @brief Wait for TX completion. */
+/** @} */
+
+/**
+ * @brief @p BaseChannel specific methods.
+ */
+#define _base_channel_methods \
+ _base_sequential_stream_methods \
+ /* Channel put method with timeout specification.*/ \
+ msg_t (*putt)(void *instance, uint8_t b, sysinterval_t time); \
+ /* Channel get method with timeout specification.*/ \
+ msg_t (*gett)(void *instance, sysinterval_t time); \
+ /* Channel write method with timeout specification.*/ \
+ size_t (*writet)(void *instance, const uint8_t *bp, \
+ size_t n, sysinterval_t time); \
+ /* Channel read method with timeout specification.*/ \
+ size_t (*readt)(void *instance, uint8_t *bp, size_t n, \
+ sysinterval_t time); \
+ /* Channel control method.*/ \
+ msg_t (*ctl)(void *instance, unsigned int operation, void *arg);
+
+/**
+ * @brief @p BaseChannel specific data.
+ * @note It is empty because @p BaseChannel is only an interface without
+ * implementation.
+ */
+#define _base_channel_data \
+ _base_sequential_stream_data
+
+/**
+ * @extends BaseSequentialStreamVMT
+ *
+ * @brief @p BaseChannel virtual methods table.
+ */
+struct BaseChannelVMT {
+ _base_channel_methods
+};
+
+/**
+ * @extends BaseSequentialStream
+ *
+ * @brief Base channel class.
+ * @details This class represents a generic, byte-wide, I/O channel. This class
+ * introduces generic I/O primitives with timeout specification.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct BaseChannelVMT *vmt;
+ _base_channel_data
+} BaseChannel;
+
+/**
+ * @name Macro Functions (BaseChannel)
+ * @{
+ */
+/**
+ * @brief Channel blocking byte write with timeout.
+ * @details This function writes a byte value to a channel. If the channel
+ * is not ready to accept data then the calling thread is suspended.
+ *
+ * @param[in] ip pointer to a @p BaseChannel or derived class
+ * @param[in] b the byte value to be written to the channel
+ * @param[in] time the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval STM_OK if the operation succeeded.
+ * @retval STM_TIMEOUT if the specified time expired.
+ * @retval STM_RESET if the channel associated queue (if any) was reset.
+ *
+ * @api
+ */
+#define chnPutTimeout(ip, b, time) ((ip)->vmt->putt(ip, b, time))
+
+/**
+ * @brief Channel blocking byte read with timeout.
+ * @details This function reads a byte value from a channel. If the data
+ * is not available then the calling thread is suspended.
+ *
+ * @param[in] ip pointer to a @p BaseChannel or derived class
+ * @param[in] time the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A byte value from the queue.
+ * @retval STM_TIMEOUT if the specified time expired.
+ * @retval STM_RESET if the channel associated queue (if any) has been
+ * reset.
+ *
+ * @api
+ */
+#define chnGetTimeout(ip, time) ((ip)->vmt->gett(ip, time))
+
+/**
+ * @brief Channel blocking write.
+ * @details The function writes data from a buffer to a channel. If the channel
+ * is not ready to accept data then the calling thread is suspended.
+ *
+ * @param[in] ip pointer to a @p BaseChannel or derived class
+ * @param[out] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred
+ *
+ * @return The number of bytes transferred.
+ *
+ * @api
+ */
+#define chnWrite(ip, bp, n) streamWrite(ip, bp, n)
+
+/**
+ * @brief Channel blocking write with timeout.
+ * @details The function writes data from a buffer to a channel. If the channel
+ * is not ready to accept data then the calling thread is suspended.
+ *
+ * @param[in] ip pointer to a @p BaseChannel or derived class
+ * @param[out] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred
+ * @param[in] time the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The number of bytes transferred.
+ *
+ * @api
+ */
+#define chnWriteTimeout(ip, bp, n, time) ((ip)->vmt->writet(ip, bp, n, time))
+
+/**
+ * @brief Channel blocking read.
+ * @details The function reads data from a channel into a buffer. If the data
+ * is not available then the calling thread is suspended.
+ *
+ * @param[in] ip pointer to a @p BaseChannel or derived class
+ * @param[in] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred
+ *
+ * @return The number of bytes transferred.
+ *
+ * @api
+ */
+#define chnRead(ip, bp, n) streamRead(ip, bp, n)
+
+/**
+ * @brief Channel blocking read with timeout.
+ * @details The function reads data from a channel into a buffer. If the data
+ * is not available then the calling thread is suspended.
+ *
+ * @param[in] ip pointer to a @p BaseChannel or derived class
+ * @param[in] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred
+ * @param[in] time the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The number of bytes transferred.
+ *
+ * @api
+ */
+#define chnReadTimeout(ip, bp, n, time) ((ip)->vmt->readt(ip, bp, n, time))
+
+/**
+ * @brief Control operation on a channel.
+ *
+ * @param[in] ip pointer to a @p BaseChannel or derived class
+ * @param[in] operation control operation code
+ * @param[in,out] arg operation argument
+ *
+ * @return The control operation status.
+ * @retval MSG_OK in case of success.
+ * @retval MSG_TIMEOUT in case of operation timeout.
+ * @retval MSG_RESET in case of operation reset.
+ *
+ * @api
+ */
+#define chnControl(ip, operation, arg) ((ip)->vmt->ctl(ip, operation, arg))
+/** @} */
+
+/**
+ * @name I/O status flags added to the event listener
+ * @{
+ */
+/** @brief No pending conditions.*/
+#define CHN_NO_ERROR (eventflags_t)0
+/** @brief Connection happened.*/
+#define CHN_CONNECTED (eventflags_t)1
+/** @brief Disconnection happened.*/
+#define CHN_DISCONNECTED (eventflags_t)2
+/** @brief Data available in the input queue.*/
+#define CHN_INPUT_AVAILABLE (eventflags_t)4
+/** @brief Output queue empty.*/
+#define CHN_OUTPUT_EMPTY (eventflags_t)8
+/** @brief Transmission end.*/
+#define CHN_TRANSMISSION_END (eventflags_t)16
+/** @} */
+
+/**
+ * @brief @p BaseAsynchronousChannel specific methods.
+ */
+#define _base_asynchronous_channel_methods \
+ _base_channel_methods \
+
+/**
+ * @brief @p BaseAsynchronousChannel specific data.
+ */
+#define _base_asynchronous_channel_data \
+ _base_channel_data \
+ /* I/O condition event source.*/ \
+ event_source_t event;
+
+/**
+ * @extends BaseChannelVMT
+ *
+ * @brief @p BaseAsynchronousChannel virtual methods table.
+ */
+struct BaseAsynchronousChannelVMT {
+ _base_asynchronous_channel_methods
+};
+
+/**
+ * @extends BaseChannel
+ *
+ * @brief Base asynchronous channel class.
+ * @details This class extends @p BaseChannel by adding event sources fields
+ * for asynchronous I/O for use in an event-driven environment.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct BaseAsynchronousChannelVMT *vmt;
+ _base_asynchronous_channel_data
+} BaseAsynchronousChannel;
+
+/**
+ * @name Macro Functions (BaseAsynchronousChannel)
+ * @{
+ */
+/**
+ * @brief Returns the I/O condition event source.
+ * @details The event source is broadcasted when an I/O condition happens.
+ *
+ * @param[in] ip pointer to a @p BaseAsynchronousChannel or derived
+ * class
+ * @return A pointer to an @p EventSource object.
+ *
+ * @api
+ */
+#define chnGetEventSource(ip) (&((ip)->event))
+
+/**
+ * @brief Adds status flags to the listeners's flags mask.
+ * @details This function is usually called from the I/O ISRs in order to
+ * notify I/O conditions such as data events, errors, signal
+ * changes etc.
+ *
+ * @param[in] ip pointer to a @p BaseAsynchronousChannel or derived
+ * class
+ * @param[in] flags condition flags to be added to the listener flags mask
+ *
+ * @iclass
+ */
+#define chnAddFlagsI(ip, flags) { \
+ osalEventBroadcastFlagsI(&(ip)->event, flags); \
+}
+/** @} */
+
+#endif /* HAL_CHANNELS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_crypto.h b/ChibiOS_20.3.2/os/hal/include/hal_crypto.h
new file mode 100644
index 0000000..5d477b8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_crypto.h
@@ -0,0 +1,383 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_crypto.h
+ * @brief Cryptographic Driver macros and structures.
+ *
+ * @addtogroup CRYPTO
+ * @{
+ */
+
+#ifndef HAL_CRYPTO_H
+#define HAL_CRYPTO_H
+
+#if (HAL_USE_CRY == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the SW fall-back of the cryptographic driver.
+ * @details When enabled, this option, activates a fall-back software
+ * implementation for algorithms not supported by the underlying
+ * hardware.
+ * @note Fall-back implementations may not be present for all algorithms.
+ */
+#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__)
+#define HAL_CRY_USE_FALLBACK FALSE
+#endif
+
+/**
+ * @brief Makes the driver forcibly use the fall-back implementations.
+ * @note If enabled then the LLD driver is not included at all.
+ */
+#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__)
+#define HAL_CRY_ENFORCE_FALLBACK FALSE
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if HAL_CRY_ENFORCE_FALLBACK == TRUE
+#undef HAL_CRY_USE_FALLBACK
+#define HAL_CRY_USE_FALLBACK TRUE
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Size, in bits, of a crypto field or message.
+ * @note It is assumed, for simplicity, that this type is equivalent to
+ * a @p size_t.
+ */
+typedef size_t bitsize_t;
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ CRY_UNINIT = 0, /**< Not initialized. */
+ CRY_STOP = 1, /**< Stopped. */
+ CRY_READY = 2 /**< Ready. */
+} crystate_t;
+
+/**
+ * @brief Driver error codes.
+ */
+typedef enum {
+ CRY_NOERROR = 0, /**< No error. */
+ CRY_ERR_INV_ALGO = 1, /**< Invalid cypher/mode. */
+ CRY_ERR_INV_KEY_SIZE = 2, /**< Invalid key size. */
+ CRY_ERR_INV_KEY_TYPE = 3, /**< Invalid key type. */
+ CRY_ERR_INV_KEY_ID = 4, /**< Invalid key identifier. */
+ CRY_ERR_AUTH_FAILED = 5, /**< Failed authentication. */
+ CRY_ERR_OP_FAILURE = 6 /**< Failed operation. */
+} cryerror_t;
+
+/**
+ * @brief Type of an algorithm identifier.
+ * @note It is only used to determine the key required for operations.
+ */
+typedef enum {
+ cry_algo_none = 0,
+ cry_algo_aes, /**< AES 128, 192, 256 bits. */
+ cry_algo_des, /**< DES 56, TDES 112, 168 bits.*/
+ cry_algo_hmac /**< HMAC variable size. */
+} cryalgorithm_t;
+
+#if HAL_CRY_ENFORCE_FALLBACK == FALSE
+/* Use the defined low level driver.*/
+#include "hal_crypto_lld.h"
+
+#if !defined(CRY_LLD_SUPPORTS_AES) || \
+ !defined(CRY_LLD_SUPPORTS_AES_ECB) || \
+ !defined(CRY_LLD_SUPPORTS_AES_CBC) || \
+ !defined(CRY_LLD_SUPPORTS_AES_CFB) || \
+ !defined(CRY_LLD_SUPPORTS_AES_CTR) || \
+ !defined(CRY_LLD_SUPPORTS_AES_GCM) || \
+ !defined(CRY_LLD_SUPPORTS_DES) || \
+ !defined(CRY_LLD_SUPPORTS_DES_ECB) || \
+ !defined(CRY_LLD_SUPPORTS_DES_CBC) || \
+ !defined(CRY_LLD_SUPPORTS_SHA1) || \
+ !defined(CRY_LLD_SUPPORTS_SHA256) || \
+ !defined(CRY_LLD_SUPPORTS_SHA512) || \
+ !defined(CRY_LLD_SUPPORTS_HMAC_SHA256) || \
+ !defined(CRY_LLD_SUPPORTS_HMAC_SHA512)
+#error "CRYPTO LLD does not export the required switches"
+#endif
+
+#else /* HAL_CRY_ENFORCE_FALLBACK == TRUE */
+/* No LLD at all, using the standalone mode.*/
+
+#define CRY_LLD_SUPPORTS_AES FALSE
+#define CRY_LLD_SUPPORTS_AES_ECB FALSE
+#define CRY_LLD_SUPPORTS_AES_CBC FALSE
+#define CRY_LLD_SUPPORTS_AES_CFB FALSE
+#define CRY_LLD_SUPPORTS_AES_CTR FALSE
+#define CRY_LLD_SUPPORTS_AES_GCM FALSE
+#define CRY_LLD_SUPPORTS_DES FALSE
+#define CRY_LLD_SUPPORTS_DES_ECB FALSE
+#define CRY_LLD_SUPPORTS_DES_CBC FALSE
+#define CRY_LLD_SUPPORTS_SHA1 FALSE
+#define CRY_LLD_SUPPORTS_SHA256 FALSE
+#define CRY_LLD_SUPPORTS_SHA512 FALSE
+#define CRY_LLD_SUPPORTS_HMAC_SHA256 FALSE
+#define CRY_LLD_SUPPORTS_HMAC_SHA512 FALSE
+
+typedef uint_fast8_t crykey_t;
+
+typedef struct CRYDriver CRYDriver;
+
+typedef struct {
+ uint32_t dummy;
+} CRYConfig;
+
+struct CRYDriver {
+ crystate_t state;
+ const CRYConfig *config;
+};
+#endif /* HAL_CRY_ENFORCE_FALLBACK == TRUE */
+
+/* The fallback header is included only if required by settings.*/
+#if HAL_CRY_USE_FALLBACK == TRUE
+#include "hal_crypto_fallback.h"
+#endif
+
+#if (HAL_CRY_USE_FALLBACK == FALSE) && (CRY_LLD_SUPPORTS_SHA1 == FALSE)
+/* Stub @p SHA1Context structure type declaration. It is not provided by
+ the LLD and the fallback is not enabled.*/
+typedef struct {
+ uint32_t dummy;
+} SHA1Context;
+#endif
+
+#if (HAL_CRY_USE_FALLBACK == FALSE) && (CRY_LLD_SUPPORTS_SHA256 == FALSE)
+/* Stub @p SHA256Context structure type declaration. It is not provided by
+ the LLD and the fallback is not enabled.*/
+typedef struct {
+ uint32_t dummy;
+} SHA256Context;
+#endif
+
+#if (HAL_CRY_USE_FALLBACK == FALSE) && (CRY_LLD_SUPPORTS_SHA512 == FALSE)
+/* Stub @p SHA512Context structure type declaration. It is not provided by
+ the LLD and the fallback is not enabled.*/
+typedef struct {
+ uint32_t dummy;
+} SHA512Context;
+#endif
+
+#if (HAL_CRY_USE_FALLBACK == FALSE) && (CRY_LLD_SUPPORTS_HMAC_SHA256 == FALSE)
+/* Stub @p HMACSHA256Context structure type declaration. It is not provided by
+ the LLD and the fallback is not enabled.*/
+typedef struct {
+ uint32_t dummy;
+} HMACSHA256Context;
+#endif
+
+#if (HAL_CRY_USE_FALLBACK == FALSE) && (CRY_LLD_SUPPORTS_HMAC_SHA512 == FALSE)
+/* Stub @p HMACSHA512Context structure type declaration. It is not provided by
+ the LLD and the fallback is not enabled.*/
+typedef struct {
+ uint32_t dummy;
+} HMACSHA512Context;
+#endif
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Low level driver helper macros
+ * @{
+ */
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void cryInit(void);
+ void cryObjectInit(CRYDriver *cryp);
+ void cryStart(CRYDriver *cryp, const CRYConfig *config);
+ void cryStop(CRYDriver *cryp);
+ cryerror_t cryLoadAESTransientKey(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *keyp);
+ cryerror_t cryEncryptAES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cryDecryptAES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cryEncryptAES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cryDecryptAES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cryEncryptAES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cryDecryptAES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cryEncryptAES_CFB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cryDecryptAES_CFB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cryEncryptAES_CTR(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cryDecryptAES_CTR(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cryEncryptAES_GCM(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t auth_size,
+ const uint8_t *auth_in,
+ size_t text_size,
+ const uint8_t *text_in,
+ uint8_t *text_out,
+ const uint8_t *iv,
+ size_t tag_size,
+ uint8_t *tag_out);
+ cryerror_t cryDecryptAES_GCM(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t auth_size,
+ const uint8_t *auth_in,
+ size_t text_size,
+ const uint8_t *text_in,
+ uint8_t *text_out,
+ const uint8_t *iv,
+ size_t tag_size,
+ const uint8_t *tag_in);
+ cryerror_t cryLoadDESTransientKey(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *keyp);
+ cryerror_t cryEncryptDES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cryDecryptDES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cryEncryptDES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cryDecryptDES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cryEncryptDES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cryDecryptDES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t crySHA1Init(CRYDriver *cryp, SHA1Context *sha1ctxp);
+ cryerror_t crySHA1Update(CRYDriver *cryp, SHA1Context *sha1ctxp,
+ size_t size, const uint8_t *in);
+ cryerror_t crySHA1Final(CRYDriver *cryp, SHA1Context *sha1ctxp,
+ uint8_t *out);
+ cryerror_t crySHA256Init(CRYDriver *cryp, SHA256Context *sha256ctxp);
+ cryerror_t crySHA256Update(CRYDriver *cryp, SHA256Context *sha256ctxp,
+ size_t size, const uint8_t *in);
+ cryerror_t crySHA256Final(CRYDriver *cryp, SHA256Context *sha256ctxp,
+ uint8_t *out);
+ cryerror_t crySHA512Init(CRYDriver *cryp, SHA512Context *sha512ctxp);
+ cryerror_t crySHA512Update(CRYDriver *cryp, SHA512Context *sha512ctxp,
+ size_t size, const uint8_t *in);
+ cryerror_t crySHA512Final(CRYDriver *cryp, SHA512Context *sha512ctxp,
+ uint8_t *out);
+ cryerror_t cryLoadHMACTransientKey(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *keyp);
+ cryerror_t cryHMACSHA256Init(CRYDriver *cryp,
+ HMACSHA256Context *hmacsha256ctxp);
+ cryerror_t cryHMACSHA256Update(CRYDriver *cryp,
+ HMACSHA256Context *hmacsha256ctxp,
+ size_t size,
+ const uint8_t *in);
+ cryerror_t cryHMACSHA256Final(CRYDriver *cryp,
+ HMACSHA256Context *hmacsha256ctxp,
+ uint8_t *out);
+ cryerror_t cryHMACSHA512Init(CRYDriver *cryp,
+ HMACSHA512Context *hmacsha512ctxp);
+ cryerror_t cryHMACSHA512Update(CRYDriver *cryp,
+ HMACSHA512Context *hmacsha512ctxp,
+ size_t size,
+ const uint8_t *in);
+ cryerror_t cryHMACSHA512Final(CRYDriver *cryp,
+ HMACSHA512Context *hmacsha512ctxp,
+ uint8_t *out);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_CRYPTO == TRUE */
+
+#endif /* HAL_CRYPTO_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_dac.h b/ChibiOS_20.3.2/os/hal/include/hal_dac.h
new file mode 100644
index 0000000..b3624dc
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_dac.h
@@ -0,0 +1,379 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_dac.h
+ * @brief DAC Driver macros and structures.
+ *
+ * @addtogroup DAC
+ * @{
+ */
+
+#ifndef HAL_DAC_H
+#define HAL_DAC_H
+
+#if (HAL_USE_DAC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name DAC configuration options
+ * @{
+ */
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__)
+#define DAC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define DAC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ DAC_UNINIT = 0, /**< Not initialized. */
+ DAC_STOP = 1, /**< Stopped. */
+ DAC_READY = 2, /**< Ready. */
+ DAC_ACTIVE = 3, /**< Exchanging data. */
+ DAC_COMPLETE = 4, /**< Asynchronous operation complete. */
+ DAC_ERROR = 5 /**< Error. */
+} dacstate_t;
+
+/**
+ * @brief Type of a structure representing an DAC driver.
+ */
+typedef struct hal_dac_driver DACDriver;
+
+/**
+ * @brief Type of a structure representing an DAC driver configuration.
+ */
+typedef struct hal_dac_config DACConfig;
+
+/**
+ * @brief Type of a DAC conversion group.
+ */
+typedef struct hal_dac_conversion_group DACConversionGroup;
+
+/* Including the low level driver header, it exports information required
+ for completing types.*/
+#include "hal_dac_lld.h"
+
+/**
+ * @brief DAC notification callback type.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object triggering the
+ */
+typedef void (*daccallback_t)(DACDriver *dacp);
+
+/**
+ * @brief DAC error callback type.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object triggering the
+ * callback
+ * @param[in] err DAC error code
+ */
+typedef void (*dacerrorcallback_t)(DACDriver *dacp, dacerror_t err);
+
+/**
+ * @brief DAC Conversion group structure.
+ */
+struct hal_dac_conversion_group {
+ /**
+ * @brief Number of DAC channels.
+ */
+ uint32_t num_channels;
+ /**
+ * @brief Operation complete callback or @p NULL.
+ */
+ daccallback_t end_cb;
+ /**
+ * @brief Error handling callback or @p NULL.
+ */
+ dacerrorcallback_t error_cb;
+ /* End of the mandatory fields.*/
+ dac_lld_conversion_group_fields;
+};
+
+/**
+ * @brief Driver configuration structure.
+ */
+struct hal_dac_config {
+ /* End of the mandatory fields.*/
+ dac_lld_config_fields;
+};
+
+/**
+ * @brief Structure representing a DAC driver.
+ */
+struct hal_dac_driver {
+ /**
+ * @brief Driver state.
+ */
+ dacstate_t state;
+ /**
+ * @brief Conversion group.
+ */
+ const DACConversionGroup *grpp;
+ /**
+ * @brief Samples buffer pointer.
+ */
+ dacsample_t *samples;
+ /**
+ * @brief Samples buffer size.
+ */
+ size_t depth;
+ /**
+ * @brief Current configuration data.
+ */
+ const DACConfig *config;
+#if (DAC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Waiting thread.
+ */
+ thread_reference_t thread;
+#endif /* DAC_USE_WAIT */
+#if (DAC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Mutex protecting the bus.
+ */
+ mutex_t mutex;
+#endif /* DAC_USE_MUTUAL_EXCLUSION */
+#if defined(DAC_DRIVER_EXT_FIELDS)
+ DAC_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ dac_lld_driver_fields;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Low level driver helper macros
+ * @{
+ */
+/**
+ * @brief Buffer state.
+ * @note This function is meant to be called from the DAC callback only.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ * @return The buffer state.
+ * @retval false if the driver filled/sent the first half of the
+ * buffer.
+ * @retval true if the driver filled/sent the second half of the
+ * buffer.
+ *
+ * @special
+ */
+#define dacIsBufferComplete(dacp) ((bool)((dacp)->state == DAC_COMPLETE))
+
+#if (DAC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Waits for operation completion.
+ * @details This function waits for the driver to complete the current
+ * operation.
+ * @pre An operation must be running while the function is invoked.
+ * @note No more than one thread can wait on a DAC driver using
+ * this function.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @notapi
+ */
+#define _dac_wait_s(dacp) osalThreadSuspendS(&(dacp)->thread)
+
+/**
+ * @brief Resumes a thread waiting for a conversion completion.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @notapi
+ */
+#define _dac_reset_i(dacp) osalThreadResumeI(&(dacp)->thread, MSG_RESET)
+
+/**
+ * @brief Resumes a thread waiting for a conversion completion.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @notapi
+ */
+#define _dac_reset_s(dacp) osalThreadResumeS(&(dacp)->thread, MSG_RESET)
+
+/**
+ * @brief Wakes up the waiting thread.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @notapi
+ */
+#define _dac_wakeup_isr(dacp) { \
+ osalSysLockFromISR(); \
+ osalThreadResumeI(&(dacp)->thread, MSG_OK); \
+ osalSysUnlockFromISR(); \
+}
+
+/**
+ * @brief Wakes up the waiting thread with a timeout message.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @notapi
+ */
+#define _dac_timeout_isr(dacp) { \
+ osalSysLockFromISR(); \
+ osalThreadResumeI(&(dacp)->thread, MSG_TIMEOUT); \
+ osalSysUnlockFromISR(); \
+}
+
+#else /* !DAC_USE_WAIT */
+#define _dac_wait_s(dacp)
+#define _dac_reset_i(dacp)
+#define _dac_reset_s(dacp)
+#define _dac_wakeup_isr(dacp)
+#define _dac_timeout_isr(dacp)
+#endif /* !DAC_USE_WAIT */
+
+/**
+ * @brief Common ISR code, half buffer event.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @notapi
+ */
+#define _dac_isr_half_code(dacp) { \
+ if ((dacp)->grpp->end_cb != NULL) { \
+ (dacp)->grpp->end_cb(dacp); \
+ } \
+}
+
+/**
+ * @brief Common ISR code, full buffer event.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @notapi
+ */
+#define _dac_isr_full_code(dacp) { \
+ if ((dacp)->grpp->end_cb) { \
+ (dacp)->state = DAC_COMPLETE; \
+ (dacp)->grpp->end_cb(dacp); \
+ if ((dacp)->state == DAC_COMPLETE) \
+ (dacp)->state = DAC_ACTIVE; \
+ } \
+}
+
+/**
+ * @brief Common ISR code, error event.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Waiting thread timeout signaling, if any.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ * @param[in] err platform dependent error code
+ *
+ * @notapi
+ */
+#define _dac_isr_error_code(dacp, err) { \
+ dac_lld_stop_conversion(dacp); \
+ if ((dacp)->grpp->error_cb != NULL) { \
+ (dacp)->state = DAC_ERROR; \
+ (dacp)->grpp->error_cb(dacp, err); \
+ if ((dacp)->state == DAC_ERROR) \
+ (dacp)->state = DAC_READY; \
+ } \
+ (dacp)->grpp = NULL; \
+ _dac_timeout_isr(dacp); \
+}
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void dacInit(void);
+ void dacObjectInit(DACDriver *dacp);
+ void dacStart(DACDriver *dacp, const DACConfig *config);
+ void dacStop(DACDriver *dacp);
+ void dacPutChannelX(DACDriver *dacp,
+ dacchannel_t channel,
+ dacsample_t sample);
+ void dacStartConversion(DACDriver *dacp, const DACConversionGroup *grpp,
+ dacsample_t *samples, size_t depth);
+ void dacStartConversionI(DACDriver *dacp, const DACConversionGroup *grpp,
+ dacsample_t *samples, size_t depth);
+ void dacStopConversion(DACDriver *dacp);
+ void dacStopConversionI(DACDriver *dacp);
+#if DAC_USE_WAIT
+ msg_t dacConvert(DACDriver *dacp, const DACConversionGroup *grpp,
+ dacsample_t *samples, size_t depth);
+#endif
+#if DAC_USE_MUTUAL_EXCLUSION
+ void dacAcquireBus(DACDriver *dacp);
+ void dacReleaseBus(DACDriver *dacp);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_DAC == TRUE */
+
+#endif /* HAL_DAC_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_efl.h b/ChibiOS_20.3.2/os/hal/include/hal_efl.h
new file mode 100644
index 0000000..f00517c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_efl.h
@@ -0,0 +1,130 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_efl.h
+ * @brief Embedded Flash Driver macros and structures.
+ *
+ * @addtogroup HAL_EFL
+ * @{
+ */
+
+#ifndef HAL_EFL_H
+#define HAL_EFL_H
+
+#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @extends BaseFlash
+ *
+ * @brief Type of external flash driver class.
+ */
+typedef struct hal_efl_driver EFlashDriver;
+
+#include "hal_efl_lld.h"
+
+/**
+ * @brief @p EFlashDriver specific methods.
+ */
+#define _efl_flash_methods_alone
+
+/**
+ * @brief @p EFlashDriver specific methods with inherited ones.
+ */
+#define _efl_flash_methods \
+ _base_flash_methods \
+ _efl_flash_methods_alone
+
+/**
+ * @brief @p EFlashDriver specific data.
+ */
+#define _efl_driver_data \
+ _base_flash_data \
+ /* Current configuration data.*/ \
+ const EFlashConfig *config;
+
+/**
+ * @extends BaseFlashVMT
+ *
+ * @brief @p EFlash virtual methods table.
+ */
+struct EFlashDriverVMT {
+ _efl_flash_methods
+};
+
+/**
+ * @brief Type of a structure representing a flash driver configuration.
+ */
+typedef struct hal_efl_config {
+ /* End of the mandatory fields.*/
+ efl_lld_config_fields;
+} EFlashConfig;
+
+/**
+ * @extends BaseFlash
+ *
+ * @brief Structure representing an embedded flash driver.
+ */
+struct hal_efl_driver {
+ /**
+ * @brief SNORDriver Virtual Methods Table.
+ */
+ const struct EFlashDriverVMT *vmt;
+ _efl_driver_data
+ /* End of the mandatory fields.*/
+ efl_lld_driver_fields;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void eflInit(void);
+ void eflObjectInit(EFlashDriver *eflp);
+ void eflStart(EFlashDriver *eflp, const EFlashConfig *config);
+ void eflStop(EFlashDriver *eflp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_EFL == TRUE */
+
+#endif /* HAL_EFL_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_files.h b/ChibiOS_20.3.2/os/hal/include/hal_files.h
new file mode 100644
index 0000000..63018ac
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_files.h
@@ -0,0 +1,240 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_files.h
+ * @brief Data files.
+ * @details This header defines abstract interfaces useful to access generic
+ * data files in a standardized way.
+ *
+ * @addtogroup HAL_FILES
+ * @details This module define an abstract interface for generic data files by
+ * extending the @p BaseSequentialStream interface. Note that no code
+ * is present, data files are just abstract interface-like structures,
+ * you should look at the systems as to a set of abstract C++ classes
+ * (even if written in C). This system has the advantage to make the
+ * access to streams independent from the implementation logic.
+ * The data files interface can be used as base class for high level
+ * object types such as an API for a File System implementation.
+ * @{
+ */
+
+#ifndef HAL_FILES_H
+#define HAL_FILES_H
+
+/**
+ * @name Files return codes
+ * @{
+ */
+/**
+ * @brief No error return code.
+ */
+#define FILE_OK STM_OK
+
+/**
+ * @brief Error code from the file stream methods.
+ */
+#define FILE_ERROR STM_TIMEOUT
+
+/**
+ * @brief End-of-file condition for file get/put methods.
+ */
+#define FILE_EOF STM_RESET
+/** @} */
+
+/**
+ * @brief File offset type.
+ */
+typedef uint32_t fileoffset_t;
+
+/**
+ * @brief FileStream specific methods.
+ */
+#define _file_stream_methods \
+ _base_sequential_stream_methods \
+ /* File close method.*/ \
+ msg_t (*close)(void *instance); \
+ /* Get last error code method.*/ \
+ msg_t (*geterror)(void *instance); \
+ /* File get size method.*/ \
+ msg_t (*getsize)(void *instance, fileoffset_t *offset); \
+ /* File get current position method.*/ \
+ msg_t (*getposition)(void *instance, fileoffset_t *offset); \
+ /* File set current position method.*/ \
+ msg_t (*setposition)(void *instance, fileoffset_t offset);
+
+/**
+ * @brief @p FileStream specific data.
+ * @note It is empty because @p FileStream is only an interface
+ * without implementation.
+ */
+#define _file_stream_data \
+ _base_sequential_stream_data
+
+/**
+ * @extends BaseSequentialStreamVMT
+ *
+ * @brief @p FileStream virtual methods table.
+ */
+struct FileStreamVMT {
+ _file_stream_methods
+};
+
+/**
+ * @extends BaseSequentialStream
+ *
+ * @brief Base file stream class.
+ * @details This class represents a generic file data stream.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct FileStreamVMT *vmt;
+ _file_stream_data
+} FileStream;
+
+/**
+ * @name Macro Functions (FileStream)
+ * @{
+ */
+/**
+ * @brief File stream write.
+ * @details The function writes data from a buffer to a file stream.
+ *
+ * @param[in] ip pointer to a @p FileStream or derived class
+ * @param[in] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred
+ * @return The number of bytes transferred. The return value can
+ * be less than the specified number of bytes if an
+ * end-of-file condition has been met.
+ * @retval FILE_ERROR operation failed.
+ *
+ * @api
+ */
+#define fileStreamWrite(ip, bp, n) streamWrite(ip, bp, n)
+
+/**
+ * @brief File stream read.
+ * @details The function reads data from a file stream into a buffer.
+ *
+ * @param[in] ip pointer to a @p FileStream or derived class
+ * @param[out] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred
+ * @return The number of bytes transferred. The return value can
+ * be less than the specified number of bytes if an
+ * end-of-file condition has been met.
+ * @retval FILE_ERROR operation failed.
+ *
+ * @api
+ */
+#define fileStreamRead(ip, bp, n) streamRead(ip, bp, n)
+
+/**
+ * @brief File stream blocking byte write.
+ * @details This function writes a byte value to a channel. If the channel
+ * is not ready to accept data then the calling thread is suspended.
+ *
+ * @param[in] ip pointer to a @p FileStream or derived class
+ * @param[in] b the byte value to be written to the channel
+ *
+ * @return The operation status.
+ * @retval FILE_OK if the operation succeeded.
+ * @retval FILE_ERROR operation failed.
+ * @retval FILE_EOF if an end-of-file condition has been met.
+ *
+ * @api
+ */
+#define fileStreamPut(ip, b) streamPut(ip, b)
+
+/**
+ * @brief File stream blocking byte read.
+ * @details This function reads a byte value from a channel. If the data
+ * is not available then the calling thread is suspended.
+ *
+ * @param[in] ip pointer to a @p FileStream or derived class
+ *
+ * @return A byte value from the queue.
+ * @retval FILE_ERROR operation failed.
+ * @retval FILE_EOF if an end-of-file condition has been met.
+ *
+ * @api
+ */
+#define fileStreamGet(ip) streamGet(ip)
+
+/**
+ * @brief File Stream close.
+ * @details The function closes a file stream.
+ *
+ * @param[in] ip pointer to a @p FileStream or derived class
+ * @return The operation status.
+ * @retval FILE_OK no error.
+ * @retval FILE_ERROR operation failed.
+ *
+ * @api
+ */
+#define fileStreamClose(ip) ((ip)->vmt->close(ip))
+
+/**
+ * @brief Returns an implementation dependent error code.
+ * @pre The previously called function must have returned @p FILE_ERROR.
+ *
+ * @param[in] ip pointer to a @p FileStream or derived class
+ * @return Implementation dependent error code.
+ *
+ * @api
+ */
+#define fileStreamGetError(ip) ((ip)->vmt->geterror(ip))
+
+/**
+ * @brief Returns the current file size.
+ *
+ * @param[in] ip pointer to a @p FileStream or derived class
+ * @param[out] offset current size of the file
+ * @return The file size.
+ * @retval FILE_ERROR operation failed.
+ *
+ * @api
+ */
+#define fileStreamGetSize(ip, offset) ((ip)->vmt->getsize(ip, offset))
+
+/**
+ * @brief Returns the current file pointer position.
+ *
+ * @param[in] ip pointer to a @p FileStream or derived class
+ * @param[out] offset current position in the file
+ * @return The current position inside the file.
+ * @retval FILE_ERROR operation failed.
+ *
+ * @api
+ */
+#define fileStreamGetPosition(ip, offset) ((ip)->vmt->getposition(ip, offset))
+
+/**
+ * @brief Moves the file current pointer to an absolute position.
+ *
+ * @param[in] ip pointer to a @p FileStream or derived class
+ * @param[in] offset new absolute position
+ * @return The operation status.
+ * @retval FILE_OK no error.
+ * @retval FILE_ERROR operation failed.
+ *
+ * @api
+ */
+#define fileStreamSetPosition(ip, offset) ((ip)->vmt->setposition(ip, offset))
+/** @} */
+
+#endif /* HAL_FILES_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_flash.h b/ChibiOS_20.3.2/os/hal/include/hal_flash.h
new file mode 100644
index 0000000..ba90a76
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_flash.h
@@ -0,0 +1,369 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_flash.h
+ * @brief Generic flash driver class header.
+ *
+ * @addtogroup HAL_FLASH
+ * @{
+ */
+
+#ifndef HAL_FLASH_H
+#define HAL_FLASH_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Flash attributes
+ * @{
+ */
+/**
+ * @brief Defines one as the erased bit state.
+ */
+#define FLASH_ATTR_ERASED_IS_ONE 0x00000001U
+/**
+ * @brief The memory is accessible in a memory mapped mode.
+ */
+#define FLASH_ATTR_MEMORY_MAPPED 0x00000002U
+/**
+ * @brief Programmed pages can be programmed again.
+ * @note This is incompatible and alternative to @p FLASH_ATTR_ECC_CAPABLE.
+ */
+#define FLASH_ATTR_REWRITABLE 0x00000004U
+/**
+ * @brief The memory is protected by an ECC mechanism.
+ * @note This usually puts restrictions on the program operations.
+ * - Program operations can only happen at offsets aligned to
+ * write page boundaries.
+ * - The programmed data size must be a multiple of the write
+ * page size.
+ * - Programmed pages cannot be re-programmed.
+ * .
+ */
+#define FLASH_ATTR_ECC_CAPABLE 0x00000008U
+/**
+ * @brief The device is able to overwrite zero to a line.
+ * @note This attribute is only meaningful for those devices that support
+ * ECC, so also @p FLASH_ATTR_ECC_CAPABLE must be specified.
+ */
+#define FLASH_ATTR_ECC_ZERO_LINE_CAPABLE 0x00000010U
+/**
+ * @brief The device is able to suspend erase operations.
+ */
+#define FLASH_ATTR_SUSPEND_ERASE_CAPABLE 0x00000020U
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ FLASH_UNINIT = 0,
+ FLASH_STOP = 1,
+ FLASH_READY = 2,
+ FLASH_READ = 3,
+ FLASH_PGM = 4,
+ FLASH_ERASE = 5
+} flash_state_t;
+
+/**
+ * @brief Type of a flash error code.
+ */
+typedef enum {
+ FLASH_NO_ERROR = 0, /* No error. */
+ FLASH_BUSY_ERASING = 1, /* Erase operation in progress. */
+ FLASH_ERROR_READ = 2, /* ECC or other error during read operation.*/
+ FLASH_ERROR_PROGRAM = 3, /* Program operation failed. */
+ FLASH_ERROR_ERASE = 4, /* Erase operation failed. */
+ FLASH_ERROR_VERIFY = 5, /* Verify operation failed. */
+ FLASH_ERROR_HW_FAILURE = 6, /* Controller or communication error. */
+ FLASH_ERROR_UNIMPLEMENTED = 7 /* Unimplemented functionality. */
+} flash_error_t;
+
+/**
+ * @brief Type of a flash offset.
+ */
+typedef uint32_t flash_offset_t;
+
+/**
+ * @brief Type of a flash sector number.
+ */
+typedef uint32_t flash_sector_t;
+
+/**
+ * @brief Flash sector descriptor.
+ */
+typedef struct {
+ /**
+ * @brief Sector offset.
+ */
+ flash_offset_t offset;
+ /**
+ * @brief Sector size.
+ */
+ uint32_t size;
+} flash_sector_descriptor_t;
+
+/**
+ * @brief Type of a flash device descriptor.
+ */
+typedef struct {
+ /**
+ * @brief Device_attributes.
+ */
+ uint32_t attributes;
+ /**
+ * @brief Size of write page.
+ */
+ uint32_t page_size;
+ /**
+ * @brief Number of sectors in the device.
+ */
+ flash_sector_t sectors_count;
+ /**
+ * @brief List of sectors for devices with non-uniform sector sizes.
+ * @note If @p NULL then the device has uniform sectors size equal
+ * to @p sector_size.
+ */
+ const flash_sector_descriptor_t *sectors;
+ /**
+ * @brief Size of sectors for devices with uniform sector size.
+ * @note If zero then the device has non uniform sectors described
+ * by the @p sectors array.
+ */
+ uint32_t sectors_size;
+ /**
+ * @brief Flash address if memory mapped or zero.
+ * @note Conventionally, non memory mapped devices have address @p NULL.
+ */
+ uint8_t *address;
+ /**
+ * @brief Flash size.
+ */
+ uint32_t size;
+} flash_descriptor_t;
+
+/**
+ * @brief @p BaseFlash specific methods.
+ */
+#define _base_flash_methods_alone \
+ /* Get flash device attributes.*/ \
+ const flash_descriptor_t * (*get_descriptor)(void *instance); \
+ /* Read operation.*/ \
+ flash_error_t (*read)(void *instance, flash_offset_t offset, \
+ size_t n, uint8_t *rp); \
+ /* Program operation.*/ \
+ flash_error_t (*program)(void *instance, flash_offset_t offset, \
+ size_t n, const uint8_t *pp); \
+ /* Erase whole flash device.*/ \
+ flash_error_t (*start_erase_all)(void *instance); \
+ /* Erase single sector.*/ \
+ flash_error_t (*start_erase_sector)(void *instance, \
+ flash_sector_t sector); \
+ flash_error_t (*query_erase)(void *instance, uint32_t *wait_time); \
+ /* Verify erase single sector.*/ \
+ flash_error_t (*verify_erase)(void *instance, flash_sector_t sector);
+
+/**
+ * @brief @p BaseFlash specific methods with inherited ones.
+ */
+#define _base_flash_methods \
+ _base_object_methods \
+ _base_flash_methods_alone
+
+/**
+ * @brief @p BaseFlash virtual methods table.
+ */
+struct BaseFlashVMT {
+ _base_flash_methods
+};
+
+/**
+ * @brief @p BaseFlash specific data.
+ */
+#define _base_flash_data \
+ _base_object_data \
+ /* Driver state.*/ \
+ flash_state_t state;
+
+/**
+ * @extends BaseObject
+ *
+ * @brief Base flash class.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct BaseFlashVMT *vmt;
+ _base_flash_data
+} BaseFlash;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions (BaseFlash)
+ * @{
+ */
+/**
+ * @brief Instance getter.
+ * @details This special method is used to get the instance of this class
+ * object from a derived class.
+ */
+#define getBaseFlash(ip) ((BaseFlash *)&(ip)->vmt)
+
+/**
+ * @brief Gets the flash descriptor structure.
+ *
+ * @param[in] ip pointer to a @p BaseFlash or derived class
+ * @return A flash device descriptor.
+ *
+ * @api
+ */
+#define flashGetDescriptor(ip) \
+ (ip)->vmt->get_descriptor(ip)
+
+/**
+ * @brief Read operation.
+ *
+ * @param[in] ip pointer to a @p BaseFlash or derived class
+ * @param[in] offset flash offset
+ * @param[in] n number of bytes to be read
+ * @param[out] rp pointer to the data buffer
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_READ if the read operation failed.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @api
+ */
+#define flashRead(ip, offset, n, rp) \
+ (ip)->vmt->read(ip, offset, n, rp)
+
+/**
+ * @brief Program operation.
+ *
+ * @param[in] ip pointer to a @p BaseFlash or derived class
+ * @param[in] offset flash offset
+ * @param[in] n number of bytes to be programmed
+ * @param[in] pp pointer to the data buffer
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_PROGRAM if the program operation failed.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @api
+ */
+#define flashProgram(ip, offset, n, pp) \
+ (ip)->vmt->program(ip, offset, n, pp)
+
+/**
+ * @brief Starts a whole-device erase operation.
+ *
+ * @param[in] ip pointer to a @p BaseFlash or derived class
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @api
+ */
+#define flashStartEraseAll(ip) \
+ (ip)->vmt->start_erase_all(ip)
+
+/**
+ * @brief Starts an sector erase operation.
+ *
+ * @param[in] ip pointer to a @p BaseFlash or derived class
+ * @param[in] sector sector to be erased
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @api
+ */
+#define flashStartEraseSector(ip, sector) \
+ (ip)->vmt->start_erase_sector(ip, sector)
+
+/**
+ * @brief Queries the driver for erase operation progress.
+ *
+ * @param[in] ip pointer to a @p BaseFlash or derived class
+ * @param[out] msec recommended time, in milliseconds, that
+ * should be spent before calling this
+ * function again, can be @p NULL
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_ERASE if the erase operation failed.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @api
+ */
+#define flashQueryErase(ip, msec) \
+ (ip)->vmt->query_erase(ip, msec)
+
+/**
+ * @brief Returns the erase state of a sector.
+ *
+ * @param[in] ip pointer to a @p BaseFlash or derived class
+ * @param[in] sector sector to be verified
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if the sector is erased.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_VERIFY if the verify operation failed.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @api
+ */
+#define flashVerifyErase(ip, sector) \
+ (ip)->vmt->verify_erase(ip, sector)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ flash_error_t flashWaitErase(BaseFlash *devp);
+ flash_offset_t flashGetSectorOffset(BaseFlash *devp, flash_sector_t sector);
+ uint32_t flashGetSectorSize(BaseFlash *devp, flash_sector_t sector);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_FLASH_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_gpt.h b/ChibiOS_20.3.2/os/hal/include/hal_gpt.h
new file mode 100644
index 0000000..fd2b8fd
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_gpt.h
@@ -0,0 +1,158 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_gpt.h
+ * @brief GPT Driver macros and structures.
+ *
+ * @addtogroup GPT
+ * @{
+ */
+
+#ifndef HAL_GPT_H
+#define HAL_GPT_H
+
+#if (HAL_USE_GPT == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ GPT_UNINIT = 0, /**< Not initialized. */
+ GPT_STOP = 1, /**< Stopped. */
+ GPT_READY = 2, /**< Ready. */
+ GPT_CONTINUOUS = 3, /**< Active in continuous mode. */
+ GPT_ONESHOT = 4 /**< Active in one shot mode. */
+} gptstate_t;
+
+/**
+ * @brief Type of a structure representing a GPT driver.
+ */
+typedef struct GPTDriver GPTDriver;
+
+/**
+ * @brief GPT notification callback type.
+ *
+ * @param[in] gptp pointer to a @p GPTDriver object
+ */
+typedef void (*gptcallback_t)(GPTDriver *gptp);
+
+#include "hal_gpt_lld.h"
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Changes the interval of GPT peripheral.
+ * @details This function changes the interval of a running GPT unit.
+ * @pre The GPT unit must be running in continuous mode.
+ * @post The GPT unit interval is changed to the new value.
+ *
+ * @param[in] gptp pointer to a @p GPTDriver object
+ * @param[in] interval new cycle time in timer ticks
+ *
+ * @iclass
+ */
+#define gptChangeIntervalI(gptp, interval) { \
+ gpt_lld_change_interval(gptp, interval); \
+}
+
+/**
+ * @brief Returns the interval of GPT peripheral.
+ * @pre The GPT unit must be running in continuous mode.
+ *
+ * @param[in] gptp pointer to a @p GPTDriver object
+ * @return The current interval.
+ *
+ * @xclass
+ */
+#define gptGetIntervalX(gptp) gpt_lld_get_interval(gptp)
+
+/**
+ * @brief Returns the counter value of GPT peripheral.
+ * @pre The GPT unit must be running in continuous mode.
+ * @note The nature of the counter is not defined, it may count upward
+ * or downward, it could be continuously running or not.
+ *
+ * @param[in] gptp pointer to a @p GPTDriver object
+ * @return The current counter value.
+ *
+ * @xclass
+ */
+#define gptGetCounterX(gptp) gpt_lld_get_counter(gptp)
+
+/**
+ * @brief Common ISR code, GPT period event.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ *
+ * @notapi
+ */
+#define _gpt_isr_invoke_cb(gptp) do { \
+ if ((gptp)->state == GPT_ONESHOT) { \
+ (gptp)->state = GPT_READY; \
+ gpt_lld_stop_timer(gptp); \
+ } \
+ if ((gptp)->config->callback != NULL) { \
+ (gptp)->config->callback(gptp); \
+ } \
+} while (0)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void gptInit(void);
+ void gptObjectInit(GPTDriver *gptp);
+ void gptStart(GPTDriver *gptp, const GPTConfig *config);
+ void gptStop(GPTDriver *gptp);
+ void gptStartContinuous(GPTDriver *gptp, gptcnt_t interval);
+ void gptStartContinuousI(GPTDriver *gptp, gptcnt_t interval);
+ void gptChangeInterval(GPTDriver *gptp, gptcnt_t interval);
+ void gptStartOneShot(GPTDriver *gptp, gptcnt_t interval);
+ void gptStartOneShotI(GPTDriver *gptp, gptcnt_t interval);
+ void gptStopTimer(GPTDriver *gptp);
+ void gptStopTimerI(GPTDriver *gptp);
+ void gptPolledDelay(GPTDriver *gptp, gptcnt_t interval);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_GPT == TRUE */
+
+#endif /* HAL_GPT_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_i2c.h b/ChibiOS_20.3.2/os/hal/include/hal_i2c.h
new file mode 100644
index 0000000..c5776d2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_i2c.h
@@ -0,0 +1,166 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file hal_i2c.h
+ * @brief I2C Driver macros and structures.
+ *
+ * @addtogroup I2C
+ * @{
+ */
+
+#ifndef HAL_I2C_H
+#define HAL_I2C_H
+
+#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/* TODO: To be reviewed, too STM32-centric.*/
+/**
+ * @name I2C bus error conditions
+ * @{
+ */
+#define I2C_NO_ERROR 0x00 /**< @brief No error. */
+#define I2C_BUS_ERROR 0x01 /**< @brief Bus Error. */
+#define I2C_ARBITRATION_LOST 0x02 /**< @brief Arbitration Lost. */
+#define I2C_ACK_FAILURE 0x04 /**< @brief Acknowledge Failure. */
+#define I2C_OVERRUN 0x08 /**< @brief Overrun/Underrun. */
+#define I2C_PEC_ERROR 0x10 /**< @brief PEC Error in
+ reception. */
+#define I2C_TIMEOUT 0x20 /**< @brief Hardware timeout. */
+#define I2C_SMB_ALERT 0x40 /**< @brief SMBus Alert. */
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the mutual exclusion APIs on the I2C bus.
+ */
+#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define I2C_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ I2C_UNINIT = 0, /**< @brief Not initialized. */
+ I2C_STOP = 1, /**< @brief Stopped. */
+ I2C_READY = 2, /**< @brief Ready. */
+ I2C_ACTIVE_TX = 3, /**< @brief Transmitting. */
+ I2C_ACTIVE_RX = 4, /**< @brief Receiving. */
+ I2C_LOCKED = 5 /**< @brief Bus locked. */
+} i2cstate_t;
+
+#include "hal_i2c_lld.h"
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Wakes up the waiting thread notifying no errors.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+#define _i2c_wakeup_isr(i2cp) do { \
+ osalSysLockFromISR(); \
+ osalThreadResumeI(&(i2cp)->thread, MSG_OK); \
+ osalSysUnlockFromISR(); \
+} while (0)
+
+/**
+ * @brief Wakes up the waiting thread notifying errors.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+#define _i2c_wakeup_error_isr(i2cp) do { \
+ osalSysLockFromISR(); \
+ osalThreadResumeI(&(i2cp)->thread, MSG_RESET); \
+ osalSysUnlockFromISR(); \
+} while (0)
+
+/**
+ * @brief Wrap i2cMasterTransmitTimeout function with TIME_INFINITE timeout.
+ * @api
+ */
+#define i2cMasterTransmit(i2cp, addr, txbuf, txbytes, rxbuf, rxbytes) \
+ (i2cMasterTransmitTimeout(i2cp, addr, txbuf, txbytes, rxbuf, rxbytes, \
+ TIME_INFINITE))
+
+/**
+ * @brief Wrap i2cMasterReceiveTimeout function with TIME_INFINITE timeout.
+ * @api
+ */
+#define i2cMasterReceive(i2cp, addr, rxbuf, rxbytes) \
+ (i2cMasterReceiveTimeout(i2cp, addr, rxbuf, rxbytes, TIME_INFINITE))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void i2cInit(void);
+ void i2cObjectInit(I2CDriver *i2cp);
+ void i2cStart(I2CDriver *i2cp, const I2CConfig *config);
+ void i2cStop(I2CDriver *i2cp);
+ i2cflags_t i2cGetErrors(I2CDriver *i2cp);
+ msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp,
+ i2caddr_t addr,
+ const uint8_t *txbuf, size_t txbytes,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout);
+ msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp,
+ i2caddr_t addr,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout);
+#if I2C_USE_MUTUAL_EXCLUSION == TRUE
+ void i2cAcquireBus(I2CDriver *i2cp);
+ void i2cReleaseBus(I2CDriver *i2cp);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_I2C == TRUE */
+
+#endif /* HAL_I2C_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_i2s.h b/ChibiOS_20.3.2/os/hal/include/hal_i2s.h
new file mode 100644
index 0000000..1dccaaa
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_i2s.h
@@ -0,0 +1,240 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_i2s.h
+ * @brief I2S Driver macros and structures.
+ *
+ * @addtogroup I2S
+ * @{
+ */
+
+#ifndef HAL_I2S_H
+#define HAL_I2S_H
+
+#if (HAL_USE_I2S == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name I2S modes
+ * @{
+ */
+#define I2S_MODE_SLAVE 0
+#define I2S_MODE_MASTER 1
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ I2S_UNINIT = 0, /**< Not initialized. */
+ I2S_STOP = 1, /**< Stopped. */
+ I2S_READY = 2, /**< Ready. */
+ I2S_ACTIVE = 3, /**< Active. */
+ I2S_COMPLETE = 4 /**< Transmission complete. */
+} i2sstate_t;
+
+/**
+ * @brief Type of a structure representing an I2S driver.
+ */
+typedef struct hal_i2s_driver I2SDriver;
+
+/**
+ * @brief Type of a structure representing an I2S driver configuration.
+ */
+typedef struct hal_i2s_config I2SConfig;
+
+/**
+ * @brief I2S notification callback type.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ */
+typedef void (*i2scallback_t)(I2SDriver *i2sp);
+
+/* Including the low level driver header, it exports information required
+ for completing types.*/
+#include "hal_i2s_lld.h"
+
+/**
+ * @brief Structure representing an I2S driver.
+ */
+struct hal_i2s_driver {
+ /**
+ * @brief Driver state.
+ */
+ i2sstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const I2SConfig *config;
+ /* End of the mandatory fields.*/
+ i2s_lld_driver_fields;
+};
+
+/**
+ * @brief Driver configuration structure.
+ */
+struct hal_i2s_config {
+ /**
+ * @brief Transmission buffer pointer.
+ * @note Can be @p NULL if TX is not required.
+ */
+ const void *tx_buffer;
+ /**
+ * @brief Receive buffer pointer.
+ * @note Can be @p NULL if RX is not required.
+ */
+ void *rx_buffer;
+ /**
+ * @brief TX and RX buffers size as number of samples.
+ */
+ size_t size;
+ /**
+ * @brief Callback function called during streaming.
+ */
+ i2scallback_t end_cb;
+ /* End of the mandatory fields.*/
+ i2s_lld_config_fields;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Buffer state.
+ * @note This function is meant to be called from the SPI callback only.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ * @return The buffer state.
+ * @retval false if the driver filled/sent the first half of the
+ * buffer.
+ * @retval true if the driver filled/sent the second half of the
+ * buffer.
+ *
+ * @special
+ */
+#define i2sIsBufferComplete(i2sp) ((bool)((i2sp)->state == I2S_COMPLETE))
+
+/**
+ * @brief Starts a I2S data exchange.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @iclass
+ */
+#define i2sStartExchangeI(i2sp) { \
+ i2s_lld_start_exchange(i2sp); \
+ (i2sp)->state = I2S_ACTIVE; \
+}
+
+/**
+ * @brief Stops the ongoing data exchange.
+ * @details The ongoing data exchange, if any, is stopped, if the driver
+ * was not active the function does nothing.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @iclass
+ */
+#define i2sStopExchangeI(i2sp) { \
+ i2s_lld_stop_exchange(i2sp); \
+ (i2sp)->state = I2S_READY; \
+}
+
+/**
+ * @brief Common ISR code, half buffer event.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] i2sp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+#define _i2s_isr_half_code(i2sp) { \
+ if ((i2sp)->config->end_cb != NULL) { \
+ (i2sp)->config->end_cb(i2sp); \
+ } \
+}
+
+/**
+ * @brief Common ISR code.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] i2sp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+#define _i2s_isr_full_code(i2sp) { \
+ if ((i2sp)->config->end_cb) { \
+ (i2sp)->state = I2S_COMPLETE; \
+ (i2sp)->config->end_cb(i2sp); \
+ if ((i2sp)->state == I2S_COMPLETE) { \
+ (i2sp)->state = I2S_ACTIVE; \
+ } \
+ } \
+}
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void i2sInit(void);
+ void i2sObjectInit(I2SDriver *i2sp);
+ void i2sStart(I2SDriver *i2sp, const I2SConfig *config);
+ void i2sStop(I2SDriver *i2sp);
+ void i2sStartExchange(I2SDriver *i2sp);
+ void i2sStopExchange(I2SDriver *i2sp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_I2S == TRUE */
+
+#endif /* HAL_I2S_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_icu.h b/ChibiOS_20.3.2/os/hal/include/hal_icu.h
new file mode 100644
index 0000000..89c4a62
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_icu.h
@@ -0,0 +1,240 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_icu.h
+ * @brief ICU Driver macros and structures.
+ *
+ * @addtogroup ICU
+ * @{
+ */
+
+#ifndef HAL_ICU_H
+#define HAL_ICU_H
+
+#if (HAL_USE_ICU == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ ICU_UNINIT = 0, /**< Not initialized. */
+ ICU_STOP = 1, /**< Stopped. */
+ ICU_READY = 2, /**< Ready. */
+ ICU_WAITING = 3, /**< Waiting for first front. */
+ ICU_ACTIVE = 4 /**< First front detected. */
+} icustate_t;
+
+/**
+ * @brief Type of a structure representing an ICU driver.
+ */
+typedef struct ICUDriver ICUDriver;
+
+/**
+ * @brief ICU notification callback type.
+ *
+ * @param[in] icup pointer to a @p ICUDriver object
+ */
+typedef void (*icucallback_t)(ICUDriver *icup);
+
+#include "hal_icu_lld.h"
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Starts the input capture.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @iclass
+ */
+#define icuStartCaptureI(icup) do { \
+ icu_lld_start_capture(icup); \
+ (icup)->state = ICU_WAITING; \
+} while (false)
+
+/**
+ * @brief Stops the input capture.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @iclass
+ */
+#define icuStopCaptureI(icup) do { \
+ icu_lld_stop_capture(icup); \
+ (icup)->state = ICU_READY; \
+} while (false)
+
+/**
+ * @brief Enables notifications.
+ * @pre The ICU unit must have been activated using @p icuStart() and the
+ * capture started using @p icuStartCapture().
+ * @note If the notification is already enabled then the call has no effect.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @iclass
+ */
+#define icuEnableNotificationsI(icup) icu_lld_enable_notifications(icup)
+
+/**
+ * @brief Disables notifications.
+ * @pre The ICU unit must have been activated using @p icuStart() and the
+ * capture started using @p icuStartCapture().
+ * @note If the notification is already disabled then the call has no effect.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @iclass
+ */
+#define icuDisableNotificationsI(icup) icu_lld_disable_notifications(icup)
+
+/**
+ * @brief Check on notifications status.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @return The notifications status.
+ * @retval false if notifications are not enabled.
+ * @retval true if notifications are enabled.
+ *
+ * @notapi
+ */
+#define icuAreNotificationsEnabledX(icup) \
+ icu_lld_are_notifications_enabled(icup)
+
+/**
+ * @brief Returns the width of the latest pulse.
+ * @details The pulse width is defined as number of ticks between the start
+ * edge and the stop edge.
+ * @note This function is meant to be invoked from the width capture
+ * callback.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @return The number of ticks.
+ *
+ * @xclass
+ */
+#define icuGetWidthX(icup) icu_lld_get_width(icup)
+
+/**
+ * @brief Returns the width of the latest cycle.
+ * @details The cycle width is defined as number of ticks between a start
+ * edge and the next start edge.
+ * @note This function is meant to be invoked from the width capture
+ * callback.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @return The number of ticks.
+ *
+ * @xclass
+ */
+#define icuGetPeriodX(icup) icu_lld_get_period(icup)
+/** @} */
+
+/**
+ * @name Low level driver helper macros
+ * @{
+ */
+/**
+ * @brief Common ISR code, ICU width event.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @notapi
+ */
+#define _icu_isr_invoke_width_cb(icup) do { \
+ if (((icup)->state == ICU_ACTIVE) && \
+ ((icup)->config->width_cb != NULL)) \
+ (icup)->config->width_cb(icup); \
+} while (0)
+
+/**
+ * @brief Common ISR code, ICU period event.
+ * @note A period event brings the driver into the @p ICU_ACTIVE state.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @notapi
+ */
+#define _icu_isr_invoke_period_cb(icup) do { \
+ if (((icup)->state == ICU_ACTIVE) && \
+ ((icup)->config->period_cb != NULL)) \
+ (icup)->config->period_cb(icup); \
+ (icup)->state = ICU_ACTIVE; \
+} while (0)
+
+/**
+ * @brief Common ISR code, ICU timer overflow event.
+ * @note An overflow always brings the driver back to the @p ICU_WAITING
+ * state.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @notapi
+ */
+#define _icu_isr_invoke_overflow_cb(icup) do { \
+ (icup)->config->overflow_cb(icup); \
+ (icup)->state = ICU_WAITING; \
+} while (0)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void icuInit(void);
+ void icuObjectInit(ICUDriver *icup);
+ void icuStart(ICUDriver *icup, const ICUConfig *config);
+ void icuStop(ICUDriver *icup);
+ void icuStartCapture(ICUDriver *icup);
+ bool icuWaitCapture(ICUDriver *icup);
+ void icuStopCapture(ICUDriver *icup);
+ void icuEnableNotifications(ICUDriver *icup);
+ void icuDisableNotifications(ICUDriver *icup);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_ICU == TRUE */
+
+#endif /* HAL_ICU_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_ioblock.h b/ChibiOS_20.3.2/os/hal/include/hal_ioblock.h
new file mode 100644
index 0000000..c720a4a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_ioblock.h
@@ -0,0 +1,269 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_ioblock.h
+ * @brief I/O block devices access.
+ * @details This header defines an abstract interface useful to access generic
+ * I/O block devices in a standardized way.
+ *
+ * @addtogroup IO_BLOCK
+ * @details This module defines an abstract interface for accessing generic
+ * block devices.
+ * Note that no code is present, just abstract interfaces-like
+ * structures, you should look at the system as to a set of
+ * abstract C++ classes (even if written in C). This system
+ * has then advantage to make the access to block devices
+ * independent from the implementation logic.
+ * @{
+ */
+
+#ifndef HAL_IOBLOCK_H
+#define HAL_IOBLOCK_H
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ BLK_UNINIT = 0, /**< Not initialized. */
+ BLK_STOP = 1, /**< Stopped. */
+ BLK_ACTIVE = 2, /**< Interface active. */
+ BLK_CONNECTING = 3, /**< Connection in progress. */
+ BLK_DISCONNECTING = 4, /**< Disconnection in progress. */
+ BLK_READY = 5, /**< Device ready. */
+ BLK_READING = 6, /**< Read operation in progress. */
+ BLK_WRITING = 7, /**< Write operation in progress. */
+ BLK_SYNCING = 8 /**< Sync. operation in progress. */
+} blkstate_t;
+
+/**
+ * @brief Block device info.
+ */
+typedef struct {
+ uint32_t blk_size; /**< @brief Block size in bytes. */
+ uint32_t blk_num; /**< @brief Total number of blocks. */
+} BlockDeviceInfo;
+
+/**
+ * @brief @p BaseBlockDevice specific methods.
+ */
+#define _base_block_device_methods \
+ _base_object_methods \
+ /* Removable media detection.*/ \
+ bool (*is_inserted)(void *instance); \
+ /* Removable write protection detection.*/ \
+ bool (*is_protected)(void *instance); \
+ /* Connection to the block device.*/ \
+ bool (*connect)(void *instance); \
+ /* Disconnection from the block device.*/ \
+ bool (*disconnect)(void *instance); \
+ /* Reads one or more blocks.*/ \
+ bool (*read)(void *instance, uint32_t startblk, \
+ uint8_t *buffer, uint32_t n); \
+ /* Writes one or more blocks.*/ \
+ bool (*write)(void *instance, uint32_t startblk, \
+ const uint8_t *buffer, uint32_t n); \
+ /* Write operations synchronization.*/ \
+ bool (*sync)(void *instance); \
+ /* Obtains info about the media.*/ \
+ bool (*get_info)(void *instance, BlockDeviceInfo *bdip);
+
+/**
+ * @brief @p BaseBlockDevice specific data.
+ */
+#define _base_block_device_data \
+ _base_object_data \
+ /* Driver state.*/ \
+ blkstate_t state;
+
+/**
+ * @brief @p BaseBlockDevice virtual methods table.
+ */
+struct BaseBlockDeviceVMT {
+ _base_block_device_methods
+};
+
+/**
+ * @extends BaseObject
+ *
+ * @brief Base block device class.
+ * @details This class represents a generic, block-accessible, device.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct BaseBlockDeviceVMT *vmt;
+ _base_block_device_data
+} BaseBlockDevice;
+
+/**
+ * @name Macro Functions (BaseBlockDevice)
+ * @{
+ */
+/**
+ * @brief Returns the driver state.
+ * @note Can be called in ISR context.
+ *
+ * @param[in] ip pointer to a @p BaseBlockDevice or derived class
+ *
+ * @return The driver state.
+ *
+ * @special
+ */
+#define blkGetDriverState(ip) ((ip)->state)
+
+/**
+ * @brief Determines if the device is transferring data.
+ * @note Can be called in ISR context.
+ *
+ * @param[in] ip pointer to a @p BaseBlockDevice or derived class
+ *
+ * @return The driver state.
+ * @retval false the device is not transferring data.
+ * @retval true the device not transferring data.
+ *
+ * @special
+ */
+#define blkIsTransferring(ip) ((((ip)->state) == BLK_CONNECTING) || \
+ (((ip)->state) == BLK_DISCONNECTING) || \
+ (((ip)->state) == BLK_READING) || \
+ (((ip)->state) == BLK_WRITING))
+
+/**
+ * @brief Returns the media insertion status.
+ * @note On some implementations this function can only be called if the
+ * device is not transferring data.
+ * The function @p blkIsTransferring() should be used before calling
+ * this function.
+ *
+ * @param[in] ip pointer to a @p BaseBlockDevice or derived class
+ *
+ * @return The media state.
+ * @retval false media not inserted.
+ * @retval true media inserted.
+ *
+ * @api
+ */
+#define blkIsInserted(ip) ((ip)->vmt->is_inserted(ip))
+
+/**
+ * @brief Returns the media write protection status.
+ *
+ * @param[in] ip pointer to a @p BaseBlockDevice or derived class
+ *
+ * @return The media state.
+ * @retval false writable media.
+ * @retval true non writable media.
+ *
+ * @api
+ */
+#define blkIsWriteProtected(ip) ((ip)->vmt->is_protected(ip))
+
+/**
+ * @brief Performs the initialization procedure on the block device.
+ * @details This function should be performed before I/O operations can be
+ * attempted on the block device and after insertion has been
+ * confirmed using @p blkIsInserted().
+ *
+ * @param[in] ip pointer to a @p BaseBlockDevice or derived class
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @api
+ */
+#define blkConnect(ip) ((ip)->vmt->connect(ip))
+
+/**
+ * @brief Terminates operations on the block device.
+ * @details This operation safely terminates operations on the block device.
+ *
+ * @param[in] ip pointer to a @p BaseBlockDevice or derived class
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @api
+ */
+#define blkDisconnect(ip) ((ip)->vmt->disconnect(ip))
+
+/**
+ * @brief Reads one or more blocks.
+ *
+ * @param[in] ip pointer to a @p BaseBlockDevice or derived class
+ * @param[in] startblk first block to read
+ * @param[out] buf pointer to the read buffer
+ * @param[in] n number of blocks to read
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @api
+ */
+#define blkRead(ip, startblk, buf, n) \
+ ((ip)->vmt->read(ip, startblk, buf, n))
+
+/**
+ * @brief Writes one or more blocks.
+ *
+ * @param[in] ip pointer to a @p BaseBlockDevice or derived class
+ * @param[in] startblk first block to write
+ * @param[out] buf pointer to the write buffer
+ * @param[in] n number of blocks to write
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @api
+ */
+#define blkWrite(ip, startblk, buf, n) \
+ ((ip)->vmt->write(ip, startblk, buf, n))
+
+/**
+ * @brief Ensures write synchronization.
+ *
+ * @param[in] ip pointer to a @p BaseBlockDevice or derived class
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @api
+ */
+#define blkSync(ip) ((ip)->vmt->sync(ip))
+
+/**
+ * @brief Returns a media information structure.
+ *
+ * @param[in] ip pointer to a @p BaseBlockDevice or derived class
+ * @param[out] bdip pointer to a @p BlockDeviceInfo structure
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @api
+ */
+#define blkGetInfo(ip, bdip) ((ip)->vmt->get_info(ip, bdip))
+
+/** @} */
+
+#endif /* HAL_IOBLOCK_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_mac.h b/ChibiOS_20.3.2/os/hal/include/hal_mac.h
new file mode 100644
index 0000000..00a73a8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_mac.h
@@ -0,0 +1,202 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_mac.h
+ * @brief MAC Driver macros and structures.
+ * @addtogroup MAC
+ * @{
+ */
+
+#ifndef HAL_MAC_H
+#define HAL_MAC_H
+
+#if (HAL_USE_MAC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name MAC configuration options
+ * @{
+ */
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
+#define MAC_USE_ZERO_COPY FALSE
+#endif
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
+#define MAC_USE_EVENTS TRUE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ MAC_UNINIT = 0, /**< Not initialized. */
+ MAC_STOP = 1, /**< Stopped. */
+ MAC_ACTIVE = 2 /**< Active. */
+} macstate_t;
+
+/**
+ * @brief Type of a structure representing a MAC driver.
+ */
+typedef struct MACDriver MACDriver;
+
+#include "hal_mac_lld.h"
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Enables the zero-copy API.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ * @return The pointer to the @p EventSource structure.
+ *
+ * @api
+ */
+#if (MAC_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+#define macGetReceiveEventSource(macp) (&(macp)->rdevent)
+#endif
+
+/**
+ * @brief Writes to a transmit descriptor's stream.
+ *
+ * @param[in] tdp pointer to a @p MACTransmitDescriptor structure
+ * @param[in] buf pointer to the buffer containing the data to be written
+ * @param[in] size number of bytes to be written
+ * @return The number of bytes written into the descriptor's
+ * stream, this value can be less than the amount
+ * specified in the parameter @p size if the maximum frame
+ * size is reached.
+ *
+ * @api
+ */
+#define macWriteTransmitDescriptor(tdp, buf, size) \
+ mac_lld_write_transmit_descriptor(tdp, buf, size)
+
+/**
+ * @brief Reads from a receive descriptor's stream.
+ *
+ * @param[in] rdp pointer to a @p MACReceiveDescriptor structure
+ * @param[in] buf pointer to the buffer that will receive the read data
+ * @param[in] size number of bytes to be read
+ * @return The number of bytes read from the descriptor's stream,
+ * this value can be less than the amount specified in the
+ * parameter @p size if there are no more bytes to read.
+ *
+ * @api
+ */
+#define macReadReceiveDescriptor(rdp, buf, size) \
+ mac_lld_read_receive_descriptor(rdp, buf, size)
+
+#if (MAC_USE_ZERO_COPY == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Returns a pointer to the next transmit buffer in the descriptor
+ * chain.
+ * @note The API guarantees that enough buffers can be requested to fill
+ * a whole frame.
+ *
+ * @param[in] tdp pointer to a @p MACTransmitDescriptor structure
+ * @param[in] size size of the requested buffer. Specify the frame size
+ * on the first call then scale the value down subtracting
+ * the amount of data already copied into the previous
+ * buffers.
+ * @param[out] sizep pointer to variable receiving the real buffer size.
+ * The returned value can be less than the amount
+ * requested, this means that more buffers must be
+ * requested in order to fill the frame data entirely.
+ * @return Pointer to the returned buffer.
+ *
+ * @api
+ */
+#define macGetNextTransmitBuffer(tdp, size, sizep) \
+ mac_lld_get_next_transmit_buffer(tdp, size, sizep)
+
+/**
+ * @brief Returns a pointer to the next receive buffer in the descriptor
+ * chain.
+ * @note The API guarantees that the descriptor chain contains a whole
+ * frame.
+ *
+ * @param[in] rdp pointer to a @p MACReceiveDescriptor structure
+ * @param[out] sizep pointer to variable receiving the buffer size, it is
+ * zero when the last buffer has already been returned.
+ * @return Pointer to the returned buffer.
+ * @retval NULL if the buffer chain has been entirely scanned.
+ *
+ * @api
+ */
+#define macGetNextReceiveBuffer(rdp, sizep) \
+ mac_lld_get_next_receive_buffer(rdp, sizep)
+#endif /* MAC_USE_ZERO_COPY */
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void macInit(void);
+ void macObjectInit(MACDriver *macp);
+ void macStart(MACDriver *macp, const MACConfig *config);
+ void macStop(MACDriver *macp);
+ void macSetAddress(MACDriver *macp, const uint8_t *p);
+ msg_t macWaitTransmitDescriptor(MACDriver *macp,
+ MACTransmitDescriptor *tdp,
+ sysinterval_t timeout);
+ void macReleaseTransmitDescriptor(MACTransmitDescriptor *tdp);
+ msg_t macWaitReceiveDescriptor(MACDriver *macp,
+ MACReceiveDescriptor *rdp,
+ sysinterval_t timeout);
+ void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp);
+ bool macPollLinkStatus(MACDriver *macp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_MAC == TRUE */
+
+#endif /* HAL_MAC_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_mii.h b/ChibiOS_20.3.2/os/hal/include/hal_mii.h
new file mode 100644
index 0000000..80cbfd2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_mii.h
@@ -0,0 +1,176 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_mii.h
+ * @brief MII macros and structures.
+ *
+ * @addtogroup MII
+ * @{
+ */
+
+#ifndef MII_H
+#define MII_H
+
+/**
+ * @name Generic MII registers
+ * @{
+ */
+#define MII_BMCR 0x00 /**< Basic mode control register. */
+#define MII_BMSR 0x01 /**< Basic mode status register. */
+#define MII_PHYSID1 0x02 /**< PHYS ID 1. */
+#define MII_PHYSID2 0x03 /**< PHYS ID 2. */
+#define MII_ADVERTISE 0x04 /**< Advertisement control reg. */
+#define MII_LPA 0x05 /**< Link partner ability reg. */
+#define MII_EXPANSION 0x06 /**< Expansion register. */
+#define MII_ANNPTR 0x07 /**< 1000BASE-T control. */
+#define MII_CTRL1000 0x09 /**< 1000BASE-T control. */
+#define MII_STAT1000 0x0a /**< 1000BASE-T status. */
+#define MII_ESTATUS 0x0f /**< Extended Status. */
+#define MII_PHYSTS 0x10 /**< PHY Status register. */
+#define MII_MICR 0x11 /**< MII Interrupt ctrl register. */
+#define MII_DCOUNTER 0x12 /**< Disconnect counter. */
+#define MII_FCSCOUNTER 0x13 /**< False carrier counter. */
+#define MII_NWAYTEST 0x14 /**< N-way auto-neg test reg. */
+#define MII_RERRCOUNTER 0x15 /**< Receive error counter. */
+#define MII_SREVISION 0x16 /**< Silicon revision. */
+#define MII_RESV1 0x17 /**< Reserved. */
+#define MII_LBRERROR 0x18 /**< Lpback, rx, bypass error. */
+#define MII_PHYADDR 0x19 /**< PHY address. */
+#define MII_RESV2 0x1a /**< Reserved. */
+#define MII_TPISTATUS 0x1b /**< TPI status for 10Mbps. */
+#define MII_NCONFIG 0x1c /**< Network interface config. */
+/** @} */
+
+/**
+ * @name Basic mode control register
+ * @{
+ */
+#define BMCR_RESV 0x007f /**< Unused. */
+#define BMCR_CTST 0x0080 /**< Collision test. */
+#define BMCR_FULLDPLX 0x0100 /**< Full duplex. */
+#define BMCR_ANRESTART 0x0200 /**< Auto negotiation restart. */
+#define BMCR_ISOLATE 0x0400 /**< Disconnect DP83840 from MII. */
+#define BMCR_PDOWN 0x0800 /**< Powerdown. */
+#define BMCR_ANENABLE 0x1000 /**< Enable auto negotiation. */
+#define BMCR_SPEED100 0x2000 /**< Select 100Mbps. */
+#define BMCR_LOOPBACK 0x4000 /**< TXD loopback bit. */
+#define BMCR_RESET 0x8000 /**< Reset. */
+/** @} */
+
+/**
+ * @name Basic mode status register
+ * @{
+ */
+#define BMSR_ERCAP 0x0001 /**< Ext-reg capability. */
+#define BMSR_JCD 0x0002 /**< Jabber detected. */
+#define BMSR_LSTATUS 0x0004 /**< Link status. */
+#define BMSR_ANEGCAPABLE 0x0008 /**< Able to do auto-negotiation. */
+#define BMSR_RFAULT 0x0010 /**< Remote fault detected. */
+#define BMSR_ANEGCOMPLETE 0x0020 /**< Auto-negotiation complete. */
+#define BMSR_MFPRESUPPCAP 0x0040 /**< Able to suppress preamble. */
+#define BMSR_RESV 0x0780 /**< Unused. */
+#define BMSR_10HALF 0x0800 /**< Can do 10mbps, half-duplex. */
+#define BMSR_10FULL 0x1000 /**< Can do 10mbps, full-duplex. */
+#define BMSR_100HALF 0x2000 /**< Can do 100mbps, half-duplex. */
+#define BMSR_100FULL 0x4000 /**< Can do 100mbps, full-duplex. */
+#define BMSR_100BASE4 0x8000 /**< Can do 100mbps, 4k packets. */
+/** @} */
+
+/**
+ * @name Advertisement control register
+ * @{
+ */
+#define ADVERTISE_SLCT 0x001f /**< Selector bits. */
+#define ADVERTISE_CSMA 0x0001 /**< Only selector supported. */
+#define ADVERTISE_10HALF 0x0020 /**< Try for 10mbps half-duplex. */
+#define ADVERTISE_10FULL 0x0040 /**< Try for 10mbps full-duplex. */
+#define ADVERTISE_100HALF 0x0080 /**< Try for 100mbps half-duplex. */
+#define ADVERTISE_100FULL 0x0100 /**< Try for 100mbps full-duplex. */
+#define ADVERTISE_100BASE4 0x0200 /**< Try for 100mbps 4k packets. */
+#define ADVERTISE_PAUSE_CAP 0x0400 /**< Try for pause. */
+#define ADVERTISE_PAUSE_ASYM 0x0800 /**< Try for asymetric pause. */
+#define ADVERTISE_RESV 0x1000 /**< Unused. */
+#define ADVERTISE_RFAULT 0x2000 /**< Say we can detect faults. */
+#define ADVERTISE_LPACK 0x4000 /**< Ack link partners response. */
+#define ADVERTISE_NPAGE 0x8000 /**< Next page bit. */
+
+#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
+ ADVERTISE_CSMA)
+#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
+ ADVERTISE_100HALF | ADVERTISE_100FULL)
+/** @} */
+
+/**
+ * @name Link partner ability register
+ * @{
+ */
+#define LPA_SLCT 0x001f /**< Same as advertise selector. */
+#define LPA_10HALF 0x0020 /**< Can do 10mbps half-duplex. */
+#define LPA_10FULL 0x0040 /**< Can do 10mbps full-duplex. */
+#define LPA_100HALF 0x0080 /**< Can do 100mbps half-duplex. */
+#define LPA_100FULL 0x0100 /**< Can do 100mbps full-duplex. */
+#define LPA_100BASE4 0x0200 /**< Can do 100mbps 4k packets. */
+#define LPA_PAUSE_CAP 0x0400 /**< Can pause. */
+#define LPA_PAUSE_ASYM 0x0800 /**< Can pause asymetrically. */
+#define LPA_RESV 0x1000 /**< Unused. */
+#define LPA_RFAULT 0x2000 /**< Link partner faulted. */
+#define LPA_LPACK 0x4000 /**< Link partner acked us. */
+#define LPA_NPAGE 0x8000 /**< Next page bit. */
+
+#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL)
+#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
+/** @} */
+
+/**
+ * @name Expansion register for auto-negotiation
+ * @{
+ */
+#define EXPANSION_NWAY 0x0001 /**< Can do N-way auto-nego. */
+#define EXPANSION_LCWP 0x0002 /**< Got new RX page code word. */
+#define EXPANSION_ENABLENPAGE 0x0004 /**< This enables npage words. */
+#define EXPANSION_NPCAPABLE 0x0008 /**< Link partner supports npage. */
+#define EXPANSION_MFAULTS 0x0010 /**< Multiple faults detected. */
+#define EXPANSION_RESV 0xffe0 /**< Unused. */
+/** @} */
+
+/**
+ * @name N-way test register
+ * @{
+ */
+#define NWAYTEST_RESV1 0x00ff /**< Unused. */
+#define NWAYTEST_LOOPBACK 0x0100 /**< Enable loopback for N-way. */
+#define NWAYTEST_RESV2 0xfe00 /**< Unused. */
+/** @} */
+
+/**
+ * @name PHY identifiers
+ * @{
+ */
+#define MII_DM9161_ID 0x0181b8a0
+#define MII_AM79C875_ID 0x00225540
+#define MII_KSZ8081_ID 0x00221560
+#define MII_KS8721_ID 0x00221610
+#define MII_STE101P_ID 0x00061C50
+#define MII_DP83848I_ID 0x20005C90
+#define MII_LAN8710A_ID 0x0007C0F1
+#define MII_LAN8720_ID 0x0007C0F0
+#define MII_LAN8742A_ID 0x0007C130
+/** @} */
+
+#endif /* MII_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_mmc_spi.h b/ChibiOS_20.3.2/os/hal/include/hal_mmc_spi.h
new file mode 100644
index 0000000..2d596db
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_mmc_spi.h
@@ -0,0 +1,195 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_mmc_spi.h
+ * @brief MMC over SPI driver header.
+ *
+ * @addtogroup MMC_SPI
+ * @{
+ */
+
+#ifndef HAL_MMC_SPI_H
+#define HAL_MMC_SPI_H
+
+#if (HAL_USE_MMC_SPI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+#define MMC_CMD0_RETRY 10U
+#define MMC_CMD1_RETRY 100U
+#define MMC_ACMD41_RETRY 100U
+#define MMC_WAIT_DATA 10000U
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name MMC_SPI configuration options
+ * @{
+ */
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ * This option is recommended also if the SPI driver does not
+ * use a DMA channel and heavily loads the CPU.
+ */
+#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
+#define MMC_NICE_WAITING TRUE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if (HAL_USE_SPI == FALSE) || (SPI_USE_WAIT == FALSE)
+#error "MMC_SPI driver requires HAL_USE_SPI and SPI_USE_WAIT"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief MMC/SD over SPI driver configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief SPI driver associated to this MMC driver.
+ */
+ SPIDriver *spip;
+ /**
+ * @brief SPI low speed configuration used during initialization.
+ */
+ const SPIConfig *lscfg;
+ /**
+ * @brief SPI high speed configuration used during transfers.
+ */
+ const SPIConfig *hscfg;
+} MMCConfig;
+
+/**
+ * @brief @p MMCDriver specific methods.
+ */
+#define _mmc_driver_methods \
+ _mmcsd_block_device_methods
+
+/**
+ * @extends MMCSDBlockDeviceVMT
+ *
+ * @brief @p MMCDriver virtual methods table.
+ */
+struct MMCDriverVMT {
+ _mmc_driver_methods
+};
+
+/**
+ * @extends MMCSDBlockDevice
+ *
+ * @brief Structure representing a MMC/SD over SPI driver.
+ */
+typedef struct {
+ /**
+ * @brief Virtual Methods Table.
+ */
+ const struct MMCDriverVMT *vmt;
+ _mmcsd_block_device_data
+ /**
+ * @brief Current configuration data.
+ */
+ const MMCConfig *config;
+ /**
+ * @brief Addresses use blocks instead of bytes.
+ */
+ bool block_addresses;
+} MMCDriver;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Returns the card insertion status.
+ * @note This macro wraps a low level function named
+ * @p sdc_lld_is_card_inserted(), this function must be
+ * provided by the application because it is not part of the
+ * SDC driver.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ * @return The card state.
+ * @retval false card not inserted.
+ * @retval true card inserted.
+ *
+ * @api
+ */
+#define mmcIsCardInserted(mmcp) mmc_lld_is_card_inserted(mmcp)
+
+/**
+ * @brief Returns the write protect status.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ * @return The card state.
+ * @retval false card not inserted.
+ * @retval true card inserted.
+ *
+ * @api
+ */
+#define mmcIsWriteProtected(mmcp) mmc_lld_is_write_protected(mmcp)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void mmcInit(void);
+ void mmcObjectInit(MMCDriver *mmcp);
+ void mmcStart(MMCDriver *mmcp, const MMCConfig *config);
+ void mmcStop(MMCDriver *mmcp);
+ bool mmcConnect(MMCDriver *mmcp);
+ bool mmcDisconnect(MMCDriver *mmcp);
+ bool mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk);
+ bool mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer);
+ bool mmcStopSequentialRead(MMCDriver *mmcp);
+ bool mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk);
+ bool mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer);
+ bool mmcStopSequentialWrite(MMCDriver *mmcp);
+ bool mmcSync(MMCDriver *mmcp);
+ bool mmcGetInfo(MMCDriver *mmcp, BlockDeviceInfo *bdip);
+ bool mmcErase(MMCDriver *mmcp, uint32_t startblk, uint32_t endblk);
+ bool mmc_lld_is_card_inserted(MMCDriver *mmcp);
+ bool mmc_lld_is_write_protected(MMCDriver *mmcp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_MMC_SPI == TRUE */
+
+#endif /* HAL_MMC_SPI_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_mmcsd.h b/ChibiOS_20.3.2/os/hal/include/hal_mmcsd.h
new file mode 100644
index 0000000..ac2701f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_mmcsd.h
@@ -0,0 +1,498 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_mmcsd.h
+ * @brief MMC/SD cards common header.
+ * @details This header defines an abstract interface useful to access MMC/SD
+ * I/O block devices in a standardized way.
+ *
+ * @addtogroup MMCSD
+ * @{
+ */
+
+#ifndef HAL_MMCSD_H
+#define HAL_MMCSD_H
+
+#if (HAL_USE_MMC_SPI == TRUE) || (HAL_USE_SDC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Fixed block size for MMC/SD block devices.
+ */
+#define MMCSD_BLOCK_SIZE 512U
+
+/**
+ * @brief Mask of error bits in R1 responses.
+ */
+#define MMCSD_R1_ERROR_MASK 0xFDFFE008U
+
+/**
+ * @brief Fixed pattern for CMD8.
+ */
+#define MMCSD_CMD8_PATTERN 0x000001AAU
+
+/**
+ * @name SD/MMC status conditions
+ * @{
+ */
+#define MMCSD_STS_IDLE 0U
+#define MMCSD_STS_READY 1U
+#define MMCSD_STS_IDENT 2U
+#define MMCSD_STS_STBY 3U
+#define MMCSD_STS_TRAN 4U
+#define MMCSD_STS_DATA 5U
+#define MMCSD_STS_RCV 6U
+#define MMCSD_STS_PRG 7U
+#define MMCSD_STS_DIS 8U
+/** @} */
+
+/**
+ * @name SD/MMC commands
+ * @{
+ */
+#define MMCSD_CMD_GO_IDLE_STATE 0U
+#define MMCSD_CMD_INIT 1U
+#define MMCSD_CMD_ALL_SEND_CID 2U
+#define MMCSD_CMD_SEND_RELATIVE_ADDR 3U
+#define MMCSD_CMD_SET_BUS_WIDTH 6U
+#define MMCSD_CMD_SWITCH MMCSD_CMD_SET_BUS_WIDTH
+#define MMCSD_CMD_SEL_DESEL_CARD 7U
+#define MMCSD_CMD_SEND_IF_COND 8U
+#define MMCSD_CMD_SEND_EXT_CSD MMCSD_CMD_SEND_IF_COND
+#define MMCSD_CMD_SEND_CSD 9U
+#define MMCSD_CMD_SEND_CID 10U
+#define MMCSD_CMD_STOP_TRANSMISSION 12U
+#define MMCSD_CMD_SEND_STATUS 13U
+#define MMCSD_CMD_SET_BLOCKLEN 16U
+#define MMCSD_CMD_READ_SINGLE_BLOCK 17U
+#define MMCSD_CMD_READ_MULTIPLE_BLOCK 18U
+#define MMCSD_CMD_SET_BLOCK_COUNT 23U
+#define MMCSD_CMD_WRITE_BLOCK 24U
+#define MMCSD_CMD_WRITE_MULTIPLE_BLOCK 25U
+#define MMCSD_CMD_ERASE_RW_BLK_START 32U
+#define MMCSD_CMD_ERASE_RW_BLK_END 33U
+#define MMCSD_CMD_ERASE 38U
+#define MMCSD_CMD_APP_OP_COND 41U
+#define MMCSD_CMD_LOCK_UNLOCK 42U
+#define MMCSD_CMD_APP_CMD 55U
+#define MMCSD_CMD_READ_OCR 58U
+/** @} */
+
+/**
+ * @name CSD record offsets
+ */
+/**
+ * @brief Slice position of values in CSD register.
+ */
+/* CSD for MMC */
+#define MMCSD_CSD_MMC_CSD_STRUCTURE_SLICE 127U, 126U
+#define MMCSD_CSD_MMC_SPEC_VERS_SLICE 125U, 122U
+#define MMCSD_CSD_MMC_TAAC_SLICE 119U, 112U
+#define MMCSD_CSD_MMC_NSAC_SLICE 111U, 104U
+#define MMCSD_CSD_MMC_TRAN_SPEED_SLICE 103U, 96U
+#define MMCSD_CSD_MMC_CCC_SLICE 95U, 84U
+#define MMCSD_CSD_MMC_READ_BL_LEN_SLICE 83U, 80U
+#define MMCSD_CSD_MMC_READ_BL_PARTIAL_SLICE 79U, 79U
+#define MMCSD_CSD_MMC_WRITE_BLK_MISALIGN_SLICE 78U, 78U
+#define MMCSD_CSD_MMC_READ_BLK_MISALIGN_SLICE 77U, 77U
+#define MMCSD_CSD_MMC_DSR_IMP_SLICE 76U, 76U
+#define MMCSD_CSD_MMC_C_SIZE_SLICE 73U, 62U
+#define MMCSD_CSD_MMC_VDD_R_CURR_MIN_SLICE 61U, 59U
+#define MMCSD_CSD_MMC_VDD_R_CURR_MAX_SLICE 58U, 56U
+#define MMCSD_CSD_MMC_VDD_W_CURR_MIN_SLICE 55U, 53U
+#define MMCSD_CSD_MMC_VDD_W_CURR_MAX_SLICE 52U, 50U
+#define MMCSD_CSD_MMC_C_SIZE_MULT_SLICE 49U, 47U
+#define MMCSD_CSD_MMC_ERASE_GRP_SIZE_SLICE 46U, 42U
+#define MMCSD_CSD_MMC_ERASE_GRP_MULT_SLICE 41U, 37U
+#define MMCSD_CSD_MMC_WP_GRP_SIZE_SLICE 36U, 32U
+#define MMCSD_CSD_MMC_WP_GRP_ENABLE_SLICE 31U, 31U
+#define MMCSD_CSD_MMC_DEFAULT_ECC_SLICE 30U, 29U
+#define MMCSD_CSD_MMC_R2W_FACTOR_SLICE 28U, 26U
+#define MMCSD_CSD_MMC_WRITE_BL_LEN_SLICE 25U, 22U
+#define MMCSD_CSD_MMC_WRITE_BL_PARTIAL_SLICE 21U, 21U
+#define MMCSD_CSD_MMC_CONTENT_PROT_APP_SLICE 16U, 16U
+#define MMCSD_CSD_MMC_FILE_FORMAT_GRP_SLICE 15U, 15U
+#define MMCSD_CSD_MMC_COPY_SLICE 14U, 14U
+#define MMCSD_CSD_MMC_PERM_WRITE_PROTECT_SLICE 13U, 13U
+#define MMCSD_CSD_MMC_TMP_WRITE_PROTECT_SLICE 12U, 12U
+#define MMCSD_CSD_MMC_FILE_FORMAT_SLICE 11U, 10U
+#define MMCSD_CSD_MMC_ECC_SLICE 9U, 8U
+#define MMCSD_CSD_MMC_CRC_SLICE 7U, 1U
+
+/* CSD version 2.0 */
+#define MMCSD_CSD_20_CRC_SLICE 7U, 1U
+#define MMCSD_CSD_20_FILE_FORMAT_SLICE 11U, 10U
+#define MMCSD_CSD_20_TMP_WRITE_PROTECT_SLICE 12U, 12U
+#define MMCSD_CSD_20_PERM_WRITE_PROTECT_SLICE 13U, 13U
+#define MMCSD_CSD_20_COPY_SLICE 14U, 14U
+#define MMCSD_CSD_20_FILE_FORMAT_GRP_SLICE 15U, 15U
+#define MMCSD_CSD_20_WRITE_BL_PARTIAL_SLICE 21U, 21U
+#define MMCSD_CSD_20_WRITE_BL_LEN_SLICE 25U, 12U
+#define MMCSD_CSD_20_R2W_FACTOR_SLICE 28U, 26U
+#define MMCSD_CSD_20_WP_GRP_ENABLE_SLICE 31U, 31U
+#define MMCSD_CSD_20_WP_GRP_SIZE_SLICE 38U, 32U
+#define MMCSD_CSD_20_ERASE_SECTOR_SIZE_SLICE 45U, 39U
+#define MMCSD_CSD_20_ERASE_BLK_EN_SLICE 46U, 46U
+#define MMCSD_CSD_20_C_SIZE_SLICE 69U, 48U
+#define MMCSD_CSD_20_DSR_IMP_SLICE 76U, 76U
+#define MMCSD_CSD_20_READ_BLK_MISALIGN_SLICE 77U, 77U
+#define MMCSD_CSD_20_WRITE_BLK_MISALIGN_SLICE 78U, 78U
+#define MMCSD_CSD_20_READ_BL_PARTIAL_SLICE 79U, 79U
+#define MMCSD_CSD_20_READ_BL_LEN_SLICE 83U, 80U
+#define MMCSD_CSD_20_CCC_SLICE 95U, 84U
+#define MMCSD_CSD_20_TRANS_SPEED_SLICE 103U, 96U
+#define MMCSD_CSD_20_NSAC_SLICE 111U, 104U
+#define MMCSD_CSD_20_TAAC_SLICE 119U, 112U
+#define MMCSD_CSD_20_CSD_STRUCTURE_SLICE 127U, 126U
+
+/* CSD version 1.0 */
+#define MMCSD_CSD_10_CRC_SLICE MMCSD_CSD_20_CRC_SLICE
+#define MMCSD_CSD_10_FILE_FORMAT_SLICE MMCSD_CSD_20_FILE_FORMAT_SLICE
+#define MMCSD_CSD_10_TMP_WRITE_PROTECT_SLICE MMCSD_CSD_20_TMP_WRITE_PROTECT_SLICE
+#define MMCSD_CSD_10_PERM_WRITE_PROTECT_SLICE MMCSD_CSD_20_PERM_WRITE_PROTECT_SLICE
+#define MMCSD_CSD_10_COPY_SLICE MMCSD_CSD_20_COPY_SLICE
+#define MMCSD_CSD_10_FILE_FORMAT_GRP_SLICE MMCSD_CSD_20_FILE_FORMAT_GRP_SLICE
+#define MMCSD_CSD_10_WRITE_BL_PARTIAL_SLICE MMCSD_CSD_20_WRITE_BL_PARTIAL_SLICE
+#define MMCSD_CSD_10_WRITE_BL_LEN_SLICE MMCSD_CSD_20_WRITE_BL_LEN_SLICE
+#define MMCSD_CSD_10_R2W_FACTOR_SLICE MMCSD_CSD_20_R2W_FACTOR_SLICE
+#define MMCSD_CSD_10_WP_GRP_ENABLE_SLICE MMCSD_CSD_20_WP_GRP_ENABLE_SLICE
+#define MMCSD_CSD_10_WP_GRP_SIZE_SLICE MMCSD_CSD_20_WP_GRP_SIZE_SLICE
+#define MMCSD_CSD_10_ERASE_SECTOR_SIZE_SLICE MMCSD_CSD_20_ERASE_SECTOR_SIZE_SLICE
+#define MMCSD_CSD_10_ERASE_BLK_EN_SLICE MMCSD_CSD_20_ERASE_BLK_EN_SLICE
+#define MMCSD_CSD_10_C_SIZE_MULT_SLICE 49U, 47U
+#define MMCSD_CSD_10_VDD_W_CURR_MAX_SLICE 52U, 50U
+#define MMCSD_CSD_10_VDD_W_CURR_MIN_SLICE 55U, 53U
+#define MMCSD_CSD_10_VDD_R_CURR_MAX_SLICE 58U, 56U
+#define MMCSD_CSD_10_VDD_R_CURR_MIX_SLICE 61U, 59U
+#define MMCSD_CSD_10_C_SIZE_SLICE 73U, 62U
+#define MMCSD_CSD_10_DSR_IMP_SLICE MMCSD_CSD_20_DSR_IMP_SLICE
+#define MMCSD_CSD_10_READ_BLK_MISALIGN_SLICE MMCSD_CSD_20_READ_BLK_MISALIGN_SLICE
+#define MMCSD_CSD_10_WRITE_BLK_MISALIGN_SLICE MMCSD_CSD_20_WRITE_BLK_MISALIGN_SLICE
+#define MMCSD_CSD_10_READ_BL_PARTIAL_SLICE MMCSD_CSD_20_READ_BL_PARTIAL_SLICE
+#define MMCSD_CSD_10_READ_BL_LEN_SLICE 83U, 80U
+#define MMCSD_CSD_10_CCC_SLICE MMCSD_CSD_20_CCC_SLICE
+#define MMCSD_CSD_10_TRANS_SPEED_SLICE MMCSD_CSD_20_TRANS_SPEED_SLICE
+#define MMCSD_CSD_10_NSAC_SLICE MMCSD_CSD_20_NSAC_SLICE
+#define MMCSD_CSD_10_TAAC_SLICE MMCSD_CSD_20_TAAC_SLICE
+#define MMCSD_CSD_10_CSD_STRUCTURE_SLICE MMCSD_CSD_20_CSD_STRUCTURE_SLICE
+/** @} */
+
+/**
+ * @name CID record offsets
+ */
+/**
+ * @brief Slice position of values in CID register.
+ */
+/* CID for SDC */
+#define MMCSD_CID_SDC_CRC_SLICE 7U, 1U
+#define MMCSD_CID_SDC_MDT_M_SLICE 11U, 8U
+#define MMCSD_CID_SDC_MDT_Y_SLICE 19U, 12U
+#define MMCSD_CID_SDC_PSN_SLICE 55U, 24U
+#define MMCSD_CID_SDC_PRV_M_SLICE 59U, 56U
+#define MMCSD_CID_SDC_PRV_N_SLICE 63U, 60U
+#define MMCSD_CID_SDC_PNM0_SLICE 71U, 64U
+#define MMCSD_CID_SDC_PNM1_SLICE 79U, 72U
+#define MMCSD_CID_SDC_PNM2_SLICE 87U, 80U
+#define MMCSD_CID_SDC_PNM3_SLICE 95U, 88U
+#define MMCSD_CID_SDC_PNM4_SLICE 103U, 96U
+#define MMCSD_CID_SDC_OID_SLICE 119U, 104U
+#define MMCSD_CID_SDC_MID_SLICE 127U, 120U
+
+/* CID for MMC */
+#define MMCSD_CID_MMC_CRC_SLICE 7U, 1U
+#define MMCSD_CID_MMC_MDT_Y_SLICE 11U, 8U
+#define MMCSD_CID_MMC_MDT_M_SLICE 15U, 12U
+#define MMCSD_CID_MMC_PSN_SLICE 47U, 16U
+#define MMCSD_CID_MMC_PRV_M_SLICE 51U, 48U
+#define MMCSD_CID_MMC_PRV_N_SLICE 55U, 52U
+#define MMCSD_CID_MMC_PNM0_SLICE 63U, 56U
+#define MMCSD_CID_MMC_PNM1_SLICE 71U, 64U
+#define MMCSD_CID_MMC_PNM2_SLICE 79U, 72U
+#define MMCSD_CID_MMC_PNM3_SLICE 87U, 80U
+#define MMCSD_CID_MMC_PNM4_SLICE 95U, 88U
+#define MMCSD_CID_MMC_PNM5_SLICE 103U, 96U
+#define MMCSD_CID_MMC_OID_SLICE 119U, 104U
+#define MMCSD_CID_MMC_MID_SLICE 127U, 120U
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief @p MMCSDBlockDevice specific methods.
+ */
+#define _mmcsd_block_device_methods \
+ _base_block_device_methods
+
+/**
+ * @brief @p MMCSDBlockDevice specific data.
+ * @note It is empty because @p MMCSDBlockDevice is only an interface
+ * without implementation.
+ */
+#define _mmcsd_block_device_data \
+ _base_block_device_data \
+ /* Card CID.*/ \
+ uint32_t cid[4]; \
+ /* Card CSD.*/ \
+ uint32_t csd[4]; \
+ /* Total number of blocks in card.*/ \
+ uint32_t capacity;
+
+/**
+ * @extends BaseBlockDeviceVMT
+ *
+ * @brief @p MMCSDBlockDevice virtual methods table.
+ */
+struct MMCSDBlockDeviceVMT {
+ _base_block_device_methods
+};
+
+/**
+ * @extends BaseBlockDevice
+ *
+ * @brief MCC/SD block device class.
+ * @details This class represents a, block-accessible, MMC/SD device.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct MMCSDBlockDeviceVMT *vmt;
+ _mmcsd_block_device_data
+} MMCSDBlockDevice;
+
+/**
+ * @brief Unpacked CID register from SDC.
+ */
+typedef struct {
+ uint8_t mid;
+ uint16_t oid;
+ char pnm[5];
+ uint8_t prv_n;
+ uint8_t prv_m;
+ uint32_t psn;
+ uint8_t mdt_m;
+ uint16_t mdt_y;
+ uint8_t crc;
+} unpacked_sdc_cid_t;
+
+/**
+ * @brief Unpacked CID register from MMC.
+ */
+typedef struct {
+ uint8_t mid;
+ uint16_t oid;
+ char pnm[6];
+ uint8_t prv_n;
+ uint8_t prv_m;
+ uint32_t psn;
+ uint8_t mdt_m;
+ uint16_t mdt_y;
+ uint8_t crc;
+} unpacked_mmc_cid_t;
+
+/**
+ * @brief Unpacked CSD v1.0 register from SDC.
+ */
+typedef struct {
+ uint8_t csd_structure;
+ uint8_t taac;
+ uint8_t nsac;
+ uint8_t tran_speed;
+ uint16_t ccc;
+ uint8_t read_bl_len;
+ uint8_t read_bl_partial;
+ uint8_t write_blk_misalign;
+ uint8_t read_blk_misalign;
+ uint8_t dsr_imp;
+ uint16_t c_size;
+ uint8_t vdd_r_curr_min;
+ uint8_t vdd_r_curr_max;
+ uint8_t vdd_w_curr_min;
+ uint8_t vdd_w_curr_max;
+ uint8_t c_size_mult;
+ uint8_t erase_blk_en;
+ uint8_t erase_sector_size;
+ uint8_t wp_grp_size;
+ uint8_t wp_grp_enable;
+ uint8_t r2w_factor;
+ uint8_t write_bl_len;
+ uint8_t write_bl_partial;
+ uint8_t file_format_grp;
+ uint8_t copy;
+ uint8_t perm_write_protect;
+ uint8_t tmp_write_protect;
+ uint8_t file_format;
+ uint8_t crc;
+} unpacked_sdc_csd_10_t;
+
+/**
+ * @brief Unpacked CSD v2.0 register from SDC.
+ */
+typedef struct {
+ uint8_t csd_structure;
+ uint8_t taac;
+ uint8_t nsac;
+ uint8_t tran_speed;
+ uint16_t ccc;
+ uint8_t read_bl_len;
+ uint8_t read_bl_partial;
+ uint8_t write_blk_misalign;
+ uint8_t read_blk_misalign;
+ uint8_t dsr_imp;
+ uint32_t c_size;
+ uint8_t erase_blk_en;
+ uint8_t erase_sector_size;
+ uint8_t wp_grp_size;
+ uint8_t wp_grp_enable;
+ uint8_t r2w_factor;
+ uint8_t write_bl_len;
+ uint8_t write_bl_partial;
+ uint8_t file_format_grp;
+ uint8_t copy;
+ uint8_t perm_write_protect;
+ uint8_t tmp_write_protect;
+ uint8_t file_format;
+ uint8_t crc;
+} unpacked_sdc_csd_20_t;
+
+/**
+ * @brief Unpacked CSD register from MMC.
+ */
+typedef struct {
+ uint8_t csd_structure;
+ uint8_t spec_vers;
+ uint8_t taac;
+ uint8_t nsac;
+ uint8_t tran_speed;
+ uint16_t ccc;
+ uint8_t read_bl_len;
+ uint8_t read_bl_partial;
+ uint8_t write_blk_misalign;
+ uint8_t read_blk_misalign;
+ uint8_t dsr_imp;
+ uint16_t c_size;
+ uint8_t vdd_r_curr_min;
+ uint8_t vdd_r_curr_max;
+ uint8_t vdd_w_curr_min;
+ uint8_t vdd_w_curr_max;
+ uint8_t c_size_mult;
+ uint8_t erase_grp_size;
+ uint8_t erase_grp_mult;
+ uint8_t wp_grp_size;
+ uint8_t wp_grp_enable;
+ uint8_t default_ecc;
+ uint8_t r2w_factor;
+ uint8_t write_bl_len;
+ uint8_t write_bl_partial;
+ uint8_t content_prot_app;
+ uint8_t file_format_grp;
+ uint8_t copy;
+ uint8_t perm_write_protect;
+ uint8_t tmp_write_protect;
+ uint8_t file_format;
+ uint8_t ecc;
+ uint8_t crc;
+} unpacked_mmc_csd_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name R1 response utilities
+ * @{
+ */
+/**
+ * @brief Evaluates to @p true if the R1 response contains error flags.
+ *
+ * @param[in] r1 the r1 response
+ */
+#define MMCSD_R1_ERROR(r1) (((r1) & MMCSD_R1_ERROR_MASK) != 0U)
+
+/**
+ * @brief Returns the status field of an R1 response.
+ *
+ * @param[in] r1 the r1 response
+ */
+#define MMCSD_R1_STS(r1) (((r1) >> 9U) & 15U)
+
+/**
+ * @brief Evaluates to @p true if the R1 response indicates a locked card.
+ *
+ * @param[in] r1 the r1 response
+ */
+#define MMCSD_R1_IS_CARD_LOCKED(r1) ((((r1) >> 21U) & 1U) != 0U)
+/** @} */
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Returns the card capacity in blocks.
+ *
+ * @param[in] ip pointer to a @p MMCSDBlockDevice or derived class
+ *
+ * @return The card capacity.
+ *
+ * @api
+ */
+#define mmcsdGetCardCapacity(ip) ((ip)->capacity)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ uint32_t _mmcsd_get_slice(const uint32_t *data,
+ uint32_t end,
+ uint32_t start);
+ uint32_t _mmcsd_get_capacity(const uint32_t *csd);
+ uint32_t _mmcsd_get_capacity_ext(const uint8_t *ext_csd);
+ void _mmcsd_unpack_sdc_cid(const MMCSDBlockDevice *sdcp,
+ unpacked_sdc_cid_t *cidsdc);
+ void _mmcsd_unpack_mmc_cid(const MMCSDBlockDevice *sdcp,
+ unpacked_mmc_cid_t *cidmmc);
+ void _mmcsd_unpack_csd_mmc(const MMCSDBlockDevice *sdcp,
+ unpacked_mmc_csd_t *csdmmc);
+ void _mmcsd_unpack_csd_v10(const MMCSDBlockDevice *sdcp,
+ unpacked_sdc_csd_10_t *csd10);
+ void _mmcsd_unpack_csd_v20(const MMCSDBlockDevice *sdcp,
+ unpacked_sdc_csd_20_t *csd20);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_MMC_SPI == TRUE || HAL_USE_MMC_SDC == TRUE */
+
+#endif /* HAL_MMCSD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_objects.h b/ChibiOS_20.3.2/os/hal/include/hal_objects.h
new file mode 100644
index 0000000..59c3884
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_objects.h
@@ -0,0 +1,86 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_objects.h
+ * @brief Base object.
+ * @details This header defines a base object that is the root for the
+ * inheritance system.
+ *
+ * @addtogroup HAL_BASE_OBJECT
+ * @details HAL uses concepts of Object Oriented Programming even if it
+ * is written in C. Things like simple inheritance, multiple
+ * inheritance and interfaces are used through the system.
+ * This module defines a "base object" that is the ancestor of
+ * all classes in the system.
+ * @{
+ */
+
+#ifndef HAL_OBJECTS_H
+#define HAL_OBJECTS_H
+
+/**
+ * @brief @p BaseObject specific methods.
+ * @note This object defines no methods.
+ */
+#define _base_object_methods \
+ /* Instance offset, used for multiple inheritance, normally zero. It
+ represents the offset between the current object and the container
+ object*/ \
+ size_t instance_offset;
+
+/**
+ * @brief @p BaseObject specific data.
+ * @note This object defines no data.
+ */
+#define _base_object_data
+
+/**
+ * @brief @p BaseObject virtual methods table.
+ */
+struct BaseObjectVMT {
+ _base_object_methods
+};
+
+/**
+ * @brief Base stream class.
+ * @details This class represents a generic blocking unbuffered sequential
+ * data stream.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct BaseObjectVMT *vmt;
+ _base_object_data
+} BaseObject;
+
+/**
+ * @name Macro Functions (BaseObject)
+ * @{
+ */
+/**
+ * @brief Returns the instance pointer starting from an interface pointer.
+ *
+ * @param[in] type the type of the instance pointer, it is used for casting
+ * @param[in] ip the interface pointer
+ * @return A pointer to the object implementing the interface
+ */
+#define objGetInstance(type, ip) \
+ (type)(((size_t)(ip)) - (ip)->vmt->instance_offset)
+/** @} */
+
+#endif /* HAL_OBJECTS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_pal.h b/ChibiOS_20.3.2/os/hal/include/hal_pal.h
new file mode 100644
index 0000000..62a2131
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_pal.h
@@ -0,0 +1,1023 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_pal.h
+ * @brief I/O Ports Abstraction Layer macros, types and structures.
+ *
+ * @addtogroup PAL
+ * @{
+ */
+
+#ifndef HAL_PAL_H
+#define HAL_PAL_H
+
+#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Pads mode constants
+ * @{
+ */
+/**
+ * @brief After reset state.
+ * @details The state itself is not specified and is architecture dependent,
+ * it is guaranteed to be equal to the after-reset state. It is
+ * usually an input state.
+ */
+#define PAL_MODE_RESET 0U
+
+/**
+ * @brief Safe state for unconnected pads.
+ * @details The state itself is not specified and is architecture dependent,
+ * it may be mapped on @p PAL_MODE_INPUT_PULLUP,
+ * @p PAL_MODE_INPUT_PULLDOWN or @p PAL_MODE_OUTPUT_PUSHPULL for
+ * example.
+ */
+#define PAL_MODE_UNCONNECTED 1U
+
+/**
+ * @brief Regular input high-Z pad.
+ */
+#define PAL_MODE_INPUT 2U
+
+/**
+ * @brief Input pad with weak pull up resistor.
+ */
+#define PAL_MODE_INPUT_PULLUP 3U
+
+/**
+ * @brief Input pad with weak pull down resistor.
+ */
+#define PAL_MODE_INPUT_PULLDOWN 4U
+
+/**
+ * @brief Analog input mode.
+ */
+#define PAL_MODE_INPUT_ANALOG 5U
+
+/**
+ * @brief Push-pull output pad.
+ */
+#define PAL_MODE_OUTPUT_PUSHPULL 6U
+
+/**
+ * @brief Open-drain output pad.
+ */
+#define PAL_MODE_OUTPUT_OPENDRAIN 7U
+/** @} */
+
+/**
+ * @name Logic level constants
+ * @{
+ */
+/**
+ * @brief Logical low state.
+ */
+#define PAL_LOW 0U
+
+/**
+ * @brief Logical high state.
+ */
+#define PAL_HIGH 1U
+/** @} */
+
+/**
+ * @name PAL event modes
+ * @{
+ */
+#define PAL_EVENT_MODE_EDGES_MASK 3U /**< @brief Mask of edges field. */
+#define PAL_EVENT_MODE_DISABLED 0U /**< @brief Channel disabled. */
+#define PAL_EVENT_MODE_RISING_EDGE 1U /**< @brief Rising edge callback. */
+#define PAL_EVENT_MODE_FALLING_EDGE 2U /**< @brief Falling edge callback. */
+#define PAL_EVENT_MODE_BOTH_EDGES 3U /**< @brief Both edges callback. */
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PAL configuration options
+ * @{
+ */
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__)
+#define PAL_USE_CALLBACKS TRUE
+#endif
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__)
+#define PAL_USE_WAIT TRUE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a PAL event callback.
+ */
+typedef void (*palcallback_t)(void *arg);
+
+#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a PAL event record.
+ */
+typedef struct {
+#if (PAL_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Threads queued for an event.
+ */
+ threads_queue_t threads;
+#endif
+#if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Event callback.
+ */
+ palcallback_t cb;
+ /**
+ * @brief Event callback argument.
+ */
+ void *arg;
+#endif
+} palevent_t;
+#endif
+
+#include "hal_pal_lld.h"
+
+/**
+ * @brief I/O bus descriptor.
+ * @details This structure describes a group of contiguous digital I/O lines
+ * that have to be handled as bus.
+ * @note I/O operations on a bus do not affect I/O lines on the same port but
+ * not belonging to the bus.
+ */
+typedef struct {
+ /**
+ * @brief Port identifier.
+ */
+ ioportid_t portid;
+ /**
+ * @brief Bus mask aligned to port bit 0.
+ * @note The bus mask implicitly define the bus width. A logic AND is
+ * performed on the bus data.
+ */
+ ioportmask_t mask;
+ /**
+ * @brief Offset, within the port, of the least significant bit of the bus.
+ */
+ uint_fast8_t offset;
+} IOBus;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Port bit helper macro.
+ * @details This macro calculates the mask of a bit within a port.
+ *
+ * @param[in] n bit position within the port
+ * @return The bit mask.
+ */
+#if !defined(PAL_PORT_BIT) || defined(__DOXYGEN__)
+#define PAL_PORT_BIT(n) ((ioportmask_t)(1U << (n)))
+#endif
+
+/**
+ * @brief Bits group mask helper.
+ * @details This macro calculates the mask of a bits group.
+ *
+ * @param[in] width group width
+ * @return The group mask.
+ */
+#if !defined(PAL_GROUP_MASK) || defined(__DOXYGEN__)
+#define PAL_GROUP_MASK(width) ((ioportmask_t)(1U << (width)) - 1U)
+#endif
+
+/**
+ * @brief Data part of a static I/O bus initializer.
+ * @details This macro should be used when statically initializing an I/O bus
+ * that is part of a bigger structure.
+ *
+ * @param[in] name name of the IOBus variable
+ * @param[in] port I/O port descriptor
+ * @param[in] width bus width in bits
+ * @param[in] offset bus bit offset within the port
+ */
+#define _IOBUS_DATA(name, port, width, offset) \
+ {port, PAL_GROUP_MASK(width), offset}
+
+/**
+ * @brief Static I/O bus initializer.
+ *
+ * @param[in] name name of the IOBus variable
+ * @param[in] port I/O port descriptor
+ * @param[in] width bus width in bits
+ * @param[in] offset bus bit offset within the port
+ */
+#define IOBUS_DECL(name, port, width, offset) \
+ IOBus name = _IOBUS_DATA(name, port, width, offset)
+
+#if (PAL_USE_CALLBACKS == TRUE) || (PAL_USE_WAIT == TRUE) || \
+ defined(__DOXYGEN__)
+/**
+ * @name Low level driver helper macros
+ * @{
+ */
+#if ((PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE)) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief Initializes a PAL event object.
+ *
+ * @param[in] e event index
+ *
+ * @notapi
+ */
+#define _pal_init_event(e) \
+ do { \
+ osalThreadQueueObjectInit(&_pal_events[e].threads); \
+ _pal_events[e].cb = NULL; \
+ _pal_events[e].arg = NULL; \
+ } while (false)
+#endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE) */
+
+#if (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE)
+#define _pal_init_event(e) \
+ do { \
+ _pal_events[e].cb = NULL; \
+ _pal_events[e].arg = NULL; \
+ } while (false)
+#endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE) */
+
+#if (PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE)
+#define _pal_init_event(e) \
+ do { \
+ osalThreadQueueObjectInit(&_pal_events[e].threads); \
+ } while (false)
+#endif /* (PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE) */
+
+#if ((PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE)) || defined(__DOXYGEN__)
+/**
+ * @brief Clears a PAL event object.
+ *
+ * @param[in] e event index
+ *
+ * @notapi
+ */
+#define _pal_clear_event(e) \
+ do { \
+ osalThreadDequeueAllI(&_pal_events[pad].threads, MSG_RESET); \
+ _pal_events[e].cb = NULL; \
+ _pal_events[e].arg = NULL; \
+ } while (false)
+#endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE) */
+
+#if (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE)
+#define _pal_clear_event(e) \
+ do { \
+ _pal_events[e].cb = NULL; \
+ _pal_events[e].arg = NULL; \
+ } while (false)
+#endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE) */
+
+#if (PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE)
+#define _pal_clear_event(e) \
+ do { \
+ osalThreadDequeueAllI(&_pal_events[pad].threads, MSG_RESET); \
+ } while (false)
+#endif /* (PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE) */
+
+/**
+ * @brief Common ISR code.
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] e event index
+ *
+ * @notapi
+ */
+#if ((PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE)) || \
+ defined(__DOXYGEN__)
+#define _pal_isr_code(e) do { \
+ if (_pal_events[e].cb != NULL) { \
+ _pal_events[e].cb(_pal_events[e].arg); \
+ } \
+ osalSysLockFromISR(); \
+ osalThreadDequeueAllI(&_pal_events[e].threads, MSG_OK); \
+ osalSysUnlockFromISR(); \
+} while (false)
+#endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == TRUE) */
+
+#if (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE)
+#define _pal_isr_code(e) do { \
+ if (_pal_events[e].cb != NULL) { \
+ _pal_events[e].cb(_pal_events[e].arg); \
+ } \
+} while (false)
+#endif /* (PAL_USE_CALLBACKS == TRUE) && (PAL_USE_WAIT == FALSE) */
+
+#if ((PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE)) || \
+ defined(__DOXYGEN__)
+#define _pal_isr_code(e) do { \
+ osalSysLockFromISR(); \
+ osalThreadDequeueAllI(&_pal_events[e].threads, MSG_OK); \
+ osalSysUnlockFromISR(); \
+} while (false)
+#endif /* (PAL_USE_CALLBACKS == FALSE) && (PAL_USE_WAIT == TRUE) */
+
+/** @} */
+#endif /* (PAL_USE_CALLBACKS == TRUE) || (PAL_USE_WAIT == TRUE) */
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief PAL subsystem initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+#if defined(PAL_NEW_INIT) || defined(__DOXYGEN__)
+#define palInit() pal_lld_init()
+#else
+#define palInit(config) pal_lld_init(config)
+#endif
+
+/**
+ * @brief Reads the physical I/O port states.
+ * @note The function can be called from any context.
+ *
+ * @param[in] port port identifier
+ * @return The port logic states.
+ *
+ * @special
+ */
+#if !defined(pal_lld_readport) || defined(__DOXYGEN__)
+#define palReadPort(port) ((void)(port), 0U)
+#else
+#define palReadPort(port) pal_lld_readport(port)
+#endif
+
+/**
+ * @brief Reads the output latch.
+ * @details The purpose of this function is to read back the latched output
+ * value.
+ * @note The function can be called from any context.
+ *
+ * @param[in] port port identifier
+ * @return The latched logic states.
+ *
+ * @special
+ */
+#if !defined(pal_lld_readlatch) || defined(__DOXYGEN__)
+#define palReadLatch(port) ((void)(port), 0U)
+#else
+#define palReadLatch(port) pal_lld_readlatch(port)
+#endif
+
+/**
+ * @brief Writes a bits mask on a I/O port.
+ * @note The function can be called from any context.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be written on the specified port
+ *
+ * @special
+ */
+#if !defined(pal_lld_writeport) || defined(__DOXYGEN__)
+#define palWritePort(port, bits) ((void)(port), (void)(bits))
+#else
+#define palWritePort(port, bits) pal_lld_writeport(port, bits)
+#endif
+
+/**
+ * @brief Sets a bits mask on a I/O port.
+ * @note The operation is not guaranteed to be atomic on all the
+ * architectures, for atomicity and/or portability reasons you may
+ * need to enclose port I/O operations between @p osalSysLock() and
+ * @p osalSysUnlock().
+ * @note The function can be called from any context.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be ORed on the specified port
+ *
+ * @special
+ */
+#if !defined(pal_lld_setport) || defined(__DOXYGEN__)
+#define palSetPort(port, bits) \
+ palWritePort(port, palReadLatch(port) | (bits))
+#else
+#define palSetPort(port, bits) pal_lld_setport(port, bits)
+#endif
+
+/**
+ * @brief Clears a bits mask on a I/O port.
+ * @note The operation is not guaranteed to be atomic on all the
+ * architectures, for atomicity and/or portability reasons you may
+ * need to enclose port I/O operations between @p osalSysLock() and
+ * @p osalSysUnlock().
+ * @note The function can be called from any context.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be cleared on the specified port
+ *
+ * @special
+ */
+#if !defined(pal_lld_clearport) || defined(__DOXYGEN__)
+#define palClearPort(port, bits) \
+ palWritePort(port, palReadLatch(port) & ~(bits))
+#else
+#define palClearPort(port, bits) pal_lld_clearport(port, bits)
+#endif
+
+/**
+ * @brief Toggles a bits mask on a I/O port.
+ * @note The operation is not guaranteed to be atomic on all the
+ * architectures, for atomicity and/or portability reasons you may
+ * need to enclose port I/O operations between @p osalSysLock() and
+ * @p osalSysUnlock().
+ * @note The function can be called from any context.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be XORed on the specified port
+ *
+ * @special
+ */
+#if !defined(pal_lld_toggleport) || defined(__DOXYGEN__)
+#define palTogglePort(port, bits) \
+ palWritePort(port, palReadLatch(port) ^ (bits))
+#else
+#define palTogglePort(port, bits) pal_lld_toggleport(port, bits)
+#endif
+
+/**
+ * @brief Reads a group of bits.
+ * @note The function can be called from any context.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask, a logic AND is performed on the input
+ * data
+ * @param[in] offset group bit offset within the port
+ * @return The group logic states.
+ *
+ * @special
+ */
+#if !defined(pal_lld_readgroup) || defined(__DOXYGEN__)
+#define palReadGroup(port, mask, offset) \
+ ((palReadPort(port) >> (offset)) & (mask))
+#else
+#define palReadGroup(port, mask, offset) pal_lld_readgroup(port, mask, offset)
+#endif
+
+/**
+ * @brief Writes a group of bits.
+ * @note The operation is not guaranteed to be atomic on all the
+ * architectures, for atomicity and/or portability reasons you may
+ * need to enclose port I/O operations between @p osalSysLock() and
+ * @p osalSysUnlock().
+ * @note The function can be called from any context.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask, a logic AND is performed on the
+ * output data
+ * @param[in] offset group bit offset within the port
+ * @param[in] bits bits to be written. Values exceeding the group
+ * width are masked.
+ *
+ * @special
+ */
+#if !defined(pal_lld_writegroup) || defined(__DOXYGEN__)
+#define palWriteGroup(port, mask, offset, bits) \
+ palWritePort(port, (palReadLatch(port) & ~((mask) << (offset))) | \
+ (((bits) & (mask)) << (offset)))
+#else
+#define palWriteGroup(port, mask, offset, bits) \
+ pal_lld_writegroup(port, mask, offset, bits)
+#endif
+
+/**
+ * @brief Pads group mode setup.
+ * @details This function programs a pads group belonging to the same port
+ * with the specified mode.
+ * @note The operation is not guaranteed to be atomic on all the
+ * architectures, for atomicity and/or portability reasons you may
+ * need to enclose port I/O operations between @p osalSysLock() and
+ * @p osalSysUnlock().
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ * @note The function can be called from any context.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask
+ * @param[in] offset group bit offset within the port
+ * @param[in] mode group mode
+ *
+ * @special
+ */
+#if !defined(pal_lld_setgroupmode) || defined(__DOXYGEN__)
+#define palSetGroupMode(port, mask, offset, mode)
+#else
+#define palSetGroupMode(port, mask, offset, mode) \
+ pal_lld_setgroupmode(port, mask, offset, mode)
+#endif
+
+/**
+ * @brief Reads an input pad logic state.
+ * @note The function can be called from any context.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @return The logic state.
+ * @retval PAL_LOW low logic state.
+ * @retval PAL_HIGH high logic state.
+ *
+ * @special
+ */
+#if !defined(pal_lld_readpad) || defined(__DOXYGEN__)
+#define palReadPad(port, pad) ((palReadPort(port) >> (pad)) & 1U)
+#else
+#define palReadPad(port, pad) pal_lld_readpad(port, pad)
+#endif
+
+/**
+ * @brief Writes a logic state on an output pad.
+ * @note The operation is not guaranteed to be atomic on all the
+ * architectures, for atomicity and/or portability reasons you may
+ * need to enclose port I/O operations between @p osalSysLock() and
+ * @p osalSysUnlock().
+ * @note The function can be called from any context.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] bit logic value, the value must be @p PAL_LOW or
+ * @p PAL_HIGH
+ *
+ * @special
+ */
+#if !defined(pal_lld_writepad) || defined(__DOXYGEN__)
+#define palWritePad(port, pad, bit) \
+ palWritePort(port, (palReadLatch(port) & ~PAL_PORT_BIT(pad)) | \
+ (((bit) & 1U) << pad))
+#else
+#define palWritePad(port, pad, bit) pal_lld_writepad(port, pad, bit)
+#endif
+
+/**
+ * @brief Sets a pad logic state to @p PAL_HIGH.
+ * @note The operation is not guaranteed to be atomic on all the
+ * architectures, for atomicity and/or portability reasons you may
+ * need to enclose port I/O operations between @p osalSysLock() and
+ * @p osalSysUnlock().
+ * @note The function can be called from any context.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @special
+ */
+#if !defined(pal_lld_setpad) || defined(__DOXYGEN__)
+#define palSetPad(port, pad) palSetPort(port, PAL_PORT_BIT(pad))
+#else
+#define palSetPad(port, pad) pal_lld_setpad(port, pad)
+#endif
+
+/**
+ * @brief Clears a pad logic state to @p PAL_LOW.
+ * @note The operation is not guaranteed to be atomic on all the
+ * architectures, for atomicity and/or portability reasons you may
+ * need to enclose port I/O operations between @p osalSysLock() and
+ * @p osalSysUnlock().
+ * @note The function can be called from any context.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @special
+ */
+#if !defined(pal_lld_clearpad) || defined(__DOXYGEN__)
+#define palClearPad(port, pad) palClearPort(port, PAL_PORT_BIT(pad))
+#else
+#define palClearPad(port, pad) pal_lld_clearpad(port, pad)
+#endif
+
+/**
+ * @brief Toggles a pad logic state.
+ * @note The operation is not guaranteed to be atomic on all the
+ * architectures, for atomicity and/or portability reasons you may
+ * need to enclose port I/O operations between @p osalSysLock() and
+ * @p osalSysUnlock().
+ * @note The function can be called from any context.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @special
+ */
+#if !defined(pal_lld_togglepad) || defined(__DOXYGEN__)
+#define palTogglePad(port, pad) palTogglePort(port, PAL_PORT_BIT(pad))
+#else
+#define palTogglePad(port, pad) pal_lld_togglepad(port, pad)
+#endif
+
+/**
+ * @brief Pad mode setup.
+ * @details This function programs a pad with the specified mode.
+ * @note The operation is not guaranteed to be atomic on all the
+ * architectures, for atomicity and/or portability reasons you may
+ * need to enclose port I/O operations between @p osalSysLock() and
+ * @p osalSysUnlock().
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ * @note The function can be called from any context.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] mode pad mode
+ *
+ * @special
+ */
+#if !defined(pal_lld_setpadmode) || defined(__DOXYGEN__)
+#define palSetPadMode(port, pad, mode) \
+ palSetGroupMode(port, PAL_PORT_BIT(pad), 0U, mode)
+#else
+#define palSetPadMode(port, pad, mode) pal_lld_setpadmode(port, pad, mode)
+#endif
+
+/**
+ * @brief Reads an input line logic state.
+ * @note The function can be called from any context.
+ *
+ * @param[in] line line identifier
+ * @return The logic state.
+ * @retval PAL_LOW low logic state.
+ * @retval PAL_HIGH high logic state.
+ *
+ * @special
+ */
+#if !defined(pal_lld_readline) || defined(__DOXYGEN__)
+#define palReadLine(line) palReadPad(PAL_PORT(line), PAL_PAD(line))
+#else
+#define palReadLine(line) pal_lld_readline(line)
+#endif
+
+/**
+ * @brief Writes a logic state on an output line.
+ * @note The operation is not guaranteed to be atomic on all the
+ * architectures, for atomicity and/or portability reasons you may
+ * need to enclose port I/O operations between @p osalSysLock() and
+ * @p osalSysUnlock().
+ * @note The function can be called from any context.
+ *
+ * @param[in] line line identifier
+ * @param[in] bit logic value, the value must be @p PAL_LOW or
+ * @p PAL_HIGH
+ *
+ * @special
+ */
+#if !defined(pal_lld_writeline) || defined(__DOXYGEN__)
+#define palWriteLine(line, bit) palWritePad(PAL_PORT(line), PAL_PAD(line), bit)
+#else
+#define palWriteLine(line, bit) pal_lld_writeline(line, bit)
+#endif
+
+/**
+ * @brief Sets a line logic state to @p PAL_HIGH.
+ * @note The operation is not guaranteed to be atomic on all the
+ * architectures, for atomicity and/or portability reasons you may
+ * need to enclose port I/O operations between @p osalSysLock() and
+ * @p osalSysUnlock().
+ * @note The function can be called from any context.
+ *
+ * @param[in] line line identifier
+ *
+ * @special
+ */
+#if !defined(pal_lld_setline) || defined(__DOXYGEN__)
+#define palSetLine(line) palSetPad(PAL_PORT(line), PAL_PAD(line))
+#else
+#define palSetLine(line) pal_lld_setline(line)
+#endif
+
+/**
+ * @brief Clears a line logic state to @p PAL_LOW.
+ * @note The operation is not guaranteed to be atomic on all the
+ * architectures, for atomicity and/or portability reasons you may
+ * need to enclose port I/O operations between @p osalSysLock() and
+ * @p osalSysUnlock().
+ * @note The function can be called from any context.
+ *
+ * @param[in] line line identifier
+ *
+ * @special
+ */
+#if !defined(pal_lld_clearline) || defined(__DOXYGEN__)
+#define palClearLine(line) palClearPad(PAL_PORT(line), PAL_PAD(line))
+#else
+#define palClearLine(line) pal_lld_clearline(line)
+#endif
+
+/**
+ * @brief Toggles a line logic state.
+ * @note The operation is not guaranteed to be atomic on all the
+ * architectures, for atomicity and/or portability reasons you may
+ * need to enclose port I/O operations between @p osalSysLock() and
+ * @p osalSysUnlock().
+ * @note The function can be called from any context.
+ *
+ * @param[in] line line identifier
+ *
+ * @special
+ */
+#if !defined(pal_lld_toggleline) || defined(__DOXYGEN__)
+#define palToggleLine(line) palTogglePad(PAL_PORT(line), PAL_PAD(line))
+#else
+#define palToggleLine(line) pal_lld_toggleline(line)
+#endif
+
+/**
+ * @brief Line mode setup.
+ * @note The operation is not guaranteed to be atomic on all the
+ * architectures, for atomicity and/or portability reasons you may
+ * need to enclose port I/O operations between @p osalSysLock() and
+ * @p osalSysUnlock().
+ * @note The function can be called from any context.
+ *
+ * @param[in] line line identifier
+ * @param[in] mode pad mode
+ *
+ * @special
+ */
+#if !defined(pal_lld_setlinemode) || defined(__DOXYGEN__)
+#define palSetLineMode(line, mode) \
+ palSetPadMode(PAL_PORT(line), PAL_PAD(line), mode)
+#else
+#define palSetLineMode(line, mode) pal_lld_setlinemode(line, mode)
+#endif
+
+#if (PAL_USE_CALLBACKS == TRUE) || (PAL_USE_WAIT == TRUE) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief Pad event enable.
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] mode pad event mode
+ *
+ * @iclass
+ */
+#if !defined(pal_lld_enablepadevent) || defined(__DOXYGEN__)
+#define palEnablePadEventI(port, pad, mode)
+#else
+#define palEnablePadEventI(port, pad, mode) \
+ pal_lld_enablepadevent(port, pad, mode)
+#endif
+
+/**
+ * @brief Pad event disable.
+ * @details This function also disables previously programmed event callbacks.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @iclass
+ */
+#if !defined(pal_lld_disablepadevent) || defined(__DOXYGEN__)
+#define palDisablePadEventI(port, pad)
+#else
+#define palDisablePadEventI(port, pad) \
+ pal_lld_disablepadevent(port, pad)
+#endif
+
+/**
+ * @brief Pad event enable.
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] mode pad event mode
+ *
+ * @api
+ */
+#define palEnablePadEvent(port, pad, mode) \
+ do { \
+ osalSysLock(); \
+ palEnablePadEventI(port, pad, mode); \
+ osalSysUnlock(); \
+ } while (false)
+
+/**
+ * @brief Pad event disable.
+ * @details This function also disables previously programmed event callbacks.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @api
+ */
+#define palDisablePadEvent(port, pad) \
+ do { \
+ osalSysLock(); \
+ palDisablePadEventI(port, pad); \
+ osalSysUnlock(); \
+ } while (false)
+
+/**
+ * @brief Line event enable.
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @param[in] line line identifier
+ * @param[in] mode line event mode
+ *
+ * @iclass
+ */
+#if !defined(pal_lld_enablelineevent) || defined(__DOXYGEN__)
+#define palEnableLineEventI(line, mode) \
+ palEnablePadEventI(PAL_PORT(line), PAL_PAD(line), mode)
+#else
+#define palEnableLineEventI(line, mode) \
+ pal_lld_enablelineevent(line, mode)
+#endif
+
+/**
+ * @brief Line event disable.
+ * @details This function also disables previously programmed event callbacks.
+ *
+ * @param[in] line line identifier
+ *
+ * @iclass
+ */
+#if !defined(pal_lld_disablelineevent) || defined(__DOXYGEN__)
+#define palDisableLineEventI(line) \
+ palDisablePadEventI(PAL_PORT(line), PAL_PAD(line))
+#else
+#define palDisableLineEventI(line) pal_lld_disablelineevent(line)
+#endif
+
+/**
+ * @brief Line event enable.
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @param[in] line line identifier
+ * @param[in] mode line event mode
+ *
+ * @api
+ */
+#define palEnableLineEvent(line, mode) \
+ do { \
+ osalSysLock(); \
+ palEnableLineEventI(line, mode); \
+ osalSysUnlock(); \
+ } while (false)
+
+/**
+ * @brief Line event disable.
+ * @details This function also disables previously programmed event callbacks.
+ *
+ * @param[in] line line identifier
+ *
+ * @api
+ */
+#define palDisableLineEvent(line) \
+ do { \
+ osalSysLock(); \
+ palDisableLineEventI(line); \
+ osalSysUnlock(); \
+ } while (false)
+
+/**
+ * @brief Pad event enable check.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @return Pad event status.
+ * @retval false if the pad event is disabled.
+ * @retval true if the pad event is enabled.
+ *
+ * @xclass
+ */
+#if !defined(pal_lld_ispadeventenabled) || defined(__DOXYGEN__)
+#define palIsPadEventEnabledX(port, pad) false
+#else
+#define palIsPadEventEnabledX(port, pad) \
+ pal_lld_ispadeventenabled(port, pad)
+#endif
+
+/**
+ * @brief Line event enable check.
+ *
+ * @param[in] line line identifier
+ * @return Line event status.
+ * @retval false if the line event is disabled.
+ * @retval true if the line event is enabled.
+ *
+ * @xclass
+ */
+#if !defined(pal_lld_islineeventenabled) || defined(__DOXYGEN__)
+#define palIsLineEventEnabledX(line) \
+ pal_lld_ispadeventenabled(PAL_PORT(line), PAL_PAD(line))
+#else
+#define palIsLineEventEnabledX(line) \
+ pal_lld_islineeventenabled(line)
+#endif
+
+#endif /* PAL_USE_CALLBACKS || PAL_USE_WAIT */
+
+#if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Associates a callback to a pad.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] cb event callback function
+ * @param[in] arg callback argument
+ *
+ * @api
+ */
+#define palSetPadCallback(port, pad, cb, arg) \
+ do { \
+ osalSysLock(); \
+ palSetPadCallbackI(port, pad, cb, arg); \
+ osalSysUnlock(); \
+ } while (false)
+
+/**
+ * @brief Associates a callback to a line.
+ *
+ * @param[in] line line identifier
+ * @param[in] cb event callback function
+ * @param[in] arg callback argument
+ *
+ * @api
+ */
+#define palSetLineCallback(line, cb, arg) \
+ do { \
+ osalSysLock(); \
+ palSetLineCallbackI(line, cb, arg); \
+ osalSysUnlock(); \
+ } while (false)
+#endif /* PAL_USE_CALLBACKS == TRUE */
+
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ ioportmask_t palReadBus(const IOBus *bus);
+ void palWriteBus(const IOBus *bus, ioportmask_t bits);
+ void palSetBusMode(const IOBus *bus, iomode_t mode);
+#if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
+ void palSetPadCallbackI(ioportid_t port, iopadid_t pad,
+ palcallback_t cb, void *arg);
+ void palSetLineCallbackI(ioline_t line, palcallback_t cb, void *arg);
+#endif /* PAL_USE_CALLBACKS == TRUE */
+#if (PAL_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+ msg_t palWaitPadTimeoutS(ioportid_t port, iopadid_t pad,
+ sysinterval_t timeout);
+ msg_t palWaitPadTimeout(ioportid_t port, iopadid_t pad,
+ sysinterval_t timeout);
+ msg_t palWaitLineTimeoutS(ioline_t line, sysinterval_t timeout);
+ msg_t palWaitLineTimeout(ioline_t line, sysinterval_t timeout);
+#endif /* PAL_USE_WAIT == TRUE */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_PAL_H */
+
+#endif /* HAL_USE_PAL == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_persistent.h b/ChibiOS_20.3.2/os/hal/include/hal_persistent.h
new file mode 100644
index 0000000..6079e77
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_persistent.h
@@ -0,0 +1,184 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_persistent.h
+ * @brief Generic persistent storage class header.
+ *
+ * @addtogroup HAL_PERSISTENT
+ * @details This module define an abstract interface for generic persistent
+ * storage. Such storage has a fixed size and can be read and
+ * written.
+ * @{
+ */
+
+#ifndef HAL_PERSISTENT_H
+#define HAL_PERSISTENT_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a persistent storage error code.
+ * @note Code values are kept equal to the equivalent codes in the flash
+ * interface, this is intentional.
+ */
+typedef enum {
+ PS_NO_ERROR = 0, /* No error. */
+ PS_ERROR_READ = 2, /* ECC or other error during read operation.*/
+ PS_ERROR_WRITE = 3, /* Program operation failed. */
+ PS_ERROR_VERIFY = 5, /* Verify operation failed. */
+ PS_ERROR_HW_FAILURE = 6 /* Controller or communication error. */
+} ps_error_t;
+
+/**
+ * @brief Type of a persistent storage offset.
+ */
+typedef uint32_t ps_offset_t;
+
+/**
+ * @brief @p BasePersistentStorage specific methods.
+ */
+#define _base_pers_storage_methods_alone \
+ /* Storage size.*/ \
+ size_t (*getsize)(void *instance); \
+ /* Read operation.*/ \
+ ps_error_t (*read)(void *instance, ps_offset_t offset, \
+ size_t n, uint8_t *rp); \
+ /* Write operation.*/ \
+ ps_error_t (*write)(void *instance, ps_offset_t offset, \
+ size_t n, const uint8_t *wp);
+
+/**
+ * @brief @p BasePersistentStorage specific methods with inherited ones.
+ */
+#define _base_pers_storage_methods \
+ _base_object_methods \
+ _base_pers_storage_methods_alone
+
+/**
+ * @brief @p BasePersistentStorage virtual methods table.
+ */
+struct BasePersistentStorageVMT {
+ _base_pers_storage_methods
+};
+
+/**
+ * @brief @p BasePersistentStorage specific data.
+ */
+#define _base_persistent_storage_data \
+ _base_object_data
+
+/**
+ * @extends BaseObject
+ *
+ * @brief Base persistent storage class.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct BasePersistentStorageVMT *vmt;
+ _base_persistent_storage_data
+} BasePersistentStorage;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions (BasePersistentStorage)
+ * @{
+ */
+/**
+ * @brief Instance getter.
+ * @details This special method is used to get the instance of this class
+ * object from a derived class.
+ */
+#define getBasePersistentStorage(ip) ((BasePersistentStorage *)&(ip)->vmt)
+
+/**
+ * @brief Get storage size.
+ *
+ * @param[in] ip pointer to a @p BasePersistentStorage or derived class
+ * @return The storage size in bytes.
+ *
+ * @api
+ */
+#define psGetStorageSize(ip) \
+ (ip)->vmt->getsize(ip)
+
+/**
+ * @brief Read operation.
+ *
+ * @param[in] ip pointer to a @p BasePersistentStorage or derived class
+ * @param[in] offset persistent storage offset
+ * @param[in] n number of bytes to be read
+ * @param[out] rp pointer to the data buffer
+ * @return An error code.
+ * @retval PS_NO_ERROR if there is no erase operation in progress.
+ * @retval PS_ERROR_READ if the read operation failed.
+ * @retval PS_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @api
+ */
+#define psRead(ip, offset, n, rp) \
+ (ip)->vmt->read(ip, offset, n, rp)
+
+/**
+ * @brief Write operation.
+ *
+ * @param[in] ip pointer to a @p BasePersistentStorage or derived class
+ * @param[in] offset persistent storage offset
+ * @param[in] n number of bytes to be written
+ * @param[in] wp pointer to the data buffer
+ * @return An error code.
+ * @retval PS_NO_ERROR if there is no erase operation in progress.
+ * @retval PS_ERROR_WRITE if the write operation failed.
+ * @retval PS_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @api
+ */
+#define psWrite(ip, offset, n, wp) \
+ (ip)->vmt->write(ip, offset, n, wp)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_PERSISTENT_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_pwm.h b/ChibiOS_20.3.2/os/hal/include/hal_pwm.h
new file mode 100644
index 0000000..ee2d191
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_pwm.h
@@ -0,0 +1,308 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_pwm.h
+ * @brief PWM Driver macros and structures.
+ *
+ * @addtogroup PWM
+ * @{
+ */
+
+#ifndef HAL_PWM_H
+#define HAL_PWM_H
+
+#if (HAL_USE_PWM == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name PWM output mode macros
+ * @{
+ */
+/**
+ * @brief Standard output modes mask.
+ */
+#define PWM_OUTPUT_MASK 0x0FU
+
+/**
+ * @brief Output not driven, callback only.
+ */
+#define PWM_OUTPUT_DISABLED 0x00U
+
+/**
+ * @brief Positive PWM logic, active is logic level one.
+ */
+#define PWM_OUTPUT_ACTIVE_HIGH 0x01U
+
+/**
+ * @brief Inverse PWM logic, active is logic level zero.
+ */
+#define PWM_OUTPUT_ACTIVE_LOW 0x02U
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ PWM_UNINIT = 0, /**< Not initialized. */
+ PWM_STOP = 1, /**< Stopped. */
+ PWM_READY = 2 /**< Ready. */
+} pwmstate_t;
+
+/**
+ * @brief Type of a structure representing a PWM driver.
+ */
+typedef struct PWMDriver PWMDriver;
+
+/**
+ * @brief Type of a PWM notification callback.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ */
+typedef void (*pwmcallback_t)(PWMDriver *pwmp);
+
+#include "hal_pwm_lld.h"
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name PWM duty cycle conversion
+ * @{
+ */
+/**
+ * @brief Converts from fraction to pulse width.
+ * @note Be careful with rounding errors, this is integer math not magic.
+ * You can specify tenths of thousandth but make sure you have the
+ * proper hardware resolution by carefully choosing the clock source
+ * and prescaler settings, see @p PWM_COMPUTE_PSC.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] denominator denominator of the fraction
+ * @param[in] numerator numerator of the fraction
+ * @return The pulse width to be passed to @p pwmEnableChannel().
+ *
+ * @api
+ */
+#define PWM_FRACTION_TO_WIDTH(pwmp, denominator, numerator) \
+ ((pwmcnt_t)((((pwmcnt_t)(pwmp)->period) * \
+ (pwmcnt_t)(numerator)) / (pwmcnt_t)(denominator)))
+
+/**
+ * @brief Converts from degrees to pulse width.
+ * @note Be careful with rounding errors, this is integer math not magic.
+ * You can specify hundredths of degrees but make sure you have the
+ * proper hardware resolution by carefully choosing the clock source
+ * and prescaler settings, see @p PWM_COMPUTE_PSC.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] degrees degrees as an integer between 0 and 36000
+ * @return The pulse width to be passed to @p pwmEnableChannel().
+ *
+ * @api
+ */
+#define PWM_DEGREES_TO_WIDTH(pwmp, degrees) \
+ PWM_FRACTION_TO_WIDTH(pwmp, 36000, degrees)
+
+/**
+ * @brief Converts from percentage to pulse width.
+ * @note Be careful with rounding errors, this is integer math not magic.
+ * You can specify tenths of thousandth but make sure you have the
+ * proper hardware resolution by carefully choosing the clock source
+ * and prescaler settings, see @p PWM_COMPUTE_PSC.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] percentage percentage as an integer between 0 and 10000
+ * @return The pulse width to be passed to @p pwmEnableChannel().
+ *
+ * @api
+ */
+#define PWM_PERCENTAGE_TO_WIDTH(pwmp, percentage) \
+ PWM_FRACTION_TO_WIDTH(pwmp, 10000, percentage)
+/** @} */
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Changes the period the PWM peripheral.
+ * @details This function changes the period of a PWM unit that has already
+ * been activated using @p pwmStart().
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @post The PWM unit period is changed to the new value.
+ * @note If a period is specified that is shorter than the pulse width
+ * programmed in one of the channels then the behavior is not
+ * guaranteed.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] value new cycle time in ticks
+ *
+ * @iclass
+ */
+#define pwmChangePeriodI(pwmp, value) { \
+ (pwmp)->period = (value); \
+ pwm_lld_change_period(pwmp, value); \
+}
+
+/**
+ * @brief Enables a PWM channel.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @post The channel is active using the specified configuration.
+ * @note Depending on the hardware implementation this function has
+ * effect starting on the next cycle (recommended implementation)
+ * or immediately (fallback implementation).
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] channel PWM channel identifier (0...channels-1)
+ * @param[in] width PWM pulse width as clock pulses number
+ *
+ * @iclass
+ */
+#define pwmEnableChannelI(pwmp, channel, width) do { \
+ (pwmp)->enabled |= ((pwmchnmsk_t)1U << (pwmchnmsk_t)(channel)); \
+ pwm_lld_enable_channel(pwmp, channel, width); \
+} while (false)
+
+/**
+ * @brief Disables a PWM channel.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @post The channel is disabled and its output line returned to the
+ * idle state.
+ * @note Depending on the hardware implementation this function has
+ * effect starting on the next cycle (recommended implementation)
+ * or immediately (fallback implementation).
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] channel PWM channel identifier (0...channels-1)
+ *
+ * @iclass
+ */
+#define pwmDisableChannelI(pwmp, channel) do { \
+ (pwmp)->enabled &= ~((pwmchnmsk_t)1U << (pwmchnmsk_t)(channel)); \
+ pwm_lld_disable_channel(pwmp, channel); \
+} while (false)
+
+/**
+ * @brief Returns a PWM channel status.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] channel PWM channel identifier (0...channels-1)
+ *
+ * @iclass
+ */
+#define pwmIsChannelEnabledI(pwmp, channel) \
+ (((pwmp)->enabled & ((pwmchnmsk_t)1U << (pwmchnmsk_t)(channel))) != 0U)
+
+/**
+ * @brief Enables the periodic activation edge notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @note If the notification is already enabled then the call has no effect.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ *
+ * @iclass
+ */
+#define pwmEnablePeriodicNotificationI(pwmp) \
+ pwm_lld_enable_periodic_notification(pwmp)
+
+/**
+ * @brief Disables the periodic activation edge notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @note If the notification is already disabled then the call has no effect.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ *
+ * @iclass
+ */
+#define pwmDisablePeriodicNotificationI(pwmp) \
+ pwm_lld_disable_periodic_notification(pwmp)
+
+/**
+ * @brief Enables a channel de-activation edge notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @pre The channel must have been activated using @p pwmEnableChannel().
+ * @note If the notification is already enabled then the call has no effect.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] channel PWM channel identifier (0...channels-1)
+ *
+ * @iclass
+ */
+#define pwmEnableChannelNotificationI(pwmp, channel) \
+ pwm_lld_enable_channel_notification(pwmp, channel)
+
+/**
+ * @brief Disables a channel de-activation edge notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @pre The channel must have been activated using @p pwmEnableChannel().
+ * @note If the notification is already disabled then the call has no effect.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] channel PWM channel identifier (0...channels-1)
+ *
+ * @iclass
+ */
+#define pwmDisableChannelNotificationI(pwmp, channel) \
+ pwm_lld_disable_channel_notification(pwmp, channel)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void pwmInit(void);
+ void pwmObjectInit(PWMDriver *pwmp);
+ void pwmStart(PWMDriver *pwmp, const PWMConfig *config);
+ void pwmStop(PWMDriver *pwmp);
+ void pwmChangePeriod(PWMDriver *pwmp, pwmcnt_t period);
+ void pwmEnableChannel(PWMDriver *pwmp,
+ pwmchannel_t channel,
+ pwmcnt_t width);
+ void pwmDisableChannel(PWMDriver *pwmp, pwmchannel_t channel);
+ void pwmEnablePeriodicNotification(PWMDriver *pwmp);
+ void pwmDisablePeriodicNotification(PWMDriver *pwmp);
+ void pwmEnableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel);
+ void pwmDisableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_PWM == TRUE */
+
+#endif /* HAL_PWM_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_queues.h b/ChibiOS_20.3.2/os/hal/include/hal_queues.h
new file mode 100644
index 0000000..d85cb93
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_queues.h
@@ -0,0 +1,328 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_queues.h
+ * @brief I/O Queues macros and structures.
+ *
+ * @addtogroup HAL_QUEUES
+ * @{
+ */
+
+#ifndef HAL_QUEUES_H
+#define HAL_QUEUES_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Queue functions returned status value
+ * @{
+ */
+#define Q_OK MSG_OK /**< @brief Operation successful. */
+#define Q_TIMEOUT MSG_TIMEOUT /**< @brief Timeout condition. */
+#define Q_RESET MSG_RESET /**< @brief Queue has been reset. */
+#define Q_EMPTY MSG_TIMEOUT /**< @brief Queue empty. */
+#define Q_FULL MSG_TIMEOUT /**< @brief Queue full, */
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a generic I/O queue structure.
+ */
+typedef struct io_queue io_queue_t;
+
+/**
+ * @brief Queue notification callback type.
+ *
+ * @param[in] qp the queue pointer
+ */
+typedef void (*qnotify_t)(io_queue_t *qp);
+
+/**
+ * @brief Generic I/O queue structure.
+ * @details This structure represents a generic Input or Output asymmetrical
+ * queue. The queue is asymmetrical because one end is meant to be
+ * accessed from a thread context, and thus can be blocking, the other
+ * end is accessible from interrupt handlers or from within a kernel
+ * lock zone and is non-blocking.
+ */
+struct io_queue {
+ threads_queue_t q_waiting; /**< @brief Queue of waiting threads. */
+ volatile size_t q_counter; /**< @brief Resources counter. */
+ uint8_t *q_buffer; /**< @brief Pointer to the queue buffer.*/
+ uint8_t *q_top; /**< @brief Pointer to the first
+ location after the buffer. */
+ uint8_t *q_wrptr; /**< @brief Write pointer. */
+ uint8_t *q_rdptr; /**< @brief Read pointer. */
+ qnotify_t q_notify; /**< @brief Data notification callback. */
+ void *q_link; /**< @brief Application defined field. */
+};
+
+/**
+ * @extends io_queue_t
+ *
+ * @brief Type of an input queue structure.
+ * @details This structure represents a generic asymmetrical input queue.
+ * Writing to the queue is non-blocking and can be performed from
+ * interrupt handlers or from within a kernel lock zone.
+ * Reading the queue can be a blocking operation and is supposed to
+ * be performed by a system thread.
+ */
+typedef io_queue_t input_queue_t;
+
+/**
+ * @extends io_queue_t
+ *
+ * @brief Type of an output queue structure.
+ * @details This structure represents a generic asymmetrical output queue.
+ * Reading from the queue is non-blocking and can be performed from
+ * interrupt handlers or from within a kernel lock zone.
+ * Writing the queue can be a blocking operation and is supposed to
+ * be performed by a system thread.
+ */
+typedef io_queue_t output_queue_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Returns the queue's buffer size.
+ *
+ * @param[in] qp pointer to a @p io_queue_t structure
+ * @return The buffer size.
+ *
+ * @xclass
+ */
+#define qSizeX(qp) \
+ /*lint -save -e9033 [10.8] The cast is safe.*/ \
+ ((size_t)((qp)->q_top - (qp)->q_buffer)) \
+ /*lint -restore*/
+
+/**
+ * @brief Queue space.
+ * @details Returns the used space if used on an input queue or the empty
+ * space if used on an output queue.
+ *
+ * @param[in] qp pointer to a @p io_queue_t structure
+ * @return The buffer space.
+ *
+ * @iclass
+ */
+#define qSpaceI(qp) ((qp)->q_counter)
+
+/**
+ * @brief Returns the queue application-defined link.
+ * @note This function can be called in any context.
+ *
+ * @param[in] qp pointer to a @p io_queue_t structure
+ * @return The application-defined link.
+ *
+ * @special
+ */
+#define qGetLink(qp) ((qp)->q_link)
+
+/**
+ * @brief Sets the queue application-defined link.
+ * @note This function can be called in any context.
+ *
+ * @param[in] qp pointer to a @p io_queue_t structure
+ * @param[in] lk The application-defined link.
+ *
+ * @special
+ */
+#define qSetLink(qp, lk) ((qp)->q_link = lk)
+
+/**
+ * @brief Returns the filled space into an input queue.
+ *
+ * @param[in] iqp pointer to an @p input_queue_t structure
+ * @return The number of full bytes in the queue.
+ * @retval 0 if the queue is empty.
+ *
+ * @iclass
+ */
+#define iqGetFullI(iqp) qSpaceI(iqp)
+
+/**
+ * @brief Returns the empty space into an input queue.
+ *
+ * @param[in] iqp pointer to an @p input_queue_t structure
+ * @return The number of empty bytes in the queue.
+ * @retval 0 if the queue is full.
+ *
+ * @iclass
+ */
+#define iqGetEmptyI(iqp) (qSizeX(iqp) - qSpaceI(iqp))
+
+/**
+ * @brief Evaluates to @p true if the specified input queue is empty.
+ *
+ * @param[in] iqp pointer to an @p input_queue_t structure
+ * @return The queue status.
+ * @retval false if the queue is not empty.
+ * @retval true if the queue is empty.
+ *
+ * @iclass
+ */
+#define iqIsEmptyI(iqp) ((bool)(qSpaceI(iqp) == 0U))
+
+/**
+ * @brief Evaluates to @p true if the specified input queue is full.
+ *
+ * @param[in] iqp pointer to an @p input_queue_t structure
+ * @return The queue status.
+ * @retval false if the queue is not full.
+ * @retval true if the queue is full.
+ *
+ * @iclass
+ */
+#define iqIsFullI(iqp) \
+ /*lint -save -e9007 [13.5] No side effects, a pointer is passed.*/ \
+ ((bool)(((iqp)->q_wrptr == (iqp)->q_rdptr) && ((iqp)->q_counter != 0U))) \
+ /*lint -restore*/
+
+/**
+ * @brief Input queue read.
+ * @details This function reads a byte value from an input queue. If the queue
+ * is empty then the calling thread is suspended until a byte arrives
+ * in the queue.
+ *
+ * @param[in] iqp pointer to an @p input_queue_t structure
+ * @return A byte value from the queue.
+ * @retval MSG_RESET if the queue has been reset.
+ *
+ * @api
+ */
+#define iqGet(iqp) iqGetTimeout(iqp, TIME_INFINITE)
+
+/**
+ * @brief Returns the filled space into an output queue.
+ *
+ * @param[in] oqp pointer to an @p output_queue_t structure
+ * @return The number of full bytes in the queue.
+ * @retval 0 if the queue is empty.
+ *
+ * @iclass
+ */
+#define oqGetFullI(oqp) (qSizeX(oqp) - qSpaceI(oqp))
+
+/**
+ * @brief Returns the empty space into an output queue.
+ *
+ * @param[in] oqp pointer to an @p output_queue_t structure
+ * @return The number of empty bytes in the queue.
+ * @retval 0 if the queue is full.
+ *
+ * @iclass
+ */
+#define oqGetEmptyI(oqp) qSpaceI(oqp)
+
+/**
+ * @brief Evaluates to @p true if the specified output queue is empty.
+ *
+ * @param[in] oqp pointer to an @p output_queue_t structure
+ * @return The queue status.
+ * @retval false if the queue is not empty.
+ * @retval true if the queue is empty.
+ *
+ * @iclass
+ */
+#define oqIsEmptyI(oqp) \
+ /*lint -save -e9007 [13.5] No side effects, a pointer is passed.*/ \
+ ((bool)(((oqp)->q_wrptr == (oqp)->q_rdptr) && ((oqp)->q_counter != 0U))) \
+ /*lint -restore*/
+
+/**
+ * @brief Evaluates to @p true if the specified output queue is full.
+ *
+ * @param[in] oqp pointer to an @p output_queue_t structure
+ * @return The queue status.
+ * @retval false if the queue is not full.
+ * @retval true if the queue is full.
+ *
+ * @iclass
+ */
+#define oqIsFullI(oqp) ((bool)(qSpaceI(oqp) == 0U))
+
+/**
+ * @brief Output queue write.
+ * @details This function writes a byte value to an output queue. If the queue
+ * is full then the calling thread is suspended until there is space
+ * in the queue.
+ *
+ * @param[in] oqp pointer to an @p output_queue_t structure
+ * @param[in] b the byte value to be written in the queue
+ * @return The operation status.
+ * @retval MSG_OK if the operation succeeded.
+ * @retval MSG_RESET if the queue has been reset.
+ *
+ * @api
+ */
+#define oqPut(oqp, b) oqPutTimeout(oqp, b, TIME_INFINITE)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+ /** @} */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void iqObjectInit(input_queue_t *iqp, uint8_t *bp, size_t size,
+ qnotify_t infy, void *link);
+ void iqResetI(input_queue_t *iqp);
+ msg_t iqPutI(input_queue_t *iqp, uint8_t b);
+ msg_t iqGetI(input_queue_t *iqp);
+ msg_t iqGetTimeout(input_queue_t *iqp, sysinterval_t timeout);
+ size_t iqReadI(input_queue_t *iqp, uint8_t *bp, size_t n);
+ size_t iqReadTimeout(input_queue_t *iqp, uint8_t *bp,
+ size_t n, sysinterval_t timeout);
+
+ void oqObjectInit(output_queue_t *oqp, uint8_t *bp, size_t size,
+ qnotify_t onfy, void *link);
+ void oqResetI(output_queue_t *oqp);
+ msg_t oqPutI(output_queue_t *oqp, uint8_t b);
+ msg_t oqPutTimeout(output_queue_t *oqp, uint8_t b, sysinterval_t timeout);
+ msg_t oqGetI(output_queue_t *oqp);
+ size_t oqWriteI(output_queue_t *oqp, const uint8_t *bp, size_t n);
+ size_t oqWriteTimeout(output_queue_t *oqp, const uint8_t *bp,
+ size_t n, sysinterval_t timeout);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_QUEUES_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_rtc.h b/ChibiOS_20.3.2/os/hal/include/hal_rtc.h
new file mode 100644
index 0000000..2003b53
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_rtc.h
@@ -0,0 +1,204 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file hal_rtc.h
+ * @brief RTC Driver macros and structures.
+ *
+ * @addtogroup RTC
+ * @{
+ */
+
+#ifndef HAL_RTC_H
+#define HAL_RTC_H
+
+#if (HAL_USE_RTC == TRUE) || defined(__DOXYGEN__)
+
+/*lint -save -e829 [21.10] The header is required.*/
+#include
+/*lint -restore*/
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Base year of the calendar.
+ */
+#define RTC_BASE_YEAR 1980U
+
+/**
+ * @name Date/Time bit masks for FAT format
+ * @{
+ */
+#define RTC_FAT_TIME_SECONDS_MASK 0x0000001FU
+#define RTC_FAT_TIME_MINUTES_MASK 0x000007E0U
+#define RTC_FAT_TIME_HOURS_MASK 0x0000F800U
+#define RTC_FAT_DATE_DAYS_MASK 0x001F0000U
+#define RTC_FAT_DATE_MONTHS_MASK 0x01E00000U
+#define RTC_FAT_DATE_YEARS_MASK 0xFE000000U
+/** @} */
+
+/**
+ * @name Day of week encoding
+ * @{
+ */
+#define RTC_DAY_CATURDAY 0U
+#define RTC_DAY_MONDAY 1U
+#define RTC_DAY_TUESDAY 2U
+#define RTC_DAY_WEDNESDAY 3U
+#define RTC_DAY_THURSDAY 4U
+#define RTC_DAY_FRIDAY 5U
+#define RTC_DAY_SATURDAY 6U
+#define RTC_DAY_SUNDAY 7U
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a structure representing an RTC driver.
+ */
+typedef struct RTCDriver RTCDriver;
+
+/**
+ * @brief Type of an RTC alarm number.
+ */
+typedef unsigned int rtcalarm_t;
+
+/**
+ * @brief Type of a structure representing an RTC date/time stamp.
+ */
+typedef struct {
+ /*lint -save -e46 [6.1] In this case uint32_t is fine.*/
+ uint32_t year: 8; /**< @brief Years since 1980. */
+ uint32_t month: 4; /**< @brief Months 1..12. */
+ uint32_t dstflag: 1; /**< @brief DST correction flag. */
+ uint32_t dayofweek: 3; /**< @brief Day of week 1..7. */
+ uint32_t day: 5; /**< @brief Day of the month 1..31. */
+ uint32_t millisecond: 27; /**< @brief Milliseconds since midnight.*/
+ /*lint -restore*/
+} RTCDateTime;
+
+/**
+ * @brief BasePersistentStorage specific methods.
+ */
+#define _rtc_driver_methods \
+ _base_pers_storage_methods
+
+#include "hal_rtc_lld.h"
+
+/* Some more checks, must happen after inclusion of the LLD header, this is
+ why are placed here.*/
+#if !defined(RTC_SUPPORTS_CALLBACKS)
+#error "RTC LLD does not define the required RTC_SUPPORTS_CALLBACKS macro"
+#endif
+
+#if !defined(RTC_ALARMS)
+#error "RTC LLD does not define the required RTC_ALARMS macro"
+#endif
+
+#if !defined(RTC_HAS_STORAGE)
+#error "RTC LLD does not define the required RTC_HAS_STORAGE macro"
+#endif
+
+#if (RTC_HAS_STORAGE == TRUE) || defined(__DOXYGEN__)
+/**
+ * @extends FileStream
+ *
+ * @brief @p RTCDriver virtual methods table.
+ */
+struct RTCDriverVMT {
+ _rtc_driver_methods
+};
+#endif
+
+/**
+ * @brief Structure representing an RTC driver.
+ */
+struct RTCDriver {
+#if (RTC_HAS_STORAGE == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Virtual Methods Table.
+ */
+ const struct RTCDriverVMT *vmt;
+#endif
+#if defined(RTC_DRIVER_EXT_FIELDS)
+ RTC_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ rtc_lld_driver_fields;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern RTCDriver RTCD1;
+#if RTC_HAS_STORAGE == TRUE
+extern struct RTCDriverVMT _rtc_lld_vmt;
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void rtcInit(void);
+ void rtcObjectInit(RTCDriver *rtcp);
+ void rtcSetTime(RTCDriver *rtcp, const RTCDateTime *timespec);
+ void rtcGetTime(RTCDriver *rtcp, RTCDateTime *timespec);
+#if RTC_ALARMS > 0
+ void rtcSetAlarm(RTCDriver *rtcp,
+ rtcalarm_t alarm,
+ const RTCAlarm *alarmspec);
+ void rtcGetAlarm(RTCDriver *rtcp, rtcalarm_t alarm, RTCAlarm *alarmspec);
+#endif
+#if RTC_SUPPORTS_CALLBACKS == TRUE
+ void rtcSetCallback(RTCDriver *rtcp, rtccb_t callback);
+#endif
+ void rtcConvertDateTimeToStructTm(const RTCDateTime *timespec,
+ struct tm *timp,
+ uint32_t *tv_msec);
+ void rtcConvertStructTmToDateTime(const struct tm *timp,
+ uint32_t tv_msec,
+ RTCDateTime *timespec);
+ uint32_t rtcConvertDateTimeToFAT(const RTCDateTime *timespec);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_RTC == TRUE */
+#endif /* HAL_RTC_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_sdc.h b/ChibiOS_20.3.2/os/hal/include/hal_sdc.h
new file mode 100644
index 0000000..0273a5a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_sdc.h
@@ -0,0 +1,209 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_sdc.h
+ * @brief SDC Driver macros and structures.
+ *
+ * @addtogroup SDC
+ * @{
+ */
+
+#ifndef HAL_SDC_H
+#define HAL_SDC_H
+
+#if (HAL_USE_SDC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name SD card types
+ * @{
+ */
+#define SDC_MODE_CARDTYPE_MASK 0xFU
+#define SDC_MODE_CARDTYPE_SDV11 0U
+#define SDC_MODE_CARDTYPE_SDV20 1U
+#define SDC_MODE_CARDTYPE_MMC 2U
+#define SDC_MODE_HIGH_CAPACITY 0x10U
+/** @} */
+
+/**
+ * @name SDC bus error conditions
+ * @{
+ */
+#define SDC_NO_ERROR 0U
+#define SDC_CMD_CRC_ERROR 1U
+#define SDC_DATA_CRC_ERROR 2U
+#define SDC_DATA_TIMEOUT 4U
+#define SDC_COMMAND_TIMEOUT 8U
+#define SDC_TX_UNDERRUN 16U
+#define SDC_RX_OVERRUN 32U
+#define SDC_STARTBIT_ERROR 64U
+#define SDC_OVERFLOW_ERROR 128U
+#define SDC_UNHANDLED_ERROR 0xFFFFFFFFU
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name SDC configuration options
+ * @{
+ */
+/**
+ * @brief Number of initialization attempts before rejecting the card.
+ * @note Attempts are performed at 10mS intervals.
+ */
+#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
+#define SDC_INIT_RETRY 100
+#endif
+
+/**
+ * @brief Include support for MMC cards.
+ * @note MMC support is not yet implemented so this option must be kept
+ * at @p FALSE.
+ */
+#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
+#define SDC_MMC_SUPPORT FALSE
+#endif
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ */
+#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
+#define SDC_NICE_WAITING TRUE
+#endif
+
+/**
+ * @brief OCR initialization constant for V20 cards.
+ */
+#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__)
+#define SDC_INIT_OCR_V20 0x50FF8000U
+#endif
+
+/**
+ * @brief OCR initialization constant for non-V20 cards.
+ */
+#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__)
+#define SDC_INIT_OCR 0x80100000U
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of SDIO bus mode.
+ */
+typedef enum {
+ SDC_MODE_1BIT = 0,
+ SDC_MODE_4BIT,
+ SDC_MODE_8BIT
+} sdcbusmode_t;
+
+/**
+ * @brief Max supported clock.
+ */
+typedef enum {
+ SDC_CLK_25MHz = 0,
+ SDC_CLK_50MHz
+} sdcbusclk_t;
+
+#include "hal_sdc_lld.h"
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Returns the card insertion status.
+ * @note This macro wraps a low level function named
+ * @p sdc_lld_is_card_inserted(), this function must be
+ * provided by the application because it is not part of the
+ * SDC driver.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @return The card state.
+ * @retval false card not inserted.
+ * @retval true card inserted.
+ *
+ * @api
+ */
+#define sdcIsCardInserted(sdcp) (sdc_lld_is_card_inserted(sdcp))
+
+/**
+ * @brief Returns the write protect status.
+ * @note This macro wraps a low level function named
+ * @p sdc_lld_is_write_protected(), this function must be
+ * provided by the application because it is not part of the
+ * SDC driver.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @return The card state.
+ * @retval false not write protected.
+ * @retval true write protected.
+ *
+ * @api
+ */
+#define sdcIsWriteProtected(sdcp) (sdc_lld_is_write_protected(sdcp))
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void sdcInit(void);
+ void sdcObjectInit(SDCDriver *sdcp);
+ void sdcStart(SDCDriver *sdcp, const SDCConfig *config);
+ void sdcStop(SDCDriver *sdcp);
+ bool sdcConnect(SDCDriver *sdcp);
+ bool sdcDisconnect(SDCDriver *sdcp);
+ bool sdcRead(SDCDriver *sdcp, uint32_t startblk,
+ uint8_t *buf, uint32_t n);
+ bool sdcWrite(SDCDriver *sdcp, uint32_t startblk,
+ const uint8_t *buf, uint32_t n);
+ sdcflags_t sdcGetAndClearErrors(SDCDriver *sdcp);
+ bool sdcSync(SDCDriver *sdcp);
+ bool sdcGetInfo(SDCDriver *sdcp, BlockDeviceInfo *bdip);
+ bool sdcErase(SDCDriver *sdcp, uint32_t startblk, uint32_t endblk);
+ bool _sdc_wait_for_transfer_state(SDCDriver *sdcp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SDC == TRUE */
+
+#endif /* HAL_SDC_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_serial.h b/ChibiOS_20.3.2/os/hal/include/hal_serial.h
new file mode 100644
index 0000000..d4309c2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_serial.h
@@ -0,0 +1,312 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_serial.h
+ * @brief Serial Driver macros and structures.
+ *
+ * @addtogroup SERIAL
+ * @{
+ */
+
+#ifndef HAL_SERIAL_H
+#define HAL_SERIAL_H
+
+#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Serial status flags
+ * @{
+ */
+#define SD_PARITY_ERROR (eventflags_t)32 /**< @brief Parity. */
+#define SD_FRAMING_ERROR (eventflags_t)64 /**< @brief Framing. */
+#define SD_OVERRUN_ERROR (eventflags_t)128 /**< @brief Overflow. */
+#define SD_NOISE_ERROR (eventflags_t)256 /**< @brief Line noise. */
+#define SD_BREAK_DETECTED (eventflags_t)512 /**< @brief LIN Break. */
+#define SD_QUEUE_FULL_ERROR (eventflags_t)1024 /**< @brief Queue full. */
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Serial configuration options
+ * @{
+ */
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, this is the baud rate selected for the
+ * default configuration.
+ */
+#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
+#define SERIAL_DEFAULT_BITRATE 38400
+#endif
+
+/**
+ * @brief Serial buffers size.
+ * @details Configuration parameter, you can change the depth of the queue
+ * buffers depending on the requirements of your application.
+ * @note The default is 16 bytes for both the transmission and receive
+ * buffers.
+ * @note This is a global setting and it can be overridden by low level
+ * driver specific settings.
+ */
+#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_BUFFERS_SIZE 16
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ SD_UNINIT = 0, /**< Not initialized. */
+ SD_STOP = 1, /**< Stopped. */
+ SD_READY = 2 /**< Ready. */
+} sdstate_t;
+
+/**
+ * @brief Structure representing a serial driver.
+ */
+typedef struct SerialDriver SerialDriver;
+
+#include "hal_serial_lld.h"
+
+/**
+ * @brief @p SerialDriver specific methods.
+ */
+#define _serial_driver_methods \
+ _base_asynchronous_channel_methods
+
+/**
+ * @extends BaseAsynchronousChannelVMT
+ *
+ * @brief @p SerialDriver virtual methods table.
+ */
+struct SerialDriverVMT {
+ _serial_driver_methods
+};
+
+/**
+ * @extends BaseAsynchronousChannel
+ *
+ * @brief Full duplex serial driver class.
+ * @details This class extends @p BaseAsynchronousChannel by adding physical
+ * I/O queues.
+ */
+struct SerialDriver {
+ /** @brief Virtual Methods Table.*/
+ const struct SerialDriverVMT *vmt;
+ _serial_driver_data
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Direct write to a @p SerialDriver.
+ * @note This function bypasses the indirect access to the channel and
+ * writes directly on the output queue. This is faster but cannot
+ * be used to write to different channels implementations.
+ *
+ * @iclass
+ */
+#define sdPutI(sdp, b) oqPutI(&(sdp)->oqueue, b)
+
+/**
+ * @brief Direct write to a @p SerialDriver.
+ * @note This function bypasses the indirect access to the channel and
+ * writes directly on the output queue. This is faster but cannot
+ * be used to write to different channels implementations.
+ *
+ * @api
+ */
+#define sdPut(sdp, b) oqPut(&(sdp)->oqueue, b)
+
+/**
+ * @brief Direct write to a @p SerialDriver with timeout specification.
+ * @note This function bypasses the indirect access to the channel and
+ * writes directly on the output queue. This is faster but cannot
+ * be used to write to different channels implementations.
+ *
+ * @api
+ */
+#define sdPutTimeout(sdp, b, t) oqPutTimeout(&(sdp)->oqueue, b, t)
+
+/**
+ * @brief Direct read from a @p SerialDriver.
+ * @note This function bypasses the indirect access to the channel and
+ * reads directly from the input queue. This is faster but cannot
+ * be used to read from different channels implementations.
+ *
+ * @iclass
+ */
+#define sdGetI(sdp) iqGetI(&(sdp)->iqueue)
+
+/**
+ * @brief Direct read from a @p SerialDriver.
+ * @note This function bypasses the indirect access to the channel and
+ * reads directly from the input queue. This is faster but cannot
+ * be used to read from different channels implementations.
+ *
+ * @api
+ */
+#define sdGet(sdp) iqGet(&(sdp)->iqueue)
+
+/**
+ * @brief Direct read from a @p SerialDriver with timeout specification.
+ * @note This function bypasses the indirect access to the channel and
+ * reads directly from the input queue. This is faster but cannot
+ * be used to read from different channels implementations.
+ *
+ * @api
+ */
+#define sdGetTimeout(sdp, t) iqGetTimeout(&(sdp)->iqueue, t)
+
+/**
+ * @brief Direct blocking write to a @p SerialDriver.
+ * @note This function bypasses the indirect access to the channel and
+ * writes directly to the output queue. This is faster but cannot
+ * be used to write from different channels implementations.
+ *
+ * @iclass
+ */
+#define sdWriteI(sdp, b, n) oqWriteI(&(sdp)->oqueue, b, n)
+
+/**
+ * @brief Direct blocking write to a @p SerialDriver.
+ * @note This function bypasses the indirect access to the channel and
+ * writes directly to the output queue. This is faster but cannot
+ * be used to write from different channels implementations.
+ *
+ * @api
+ */
+#define sdWrite(sdp, b, n) oqWriteTimeout(&(sdp)->oqueue, b, n, TIME_INFINITE)
+
+/**
+ * @brief Direct blocking write to a @p SerialDriver with timeout
+ * specification.
+ * @note This function bypasses the indirect access to the channel and
+ * writes directly to the output queue. This is faster but cannot
+ * be used to write to different channels implementations.
+ *
+ * @api
+ */
+#define sdWriteTimeout(sdp, b, n, t) \
+ oqWriteTimeout(&(sdp)->oqueue, b, n, t)
+
+/**
+ * @brief Direct non-blocking write to a @p SerialDriver.
+ * @note This function bypasses the indirect access to the channel and
+ * writes directly to the output queue. This is faster but cannot
+ * be used to write to different channels implementations.
+ *
+ * @api
+ */
+#define sdAsynchronousWrite(sdp, b, n) \
+ oqWriteTimeout(&(sdp)->oqueue, b, n, TIME_IMMEDIATE)
+
+/**
+ * @brief Direct blocking read from a @p SerialDriver.
+ * @note This function bypasses the indirect access to the channel and
+ * reads directly from the input queue. This is faster but cannot
+ * be used to read from different channels implementations.
+ *
+ * @iclass
+ */
+#define sdReadI(sdp, b, n) iqReadI(&(sdp)->iqueue, b, n, TIME_INFINITE)
+
+/**
+ * @brief Direct blocking read from a @p SerialDriver.
+ * @note This function bypasses the indirect access to the channel and
+ * reads directly from the input queue. This is faster but cannot
+ * be used to read from different channels implementations.
+ *
+ * @api
+ */
+#define sdRead(sdp, b, n) iqReadTimeout(&(sdp)->iqueue, b, n, TIME_INFINITE)
+
+/**
+ * @brief Direct blocking read from a @p SerialDriver with timeout
+ * specification.
+ * @note This function bypasses the indirect access to the channel and
+ * reads directly from the input queue. This is faster but cannot
+ * be used to read from different channels implementations.
+ *
+ * @api
+ */
+#define sdReadTimeout(sdp, b, n, t) iqReadTimeout(&(sdp)->iqueue, b, n, t)
+
+/**
+ * @brief Direct non-blocking read from a @p SerialDriver.
+ * @note This function bypasses the indirect access to the channel and
+ * reads directly from the input queue. This is faster but cannot
+ * be used to read from different channels implementations.
+ *
+ * @api
+ */
+#define sdAsynchronousRead(sdp, b, n) \
+ iqReadTimeout(&(sdp)->iqueue, b, n, TIME_IMMEDIATE)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void sdInit(void);
+#if !defined(SERIAL_ADVANCED_BUFFERING_SUPPORT) || \
+ (SERIAL_ADVANCED_BUFFERING_SUPPORT == FALSE)
+ void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify);
+#else
+ void sdObjectInit(SerialDriver *sdp);
+#endif
+ void sdStart(SerialDriver *sdp, const SerialConfig *config);
+ void sdStop(SerialDriver *sdp);
+ void sdIncomingDataI(SerialDriver *sdp, uint8_t b);
+ msg_t sdRequestDataI(SerialDriver *sdp);
+ bool sdPutWouldBlock(SerialDriver *sdp);
+ bool sdGetWouldBlock(SerialDriver *sdp);
+ msg_t sdControl(SerialDriver *sdp, unsigned int operation, void *arg);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SERIAL == TRUE */
+
+#endif /* HAL_SERIAL_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_serial_usb.h b/ChibiOS_20.3.2/os/hal/include/hal_serial_usb.h
new file mode 100644
index 0000000..0e32429
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_serial_usb.h
@@ -0,0 +1,197 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_serial_usb.h
+ * @brief Serial over USB Driver macros and structures.
+ *
+ * @addtogroup SERIAL_USB
+ * @{
+ */
+
+#ifndef HAL_SERIAL_USB_H
+#define HAL_SERIAL_USB_H
+
+#if (HAL_USE_SERIAL_USB == TRUE) || defined(__DOXYGEN__)
+
+#include "hal_usb_cdc.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name SERIAL_USB configuration options
+ * @{
+ */
+/**
+ * @brief Serial over USB buffers size.
+ * @details Configuration parameter, the buffer size must be a multiple of
+ * the USB data endpoint maximum packet size.
+ * @note The default is 256 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_SIZE 256
+#endif
+
+/**
+ * @brief Serial over USB number of buffers.
+ * @note The default is 2 buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_NUMBER 2
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if HAL_USE_USB == FALSE
+#error "Serial over USB Driver requires HAL_USE_USB"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ SDU_UNINIT = 0, /**< Not initialized. */
+ SDU_STOP = 1, /**< Stopped. */
+ SDU_READY = 2 /**< Ready. */
+} sdustate_t;
+
+/**
+ * @brief Structure representing a serial over USB driver.
+ */
+typedef struct SerialUSBDriver SerialUSBDriver;
+
+/**
+ * @brief Serial over USB Driver configuration structure.
+ * @details An instance of this structure must be passed to @p sduStart()
+ * in order to configure and start the driver operations.
+ */
+typedef struct {
+ /**
+ * @brief USB driver to use.
+ */
+ USBDriver *usbp;
+ /**
+ * @brief Bulk IN endpoint used for outgoing data transfer.
+ */
+ usbep_t bulk_in;
+ /**
+ * @brief Bulk OUT endpoint used for incoming data transfer.
+ */
+ usbep_t bulk_out;
+ /**
+ * @brief Interrupt IN endpoint used for notifications.
+ * @note If set to zero then the INT endpoint is assumed to be not
+ * present, USB descriptors must be changed accordingly.
+ */
+ usbep_t int_in;
+} SerialUSBConfig;
+
+/**
+ * @brief @p SerialDriver specific data.
+ */
+#define _serial_usb_driver_data \
+ _base_asynchronous_channel_data \
+ /* Driver state.*/ \
+ sdustate_t state; \
+ /* Input buffers queue.*/ \
+ input_buffers_queue_t ibqueue; \
+ /* Output queue.*/ \
+ output_buffers_queue_t obqueue; \
+ /* Input buffer.*/ \
+ uint8_t ib[BQ_BUFFER_SIZE(SERIAL_USB_BUFFERS_NUMBER, \
+ SERIAL_USB_BUFFERS_SIZE)]; \
+ /* Output buffer.*/ \
+ uint8_t ob[BQ_BUFFER_SIZE(SERIAL_USB_BUFFERS_NUMBER, \
+ SERIAL_USB_BUFFERS_SIZE)]; \
+ /* End of the mandatory fields.*/ \
+ /* Current configuration data.*/ \
+ const SerialUSBConfig *config;
+
+/**
+ * @brief @p SerialUSBDriver specific methods.
+ */
+#define _serial_usb_driver_methods \
+ _base_asynchronous_channel_methods
+
+/**
+ * @extends BaseAsynchronousChannelVMT
+ *
+ * @brief @p SerialDriver virtual methods table.
+ */
+struct SerialUSBDriverVMT {
+ _serial_usb_driver_methods
+};
+
+/**
+ * @extends BaseAsynchronousChannel
+ *
+ * @brief Full duplex serial driver class.
+ * @details This class extends @p BaseAsynchronousChannel by adding physical
+ * I/O queues.
+ */
+struct SerialUSBDriver {
+ /** @brief Virtual Methods Table.*/
+ const struct SerialUSBDriverVMT *vmt;
+ _serial_usb_driver_data
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void sduInit(void);
+ void sduObjectInit(SerialUSBDriver *sdup);
+ void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config);
+ void sduStop(SerialUSBDriver *sdup);
+ void sduSuspendHookI(SerialUSBDriver *sdup);
+ void sduWakeupHookI(SerialUSBDriver *sdup);
+ void sduConfigureHookI(SerialUSBDriver *sdup);
+ bool sduRequestsHook(USBDriver *usbp);
+ void sduSOFHookI(SerialUSBDriver *sdup);
+ void sduDataTransmitted(USBDriver *usbp, usbep_t ep);
+ void sduDataReceived(USBDriver *usbp, usbep_t ep);
+ void sduInterruptTransmitted(USBDriver *usbp, usbep_t ep);
+ msg_t sduControl(USBDriver *usbp, unsigned int operation, void *arg);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SERIAL_USB == TRUE */
+
+#endif /* HAL_SERIAL_USB_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_sio.h b/ChibiOS_20.3.2/os/hal/include/hal_sio.h
new file mode 100644
index 0000000..e10efee
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_sio.h
@@ -0,0 +1,208 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_sio.h
+ * @brief SIO Driver macros and structures.
+ *
+ * @addtogroup SIO
+ * @{
+ */
+
+#ifndef HAL_SIO_H
+#define HAL_SIO_H
+
+#if (HAL_USE_SIO == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name SIO status flags
+ * @{
+ */
+#define SIO_NO_ERROR 0 /**< @brief No pending conditions. */
+#define SIO_PARITY_ERROR 4 /**< @brief Parity error happened. */
+#define SIO_FRAMING_ERROR 8 /**< @brief Framing error happened. */
+#define SIO_OVERRUN_ERROR 16 /**< @brief Overflow happened. */
+#define SIO_NOISE_ERROR 32 /**< @brief Noise on the line. */
+#define SIO_BREAK_DETECTED 64 /**< @brief Break detected. */
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name SIO configuration options
+ * @{
+ */
+
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of structure representing a SIO driver.
+ */
+typedef struct hal_sio_driver SIODriver;
+
+/**
+ * @brief Type of structure representing a SIO configuration.
+ */
+typedef struct hal_sio_config SIOConfig;
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ SIO_UNINIT = 0, /**< Not initialized. */
+ SIO_STOP = 1, /**< Stopped. */
+ SIO_READY = 2 /**< Ready. */
+} siostate_t;
+
+#include "hal_sio_lld.h"
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Returns the current set of flags and clears it.
+ */
+#define sioGetFlagsX(siop) sio_lld_get_flags(siop)
+
+/**
+ * @brief Determines the state of the RX FIFO.
+ *
+ * @param[in] siop pointer to the @p SIODriver object
+ * @return The RX FIFO state.
+ * @retval false if RX FIFO is not empty
+ * @retval true if RX FIFO is empty
+ *
+ * @xclass
+ */
+#define sioRXIsEmptyX(siop) sio_lld_rx_is_empty(siop)
+
+/**
+ * @brief Determines the state of the TX FIFO.
+ *
+ * @param[in] siop pointer to the @p SIODriver object
+ * @return The TX FIFO state.
+ * @retval false if TX FIFO is not full
+ * @retval true if TX FIFO is full
+ *
+ * @xclass
+ */
+#define sioTXIsFullX(siop) sio_lld_tx_is_full(siop)
+
+/**
+ * @brief Returns one frame from the RX FIFO.
+ * @note If the FIFO is empty then the returned value is unpredictable.
+ *
+ * @param[in] siop pointer to the @p SIODriver object
+ * @return The frame from RX FIFO.
+ *
+ * @xclass
+ */
+#define sioRXGetX(siop) sio_lld_rx_get(siop)
+
+/**
+ * @brief Pushes one frame into the TX FIFO.
+ * @note If the FIFO is full then the behavior is unpredictable.
+ *
+ * @param[in] siop pointer to the @p SIODriver object
+ * @param[in] data frame to be written
+ *
+ * @xclass
+ */
+#define sioTXPutX(siop, data) sio_lld_tx_put(siop, data)
+
+/**
+ * @brief Reads data from the RX FIFO.
+ * @details This function is non-blocking, data is read if present and the
+ * effective amount is returned.
+ * @note This function can be called from any context but it is meant to
+ * be called from the @p rxne_cb callback handler.
+ *
+ * @param[in] siop pointer to the @p SIODriver object
+ * @param[in] buffer buffer for the received data
+ * @param[in] size maximum number of frames to read
+ * @return The number of received frames.
+ *
+ * @xclass
+ */
+#define sioReadX(siop, buffer, size) sio_lld_read(siop, buffer, size)
+
+/**
+ * @brief Writes data into the TX FIFO.
+ * @details This function is non-blocking, data is written if there is space
+ * in the FIFO and the effective amount is returned.
+ * @note This function can be called from any context but it is meant to
+ * be called from the @p txnf_cb callback handler.
+ *
+ * @param[in] siop pointer to the @p SIODriver object
+ * @param[out] buffer buffer containing the data to be transmitted
+ * @param[in] size maximum number of frames to read
+ * @return The number of transmitted frames.
+ *
+ * @xclass
+ */
+#define sioWriteX(siop, buffer, size) sio_lld_write(siop, buffer, size)
+
+/**
+ * @brief Control operation on a serial port.
+ *
+ * @param[in] siop pointer to the @p SIODriver object
+ * @param[in] operation control operation code
+ * @param[in,out] arg operation argument
+ *
+ * @return The control operation status.
+ * @retval MSG_OK in case of success.
+ * @retval MSG_TIMEOUT in case of operation timeout.
+ * @retval MSG_RESET in case of operation reset.
+ *
+ * @xclass
+ */
+#define sioControlX(siop, operation, arg) sio_lld_control(siop, operation, arg)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void sioInit(void);
+ void sioObjectInit(SIODriver *siop);
+ void sioStart(SIODriver *siop, const SIOConfig *config);
+ void sioStop(SIODriver *siop);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SIO == TRUE */
+
+#endif /* HAL_SIO_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_spi.h b/ChibiOS_20.3.2/os/hal/include/hal_spi.h
new file mode 100644
index 0000000..35b42c9
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_spi.h
@@ -0,0 +1,532 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_spi.h
+ * @brief SPI Driver macros and structures.
+ *
+ * @addtogroup SPI
+ * @{
+ */
+
+#ifndef HAL_SPI_H
+#define HAL_SPI_H
+
+#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Chip Select modes
+ * @{
+ */
+#define SPI_SELECT_MODE_NONE 0 /** @brief @p spiSelect() and
+ @p spiUnselect() do
+ nothing. */
+#define SPI_SELECT_MODE_PAD 1 /** @brief Legacy mode. */
+#define SPI_SELECT_MODE_PORT 2 /** @brief Fastest mode. */
+#define SPI_SELECT_MODE_LINE 3 /** @brief Packed mode. */
+#define SPI_SELECT_MODE_LLD 4 /** @brief LLD-defined mode.*/
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name SPI configuration options
+ * @{
+ */
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
+#define SPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables circular transfers APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__)
+#define SPI_USE_CIRCULAR FALSE
+#endif
+
+/**
+ * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define SPI_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/**
+ * @brief Handling method for SPI CS line.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__)
+#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if (SPI_SELECT_MODE != SPI_SELECT_MODE_NONE) && \
+ (SPI_SELECT_MODE != SPI_SELECT_MODE_PAD) && \
+ (SPI_SELECT_MODE != SPI_SELECT_MODE_PORT) && \
+ (SPI_SELECT_MODE != SPI_SELECT_MODE_LINE) && \
+ (SPI_SELECT_MODE != SPI_SELECT_MODE_LLD)
+#error "invalid SPI_SELECT_MODE setting"
+#endif
+
+/* Some modes have a dependency on the PAL driver, making the required
+ checks here.*/
+#if ((SPI_SELECT_MODE != SPI_SELECT_MODE_PAD) || \
+ (SPI_SELECT_MODE != SPI_SELECT_MODE_PORT) || \
+ (SPI_SELECT_MODE != SPI_SELECT_MODE_LINE)) && \
+ (HAL_USE_PAL != TRUE)
+#error "current SPI_SELECT_MODE requires HAL_USE_PAL"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ SPI_UNINIT = 0, /**< Not initialized. */
+ SPI_STOP = 1, /**< Stopped. */
+ SPI_READY = 2, /**< Ready. */
+ SPI_ACTIVE = 3, /**< Exchanging data. */
+ SPI_COMPLETE = 4 /**< Asynchronous operation complete. */
+} spistate_t;
+
+/**
+ * @brief Type of a structure representing an SPI driver.
+ */
+typedef struct hal_spi_driver SPIDriver;
+/**
+ * @brief Type of a SPI driver configuration structure.
+ */
+typedef struct hal_spi_config SPIConfig;
+
+/**
+ * @brief SPI notification callback type.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object triggering the
+ * callback
+ */
+typedef void (*spicallback_t)(SPIDriver *spip);
+
+/* Including the low level driver header, it exports information required
+ for completing types.*/
+#include "hal_spi_lld.h"
+
+/**
+ * @brief Driver configuration structure.
+ */
+struct hal_spi_config {
+#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Enables the circular buffer mode.
+ */
+ bool circular;
+#endif
+ /**
+ * @brief Operation complete callback or @p NULL.
+ */
+ spicallback_t end_cb;
+#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LINE) || defined(__DOXYGEN__)
+ /**
+ * @brief The chip select line.
+ */
+ ioline_t ssline;
+#endif
+#if (SPI_SELECT_MODE == SPI_SELECT_MODE_PORT) || defined(__DOXYGEN__)
+ /**
+ * @brief The chip select port.
+ */
+ ioportid_t ssport;
+ /**
+ * @brief The chip select port mask.
+ */
+ ioportmask_t ssmask;
+#endif
+#if (SPI_SELECT_MODE == SPI_SELECT_MODE_PAD) || defined(__DOXYGEN__)
+ /**
+ * @brief The chip select port.
+ */
+ ioportid_t ssport;
+ /**
+ * @brief The chip select pad number.
+ */
+ uint_fast8_t sspad;
+#endif
+ /* End of the mandatory fields.*/
+ spi_lld_config_fields;
+};
+
+/**
+ * @brief Structure representing an SPI driver.
+ */
+struct hal_spi_driver {
+ /**
+ * @brief Driver state.
+ */
+ spistate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const SPIConfig *config;
+#if (SPI_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Waiting thread.
+ */
+ thread_reference_t thread;
+#endif /* SPI_USE_WAIT == TRUE */
+#if (SPI_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Mutex protecting the peripheral.
+ */
+ mutex_t mutex;
+#endif /* SPI_USE_MUTUAL_EXCLUSION == TRUE */
+#if defined(SPI_DRIVER_EXT_FIELDS)
+ SPI_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ spi_lld_driver_fields;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Buffer state.
+ * @note This function is meant to be called from the SPI callback only.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @return The buffer state.
+ * @retval false if the driver filled/sent the first half of the
+ * buffer.
+ * @retval true if the driver filled/sent the second half of the
+ * buffer.
+ *
+ * @special
+ */
+#define spiIsBufferComplete(spip) ((bool)((spip)->state == SPI_COMPLETE))
+
+#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__)
+/**
+ * @brief Asserts the slave select signal and prepares for transfers.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @iclass
+ */
+#define spiSelectI(spip) \
+do { \
+ spi_lld_select(spip); \
+} while (false)
+
+/**
+ * @brief Deasserts the slave select signal.
+ * @details The previously selected peripheral is unselected.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @iclass
+ */
+#define spiUnselectI(spip) \
+do { \
+ spi_lld_unselect(spip); \
+} while (false)
+
+#elif SPI_SELECT_MODE == SPI_SELECT_MODE_LINE
+#define spiSelectI(spip) \
+do { \
+ palClearLine((spip)->config->ssline); \
+} while (false)
+
+#define spiUnselectI(spip) \
+do { \
+ palSetLine((spip)->config->ssline); \
+} while (false)
+
+#elif SPI_SELECT_MODE == SPI_SELECT_MODE_PORT
+#define spiSelectI(spip) \
+do { \
+ palClearPort((spip)->config->ssport, (spip)->config->ssmask); \
+} while (false)
+
+#define spiUnselectI(spip) \
+do { \
+ palSetPort((spip)->config->ssport, (spip)->config->ssmask); \
+} while (false)
+
+#elif SPI_SELECT_MODE == SPI_SELECT_MODE_PAD
+#define spiSelectI(spip) \
+do { \
+ palClearPad((spip)->config->ssport, (spip)->config->sspad); \
+} while (false)
+
+#define spiUnselectI(spip) \
+do { \
+ palSetPad((spip)->config->ssport, (spip)->config->sspad); \
+} while (false)
+
+#elif SPI_SELECT_MODE == SPI_SELECT_MODE_NONE
+#define spiSelectI(spip)
+
+#define spiUnselectI(spip)
+#endif
+
+/**
+ * @brief Ignores data on the SPI bus.
+ * @details This asynchronous function starts the transmission of a series of
+ * idle words on the SPI bus and ignores the received data.
+ * @pre A slave must have been selected using @p spiSelect() or
+ * @p spiSelectI().
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be ignored
+ *
+ * @iclass
+ */
+#define spiStartIgnoreI(spip, n) { \
+ (spip)->state = SPI_ACTIVE; \
+ spi_lld_ignore(spip, n); \
+}
+
+/**
+ * @brief Exchanges data on the SPI bus.
+ * @details This asynchronous function starts a simultaneous transmit/receive
+ * operation.
+ * @pre A slave must have been selected using @p spiSelect() or
+ * @p spiSelectI().
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be exchanged
+ * @param[in] txbuf the pointer to the transmit buffer
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @iclass
+ */
+#define spiStartExchangeI(spip, n, txbuf, rxbuf) { \
+ (spip)->state = SPI_ACTIVE; \
+ spi_lld_exchange(spip, n, txbuf, rxbuf); \
+}
+
+/**
+ * @brief Sends data over the SPI bus.
+ * @details This asynchronous function starts a transmit operation.
+ * @pre A slave must have been selected using @p spiSelect() or
+ * @p spiSelectI().
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @iclass
+ */
+#define spiStartSendI(spip, n, txbuf) { \
+ (spip)->state = SPI_ACTIVE; \
+ spi_lld_send(spip, n, txbuf); \
+}
+
+/**
+ * @brief Receives data from the SPI bus.
+ * @details This asynchronous function starts a receive operation.
+ * @pre A slave must have been selected using @p spiSelect() or
+ * @p spiSelectI().
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to receive
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @iclass
+ */
+#define spiStartReceiveI(spip, n, rxbuf) { \
+ (spip)->state = SPI_ACTIVE; \
+ spi_lld_receive(spip, n, rxbuf); \
+}
+
+/**
+ * @brief Exchanges one frame using a polled wait.
+ * @details This synchronous function exchanges one frame using a polled
+ * synchronization method. This function is useful when exchanging
+ * small amount of data on high speed channels, usually in this
+ * situation is much more efficient just wait for completion using
+ * polling than suspending the thread waiting for an interrupt.
+ * @note This API is implemented as a macro in order to minimize latency.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] frame the data frame to send over the SPI bus
+ * @return The received data frame from the SPI bus.
+ */
+#define spiPolledExchange(spip, frame) spi_lld_polled_exchange(spip, frame)
+/** @} */
+
+/**
+ * @name Low level driver helper macros
+ * @{
+ */
+#if (SPI_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Wakes up the waiting thread.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+#define _spi_wakeup_isr(spip) { \
+ osalSysLockFromISR(); \
+ osalThreadResumeI(&(spip)->thread, MSG_OK); \
+ osalSysUnlockFromISR(); \
+}
+#else /* !SPI_USE_WAIT */
+#define _spi_wakeup_isr(spip)
+#endif /* !SPI_USE_WAIT */
+
+/**
+ * @brief Common ISR code when circular mode is not supported.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Waiting thread wakeup, if any.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+#define _spi_isr_code(spip) { \
+ if ((spip)->config->end_cb) { \
+ (spip)->state = SPI_COMPLETE; \
+ (spip)->config->end_cb(spip); \
+ if ((spip)->state == SPI_COMPLETE) \
+ (spip)->state = SPI_READY; \
+ } \
+ else \
+ (spip)->state = SPI_READY; \
+ _spi_wakeup_isr(spip); \
+}
+
+/**
+ * @brief Half buffer filled ISR code in circular mode.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+#define _spi_isr_half_code(spip) { \
+ if ((spip)->config->end_cb) { \
+ (spip)->config->end_cb(spip); \
+ } \
+}
+
+/**
+ * @brief Full buffer filled ISR code in circular mode.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+#define _spi_isr_full_code(spip) { \
+ if ((spip)->config->end_cb) { \
+ (spip)->state = SPI_COMPLETE; \
+ (spip)->config->end_cb(spip); \
+ if ((spip)->state == SPI_COMPLETE) \
+ (spip)->state = SPI_ACTIVE; \
+ } \
+}
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void spiInit(void);
+ void spiObjectInit(SPIDriver *spip);
+ void spiStart(SPIDriver *spip, const SPIConfig *config);
+ void spiStop(SPIDriver *spip);
+ void spiSelect(SPIDriver *spip);
+ void spiUnselect(SPIDriver *spip);
+ void spiStartIgnore(SPIDriver *spip, size_t n);
+ void spiStartExchange(SPIDriver *spip, size_t n,
+ const void *txbuf, void *rxbuf);
+ void spiStartSend(SPIDriver *spip, size_t n, const void *txbuf);
+ void spiStartReceive(SPIDriver *spip, size_t n, void *rxbuf);
+#if SPI_SUPPORTS_CIRCULAR == TRUE
+ void spiAbortI(SPIDriver *spip);
+ void spiAbort(SPIDriver *spip);
+#endif
+#if SPI_USE_WAIT == TRUE
+ void spiIgnore(SPIDriver *spip, size_t n);
+ void spiExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf);
+ void spiSend(SPIDriver *spip, size_t n, const void *txbuf);
+ void spiReceive(SPIDriver *spip, size_t n, void *rxbuf);
+#endif
+#if SPI_USE_MUTUAL_EXCLUSION == TRUE
+ void spiAcquireBus(SPIDriver *spip);
+ void spiReleaseBus(SPIDriver *spip);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SPI == TRUE */
+
+#endif /* HAL_SPI_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_st.h b/ChibiOS_20.3.2/os/hal/include/hal_st.h
new file mode 100644
index 0000000..ef8d985
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_st.h
@@ -0,0 +1,90 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_st.h
+ * @brief ST Driver macros and structures.
+ * @details This header is designed to be include-able without having to
+ * include other files from the HAL.
+ *
+ * @addtogroup ST
+ * @{
+ */
+
+#ifndef HAL_ST_H
+#define HAL_ST_H
+
+#include "hal_st_lld.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Compatibility with old LLDS.*/
+#if !defined(ST_LLD_NUM_ALARMS)
+#define ST_LLD_NUM_ALARMS 1
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+typedef void (*st_callback_t)(unsigned alarm);
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (ST_LLD_NUM_ALARMS > 1) && !defined(__DOXYGEN__)
+extern st_callback_t st_callbacks[ST_LLD_NUM_ALARMS - 1];
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void stInit(void);
+ void stStartAlarm(systime_t abstime);
+ void stStopAlarm(void);
+ void stSetAlarm(systime_t abstime);
+ systime_t stGetAlarm(void);
+ systime_t stGetCounter(void);
+ bool stIsAlarmActive(void);
+#if ST_LLD_NUM_ALARMS > 1
+ bool stIsAlarmActiveN(unsigned alarm);
+ void stStartAlarmN(unsigned alarm, systime_t abstime, st_callback_t cb);
+ void stStopAlarmN(unsigned alarm);
+ void stSetAlarmN(unsigned alarm, systime_t abstime);
+ systime_t stGetAlarmN(unsigned alarm);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_ST_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_streams.h b/ChibiOS_20.3.2/os/hal/include/hal_streams.h
new file mode 100644
index 0000000..bbdc653
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_streams.h
@@ -0,0 +1,156 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_streams.h
+ * @brief Data streams.
+ * @details This header defines abstract interfaces useful to access generic
+ * data streams in a standardized way.
+ *
+ * @addtogroup HAL_STREAMS
+ * @details This module define an abstract interface for generic data streams.
+ * Note that no code is present, just abstract interfaces-like
+ * structures, you should look at the system as to a set of
+ * abstract C++ classes (even if written in C). This system
+ * has then advantage to make the access to data streams
+ * independent from the implementation logic.
+ * The stream interface can be used as base class for high level
+ * object types such as files, sockets, serial ports, pipes etc.
+ * @{
+ */
+
+#ifndef HAL_STREAMS_H
+#define HAL_STREAMS_H
+
+/**
+ * @name Streams return codes
+ * @{
+ */
+#define STM_OK MSG_OK
+#define STM_TIMEOUT MSG_TIMEOUT
+#define STM_RESET MSG_RESET
+/** @} */
+
+/**
+ * @brief BaseSequentialStream specific methods.
+ */
+#define _base_sequential_stream_methods \
+ _base_object_methods \
+ /* Stream write buffer method.*/ \
+ size_t (*write)(void *instance, const uint8_t *bp, size_t n); \
+ /* Stream read buffer method.*/ \
+ size_t (*read)(void *instance, uint8_t *bp, size_t n); \
+ /* Channel put method, blocking.*/ \
+ msg_t (*put)(void *instance, uint8_t b); \
+ /* Channel get method, blocking.*/ \
+ msg_t (*get)(void *instance); \
+
+/**
+ * @brief @p BaseSequentialStream specific data.
+ * @note It is empty because @p BaseSequentialStream is only an interface
+ * without implementation.
+ */
+#define _base_sequential_stream_data \
+ _base_object_data
+
+/**
+ * @brief @p BaseSequentialStream virtual methods table.
+ */
+struct BaseSequentialStreamVMT {
+ _base_sequential_stream_methods
+};
+
+/**
+ * @extends BaseObject
+ *
+ * @brief Base stream class.
+ * @details This class represents a generic blocking unbuffered sequential
+ * data stream.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct BaseSequentialStreamVMT *vmt;
+ _base_sequential_stream_data
+} BaseSequentialStream;
+
+/**
+ * @name Macro Functions (BaseSequentialStream)
+ * @{
+ */
+/**
+ * @brief Sequential Stream write.
+ * @details The function writes data from a buffer to a stream.
+ *
+ * @param[in] ip pointer to a @p BaseSequentialStream or derived class
+ * @param[in] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred
+ * @return The number of bytes transferred. The return value can
+ * be less than the specified number of bytes if an
+ * end-of-file condition has been met.
+ *
+ * @api
+ */
+#define streamWrite(ip, bp, n) ((ip)->vmt->write(ip, bp, n))
+
+/**
+ * @brief Sequential Stream read.
+ * @details The function reads data from a stream into a buffer.
+ *
+ * @param[in] ip pointer to a @p BaseSequentialStream or derived class
+ * @param[out] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred
+ * @return The number of bytes transferred. The return value can
+ * be less than the specified number of bytes if an
+ * end-of-file condition has been met.
+ *
+ * @api
+ */
+#define streamRead(ip, bp, n) ((ip)->vmt->read(ip, bp, n))
+
+/**
+ * @brief Sequential Stream blocking byte write.
+ * @details This function writes a byte value to a channel. If the channel
+ * is not ready to accept data then the calling thread is suspended.
+ *
+ * @param[in] ip pointer to a @p BaseChannel or derived class
+ * @param[in] b the byte value to be written to the channel
+ *
+ * @return The operation status.
+ * @retval STM_OK if the operation succeeded.
+ * @retval STM_RESET if an end-of-file condition has been met.
+ *
+ * @api
+ */
+#define streamPut(ip, b) ((ip)->vmt->put(ip, b))
+
+/**
+ * @brief Sequential Stream blocking byte read.
+ * @details This function reads a byte value from a channel. If the data
+ * is not available then the calling thread is suspended.
+ *
+ * @param[in] ip pointer to a @p BaseChannel or derived class
+ *
+ * @return A byte value from the queue.
+ * @retval STM_RESET if an end-of-file condition has been met.
+ *
+ * @api
+ */
+#define streamGet(ip) ((ip)->vmt->get(ip))
+/** @} */
+
+#endif /* HAL_STREAMS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_trng.h b/ChibiOS_20.3.2/os/hal/include/hal_trng.h
new file mode 100644
index 0000000..0e3648a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_trng.h
@@ -0,0 +1,122 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_trng.h
+ * @brief TRNG Driver macros and structures.
+ *
+ * @addtogroup TRNG
+ * @{
+ */
+
+#ifndef HAL_TRNG_H
+#define HAL_TRNG_H
+
+#if (HAL_USE_TRNG == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ TRNG_UNINIT = 0, /**< Not initialized. */
+ TRNG_STOP = 1, /**< Stopped. */
+ TRNG_READY = 2, /**< Ready. */
+ TRNG_RUNNING = 3 /**< Generating random number. */
+} trngstate_t;
+
+/**
+ * @brief Type of a structure representing a TRNG driver.
+ */
+typedef struct hal_trng_driver TRNGDriver;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct hal_trng_config TRNGConfig;
+
+/* Including the low level driver header, it exports information required
+ for completing types.*/
+#include "hal_trng_lld.h"
+
+/**
+ * @brief Driver configuration structure.
+ */
+struct hal_trng_config {
+ /* End of the mandatory fields.*/
+ trng_lld_config_fields;
+};
+
+/**
+ * @brief Structure representing a TRNG driver.
+ */
+struct hal_trng_driver {
+ /**
+ * @brief Driver state.
+ */
+ trngstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const TRNGConfig *config;
+#if defined(TRNG_DRIVER_EXT_FIELDS)
+ TRNG_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ trng_lld_driver_fields;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void trngInit(void);
+ void trngObjectInit(TRNGDriver *trngp);
+ void trngStart(TRNGDriver *trngp, const TRNGConfig *config);
+ void trngStop(TRNGDriver *trngp);
+ bool trngGenerate(TRNGDriver *trngp, size_t size, uint8_t *out);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_TRNG == TRUE */
+
+#endif /* HAL_TRNG_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_uart.h b/ChibiOS_20.3.2/os/hal/include/hal_uart.h
new file mode 100644
index 0000000..a074649
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_uart.h
@@ -0,0 +1,425 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_uart.h
+ * @brief UART Driver macros and structures.
+ *
+ * @addtogroup UART
+ * @{
+ */
+
+#ifndef HAL_UART_H
+#define HAL_UART_H
+
+#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name UART status flags
+ * @{
+ */
+#define UART_NO_ERROR 0 /**< @brief No pending conditions. */
+#define UART_PARITY_ERROR 4 /**< @brief Parity error happened. */
+#define UART_FRAMING_ERROR 8 /**< @brief Framing error happened. */
+#define UART_OVERRUN_ERROR 16 /**< @brief Overflow happened. */
+#define UART_NOISE_ERROR 32 /**< @brief Noise on the line. */
+#define UART_BREAK_DETECTED 64 /**< @brief Break detected. */
+/** @} */
+
+/**
+ * @name UART error conditions
+ * @{
+ */
+#define UART_ERR_NOT_ACTIVE (size_t)-1
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name UART configuration options
+ * @{
+ */
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__)
+#define UART_USE_WAIT FALSE
+#endif
+
+/**
+ * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define UART_USE_MUTUAL_EXCLUSION FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ UART_UNINIT = 0, /**< Not initialized. */
+ UART_STOP = 1, /**< Stopped. */
+ UART_READY = 2 /**< Ready. */
+} uartstate_t;
+
+/**
+ * @brief Transmitter state machine states.
+ */
+typedef enum {
+ UART_TX_IDLE = 0, /**< Not transmitting. */
+ UART_TX_ACTIVE = 1, /**< Transmitting. */
+ UART_TX_COMPLETE = 2 /**< Buffer complete. */
+} uarttxstate_t;
+
+/**
+ * @brief Receiver state machine states.
+ */
+typedef enum {
+ UART_RX_IDLE = 0, /**< Not receiving. */
+ UART_RX_ACTIVE = 1, /**< Receiving. */
+ UART_RX_COMPLETE = 2 /**< Buffer complete. */
+} uartrxstate_t;
+
+#include "hal_uart_lld.h"
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Low level driver helper macros
+ * @{
+ */
+#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Wakes up the waiting thread in case of early TX complete.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+#define _uart_wakeup_tx1_isr(uartp) { \
+ if ((uartp)->early == true) { \
+ osalSysLockFromISR(); \
+ osalThreadResumeI(&(uartp)->threadtx, MSG_OK); \
+ osalSysUnlockFromISR(); \
+ } \
+}
+#else /* !UART_USE_WAIT */
+#define _uart_wakeup_tx1_isr(uartp)
+#endif /* !UART_USE_WAIT */
+
+#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Wakes up the waiting thread in case of late TX complete.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+#define _uart_wakeup_tx2_isr(uartp) { \
+ if ((uartp)->early == false) { \
+ osalSysLockFromISR(); \
+ osalThreadResumeI(&(uartp)->threadtx, MSG_OK); \
+ osalSysUnlockFromISR(); \
+ } \
+}
+#else /* !UART_USE_WAIT */
+#define _uart_wakeup_tx2_isr(uartp)
+#endif /* !UART_USE_WAIT */
+
+#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Wakes up the waiting thread in case of RX complete.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+#define _uart_wakeup_rx_complete_isr(uartp) { \
+ osalSysLockFromISR(); \
+ osalThreadResumeI(&(uartp)->threadrx, MSG_OK); \
+ osalSysUnlockFromISR(); \
+}
+#else /* !UART_USE_WAIT */
+#define _uart_wakeup_rx_complete_isr(uartp)
+#endif /* !UART_USE_WAIT */
+
+#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Wakes up the waiting thread in case of RX error.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+#define _uart_wakeup_rx_error_isr(uartp) { \
+ osalSysLockFromISR(); \
+ osalThreadResumeI(&(uartp)->threadrx, MSG_RESET); \
+ osalSysUnlockFromISR(); \
+}
+#else /* !UART_USE_WAIT */
+#define _uart_wakeup_rx_error_isr(uartp)
+#endif /* !UART_USE_WAIT */
+
+#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Wakes up the waiting thread in case of RX character match.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+#define _uart_wakeup_rx_cm_isr(uartp) { \
+ osalSysLockFromISR(); \
+ osalThreadResumeI(&(uartp)->threadrx, MSG_TIMEOUT); \
+ osalSysUnlockFromISR(); \
+}
+#else /* !UART_USE_WAIT */
+#define _uart_wakeup_rx_cm_isr(uartp)
+#endif /* !UART_USE_WAIT */
+
+#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Wakes up the waiting thread in case of RX timeout.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+#define _uart_wakeup_rx_timeout_isr(uartp) { \
+ osalSysLockFromISR(); \
+ osalThreadResumeI(&(uartp)->threadrx, MSG_TIMEOUT); \
+ osalSysUnlockFromISR(); \
+}
+#else /* !UART_USE_WAIT */
+#define _uart_wakeup_rx_timeout_isr(uartp)
+#endif /* !UART_USE_WAIT */
+
+/**
+ * @brief Common ISR code for early TX.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Waiting thread wakeup, if any.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+#define _uart_tx1_isr_code(uartp) { \
+ (uartp)->txstate = UART_TX_COMPLETE; \
+ if ((uartp)->config->txend1_cb != NULL) { \
+ (uartp)->config->txend1_cb(uartp); \
+ } \
+ if ((uartp)->txstate == UART_TX_COMPLETE) { \
+ (uartp)->txstate = UART_TX_IDLE; \
+ } \
+ _uart_wakeup_tx1_isr(uartp); \
+}
+
+/**
+ * @brief Common ISR code for late TX.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Waiting thread wakeup, if any.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+#define _uart_tx2_isr_code(uartp) { \
+ if ((uartp)->config->txend2_cb != NULL) { \
+ (uartp)->config->txend2_cb(uartp); \
+ } \
+ _uart_wakeup_tx2_isr(uartp); \
+}
+
+/**
+ * @brief Common ISR code for RX complete.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Waiting thread wakeup, if any.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+#define _uart_rx_complete_isr_code(uartp) { \
+ (uartp)->rxstate = UART_RX_COMPLETE; \
+ if ((uartp)->config->rxend_cb != NULL) { \
+ (uartp)->config->rxend_cb(uartp); \
+ } \
+ if ((uartp)->rxstate == UART_RX_COMPLETE) { \
+ (uartp)->rxstate = UART_RX_IDLE; \
+ uart_enter_rx_idle_loop(uartp); \
+ } \
+ _uart_wakeup_rx_complete_isr(uartp); \
+}
+
+/**
+ * @brief Common ISR code for RX error.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Waiting thread wakeup, if any.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] errors mask of errors to be reported
+ *
+ * @notapi
+ */
+#define _uart_rx_error_isr_code(uartp, errors) { \
+ if ((uartp)->config->rxerr_cb != NULL) { \
+ (uartp)->config->rxerr_cb(uartp, errors); \
+ } \
+ _uart_wakeup_rx_error_isr(uartp); \
+}
+
+/**
+ * @brief Common ISR code for RX on idle.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Waiting thread wakeup, if any.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+#define _uart_rx_idle_code(uartp) { \
+ if ((uartp)->config->rxchar_cb != NULL) \
+ (uartp)->config->rxchar_cb(uartp, (uartp)->rxbuf); \
+}
+
+/**
+ * @brief Timeout ISR code for receiver.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Waiting thread wakeup, if any.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+#define _uart_timeout_isr_code(uartp) { \
+ if ((uartp)->config->timeout_cb != NULL) { \
+ (uartp)->config->timeout_cb(uartp); \
+ } \
+ _uart_wakeup_rx_timeout_isr(uartp); \
+}
+
+/**
+ * @brief Character match ISR code for receiver.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Waiting thread wakeup, if any.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+#define _uart_rx_char_match_isr_code(uartp) { \
+ if ((uartp)->config->rx_cm_cb != NULL) { \
+ (uartp)->config->rx_cm_cb(uartp); \
+ } \
+ _uart_wakeup_rx_cm_isr(uartp); \
+}
+
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void uartInit(void);
+ void uartObjectInit(UARTDriver *uartp);
+ void uartStart(UARTDriver *uartp, const UARTConfig *config);
+ void uartStop(UARTDriver *uartp);
+ void uartStartSend(UARTDriver *uartp, size_t n, const void *txbuf);
+ void uartStartSendI(UARTDriver *uartp, size_t n, const void *txbuf);
+ size_t uartStopSend(UARTDriver *uartp);
+ size_t uartStopSendI(UARTDriver *uartp);
+ void uartStartReceive(UARTDriver *uartp, size_t n, void *rxbuf);
+ void uartStartReceiveI(UARTDriver *uartp, size_t n, void *rxbuf);
+ size_t uartStopReceive(UARTDriver *uartp);
+ size_t uartStopReceiveI(UARTDriver *uartp);
+#if UART_USE_WAIT == TRUE
+ msg_t uartSendTimeout(UARTDriver *uartp, size_t *np,
+ const void *txbuf, sysinterval_t timeout);
+ msg_t uartSendFullTimeout(UARTDriver *uartp, size_t *np,
+ const void *txbuf, sysinterval_t timeout);
+ msg_t uartReceiveTimeout(UARTDriver *uartp, size_t *np,
+ void *rxbuf, sysinterval_t timeout);
+#endif
+#if UART_USE_MUTUAL_EXCLUSION == TRUE
+ void uartAcquireBus(UARTDriver *uartp);
+ void uartReleaseBus(UARTDriver *uartp);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_UART == TRUE */
+
+#endif /* HAL_UART_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_usb.h b/ChibiOS_20.3.2/os/hal/include/hal_usb.h
new file mode 100644
index 0000000..9fe67a6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_usb.h
@@ -0,0 +1,638 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_usb.h
+ * @brief USB Driver macros and structures.
+ *
+ * @addtogroup USB
+ * @{
+ */
+
+#ifndef HAL_USB_H
+#define HAL_USB_H
+
+#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+#define USB_ENDPOINT_OUT(ep) (ep)
+#define USB_ENDPOINT_IN(ep) ((ep) | 0x80U)
+
+#define USB_RTYPE_DIR_MASK 0x80U
+#define USB_RTYPE_DIR_HOST2DEV 0x00U
+#define USB_RTYPE_DIR_DEV2HOST 0x80U
+#define USB_RTYPE_TYPE_MASK 0x60U
+#define USB_RTYPE_TYPE_STD 0x00U
+#define USB_RTYPE_TYPE_CLASS 0x20U
+#define USB_RTYPE_TYPE_VENDOR 0x40U
+#define USB_RTYPE_TYPE_RESERVED 0x60U
+#define USB_RTYPE_RECIPIENT_MASK 0x1FU
+#define USB_RTYPE_RECIPIENT_DEVICE 0x00U
+#define USB_RTYPE_RECIPIENT_INTERFACE 0x01U
+#define USB_RTYPE_RECIPIENT_ENDPOINT 0x02U
+#define USB_RTYPE_RECIPIENT_OTHER 0x03U
+
+#define USB_REQ_GET_STATUS 0U
+#define USB_REQ_CLEAR_FEATURE 1U
+#define USB_REQ_SET_FEATURE 3U
+#define USB_REQ_SET_ADDRESS 5U
+#define USB_REQ_GET_DESCRIPTOR 6U
+#define USB_REQ_SET_DESCRIPTOR 7U
+#define USB_REQ_GET_CONFIGURATION 8U
+#define USB_REQ_SET_CONFIGURATION 9U
+#define USB_REQ_GET_INTERFACE 10U
+#define USB_REQ_SET_INTERFACE 11U
+#define USB_REQ_SYNCH_FRAME 12U
+
+#define USB_DESCRIPTOR_DEVICE 1U
+#define USB_DESCRIPTOR_CONFIGURATION 2U
+#define USB_DESCRIPTOR_STRING 3U
+#define USB_DESCRIPTOR_INTERFACE 4U
+#define USB_DESCRIPTOR_ENDPOINT 5U
+#define USB_DESCRIPTOR_DEVICE_QUALIFIER 6U
+#define USB_DESCRIPTOR_OTHER_SPEED_CFG 7U
+#define USB_DESCRIPTOR_INTERFACE_POWER 8U
+#define USB_DESCRIPTOR_INTERFACE_ASSOCIATION 11U
+
+#define USB_FEATURE_ENDPOINT_HALT 0U
+#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1U
+#define USB_FEATURE_TEST_MODE 2U
+
+#define USB_EARLY_SET_ADDRESS 0
+#define USB_LATE_SET_ADDRESS 1
+
+#define USB_EP0_STATUS_STAGE_SW 0
+#define USB_EP0_STATUS_STAGE_HW 1
+
+#define USB_SET_ADDRESS_ACK_SW 0
+#define USB_SET_ADDRESS_ACK_HW 1
+
+/**
+ * @name Helper macros for USB descriptors
+ * @{
+ */
+/**
+ * @brief Helper macro for index values into descriptor strings.
+ */
+#define USB_DESC_INDEX(i) ((uint8_t)(i))
+
+/**
+ * @brief Helper macro for byte values into descriptor strings.
+ */
+#define USB_DESC_BYTE(b) ((uint8_t)(b))
+
+/**
+ * @brief Helper macro for word values into descriptor strings.
+ */
+#define USB_DESC_WORD(w) \
+ (uint8_t)((w) & 255U), \
+ (uint8_t)(((w) >> 8) & 255U)
+
+/**
+ * @brief Helper macro for BCD values into descriptor strings.
+ */
+#define USB_DESC_BCD(bcd) \
+ (uint8_t)((bcd) & 255U), \
+ (uint8_t)(((bcd) >> 8) & 255)
+
+/*
+ * @define Device Descriptor size.
+ */
+#define USB_DESC_DEVICE_SIZE 18U
+
+/**
+ * @brief Device Descriptor helper macro.
+ */
+#define USB_DESC_DEVICE(bcdUSB, bDeviceClass, bDeviceSubClass, \
+ bDeviceProtocol, bMaxPacketSize, idVendor, \
+ idProduct, bcdDevice, iManufacturer, \
+ iProduct, iSerialNumber, bNumConfigurations) \
+ USB_DESC_BYTE(USB_DESC_DEVICE_SIZE), \
+ USB_DESC_BYTE(USB_DESCRIPTOR_DEVICE), \
+ USB_DESC_BCD(bcdUSB), \
+ USB_DESC_BYTE(bDeviceClass), \
+ USB_DESC_BYTE(bDeviceSubClass), \
+ USB_DESC_BYTE(bDeviceProtocol), \
+ USB_DESC_BYTE(bMaxPacketSize), \
+ USB_DESC_WORD(idVendor), \
+ USB_DESC_WORD(idProduct), \
+ USB_DESC_BCD(bcdDevice), \
+ USB_DESC_INDEX(iManufacturer), \
+ USB_DESC_INDEX(iProduct), \
+ USB_DESC_INDEX(iSerialNumber), \
+ USB_DESC_BYTE(bNumConfigurations)
+
+/**
+ * @brief Configuration Descriptor size.
+ */
+#define USB_DESC_CONFIGURATION_SIZE 9U
+
+/**
+ * @brief Configuration Descriptor helper macro.
+ */
+#define USB_DESC_CONFIGURATION(wTotalLength, bNumInterfaces, \
+ bConfigurationValue, iConfiguration, \
+ bmAttributes, bMaxPower) \
+ USB_DESC_BYTE(USB_DESC_CONFIGURATION_SIZE), \
+ USB_DESC_BYTE(USB_DESCRIPTOR_CONFIGURATION), \
+ USB_DESC_WORD(wTotalLength), \
+ USB_DESC_BYTE(bNumInterfaces), \
+ USB_DESC_BYTE(bConfigurationValue), \
+ USB_DESC_INDEX(iConfiguration), \
+ USB_DESC_BYTE(bmAttributes), \
+ USB_DESC_BYTE(bMaxPower)
+
+/**
+ * @brief Interface Descriptor size.
+ */
+#define USB_DESC_INTERFACE_SIZE 9U
+
+/**
+ * @brief Interface Descriptor helper macro.
+ */
+#define USB_DESC_INTERFACE(bInterfaceNumber, bAlternateSetting, \
+ bNumEndpoints, bInterfaceClass, \
+ bInterfaceSubClass, bInterfaceProtocol, \
+ iInterface) \
+ USB_DESC_BYTE(USB_DESC_INTERFACE_SIZE), \
+ USB_DESC_BYTE(USB_DESCRIPTOR_INTERFACE), \
+ USB_DESC_BYTE(bInterfaceNumber), \
+ USB_DESC_BYTE(bAlternateSetting), \
+ USB_DESC_BYTE(bNumEndpoints), \
+ USB_DESC_BYTE(bInterfaceClass), \
+ USB_DESC_BYTE(bInterfaceSubClass), \
+ USB_DESC_BYTE(bInterfaceProtocol), \
+ USB_DESC_INDEX(iInterface)
+
+/**
+ * @brief Interface Association Descriptor size.
+ */
+#define USB_DESC_INTERFACE_ASSOCIATION_SIZE 8U
+
+/**
+ * @brief Interface Association Descriptor helper macro.
+ */
+#define USB_DESC_INTERFACE_ASSOCIATION(bFirstInterface, \
+ bInterfaceCount, bFunctionClass, \
+ bFunctionSubClass, bFunctionProcotol, \
+ iInterface) \
+ USB_DESC_BYTE(USB_DESC_INTERFACE_ASSOCIATION_SIZE), \
+ USB_DESC_BYTE(USB_DESCRIPTOR_INTERFACE_ASSOCIATION), \
+ USB_DESC_BYTE(bFirstInterface), \
+ USB_DESC_BYTE(bInterfaceCount), \
+ USB_DESC_BYTE(bFunctionClass), \
+ USB_DESC_BYTE(bFunctionSubClass), \
+ USB_DESC_BYTE(bFunctionProcotol), \
+ USB_DESC_INDEX(iInterface)
+
+/**
+ * @brief Endpoint Descriptor size.
+ */
+#define USB_DESC_ENDPOINT_SIZE 7U
+
+/**
+ * @brief Endpoint Descriptor helper macro.
+ */
+#define USB_DESC_ENDPOINT(bEndpointAddress, bmAttributes, wMaxPacketSize, \
+ bInterval) \
+ USB_DESC_BYTE(USB_DESC_ENDPOINT_SIZE), \
+ USB_DESC_BYTE(USB_DESCRIPTOR_ENDPOINT), \
+ USB_DESC_BYTE(bEndpointAddress), \
+ USB_DESC_BYTE(bmAttributes), \
+ USB_DESC_WORD(wMaxPacketSize), \
+ USB_DESC_BYTE(bInterval)
+/** @} */
+
+/**
+ * @name Endpoint types and settings
+ * @{
+ */
+#define USB_EP_MODE_TYPE 0x0003U /**< Endpoint type mask. */
+#define USB_EP_MODE_TYPE_CTRL 0x0000U /**< Control endpoint. */
+#define USB_EP_MODE_TYPE_ISOC 0x0001U /**< Isochronous endpoint. */
+#define USB_EP_MODE_TYPE_BULK 0x0002U /**< Bulk endpoint. */
+#define USB_EP_MODE_TYPE_INTR 0x0003U /**< Interrupt endpoint. */
+/** @} */
+
+#define USB_IN_STATE 0x08U
+#define USB_OUT_STATE 0x10U
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
+#define USB_USE_WAIT FALSE
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a structure representing an USB driver.
+ */
+typedef struct USBDriver USBDriver;
+
+/**
+ * @brief Type of an endpoint identifier.
+ */
+typedef uint8_t usbep_t;
+
+/**
+ * @brief Type of a driver state machine possible states.
+ */
+typedef enum {
+ USB_UNINIT = 0, /**< Not initialized. */
+ USB_STOP = 1, /**< Stopped. */
+ USB_READY = 2, /**< Ready, after bus reset. */
+ USB_SELECTED = 3, /**< Address assigned. */
+ USB_ACTIVE = 4, /**< Active, configuration selected.*/
+ USB_SUSPENDED = 5 /**< Suspended, low power mode. */
+} usbstate_t;
+
+/**
+ * @brief Type of an endpoint status.
+ */
+typedef enum {
+ EP_STATUS_DISABLED = 0, /**< Endpoint not active. */
+ EP_STATUS_STALLED = 1, /**< Endpoint opened but stalled. */
+ EP_STATUS_ACTIVE = 2 /**< Active endpoint. */
+} usbepstatus_t;
+
+/**
+ * @brief Type of an endpoint zero state machine states.
+ */
+typedef enum {
+ USB_EP0_STP_WAITING = 0U, /**< Waiting for SETUP data.*/
+ USB_EP0_IN_TX = USB_IN_STATE | 1U, /**< Transmitting. */
+ USB_EP0_IN_WAITING_TX0 = USB_IN_STATE | 2U, /**< Waiting transmit 0. */
+ USB_EP0_IN_SENDING_STS = USB_IN_STATE | 3U, /**< Sending status. */
+ USB_EP0_OUT_WAITING_STS = USB_OUT_STATE | 4U, /**< Waiting status. */
+ USB_EP0_OUT_RX = USB_OUT_STATE | 5U, /**< Receiving. */
+ USB_EP0_ERROR = 6U /**< Error, EP0 stalled. */
+} usbep0state_t;
+
+/**
+ * @brief Type of an enumeration of the possible USB events.
+ */
+typedef enum {
+ USB_EVENT_RESET = 0, /**< Driver has been reset by host. */
+ USB_EVENT_ADDRESS = 1, /**< Address assigned. */
+ USB_EVENT_CONFIGURED = 2, /**< Configuration selected. */
+ USB_EVENT_UNCONFIGURED = 3, /**< Configuration removed. */
+ USB_EVENT_SUSPEND = 4, /**< Entering suspend mode. */
+ USB_EVENT_WAKEUP = 5, /**< Leaving suspend mode. */
+ USB_EVENT_STALLED = 6 /**< Endpoint 0 error, stalled. */
+} usbevent_t;
+
+/**
+ * @brief Type of an USB descriptor.
+ */
+typedef struct {
+ /**
+ * @brief Descriptor size in unicode characters.
+ */
+ size_t ud_size;
+ /**
+ * @brief Pointer to the descriptor.
+ */
+ const uint8_t *ud_string;
+} USBDescriptor;
+
+/**
+ * @brief Type of an USB generic notification callback.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object triggering the
+ * callback
+ */
+typedef void (*usbcallback_t)(USBDriver *usbp);
+
+/**
+ * @brief Type of an USB endpoint callback.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object triggering the
+ * callback
+ * @param[in] ep endpoint number
+ */
+typedef void (*usbepcallback_t)(USBDriver *usbp, usbep_t ep);
+
+/**
+ * @brief Type of an USB event notification callback.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object triggering the
+ * callback
+ * @param[in] event event type
+ */
+typedef void (*usbeventcb_t)(USBDriver *usbp, usbevent_t event);
+
+/**
+ * @brief Type of a requests handler callback.
+ * @details The request is encoded in the @p usb_setup buffer.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object triggering the
+ * callback
+ * @return The request handling exit code.
+ * @retval false Request not recognized by the handler.
+ * @retval true Request handled.
+ */
+typedef bool (*usbreqhandler_t)(USBDriver *usbp);
+
+/**
+ * @brief Type of an USB descriptor-retrieving callback.
+ */
+typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
+ uint8_t dtype,
+ uint8_t dindex,
+ uint16_t lang);
+
+#include "hal_usb_lld.h"
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Returns the driver state.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @return The driver state.
+ *
+ * @iclass
+ */
+#define usbGetDriverStateI(usbp) ((usbp)->state)
+
+/**
+ * @brief Connects the USB device.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @api
+ */
+#define usbConnectBus(usbp) usb_lld_connect_bus(usbp)
+
+/**
+ * @brief Disconnect the USB device.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @api
+ */
+#define usbDisconnectBus(usbp) usb_lld_disconnect_bus(usbp)
+
+/**
+ * @brief Returns the current frame number.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @return The current frame number.
+ *
+ * @xclass
+ */
+#define usbGetFrameNumberX(usbp) usb_lld_get_frame_number(usbp)
+
+/**
+ * @brief Returns the status of an IN endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @return The operation status.
+ * @retval false Endpoint ready.
+ * @retval true Endpoint transmitting.
+ *
+ * @iclass
+ */
+#define usbGetTransmitStatusI(usbp, ep) \
+ (((usbp)->transmitting & (uint16_t)((unsigned)1U << (unsigned)(ep))) != 0U)
+
+/**
+ * @brief Returns the status of an OUT endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @return The operation status.
+ * @retval false Endpoint ready.
+ * @retval true Endpoint receiving.
+ *
+ * @iclass
+ */
+#define usbGetReceiveStatusI(usbp, ep) \
+ (((usbp)->receiving & (uint16_t)((unsigned)1U << (unsigned)(ep))) != 0U)
+
+/**
+ * @brief Returns the exact size of a receive transaction.
+ * @details The received size can be different from the size specified in
+ * @p usbStartReceiveI() because the last packet could have a size
+ * different from the expected one.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @return Received data size.
+ *
+ * @xclass
+ */
+#define usbGetReceiveTransactionSizeX(usbp, ep) \
+ usb_lld_get_transaction_size(usbp, ep)
+
+/**
+ * @brief Request transfer setup.
+ * @details This macro is used by the request handling callbacks in order to
+ * prepare a transaction over the endpoint zero.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] buf pointer to a buffer for the transaction data
+ * @param[in] n number of bytes to be transferred
+ * @param[in] endcb callback to be invoked after the transfer or @p NULL
+ *
+ * @special
+ */
+#define usbSetupTransfer(usbp, buf, n, endcb) { \
+ (usbp)->ep0next = (buf); \
+ (usbp)->ep0n = (n); \
+ (usbp)->ep0endcb = (endcb); \
+}
+
+/**
+ * @brief Reads a setup packet from the dedicated packet buffer.
+ * @details This function must be invoked in the context of the @p setup_cb
+ * callback in order to read the received setup packet.
+ * @pre In order to use this function the endpoint must have been
+ * initialized as a control endpoint.
+ * @note This function can be invoked both in thread and IRQ context.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[out] buf buffer where to copy the packet data
+ *
+ * @special
+ */
+#define usbReadSetup(usbp, ep, buf) usb_lld_read_setup(usbp, ep, buf)
+/** @} */
+
+/**
+ * @name Low level driver helper macros
+ * @{
+ */
+/**
+ * @brief Common ISR code, usb event callback.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] evt USB event code
+ *
+ * @notapi
+ */
+#define _usb_isr_invoke_event_cb(usbp, evt) { \
+ if (((usbp)->config->event_cb) != NULL) { \
+ (usbp)->config->event_cb(usbp, evt); \
+ } \
+}
+
+/**
+ * @brief Common ISR code, SOF callback.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+#define _usb_isr_invoke_sof_cb(usbp) { \
+ if (((usbp)->config->sof_cb) != NULL) { \
+ (usbp)->config->sof_cb(usbp); \
+ } \
+}
+
+/**
+ * @brief Common ISR code, setup packet callback.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+#define _usb_isr_invoke_setup_cb(usbp, ep) { \
+ (usbp)->epc[ep]->setup_cb(usbp, ep); \
+}
+
+/**
+ * @brief Common ISR code, IN endpoint callback.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+#define _usb_isr_invoke_in_cb(usbp, ep) { \
+ (usbp)->transmitting &= ~(1 << (ep)); \
+ if ((usbp)->epc[ep]->in_cb != NULL) { \
+ (usbp)->epc[ep]->in_cb(usbp, ep); \
+ } \
+ osalSysLockFromISR(); \
+ osalThreadResumeI(&(usbp)->epc[ep]->in_state->thread, MSG_OK); \
+ osalSysUnlockFromISR(); \
+}
+#else
+#define _usb_isr_invoke_in_cb(usbp, ep) { \
+ (usbp)->transmitting &= ~(1 << (ep)); \
+ if ((usbp)->epc[ep]->in_cb != NULL) { \
+ (usbp)->epc[ep]->in_cb(usbp, ep); \
+ } \
+}
+#endif
+
+/**
+ * @brief Common ISR code, OUT endpoint event.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+#define _usb_isr_invoke_out_cb(usbp, ep) { \
+ (usbp)->receiving &= ~(1 << (ep)); \
+ if ((usbp)->epc[ep]->out_cb != NULL) { \
+ (usbp)->epc[ep]->out_cb(usbp, ep); \
+ } \
+ osalSysLockFromISR(); \
+ osalThreadResumeI(&(usbp)->epc[ep]->out_state->thread, \
+ usbGetReceiveTransactionSizeX(usbp, ep)); \
+ osalSysUnlockFromISR(); \
+}
+#else
+#define _usb_isr_invoke_out_cb(usbp, ep) { \
+ (usbp)->receiving &= ~(1 << (ep)); \
+ if ((usbp)->epc[ep]->out_cb != NULL) { \
+ (usbp)->epc[ep]->out_cb(usbp, ep); \
+ } \
+}
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void usbInit(void);
+ void usbObjectInit(USBDriver *usbp);
+ void usbStart(USBDriver *usbp, const USBConfig *config);
+ void usbStop(USBDriver *usbp);
+ void usbInitEndpointI(USBDriver *usbp, usbep_t ep,
+ const USBEndpointConfig *epcp);
+ void usbDisableEndpointsI(USBDriver *usbp);
+ void usbReadSetupI(USBDriver *usbp, usbep_t ep, uint8_t *buf);
+ void usbStartReceiveI(USBDriver *usbp, usbep_t ep,
+ uint8_t *buf, size_t n);
+ void usbStartTransmitI(USBDriver *usbp, usbep_t ep,
+ const uint8_t *buf, size_t n);
+#if USB_USE_WAIT == TRUE
+ msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n);
+ msg_t usbTransmit(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n);
+#endif
+ bool usbStallReceiveI(USBDriver *usbp, usbep_t ep);
+ bool usbStallTransmitI(USBDriver *usbp, usbep_t ep);
+ void usbWakeupHost(USBDriver *usbp);
+ void _usb_reset(USBDriver *usbp);
+ void _usb_suspend(USBDriver *usbp);
+ void _usb_wakeup(USBDriver *usbp);
+ void _usb_ep0setup(USBDriver *usbp, usbep_t ep);
+ void _usb_ep0in(USBDriver *usbp, usbep_t ep);
+ void _usb_ep0out(USBDriver *usbp, usbep_t ep);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_USB == TRUE */
+
+#endif /* HAL_USB_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_usb_cdc.h b/ChibiOS_20.3.2/os/hal/include/hal_usb_cdc.h
new file mode 100644
index 0000000..4eaf905
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_usb_cdc.h
@@ -0,0 +1,136 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_usb_cdc.h
+ * @brief USB CDC macros and structures.
+ *
+ * @addtogroup USB_CDC
+ * @{
+ */
+
+#ifndef USB_CDC_H
+#define USB_CDC_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name CDC specific messages.
+ * @{
+ */
+#define CDC_SEND_ENCAPSULATED_COMMAND 0x00U
+#define CDC_GET_ENCAPSULATED_RESPONSE 0x01U
+#define CDC_SET_COMM_FEATURE 0x02U
+#define CDC_GET_COMM_FEATURE 0x03U
+#define CDC_CLEAR_COMM_FEATURE 0x04U
+#define CDC_SET_AUX_LINE_STATE 0x10U
+#define CDC_SET_HOOK_STATE 0x11U
+#define CDC_PULSE_SETUP 0x12U
+#define CDC_SEND_PULSE 0x13U
+#define CDC_SET_PULSE_TIME 0x14U
+#define CDC_RING_AUX_JACK 0x15U
+#define CDC_SET_LINE_CODING 0x20U
+#define CDC_GET_LINE_CODING 0x21U
+#define CDC_SET_CONTROL_LINE_STATE 0x22U
+#define CDC_SEND_BREAK 0x23U
+#define CDC_SET_RINGER_PARMS 0x30U
+#define CDC_GET_RINGER_PARMS 0x31U
+#define CDC_SET_OPERATION_PARMS 0x32U
+#define CDC_GET_OPERATION_PARMS 0x33U
+/** @} */
+
+/**
+ * @name CDC classes
+ * @{
+ */
+#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02U
+#define CDC_DATA_INTERFACE_CLASS 0x0AU
+/** @} */
+
+/**
+ * @name CDC subclasses
+ * @{
+ */
+#define CDC_ABSTRACT_CONTROL_MODEL 0x02U
+/** @} */
+
+/**
+ * @name CDC descriptors
+ * @{
+ */
+#define CDC_CS_INTERFACE 0x24U
+/** @} */
+
+/**
+ * @name CDC subdescriptors
+ * @{
+ */
+#define CDC_HEADER 0x00U
+#define CDC_CALL_MANAGEMENT 0x01U
+#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02U
+#define CDC_UNION 0x06U
+/** @} */
+
+/**
+ * @name Line Control bit definitions.
+ * @{
+ */
+#define LC_STOP_1 0U
+#define LC_STOP_1P5 1U
+#define LC_STOP_2 2U
+
+#define LC_PARITY_NONE 0U
+#define LC_PARITY_ODD 1U
+#define LC_PARITY_EVEN 2U
+#define LC_PARITY_MARK 3U
+#define LC_PARITY_SPACE 4U
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of Line Coding structure.
+ */
+typedef struct {
+ uint8_t dwDTERate[4];
+ uint8_t bCharFormat;
+ uint8_t bParityType;
+ uint8_t bDataBits;
+} cdc_linecoding_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#endif /* USB_CDC_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_wdg.h b/ChibiOS_20.3.2/os/hal/include/hal_wdg.h
new file mode 100644
index 0000000..8513740
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_wdg.h
@@ -0,0 +1,89 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_wdg.h
+ * @brief WDG Driver macros and structures.
+ *
+ * @addtogroup WDG
+ * @{
+ */
+
+#ifndef HAL_WDG_H
+#define HAL_WDG_H
+
+#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ WDG_UNINIT = 0, /**< Not initialized. */
+ WDG_STOP = 1, /**< Stopped. */
+ WDG_READY = 2 /**< Ready. */
+} wdgstate_t;
+
+#include "hal_wdg_lld.h"
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Resets WDG's counter.
+ *
+ * @param[in] wdgp pointer to the @p WDGDriver object
+ *
+ * @iclass
+ */
+#define wdgResetI(wdgp) wdg_lld_reset(wdgp)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void wdgInit(void);
+ void wdgStart(WDGDriver *wdgp, const WDGConfig * config);
+ void wdgStop(WDGDriver *wdgp);
+ void wdgReset(WDGDriver *wdgp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_WDG == TRUE */
+
+#endif /* HAL_WDG_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/include/hal_wspi.h b/ChibiOS_20.3.2/os/hal/include/hal_wspi.h
new file mode 100644
index 0000000..d0a99c1
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/include/hal_wspi.h
@@ -0,0 +1,468 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_wspi.h
+ * @brief WSPI Driver macros and structures.
+ *
+ * @addtogroup WSPI
+ * @{
+ */
+
+#ifndef HAL_WSPI_H
+#define HAL_WSPI_H
+
+#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name WSPI configuration options
+ * @{
+ */
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__)
+#define WSPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define WSPI_USE_MUTUAL_EXCLUSION TRUE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver state machine possible states.
+ */
+typedef enum {
+ WSPI_UNINIT = 0, /**< Not initialized. */
+ WSPI_STOP = 1, /**< Stopped. */
+ WSPI_READY = 2, /**< Ready. */
+ WSPI_SEND = 3, /**< Sending data. */
+ WSPI_RECEIVE = 4, /**< Receiving data. */
+ WSPI_COMPLETE = 5, /**< Asynchronous operation complete. */
+ WSPI_MEMMAP = 6 /**< In memory mapped mode. */
+} wspistate_t;
+
+/**
+ * @brief Type of a structure representing an WSPI driver.
+ */
+typedef struct hal_wspi_driver WSPIDriver;
+
+/**
+ * @brief Type of a structure representing an WSPI driver configuration.
+ */
+typedef struct hal_wspi_config WSPIConfig;
+
+/**
+ * @brief Type of a WSPI notification callback.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object triggering the
+ * callback
+ */
+typedef void (*wspicallback_t)(WSPIDriver *wspip);
+
+/**
+ * @brief Type of a WSPI command descriptor.
+ */
+typedef struct {
+ /**
+ * @brief Transfer configuration field.
+ */
+ uint32_t cfg;
+ /**
+ * @brief Command phase data.
+ */
+ uint32_t cmd;
+ /**
+ * @brief Address phase data.
+ */
+ uint32_t addr;
+ /**
+ * @brief Alternate phase data.
+ */
+ uint32_t alt;
+ /**
+ * @brief Number of dummy cycles to be inserted.
+ */
+ uint32_t dummy;
+} wspi_command_t;
+
+/* Including the low level driver header, it exports information required
+ for completing types.*/
+#include "hal_wspi_lld.h"
+
+#if !defined(WSPI_SUPPORTS_MEMMAP)
+#error "low level does not define WSPI_SUPPORTS_MEMMAP"
+#endif
+
+#if !defined(WSPI_DEFAULT_CFG_MASKS)
+#error "low level does not define WSPI_DEFAULT_CFG_MASKS"
+#endif
+
+/**
+ * @brief Driver configuration structure.
+ */
+struct hal_wspi_config {
+ /**
+ * @brief Operation complete callback or @p NULL.
+ */
+ wspicallback_t end_cb;
+ /**
+ * @brief Operation error callback or @p NULL.
+ */
+ wspicallback_t error_cb;
+ /* End of the mandatory fields.*/
+ wspi_lld_config_fields;
+};
+
+/**
+ * @brief Structure representing an WSPI driver.
+ */
+struct hal_wspi_driver {
+ /**
+ * @brief Driver state.
+ */
+ wspistate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const WSPIConfig *config;
+#if (WSPI_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Waiting thread.
+ */
+ thread_reference_t thread;
+#endif /* WSPI_USE_WAIT */
+#if (WSPI_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Mutex protecting the peripheral.
+ */
+ mutex_t mutex;
+#endif /* WSPI_USE_MUTUAL_EXCLUSION */
+#if defined(WSPI_DRIVER_EXT_FIELDS)
+ WSPI_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ wspi_lld_driver_fields;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+#if (WSPI_DEFAULT_CFG_MASKS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @name Transfer options
+ * @note The low level driver has the option to override the following
+ * definitions and use its own ones. In must take care to use
+ * the same name for the same function or compatibility is not
+ * ensured.
+ * @{
+ */
+#define WSPI_CFG_CMD_MODE_MASK (7LU << 0LU)
+#define WSPI_CFG_CMD_MODE_NONE (0LU << 0LU)
+#define WSPI_CFG_CMD_MODE_ONE_LINE (1LU << 0LU)
+#define WSPI_CFG_CMD_MODE_TWO_LINES (2LU << 0LU)
+#define WSPI_CFG_CMD_MODE_FOUR_LINES (3LU << 0LU)
+#define WSPI_CFG_CMD_MODE_EIGHT_LINES (4LU << 0LU)
+
+#define WSPI_CFG_CMD_DTR (1LU << 3LU)
+
+#define WSPI_CFG_CMD_SIZE_MASK (3LU << 4LU)
+#define WSPI_CFG_CMD_SIZE_8 (0LU << 4LU)
+#define WSPI_CFG_CMD_SIZE_16 (1LU << 4LU)
+#define WSPI_CFG_CMD_SIZE_24 (2LU << 4LU)
+#define WSPI_CFG_CMD_SIZE_32 (3LU << 4LU)
+
+#define WSPI_CFG_ADDR_MODE_MASK (7LU << 8LU)
+#define WSPI_CFG_ADDR_MODE_NONE (0LU << 8LU)
+#define WSPI_CFG_ADDR_MODE_ONE_LINE (1LU << 8LU)
+#define WSPI_CFG_ADDR_MODE_TWO_LINES (2LU << 8LU)
+#define WSPI_CFG_ADDR_MODE_FOUR_LINES (3LU << 8LU)
+#define WSPI_CFG_ADDR_MODE_EIGHT_LINES (4LU << 8LU)
+
+#define WSPI_CFG_ADDR_DTR (1LU << 11LU)
+
+#define WSPI_CFG_ADDR_SIZE_MASK (3LU << 12LU)
+#define WSPI_CFG_ADDR_SIZE_8 (0LU << 12LU)
+#define WSPI_CFG_ADDR_SIZE_16 (1LU << 12LU)
+#define WSPI_CFG_ADDR_SIZE_24 (2LU << 12LU)
+#define WSPI_CFG_ADDR_SIZE_32 (3LU << 12LU)
+
+#define WSPI_CFG_ALT_MODE_MASK (7LU << 16LU)
+#define WSPI_CFG_ALT_MODE_NONE (0LU << 16LU)
+#define WSPI_CFG_ALT_MODE_ONE_LINE (1LU << 16LU)
+#define WSPI_CFG_ALT_MODE_TWO_LINES (2LU << 16LU)
+#define WSPI_CFG_ALT_MODE_FOUR_LINES (3LU << 16LU)
+#define WSPI_CFG_ALT_MODE_EIGHT_LINES (4LU << 16LU)
+
+#define WSPI_CFG_ALT_DTR (1LU << 19LU)
+
+#define WSPI_CFG_ALT_SIZE_MASK (3LU << 20LU)
+#define WSPI_CFG_ALT_SIZE_8 (0LU << 20LU)
+#define WSPI_CFG_ALT_SIZE_16 (1LU << 20LU)
+#define WSPI_CFG_ALT_SIZE_24 (2LU << 20LU)
+#define WSPI_CFG_ALT_SIZE_32 (3LU << 20LU)
+
+#define WSPI_CFG_DATA_MODE_MASK (7LU << 24LU)
+#define WSPI_CFG_DATA_MODE_NONE (0LU << 24LU)
+#define WSPI_CFG_DATA_MODE_ONE_LINE (1LU << 24LU)
+#define WSPI_CFG_DATA_MODE_TWO_LINES (2LU << 24LU)
+#define WSPI_CFG_DATA_MODE_FOUR_LINES (3LU << 24LU)
+#define WSPI_CFG_DATA_MODE_EIGHT_LINES (4LU << 24LU)
+
+#define WSPI_CFG_DATA_DTR (1LU << 27LU)
+
+#define WSPI_CFG_DQS_ENABLE (1LU << 29LU)
+
+#define WSPI_CFG_SIOO (1LU << 31LU)
+
+#define WSPI_CFG_ALL_DTR (WSPI_CFG_CMD_DTR | \
+ WSPI_CFG_ADDR_DTR | \
+ WSPI_CFG_ALT_DTR | \
+ WSPI_CFG_DATA_DTR)
+/** @} */
+#endif /* WSPI_USE_DEFAULT_CFG_MASKS == TRUE */
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Sends a command without data phase.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ *
+ * @iclass
+ */
+#define wspiStartCommandI(wspip, cmdp) { \
+ osalDbgAssert(((cmdp)->cfg & WSPI_CFG_DATA_MODE_MASK) == \
+ WSPI_CFG_DATA_MODE_NONE, \
+ "data mode specified"); \
+ (wspip)->state = WSPI_SEND; \
+ wspi_lld_command(wspip, cmdp); \
+}
+
+/**
+ * @brief Sends data over the WSPI bus.
+ * @details This asynchronous function starts a transmit operation.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[in] n number of bytes to send or zero if no data phase
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @iclass
+ */
+#define wspiStartSendI(wspip, cmdp, n, txbuf) { \
+ osalDbgAssert(((cmdp)->cfg & WSPI_CFG_DATA_MODE_MASK) != \
+ WSPI_CFG_DATA_MODE_NONE, \
+ "data mode required"); \
+ (wspip)->state = WSPI_SEND; \
+ wspi_lld_send(wspip, cmdp, n, txbuf); \
+}
+
+/**
+ * @brief Receives data from the WSPI bus.
+ * @details This asynchronous function starts a receive operation.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[in] n number of bytes to receive or zero if no data phase
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @iclass
+ */
+#define wspiStartReceiveI(wspip, cmdp, n, rxbuf) { \
+ osalDbgAssert(((cmdp)->cfg & WSPI_CFG_DATA_MODE_MASK) != \
+ WSPI_CFG_DATA_MODE_NONE, \
+ "data mode required"); \
+ (wspip)->state = WSPI_RECEIVE; \
+ wspi_lld_receive(wspip, cmdp, n, rxbuf); \
+}
+
+#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Maps in memory space a WSPI flash device.
+ * @pre The memory flash device must be initialized appropriately
+ * before mapping it in memory space.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[out] addrp pointer to the memory start address of the mapped
+ * flash or @p NULL
+ *
+ * @iclass
+ */
+#define wspiMapFlashI(wspip, cmdp, addrp) \
+ wspi_lld_map_flash(wspip, cmdp, addrp)
+
+/**
+ * @brief Maps in memory space a WSPI flash device.
+ * @post The memory flash device must be re-initialized for normal
+ * commands exchange.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @iclass
+ */
+#define wspiUnmapFlashI(wspip) \
+ wspi_lld_unmap_flash(wspip)
+#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */
+/** @} */
+
+/**
+ * @name Low level driver helper macros
+ * @{
+ */
+#if (WSPI_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Wakes up the waiting thread.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] msg the wakeup message
+ *
+ * @notapi
+ */
+#define _wspi_wakeup_isr(wspip, msg) { \
+ osalSysLockFromISR(); \
+ osalThreadResumeI(&(wspip)->thread, msg); \
+ osalSysUnlockFromISR(); \
+}
+#else /* !WSPI_USE_WAIT */
+#define _wspi_wakeup_isr(wspip, msg)
+#endif /* !WSPI_USE_WAIT */
+
+/**
+ * @brief Common ISR code.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Waiting thread wakeup, if any.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @notapi
+ */
+#define _wspi_isr_code(wspip) { \
+ if ((wspip)->config->end_cb) { \
+ (wspip)->state = WSPI_COMPLETE; \
+ (wspip)->config->end_cb(wspip); \
+ if ((wspip)->state == WSPI_COMPLETE) \
+ (wspip)->state = WSPI_READY; \
+ } \
+ else \
+ (wspip)->state = WSPI_READY; \
+ _wspi_wakeup_isr(wspip, MSG_OK); \
+}
+
+/**
+ * @brief Common error ISR code.
+ * @details This code handles the portable part of the ISR code:
+ * - Callback invocation.
+ * - Waiting thread wakeup, if any.
+ * - Driver state transitions.
+ * .
+ * @note This macro is meant to be used in the low level drivers
+ * implementation only.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @notapi
+ */
+#define _wspi_error_code(wspip) { \
+ if ((wspip)->config->error_cb) { \
+ (wspip)->state = WSPI_COMPLETE; \
+ (wspip)->config->error_cb(wspip); \
+ if ((wspip)->state == WSPI_COMPLETE) \
+ (wspip)->state = WSPI_READY; \
+ } \
+ else \
+ (wspip)->state = WSPI_READY; \
+ _wspi_wakeup_isr(wspip, MSG_RESET); \
+}
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void wspiInit(void);
+ void wspiObjectInit(WSPIDriver *wspip);
+ void wspiStart(WSPIDriver *wspip, const WSPIConfig *config);
+ void wspiStop(WSPIDriver *wspip);
+ void wspiStartCommand(WSPIDriver *wspip, const wspi_command_t *cmdp);
+ void wspiStartSend(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, const uint8_t *txbuf);
+ void wspiStartReceive(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, uint8_t *rxbuf);
+#if WSPI_USE_WAIT == TRUE
+ bool wspiCommand(WSPIDriver *wspip, const wspi_command_t *cmdp);
+ bool wspiSend(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, const uint8_t *txbuf);
+ bool wspiReceive(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, uint8_t *rxbuf);
+#endif
+#if WSPI_SUPPORTS_MEMMAP == TRUE
+void wspiMapFlash(WSPIDriver *wspip,
+ const wspi_command_t *cmdp,
+ uint8_t **addrp);
+void wspiUnmapFlash(WSPIDriver *wspip);
+#endif
+#if WSPI_USE_MUTUAL_EXCLUSION == TRUE
+ void wspiAcquireBus(WSPIDriver *wspip);
+ void wspiReleaseBus(WSPIDriver *wspip);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_WSPI == TRUE */
+
+#endif /* HAL_WSPI_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/lib/complex/mfs/hal_mfs.c b/ChibiOS_20.3.2/os/hal/lib/complex/mfs/hal_mfs.c
new file mode 100644
index 0000000..7b898ff
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/complex/mfs/hal_mfs.c
@@ -0,0 +1,1482 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file hal_mfs.c
+ * @brief Managed Flash Storage module code.
+ * @details This module manages a flash partition as a generic storage where
+ * arbitrary data records can be created, updated, deleted and
+ * retrieved.
+ * A managed partition is composed of two banks of equal size, a
+ * bank is composed of one or more erasable sectors, a sector is
+ * divided in writable pages.
+ * The module handles flash wear leveling and recovery of damaged
+ * banks (where possible) caused by power loss during operations.
+ * Both operations are transparent to the user.
+ *
+ * @addtogroup HAL_MFS
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+
+#include "hal_mfs.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/**
+ * @brief Data record size aligned.
+ */
+#define ALIGNED_REC_SIZE(n) \
+ (flash_offset_t)MFS_ALIGN_NEXT(sizeof (mfs_data_header_t) + (size_t)(n))
+
+/**
+ * @brief Data record header size aligned.
+ */
+#define ALIGNED_DHDR_SIZE \
+ ALIGNED_REC_SIZE(0)
+
+/**
+ * @brief Aligned size of a type.
+ */
+#define ALIGNED_SIZEOF(t) \
+ (((sizeof (t) - 1U) | MFS_ALIGN_MASK) + 1U)
+
+/**
+ * @brief Combines two values (0..3) in one (0..15).
+ */
+#define PAIR(a, b) (((unsigned)(a) << 2U) | (unsigned)(b))
+
+/**
+ * @brief Error check helper.
+ */
+#define RET_ON_ERROR(err) do { \
+ mfs_error_t e = (err); \
+ if (e != MFS_NO_ERROR) { \
+ return e; \
+ } \
+} while (false)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+static const uint16_t crc16_table[256] = {
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
+ 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
+ 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
+ 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
+ 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
+ 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
+ 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
+ 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
+ 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
+ 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
+ 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
+ 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
+ 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
+ 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
+ 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
+ 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
+ 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
+ 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
+ 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
+ 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
+ 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
+ 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
+ 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+uint16_t crc16(uint16_t crc, const uint8_t *data, size_t n) {
+
+ while (n > 0U) {
+ crc = (crc << 8U) ^ crc16_table[(crc >> 8U) ^ (uint16_t)*data];
+ data++;
+ n--;
+ }
+
+ return crc;
+}
+
+static void mfs_state_reset(MFSDriver *mfsp) {
+ unsigned i;
+
+ mfsp->current_bank = MFS_BANK_0;
+ mfsp->current_counter = 0U;
+ mfsp->next_offset = 0U;
+ mfsp->used_space = 0U;
+
+ for (i = 0; i < MFS_CFG_MAX_RECORDS; i++) {
+ mfsp->descriptors[i].offset = 0U;
+ mfsp->descriptors[i].size = 0U;
+ }
+}
+
+static flash_offset_t mfs_flash_get_bank_offset(MFSDriver *mfsp,
+ mfs_bank_t bank) {
+
+ return bank == MFS_BANK_0 ? flashGetSectorOffset(mfsp->config->flashp,
+ mfsp->config->bank0_start) :
+ flashGetSectorOffset(mfsp->config->flashp,
+ mfsp->config->bank1_start);
+}
+
+/**
+ * @brief Flash read.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @param[in] offset flash offset
+ * @param[in] n number of bytes to be read
+ * @param[out] rp pointer to the data buffer
+ * @return The operation status.
+ *
+ * @notapi
+ */
+static mfs_error_t mfs_flash_read(MFSDriver *mfsp, flash_offset_t offset,
+ size_t n, uint8_t *rp) {
+ flash_error_t ferr;
+
+ ferr = flashRead(mfsp->config->flashp, offset, n, rp);
+ if (ferr != FLASH_NO_ERROR) {
+ mfsp->state = MFS_ERROR;
+ return MFS_ERR_FLASH_FAILURE;
+ }
+
+ return MFS_NO_ERROR;
+}
+
+/**
+ * @brief Flash write.
+ * @note If the option @p MFS_CFG_WRITE_VERIFY is enabled then the flash
+ * is also read back for verification.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @param[in] offset flash offset
+ * @param[in] n number of bytes to be written
+ * @param[in] wp pointer to the data buffer
+ * @return The operation status.
+ *
+ * @notapi
+ */
+static mfs_error_t mfs_flash_write(MFSDriver *mfsp,
+ flash_offset_t offset,
+ size_t n,
+ const uint8_t *wp) {
+ flash_error_t ferr;
+
+ ferr = flashProgram(mfsp->config->flashp, offset, n, wp);
+ if (ferr != FLASH_NO_ERROR) {
+ mfsp->state = MFS_ERROR;
+ return MFS_ERR_FLASH_FAILURE;
+ }
+
+#if MFS_CFG_WRITE_VERIFY == TRUE
+ /* Verifying the written data by reading it back and comparing.*/
+ while (n > 0U) {
+ size_t chunk = n <= MFS_CFG_BUFFER_SIZE ? n : MFS_CFG_BUFFER_SIZE;
+
+ RET_ON_ERROR(mfs_flash_read(mfsp, offset, chunk, mfsp->buffer.data8));
+
+ if (memcmp((void *)mfsp->buffer.data8, (void *)wp, chunk)) {
+ mfsp->state = MFS_ERROR;
+ return MFS_ERR_FLASH_FAILURE;
+ }
+ n -= chunk;
+ offset += (flash_offset_t)chunk;
+ wp += chunk;
+ }
+#endif
+
+ return MFS_NO_ERROR;
+}
+
+/**
+ * @brief Flash copy.
+ * @note If the option @p MFS_CFG_WRITE_VERIFY is enabled then the flash
+ * is also read back for verification.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @param[in] doffset destination flash offset
+ * @param[in] soffset source flash offset
+ * @param[in] n number of bytes to be copied
+ * @return The operation status.
+ *
+ * @notapi
+ */
+static mfs_error_t mfs_flash_copy(MFSDriver *mfsp,
+ flash_offset_t doffset,
+ flash_offset_t soffset,
+ uint32_t n) {
+
+ /* Splitting the operation in smaller operations because the buffer is
+ small.*/
+ while (n > 0U) {
+ /* Data size that can be written in a single program page operation.*/
+ size_t chunk = (size_t)(((doffset | (MFS_CFG_BUFFER_SIZE - 1U)) + 1U) -
+ doffset);
+ if (chunk > n) {
+ chunk = n;
+ }
+
+ RET_ON_ERROR(mfs_flash_read(mfsp, soffset, chunk, mfsp->buffer.data8));
+ RET_ON_ERROR(mfs_flash_write(mfsp, doffset, chunk, mfsp->buffer.data8));
+
+ /* Next page.*/
+ soffset += chunk;
+ doffset += chunk;
+ n -= chunk;
+ }
+
+ return MFS_NO_ERROR;
+}
+
+/**
+ * @brief Erases and verifies all sectors belonging to a bank.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @param[in] bank bank to be erased
+ * @return The operation status.
+ *
+ * @notapi
+ */
+static mfs_error_t mfs_bank_erase(MFSDriver *mfsp, mfs_bank_t bank) {
+ flash_sector_t sector, end;
+
+ if (bank == MFS_BANK_0) {
+ sector = mfsp->config->bank0_start;
+ end = mfsp->config->bank0_start + mfsp->config->bank0_sectors;
+ }
+ else {
+ sector = mfsp->config->bank1_start;
+ end = mfsp->config->bank1_start + mfsp->config->bank1_sectors;
+ }
+
+ while (sector < end) {
+ flash_error_t ferr;
+
+ ferr = flashStartEraseSector(mfsp->config->flashp, sector);
+ if (ferr != FLASH_NO_ERROR) {
+ mfsp->state = MFS_ERROR;
+ return MFS_ERR_FLASH_FAILURE;
+ }
+ ferr = flashWaitErase(mfsp->config->flashp);
+ if (ferr != FLASH_NO_ERROR) {
+ mfsp->state = MFS_ERROR;
+ return MFS_ERR_FLASH_FAILURE;
+ }
+ ferr = flashVerifyErase(mfsp->config->flashp, sector);
+ if (ferr != FLASH_NO_ERROR) {
+ mfsp->state = MFS_ERROR;
+ return MFS_ERR_FLASH_FAILURE;
+ }
+
+ sector++;
+ }
+
+ return MFS_NO_ERROR;
+}
+
+/**
+ * @brief Erases and verifies all sectors belonging to a bank.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @param[in] bank bank to be verified
+ * @return The operation status.
+ *
+ * @notapi
+ */
+static mfs_error_t mfs_bank_verify_erase(MFSDriver *mfsp, mfs_bank_t bank) {
+ flash_sector_t sector, end;
+
+ if (bank == MFS_BANK_0) {
+ sector = mfsp->config->bank0_start;
+ end = mfsp->config->bank0_start + mfsp->config->bank0_sectors;
+ }
+ else {
+ sector = mfsp->config->bank1_start;
+ end = mfsp->config->bank1_start + mfsp->config->bank1_sectors;
+ }
+
+ while (sector < end) {
+ flash_error_t ferr;
+
+ ferr = flashVerifyErase(mfsp->config->flashp, sector);
+ if (ferr == FLASH_ERROR_VERIFY) {
+ return MFS_ERR_NOT_ERASED;
+ }
+ if (ferr != FLASH_NO_ERROR) {
+ mfsp->state = MFS_ERROR;
+ return MFS_ERR_FLASH_FAILURE;
+ }
+
+ sector++;
+ }
+
+ return MFS_NO_ERROR;
+}
+
+/**
+ * @brief Writes the validation header in a bank.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @param[in] bank bank to be validated
+ * @param[in] cnt value for the flash usage counter
+ * @return The operation status.
+ *
+ * @notapi
+ */
+static mfs_error_t mfs_bank_write_header(MFSDriver *mfsp,
+ mfs_bank_t bank,
+ uint32_t cnt) {
+ flash_sector_t sector;
+ mfs_bank_header_t bhdr;
+
+ if (bank == MFS_BANK_0) {
+ sector = mfsp->config->bank0_start;
+ }
+ else {
+ sector = mfsp->config->bank1_start;
+ }
+
+ bhdr.fields.magic1 = MFS_BANK_MAGIC_1;
+ bhdr.fields.magic2 = MFS_BANK_MAGIC_2;
+ bhdr.fields.counter = cnt;
+ bhdr.fields.reserved1 = (uint16_t)mfsp->config->erased;
+ bhdr.fields.crc = crc16(0xFFFFU, bhdr.hdr8,
+ sizeof (mfs_bank_header_t) - sizeof (uint16_t));
+
+ return mfs_flash_write(mfsp,
+ flashGetSectorOffset(mfsp->config->flashp, sector),
+ sizeof (mfs_bank_header_t),
+ bhdr.hdr8);
+}
+
+/**
+ * @brief Checks integrity of the header in the shared buffer.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @return The header state.
+ *
+ * @notapi
+ */
+static mfs_bank_state_t mfs_bank_check_header(MFSDriver *mfsp) {
+ uint16_t crc;
+
+ if ((mfsp->buffer.bhdr.hdr32[0] == mfsp->config->erased) &&
+ (mfsp->buffer.bhdr.hdr32[1] == mfsp->config->erased) &&
+ (mfsp->buffer.bhdr.hdr32[2] == mfsp->config->erased) &&
+ (mfsp->buffer.bhdr.hdr32[3] == mfsp->config->erased)) {
+ return MFS_BANK_ERASED;
+ }
+
+ /* Checking header fields integrity.*/
+ if ((mfsp->buffer.bhdr.fields.magic1 != MFS_BANK_MAGIC_1) ||
+ (mfsp->buffer.bhdr.fields.magic2 != MFS_BANK_MAGIC_2) ||
+ (mfsp->buffer.bhdr.fields.counter == mfsp->config->erased) ||
+ (mfsp->buffer.bhdr.fields.reserved1 != (uint16_t)mfsp->config->erased)) {
+ return MFS_BANK_GARBAGE;
+ }
+
+ /* Verifying header CRC.*/
+ crc = crc16(0xFFFFU, mfsp->buffer.bhdr.hdr8,
+ sizeof (mfs_bank_header_t) - sizeof (uint16_t));
+ if (crc != mfsp->buffer.bhdr.fields.crc) {
+ return MFS_BANK_GARBAGE;
+ }
+
+ return MFS_BANK_OK;
+}
+
+/**
+ * @brief Scans blocks searching for records.
+ * @note The block integrity is strongly checked.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @param[in] bank the bank identifier
+ * @param[out] wflagp warning flag on anomalies
+ *
+ * @return The operation status.
+ *
+ * @notapi
+ */
+static mfs_error_t mfs_bank_scan_records(MFSDriver *mfsp,
+ mfs_bank_t bank,
+ bool *wflagp) {
+ flash_offset_t hdr_offset, start_offset, end_offset;
+
+ /* No warning by default.*/
+ *wflagp = false;
+
+ /* Boundaries.*/
+ start_offset = mfs_flash_get_bank_offset(mfsp, bank);
+ hdr_offset = start_offset + (flash_offset_t)ALIGNED_SIZEOF(mfs_bank_header_t);
+ end_offset = start_offset + mfsp->config->bank_size;
+
+ /* Scanning records until there is there is not enough space left for an
+ header.*/
+ while (hdr_offset < end_offset - ALIGNED_DHDR_SIZE) {
+ union {
+ mfs_data_header_t dhdr;
+ uint8_t data8[ALIGNED_SIZEOF(mfs_data_header_t)];
+ } u;
+ uint16_t crc;
+
+ /* Reading the current record header.*/
+ RET_ON_ERROR(mfs_flash_read(mfsp, hdr_offset,
+ sizeof (mfs_data_header_t),
+ u.data8));
+
+ /* Checking if the found header is in erased state.*/
+ if ((u.dhdr.hdr32[0] == mfsp->config->erased) &&
+ (u.dhdr.hdr32[1] == mfsp->config->erased) &&
+ (u.dhdr.hdr32[2] == mfsp->config->erased)) {
+ break;
+ }
+
+ /* It is not erased so checking for integrity.*/
+ if ((u.dhdr.fields.magic1 != MFS_HEADER_MAGIC_1) ||
+ (u.dhdr.fields.magic2 != MFS_HEADER_MAGIC_2) ||
+ (u.dhdr.fields.id < 1U) ||
+ (u.dhdr.fields.id > (uint32_t)MFS_CFG_MAX_RECORDS) ||
+ (u.dhdr.fields.size > end_offset - hdr_offset)) {
+ *wflagp = true;
+ break;
+ }
+
+ /* Finally checking the CRC, we need to perform it in chunks because
+ we have a limited buffer.*/
+ crc = 0xFFFFU;
+ if (u.dhdr.fields.size > 0U) {
+ flash_offset_t data = hdr_offset + sizeof (mfs_data_header_t);
+ uint32_t total = u.dhdr.fields.size;
+
+ while (total > 0U) {
+ uint32_t chunk = total > MFS_CFG_BUFFER_SIZE ? MFS_CFG_BUFFER_SIZE :
+ total;
+
+ /* Reading the data chunk.*/
+ RET_ON_ERROR(mfs_flash_read(mfsp, data, chunk, mfsp->buffer.data8));
+
+ /* CRC on the read data chunk.*/
+ crc = crc16(crc, &mfsp->buffer.data8[0], chunk);
+
+ /* Next chunk.*/
+ data += chunk;
+ total -= chunk;
+ }
+ }
+ if (crc != u.dhdr.fields.crc) {
+ /* If the CRC is invalid then this record is ignored but scanning
+ continues because there could be more valid records afterward.*/
+ *wflagp = true;
+ }
+ else {
+ /* Zero-sized records are erase markers.*/
+ if (u.dhdr.fields.size == 0U) {
+ mfsp->descriptors[u.dhdr.fields.id - 1U].offset = 0U;
+ mfsp->descriptors[u.dhdr.fields.id - 1U].size = 0U;
+ }
+ else {
+ mfsp->descriptors[u.dhdr.fields.id - 1U].offset = hdr_offset;
+ mfsp->descriptors[u.dhdr.fields.id - 1U].size = u.dhdr.fields.size;
+ }
+ }
+
+ /* On the next header.*/
+ hdr_offset = hdr_offset + ALIGNED_REC_SIZE(u.dhdr.fields.size);
+ }
+
+ /* Next writable offset.*/
+ mfsp->next_offset = hdr_offset;
+
+ return MFS_NO_ERROR;
+}
+
+/**
+ * @brief Determines the state of a bank.
+ * @note This function does not test the bank integrity by scanning
+ * the data area, it just checks the header.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @param[in] bank bank to be checked
+ * @param[out] statep bank state, it can be:
+ * - MFS_BANK_ERASED
+ * - MFS_BANK_GARBAGE
+ * - MFS_BANK_OK
+ * .
+ * @param[out] cntp bank counter
+ * @return The operation status.
+ *
+ * @notapi
+ */
+static mfs_error_t mfs_bank_get_state(MFSDriver *mfsp,
+ mfs_bank_t bank,
+ mfs_bank_state_t *statep,
+ uint32_t *cntp) {
+
+ /* Reading the current bank header.*/
+ RET_ON_ERROR(mfs_flash_read(mfsp, mfs_flash_get_bank_offset(mfsp, bank),
+ sizeof (mfs_bank_header_t),
+ mfsp->buffer.data8));
+
+ /* Getting the counter regardless of the bank state, it is only valid if
+ the state is MFS_BANK_OK.*/
+ *cntp = mfsp->buffer.bhdr.fields.counter;
+
+ /* Checking just the header.*/
+ *statep = mfs_bank_check_header(mfsp);
+ if (*statep == MFS_BANK_ERASED) {
+ mfs_error_t err;
+
+ /* Checking if the bank is really all erased.*/
+ err = mfs_bank_verify_erase(mfsp, bank);
+ if (err == MFS_ERR_NOT_ERASED) {
+ *statep = MFS_BANK_GARBAGE;
+ }
+ }
+
+ return MFS_NO_ERROR;
+}
+
+/**
+ * @brief Enforces a garbage collection.
+ * @details Storage data is compacted into a single bank.
+ *
+ * @param[out] mfsp pointer to the @p MFSDriver object
+ * @return The operation status.
+ *
+ * @notapi
+ */
+static mfs_error_t mfs_garbage_collect(MFSDriver *mfsp) {
+ unsigned i;
+ mfs_bank_t sbank, dbank;
+ flash_offset_t dest_offset;
+
+ sbank = mfsp->current_bank;
+ if (sbank == MFS_BANK_0) {
+ dbank = MFS_BANK_1;
+ }
+ else {
+ dbank = MFS_BANK_0;
+ }
+
+ /* Write address.*/
+ dest_offset = mfs_flash_get_bank_offset(mfsp, dbank) +
+ ALIGNED_SIZEOF(mfs_bank_header_t);
+
+ /* Copying the most recent record instances only.*/
+ for (i = 0; i < MFS_CFG_MAX_RECORDS; i++) {
+ uint32_t totsize = ALIGNED_REC_SIZE(mfsp->descriptors[i].size);
+ if (mfsp->descriptors[i].offset != 0) {
+ RET_ON_ERROR(mfs_flash_copy(mfsp, dest_offset,
+ mfsp->descriptors[i].offset,
+ totsize));
+ mfsp->descriptors[i].offset = dest_offset;
+ dest_offset += totsize;
+ }
+ }
+
+ /* New current bank.*/
+ mfsp->current_bank = dbank;
+ mfsp->current_counter += 1U;
+ mfsp->next_offset = dest_offset;
+
+ /* The header is written after the data.*/
+ RET_ON_ERROR(mfs_bank_write_header(mfsp, dbank, mfsp->current_counter));
+
+ /* The source bank is erased last.*/
+ RET_ON_ERROR(mfs_bank_erase(mfsp, sbank));
+
+ return MFS_NO_ERROR;
+}
+
+/**
+ * @brief Performs a flash partition mount attempt.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @return The operation status.
+ *
+ * @api
+ */
+static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
+ mfs_bank_state_t sts0, sts1;
+ mfs_bank_t bank;
+ uint32_t cnt0 = 0, cnt1 = 0;
+ bool w1 = false, w2 = false;
+
+ /* Resetting the bank state.*/
+ mfs_state_reset(mfsp);
+
+ /* Assessing the state of the two banks.*/
+ RET_ON_ERROR(mfs_bank_get_state(mfsp, MFS_BANK_0, &sts0, &cnt0));
+ RET_ON_ERROR(mfs_bank_get_state(mfsp, MFS_BANK_1, &sts1, &cnt1));
+
+ /* Handling all possible scenarios, each one requires its own recovery
+ strategy.*/
+ switch (PAIR(sts0, sts1)) {
+
+ case PAIR(MFS_BANK_ERASED, MFS_BANK_ERASED):
+ /* Both banks erased, first initialization.*/
+ RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_0, 1));
+ bank = MFS_BANK_0;
+ break;
+
+ case PAIR(MFS_BANK_OK, MFS_BANK_OK):
+ /* Both banks appear to be valid but one must be newer, erasing the
+ older one.*/
+ if (cnt0 > cnt1) {
+ /* Bank 0 is newer.*/
+ RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
+ bank = MFS_BANK_0;
+ }
+ else {
+ /* Bank 1 is newer.*/
+ RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
+ bank = MFS_BANK_1;
+ }
+ w1 = true;
+ break;
+
+ case PAIR(MFS_BANK_GARBAGE, MFS_BANK_GARBAGE):
+ /* Both banks are unreadable, reinitializing.*/
+ RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
+ RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
+ RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_0, 1));
+ bank = MFS_BANK_0;
+ w1 = true;
+ break;
+
+ case PAIR(MFS_BANK_ERASED, MFS_BANK_OK):
+ /* Normal situation, bank one is used.*/
+ bank = MFS_BANK_1;
+ break;
+
+ case PAIR(MFS_BANK_OK, MFS_BANK_ERASED):
+ /* Normal situation, bank zero is used.*/
+ bank = MFS_BANK_0;
+ break;
+
+ case PAIR(MFS_BANK_ERASED, MFS_BANK_GARBAGE):
+ /* Bank zero is erased, bank one is not readable.*/
+ RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
+ RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_0, 1));
+ bank = MFS_BANK_0;
+ w1 = true;
+ break;
+
+ case PAIR(MFS_BANK_GARBAGE, MFS_BANK_ERASED):
+ /* Bank zero is not readable, bank one is erased.*/
+ RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
+ RET_ON_ERROR(mfs_bank_write_header(mfsp, MFS_BANK_1, 1));
+ bank = MFS_BANK_1;
+ w1 = true;
+ break;
+
+ case PAIR(MFS_BANK_OK, MFS_BANK_GARBAGE):
+ /* Bank zero is normal, bank one is unreadable.*/
+ RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
+ bank = MFS_BANK_0;
+ w1 = true;
+ break;
+
+ case PAIR(MFS_BANK_GARBAGE, MFS_BANK_OK):
+ /* Bank zero is unreadable, bank one is normal.*/
+ RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
+ bank = MFS_BANK_1;
+ w1 = true;
+ break;
+
+ default:
+ return MFS_ERR_INTERNAL;
+ }
+
+ /* Mounting the bank.*/
+ {
+ unsigned i;
+
+ /* Reading the bank header again.*/
+ RET_ON_ERROR(mfs_flash_read(mfsp, mfs_flash_get_bank_offset(mfsp, bank),
+ sizeof (mfs_bank_header_t),
+ mfsp->buffer.data8));
+
+ /* Checked again for extra safety.*/
+ if (mfs_bank_check_header(mfsp) != MFS_BANK_OK) {
+ return MFS_ERR_INTERNAL;
+ }
+
+ /* Storing the bank data.*/
+ mfsp->current_bank = bank;
+ mfsp->current_counter = mfsp->buffer.bhdr.fields.counter;
+
+ /* Scanning for the most recent instance of all records.*/
+ RET_ON_ERROR(mfs_bank_scan_records(mfsp, bank, &w2));
+
+ /* Calculating the effective used size.*/
+ mfsp->used_space = ALIGNED_SIZEOF(mfs_bank_header_t);
+ for (i = 0; i < MFS_CFG_MAX_RECORDS; i++) {
+ if (mfsp->descriptors[i].offset != 0U) {
+ mfsp->used_space += ALIGNED_REC_SIZE(mfsp->descriptors[i].size);
+ }
+ }
+ }
+
+ /* In case of detected problems then a garbage collection is performed in
+ order to repair/remove anomalies.*/
+ if (w2) {
+ RET_ON_ERROR(mfs_garbage_collect(mfsp));
+ }
+
+ return (w1 || w2) ? MFS_WARN_REPAIR : MFS_NO_ERROR;
+}
+
+/**
+ * @brief Configures and activates a MFS driver.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @return The operation status.
+ * @retval MFS_NO_ERROR if the operation has been successfully
+ * completed.
+ * @retval MFS_WARN_GC if the operation triggered a garbage
+ * collection.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ *
+ * @api
+ */
+mfs_error_t mfs_mount(MFSDriver *mfsp) {
+ unsigned i;
+
+ /* Resetting previous state.*/
+ mfs_state_reset(mfsp);
+
+ /* Attempting to mount the managed partition.*/
+ for (i = 0; i < MFS_CFG_MAX_REPAIR_ATTEMPTS; i++) {
+ mfs_error_t err;
+
+ err = mfs_try_mount(mfsp);
+ if (err == MFS_ERR_INTERNAL) {
+ /* Special case, do not retry on internal errors but report
+ immediately.*/
+ mfsp->state = MFS_ERROR;
+ return err;
+ }
+ if (!MFS_IS_ERROR(err)) {
+ mfsp->state = MFS_READY;
+ return err;
+ }
+ }
+
+ /* Driver start failed.*/
+ mfsp->state = MFS_ERROR;
+ return MFS_ERR_FLASH_FAILURE;
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes an instance.
+ *
+ * @param[out] mfsp pointer to the @p MFSDriver object
+ *
+ * @init
+ */
+void mfsObjectInit(MFSDriver *mfsp) {
+
+ osalDbgCheck(mfsp != NULL);
+
+ mfsp->state = MFS_STOP;
+ mfsp->config = NULL;
+}
+
+/**
+ * @brief Configures and activates a MFS driver.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @param[in] config pointer to the configuration
+ * @return The operation status.
+ * @retval MFS_NO_ERROR if the operation has been
+ * completed.
+ * @retval MFS_WARN_GC if the operation triggered a garbage
+ * collection.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ *
+ * @api
+ */
+mfs_error_t mfsStart(MFSDriver *mfsp, const MFSConfig *config) {
+
+ osalDbgCheck((mfsp != NULL) && (config != NULL));
+ osalDbgAssert((mfsp->state == MFS_STOP) || (mfsp->state == MFS_READY) ||
+ (mfsp->state == MFS_ERROR), "invalid state");
+
+ /* Storing configuration.*/
+ mfsp->config = config;
+
+ return mfs_mount(mfsp);
+}
+
+/**
+ * @brief Deactivates a MFS driver.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ *
+ * @api
+ */
+void mfsStop(MFSDriver *mfsp) {
+
+ osalDbgCheck(mfsp != NULL);
+ osalDbgAssert((mfsp->state == MFS_STOP) || (mfsp->state == MFS_READY) ||
+ (mfsp->state == MFS_ERROR), "invalid state");
+
+ mfsp->config = NULL;
+ mfsp->state = MFS_STOP;
+}
+
+/**
+ * @brief Destroys the state of the managed storage by erasing the flash.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @return The operation status.
+ * @retval MFS_ERR_INV_STATE if the driver is in not in @p MFS_READY
+ * state.
+ * @retval MFS_NO_ERROR if the operation has been successfully
+ * completed.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ *
+ * @api
+ */
+mfs_error_t mfsErase(MFSDriver *mfsp) {
+
+ osalDbgCheck(mfsp != NULL);
+
+ if (mfsp->state != MFS_READY) {
+ return MFS_ERR_INV_STATE;
+ }
+
+ RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
+ RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
+
+ return mfs_mount(mfsp);
+}
+
+/**
+ * @brief Retrieves and reads a data record.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @param[in] id record numeric identifier, the valid range is between
+ * @p 1 and @p MFS_CFG_MAX_RECORDS
+ * @param[in,out] np on input is the maximum buffer size, on return it is
+ * the size of the data copied into the buffer
+ * @param[out] buffer pointer to a buffer for record data
+ * @return The operation status.
+ * @retval MFS_NO_ERROR if the operation has been successfully
+ * completed.
+ * @retval MFS_ERR_INV_STATE if the driver is in not in @p MFS_READY
+ * state.
+ * @retval MFS_ERR_INV_SIZE if the passed buffer is not large enough to
+ * contain the record data.
+ * @retval MFS_ERR_NOT_FOUND if the specified id does not exists.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ *
+ * @api
+ */
+mfs_error_t mfsReadRecord(MFSDriver *mfsp, mfs_id_t id,
+ size_t *np, uint8_t *buffer) {
+ uint16_t crc;
+
+ osalDbgCheck((mfsp != NULL) &&
+ (id >= 1U) && (id <= (mfs_id_t)MFS_CFG_MAX_RECORDS) &&
+ (np != NULL) && (*np > 0U) && (buffer != NULL));
+
+ if ((mfsp->state != MFS_READY) && (mfsp->state != MFS_TRANSACTION)) {
+ return MFS_ERR_INV_STATE;
+ }
+
+ /* Checking if the requested record actually exists.*/
+ if (mfsp->descriptors[id - 1U].offset == 0U) {
+ return MFS_ERR_NOT_FOUND;
+ }
+
+ /* Making sure to not overflow the buffer.*/
+ if (*np < mfsp->descriptors[id - 1U].size) {
+ return MFS_ERR_INV_SIZE;
+ }
+
+ /* Header read from flash.*/
+ RET_ON_ERROR(mfs_flash_read(mfsp,
+ mfsp->descriptors[id - 1U].offset,
+ sizeof (mfs_data_header_t),
+ mfsp->buffer.data8));
+
+ /* Data read from flash.*/
+ *np = mfsp->descriptors[id - 1U].size;
+ RET_ON_ERROR(mfs_flash_read(mfsp,
+ mfsp->descriptors[id - 1U].offset + sizeof (mfs_data_header_t),
+ *np,
+ buffer));
+
+ /* Checking CRC.*/
+ crc = crc16(0xFFFFU, buffer, *np);
+ if (crc != mfsp->buffer.dhdr.fields.crc) {
+ mfsp->state = MFS_ERROR;
+ return MFS_ERR_FLASH_FAILURE;
+ }
+
+ return MFS_NO_ERROR;
+}
+
+/**
+ * @brief Creates or updates a data record.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @param[in] id record numeric identifier, the valid range is between
+ * @p 1 and @p MFS_CFG_MAX_RECORDS
+ * @param[in] n size of data to be written, it cannot be zero
+ * @param[in] buffer pointer to a buffer for record data
+ * @return The operation status.
+ * @retval MFS_NO_ERROR if the operation has been successfully
+ * completed.
+ * @retval MFS_WARN_GC if the operation triggered a garbage
+ * collection.
+ * @retval MFS_ERR_INV_STATE if the driver is in not in @p MFS_READY
+ * state.
+ * @retval MFS_ERR_OUT_OF_MEM if there is not enough flash space for the
+ * operation.
+ * @retval MFS_ERR_TRANSACTION_NUM if the transaction operations buffer space
+ * has been exceeded.
+ * @retval MFS_ERR_TRANSACTION_SIZE if the transaction allocated space
+ * has been exceeded.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ *
+ * @api
+ */
+mfs_error_t mfsWriteRecord(MFSDriver *mfsp, mfs_id_t id,
+ size_t n, const uint8_t *buffer) {
+ flash_offset_t free, asize, rspace;
+
+ osalDbgCheck((mfsp != NULL) &&
+ (id >= 1U) && (id <= (mfs_id_t)MFS_CFG_MAX_RECORDS) &&
+ (n > 0U) && (buffer != NULL));
+
+ /* Aligned record size.*/
+ asize = ALIGNED_REC_SIZE(n);
+
+ /* Normal mode code path.*/
+ if (mfsp->state == MFS_READY) {
+ bool warning = false;
+
+ /* If the required space is beyond the available (compacted) block
+ size then an error is returned.
+ NOTE: The space for one extra header is reserved in order to allow
+ for an erase operation after the space has been fully allocated.*/
+ rspace = ALIGNED_DHDR_SIZE + asize;
+ if (rspace > mfsp->config->bank_size - mfsp->used_space) {
+ return MFS_ERR_OUT_OF_MEM;
+ }
+
+ /* Checking for immediately (not compacted) available space.*/
+ free = (mfs_flash_get_bank_offset(mfsp, mfsp->current_bank) +
+ mfsp->config->bank_size) - mfsp->next_offset;
+ if (rspace > free) {
+ /* We need to perform a garbage collection, there is enough space
+ but it has to be freed.*/
+ warning = true;
+ RET_ON_ERROR(mfs_garbage_collect(mfsp));
+ }
+
+ /* Writing the data header without the magic, it will be written last.*/
+ mfsp->buffer.dhdr.fields.id = (uint16_t)id;
+ mfsp->buffer.dhdr.fields.size = (uint32_t)n;
+ mfsp->buffer.dhdr.fields.crc = crc16(0xFFFFU, buffer, n);
+ RET_ON_ERROR(mfs_flash_write(mfsp,
+ mfsp->next_offset + (sizeof (uint32_t) * 2U),
+ sizeof (mfs_data_header_t) - (sizeof (uint32_t) * 2U),
+ mfsp->buffer.data8 + (sizeof (uint32_t) * 2U)));
+
+ /* Writing the data part.*/
+ RET_ON_ERROR(mfs_flash_write(mfsp,
+ mfsp->next_offset + sizeof (mfs_data_header_t),
+ n,
+ buffer));
+
+ /* Finally writing the magic number, it seals the operation.*/
+ mfsp->buffer.dhdr.fields.magic1 = (uint32_t)MFS_HEADER_MAGIC_1;
+ mfsp->buffer.dhdr.fields.magic2 = (uint32_t)MFS_HEADER_MAGIC_2;
+ RET_ON_ERROR(mfs_flash_write(mfsp,
+ mfsp->next_offset,
+ sizeof (uint32_t) * 2U,
+ mfsp->buffer.data8));
+
+ /* The size of the old record instance, if present, must be subtracted
+ to the total used size.*/
+ if (mfsp->descriptors[id - 1U].offset != 0U) {
+ mfsp->used_space -= ALIGNED_REC_SIZE(mfsp->descriptors[id - 1U].size);
+ }
+
+ /* Adjusting bank-related metadata.*/
+ mfsp->descriptors[id - 1U].offset = mfsp->next_offset;
+ mfsp->descriptors[id - 1U].size = (uint32_t)n;
+ mfsp->next_offset += asize;
+ mfsp->used_space += asize;
+
+ return warning ? MFS_WARN_GC : MFS_NO_ERROR;
+ }
+
+#if MFS_CFG_TRANSACTION_MAX > 0
+ /* Transaction mode code path.*/
+ if (mfsp->state == MFS_TRANSACTION) {
+ mfs_transaction_op_t *top;
+
+ /* Checking if the maximum number of operations in a transaction is
+ Exceeded.*/
+ if (mfsp->tr_nops >= MFS_CFG_TRANSACTION_MAX) {
+ return MFS_ERR_TRANSACTION_NUM;
+ }
+
+ /* If the required space is greater than the space allocated for the
+ transaction then error.*/
+ rspace = asize;
+ if (rspace > mfsp->tr_limit_offet - mfsp->tr_next_offset) {
+ return MFS_ERR_TRANSACTION_SIZE;
+ }
+
+ /* Writing the data header without the magic, it will be written last.*/
+ mfsp->buffer.dhdr.fields.id = (uint16_t)id;
+ mfsp->buffer.dhdr.fields.size = (uint32_t)n;
+ mfsp->buffer.dhdr.fields.crc = crc16(0xFFFFU, buffer, n);
+ RET_ON_ERROR(mfs_flash_write(mfsp,
+ mfsp->tr_next_offset + (sizeof (uint32_t) * 2U),
+ sizeof (mfs_data_header_t) - (sizeof (uint32_t) * 2U),
+ mfsp->buffer.data8 + (sizeof (uint32_t) * 2U)));
+
+ /* Writing the data part.*/
+ RET_ON_ERROR(mfs_flash_write(mfsp,
+ mfsp->tr_next_offset + sizeof (mfs_data_header_t),
+ n,
+ buffer));
+
+ /* Adding a transaction operation record.*/
+ top = &mfsp->tr_ops[mfsp->tr_nops];
+ top->offset = mfsp->tr_next_offset;
+ top->size = n;
+ top->id = id;
+
+ /* Number of records and next write position updated.*/
+ mfsp->tr_nops++;
+ mfsp->tr_next_offset += asize;
+
+ return MFS_NO_ERROR;
+ }
+#endif /* MFS_CFG_TRANSACTION_MAX > 0 */
+
+ /* Invalid state.*/
+ return MFS_ERR_INV_STATE;
+}
+
+/**
+ * @brief Erases a data record.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @param[in] id record numeric identifier, the valid range is between
+ * @p 1 and @p MFS_CFG_MAX_RECORDS
+ * @return The operation status.
+ * @retval MFS_NO_ERROR if the operation has been successfully
+ * completed.
+ * @retval MFS_WARN_GC if the operation triggered a garbage
+ * collection.
+ * @retval MFS_ERR_INV_STATE if the driver is in not in @p MFS_READY
+ * state.
+ * @retval MFS_ERR_OUT_OF_MEM if there is not enough flash space for the
+ * operation.
+ * @retval MFS_ERR_TRANSACTION_NUM if the transaction operations buffer space
+ * has been exceeded.
+ * @retval MFS_ERR_TRANSACTION_SIZE if the transaction allocated space
+ * has been exceeded.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ *
+ * @api
+ */
+mfs_error_t mfsEraseRecord(MFSDriver *mfsp, mfs_id_t id) {
+ flash_offset_t free, asize, rspace;
+
+ osalDbgCheck((mfsp != NULL) &&
+ (id >= 1U) && (id <= (mfs_id_t)MFS_CFG_MAX_RECORDS));
+
+ /* Aligned record size.*/
+ asize = ALIGNED_DHDR_SIZE;
+
+ /* Normal mode code path.*/
+ if (mfsp->state == MFS_READY) {
+ bool warning = false;
+
+ /* Checking if the requested record actually exists.*/
+ if (mfsp->descriptors[id - 1U].offset == 0U) {
+ return MFS_ERR_NOT_FOUND;
+ }
+
+ /* If the required space is beyond the available (compacted) block
+ size then an internal error is returned, it should never happen.*/
+ rspace = asize;
+ if (rspace > mfsp->config->bank_size - mfsp->used_space) {
+ return MFS_ERR_INTERNAL;
+ }
+
+ /* Checking for immediately (not compacted) available space.*/
+ free = (mfs_flash_get_bank_offset(mfsp, mfsp->current_bank) +
+ mfsp->config->bank_size) - mfsp->next_offset;
+ if (rspace > free) {
+ /* We need to perform a garbage collection, there is enough space
+ but it has to be freed.*/
+ warning = true;
+ RET_ON_ERROR(mfs_garbage_collect(mfsp));
+ }
+
+ /* Writing the data header with size set to zero, it means that the
+ record is logically erased.*/
+ mfsp->buffer.dhdr.fields.magic1 = (uint32_t)MFS_HEADER_MAGIC_1;
+ mfsp->buffer.dhdr.fields.magic2 = (uint32_t)MFS_HEADER_MAGIC_2;
+ mfsp->buffer.dhdr.fields.id = (uint16_t)id;
+ mfsp->buffer.dhdr.fields.size = (uint32_t)0;
+ mfsp->buffer.dhdr.fields.crc = (uint16_t)0xFFFF;
+ RET_ON_ERROR(mfs_flash_write(mfsp,
+ mfsp->next_offset,
+ sizeof (mfs_data_header_t),
+ mfsp->buffer.data8));
+
+ /* Adjusting bank-related metadata.*/
+ mfsp->used_space -= ALIGNED_REC_SIZE(mfsp->descriptors[id - 1U].size);
+ mfsp->next_offset += sizeof (mfs_data_header_t);
+ mfsp->descriptors[id - 1U].offset = 0U;
+ mfsp->descriptors[id - 1U].size = 0U;
+
+ return warning ? MFS_WARN_GC : MFS_NO_ERROR;
+ }
+
+#if MFS_CFG_TRANSACTION_MAX > 0
+ /* Transaction mode code path.*/
+ if (mfsp->state == MFS_TRANSACTION) {
+ mfs_transaction_op_t *top;
+
+ /* Checking if the requested record actually exists.*/
+ if (mfsp->descriptors[id - 1U].offset == 0U) {
+ return MFS_ERR_NOT_FOUND;
+ }
+
+ /* Checking if the maximum number of operations in a transaction is
+ Exceeded.*/
+ if (mfsp->tr_nops >= MFS_CFG_TRANSACTION_MAX) {
+ return MFS_ERR_TRANSACTION_NUM;
+ }
+
+ /* If the required space is greater than the space allocated for the
+ transaction then error.*/
+ rspace = asize;
+ if (rspace > mfsp->tr_limit_offet - mfsp->tr_next_offset) {
+ return MFS_ERR_TRANSACTION_SIZE;
+ }
+
+ /* Writing the data header with size set to zero, it means that the
+ record is logically erased. Note, the magic number is not set.*/
+ mfsp->buffer.dhdr.fields.id = (uint16_t)id;
+ mfsp->buffer.dhdr.fields.size = (uint32_t)0;
+ mfsp->buffer.dhdr.fields.crc = (uint16_t)0xFFFF;
+ RET_ON_ERROR(mfs_flash_write(mfsp,
+ mfsp->tr_next_offset + (sizeof (uint32_t) * 2U),
+ sizeof (mfs_data_header_t) - (sizeof (uint32_t) * 2U),
+ mfsp->buffer.data8 + (sizeof (uint32_t) * 2U)));
+
+ /* Adding a transaction operation record.*/
+ top = &mfsp->tr_ops[mfsp->tr_nops];
+ top->offset = mfsp->tr_next_offset;
+ top->size = 0U;
+ top->id = id;
+
+ /* Number of records and next write position updated.*/
+ mfsp->tr_nops++;
+ mfsp->tr_next_offset += asize;
+
+ return MFS_NO_ERROR;
+ }
+#endif /* MFS_CFG_TRANSACTION_MAX > 0 */
+
+ return MFS_ERR_INV_STATE;
+}
+
+/**
+ * @brief Enforces a garbage collection operation.
+ * @details Garbage collection involves: integrity check, optionally repairs,
+ * obsolete data removal, data compaction and a flash bank swap.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @return The operation status.
+ * @retval MFS_NO_ERROR if the operation has been successfully
+ * completed.
+ * @retval MFS_ERR_INV_STATE if the driver is in not in @p MFS_READY
+ * state.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ *
+ * @api
+ */
+mfs_error_t mfsPerformGarbageCollection(MFSDriver *mfsp) {
+
+ osalDbgCheck(mfsp != NULL);
+
+ if (mfsp->state != MFS_READY) {
+ return MFS_ERR_INV_STATE;
+ }
+
+ return mfs_garbage_collect(mfsp);
+}
+
+#if (MFS_CFG_TRANSACTION_MAX > 0) || defined(__DOXYGEN__)
+/**
+ * @brief Puts the driver in transaction mode.
+ * @note The parameters @p n and @p size are used to make an
+ * estimation of the space required for the transaction to succeed.
+ * Note that the estimated size must include also the extra space
+ * required by alignment enforcement option. If the estimated size
+ * is wrong (by defect) what could happen is that there is a failure
+ * in the middle of a transaction and a roll-back would be required.
+ * @note The conditions for starting a transaction are:
+ * - The driver must be started.
+ * - There must be enough compacted storage to accommodate the whole
+ * transaction. If the required space is available but it is not
+ * compacted then a garbage collect operation is performed.
+ * .
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @param[in] size estimated total size of written records in transaction,
+ * this includes, data, headers and alignment gaps
+ * @return The operation status.
+ * @retval MFS_NO_ERROR if the operation has been successfully
+ * completed.
+ * @retval MFS_ERR_INV_STATE if the driver is in not in @p MFS_READY
+ * state.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ *
+ * @api
+ */
+mfs_error_t mfsStartTransaction(MFSDriver *mfsp, size_t size) {
+ flash_offset_t free, tspace, rspace;
+
+ osalDbgCheck((mfsp != NULL) && (size > ALIGNED_DHDR_SIZE));
+
+ /* The driver must be in ready mode.*/
+ if (mfsp->state != MFS_READY) {
+ return MFS_ERR_INV_STATE;
+ }
+
+ /* Estimating the required contiguous compacted space.*/
+ tspace = (flash_offset_t)MFS_ALIGN_NEXT(size);
+ rspace = tspace + ALIGNED_DHDR_SIZE;
+
+ /* If the required space is beyond the available (compacted) block
+ size then an error is returned.*/
+ if (rspace > mfsp->config->bank_size - mfsp->used_space) {
+ return MFS_ERR_OUT_OF_MEM;
+ }
+
+ /* Checking for immediately (not compacted) available space.*/
+ free = (mfs_flash_get_bank_offset(mfsp, mfsp->current_bank) +
+ mfsp->config->bank_size) - mfsp->next_offset;
+ if (rspace > free) {
+ /* We need to perform a garbage collection, there is enough space
+ but it has to be freed.*/
+ RET_ON_ERROR(mfs_garbage_collect(mfsp));
+ }
+
+ /* Entering transaction mode.*/
+ mfsp->state = MFS_TRANSACTION;
+
+ /* Initializing transaction state.*/
+ mfsp->tr_next_offset = mfsp->next_offset;
+ mfsp->tr_nops = 0U;
+ mfsp->tr_limit_offet = mfsp->tr_next_offset + tspace;
+
+ return MFS_NO_ERROR;
+}
+
+/**
+ * @brief A transaction is committed and finalized atomically.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @return The operation status.
+ * @retval MFS_NO_ERROR if the operation has been successfully
+ * completed.
+ * @retval MFS_ERR_INV_STATE if the driver is in not in @p MFS_TRANSACTION
+ * state.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ *
+ * @api
+ */
+mfs_error_t mfsCommitTransaction(MFSDriver *mfsp) {
+ mfs_transaction_op_t *top;
+
+ osalDbgCheck(mfsp != NULL);
+
+ /* The driver must be in transaction mode.*/
+ if (mfsp->state != MFS_TRANSACTION) {
+ return MFS_ERR_INV_STATE;
+ }
+
+ /* Scanning all buffered operations in reverse order.*/
+ mfsp->buffer.dhdr.fields.magic1 = (uint32_t)MFS_HEADER_MAGIC_1;
+ mfsp->buffer.dhdr.fields.magic2 = (uint32_t)MFS_HEADER_MAGIC_2;
+ top = &mfsp->tr_ops[mfsp->tr_nops];
+ while (top > &mfsp->tr_ops[0]) {
+ /* On the previous element.*/
+ top--;
+
+ /* Finalizing the operation by writing the magic number.*/
+ RET_ON_ERROR(mfs_flash_write(mfsp,
+ top->offset,
+ sizeof (uint32_t) * 2U,
+ mfsp->buffer.data8));
+ }
+
+ /* Transaction fully committed by writing the last (first in transaction)
+ magic number, now updating the internal state using the buffered data.*/
+ mfsp->next_offset = mfsp->tr_next_offset;
+ while (top < &mfsp->tr_ops[mfsp->tr_nops]) {
+ unsigned i = (unsigned)top->id - 1U;
+
+ /* The calculation is a bit different depending on write or erase record
+ operations.*/
+ if (top->size > 0U) {
+ /* It is a write.*/
+ if (mfsp->descriptors[i].offset != 0U) {
+ /* The size of the old record instance, if present, must be subtracted
+ to the total used size.*/
+ mfsp->used_space -= ALIGNED_REC_SIZE(mfsp->descriptors[i].size);
+ }
+
+ /* Adjusting bank-related metadata.*/
+ mfsp->used_space += ALIGNED_REC_SIZE(top->size);
+ mfsp->descriptors[i].offset = top->offset;
+ mfsp->descriptors[i].size = top->size;
+ }
+ else {
+ /* It is an erase.*/
+ mfsp->used_space -= ALIGNED_REC_SIZE(mfsp->descriptors[i].size);
+ mfsp->descriptors[i].offset = 0U;
+ mfsp->descriptors[i].size = 0U;
+ }
+
+ /* On the next element.*/
+ top++;
+ }
+
+ /* Returning to ready mode.*/
+ mfsp->state = MFS_READY;
+
+ return MFS_NO_ERROR;
+}
+
+/**
+ * @brief A transaction is rolled back atomically.
+ * @details This function performs a garbage collection in order to discard
+ * all written data that has not been finalized.
+ *
+ * @param[in] mfsp pointer to the @p MFSDriver object
+ * @return The operation status.
+ * @retval MFS_NO_ERROR if the operation has been successfully
+ * completed.
+ * @retval MFS_ERR_INV_STATE if the driver is in not in @p MFS_TRANSACTION
+ * state.
+ * @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
+ * failures. Makes the driver enter the
+ * @p MFS_ERROR state.
+ * @retval MFS_ERR_INTERNAL if an internal logic failure is detected.
+ *
+ * @api
+ */
+mfs_error_t mfsRollbackTransaction(MFSDriver *mfsp) {
+ mfs_error_t err;
+
+ osalDbgCheck(mfsp != NULL);
+
+ if (mfsp->state != MFS_TRANSACTION) {
+ return MFS_ERR_INV_STATE;
+ }
+
+ /* Returning to ready mode.*/
+ mfsp->state = MFS_READY;
+
+ /* If no operations have been performed then there is no need to perform
+ a garbage collection.*/
+ if (mfsp->tr_nops > 0U) {
+ err = mfs_garbage_collect(mfsp);
+ }
+ else {
+ err = MFS_NO_ERROR;
+ }
+
+ return err;
+}
+#endif /* MFS_CFG_TRANSACTION_MAX > 0 */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/lib/complex/mfs/hal_mfs.h b/ChibiOS_20.3.2/os/hal/lib/complex/mfs/hal_mfs.h
new file mode 100644
index 0000000..43ffcbd
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/complex/mfs/hal_mfs.h
@@ -0,0 +1,451 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file hal_mfs.h
+ * @brief Managed Flash Storage module header.
+ *
+ * @addtogroup HAL_MFS
+ * @{
+ */
+
+#ifndef HAL_MFS_H
+#define HAL_MFS_H
+
+#include "hal_flash.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+#define MFS_BANK_MAGIC_1 0xEC705ADEU
+#define MFS_BANK_MAGIC_2 0xF0339CC5U
+#define MFS_HEADER_MAGIC_1 0x5FAE45F0U
+#define MFS_HEADER_MAGIC_2 0xF045AE5FU
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief Maximum number of indexed records in the managed storage.
+ * @note Record indexes go from 1 to @p MFS_CFG_MAX_RECORDS.
+ */
+#if !defined(MFS_CFG_MAX_RECORDS) || defined(__DOXYGEN__)
+#define MFS_CFG_MAX_RECORDS 32
+#endif
+
+/**
+ * @brief Maximum number of repair attempts on partition mount.
+ */
+#if !defined(MFS_CFG_MAX_REPAIR_ATTEMPTS) || defined(__DOXYGEN__)
+#define MFS_CFG_MAX_REPAIR_ATTEMPTS 3
+#endif
+
+/**
+ * @brief Verify written data.
+ */
+#if !defined(MFS_CFG_WRITE_VERIFY) || defined(__DOXYGEN__)
+#define MFS_CFG_WRITE_VERIFY TRUE
+#endif
+
+/**
+ * @brief Enables a stronger and slower check procedure on mount.
+ * @details Strong checking requires reading of the whole written data and
+ * this can be slow, normal checking only checks integrity of
+ * metadata, data errors would be detected on read.
+ */
+#if !defined(MFS_CFG_STRONG_CHECKING) || defined(__DOXYGEN__)
+#define MFS_CFG_STRONG_CHECKING TRUE
+#endif
+
+/**
+ * @brief Size of the buffer used for data copying.
+ * @note The buffer size must be a power of two and not smaller than
+ * 16 bytes.
+ * @note Larger buffers improve performance, buffers with size multiple
+ * of the flash program page size work better.
+ */
+#if !defined(MFS_CFG_BUFFER_SIZE) || defined(__DOXYGEN__)
+#define MFS_CFG_BUFFER_SIZE 32
+#endif
+
+/**
+ * @brief Enforced memory alignment.
+ * @details This value must be a power of two, it enforces a memory alignment
+ * for records in the flash array. This is required when alignment
+ * constraints exist, for example when using a DTR mode on OSPI
+ * devices.
+ */
+#if !defined(MFS_CFG_MEMORY_ALIGNMENT) || defined(__DOXYGEN__)
+#define MFS_CFG_MEMORY_ALIGNMENT 2
+#endif
+
+/**
+ * @brief Maximum number of objects writable in a single transaction.
+ */
+#if !defined(MFS_CFG_TRANSACTION_MAX) || defined(__DOXYGEN__)
+#define MFS_CFG_TRANSACTION_MAX 16
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if MFS_CFG_MAX_RECORDS < 0
+#error "invalid MFS_CFG_MAX_RECORDS value"
+#endif
+
+#if (MFS_CFG_MAX_REPAIR_ATTEMPTS < 1) || \
+ (MFS_CFG_MAX_REPAIR_ATTEMPTS > 10)
+#error "invalid MFS_MAX_REPAIR_ATTEMPTS value"
+#endif
+
+#if MFS_CFG_BUFFER_SIZE < 16
+#error "invalid MFS_CFG_BUFFER_SIZE value"
+#endif
+
+#if (MFS_CFG_BUFFER_SIZE & (MFS_CFG_BUFFER_SIZE - 1)) != 0
+#error "MFS_CFG_BUFFER_SIZE is not a power of two"
+#endif
+
+#if (MFS_CFG_MEMORY_ALIGNMENT < 1) || \
+ (MFS_CFG_MEMORY_ALIGNMENT > MFS_CFG_BUFFER_SIZE)
+#error "invalid MFS_CFG_MEMORY_ALIGNMENT value"
+#endif
+
+#if (MFS_CFG_MEMORY_ALIGNMENT & (MFS_CFG_MEMORY_ALIGNMENT - 1)) != 0
+#error "MFS_CFG_MEMORY_ALIGNMENT is not a power of two"
+#endif
+
+#if (MFS_CFG_TRANSACTION_MAX < 0) || \
+ (MFS_CFG_TRANSACTION_MAX > MFS_CFG_MAX_RECORDS)
+#error "invalid MFS_CFG_TRANSACTION_MAX value"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a flash bank.
+ */
+typedef enum {
+ MFS_BANK_0 = 0,
+ MFS_BANK_1 = 1
+} mfs_bank_t;
+
+/**
+ * @brief Type of driver state machine states.
+ */
+typedef enum {
+ MFS_UNINIT = 0,
+ MFS_STOP = 1,
+ MFS_READY = 2,
+ MFS_TRANSACTION = 3,
+ MFS_ERROR = 4
+} mfs_state_t;
+
+/**
+ * @brief Type of an MFS error code.
+ * @note Errors are negative integers, informative warnings are positive
+ * integers.
+ */
+typedef enum {
+ MFS_NO_ERROR = 0,
+ MFS_WARN_REPAIR = 1,
+ MFS_WARN_GC = 2,
+ MFS_ERR_INV_STATE = -1,
+ MFS_ERR_INV_SIZE = -2,
+ MFS_ERR_NOT_FOUND = -3,
+ MFS_ERR_OUT_OF_MEM = -4,
+ MFS_ERR_TRANSACTION_NUM = -5,
+ MFS_ERR_TRANSACTION_SIZE = -6,
+ MFS_ERR_NOT_ERASED = -7,
+ MFS_ERR_FLASH_FAILURE = -8,
+ MFS_ERR_INTERNAL = -9
+} mfs_error_t;
+
+/**
+ * @brief Type of a bank state assessment.
+ */
+typedef enum {
+ MFS_BANK_ERASED = 0,
+ MFS_BANK_OK = 1,
+ MFS_BANK_GARBAGE = 2
+} mfs_bank_state_t;
+
+/**
+ * @brief Type of a record identifier.
+ */
+typedef uint32_t mfs_id_t;
+
+/**
+ * @brief Type of a bank header.
+ * @note The header resides in the first 16 bytes of a bank.
+ */
+typedef union {
+ struct {
+ /**
+ * @brief Bank magic 1.
+ */
+ uint32_t magic1;
+ /**
+ * @brief Bank magic 2.
+ */
+ uint32_t magic2;
+ /**
+ * @brief Usage counter of the bank.
+ * @details This value is increased each time a bank swap is performed. It
+ * indicates how much wearing the flash has already endured.
+ */
+ uint32_t counter;
+ /**
+ * @brief Reserved field.
+ */
+ uint16_t reserved1;
+ /**
+ * @brief Header CRC.
+ */
+ uint16_t crc;
+ } fields;
+ uint8_t hdr8[16];
+ uint32_t hdr32[4];
+} mfs_bank_header_t;
+
+/**
+ * @brief Type of a data block header.
+ * @details This structure is placed before each written data block.
+ */
+typedef union {
+ struct {
+ /**
+ * @brief Data header magic 1.
+ */
+ uint32_t magic1;
+ /**
+ * @brief Data header magic 2.
+ */
+ uint32_t magic2;
+ /**
+ * @brief Record identifier.
+ */
+ uint16_t id;
+ /**
+ * @brief Data CRC.
+ */
+ uint16_t crc;
+ /**
+ * @brief Data size.
+ * @note The next record is located at @p MFS_ALIGN_NEXT(size).
+ */
+ uint32_t size;
+ } fields;
+ uint8_t hdr8[16];
+ uint32_t hdr32[4];
+} mfs_data_header_t;
+
+typedef struct {
+ /**
+ * @brief Offset of the record header.
+ */
+ flash_offset_t offset;
+ /**
+ * @brief Record data size.
+ */
+ uint32_t size;
+} mfs_record_descriptor_t;
+
+/**
+ * @brief Type of a MFS configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief Flash driver associated to this MFS instance.
+ */
+ BaseFlash *flashp;
+ /**
+ * @brief Erased value.
+ */
+ uint32_t erased;
+ /**
+ * @brief Banks size.
+ */
+ flash_offset_t bank_size;
+ /**
+ * @brief Base sector index for bank 0.
+ */
+ flash_sector_t bank0_start;
+ /**
+ * @brief Number of sectors for bank 0.
+ * @note The total size of bank0 sectors must be greater or equal to
+ * @p bank_size.
+ */
+ flash_sector_t bank0_sectors;
+ /**
+ * @brief Base sector index for bank 1.
+ */
+ flash_sector_t bank1_start;
+ /**
+ * @brief Number of sectors for bank 1.
+ * @note The total size of bank1 sectors must be greater or equal to
+ * @p bank_size.
+ */
+ flash_sector_t bank1_sectors;
+} MFSConfig;
+
+/**
+ * @brief Type of a buffered write/erase operation within a transaction.
+ */
+typedef struct {
+ /**
+ * @brief Written header offset.
+ */
+ flash_offset_t offset;
+ /**
+ * @brief Written data size.
+ */
+ size_t size;
+ /**
+ * @brief Record identifier.
+ */
+ mfs_id_t id;
+} mfs_transaction_op_t;
+
+/**
+ * @brief Type of an MFS instance.
+ */
+typedef struct {
+ /**
+ * @brief Driver state.
+ */
+ mfs_state_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const MFSConfig *config;
+ /**
+ * @brief Bank currently in use.
+ */
+ mfs_bank_t current_bank;
+ /**
+ * @brief Usage counter of the current bank.
+ */
+ uint32_t current_counter;
+ /**
+ * @brief Pointer to the next free position in the current bank.
+ */
+ flash_offset_t next_offset;
+ /**
+ * @brief Used space in the current bank without considering erased records.
+ */
+ flash_offset_t used_space;
+ /**
+ * @brief Offsets of the most recent instance of the records.
+ * @note Zero means that there is not a record with that id.
+ */
+ mfs_record_descriptor_t descriptors[MFS_CFG_MAX_RECORDS];
+#if (MFS_CFG_TRANSACTION_MAX > 0) || defined(__DOXYGEN__)
+ /**
+ * @brief Next write offset for current transaction.
+ */
+ flash_offset_t tr_next_offset;
+ /**
+ * @brief Maximum offset for the transaction.
+ */
+ flash_offset_t tr_limit_offet;
+ /**
+ * @brief Number of buffered operations in current transaction.
+ */
+ uint32_t tr_nops;
+ /**
+ * @brief Buffered operations in current transaction.
+ */
+ mfs_transaction_op_t tr_ops[MFS_CFG_TRANSACTION_MAX];
+#endif
+ /**
+ * @brief Transient buffer.
+ */
+ union {
+ mfs_data_header_t dhdr;
+ mfs_bank_header_t bhdr;
+ uint8_t data8[MFS_CFG_BUFFER_SIZE];
+ uint16_t data16[MFS_CFG_BUFFER_SIZE / sizeof (uint16_t)];
+ uint32_t data32[MFS_CFG_BUFFER_SIZE / sizeof (uint32_t)];
+ } buffer;
+} MFSDriver;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Error codes handling macros
+ * @{
+ */
+#define MFS_IS_ERROR(err) ((err) < MFS_NO_ERROR)
+#define MFS_IS_WARNING(err) ((err) > MFS_NO_ERROR)
+/** @} */
+
+/**
+ * @name Alignment macros
+ * @{
+ */
+#define MFS_ALIGN_MASK ((uint32_t)MFS_CFG_MEMORY_ALIGNMENT - 1U)
+#define MFS_IS_ALIGNED(v) (((uint32_t)(v) & MFS_ALIGN_MASK) == 0U)
+#define MFS_ALIGN_PREV(v) ((uint32_t)(v) & ~MFS_ALIGN_MASK)
+#define MFS_ALIGN_NEXT(v) (MFS_ALIGN_PREV(((uint32_t)(v) - 1U)) + \
+ MFS_CFG_MEMORY_ALIGNMENT)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void mfsObjectInit(MFSDriver *devp);
+ mfs_error_t mfsStart(MFSDriver *devp, const MFSConfig *config);
+ void mfsStop(MFSDriver *devp);
+ mfs_error_t mfsErase(MFSDriver *mfsp);
+ mfs_error_t mfsReadRecord(MFSDriver *devp, mfs_id_t id,
+ size_t *np, uint8_t *buffer);
+ mfs_error_t mfsWriteRecord(MFSDriver *devp, mfs_id_t id,
+ size_t n, const uint8_t *buffer);
+ mfs_error_t mfsEraseRecord(MFSDriver *devp, mfs_id_t id);
+ mfs_error_t mfsPerformGarbageCollection(MFSDriver *mfsp);
+#if MFS_CFG_TRANSACTION_MAX > 0
+ mfs_error_t mfsStartTransaction(MFSDriver *mfsp, size_t size);
+ mfs_error_t mfsCommitTransaction(MFSDriver *mfsp);
+ mfs_error_t mfsRollbackTransaction(MFSDriver *mfsp);
+#endif /* MFS_CFG_TRANSACTION_MAX > 0 */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_MFS_H */
+
+/** @} */
+
diff --git a/ChibiOS_20.3.2/os/hal/lib/complex/mfs/hal_mfs.mk b/ChibiOS_20.3.2/os/hal/lib/complex/mfs/hal_mfs.mk
new file mode 100644
index 0000000..6448737
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/complex/mfs/hal_mfs.mk
@@ -0,0 +1,9 @@
+# List of all the MFS subsystem files.
+MFSSRC := $(CHIBIOS)/os/hal/lib/complex/mfs/hal_mfs.c
+
+# Required include directories
+MFSINC := $(CHIBIOS)/os/hal/lib/complex/mfs
+
+# Shared variables
+ALLCSRC += $(MFSSRC)
+ALLINC += $(MFSINC)
diff --git a/ChibiOS_20.3.2/os/hal/lib/complex/readme.txt b/ChibiOS_20.3.2/os/hal/lib/complex/readme.txt
new file mode 100644
index 0000000..fafdfac
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/complex/readme.txt
@@ -0,0 +1,6 @@
+This directory contains complex drivers subsystems. Complex Drivers must
+abide to the following rules:
+- Must use HAL and OSAL only.
+- Cannot use RTOS functionalities.
+- Cannot use HW resources directly.
+- Must not use non-standard C language features.
diff --git a/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/devices/macronix_mx25/hal_flash_device.c b/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/devices/macronix_mx25/hal_flash_device.c
new file mode 100644
index 0000000..39a7475
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/devices/macronix_mx25/hal_flash_device.c
@@ -0,0 +1,666 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_flash_device.c
+ * @brief Macronix MX25 serial flash driver code.
+ *
+ * @addtogroup MACRONIX_MX25
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+#include "hal_serial_nor.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define PAGE_SIZE 256U
+#define PAGE_MASK (PAGE_SIZE - 1U)
+
+#if MX25_USE_SUB_SECTORS == TRUE
+#define SECTOR_SIZE 0x00001000U
+#define CMD_SECTOR_ERASE MX25_CMD_SUBSECTOR_ERASE
+#else
+#define SECTOR_SIZE 0x00010000U
+#define CMD_SECTOR_ERASE MX25_CMD_SECTOR_ERASE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief MX25LM51245G descriptor.
+ */
+flash_descriptor_t snor_descriptor = {
+ .attributes = FLASH_ATTR_ERASED_IS_ONE | FLASH_ATTR_REWRITABLE |
+ FLASH_ATTR_SUSPEND_ERASE_CAPABLE,
+ .page_size = 256U,
+ .sectors_count = 0U, /* It is overwritten.*/
+ .sectors = NULL,
+ .sectors_size = SECTOR_SIZE,
+ .address = 0U,
+ .size = 0U /* It is overwritten.*/
+};
+
+#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) || defined(__DOXYGEN__)
+#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Fast read command for memory mapped mode.
+ */
+const wspi_command_t snor_memmap_read = {
+ .addr = 0U,
+#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
+ .cmd = MX25_CMD_SPI_FAST_READ4B,
+ .dummy = 8, /* Note, always 8 for this command. */
+ .cfg = MX25_CFG_C8_A32_DATA_SPI
+#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_STR
+ .cmd = MX25_CMD_OPI_8READ,
+ .dummy = MX25_READ_DUMMY_CYCLES,
+ .cfg = MX25_CFG_C16_A32_DATA_8STR
+#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR
+ .cmd = MX25_CMD_OPI_8DTRD,
+ .dummy = MX25_READ_DUMMY_CYCLES,
+ .cfg = MX25_CFG_C16_A32_DATA_8DTR
+#endif
+};
+#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */
+#endif /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
+/* Initial MX25_CMD_READ_ID command.*/
+static const wspi_command_t mx25_cmd_read_id = {
+
+#if MX25_SWITCH_WIDTH == TRUE
+ .cmd = MX25_CMD_SPI_RDID,
+ .cfg = MX25_CFG_C8_DATA_SPI,
+ .dummy = 0,
+#else
+#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
+ .cmd = MX25_CMD_SPI_RDID,
+ .cfg = MX25_CFG_C8_DATA_SPI,
+ .dummy = 0,
+#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_STR
+ .cmd = MX25_CMD_OPI_RDID,
+ .cfg = MX25_CFG_C16_A32_DATA_8STR,
+ .dummy = 4U, /*Note: always 4 dummies. */
+#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR
+ .cmd = MX25_CMD_OPI_RDID,
+ .cfg = MX25_CFG_C16_A32_DATA_8DTR
+ .dummy = 4U, /*Note: always 4 dummies. */
+#endif
+#endif
+ .addr = 0,
+ .alt = 0
+};
+
+static const uint8_t mx25_manufacturer_ids[] = MX25_SUPPORTED_MANUFACTURE_IDS;
+static const uint8_t mx25_memory_type_ids[] = MX25_SUPPORTED_MEMORY_TYPE_IDS;
+#endif /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static bool mx25_find_id(const uint8_t *set, size_t size, uint8_t element) {
+ size_t i;
+
+ for (i = 0; i < size; i++) {
+ if (set[i] == element) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static flash_error_t mx25_poll_status(SNORDriver *devp) {
+ uint8_t sts[2], sec[2];
+
+ do {
+#if MX25_NICE_WAITING == TRUE
+ osalThreadSleepMilliseconds(1);
+#endif
+ /* Read status command.*/
+#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
+ bus_cmd_receive(devp->config->busp, MX25_CMD_SPI_RDSR, 1U, sts);
+#else
+ bus_cmd_addr_dummy_receive(devp->config->busp, MX25_CMD_OPI_RDSR,
+ 0U, 4U, 2U, sts); /*Note: always 4 dummies.*/
+#endif
+ } while ((sts[0] & 1U) != 0U);
+
+ /* Reading security register and checking for errors.*/
+#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
+ bus_cmd_receive(devp->config->busp, MX25_CMD_SPI_RDSCUR, 1U, sec);
+#else
+ bus_cmd_addr_dummy_receive(devp->config->busp, MX25_CMD_OPI_RDSCUR,
+ 0U, 4U, 2U, sec); /*Note: always 4 dummies.*/
+#endif
+ if ((sec[0] & MX25_FLAGS_ALL_ERRORS) != 0U) {
+
+ return FLASH_ERROR_PROGRAM;
+ }
+
+ return FLASH_NO_ERROR;
+}
+
+#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) || defined(__DOXYGEN__)
+/**
+ * @brief Device software reset.
+ * @note It attempts to reset first in supposed final bus mode then tries
+ * in SPI mode.
+ *
+ * @param[in] devp pointer to a @p SNORDriver instance
+ */
+static void mx25_reset(SNORDriver *devp) {
+
+ /* 1x MX25_CMD_SPI_RSTEN command.*/
+ static const wspi_command_t cmd_reset_enable_1 = {
+ .cmd = MX25_CMD_SPI_RSTEN,
+ .cfg = MX25_CFG_C8_SPI,
+ .addr = 0,
+ .alt = 0,
+ .dummy = 0
+ };
+
+ /* 1x MX25_CMD_SPI_RST command.*/
+ static const wspi_command_t cmd_reset_memory_1 = {
+ .cmd = MX25_CMD_SPI_RST,
+ .cfg = MX25_CFG_C8_SPI,
+ .addr = 0,
+ .alt = 0,
+ .dummy = 0
+ };
+
+ /* If the device is in one bit mode then the following commands are
+ rejected because shorter than 8 bits. If the device is in multiple
+ bits mode then the commands are accepted and the device is reset to
+ one bit mode.*/
+#if MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR
+ /* 8xDTR MX25_CMD_OPI_RSTEN command.*/
+ static const wspi_command_t cmd_reset_enable_8dtr = {
+ .cmd = MX25_CMD_OPI_RSTEN,
+ .cfg = MX25_CFG_C16_8DTR,
+ .addr = 0,
+ .alt = 0,
+ .dummy = 0
+ };
+
+ /* 8xDTR MX25_CMD_OPI_RST command.*/
+ static const wspi_command_t cmd_reset_memory_8dtr = {
+ .cmd = MX25_CMD_OPI_RST,
+ .cfg = MX25_CFG_C16_8DTR,
+ .addr = 0,
+ .alt = 0,
+ .dummy = 0
+ };
+
+ wspiCommand(devp->config->busp, &cmd_reset_enable_8dtr);
+ wspiCommand(devp->config->busp, &cmd_reset_memory_8dtr);
+#else
+ /* 8xSTR MX25_CMD_OPI_RSTEN command.*/
+ static const wspi_command_t cmd_reset_enable_8str = {
+ .cmd = MX25_CMD_OPI_RSTEN,
+ .cfg = MX25_CFG_C16_8STR,
+ .addr = 0,
+ .alt = 0,
+ .dummy = 0
+ };
+
+ /* 8xSTR MX25_CMD_OPI_RST command.*/
+ static const wspi_command_t cmd_reset_memory_8str = {
+ .cmd = MX25_CMD_OPI_RST,
+ .cfg = MX25_CFG_C16_8STR,
+ .addr = 0,
+ .alt = 0,
+ .dummy = 0
+ };
+
+ wspiCommand(devp->config->busp, &cmd_reset_enable_8str);
+ wspiCommand(devp->config->busp, &cmd_reset_memory_8str);
+#endif
+
+ /* Now the device should be in one bit mode for sure and we perform a
+ device reset.*/
+ wspiCommand(devp->config->busp, &cmd_reset_enable_1);
+ wspiCommand(devp->config->busp, &cmd_reset_memory_1);
+}
+
+/**
+ * @brief Writes a CR2 register in after-reset bus mode.
+ * @note This function can only be used before the device is switched to
+ * the final bus width.
+ *
+ * @param[in] devp pointer to a @p SNORDriver instance
+ * @param[in] addr address field
+ * @param[in] value value to be written
+ */
+static void mx25_write_cr2(SNORDriver *devp, uint32_t addr, const uint8_t *value) {
+
+ static const wspi_command_t cmd_write_enable = {
+#if MX25_SWITCH_WIDTH == TRUE
+ .cmd = MX25_CMD_SPI_WREN,
+ .cfg = MX25_CFG_C8_SPI,
+#else
+#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
+ .cmd = MX25_CMD_SPI_WREN,
+ .cfg = MX25_CFG_C8_SPI,
+#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_STR
+ .cmd = MX25_CMD_OPI_WREN,
+ .cfg = MX25_CFG_C16_8STR,
+#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR
+ .cmd = MX25_CMD_OPI_WREN,
+ .cfg = MX25_CFG_C16_8DTR,
+#endif
+#endif
+ .addr = 0,
+ .alt = 0,
+ .dummy = 0
+ };
+
+ const wspi_command_t cmd_write_cr2 = {
+
+#if MX25_SWITCH_WIDTH == TRUE
+ .cmd = MX25_CMD_SPI_WRCR2,
+ .cfg = MX25_CFG_C8_A32_DATA_SPI,
+#else
+#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
+ .cmd = MX25_CMD_SPI_WRCR2,
+ .cfg = MX25_CFG_C8_A32_DATA_SPI,
+#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_STR
+ .cmd = MX25_CMD_OPI_WRCR2,
+ .cfg = MX25_CFG_C16_A32_DATA_8STR,
+#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR
+ .cmd = MX25_CMD_OPI_WRCR2,
+ .cfg = MX25_CFG_C16_A32_DATA_8DTR,
+#endif
+#endif
+ .addr = addr,
+ .alt = 0,
+ .dummy = 0
+ };
+
+ wspiCommand(devp->config->busp, &cmd_write_enable);
+ wspiSend(devp->config->busp, &cmd_write_cr2, 1, value);
+}
+#endif /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Device initialization.
+ *
+ * @param[in] devp pointer to a @p SNORDriver instance
+ */
+void snor_device_init(SNORDriver *devp) {
+
+#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_SPI
+ /* Reading device ID.*/
+ bus_cmd_receive(devp->config->busp, MX25_CMD_READ_ID,
+ sizeof devp->device_id, devp->device_id);
+
+#else /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
+
+#if MX25_RESET_ON_INIT == TRUE
+ {
+ /* Attempting a reset of the device, it could be in an unexpected state
+ because a CPU reset does not reset the memory too.*/
+ mx25_reset(devp);
+
+ /* The device requires at least 10uS to recover after a reset, it could
+ need up to 100mS in cause a reset occurred during a chip erase, 50uS
+ covers most cases.*/
+ osalThreadSleepMicroseconds(50);
+ }
+#endif
+
+ /* Reading device ID and unique ID.*/
+ wspiReceive(devp->config->busp, &mx25_cmd_read_id, 3U, devp->device_id);
+#endif /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
+
+ /* Checking if the device is white listed.*/
+ osalDbgAssert(mx25_find_id(mx25_manufacturer_ids,
+ sizeof mx25_manufacturer_ids,
+ devp->device_id[0]),
+ "invalid manufacturer id");
+ osalDbgAssert(mx25_find_id(mx25_memory_type_ids,
+ sizeof mx25_memory_type_ids,
+ devp->device_id[1]),
+ "invalid memory type id");
+
+#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
+ /* Setting up the dummy cycles to be used for fast read operations.*/
+ {
+ static const uint8_t v[1] = {~((MX25_READ_DUMMY_CYCLES - 6U) / 2U) & 7U};
+ mx25_write_cr2(devp, 0x00000300U, v);
+ }
+#endif
+
+#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) && (MX25_SWITCH_WIDTH == TRUE)
+ {
+ uint8_t id[8];
+#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
+ static const uint8_t v[1] = {0x00};
+#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_STR
+ static const uint8_t v[1] = {0x01};
+#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR
+ static const uint8_t v[1] = {0x02};
+#endif
+
+ /* Setting up final bus width.*/
+ mx25_write_cr2(devp, 0x00000000U, v);
+
+ /* Reading ID again for confirmation, in DTR mode bytes are read twice,
+ it needs adjusting.*/
+#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
+ bus_cmd_receive(devp->config->busp, MX25_CMD_SPI_RDID, 3U, id);
+#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_STR
+ bus_cmd_addr_dummy_receive(devp->config->busp, MX25_CMD_OPI_RDID,
+ 0U, 4U, 3U, id); /*Note: always 4 dummies. */
+#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR
+ bus_cmd_addr_dummy_receive(devp->config->busp, MX25_CMD_OPI_RDID,
+ 0U, 4U, 6U, id); /*Note: always 4 dummies. */
+ id[1] = id[2];
+ id[2] = id[4];
+#endif
+
+ /* Checking if the device is white listed.*/
+ osalDbgAssert(memcmp(id, devp->device_id, 3) == 0,
+ "id confirmation failed");
+ }
+#endif
+
+ /* Setting up the device size.*/
+ snor_descriptor.sectors_count = (1U << ((size_t)devp->device_id[2] & 0x1FU)) /
+ SECTOR_SIZE;
+ snor_descriptor.size = (size_t)snor_descriptor.sectors_count * SECTOR_SIZE;
+}
+
+/**
+ * @brief Device read.
+ *
+ * @param[in] devp pointer to a @p SNORDriver instance
+ * @param[in] offset flash offset
+ * @param[in] n number of bytes
+ * @param[out] rp pointer to the buffer
+ */
+flash_error_t snor_device_read(SNORDriver *devp, flash_offset_t offset,
+ size_t n, uint8_t *rp) {
+
+#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
+ /* Fast read command in WSPI mode.*/
+#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
+ bus_cmd_addr_dummy_receive(devp->config->busp, MX25_CMD_SPI_FAST_READ4B,
+ offset, 8, /* Note, always 8 dummy cycles. */
+ n, rp);
+#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR
+ bus_cmd_addr_dummy_receive(devp->config->busp, MX25_CMD_OPI_8DTRD,
+ offset, MX25_READ_DUMMY_CYCLES, n, rp);
+#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_STR
+ bus_cmd_addr_dummy_receive(devp->config->busp, MX25_CMD_OPI_8READ,
+ offset, MX25_READ_DUMMY_CYCLES, n, rp);
+#endif
+#else
+ /* Normal read command in SPI mode.*/
+ bus_cmd_addr_receive(devp->config->busp, MX25_CMD_SPI_READ4B,
+ offset, n, rp);
+#endif
+
+ return FLASH_NO_ERROR;
+}
+
+
+/**
+ * @brief Device program.
+ *
+ * @param[in] devp pointer to a @p SNORDriver instance
+ * @param[in] offset flash offset
+ * @param[in] n number of bytes
+ * @param[in] pp pointer to the buffer
+ */
+flash_error_t snor_device_program(SNORDriver *devp, flash_offset_t offset,
+ size_t n, const uint8_t *pp) {
+
+ /* Data is programmed page by page.*/
+ while (n > 0U) {
+ flash_error_t err;
+
+ /* Data size that can be written in a single program page operation.*/
+ size_t chunk = (size_t)(((offset | PAGE_MASK) + 1U) - offset);
+ if (chunk > n) {
+ chunk = n;
+ }
+
+#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
+ /* Enabling write operation.*/
+ bus_cmd(devp->config->busp, MX25_CMD_SPI_WREN);
+
+ /* Page program command.*/
+ bus_cmd_addr_send(devp->config->busp, MX25_CMD_SPI_PP4B, offset,
+ chunk, pp);
+#else
+ /* Enabling write operation.*/
+ bus_cmd(devp->config->busp, MX25_CMD_OPI_WREN);
+
+ /* Page program command.*/
+ bus_cmd_addr_send(devp->config->busp, MX25_CMD_OPI_PP, offset,
+ chunk, pp);
+#endif
+
+ /* Wait for status and check errors.*/
+ err = mx25_poll_status(devp);
+ if (err != FLASH_NO_ERROR) {
+
+ return err;
+ }
+
+ /* Next page.*/
+ offset += chunk;
+ pp += chunk;
+ n -= chunk;
+ }
+
+ return FLASH_NO_ERROR;
+}
+
+/**
+ * @brief Device global erase start.
+ *
+ * @param[in] devp pointer to a @p SNORDriver instance
+ */
+flash_error_t snor_device_start_erase_all(SNORDriver *devp) {
+
+#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
+ /* Enabling write operation.*/
+ bus_cmd(devp->config->busp, MX25_CMD_SPI_WREN);
+
+ /* Bulk erase command.*/
+ bus_cmd(devp->config->busp, MX25_CMD_SPI_CE);
+#else
+ /* Enabling write operation.*/
+ bus_cmd(devp->config->busp, MX25_CMD_OPI_WREN);
+
+ /* Bulk erase command.*/
+ bus_cmd(devp->config->busp, MX25_CMD_OPI_CE);
+#endif
+
+ return FLASH_NO_ERROR;
+}
+
+
+/**
+ * @brief Device sector erase start.
+ *
+ * @param[in] devp pointer to a @p SNORDriver instance
+ * @param[in] sector flash sector
+ */
+flash_error_t snor_device_start_erase_sector(SNORDriver *devp,
+ flash_sector_t sector) {
+ flash_offset_t offset = (flash_offset_t)(sector * SECTOR_SIZE);
+
+#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
+ /* Enabling write operation.*/
+ bus_cmd(devp->config->busp, MX25_CMD_SPI_WREN);
+
+#if MX25_USE_SUB_SECTORS == FALSE
+ /* Block erase command.*/
+ bus_cmd_addr(devp->config->busp, MX25_CMD_SPI_BE4B, offset);
+#else
+ /* Sector erase command.*/
+ bus_cmd_addr(devp->config->busp, MX25_CMD_SPI_SE4B, offset);
+#endif
+#else
+ /* Enabling write operation.*/
+ bus_cmd(devp->config->busp, MX25_CMD_OPI_WREN);
+
+#if MX25_USE_SUB_SECTORS == FALSE
+ /* Block erase command.*/
+ bus_cmd_addr(devp->config->busp, MX25_CMD_OPI_BE, offset);
+#else
+ /* Sector erase command.*/
+ bus_cmd_addr(devp->config->busp, MX25_CMD_OPI_SE, offset);
+#endif
+#endif
+
+ return FLASH_NO_ERROR;
+}
+
+/**
+ * @brief Device erase verify.
+ *
+ * @param[in] devp pointer to a @p SNORDriver instance
+ * @param[in] sector flash sector
+ */
+flash_error_t snor_device_verify_erase(SNORDriver *devp,
+ flash_sector_t sector) {
+ uint8_t cmpbuf[MX25_COMPARE_BUFFER_SIZE];
+ flash_offset_t offset;
+ size_t n;
+
+ /* Read command.*/
+ offset = (flash_offset_t)(sector * SECTOR_SIZE);
+ n = SECTOR_SIZE;
+ while (n > 0U) {
+ uint8_t *p;
+
+#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
+#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
+ bus_cmd_addr_dummy_receive(devp->config->busp, MX25_CMD_SPI_FAST_READ4B,
+ offset, 8, /* Note, always 8 dummy cycles. */
+ sizeof cmpbuf, cmpbuf);
+#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_STR
+ bus_cmd_addr_dummy_receive(devp->config->busp, MX25_CMD_OPI_8READ,
+ offset, MX25_READ_DUMMY_CYCLES,
+ sizeof cmpbuf, cmpbuf);
+#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR
+ bus_cmd_addr_dummy_receive(devp->config->busp, MX25_CMD_OPI_8DTRD,
+ offset, MX25_READ_DUMMY_CYCLES,
+ sizeof cmpbuf, cmpbuf);
+#endif
+#else
+ /* Normal read command in SPI mode.*/
+ bus_cmd_addr_receive(devp->config->busp, MX25_CMD_SPI_READ4B,
+ offset, sizeof cmpbuf, cmpbuf);
+#endif
+
+ /* Checking for erased state of current buffer.*/
+ for (p = cmpbuf; p < &cmpbuf[MX25_COMPARE_BUFFER_SIZE]; p++) {
+ if (*p != 0xFFU) {
+ /* Ready state again.*/
+ devp->state = FLASH_READY;
+
+ return FLASH_ERROR_VERIFY;
+ }
+ }
+
+ offset += sizeof cmpbuf;
+ n -= sizeof cmpbuf;
+ }
+
+ return FLASH_NO_ERROR;
+}
+
+/**
+ * @brief Queries if there is an erase in progress.
+ *
+ * @param[in] devp pointer to a @p SNORDriver instance
+ * @param[out] msec suggested number of milliseconds before calling this
+ * function again
+ */
+flash_error_t snor_device_query_erase(SNORDriver *devp, uint32_t *msec) {
+ uint8_t sts[2], sec[2];
+
+ /* Read status register.*/
+#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
+ bus_cmd_receive(devp->config->busp, MX25_CMD_SPI_RDSR, 1U, sts);
+#else
+ bus_cmd_addr_dummy_receive(devp->config->busp, MX25_CMD_OPI_RDSR,
+ 0U, 4U, 2U, sts); /*Note: always 4 dummies. */
+#endif
+
+ /* Read security register.*/
+#if MX25_BUS_MODE == MX25_BUS_MODE_SPI
+ bus_cmd_receive(devp->config->busp, MX25_CMD_SPI_RDSCUR, 1U, sec);
+#else
+ bus_cmd_addr_dummy_receive(devp->config->busp, MX25_CMD_OPI_RDSCUR,
+ 0U, 4U, 2U, sec); /*Note: always 4 dummies. */
+#endif
+
+ /* If the WIP bit is one (busy) or the flash in a suspended state then
+ report that the operation is still in progress.*/
+ if (((sts[0] & 1) != 0U) || ((sec[0] & 8) != 0U)) {
+
+ /* Recommended time before polling again, this is a simplified
+ implementation.*/
+ if (msec != NULL) {
+ *msec = 1U;
+ }
+
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* Checking for errors.*/
+ if ((sec[0] & MX25_FLAGS_ALL_ERRORS) != 0U) {
+
+ /* Erase operation failed.*/
+ return FLASH_ERROR_ERASE;
+ }
+
+ return FLASH_NO_ERROR;
+}
+
+flash_error_t snor_device_read_sfdp(SNORDriver *devp, flash_offset_t offset,
+ size_t n, uint8_t *rp) {
+
+ (void)devp;
+ (void)rp;
+ (void)offset;
+ (void)n;
+
+ return FLASH_NO_ERROR;
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/devices/macronix_mx25/hal_flash_device.h b/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/devices/macronix_mx25/hal_flash_device.h
new file mode 100644
index 0000000..45a8ef9
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/devices/macronix_mx25/hal_flash_device.h
@@ -0,0 +1,441 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_flash_device.h
+ * @brief Macronix MX25 serial flash driver header.
+ *
+ * @addtogroup MACRONIX_MX25
+ * @{
+ */
+
+#ifndef HAL_FLASH_DEVICE_H
+#define HAL_FLASH_DEVICE_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Device capabilities
+ * @{
+ */
+#define SNOR_DEVICE_SUPPORTS_XIP FALSE
+/** @} */
+
+/**
+ * @name Device identification
+ * @{
+ */
+#define MX25_SUPPORTED_MANUFACTURE_IDS {0xC2}
+#define MX25_SUPPORTED_MEMORY_TYPE_IDS {0x85}
+/** @} */
+
+/**
+ * @name Command codes, SPI mode
+ * @{
+ */
+#define MX25_CMD_SPI_READ3B 0x03U
+#define MX25_CMD_SPI_FAST_READ3B 0x0BU
+#define MX25_CMD_SPI_PP3B 0x02U
+#define MX25_CMD_SPI_SE3B 0x20U
+#define MX25_CMD_SPI_BE3B 0xD8U
+#define MX25_CMD_SPI_CE 0xC7U
+#define MX25_CMD_SPI_READ4B 0x13U
+#define MX25_CMD_SPI_FAST_READ4B 0x0CU
+#define MX25_CMD_SPI_PP4B 0x12U
+#define MX25_CMD_SPI_SE4B 0x21U
+#define MX25_CMD_SPI_BE4B 0xDCU
+#define MX25_CMD_SPI_WREN 0x06U
+#define MX25_CMD_SPI_WRDI 0x04U
+#define MX25_CMD_SPI_PE_SUSPEND 0xB0U
+#define MX25_CMD_SPI_PE_RESUME 0x30U
+#define MX25_CMD_SPI_DP 0xB9U
+#define MX25_CMD_SPI_SBL 0xC0U
+#define MX25_CMD_SPI_ENSO 0xB1U
+#define MX25_CMD_SPI_EXSO 0xC1U
+#define MX25_CMD_SPI_NOP 0x00U
+#define MX25_CMD_SPI_RSTEN 0x66U
+#define MX25_CMD_SPI_RST 0x99U
+#define MX25_CMD_SPI_RDID 0x9FU
+#define MX25_CMD_SPI_RDSFDP 0x5AU
+#define MX25_CMD_SPI_RDSR 0x05U
+#define MX25_CMD_SPI_RDCR 0x15U
+#define MX25_CMD_SPI_WRSR 0x01U
+#define MX25_CMD_SPI_RDCR2 0x71U
+#define MX25_CMD_SPI_WRCR2 0x72U
+#define MX25_CMD_SPI_RDFBR 0x16U
+#define MX25_CMD_SPI_WRFBR 0x17U
+#define MX25_CMD_SPI_ESFBR 0x18U
+#define MX25_CMD_SPI_RDSCUR 0x2BU
+#define MX25_CMD_SPI_WRSCUR 0x2FU
+#define MX25_CMD_SPI_WRLR 0x2CU
+#define MX25_CMD_SPI_RDLR 0x2DU
+#define MX25_CMD_SPI_WRSPB 0xE3U
+#define MX25_CMD_SPI_ESSPB 0xE4U
+#define MX25_CMD_SPI_RDSPB 0xE2U
+#define MX25_CMD_SPI_WRDPB 0xE1U
+#define MX25_CMD_SPI_RDDPB 0xE0U
+#define MX25_CMD_SPI_WPSEL 0x68U
+#define MX25_CMD_SPI_GBLK 0x7EU
+#define MX25_CMD_SPI_GBULK 0x98U
+#define MX25_CMD_SPI_RDPASS 0x27U
+#define MX25_CMD_SPI_WRPASS 0x28U
+#define MX25_CMD_SPI_PASSULK 0x29U
+/** @} */
+
+/**
+ * @name Command codes, OPI mode
+ * @{
+ */
+#define MX25_CMD_OPI_8READ 0xEC13U
+#define MX25_CMD_OPI_8DTRD 0xEE11U
+#define MX25_CMD_OPI_RDID 0x9F60U
+#define MX25_CMD_OPI_RDSFDP 0x5AA5U
+#define MX25_CMD_OPI_PP 0x12EDU
+#define MX25_CMD_OPI_SE 0x21DEU
+#define MX25_CMD_OPI_BE 0xDC23U
+#define MX25_CMD_OPI_CE 0xC738U
+#define MX25_CMD_OPI_WREN 0x06F9U
+#define MX25_CMD_OPI_WRDI 0x04FBU
+#define MX25_CMD_OPI_PE_SUSPEND 0xB04FU
+#define MX25_CMD_OPI_PE_RESUME 0x30CFU
+#define MX25_CMD_OPI_DP 0xB946U
+#define MX25_CMD_OPI_SBL 0xC03FU
+#define MX25_CMD_OPI_ENSO 0xB14EU
+#define MX25_CMD_OPI_EXSO 0xC13EU
+#define MX25_CMD_OPI_NOP 0x00FFU
+#define MX25_CMD_OPI_RSTEN 0x6699U
+#define MX25_CMD_OPI_RST 0x9966U
+#define MX25_CMD_OPI_RDSR 0x05FAU
+#define MX25_CMD_OPI_RDCR 0x15EAU
+#define MX25_CMD_OPI_WRSR 0x01FEU
+#define MX25_CMD_OPI_WRCR 0x01FEU
+#define MX25_CMD_OPI_RDCR2 0x718EU
+#define MX25_CMD_OPI_WRCR2 0x728DU
+#define MX25_CMD_OPI_RDFBR 0x16E9U
+#define MX25_CMD_OPI_WRFBR 0x17E8U
+#define MX25_CMD_OPI_ESFBR 0x18E7U
+#define MX25_CMD_OPI_RDSCUR 0x2BD4U
+#define MX25_CMD_OPI_WRSCUR 0x2FD0U
+#define MX25_CMD_OPI_WRLR 0x2CD3U
+#define MX25_CMD_OPI_RDLR 0x2DD2U
+#define MX25_CMD_OPI_WRSPB 0xE31CU
+#define MX25_CMD_OPI_ESSPB 0xE41BU
+#define MX25_CMD_OPI_RDSPB 0xE21DU
+#define MX25_CMD_OPI_WRDPB 0xE11EU
+#define MX25_CMD_OPI_RDDPB 0xE01FU
+#define MX25_CMD_OPI_WPSEL 0x6897U
+#define MX25_CMD_OPI_GBLK 0x7E81U
+#define MX25_CMD_OPI_GBULK 0x9867U
+#define MX25_CMD_OPI_RDPASS 0x27D8U
+#define MX25_CMD_OPI_WRPASS 0x28D7U
+#define MX25_CMD_OPI_PASSULK 0x29D6U
+/** @} */
+
+/**
+ * @name Flags status register bits
+ * @{
+ */
+#define MX25_FLAGS_WPSEL 0x80U
+#define MX25_FLAGS_E_FAIL 0x40U
+#define MX25_FLAGS_P_FAIL 0x20U
+#define MX25_FLAGS_ESB 0x08U
+#define MX25_FLAGS_PSB 0x04U
+#define MX25_FLAGS_LDSO 0x02U
+#define MX25_FLAGS_SECURED_OTP 0x01U
+#define MX25_FLAGS_ALL_ERRORS (MX25_FLAGS_E_FAIL | \
+ MX25_FLAGS_P_FAIL)
+/** @} */
+
+/**
+ * @name Bus interface modes.
+ * @{
+ */
+#define MX25_BUS_MODE_SPI 0U
+#define MX25_BUS_MODE_OPI_STR 1U
+#define MX25_BUS_MODE_OPI_DTR 2U
+/** @} */
+
+/**
+ * @name MX25-required transfer modes
+ * @{
+ */
+#define MX25_CFG_C8_SPI (WSPI_CFG_CMD_SIZE_8 | \
+ WSPI_CFG_CMD_MODE_ONE_LINE | \
+ WSPI_CFG_ADDR_MODE_NONE | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_NONE)
+
+#define MX25_CFG_C16_8STR (WSPI_CFG_CMD_SIZE_16 | \
+ WSPI_CFG_CMD_MODE_EIGHT_LINES | \
+ WSPI_CFG_ADDR_MODE_NONE | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_NONE)
+
+#define MX25_CFG_C16_8DTR (WSPI_CFG_CMD_SIZE_16 | \
+ WSPI_CFG_CMD_MODE_EIGHT_LINES | \
+ WSPI_CFG_ADDR_MODE_NONE | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_NONE | \
+ WSPI_CFG_ALL_DTR)
+
+#define MX25_CFG_C8_A32_SPI (WSPI_CFG_CMD_SIZE_8 | \
+ WSPI_CFG_CMD_MODE_ONE_LINE | \
+ WSPI_CFG_ADDR_MODE_ONE_LINE | \
+ WSPI_CFG_ADDR_SIZE_32 | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_NONE)
+
+#define MX25_CFG_C16_A32_8STR (WSPI_CFG_CMD_SIZE_16 | \
+ WSPI_CFG_CMD_MODE_EIGHT_LINES | \
+ WSPI_CFG_ADDR_MODE_EIGHT_LINES | \
+ WSPI_CFG_ADDR_SIZE_32 | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_NONE)
+
+#define MX25_CFG_C16_A32_8DTR (WSPI_CFG_CMD_SIZE_16 | \
+ WSPI_CFG_CMD_MODE_EIGHT_LINES | \
+ WSPI_CFG_ADDR_MODE_EIGHT_LINES | \
+ WSPI_CFG_ADDR_SIZE_32 | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_NONE | \
+ WSPI_CFG_ALL_DTR)
+
+#define MX25_CFG_C8_DATA_SPI (WSPI_CFG_CMD_SIZE_8 | \
+ WSPI_CFG_CMD_MODE_ONE_LINE | \
+ WSPI_CFG_ADDR_MODE_NONE | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_ONE_LINE)
+
+#define MX25_CFG_C16_DATA_8STR (WSPI_CFG_CMD_SIZE_16 | \
+ WSPI_CFG_CMD_MODE_EIGHT_LINES | \
+ WSPI_CFG_ADDR_MODE_NONE | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_EIGHT_LINES)
+
+#define MX25_CFG_C16_DATA_8DTR (WSPI_CFG_CMD_SIZE_16 | \
+ WSPI_CFG_CMD_MODE_EIGHT_LINES | \
+ WSPI_CFG_ADDR_MODE_NONE | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_EIGHT_LINES | \
+ WSPI_CFG_ALL_DTR | \
+ WSPI_CFG_DQS_ENABLE)
+
+#define MX25_CFG_C8_A32_DATA_SPI (WSPI_CFG_CMD_SIZE_8 | \
+ WSPI_CFG_CMD_MODE_ONE_LINE | \
+ WSPI_CFG_ADDR_MODE_ONE_LINE | \
+ WSPI_CFG_ADDR_SIZE_32 | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_ONE_LINE)
+
+#define MX25_CFG_C16_A32_DATA_8STR (WSPI_CFG_CMD_SIZE_16 | \
+ WSPI_CFG_CMD_MODE_EIGHT_LINES | \
+ WSPI_CFG_ADDR_MODE_EIGHT_LINES | \
+ WSPI_CFG_ADDR_SIZE_32 | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_EIGHT_LINES)
+
+#define MX25_CFG_C16_A32_DATA_8DTR (WSPI_CFG_CMD_SIZE_16 | \
+ WSPI_CFG_CMD_MODE_EIGHT_LINES | \
+ WSPI_CFG_ADDR_MODE_EIGHT_LINES | \
+ WSPI_CFG_ADDR_SIZE_32 | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_EIGHT_LINES | \
+ WSPI_CFG_ALL_DTR | \
+ WSPI_CFG_DQS_ENABLE)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief SW reset on initialization.
+ * @details Enforces a reset on initialization, this could be required if
+ * the device is not reset in HW or during debugging.
+ * @note It is only effective if the WSPI driver is in use, it does
+ * nothing when SPI driver is used.
+ */
+#if !defined(MX25_RESET_ON_INIT) || defined(__DOXYGEN__)
+#define MX25_RESET_ON_INIT TRUE
+#endif
+
+/**
+ * @brief Switch WSPI bus width on initialization.
+ * @details A bus width initialization is performed by writing the
+ * Enhanced Volatile Configuration Register. If the flash
+ * device is configured using the Non Volatile Configuration
+ * Register then this option is not required.
+ * @note This option is only valid in QSPI bus modes.
+ */
+#if !defined(MX25_SWITCH_WIDTH) || defined(__DOXYGEN__)
+#define MX25_SWITCH_WIDTH TRUE
+#endif
+
+/**
+ * @brief Device bus mode to be used.
+ * #note if @p MX25_SWITCH_WIDTH is @p FALSE then this is the bus mode
+ * that the device is expected to be using.
+ * #note if @p MX25_SWITCH_WIDTH is @p TRUE then this is the bus mode
+ * that the device will be switched in.
+ * @note This option is only valid in WSPI bus mode.
+ */
+#if !defined(MX25_BUS_MODE) || defined(__DOXYGEN__)
+#define MX25_BUS_MODE MX25_BUS_MODE_OPI_DTR
+#endif
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the flash waiting
+ * routines releasing some extra CPU time for threads with lower
+ * priority, this may slow down the driver a bit however.
+ */
+#if !defined(MX25_NICE_WAITING) || defined(__DOXYGEN__)
+#define MX25_NICE_WAITING TRUE
+#endif
+
+/**
+ * @brief Uses 4kB sub-sectors rather than 64kB sectors.
+ */
+#if !defined(MX25_USE_SUB_SECTORS) || defined(__DOXYGEN__)
+#define MX25_USE_SUB_SECTORS FALSE
+#endif
+
+/**
+ * @brief Size of the compare buffer.
+ * @details This buffer is allocated in the stack frame of the function
+ * @p flashVerifyErase() and its size must be a power of two.
+ * Larger buffers lead to better verify performance but increase
+ * stack usage for that function.
+ */
+#if !defined(MX25_COMPARE_BUFFER_SIZE) || defined(__DOXYGEN__)
+#define MX25_COMPARE_BUFFER_SIZE 32
+#endif
+
+/**
+ * @brief Number of dummy cycles for fast read (1..15).
+ * @details This is the number of dummy cycles to be used for fast read
+ * operations.
+ */
+#if !defined(MX25_READ_DUMMY_CYCLES) || defined(__DOXYGEN__)
+#define MX25_READ_DUMMY_CYCLES 6
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if (MX25_COMPARE_BUFFER_SIZE & (MX25_COMPARE_BUFFER_SIZE - 1)) != 0
+#error "invalid MX25_COMPARE_BUFFER_SIZE value"
+#endif
+
+#if (MX25_READ_DUMMY_CYCLES < 6) || (MX25_READ_DUMMY_CYCLES > 20) || \
+ ((MX25_READ_DUMMY_CYCLES & 1) != 0)
+#error "invalid MX25_READ_DUMMY_CYCLES value (6, 8, 10, 12, 14, 16, 18, 20)"
+#endif
+
+#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_SPI) && \
+ (MX25_BUS_MODE != MX25_BUS_MODE_SPI)
+#error "only MX25_BUS_MODE_SPI is allowed when using SPI driver"
+#endif
+
+#if (MX25_BUS_MODE == MX25_BUS_MODE_OPI_DTR) || defined(__DOXYGEN__)
+/**
+ * @brief WSPI settings for command only.
+ */
+#define SNOR_WSPI_CFG_CMD MX25_CFG_C16_8DTR
+
+/**
+ * @brief WSPI settings for command and address.
+ */
+#define SNOR_WSPI_CFG_CMD_ADDR MX25_CFG_C16_A32_8DTR
+
+/**
+ * @brief WSPI settings for command and data.
+ */
+#define SNOR_WSPI_CFG_CMD_DATA MX25_CFG_C16_DATA_8DTR
+
+/**
+ * @brief WSPI settings for command, address and data.
+ */
+#define SNOR_WSPI_CFG_CMD_ADDR_DATA MX25_CFG_C16_A32_DATA_8DTR
+
+#elif MX25_BUS_MODE == MX25_BUS_MODE_OPI_STR
+#define SNOR_WSPI_CFG_CMD MX25_CFG_C16_8STR
+#define SNOR_WSPI_CFG_CMD_ADDR MX25_CFG_C16_A32_8STR
+#define SNOR_WSPI_CFG_CMD_DATA MX25_CFG_C16_DATA_8STR
+#define SNOR_WSPI_CFG_CMD_ADDR_DATA MX25_CFG_C16_A32_DATA_8STR
+
+#elif MX25_BUS_MODE == MX25_BUS_MODE_SPI
+#define SNOR_WSPI_CFG_CMD MX25_CFG_C8_SPI
+#define SNOR_WSPI_CFG_CMD_ADDR MX25_CFG_C8_A32_SPI
+#define SNOR_WSPI_CFG_CMD_DATA MX25_CFG_C8_DATA_SPI
+#define SNOR_WSPI_CFG_CMD_ADDR_DATA MX25_CFG_C8_A32_DATA_SPI
+
+#else
+#error "invalid MX25_BUS_MODE setting"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern flash_descriptor_t snor_descriptor;
+#endif
+
+#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) && (WSPI_SUPPORTS_MEMMAP == TRUE)
+extern const wspi_command_t snor_memmap_read;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void snor_device_init(SNORDriver *devp);
+ flash_error_t snor_device_read(SNORDriver *devp, flash_offset_t offset,
+ size_t n, uint8_t *rp);
+ flash_error_t snor_device_program(SNORDriver *devp, flash_offset_t offset,
+ size_t n, const uint8_t *pp);
+ flash_error_t snor_device_start_erase_all(SNORDriver *devp);
+ flash_error_t snor_device_start_erase_sector(SNORDriver *devp,
+ flash_sector_t sector);
+ flash_error_t snor_device_verify_erase(SNORDriver *devp,
+ flash_sector_t sector);
+ flash_error_t snor_device_query_erase(SNORDriver *devp, uint32_t *msec);
+ flash_error_t snor_device_read_sfdp(SNORDriver *devp, flash_offset_t offset,
+ size_t n, uint8_t *rp);
+#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) && \
+ (SNOR_DEVICE_SUPPORTS_XIP == TRUE)
+ void snor_activate_xip(SNORDriver *devp);
+ void snor_reset_xip(SNORDriver *devp);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_FLASH_DEVICE_H */
+
+/** @} */
+
diff --git a/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/devices/macronix_mx25/hal_flash_device.mk b/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/devices/macronix_mx25/hal_flash_device.mk
new file mode 100644
index 0000000..4fb2168
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/devices/macronix_mx25/hal_flash_device.mk
@@ -0,0 +1,11 @@
+# List of all the Micron N25Q device files.
+SERNORSRC := $(CHIBIOS)/os/hal/lib/complex/serial_nor/hal_serial_nor.c \
+ $(CHIBIOS)/os/hal/lib/complex/serial_nor/devices/macronix_mx25/hal_flash_device.c
+
+# Required include directories
+SERNORINC := $(CHIBIOS)/os/hal/lib/complex/serial_nor \
+ $(CHIBIOS)/os/hal/lib/complex/serial_nor/devices/macronix_mx25
+
+# Shared variables
+ALLCSRC += $(SERNORSRC)
+ALLINC += $(SERNORINC)
diff --git a/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/devices/micron_n25q/hal_flash_device.c b/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/devices/micron_n25q/hal_flash_device.c
new file mode 100644
index 0000000..1b5d81f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/devices/micron_n25q/hal_flash_device.c
@@ -0,0 +1,586 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_flash_device.c
+ * @brief Micron N25Q serial flash driver code.
+ *
+ * @addtogroup MICRON_N25Q
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+#include "hal_serial_nor.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define PAGE_SIZE 256U
+#define PAGE_MASK (PAGE_SIZE - 1U)
+
+#if N25Q_USE_SUB_SECTORS == TRUE
+#define SECTOR_SIZE 0x00001000U
+#define CMD_SECTOR_ERASE N25Q_CMD_SUBSECTOR_ERASE
+#else
+#define SECTOR_SIZE 0x00010000U
+#define CMD_SECTOR_ERASE N25Q_CMD_SECTOR_ERASE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief N25Q128 descriptor.
+ */
+flash_descriptor_t snor_descriptor = {
+ .attributes = FLASH_ATTR_ERASED_IS_ONE | FLASH_ATTR_REWRITABLE |
+ FLASH_ATTR_SUSPEND_ERASE_CAPABLE,
+ .page_size = 256U,
+ .sectors_count = 0U, /* It is overwritten.*/
+ .sectors = NULL,
+ .sectors_size = SECTOR_SIZE,
+ .address = 0U,
+ .size = 0U /* It is overwritten.*/
+
+};
+
+#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) || defined(__DOXYGEN__)
+#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Fast read command for memory mapped mode.
+ */
+const wspi_command_t snor_memmap_read = {
+ .cmd = N25Q_CMD_FAST_READ,
+ .addr = 0,
+ .dummy = N25Q_READ_DUMMY_CYCLES - 2,
+ .cfg = WSPI_CFG_ADDR_SIZE_24 |
+#if N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI1L
+ WSPI_CFG_CMD_MODE_ONE_LINE |
+ WSPI_CFG_ADDR_MODE_ONE_LINE |
+ WSPI_CFG_DATA_MODE_ONE_LINE |
+#elif N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI2L
+ WSPI_CFG_CMD_MODE_TWO_LINES |
+ WSPI_CFG_ADDR_MODE_TWO_LINES |
+ WSPI_CFG_DATA_MODE_TWO_LINES |
+#else
+ WSPI_CFG_CMD_MODE_FOUR_LINES |
+ WSPI_CFG_ADDR_MODE_FOUR_LINES |
+ WSPI_CFG_DATA_MODE_FOUR_LINES |
+#endif
+ WSPI_CFG_ALT_MODE_FOUR_LINES | /* Always 4 lines, note.*/
+ WSPI_CFG_ALT_SIZE_8 |
+ WSPI_CFG_SIOO
+};
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
+/* Initial N25Q_CMD_READ_ID command.*/
+static const wspi_command_t n25q_cmd_read_id = {
+ .cmd = N25Q_CMD_READ_ID,
+ .cfg = 0U |
+#if N25Q_SWITCH_WIDTH == TRUE
+ WSPI_CFG_CMD_MODE_ONE_LINE |
+ WSPI_CFG_DATA_MODE_ONE_LINE,
+#else
+#if N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI1L
+ WSPI_CFG_CMD_MODE_ONE_LINE |
+ WSPI_CFG_DATA_MODE_ONE_LINE,
+#elif N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI2L
+ WSPI_CFG_CMD_MODE_TWO_LINES |
+ WSPI_CFG_DATA_MODE_TWO_LINES,
+#elif N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI4L
+ WSPI_CFG_CMD_MODE_FOUR_LINES |
+ WSPI_CFG_DATA_MODE_FOUR_LINES,
+#else
+ WSPI_CFG_CMD_MODE_EIGHT_LINES |
+ WSPI_CFG_DATA_MODE_EIGHT_LINES,
+#endif
+#endif
+ .addr = 0,
+ .alt = 0,
+ .dummy = 0
+};
+
+/* Initial N25Q_CMD_WRITE_ENHANCED_V_CONF_REGISTER command.*/
+static const wspi_command_t n25q_cmd_write_evconf = {
+ .cmd = N25Q_CMD_WRITE_ENHANCED_V_CONF_REGISTER,
+ .cfg = 0U |
+#if N25Q_SWITCH_WIDTH == TRUE
+ WSPI_CFG_CMD_MODE_ONE_LINE |
+ WSPI_CFG_DATA_MODE_ONE_LINE,
+#else
+#if N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI1L
+ WSPI_CFG_CMD_MODE_ONE_LINE |
+ WSPI_CFG_DATA_MODE_ONE_LINE,
+#elif N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI2L
+ WSPI_CFG_CMD_MODE_TWO_LINES |
+ WSPI_CFG_DATA_MODE_TWO_LINES,
+#elif N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI4L
+ WSPI_CFG_CMD_MODE_FOUR_LINES |
+ WSPI_CFG_DATA_MODE_FOUR_LINES,
+#else
+ WSPI_CFG_CMD_MODE_EIGHT_LINES |
+ WSPI_CFG_DATA_MODE_EIGHT_LINES,
+#endif
+#endif
+ .addr = 0,
+ .alt = 0,
+ .dummy = 0
+};
+
+/* Initial N25Q_CMD_WRITE_ENABLE command.*/
+static const wspi_command_t n25q_cmd_write_enable = {
+ .cmd = N25Q_CMD_WRITE_ENABLE,
+ .cfg = 0U |
+#if N25Q_SWITCH_WIDTH == TRUE
+ WSPI_CFG_CMD_MODE_ONE_LINE,
+#else
+#if N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI1L
+ WSPI_CFG_CMD_MODE_ONE_LINE,
+#elif N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI2L
+ WSPI_CFG_CMD_MODE_TWO_LINES,
+#elif N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI4L
+ WSPI_CFG_CMD_MODE_FOUR_LINES,
+#else
+ WSPI_CFG_CMD_MODE_EIGHT_LINES,
+#endif
+#endif
+ .addr = 0,
+ .alt = 0,
+ .dummy = 0
+};
+
+/* Bus width initialization.*/
+#if N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI1L
+static const uint8_t n25q_evconf_value[1] = {0xCF};
+#elif N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI2L
+static const uint8_t n25q_evconf_value[1] = {0x8F};
+#else
+static const uint8_t n25q_evconf_value[1] = {0x4F};
+#endif
+#endif /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static bool n25q_find_id(const uint8_t *set, size_t size, uint8_t element) {
+ size_t i;
+
+ for (i = 0; i < size; i++) {
+ if (set[i] == element) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static flash_error_t n25q_poll_status(SNORDriver *devp) {
+ uint8_t sts;
+
+ do {
+#if N25Q_NICE_WAITING == TRUE
+ osalThreadSleepMilliseconds(1);
+#endif
+ /* Read status command.*/
+ bus_cmd_receive(devp->config->busp, N25Q_CMD_READ_FLAG_STATUS_REGISTER,
+ 1, &sts);
+ } while ((sts & N25Q_FLAGS_PROGRAM_ERASE) == 0U);
+
+ /* Checking for errors.*/
+ if ((sts & N25Q_FLAGS_ALL_ERRORS) != 0U) {
+ /* Clearing status register.*/
+ bus_cmd(devp->config->busp, N25Q_CMD_CLEAR_FLAG_STATUS_REGISTER);
+
+ /* Program operation failed.*/
+ return FLASH_ERROR_PROGRAM;
+ }
+
+ return FLASH_NO_ERROR;
+}
+
+#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) || defined(__DOXYGEN__)
+static void n25q_reset_memory(SNORDriver *devp) {
+
+ /* 1x N25Q_CMD_RESET_ENABLE command.*/
+ static const wspi_command_t cmd_reset_enable_1 = {
+ .cmd = N25Q_CMD_RESET_ENABLE,
+ .cfg = WSPI_CFG_CMD_MODE_ONE_LINE,
+ .addr = 0,
+ .alt = 0,
+ .dummy = 0
+ };
+
+ /* 1x N25Q_CMD_RESET_MEMORY command.*/
+ static const wspi_command_t cmd_reset_memory_1 = {
+ .cmd = N25Q_CMD_RESET_MEMORY,
+ .cfg = WSPI_CFG_CMD_MODE_ONE_LINE,
+ .addr = 0,
+ .alt = 0,
+ .dummy = 0
+ };
+
+ /* If the device is in one bit mode then the following commands are
+ rejected because shorter than 8 bits. If the device is in multiple
+ bits mode then the commands are accepted and the device is reset to
+ one bit mode.*/
+#if N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI4L
+ /* 4x N25Q_CMD_RESET_ENABLE command.*/
+ static const wspi_command_t cmd_reset_enable_4 = {
+ .cmd = N25Q_CMD_RESET_ENABLE,
+ .cfg = WSPI_CFG_CMD_MODE_FOUR_LINES,
+ .addr = 0,
+ .alt = 0,
+ .dummy = 0
+ };
+
+ /* 4x N25Q_CMD_RESET_MEMORY command.*/
+ static const wspi_command_t cmd_reset_memory_4 = {
+ .cmd = N25Q_CMD_RESET_MEMORY,
+ .cfg = WSPI_CFG_CMD_MODE_FOUR_LINES,
+ .addr = 0,
+ .alt = 0,
+ .dummy = 0
+ };
+
+ wspiCommand(devp->config->busp, &cmd_reset_enable_4);
+ wspiCommand(devp->config->busp, &cmd_reset_memory_4);
+#else
+ /* 2x N25Q_CMD_RESET_ENABLE command.*/
+ static const wspi_command_t cmd_reset_enable_2 = {
+ .cfg = WSPI_CFG_CMD(N25Q_CMD_RESET_ENABLE) |
+ WSPI_CFG_CMD_MODE_TWO_LINES,
+ .addr = 0,
+ .alt = 0,
+ .dummy = 0
+ };
+
+ /* 2x N25Q_CMD_RESET_MEMORY command.*/
+ static const wspi_command_t cmd_reset_memory_2 = {
+ .cfg = WSPI_CFG_CMD(N25Q_CMD_RESET_MEMORY) |
+ WSPI_CFG_CMD_MODE_TWO_LINES,
+ .addr = 0,
+ .alt = 0,
+ .dummy = 0
+ };
+
+ wspiCommand(devp->config->busp, &cmd_reset_enable_2);
+ wspiCommand(devp->config->busp, &cmd_reset_memory_2);
+#endif
+
+ /* Now the device should be in one bit mode for sure and we perform a
+ device reset.*/
+ wspiCommand(devp->config->busp, &cmd_reset_enable_1);
+ wspiCommand(devp->config->busp, &cmd_reset_memory_1);
+}
+#endif /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
+
+static const uint8_t n25q_manufacturer_ids[] = N25Q_SUPPORTED_MANUFACTURE_IDS;
+static const uint8_t n25q_memory_type_ids[] = N25Q_SUPPORTED_MEMORY_TYPE_IDS;
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+void snor_device_init(SNORDriver *devp) {
+
+#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_SPI
+ /* Reading device ID.*/
+ bus_cmd_receive(devp->config->busp, N25Q_CMD_READ_ID,
+ sizeof devp->device_id, devp->device_id);
+
+#else /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
+ /* Attempting a reset of the XIP mode, it could be in an unexpected state
+ because a CPU reset does not reset the memory too.*/
+ snor_reset_xip(devp);
+
+ /* Attempting a reset of the device, it could be in an unexpected state
+ because a CPU reset does not reset the memory too.*/
+ n25q_reset_memory(devp);
+
+ /* Reading device ID and unique ID.*/
+ wspiReceive(devp->config->busp, &n25q_cmd_read_id,
+ sizeof devp->device_id, devp->device_id);
+#endif /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
+
+ /* Checking if the device is white listed.*/
+ osalDbgAssert(n25q_find_id(n25q_manufacturer_ids,
+ sizeof n25q_manufacturer_ids,
+ devp->device_id[0]),
+ "invalid manufacturer id");
+ osalDbgAssert(n25q_find_id(n25q_memory_type_ids,
+ sizeof n25q_memory_type_ids,
+ devp->device_id[1]),
+ "invalid memory type id");
+
+#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) && (N25Q_SWITCH_WIDTH == TRUE)
+ /* Setting up final bus width.*/
+ wspiCommand(devp->config->busp, &n25q_cmd_write_enable);
+ wspiSend(devp->config->busp, &n25q_cmd_write_evconf, 1, n25q_evconf_value);
+
+ {
+ uint8_t id[3];
+
+ /* Reading ID again for confirmation.*/
+ bus_cmd_receive(devp->config->busp, N25Q_CMD_MULTIPLE_IO_READ_ID, 3, id);
+
+ /* Checking if the device is white listed.*/
+ osalDbgAssert(memcmp(id, devp->device_id, 3) == 0,
+ "id confirmation failed");
+ }
+#endif
+
+ /* Setting up the device size.*/
+ snor_descriptor.sectors_count = (1U << (size_t)devp->device_id[2]) /
+ SECTOR_SIZE;
+ snor_descriptor.size = (size_t)snor_descriptor.sectors_count * SECTOR_SIZE;
+
+#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
+ {
+ static const uint8_t flash_conf[1] = {
+ (N25Q_READ_DUMMY_CYCLES << 4U) | 0x0FU
+ };
+
+ /* Setting up the dummy cycles to be used for fast read operations.*/
+ bus_cmd(devp->config->busp, N25Q_CMD_WRITE_ENABLE);
+ bus_cmd_send(devp->config->busp, N25Q_CMD_WRITE_V_CONF_REGISTER,
+ 1, flash_conf);
+ }
+#endif
+}
+
+flash_error_t snor_device_read(SNORDriver *devp, flash_offset_t offset,
+ size_t n, uint8_t *rp) {
+
+#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
+ /* Fast read command in WSPI mode.*/
+ bus_cmd_addr_dummy_receive(devp->config->busp, N25Q_CMD_FAST_READ,
+ offset, N25Q_READ_DUMMY_CYCLES, n, rp);
+#else
+ /* Normal read command in SPI mode.*/
+ bus_cmd_addr_receive(devp->config->busp, N25Q_CMD_READ,
+ offset, n, rp);
+#endif
+
+ return FLASH_NO_ERROR;
+}
+
+flash_error_t snor_device_program(SNORDriver *devp, flash_offset_t offset,
+ size_t n, const uint8_t *pp) {
+
+ /* Data is programmed page by page.*/
+ while (n > 0U) {
+ flash_error_t err;
+
+ /* Data size that can be written in a single program page operation.*/
+ size_t chunk = (size_t)(((offset | PAGE_MASK) + 1U) - offset);
+ if (chunk > n) {
+ chunk = n;
+ }
+
+ /* Enabling write operation.*/
+ bus_cmd(devp->config->busp, N25Q_CMD_WRITE_ENABLE);
+
+ /* Page program command.*/
+ bus_cmd_addr_send(devp->config->busp, N25Q_CMD_PAGE_PROGRAM, offset,
+ chunk, pp);
+
+ /* Wait for status and check errors.*/
+ err = n25q_poll_status(devp);
+ if (err != FLASH_NO_ERROR) {
+
+ return err;
+ }
+
+ /* Next page.*/
+ offset += chunk;
+ pp += chunk;
+ n -= chunk;
+ }
+
+ return FLASH_NO_ERROR;
+}
+
+flash_error_t snor_device_start_erase_all(SNORDriver *devp) {
+
+ /* Enabling write operation.*/
+ bus_cmd(devp->config->busp, N25Q_CMD_WRITE_ENABLE);
+
+ /* Bulk erase command.*/
+ bus_cmd(devp->config->busp, N25Q_CMD_BULK_ERASE);
+
+ return FLASH_NO_ERROR;
+}
+
+flash_error_t snor_device_start_erase_sector(SNORDriver *devp,
+ flash_sector_t sector) {
+ flash_offset_t offset = (flash_offset_t)(sector * SECTOR_SIZE);
+
+ /* Enabling write operation.*/
+ bus_cmd(devp->config->busp, N25Q_CMD_WRITE_ENABLE);
+
+ /* Sector erase command.*/
+ bus_cmd_addr(devp->config->busp, N25Q_CMD_SECTOR_ERASE, offset);
+
+ return FLASH_NO_ERROR;
+}
+
+flash_error_t snor_device_verify_erase(SNORDriver *devp,
+ flash_sector_t sector) {
+ uint8_t cmpbuf[N25Q_COMPARE_BUFFER_SIZE];
+ flash_offset_t offset;
+ size_t n;
+
+ /* Read command.*/
+ offset = (flash_offset_t)(sector * SECTOR_SIZE);
+ n = SECTOR_SIZE;
+ while (n > 0U) {
+ uint8_t *p;
+
+#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
+ bus_cmd_addr_dummy_receive(devp->config->busp, N25Q_CMD_FAST_READ,
+ offset, N25Q_READ_DUMMY_CYCLES,
+ sizeof cmpbuf, cmpbuf);
+#else
+ /* Normal read command in SPI mode.*/
+ bus_cmd_addr_receive(devp->config->busp, N25Q_CMD_READ,
+ offset, sizeof cmpbuf, cmpbuf);
+#endif
+
+ /* Checking for erased state of current buffer.*/
+ for (p = cmpbuf; p < &cmpbuf[N25Q_COMPARE_BUFFER_SIZE]; p++) {
+ if (*p != 0xFFU) {
+ /* Ready state again.*/
+ devp->state = FLASH_READY;
+
+ return FLASH_ERROR_VERIFY;
+ }
+ }
+
+ offset += sizeof cmpbuf;
+ n -= sizeof cmpbuf;
+ }
+
+ return FLASH_NO_ERROR;
+}
+
+flash_error_t snor_device_query_erase(SNORDriver *devp, uint32_t *msec) {
+ uint8_t sts;
+
+ /* Read status command.*/
+ bus_cmd_receive(devp->config->busp, N25Q_CMD_READ_FLAG_STATUS_REGISTER,
+ 1, &sts);
+
+ /* If the P/E bit is zero (busy) or the flash in a suspended state then
+ report that the operation is still in progress.*/
+ if (((sts & N25Q_FLAGS_PROGRAM_ERASE) == 0U) ||
+ ((sts & N25Q_FLAGS_ERASE_SUSPEND) != 0U)) {
+
+ /* Recommended time before polling again, this is a simplified
+ implementation.*/
+ if (msec != NULL) {
+ *msec = 1U;
+ }
+
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* Checking for errors.*/
+ if ((sts & N25Q_FLAGS_ALL_ERRORS) != 0U) {
+
+ /* Clearing status register.*/
+ bus_cmd(devp->config->busp, N25Q_CMD_CLEAR_FLAG_STATUS_REGISTER);
+
+ /* Erase operation failed.*/
+ return FLASH_ERROR_ERASE;
+ }
+
+ return FLASH_NO_ERROR;
+}
+
+flash_error_t snor_device_read_sfdp(SNORDriver *devp, flash_offset_t offset,
+ size_t n, uint8_t *rp) {
+
+ (void)devp;
+ (void)rp;
+ (void)offset;
+ (void)n;
+
+ return FLASH_NO_ERROR;
+}
+
+#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) || defined(__DOXYGEN__)
+void snor_activate_xip(SNORDriver *devp) {
+ static const uint8_t flash_status_xip[1] = {
+ (N25Q_READ_DUMMY_CYCLES << 4U) | 0x07U
+ };
+
+ /* Activating XIP mode in the device.*/
+ bus_cmd(devp->config->busp, N25Q_CMD_WRITE_ENABLE);
+ bus_cmd_send(devp->config->busp, N25Q_CMD_WRITE_V_CONF_REGISTER,
+ 1, flash_status_xip);
+}
+
+void snor_reset_xip(SNORDriver *devp) {
+ static const uint8_t flash_conf[1] = {
+ (N25Q_READ_DUMMY_CYCLES << 4U) | 0x0FU
+ };
+ wspi_command_t cmd;
+ uint8_t buf[1];
+
+ /* Resetting XIP mode by reading one byte without XIP confirmation bit.*/
+ cmd.cmd = 0U;
+ cmd.alt = 0xFFU;
+ cmd.addr = 0U;
+ cmd.dummy = N25Q_READ_DUMMY_CYCLES - 2U;
+ cmd.cfg = WSPI_CFG_CMD_MODE_NONE |
+ WSPI_CFG_ADDR_SIZE_24 |
+#if N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI1L
+ WSPI_CFG_ADDR_MODE_ONE_LINE |
+ WSPI_CFG_DATA_MODE_ONE_LINE |
+#elif N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI2L
+ WSPI_CFG_ADDR_MODE_TWO_LINES |
+ WSPI_CFG_DATA_MODE_TWO_LINES |
+#elif N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI4L
+ WSPI_CFG_ADDR_MODE_FOUR_LINES |
+ WSPI_CFG_DATA_MODE_FOUR_LINES |
+#else
+ WSPI_CFG_ADDR_MODE_EIGHT_LINES |
+ WSPI_CFG_DATA_MODE_EIGHT_LINES |
+#endif
+ WSPI_CFG_ALT_MODE_FOUR_LINES | /* Always 4 lines, note.*/
+ WSPI_CFG_ALT_SIZE_8;
+ wspiReceive(devp->config->busp, &cmd, 1, buf);
+
+ /* Enabling write operation.*/
+ bus_cmd(devp->config->busp, N25Q_CMD_WRITE_ENABLE);
+
+ /* Rewriting volatile configuration register.*/
+ bus_cmd_send(devp->config->busp, N25Q_CMD_WRITE_V_CONF_REGISTER,
+ 1, flash_conf);
+}
+#endif /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/devices/micron_n25q/hal_flash_device.h b/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/devices/micron_n25q/hal_flash_device.h
new file mode 100644
index 0000000..14d00c7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/devices/micron_n25q/hal_flash_device.h
@@ -0,0 +1,337 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_flash_device.h
+ * @brief Micron N25Q serial flash driver header.
+ *
+ * @addtogroup MICRON_N25Q
+ * @{
+ */
+
+#ifndef HAL_FLASH_DEVICE_H
+#define HAL_FLASH_DEVICE_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Device capabilities
+ * @{
+ */
+#define SNOR_DEVICE_SUPPORTS_XIP TRUE
+/** @} */
+
+/**
+ * @name Device identification
+ * @{
+ */
+#define N25Q_SUPPORTED_MANUFACTURE_IDS {0x20}
+#define N25Q_SUPPORTED_MEMORY_TYPE_IDS {0xBA, 0xBB}
+/** @} */
+
+/**
+ * @name Command codes
+ * @{
+ */
+#define N25Q_CMD_RESET_ENABLE 0x66
+#define N25Q_CMD_RESET_MEMORY 0x99
+#define N25Q_CMD_READ_ID 0x9F
+#define N25Q_CMD_MULTIPLE_IO_READ_ID 0xAF
+#define N25Q_CMD_READ_DISCOVERY_PARAMETER 0x5A
+#define N25Q_CMD_READ 0x03
+#define N25Q_CMD_FAST_READ 0x0B
+#define N25Q_CMD_WRITE_ENABLE 0x06
+#define N25Q_CMD_WRITE_DISABLE 0x04
+#define N25Q_CMD_READ_STATUS_REGISTER 0x05
+#define N25Q_CMD_WRITE_STATUS_REGISTER 0x01
+#define N25Q_CMD_READ_LOCK_REGISTER 0xE8
+#define N25Q_CMD_WRITE_LOCK_REGISTER 0xE5
+#define N25Q_CMD_READ_FLAG_STATUS_REGISTER 0x70
+#define N25Q_CMD_CLEAR_FLAG_STATUS_REGISTER 0x50
+#define N25Q_CMD_READ_NV_CONFIGURATION_REGISTER 0xB5
+#define N25Q_CMD_WRITE_NV_CONFIGURATION_REGISTER 0xB1
+#define N25Q_CMD_READ_V_CONF_REGISTER 0x85
+#define N25Q_CMD_WRITE_V_CONF_REGISTER 0x81
+#define N25Q_CMD_READ_ENHANCED_V_CONF_REGISTER 0x65
+#define N25Q_CMD_WRITE_ENHANCED_V_CONF_REGISTER 0x61
+#define N25Q_CMD_PAGE_PROGRAM 0x02
+#define N25Q_CMD_SUBSECTOR_ERASE 0x20
+#define N25Q_CMD_SECTOR_ERASE 0xD8
+#define N25Q_CMD_BULK_ERASE 0xC7
+#define N25Q_CMD_PROGRAM_ERASE_RESUME 0x7A
+#define N25Q_CMD_PROGRAM_ERASE_SUSPEND 0x75
+#define N25Q_CMD_READ_OTP_ARRAY 0x4B
+#define N25Q_CMD_PROGRAM_OTP_ARRAY 0x42
+/** @} */
+
+/**
+ * @name Flags status register bits
+ * @{
+ */
+#define N25Q_FLAGS_PROGRAM_ERASE 0x80U
+#define N25Q_FLAGS_ERASE_SUSPEND 0x40U
+#define N25Q_FLAGS_ERASE_ERROR 0x20U
+#define N25Q_FLAGS_PROGRAM_ERROR 0x10U
+#define N25Q_FLAGS_VPP_ERROR 0x08U
+#define N25Q_FLAGS_PROGRAM_SUSPEND 0x04U
+#define N25Q_FLAGS_PROTECTION_ERROR 0x02U
+#define N25Q_FLAGS_RESERVED 0x01U
+#define N25Q_FLAGS_ALL_ERRORS (N25Q_FLAGS_ERASE_ERROR | \
+ N25Q_FLAGS_PROGRAM_ERROR | \
+ N25Q_FLAGS_VPP_ERROR | \
+ N25Q_FLAGS_PROTECTION_ERROR)
+/** @} */
+
+/**
+ * @name Bus interface modes.
+ * @{
+ */
+#define N25Q_BUS_MODE_WSPI1L 1U
+#define N25Q_BUS_MODE_WSPI2L 2U
+#define N25Q_BUS_MODE_WSPI4L 4U
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Switch WSPI bus width on initialization.
+ * @details A bus width initialization is performed by writing the
+ * Enhanced Volatile Configuration Register. If the flash
+ * device is configured using the Non Volatile Configuration
+ * Register then this option is not required.
+ * @note This option is only valid in WSPI bus mode.
+ */
+#if !defined(N25Q_SWITCH_WIDTH) || defined(__DOXYGEN__)
+#define N25Q_SWITCH_WIDTH TRUE
+#endif
+
+/**
+ * @brief Device bus mode to be used.
+ * #note if @p N25Q_SWITCH_WIDTH is @p FALSE then this is the bus mode
+ * that the device is expected to be using.
+ * #note if @p N25Q_SWITCH_WIDTH is @p TRUE then this is the bus mode
+ * that the device will be switched in.
+ * @note This option is only valid in WSPI bus mode.
+ */
+#if !defined(N25Q_BUS_MODE) || defined(__DOXYGEN__)
+#define N25Q_BUS_MODE N25Q_BUS_MODE_WSPI4L
+#endif
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the flash waiting
+ * routines releasing some extra CPU time for threads with lower
+ * priority, this may slow down the driver a bit however.
+ */
+#if !defined(N25Q_NICE_WAITING) || defined(__DOXYGEN__)
+#define N25Q_NICE_WAITING TRUE
+#endif
+
+/**
+ * @brief Uses 4kB sub-sectors rather than 64kB sectors.
+ */
+#if !defined(N25Q_USE_SUB_SECTORS) || defined(__DOXYGEN__)
+#define N25Q_USE_SUB_SECTORS FALSE
+#endif
+
+/**
+ * @brief Size of the compare buffer.
+ * @details This buffer is allocated in the stack frame of the function
+ * @p flashVerifyErase() and its size must be a power of two.
+ * Larger buffers lead to better verify performance but increase
+ * stack usage for that function.
+ */
+#if !defined(N25Q_COMPARE_BUFFER_SIZE) || defined(__DOXYGEN__)
+#define N25Q_COMPARE_BUFFER_SIZE 32
+#endif
+
+/**
+ * @brief Number of dummy cycles for fast read (1..15).
+ * @details This is the number of dummy cycles to be used for fast read
+ * operations.
+ */
+#if !defined(N25Q_READ_DUMMY_CYCLES) || defined(__DOXYGEN__)
+#define N25Q_READ_DUMMY_CYCLES 8
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if (N25Q_COMPARE_BUFFER_SIZE & (N25Q_COMPARE_BUFFER_SIZE - 1)) != 0
+#error "invalid N25Q_COMPARE_BUFFER_SIZE value"
+#endif
+
+#if (N25Q_READ_DUMMY_CYCLES < 1) || (N25Q_READ_DUMMY_CYCLES > 15)
+#error "invalid N25Q_READ_DUMMY_CYCLES value (1..15)"
+#endif
+
+#if (N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI4L) || defined(__DOXYGEN__)
+/**
+ * @brief WSPI settings for command only.
+ */
+#define SNOR_WSPI_CFG_CMD (WSPI_CFG_CMD_MODE_FOUR_LINES | \
+ WSPI_CFG_ADDR_MODE_NONE | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_NONE | \
+ WSPI_CFG_CMD_SIZE_8 | \
+ WSPI_CFG_ADDR_SIZE_24)
+
+/**
+ * @brief WSPI settings for command and address.
+ */
+#define SNOR_WSPI_CFG_CMD_ADDR (WSPI_CFG_CMD_MODE_FOUR_LINES | \
+ WSPI_CFG_ADDR_MODE_FOUR_LINES | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_NONE | \
+ WSPI_CFG_CMD_SIZE_8 | \
+ WSPI_CFG_ADDR_SIZE_24)
+
+/**
+ * @brief WSPI settings for command and data.
+ */
+#define SNOR_WSPI_CFG_CMD_DATA (WSPI_CFG_CMD_MODE_FOUR_LINES | \
+ WSPI_CFG_ADDR_MODE_NONE | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_FOUR_LINES | \
+ WSPI_CFG_CMD_SIZE_8 | \
+ WSPI_CFG_ADDR_SIZE_24)
+
+/**
+ * @brief WSPI settings for command, address and data.
+ */
+#define SNOR_WSPI_CFG_CMD_ADDR_DATA (WSPI_CFG_CMD_MODE_FOUR_LINES | \
+ WSPI_CFG_ADDR_MODE_FOUR_LINES | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_FOUR_LINES | \
+ WSPI_CFG_CMD_SIZE_8 | \
+ WSPI_CFG_ADDR_SIZE_24)
+
+#elif N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI2L
+#define SNOR_WSPI_CFG_CMD (WSPI_CFG_CMD_MODE_TWO_LINES | \
+ WSPI_CFG_ADDR_MODE_NONE | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_NONE | \
+ WSPI_CFG_CMD_SIZE_8 | \
+ WSPI_CFG_ADDR_SIZE_24)
+
+#define SNOR_WSPI_CFG_CMD_ADDR (WSPI_CFG_CMD_MODE_TWO_LINES | \
+ WSPI_CFG_ADDR_MODE_TWO_LINES | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_NONE | \
+ WSPI_CFG_CMD_SIZE_8 | \
+ WSPI_CFG_ADDR_SIZE_24)
+
+#define SNOR_WSPI_CFG_CMD_DATA (WSPI_CFG_CMD_MODE_TWO_LINES | \
+ WSPI_CFG_ADDR_MODE_NONE | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_TWO_LINES | \
+ WSPI_CFG_CMD_SIZE_8 | \
+ WSPI_CFG_ADDR_SIZE_24)
+
+#define SNOR_WSPI_CFG_CMD_ADDR_DATA (WSPI_CFG_CMD_MODE_ONE_LINE | \
+ WSPI_CFG_ADDR_MODE_ONE_LINE | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_ONE_LINE | \
+ WSPI_CFG_CMD_SIZE_8 | \
+ WSPI_CFG_ADDR_SIZE_24)
+
+#elif N25Q_BUS_MODE == N25Q_BUS_MODE_WSPI1L
+#define SNOR_WSPI_CFG_CMD (WSPI_CFG_CMD_MODE_ONE_LINE | \
+ WSPI_CFG_ADDR_MODE_NONE | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_NONE | \
+ WSPI_CFG_CMD_SIZE_8 | \
+ WSPI_CFG_ADDR_SIZE_24)
+
+#define SNOR_WSPI_CFG_CMD_ADDR (WSPI_CFG_CMD_MODE_ONE_LINE | \
+ WSPI_CFG_ADDR_MODE_ONE_LINE | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_NONE | \
+ WSPI_CFG_CMD_SIZE_8 | \
+ WSPI_CFG_ADDR_SIZE_24)
+
+#define SNOR_WSPI_CFG_CMD_DATA (WSPI_CFG_CMD_MODE_ONE_LINE | \
+ WSPI_CFG_ADDR_MODE_NONE | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_ONE_LINE | \
+ WSPI_CFG_CMD_SIZE_8 | \
+ WSPI_CFG_ADDR_SIZE_24)
+
+#define SNOR_WSPI_CFG_CMD_ADDR_DATA (WSPI_CFG_CMD_MODE_ONE_LINE | \
+ WSPI_CFG_ADDR_MODE_ONE_LINE | \
+ WSPI_CFG_ALT_MODE_NONE | \
+ WSPI_CFG_DATA_MODE_ONE_LINE | \
+ WSPI_CFG_CMD_SIZE_8 | \
+ WSPI_CFG_ADDR_SIZE_24)
+
+#else
+#error "invalid N25Q_BUS_MODE setting"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern flash_descriptor_t snor_descriptor;
+#endif
+
+#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) && (WSPI_SUPPORTS_MEMMAP == TRUE)
+extern const wspi_command_t snor_memmap_read;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void snor_device_init(SNORDriver *devp);
+ flash_error_t snor_device_read(SNORDriver *devp, flash_offset_t offset,
+ size_t n, uint8_t *rp);
+ flash_error_t snor_device_program(SNORDriver *devp, flash_offset_t offset,
+ size_t n, const uint8_t *pp);
+ flash_error_t snor_device_start_erase_all(SNORDriver *devp);
+ flash_error_t snor_device_start_erase_sector(SNORDriver *devp,
+ flash_sector_t sector);
+ flash_error_t snor_device_verify_erase(SNORDriver *devp,
+ flash_sector_t sector);
+ flash_error_t snor_device_query_erase(SNORDriver *devp, uint32_t *msec);
+ flash_error_t snor_device_read_sfdp(SNORDriver *devp, flash_offset_t offset,
+ size_t n, uint8_t *rp);
+#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) && \
+ (SNOR_DEVICE_SUPPORTS_XIP == TRUE)
+ void snor_activate_xip(SNORDriver *devp);
+ void snor_reset_xip(SNORDriver *devp);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_FLASH_DEVICE_H */
+
+/** @} */
+
diff --git a/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/devices/micron_n25q/hal_flash_device.mk b/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/devices/micron_n25q/hal_flash_device.mk
new file mode 100644
index 0000000..43ddcef
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/devices/micron_n25q/hal_flash_device.mk
@@ -0,0 +1,11 @@
+# List of all the Micron N25Q device files.
+SNORSRC := $(CHIBIOS)/os/hal/lib/complex/serial_nor/hal_serial_nor.c \
+ $(CHIBIOS)/os/hal/lib/complex/serial_nor/devices/micron_n25q/hal_flash_device.c
+
+# Required include directories
+SNORINC := $(CHIBIOS)/os/hal/lib/complex/serial_nor \
+ $(CHIBIOS)/os/hal/lib/complex/serial_nor/devices/micron_n25q
+
+# Shared variables
+ALLCSRC += $(SNORSRC)
+ALLINC += $(SNORINC)
diff --git a/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/hal_serial_nor.c b/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/hal_serial_nor.c
new file mode 100644
index 0000000..82d9083
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/hal_serial_nor.c
@@ -0,0 +1,770 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_serial_nor.c
+ * @brief Serial NOR serial flash driver code.
+ *
+ * @addtogroup HAL_SERIAL_NOR
+ * @{
+ */
+
+#include "hal.h"
+#include "hal_serial_nor.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+static const flash_descriptor_t *snor_get_descriptor(void *instance);
+static flash_error_t snor_read(void *instance, flash_offset_t offset,
+ size_t n, uint8_t *rp);
+static flash_error_t snor_program(void *instance, flash_offset_t offset,
+ size_t n, const uint8_t *pp);
+static flash_error_t snor_start_erase_all(void *instance);
+static flash_error_t snor_start_erase_sector(void *instance,
+ flash_sector_t sector);
+static flash_error_t snor_verify_erase(void *instance,
+ flash_sector_t sector);
+static flash_error_t snor_query_erase(void *instance, uint32_t *msec);
+static flash_error_t snor_read_sfdp(void *instance, flash_offset_t offset,
+ size_t n, uint8_t *rp);
+
+/**
+ * @brief Virtual methods table.
+ */
+static const struct SNORDriverVMT snor_vmt = {
+ (size_t)0,
+ snor_get_descriptor, snor_read, snor_program,
+ snor_start_erase_all, snor_start_erase_sector,
+ snor_query_erase, snor_verify_erase,
+ snor_read_sfdp
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Returns a pointer to the device descriptor.
+ *
+ * @param[in] instance instance pointer
+ * @return Pointer to a static descriptor structure.
+ */
+static const flash_descriptor_t *snor_get_descriptor(void *instance) {
+ SNORDriver *devp = (SNORDriver *)instance;
+
+ osalDbgCheck(instance != NULL);
+ osalDbgAssert((devp->state != FLASH_UNINIT) && (devp->state != FLASH_STOP),
+ "invalid state");
+
+ return &snor_descriptor;
+}
+
+static flash_error_t snor_read(void *instance, flash_offset_t offset,
+ size_t n, uint8_t *rp) {
+ SNORDriver *devp = (SNORDriver *)instance;
+ flash_error_t err;
+
+ osalDbgCheck((instance != NULL) && (rp != NULL) && (n > 0U));
+ osalDbgCheck((size_t)offset + n <= (size_t)snor_descriptor.sectors_count *
+ (size_t)snor_descriptor.sectors_size);
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* Bus acquired.*/
+ bus_acquire(devp->config->busp, devp->config->buscfg);
+
+ /* FLASH_READY state while the operation is performed.*/
+ devp->state = FLASH_READ;
+
+ /* Actual read implementation.*/
+ err = snor_device_read(devp, offset, n, rp);
+
+ /* Ready state again.*/
+ devp->state = FLASH_READY;
+
+ /* Bus released.*/
+ bus_release(devp->config->busp);
+
+ return err;
+}
+
+static flash_error_t snor_program(void *instance, flash_offset_t offset,
+ size_t n, const uint8_t *pp) {
+ SNORDriver *devp = (SNORDriver *)instance;
+ flash_error_t err;
+
+ osalDbgCheck((instance != NULL) && (pp != NULL) && (n > 0U));
+ osalDbgCheck((size_t)offset + n <= (size_t)snor_descriptor.sectors_count *
+ (size_t)snor_descriptor.sectors_size);
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* Bus acquired.*/
+ bus_acquire(devp->config->busp, devp->config->buscfg);
+
+ /* FLASH_PGM state while the operation is performed.*/
+ devp->state = FLASH_PGM;
+
+ /* Actual program implementation.*/
+ err = snor_device_program(devp, offset, n, pp);
+
+ /* Ready state again.*/
+ devp->state = FLASH_READY;
+
+ /* Bus released.*/
+ bus_release(devp->config->busp);
+
+ return err;
+}
+
+static flash_error_t snor_start_erase_all(void *instance) {
+ SNORDriver *devp = (SNORDriver *)instance;
+ flash_error_t err;
+
+ osalDbgCheck(instance != NULL);
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* Bus acquired.*/
+ bus_acquire(devp->config->busp, devp->config->buscfg);
+
+ /* FLASH_ERASE state while the operation is performed.*/
+ devp->state = FLASH_ERASE;
+
+ /* Actual erase implementation.*/
+ err = snor_device_start_erase_all(devp);
+
+ /* Ready state again.*/
+ devp->state = FLASH_READY;
+
+ /* Bus released.*/
+ bus_release(devp->config->busp);
+
+ return err;
+}
+
+static flash_error_t snor_start_erase_sector(void *instance,
+ flash_sector_t sector) {
+ SNORDriver *devp = (SNORDriver *)instance;
+ flash_error_t err;
+
+ osalDbgCheck(instance != NULL);
+ osalDbgCheck(sector < snor_descriptor.sectors_count);
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* Bus acquired.*/
+ bus_acquire(devp->config->busp, devp->config->buscfg);
+
+ /* FLASH_ERASE state while the operation is performed.*/
+ devp->state = FLASH_ERASE;
+
+ /* Actual erase implementation.*/
+ err = snor_device_start_erase_sector(devp, sector);
+
+ /* Bus released.*/
+ bus_release(devp->config->busp);
+
+ return err;
+}
+
+static flash_error_t snor_verify_erase(void *instance,
+ flash_sector_t sector) {
+ SNORDriver *devp = (SNORDriver *)instance;
+ flash_error_t err;
+
+ osalDbgCheck(instance != NULL);
+ osalDbgCheck(sector < snor_descriptor.sectors_count);
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* Bus acquired.*/
+ bus_acquire(devp->config->busp, devp->config->buscfg);
+
+ /* FLASH_READY state while the operation is performed.*/
+ devp->state = FLASH_READ;
+
+ /* Actual verify erase implementation.*/
+ err = snor_device_verify_erase(devp, sector);
+
+ /* Ready state again.*/
+ devp->state = FLASH_READY;
+
+ /* Bus released.*/
+ bus_release(devp->config->busp);
+
+ return err;
+}
+
+static flash_error_t snor_query_erase(void *instance, uint32_t *msec) {
+ SNORDriver *devp = (SNORDriver *)instance;
+ flash_error_t err;
+
+ osalDbgCheck(instance != NULL);
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ /* If there is an erase in progress then the device must be checked.*/
+ if (devp->state == FLASH_ERASE) {
+
+ /* Bus acquired.*/
+ bus_acquire(devp->config->busp, devp->config->buscfg);
+
+ /* Actual query erase implementation.*/
+ err = snor_device_query_erase(devp, msec);
+
+ /* The device is ready to accept commands.*/
+ if (err == FLASH_NO_ERROR) {
+ devp->state = FLASH_READY;
+ }
+
+ /* Bus released.*/
+ bus_release(devp->config->busp);
+ }
+ else {
+ err = FLASH_NO_ERROR;
+ }
+
+ return err;
+}
+
+static flash_error_t snor_read_sfdp(void *instance, flash_offset_t offset,
+ size_t n, uint8_t *rp) {
+ SNORDriver *devp = (SNORDriver *)instance;
+ flash_error_t err;
+
+ osalDbgCheck((instance != NULL) && (rp != NULL) && (n > 0U));
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* Bus acquired.*/
+ bus_acquire(devp->config->busp, devp->config->buscfg);
+
+ /* Actual read SFDP implementation.*/
+ err = snor_device_read_sfdp(devp, offset, n, rp);
+
+ /* The device is ready to accept commands.*/
+ if (err == FLASH_NO_ERROR) {
+ devp->state = FLASH_READY;
+ }
+
+ /* Bus released.*/
+ bus_release(devp->config->busp);
+
+ return err;
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+#if ((SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) && \
+ (SNOR_SHARED_BUS == TRUE)) || defined(__DOXYGEN__)
+/**
+ * @brief Bus acquisition and lock.
+ *
+ * @param[in] busp pointer to the bus driver
+ * @param[in] config bus configuration
+ *
+ * @notapi
+ */
+void bus_acquire(BUSDriver *busp, const BUSConfig *config) {
+
+ (void)config;
+
+ wspiAcquireBus(busp);
+ if (busp->config != config) {
+ wspiStart(busp, config);
+ }
+}
+
+/**
+ * @brief Bus release.
+ *
+ * @param[in] busp pointer to the bus driver
+ *
+ * @notapi
+ */
+void bus_release(BUSDriver *busp) {
+
+ wspiReleaseBus(busp);
+}
+#endif
+
+#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_SPI) && \
+ (SNOR_SHARED_BUS == TRUE)
+void bus_acquire(BUSDriver *busp, const BUSConfig *config) {
+
+ spiAcquireBus(busp);
+ if (busp->config != config) {
+ spiStart(busp, config);
+ }
+}
+
+void bus_release(BUSDriver *busp) {
+
+ spiReleaseBus(busp);
+}
+#endif
+
+/**
+ * @brief Stops the underlying bus driver.
+ *
+ * @param[in] busp pointer to the bus driver
+ *
+ * @notapi
+ */
+void bus_stop(BUSDriver *busp) {
+
+#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
+ wspiStop(busp);
+#else
+ spiStop(busp);
+#endif
+}
+
+/**
+ * @brief Sends a naked command.
+ *
+ * @param[in] busp pointer to the bus driver
+ * @param[in] cmd instruction code
+ *
+ * @notapi
+ */
+void bus_cmd(BUSDriver *busp, uint32_t cmd) {
+#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
+ wspi_command_t mode;
+
+ mode.cmd = cmd;
+ mode.cfg = SNOR_WSPI_CFG_CMD;
+ mode.addr = 0U;
+ mode.alt = 0U;
+ mode.dummy = 0U;
+ wspiCommand(busp, &mode);
+#else
+ uint8_t buf[1];
+
+ spiSelect(busp);
+ buf[0] = cmd;
+ spiSend(busp, 1, buf);
+ spiUnselect(busp);
+#endif
+}
+
+/**
+ * @brief Sends a command followed by a data transmit phase.
+ *
+ * @param[in] busp pointer to the bus driver
+ * @param[in] cmd instruction code
+ * @param[in] n number of bytes to receive
+ * @param[in] p data buffer
+ *
+ * @notapi
+ */
+void bus_cmd_send(BUSDriver *busp, uint32_t cmd, size_t n, const uint8_t *p) {
+#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
+ wspi_command_t mode;
+
+ mode.cmd = cmd;
+ mode.cfg = SNOR_WSPI_CFG_CMD_DATA;
+ mode.addr = 0U;
+ mode.alt = 0U;
+ mode.dummy = 0U;
+ wspiSend(busp, &mode, n, p);
+#else
+ uint8_t buf[1];
+
+ spiSelect(busp);
+ buf[0] = cmd;
+ spiSend(busp, 1, buf);
+ spiSend(busp, n, p);
+ spiUnselect(busp);
+#endif
+}
+
+/**
+ * @brief Sends a command followed by a data receive phase.
+ *
+ * @param[in] busp pointer to the bus driver
+ * @param[in] cmd instruction code
+ * @param[in] n number of bytes to receive
+ * @param[out] p data buffer
+ *
+ * @notapi
+ */
+void bus_cmd_receive(BUSDriver *busp,
+ uint32_t cmd,
+ size_t n,
+ uint8_t *p) {
+#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
+ wspi_command_t mode;
+
+ mode.cmd = cmd;
+ mode.cfg = SNOR_WSPI_CFG_CMD_DATA;
+ mode.addr = 0U;
+ mode.alt = 0U;
+ mode.dummy = 0U;
+ wspiReceive(busp, &mode, n, p);
+#else
+ uint8_t buf[1];
+
+ spiSelect(busp);
+ buf[0] = cmd;
+ spiSend(busp, 1, buf);
+ spiReceive(busp, n, p);
+ spiUnselect(busp);
+#endif
+}
+
+/**
+ * @brief Sends a command followed by a flash address.
+ *
+ * @param[in] busp pointer to the bus driver
+ * @param[in] cmd instruction code
+ * @param[in] offset flash offset
+ *
+ * @notapi
+ */
+void bus_cmd_addr(BUSDriver *busp, uint32_t cmd, flash_offset_t offset) {
+#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
+ wspi_command_t mode;
+
+ mode.cmd = cmd;
+ mode.cfg = SNOR_WSPI_CFG_CMD_ADDR;
+ mode.addr = offset;
+ mode.alt = 0U;
+ mode.dummy = 0U;
+ wspiCommand(busp, &mode);
+#else
+ uint8_t buf[4];
+
+ spiSelect(busp);
+ buf[0] = cmd;
+ buf[1] = (uint8_t)(offset >> 16);
+ buf[2] = (uint8_t)(offset >> 8);
+ buf[3] = (uint8_t)(offset >> 0);
+ spiSend(busp, 4, buf);
+ spiUnselect(busp);
+#endif
+}
+
+/**
+ * @brief Sends a command followed by a flash address and a data transmit
+ * phase.
+ *
+ * @param[in] busp pointer to the bus driver
+ * @param[in] cmd instruction code
+ * @param[in] offset flash offset
+ * @param[in] n number of bytes to receive
+ * @param[in] p data buffer
+ *
+ * @notapi
+ */
+void bus_cmd_addr_send(BUSDriver *busp,
+ uint32_t cmd,
+ flash_offset_t offset,
+ size_t n,
+ const uint8_t *p) {
+#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
+ wspi_command_t mode;
+
+ mode.cmd = cmd;
+ mode.cfg = SNOR_WSPI_CFG_CMD_ADDR_DATA;
+ mode.addr = offset;
+ mode.alt = 0U;
+ mode.dummy = 0U;
+ wspiSend(busp, &mode, n, p);
+#else
+ uint8_t buf[4];
+
+ spiSelect(busp);
+ buf[0] = cmd;
+ buf[1] = (uint8_t)(offset >> 16);
+ buf[2] = (uint8_t)(offset >> 8);
+ buf[3] = (uint8_t)(offset >> 0);
+ spiSend(busp, 4, buf);
+ spiSend(busp, n, p);
+ spiUnselect(busp);
+#endif
+}
+
+/**
+ * @brief Sends a command followed by a flash address and a data receive
+ * phase.
+ *
+ * @param[in] busp pointer to the bus driver
+ * @param[in] cmd instruction code
+ * @param[in] offset flash offset
+ * @param[in] n number of bytes to receive
+ * @param[out] p data buffer
+ *
+ * @notapi
+ */
+void bus_cmd_addr_receive(BUSDriver *busp,
+ uint32_t cmd,
+ flash_offset_t offset,
+ size_t n,
+ uint8_t *p) {
+#if SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
+ wspi_command_t mode;
+
+ mode.cmd = cmd;
+ mode.cfg = SNOR_WSPI_CFG_CMD_ADDR_DATA;
+ mode.addr = offset;
+ mode.alt = 0U;
+ mode.dummy = 0U;
+ wspiReceive(busp, &mode, n, p);
+#else
+ uint8_t buf[4];
+
+ spiSelect(busp);
+ buf[0] = cmd;
+ buf[1] = (uint8_t)(offset >> 16);
+ buf[2] = (uint8_t)(offset >> 8);
+ buf[3] = (uint8_t)(offset >> 0);
+ spiSend(busp, 4, buf);
+ spiReceive(busp, n, p);
+ spiUnselect(busp);
+#endif
+}
+
+#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) || defined(__DOXYGEN__)
+/**
+ * @brief Sends a command followed by dummy cycles and a
+ * data receive phase.
+ *
+ * @param[in] busp pointer to the bus driver
+ * @param[in] cmd instruction code
+ * @param[in] dummy number of dummy cycles
+ * @param[in] n number of bytes to receive
+ * @param[out] p data buffer
+ *
+ * @notapi
+ */
+void bus_cmd_dummy_receive(BUSDriver *busp,
+ uint32_t cmd,
+ uint32_t dummy,
+ size_t n,
+ uint8_t *p) {
+ wspi_command_t mode;
+
+ mode.cmd = cmd;
+ mode.cfg = SNOR_WSPI_CFG_CMD_DATA;
+ mode.addr = 0U;
+ mode.alt = 0U;
+ mode.dummy = dummy;
+ wspiReceive(busp, &mode, n, p);
+}
+
+/**
+ * @brief Sends a command followed by a flash address, dummy cycles and a
+ * data receive phase.
+ *
+ * @param[in] busp pointer to the bus driver
+ * @param[in] cmd instruction code
+ * @param[in] offset flash offset
+ * @param[in] dummy number of dummy cycles
+ * @param[in] n number of bytes to receive
+ * @param[out] p data buffer
+ *
+ * @notapi
+ */
+void bus_cmd_addr_dummy_receive(BUSDriver *busp,
+ uint32_t cmd,
+ flash_offset_t offset,
+ uint32_t dummy,
+ size_t n,
+ uint8_t *p) {
+ wspi_command_t mode;
+
+ mode.cmd = cmd;
+ mode.cfg = SNOR_WSPI_CFG_CMD_ADDR_DATA;
+ mode.addr = offset;
+ mode.alt = 0U;
+ mode.dummy = dummy;
+ wspiReceive(busp, &mode, n, p);
+}
+#endif /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
+
+/**
+ * @brief Initializes an instance.
+ *
+ * @param[out] devp pointer to the @p SNORDriver object
+ *
+ * @init
+ */
+void snorObjectInit(SNORDriver *devp) {
+
+ osalDbgCheck(devp != NULL);
+
+ devp->vmt = &snor_vmt;
+ devp->state = FLASH_STOP;
+ devp->config = NULL;
+}
+
+/**
+ * @brief Configures and activates SNOR driver.
+ *
+ * @param[in] devp pointer to the @p SNORDriver object
+ * @param[in] config pointer to the configuration
+ *
+ * @api
+ */
+void snorStart(SNORDriver *devp, const SNORConfig *config) {
+
+ osalDbgCheck((devp != NULL) && (config != NULL));
+ osalDbgAssert(devp->state != FLASH_UNINIT, "invalid state");
+
+ devp->config = config;
+
+ if (devp->state == FLASH_STOP) {
+
+ /* Bus acquisition.*/
+ bus_acquire(devp->config->busp, devp->config->buscfg);
+
+ /* Device identification and initialization.*/
+ snor_device_init(devp);
+
+ /* Driver in ready state.*/
+ devp->state = FLASH_READY;
+
+ /* Bus release.*/
+ bus_release(devp->config->busp);
+ }
+}
+
+/**
+ * @brief Deactivates the SNOR driver.
+ *
+ * @param[in] devp pointer to the @p SNORDriver object
+ *
+ * @api
+ */
+void snorStop(SNORDriver *devp) {
+
+ osalDbgCheck(devp != NULL);
+ osalDbgAssert(devp->state != FLASH_UNINIT, "invalid state");
+
+ if (devp->state != FLASH_STOP) {
+
+ /* Bus acquisition.*/
+ bus_acquire(devp->config->busp, devp->config->buscfg);
+
+ /* Stopping bus device.*/
+ bus_stop(devp->config->busp);
+
+ /* Driver stopped.*/
+ devp->state = FLASH_STOP;
+
+ /* Bus release.*/
+ bus_release(devp->config->busp);
+
+ /* Deleting current configuration.*/
+ devp->config = NULL;
+ }
+}
+
+#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) || defined(__DOXYGEN__)
+#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Enters the memory Mapping mode.
+ * @details The memory mapping mode is only available when the WSPI mode
+ * is selected and the underlying WSPI controller supports the
+ * feature.
+ *
+ * @param[in] devp pointer to the @p SNORDriver object
+ * @param[out] addrp pointer to the memory start address of the mapped
+ * flash or @p NULL
+ *
+ * @api
+ */
+void snorMemoryMap(SNORDriver *devp, uint8_t **addrp) {
+
+ /* Bus acquisition.*/
+ bus_acquire(devp->config->busp, devp->config->buscfg);
+
+#if SNOR_DEVICE_SUPPORTS_XIP == TRUE
+ /* Activating XIP mode in the device.*/
+ snor_activate_xip(devp);
+#endif
+
+ /* Starting WSPI memory mapped mode.*/
+ wspiMapFlash(devp->config->busp, &snor_memmap_read, addrp);
+
+ /* Bus release.*/
+ bus_release(devp->config->busp);
+}
+
+/**
+ * @brief Leaves the memory Mapping mode.
+ *
+ * @param[in] devp pointer to the @p SNORDriver object
+ *
+ * @api
+ */
+void snorMemoryUnmap(SNORDriver *devp) {
+
+ /* Bus acquisition.*/
+ bus_acquire(devp->config->busp, devp->config->buscfg);
+
+ /* Stopping WSPI memory mapped mode.*/
+ wspiUnmapFlash(devp->config->busp);
+
+#if SNOR_DEVICE_SUPPORTS_XIP == TRUE
+ snor_reset_xip(devp);
+#endif
+
+ /* Bus release.*/
+ bus_release(devp->config->busp);
+}
+#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */
+#endif /* SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/hal_serial_nor.h b/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/hal_serial_nor.h
new file mode 100644
index 0000000..cca0297
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/complex/serial_nor/hal_serial_nor.h
@@ -0,0 +1,210 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_serial_nor.h
+ * @brief Serial NOR driver header.
+ *
+ * @addtogroup HAL_SERIAL_NOR
+ * @{
+ */
+
+#ifndef HAL_SERIAL_NOR_H
+#define HAL_SERIAL_NOR_H
+
+#include "hal_flash.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Bus interface modes.
+ * @{
+ */
+#define SNOR_BUS_DRIVER_SPI 0U
+#define SNOR_BUS_DRIVER_WSPI 1U
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief Physical transport interface.
+ */
+#if !defined(SNOR_BUS_DRIVER) || defined(__DOXYGEN__)
+#define SNOR_BUS_DRIVER SNOR_BUS_DRIVER_WSPI
+#endif
+
+/**
+ * @brief Shared bus switch.
+ * @details If set to @p TRUE the device acquires bus ownership
+ * on each transaction.
+ * @note Requires @p SPI_USE_MUTUAL_EXCLUSION or
+ * @p WSPI_USE_MUTUAL_EXCLUSION depending on mode selected
+ * with @p SNOR_BUS_MODE.
+ */
+#if !defined(SNOR_SHARED_BUS) || defined(__DOXYGEN__)
+#define SNOR_SHARED_BUS TRUE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_SPI) || defined(__DOXYGEN__)
+#define BUSConfig SPIConfig
+#define BUSDriver SPIDriver
+#elif SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI
+#define BUSConfig WSPIConfig
+#define BUSDriver WSPIDriver
+#else
+#error "invalid SNOR_BUS_DRIVER setting"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a SNOR configuration structure.
+ */
+typedef struct {
+ BUSDriver *busp;
+ const BUSConfig *buscfg;
+} SNORConfig;
+
+/**
+ * @brief @p SNORDriver specific methods.
+ */
+#define _snor_flash_methods_alone \
+ /* Read SFDP.*/ \
+ flash_error_t (*read_sfdp)(void *instance, \
+ flash_offset_t offset, \
+ size_t n, \
+ uint8_t *rp);
+
+/**
+ * @brief @p SNORDriver specific methods with inherited ones.
+ */
+#define _snor_flash_methods \
+ _base_flash_methods \
+ _snor_flash_methods_alone
+
+/**
+ * @extends BaseFlashVMT
+ *
+ * @brief @p SNOR virtual methods table.
+ */
+struct SNORDriverVMT {
+ _snor_flash_methods
+};
+
+/**
+ * @extends BaseFlash
+ *
+ * @brief Type of SNOR flash class.
+ */
+typedef struct {
+ /**
+ * @brief SNORDriver Virtual Methods Table.
+ */
+ const struct SNORDriverVMT *vmt;
+ _base_flash_data
+ /**
+ * @brief Current configuration data.
+ */
+ const SNORConfig *config;
+ /**
+ * @brief Device ID and unique ID.
+ */
+ uint8_t device_id[20];
+} SNORDriver;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+#if SNOR_SHARED_BUS == FALSE
+#define bus_acquire(busp, config)
+#define bus_release(busp)
+#endif
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void bus_acquire(BUSDriver *busp, const BUSConfig *config);
+ void bus_release(BUSDriver *busp);
+ void bus_cmd(BUSDriver *busp, uint32_t cmd);
+ void bus_cmd_send(BUSDriver *busp, uint32_t cmd, size_t n, const uint8_t *p);
+ void bus_cmd_receive(BUSDriver *busp,
+ uint32_t cmd,
+ size_t n,
+ uint8_t *p);
+ void bus_cmd_addr(BUSDriver *busp, uint32_t cmd, flash_offset_t offset);
+ void bus_cmd_addr_send(BUSDriver *busp,
+ uint32_t cmd,
+ flash_offset_t offset,
+ size_t n,
+ const uint8_t *p);
+ void bus_cmd_addr_receive(BUSDriver *busp,
+ uint32_t cmd,
+ flash_offset_t offset,
+ size_t n,
+ uint8_t *p);
+#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) || defined(__DOXYGEN__)
+ void bus_cmd_dummy_receive(BUSDriver *busp,
+ uint32_t cmd,
+ uint32_t dummy,
+ size_t n,
+ uint8_t *p);
+ void bus_cmd_addr_dummy_receive(BUSDriver *busp,
+ uint32_t cmd,
+ flash_offset_t offset,
+ uint32_t dummy,
+ size_t n,
+ uint8_t *p);
+#endif
+ void snorObjectInit(SNORDriver *devp);
+ void snorStart(SNORDriver *devp, const SNORConfig *config);
+ void snorStop(SNORDriver *devp);
+#if (SNOR_BUS_DRIVER == SNOR_BUS_DRIVER_WSPI) || defined(__DOXYGEN__)
+#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
+ void snorMemoryMap(SNORDriver *devp, uint8_t ** addrp);
+ void snorMemoryUnmap(SNORDriver *devp);
+#endif /* QSPI_SUPPORTS_MEMMAP == TRUE */
+#endif /* SNOR_BUS_MODE != SNOR_BUS_MODE_SPI */
+#ifdef __cplusplus
+}
+#endif
+
+/* Device-specific implementations.*/
+#include "hal_flash_device.h"
+
+#endif /* HAL_SERIAL_NOR_H */
+
+/** @} */
+
diff --git a/ChibiOS_20.3.2/os/hal/lib/fallback/I2C/hal_i2c_lld.c b/ChibiOS_20.3.2/os/hal/lib/fallback/I2C/hal_i2c_lld.c
new file mode 100644
index 0000000..e4ae9a9
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/fallback/I2C/hal_i2c_lld.c
@@ -0,0 +1,444 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file common/I2C/hal_i2c_lld.c
+ * @brief SW I2C subsystem low level driver source.
+ *
+ * @addtogroup I2C
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_I2C || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define CHECK_ERROR(msg) \
+ if ((msg) < (msg_t)0) { \
+ return MSG_TIMEOUT; \
+ }
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief I2C1 driver identifier.*/
+#if SW_I2C_USE_I2C1 || defined(__DOXYGEN__)
+I2CDriver I2CD1;
+#endif
+
+/** @brief I2C2 driver identifier.*/
+#if SW_I2C_USE_I2C2 || defined(__DOXYGEN__)
+I2CDriver I2CD2;
+#endif
+
+/** @brief I2C3 driver identifier.*/
+#if SW_I2C_USE_I2C3 || defined(__DOXYGEN__)
+I2CDriver I2CD3;
+#endif
+
+/** @brief I2C4 driver identifier.*/
+#if SW_I2C_USE_I2C4 || defined(__DOXYGEN__)
+I2CDriver I2CD4;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static msg_t i2c_write_stop(I2CDriver *i2cp);
+
+static inline void i2c_delay(I2CDriver *i2cp) {
+
+#if SW_I2C_USE_OSAL_DELAY || defined(__DOXYGEN__)
+ osalThreadSleepS(i2cp->config->ticks);
+#else
+ i2cp->config->delay();
+#endif
+}
+
+static inline msg_t i2c_check_arbitration(I2CDriver *i2cp) {
+
+ if (palReadLine(i2cp->config->sda) == PAL_LOW) {
+ i2cp->errors |= I2C_ARBITRATION_LOST;
+ return MSG_RESET;
+ }
+
+ return MSG_OK;
+}
+
+static inline msg_t i2c_check_timeout(I2CDriver *i2cp) {
+
+ if ((i2cp->start != i2cp->end) &&
+ (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), i2cp->start, i2cp->end))) {
+ i2c_write_stop(i2cp);
+ return MSG_TIMEOUT;
+ }
+
+ return MSG_OK;
+}
+
+static msg_t i2c_wait_clock(I2CDriver *i2cp) {
+
+ while (palReadLine(i2cp->config->scl) == PAL_LOW) {
+ if ((i2cp->start != i2cp->end) &&
+ (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), i2cp->start, i2cp->end))) {
+ return MSG_TIMEOUT;
+ }
+ i2c_delay(i2cp);
+ }
+
+ return MSG_OK;
+}
+
+static inline msg_t i2c_write_start(I2CDriver *i2cp) {
+
+ /* Arbitration check.*/
+ CHECK_ERROR(i2c_check_arbitration(i2cp));
+
+ palClearLine(i2cp->config->sda);
+ i2c_delay(i2cp);
+ palClearLine(i2cp->config->scl);
+
+ return MSG_OK;
+}
+
+static msg_t i2c_write_restart(I2CDriver *i2cp) {
+
+ palSetLine(i2cp->config->sda);
+ i2c_delay(i2cp);
+ palSetLine(i2cp->config->scl);
+
+ /* Clock stretching.*/
+ CHECK_ERROR(i2c_wait_clock(i2cp));
+
+ i2c_delay(i2cp);
+ i2c_write_start(i2cp);
+
+ return MSG_OK;
+}
+
+static msg_t i2c_write_stop(I2CDriver *i2cp) {
+
+ palClearLine(i2cp->config->sda);
+ i2c_delay(i2cp);
+ palSetLine(i2cp->config->scl);
+
+ /* Clock stretching.*/
+ CHECK_ERROR(i2c_wait_clock(i2cp));
+
+ i2c_delay(i2cp);
+ palSetLine(i2cp->config->sda);
+ i2c_delay(i2cp);
+
+ /* Arbitration check.*/
+ CHECK_ERROR(i2c_check_arbitration(i2cp));
+
+ i2c_delay(i2cp);
+
+ return MSG_OK;
+}
+
+static msg_t i2c_write_bit(I2CDriver *i2cp, unsigned bit) {
+
+ palWriteLine(i2cp->config->sda, bit);
+ i2c_delay(i2cp);
+ palSetLine(i2cp->config->scl);
+ i2c_delay(i2cp);
+
+ /* Clock stretching.*/
+ CHECK_ERROR(i2c_wait_clock(i2cp));
+
+ /* Arbitration check.*/
+ if (bit == PAL_HIGH) {
+ CHECK_ERROR(i2c_check_arbitration(i2cp));
+ }
+
+ palClearLine(i2cp->config->scl);
+
+ return MSG_OK;
+}
+
+static msg_t i2c_read_bit(I2CDriver *i2cp) {
+ msg_t bit;
+
+ palSetLine(i2cp->config->sda);
+ i2c_delay(i2cp);
+ palSetLine(i2cp->config->scl);
+
+ /* Clock stretching.*/
+ CHECK_ERROR(i2c_wait_clock(i2cp));
+
+ i2c_delay(i2cp);
+ bit = palReadLine(i2cp->config->sda);
+ palClearLine(i2cp->config->scl);
+
+ return bit;
+}
+
+static msg_t i2c_write_byte(I2CDriver *i2cp, uint8_t byte) {
+ msg_t msg;
+ uint8_t mask;
+
+ CHECK_ERROR(i2c_check_timeout(i2cp));
+
+ for (mask = 0x80U; mask > 0U; mask >>= 1U) {
+ CHECK_ERROR(i2c_write_bit(i2cp, (byte & mask) != 0));
+ }
+
+ msg = i2c_read_bit(i2cp);
+ CHECK_ERROR(msg);
+
+ /* Checking for NACK.*/
+ if (msg == PAL_HIGH) {
+ i2cp->errors |= I2C_ACK_FAILURE;
+ return MSG_RESET;
+ }
+
+ return MSG_OK;
+}
+
+static msg_t i2c_read_byte(I2CDriver *i2cp, unsigned nack) {
+ msg_t byte;
+ unsigned i;
+
+ CHECK_ERROR(i2c_check_timeout(i2cp));
+
+ byte = 0U;
+ for (i = 0; i < 8; i++) {
+ msg_t msg = i2c_read_bit(i2cp);
+ CHECK_ERROR(msg);
+ byte = (byte << 1U) | msg;
+ }
+
+ CHECK_ERROR(i2c_write_bit(i2cp, nack));
+
+ return byte;
+}
+
+static msg_t i2c_write_header(I2CDriver *i2cp, i2caddr_t addr, bool rw) {
+
+ /* Check for 10 bits addressing.*/
+ if (i2cp->config->addr10) {
+ /* It is 10 bits.*/
+ uint8_t b1, b2;
+
+ b1 = 0xF0U | ((addr >> 8U) << 1U);
+ b2 = (uint8_t)(addr & 255U);
+ if (rw) {
+ b1 |= 1U;
+ }
+ CHECK_ERROR(i2c_write_byte(i2cp, b1));
+ CHECK_ERROR(i2c_write_byte(i2cp, b2));
+ }
+ else {
+ /* It is 7 bits.*/
+ if (rw) {
+ /* Read.*/
+ CHECK_ERROR(i2c_write_byte(i2cp, (addr << 1U) | 1U));
+ }
+ else {
+ /* Write.*/
+ CHECK_ERROR(i2c_write_byte(i2cp, (addr << 1U) | 0U));
+ }
+ }
+
+ return MSG_OK;
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level I2C driver initialization.
+ *
+ * @notapi
+ */
+void i2c_lld_init(void) {
+
+#if SW_I2C_USE_I2C1
+ i2cObjectInit(&I2CD1);
+#endif
+#if SW_I2C_USE_I2C2
+ i2cObjectInit(&I2CD2);
+#endif
+#if SW_I2C_USE_I2C3
+ i2cObjectInit(&I2CD3);
+#endif
+#if SW_I2C_USE_I2C4
+ i2cObjectInit(&I2CD4);
+#endif
+}
+
+/**
+ * @brief Configures and activates the I2C peripheral.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+void i2c_lld_start(I2CDriver *i2cp) {
+
+ /* Does nothing.*/
+ (void)i2cp;
+}
+
+/**
+ * @brief Deactivates the I2C peripheral.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+void i2c_lld_stop(I2CDriver *i2cp) {
+
+ /* Does nothing.*/
+ (void)i2cp;
+}
+
+/**
+ * @brief Receives data via the I2C bus as master.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] addr slave device address
+ * @param[out] rxbuf pointer to the receive buffer
+ * @param[in] rxbytes number of bytes to be received
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a
+ * timeout the driver must be stopped and restarted
+ * because the bus is in an uncertain state.
+ *
+ * @notapi
+ */
+msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout) {
+
+ /* Setting timeout fields.*/
+ i2cp->start = osalOsGetSystemTimeX();
+ i2cp->end = i2cp->start;
+ if (timeout != TIME_INFINITE) {
+ i2cp->end = osalTimeAddX(i2cp->start, timeout);
+ }
+
+ CHECK_ERROR(i2c_write_start(i2cp));
+
+ /* Sending address and mode.*/
+ CHECK_ERROR(i2c_write_header(i2cp, addr, true));
+
+ do {
+ /* Last byte sends a NACK.*/
+ msg_t msg = i2c_read_byte(i2cp, rxbytes > 1U ? 0U : 1U);
+ CHECK_ERROR(msg);
+ *rxbuf++ = (uint8_t)msg;
+ } while (--rxbytes);
+
+ return i2c_write_stop(i2cp);
+}
+
+/**
+ * @brief Transmits data via the I2C bus as master.
+ * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x.
+ * This is hardware restriction.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] addr slave device address
+ * @param[in] txbuf pointer to the transmit buffer
+ * @param[in] txbytes number of bytes to be transmitted
+ * @param[out] rxbuf pointer to the receive buffer
+ * @param[in] rxbytes number of bytes to be received
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a
+ * timeout the driver must be stopped and restarted
+ * because the bus is in an uncertain state.
+ *
+ * @notapi
+ */
+msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ const uint8_t *txbuf, size_t txbytes,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout) {
+
+ /* Setting timeout fields.*/
+ i2cp->start = osalOsGetSystemTimeX();
+ i2cp->end = i2cp->start;
+ if (timeout != TIME_INFINITE) {
+ i2cp->end = osalTimeAddX(i2cp->start, timeout);
+ }
+
+ /* Sending start condition.*/
+ CHECK_ERROR(i2c_write_start(i2cp));
+
+ /* Sending address and mode.*/
+ CHECK_ERROR(i2c_write_header(i2cp, addr, false));
+
+ do {
+ CHECK_ERROR(i2c_write_byte(i2cp, *txbuf++));
+ } while (--txbytes);
+
+ /* Is there a read phase? */
+ if (rxbytes > 0U) {
+
+ /* Sending restart condition.*/
+ CHECK_ERROR(i2c_write_restart(i2cp));
+ /* Sending address and mode.*/
+ CHECK_ERROR(i2c_write_header(i2cp, addr, true));
+
+ do {
+ /* Last byte sends a NACK.*/
+ msg_t msg = i2c_read_byte(i2cp, rxbytes > 1U ? 0U : 1U);
+ CHECK_ERROR(msg);
+ *rxbuf++ = (uint8_t)msg;
+ } while (--rxbytes);
+ }
+
+ return i2c_write_stop(i2cp);
+}
+
+#endif /* HAL_USE_I2C */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/lib/fallback/I2C/hal_i2c_lld.h b/ChibiOS_20.3.2/os/hal/lib/fallback/I2C/hal_i2c_lld.h
new file mode 100644
index 0000000..38c1552
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/fallback/I2C/hal_i2c_lld.h
@@ -0,0 +1,232 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file common/I2C/hal_i2c_lld.h
+ * @brief SW I2C subsystem low level driver header.
+ *
+ * @addtogroup I2C
+ * @{
+ */
+
+#ifndef HAL_I2C_LLD_H
+#define HAL_I2C_LLD_H
+
+#if HAL_USE_I2C || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief Use OSAL delays.
+ * @details If set to @p TRUE then delays are implemented using the
+ * thread-friendly delay function else a delay function must
+ * be provided externally.
+ */
+#if !defined(SW_I2C_USE_OSAL_DELAY) || defined(__DOXYGEN__)
+#define SW_I2C_USE_OSAL_DELAY TRUE
+#endif
+
+/**
+ * @brief I2C1 driver enable switch.
+ * @details If set to @p TRUE the support for I2C1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(SW_I2C_USE_I2C1) || defined(__DOXYGEN__)
+#define SW_I2C_USE_I2C1 FALSE
+#endif
+
+/**
+ * @brief I2C2 driver enable switch.
+ * @details If set to @p TRUE the support for I2C2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(SW_I2C_USE_I2C2) || defined(__DOXYGEN__)
+#define SW_I2C_USE_I2C2 FALSE
+#endif
+
+/**
+ * @brief I2C3 driver enable switch.
+ * @details If set to @p TRUE the support for I2C3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(SW_I2C_USE_I2C3) || defined(__DOXYGEN__)
+#define SW_I2C_USE_I2C3 FALSE
+#endif
+
+/**
+ * @brief I2C4 driver enable switch.
+ * @details If set to @p TRUE the support for I2C4 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(SW_I2C_USE_I2C4) || defined(__DOXYGEN__)
+#define SW_I2C_USE_I2C4 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type representing an I2C address.
+ */
+typedef uint16_t i2caddr_t;
+
+/**
+ * @brief Type of I2C driver condition flags.
+ */
+typedef uint8_t i2cflags_t;
+
+/**
+ * @brief Type of a delay function.
+ */
+typedef void (*i2c_delay_t)(void);
+
+/**
+ * @brief Type of I2C driver configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief 10 bits addressing switch.
+ */
+ bool addr10;
+ /**
+ * @brief I2C clock line.
+ */
+ ioline_t scl;
+ /**
+ * @brief I2C data line.
+ */
+ ioline_t sda;
+#if SW_I2C_USE_OSAL_DELAY || defined(__DOXYGEN__)
+ /**
+ * @brief Delay of an half bit time in system ticks.
+ */
+ systime_t ticks;
+#else
+ /**
+ * @brief Pointer to an externally defined delay function.
+ */
+ i2c_delay_t delay;
+#endif
+} I2CConfig;
+
+/**
+ * @brief Type of a structure representing an I2C driver.
+ */
+typedef struct I2CDriver I2CDriver;
+
+/**
+ * @brief Structure representing an I2C driver.
+ */
+struct I2CDriver {
+ /**
+ * @brief Driver state.
+ */
+ i2cstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const I2CConfig *config;
+ /**
+ * @brief Error flags.
+ */
+ i2cflags_t errors;
+#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
+ mutex_t mutex;
+#endif /* I2C_USE_MUTUAL_EXCLUSION */
+#if defined(I2C_DRIVER_EXT_FIELDS)
+ I2C_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Time of operation begin.
+ */
+ systime_t start;
+ /**
+ * @brief Time of operation timeout.
+ */
+ systime_t end;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Get errors from I2C driver.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+#define i2c_lld_get_errors(i2cp) ((i2cp)->errors)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+#if SW_I2C_USE_I2C1
+extern I2CDriver I2CD1;
+#endif
+#if SW_I2C_USE_I2C2
+extern I2CDriver I2CD2;
+#endif
+#if SW_I2C_USE_I2C3
+extern I2CDriver I2CD3;
+#endif
+#if SW_I2C_USE_I2C4
+extern I2CDriver I2CD4;
+#endif
+#endif /* !defined(__DOXYGEN__) */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void i2c_lld_init(void);
+ void i2c_lld_start(I2CDriver *i2cp);
+ void i2c_lld_stop(I2CDriver *i2cp);
+ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ const uint8_t *txbuf, size_t txbytes,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout);
+ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_I2C */
+
+#endif /* HAL_I2C_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/lib/streams/chprintf.c b/ChibiOS_20.3.2/os/hal/lib/streams/chprintf.c
new file mode 100644
index 0000000..33134da
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/streams/chprintf.c
@@ -0,0 +1,473 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ Concepts and parts of this file have been contributed by Fabio Utzig,
+ chvprintf() added by Brent Roman.
+ */
+
+/**
+ * @file chprintf.c
+ * @brief Mini printf-like functionality.
+ *
+ * @addtogroup HAL_CHPRINTF
+ * @details Mini printf-like functionality.
+ * @{
+ */
+
+#include "hal.h"
+#include "chprintf.h"
+#include "memstreams.h"
+
+#define MAX_FILLER 11
+#define FLOAT_PRECISION 9
+
+static char *long_to_string_with_divisor(char *p,
+ long num,
+ unsigned radix,
+ long divisor) {
+ int i;
+ char *q;
+ long l, ll;
+
+ l = num;
+ if (divisor == 0) {
+ ll = num;
+ } else {
+ ll = divisor;
+ }
+
+ q = p + MAX_FILLER;
+ do {
+ i = (int)(l % radix);
+ i += '0';
+ if (i > '9') {
+ i += 'A' - '0' - 10;
+ }
+ *--q = i;
+ l /= radix;
+ } while ((ll /= radix) != 0);
+
+ i = (int)(p + MAX_FILLER - q);
+ do
+ *p++ = *q++;
+ while (--i);
+
+ return p;
+}
+
+static char *ch_ltoa(char *p, long num, unsigned radix) {
+
+ return long_to_string_with_divisor(p, num, radix, 0);
+}
+
+#if CHPRINTF_USE_FLOAT
+static const long pow10[FLOAT_PRECISION] = {
+ 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
+};
+
+static char *ftoa(char *p, double num, unsigned long precision) {
+ long l;
+
+ if ((precision == 0) || (precision > FLOAT_PRECISION)) {
+ precision = FLOAT_PRECISION;
+ }
+ precision = pow10[precision - 1];
+
+ l = (long)num;
+ p = long_to_string_with_divisor(p, l, 10, 0);
+ *p++ = '.';
+ l = (long)((num - l) * precision);
+
+ return long_to_string_with_divisor(p, l, 10, precision / 10);
+}
+#endif
+
+/**
+ * @brief System formatted output function.
+ * @details This function implements a minimal @p vprintf()-like functionality
+ * with output on a @p BaseSequentialStream.
+ * The general parameters format is: %[-][width|*][.precision|*][l|L]p.
+ * The following parameter types (p) are supported:
+ * - x hexadecimal integer.
+ * - X hexadecimal long.
+ * - o octal integer.
+ * - O octal long.
+ * - d decimal signed integer.
+ * - D decimal signed long.
+ * - u decimal unsigned integer.
+ * - U decimal unsigned long.
+ * - c character.
+ * - s string.
+ * .
+ *
+ * @param[in] chp pointer to a @p BaseSequentialStream implementing object
+ * @param[in] fmt formatting string
+ * @param[in] ap list of parameters
+ * @return The number of bytes that would have been
+ * written to @p chp if no stream error occurs
+ *
+ * @api
+ */
+int chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap) {
+ char *p, *s, c, filler;
+ int i, precision, width;
+ int n = 0;
+ bool is_long, left_align, do_sign;
+ long l;
+#if CHPRINTF_USE_FLOAT
+ float f;
+ char tmpbuf[2*MAX_FILLER + 1];
+#else
+ char tmpbuf[MAX_FILLER + 1];
+#endif
+
+ while (true) {
+ c = *fmt++;
+ if (c == 0) {
+ return n;
+ }
+
+ if (c != '%') {
+ streamPut(chp, (uint8_t)c);
+ n++;
+ continue;
+ }
+
+ p = tmpbuf;
+ s = tmpbuf;
+
+ /* Alignment mode.*/
+ left_align = false;
+ if (*fmt == '-') {
+ fmt++;
+ left_align = true;
+ }
+
+ /* Sign mode.*/
+ do_sign = false;
+ if (*fmt == '+') {
+ fmt++;
+ do_sign = true;
+ }
+
+ /* Filler mode.*/
+ filler = ' ';
+ if (*fmt == '0') {
+ fmt++;
+ filler = '0';
+ }
+
+ /* Width modifier.*/
+ if ( *fmt == '*') {
+ width = va_arg(ap, int);
+ ++fmt;
+ c = *fmt++;
+ }
+ else {
+ width = 0;
+ while (true) {
+ c = *fmt++;
+ if (c == 0) {
+ return n;
+ }
+ if (c >= '0' && c <= '9') {
+ c -= '0';
+ width = width * 10 + c;
+ }
+ else {
+ break;
+ }
+ }
+ }
+
+ /* Precision modifier.*/
+ precision = 0;
+ if (c == '.') {
+ c = *fmt++;
+ if (c == 0) {
+ return n;
+ }
+ if (c == '*') {
+ precision = va_arg(ap, int);
+ c = *fmt++;
+ }
+ else {
+ while (c >= '0' && c <= '9') {
+ c -= '0';
+ precision = precision * 10 + c;
+ c = *fmt++;
+ if (c == 0) {
+ return n;
+ }
+ }
+ }
+ }
+
+ /* Long modifier.*/
+ if (c == 'l' || c == 'L') {
+ is_long = true;
+ c = *fmt++;
+ if (c == 0) {
+ return n;
+ }
+ }
+ else {
+ is_long = (c >= 'A') && (c <= 'Z');
+ }
+
+ /* Command decoding.*/
+ switch (c) {
+ case 'c':
+ filler = ' ';
+ *p++ = va_arg(ap, int);
+ break;
+ case 's':
+ filler = ' ';
+ if ((s = va_arg(ap, char *)) == 0) {
+ s = "(null)";
+ }
+ if (precision == 0) {
+ precision = 32767;
+ }
+ for (p = s; *p && (--precision >= 0); p++)
+ ;
+ break;
+ case 'D':
+ case 'd':
+ case 'I':
+ case 'i':
+ if (is_long) {
+ l = va_arg(ap, long);
+ }
+ else {
+ l = va_arg(ap, int);
+ }
+ if (l < 0) {
+ *p++ = '-';
+ l = -l;
+ }
+ else
+ if (do_sign) {
+ *p++ = '+';
+ }
+ p = ch_ltoa(p, l, 10);
+ break;
+#if CHPRINTF_USE_FLOAT
+ case 'f':
+ f = (float) va_arg(ap, double);
+ if (f < 0) {
+ *p++ = '-';
+ f = -f;
+ }
+ else {
+ if (do_sign) {
+ *p++ = '+';
+ }
+ }
+ p = ftoa(p, f, precision);
+ break;
+#endif
+ case 'X':
+ case 'x':
+ case 'P':
+ case 'p':
+ c = 16;
+ goto unsigned_common;
+ case 'U':
+ case 'u':
+ c = 10;
+ goto unsigned_common;
+ case 'O':
+ case 'o':
+ c = 8;
+unsigned_common:
+ if (is_long) {
+ l = va_arg(ap, unsigned long);
+ }
+ else {
+ l = va_arg(ap, unsigned int);
+ }
+ p = ch_ltoa(p, l, c);
+ break;
+ default:
+ *p++ = c;
+ break;
+ }
+ i = (int)(p - s);
+ if ((width -= i) < 0) {
+ width = 0;
+ }
+ if (left_align == false) {
+ width = -width;
+ }
+ if (width < 0) {
+ if (*s == '-' && filler == '0') {
+ streamPut(chp, (uint8_t)*s++);
+ n++;
+ i--;
+ }
+ do {
+ streamPut(chp, (uint8_t)filler);
+ n++;
+ } while (++width != 0);
+ }
+ while (--i >= 0) {
+ streamPut(chp, (uint8_t)*s++);
+ n++;
+ }
+
+ while (width) {
+ streamPut(chp, (uint8_t)filler);
+ n++;
+ width--;
+ }
+ }
+}
+
+/**
+ * @brief System formatted output function.
+ * @details This function implements a minimal @p printf() like functionality
+ * with output on a @p BaseSequentialStream.
+ * The general parameters format is: %[-][width|*][.precision|*][l|L]p.
+ * The following parameter types (p) are supported:
+ * - x hexadecimal integer.
+ * - X hexadecimal long.
+ * - o octal integer.
+ * - O octal long.
+ * - d decimal signed integer.
+ * - D decimal signed long.
+ * - u decimal unsigned integer.
+ * - U decimal unsigned long.
+ * - c character.
+ * - s string.
+ * .
+ *
+ * @param[in] chp pointer to a @p BaseSequentialStream implementing object
+ * @param[in] fmt formatting string
+ * @return The number of bytes that would have been
+ * written to @p chp if no stream error occurs
+ *
+ * @api
+ */
+int chprintf(BaseSequentialStream *chp, const char *fmt, ...) {
+ va_list ap;
+ int formatted_bytes;
+
+ va_start(ap, fmt);
+ formatted_bytes = chvprintf(chp, fmt, ap);
+ va_end(ap);
+
+ return formatted_bytes;
+}
+
+/**
+ * @brief System formatted output function.
+ * @details This function implements a minimal @p snprintf()-like functionality.
+ * The general parameters format is: %[-][width|*][.precision|*][l|L]p.
+ * The following parameter types (p) are supported:
+ * - x hexadecimal integer.
+ * - X hexadecimal long.
+ * - o octal integer.
+ * - O octal long.
+ * - d decimal signed integer.
+ * - D decimal signed long.
+ * - u decimal unsigned integer.
+ * - U decimal unsigned long.
+ * - c character.
+ * - s string.
+ * .
+ * @post @p str is NUL-terminated, unless @p size is 0.
+ *
+ * @param[in] str pointer to a buffer
+ * @param[in] size maximum size of the buffer
+ * @param[in] fmt formatting string
+ * @return The number of characters (excluding the
+ * terminating NUL byte) that would have been
+ * stored in @p str if there was room.
+ *
+ * @api
+ */
+int chsnprintf(char *str, size_t size, const char *fmt, ...) {
+ va_list ap;
+ int retval;
+
+ /* Performing the print operation.*/
+ va_start(ap, fmt);
+ retval = chvsnprintf(str, size, fmt, ap);
+ va_end(ap);
+
+ /* Return number of bytes that would have been written.*/
+ return retval;
+}
+
+/**
+ * @brief System formatted output function.
+ * @details This function implements a minimal @p vsnprintf()-like functionality.
+ * The general parameters format is: %[-][width|*][.precision|*][l|L]p.
+ * The following parameter types (p) are supported:
+ * - x hexadecimal integer.
+ * - X hexadecimal long.
+ * - o octal integer.
+ * - O octal long.
+ * - d decimal signed integer.
+ * - D decimal signed long.
+ * - u decimal unsigned integer.
+ * - U decimal unsigned long.
+ * - c character.
+ * - s string.
+ * .
+ * @post @p str is NUL-terminated, unless @p size is 0.
+ *
+ * @param[in] str pointer to a buffer
+ * @param[in] size maximum size of the buffer
+ * @param[in] fmt formatting string
+ * @param[in] ap list of parameters
+ * @return The number of characters (excluding the
+ * terminating NUL byte) that would have been
+ * stored in @p str if there was room.
+ *
+ * @api
+ */
+int chvsnprintf(char *str, size_t size, const char *fmt, va_list ap) {
+ MemoryStream ms;
+ BaseSequentialStream *chp;
+ size_t size_wo_nul;
+ int retval;
+
+ if (size > 0)
+ size_wo_nul = size - 1;
+ else
+ size_wo_nul = 0;
+
+ /* Memory stream object to be used as a string writer, reserving one
+ byte for the final zero.*/
+ msObjectInit(&ms, (uint8_t *)str, size_wo_nul, 0);
+
+ /* Performing the print operation using the common code.*/
+ chp = (BaseSequentialStream *)(void *)&ms;
+ retval = chvprintf(chp, fmt, ap);
+
+ /* Terminate with a zero, unless size==0.*/
+ if (ms.eos < size) {
+ str[ms.eos] = 0;
+ }
+
+ /* Return number of bytes that would have been written.*/
+ return retval;
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/lib/streams/chprintf.h b/ChibiOS_20.3.2/os/hal/lib/streams/chprintf.h
new file mode 100644
index 0000000..9eb3afd
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/streams/chprintf.h
@@ -0,0 +1,50 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file chprintf.h
+ * @brief Mini printf-like functionality.
+ *
+ * @addtogroup HAL_CHPRINTF
+ * @{
+ */
+
+#ifndef CHPRINTF_H
+#define CHPRINTF_H
+
+#include
+
+/**
+ * @brief Float type support.
+ */
+#if !defined(CHPRINTF_USE_FLOAT) || defined(__DOXYGEN__)
+#define CHPRINTF_USE_FLOAT FALSE
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ int chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap);
+ int chprintf(BaseSequentialStream *chp, const char *fmt, ...);
+ int chsnprintf(char *str, size_t size, const char *fmt, ...);
+ int chvsnprintf(char *str, size_t size, const char *fmt, va_list ap);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CHPRINTF_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/lib/streams/memstreams.c b/ChibiOS_20.3.2/os/hal/lib/streams/memstreams.c
new file mode 100644
index 0000000..98b3fe6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/streams/memstreams.c
@@ -0,0 +1,114 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file memstreams.c
+ * @brief Memory streams code.
+ *
+ * @addtogroup HAL_MEMORY_STREAMS
+ * @details Memory buffers handled as streams.
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+#include "memstreams.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static size_t _writes(void *ip, const uint8_t *bp, size_t n) {
+ MemoryStream *msp = ip;
+
+ if (msp->size - msp->eos < n)
+ n = msp->size - msp->eos;
+ memcpy(msp->buffer + msp->eos, bp, n);
+ msp->eos += n;
+ return n;
+}
+
+static size_t _reads(void *ip, uint8_t *bp, size_t n) {
+ MemoryStream *msp = ip;
+
+ if (msp->eos - msp->offset < n)
+ n = msp->eos - msp->offset;
+ memcpy(bp, msp->buffer + msp->offset, n);
+ msp->offset += n;
+ return n;
+}
+
+static msg_t _put(void *ip, uint8_t b) {
+ MemoryStream *msp = ip;
+
+ if (msp->size - msp->eos <= 0)
+ return MSG_RESET;
+ *(msp->buffer + msp->eos) = b;
+ msp->eos += 1;
+ return MSG_OK;
+}
+
+static msg_t _get(void *ip) {
+ uint8_t b;
+ MemoryStream *msp = ip;
+
+ if (msp->eos - msp->offset <= 0)
+ return MSG_RESET;
+ b = *(msp->buffer + msp->offset);
+ msp->offset += 1;
+ return b;
+}
+
+static const struct MemStreamVMT vmt = {(size_t)0, _writes, _reads, _put, _get};
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Memory stream object initialization.
+ *
+ * @param[out] msp pointer to the @p MemoryStream object to be initialized
+ * @param[in] buffer pointer to the memory buffer for the memory stream
+ * @param[in] size total size of the memory stream buffer
+ * @param[in] eos initial End Of Stream offset. Normally you need to
+ * put this to zero for RAM buffers or equal to @p size
+ * for ROM streams.
+ */
+void msObjectInit(MemoryStream *msp, uint8_t *buffer,
+ size_t size, size_t eos) {
+
+ msp->vmt = &vmt;
+ msp->buffer = buffer;
+ msp->size = size;
+ msp->eos = eos;
+ msp->offset = 0;
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/lib/streams/memstreams.h b/ChibiOS_20.3.2/os/hal/lib/streams/memstreams.h
new file mode 100644
index 0000000..0c2236b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/streams/memstreams.h
@@ -0,0 +1,95 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file memstreams.h
+ * @brief Memory streams structures and macros.
+
+ * @addtogroup HAL_MEMORY_STREAMS
+ * @{
+ */
+
+#ifndef MEMSTREAMS_H
+#define MEMSTREAMS_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief @p MemStream specific data.
+ */
+#define _memory_stream_data \
+ _base_sequential_stream_data \
+ /* Pointer to the stream buffer.*/ \
+ uint8_t *buffer; \
+ /* Size of the stream.*/ \
+ size_t size; \
+ /* Current end of stream.*/ \
+ size_t eos; \
+ /* Current read offset.*/ \
+ size_t offset;
+
+/**
+ * @brief @p MemStream virtual methods table.
+ */
+struct MemStreamVMT {
+ _base_sequential_stream_methods
+};
+
+/**
+ * @extends BaseSequentialStream
+ *
+ * @brief Memory stream object.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct MemStreamVMT *vmt;
+ _memory_stream_data
+} MemoryStream;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void msObjectInit(MemoryStream *msp, uint8_t *buffer,
+ size_t size, size_t eos);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MEMSTREAMS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/lib/streams/nullstreams.c b/ChibiOS_20.3.2/os/hal/lib/streams/nullstreams.c
new file mode 100644
index 0000000..dcfd424
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/streams/nullstreams.c
@@ -0,0 +1,93 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file nullstreams.c
+ * @brief Null streams code.
+ *
+ * @addtogroup HAL_NULL_STREAMS
+ * @details A null streams.
+ * @{
+ */
+
+#include "hal.h"
+#include "nullstreams.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static size_t writes(void *ip, const uint8_t *bp, size_t n) {
+
+ (void)ip;
+ (void)bp;
+
+ return n;
+}
+
+static size_t reads(void *ip, uint8_t *bp, size_t n) {
+
+ (void)ip;
+ (void)bp;
+ (void)n;
+
+ return 0;
+}
+
+static msg_t put(void *ip, uint8_t b) {
+
+ (void)ip;
+ (void)b;
+
+ return MSG_OK;
+}
+
+static msg_t get(void *ip) {
+
+ (void)ip;
+
+ return 4;
+}
+
+static const struct NullStreamVMT vmt = {(size_t)0, writes, reads, put, get};
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Null stream object initialization.
+ *
+ * @param[out] nsp pointer to the @p NullStream object to be initialized
+ */
+void nullObjectInit(NullStream *nsp) {
+
+ nsp->vmt = &vmt;
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/lib/streams/nullstreams.h b/ChibiOS_20.3.2/os/hal/lib/streams/nullstreams.h
new file mode 100644
index 0000000..c874815
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/streams/nullstreams.h
@@ -0,0 +1,86 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file nullstreams.h
+ * @brief Null streams structures and macros.
+
+ * @addtogroup HAL_NULL_STREAMS
+ * @{
+ */
+
+#ifndef NULLSTREAMS_H
+#define NULLSTREAMS_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief @p NullStream specific data.
+ */
+#define _null_stream_data \
+ _base_sequential_stream_data
+
+/**
+ * @brief @p NullStream virtual methods table.
+ */
+struct NullStreamVMT {
+ _base_sequential_stream_methods
+};
+
+/**
+ * @extends BaseSequentialStream
+ *
+ * @brief Null stream object.
+ */
+typedef struct {
+ /** @brief Virtual Methods Table.*/
+ const struct NullStreamVMT *vmt;
+ _null_stream_data
+} NullStream;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void nullObjectInit(NullStream *nsp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NULLSTREAMS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/lib/streams/streams.mk b/ChibiOS_20.3.2/os/hal/lib/streams/streams.mk
new file mode 100644
index 0000000..9c746e9
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/lib/streams/streams.mk
@@ -0,0 +1,10 @@
+# RT Shell files.
+STREAMSSRC = $(CHIBIOS)/os/hal/lib/streams/chprintf.c \
+ $(CHIBIOS)/os/hal/lib/streams/memstreams.c \
+ $(CHIBIOS)/os/hal/lib/streams/nullstreams.c
+
+STREAMSINC = $(CHIBIOS)/os/hal/lib/streams
+
+# Shared variables
+ALLCSRC += $(STREAMSSRC)
+ALLINC += $(STREAMSINC)
\ No newline at end of file
diff --git a/ChibiOS_20.3.2/os/hal/osal/lib/osal_vt.c b/ChibiOS_20.3.2/os/hal/osal/lib/osal_vt.c
new file mode 100644
index 0000000..7d92d13
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/osal/lib/osal_vt.c
@@ -0,0 +1,168 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file osal_vt.c
+ * @brief OSAL Virtual Timers module code.
+ * @details This module can be used in an OSAL implementation whenever an
+ * underlying RTOS is unable to provide timeout services or there
+ * is no underlying RTOS.
+ *
+ * @addtogroup OSAL_VT
+ * @{
+ */
+
+#include "osal.h"
+#include "osal_vt.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief Virtual timers delta list header.
+ */
+virtual_timers_list_t vtlist;
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Timers initialization.
+ *
+ * @init
+ */
+void vtInit(void) {
+
+ /* Virtual Timers initialization.*/
+ vtlist.vt_next = vtlist.vt_prev = (void *)&vtlist;
+ vtlist.vt_delta = (sysinterval_t)-1;
+ vtlist.vt_systime = 0;
+}
+
+/**
+ * @brief Returns @p TRUE if the specified timer is armed.
+ *
+ * @param[out] vtp the @p virtual_timer_t structure pointer
+ *
+ * @iclass
+ */
+bool vtIsArmedI(virtual_timer_t *vtp) {
+
+ return vtp->vt_func != NULL;
+}
+
+/**
+ * @brief Virtual timers ticker.
+ * @note The system lock is released before entering the callback and
+ * re-acquired immediately after. It is callback's responsibility
+ * to acquire the lock if needed. This is done in order to reduce
+ * interrupts jitter when many timers are in use.
+ *
+ * @iclass
+ */
+void vtDoTickI(void) {
+
+ vtlist.vt_systime++;
+ if (&vtlist != (virtual_timers_list_t *)vtlist.vt_next) {
+ virtual_timer_t *vtp;
+
+ --vtlist.vt_next->vt_delta;
+ while (!(vtp = vtlist.vt_next)->vt_delta) {
+ vtfunc_t fn = vtp->vt_func;
+ vtp->vt_func = (vtfunc_t)NULL;
+ vtp->vt_next->vt_prev = (void *)&vtlist;
+ (&vtlist)->vt_next = vtp->vt_next;
+ osalSysUnlockFromISR();
+ fn(vtp->vt_par);
+ osalSysLockFromISR();
+ }
+ }
+}
+
+/**
+ * @brief Enables a virtual timer.
+ * @note The associated function is invoked from interrupt context.
+ *
+ * @param[out] vtp the @p virtual_timer_t structure pointer
+ * @param[in] timeout the number of ticks before the operation timeouts, the
+ * special values are handled as follow:
+ * - @a TIME_INFINITE is allowed but interpreted as a
+ * normal time specification.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ * @param[in] vtfunc the timer callback function. After invoking the
+ * callback the timer is disabled and the structure can
+ * be disposed or reused.
+ * @param[in] par a parameter that will be passed to the callback
+ * function
+ *
+ * @iclass
+ */
+void vtSetI(virtual_timer_t *vtp, sysinterval_t timeout,
+ vtfunc_t vtfunc, void *par) {
+ virtual_timer_t *p;
+
+ vtp->vt_par = par;
+ vtp->vt_func = vtfunc;
+ p = vtlist.vt_next;
+ while (p->vt_delta < timeout) {
+ timeout -= p->vt_delta;
+ p = p->vt_next;
+ }
+
+ vtp->vt_prev = (vtp->vt_next = p)->vt_prev;
+ vtp->vt_prev->vt_next = p->vt_prev = vtp;
+ vtp->vt_delta = timeout;
+ if (p != (void *)&vtlist)
+ p->vt_delta -= timeout;
+}
+
+/**
+ * @brief Disables a Virtual Timer.
+ * @note The timer MUST be active when this function is invoked.
+ *
+ * @param[in] vtp the @p virtual_timer_t structure pointer
+ *
+ * @iclass
+ */
+void vtResetI(virtual_timer_t *vtp) {
+
+ if (vtp->vt_next != (void *)&vtlist)
+ vtp->vt_next->vt_delta += vtp->vt_delta;
+ vtp->vt_prev->vt_next = vtp->vt_next;
+ vtp->vt_next->vt_prev = vtp->vt_prev;
+ vtp->vt_func = (vtfunc_t)NULL;
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/osal/lib/osal_vt.h b/ChibiOS_20.3.2/os/hal/osal/lib/osal_vt.h
new file mode 100644
index 0000000..4926bc5
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/osal/lib/osal_vt.h
@@ -0,0 +1,123 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file osal_vt.h
+ * @brief OSAL Virtual Timers module header.
+ *
+ * @addtogroup OSAL_VT
+ * @{
+ */
+
+#ifndef _OSAL_VT_H_
+#define _OSAL_VT_H_
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a Virtual Timer callback function.
+ */
+typedef void (*vtfunc_t)(void *);
+
+/**
+ * @brief Type of a Virtual Timer structure.
+ */
+typedef struct virtual_timer virtual_timer_t;
+
+/**
+ * @brief Virtual timers list header.
+ * @note The content of this structure is not part of the API and should
+ * not be relied upon. Implementers may define this structure in
+ * an entirely different way.
+ * @note The delta list is implemented as a double link bidirectional list
+ * in order to make the unlink time constant, the reset of a virtual
+ * timer is often used in the code.
+ */
+typedef struct {
+ virtual_timer_t *vt_next; /**< @brief Next timer in the timers
+ list. */
+ virtual_timer_t *vt_prev; /**< @brief Last timer in the timers
+ list. */
+ sysinterval_t vt_delta; /**< @brief Must be initialized to -1. */
+ volatile systime_t vt_systime; /**< @brief System Time counter. */
+} virtual_timers_list_t;
+
+/**
+ * @extends virtual_timers_list_t
+ *
+ * @brief Virtual Timer descriptor structure.
+ * @note The content of this structure is not part of the API and should
+ * not be relied upon. Implementers may define this structure in
+ * an entirely different way.
+ */
+struct virtual_timer {
+ virtual_timer_t *vt_next; /**< @brief Next timer in the timers
+ list. */
+ virtual_timer_t *vt_prev; /**< @brief Previous timer in the timers
+ list. */
+ sysinterval_t vt_delta; /**< @brief Time delta before timeout. */
+ vtfunc_t vt_func; /**< @brief Timer callback function
+ pointer. */
+ void *vt_par; /**< @brief Timer callback function
+ parameter. */
+};
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern virtual_timers_list_t vtlist;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void vtInit(void);
+ bool vtIsArmedI(virtual_timer_t *vtp);
+ void vtDoTickI(void);
+ void vtSetI(virtual_timer_t *vtp, sysinterval_t timeout,
+ vtfunc_t vtfunc, void *par);
+ void vtResetI(virtual_timer_t *vtp);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* _OSAL_VT_H_ */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/osal/os-less/ARMCMx/osal.c b/ChibiOS_20.3.2/os/hal/osal/os-less/ARMCMx/osal.c
new file mode 100644
index 0000000..5c62069
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/osal/os-less/ARMCMx/osal.c
@@ -0,0 +1,467 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file osal.c
+ * @brief OSAL module code.
+ *
+ * @addtogroup OSAL
+ * @{
+ */
+
+#include "osal.h"
+#include "osal_vt.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief Pointer to a halt error message.
+ * @note The message is meant to be retrieved by the debugger after the
+ * system halt caused by an unexpected error.
+ */
+const char *osal_halt_msg;
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+static void callback_timeout(void *p) {
+ osalSysLockFromISR();
+ osalThreadResumeI((thread_reference_t *)p, MSG_TIMEOUT);
+ osalSysUnlockFromISR();
+}
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief OSAL module initialization.
+ *
+ * @api
+ */
+void osalInit(void) {
+
+ vtInit();
+
+ OSAL_INIT_HOOK();
+}
+
+/**
+ * @brief System halt with error message.
+ *
+ * @param[in] reason the halt message pointer
+ *
+ * @api
+ */
+#if !defined(__DOXYGEN__)
+__attribute__((weak, noreturn))
+#endif
+void osalSysHalt(const char *reason) {
+
+ osalSysDisable();
+ osal_halt_msg = reason;
+ while (true) {
+ }
+}
+
+/**
+ * @brief Polled delay.
+ * @note The real delay is always few cycles in excess of the specified
+ * value.
+ *
+ * @param[in] cycles number of cycles
+ *
+ * @xclass
+ */
+void osalSysPolledDelayX(rtcnt_t cycles) {
+
+ (void)cycles;
+}
+
+/**
+ * @brief System timer handler.
+ * @details The handler is used for scheduling and Virtual Timers management.
+ *
+ * @iclass
+ */
+void osalOsTimerHandlerI(void) {
+
+ osalDbgCheckClassI();
+
+ vtDoTickI();
+}
+
+/**
+ * @brief Checks if a reschedule is required and performs it.
+ * @note I-Class functions invoked from thread context must not reschedule
+ * by themselves, an explicit reschedule using this function is
+ * required in this scenario.
+ * @note Not implemented in this simplified OSAL.
+ *
+ * @sclass
+ */
+void osalOsRescheduleS(void) {
+
+}
+
+/**
+ * @brief Current system time.
+ * @details Returns the number of system ticks since the @p osalInit()
+ * invocation.
+ * @note The counter can reach its maximum and then restart from zero.
+ * @note This function can be called from any context but its atomicity
+ * is not guaranteed on architectures whose word size is less than
+ * @p systime_t size.
+ *
+ * @return The system time in ticks.
+ *
+ * @xclass
+ */
+systime_t osalOsGetSystemTimeX(void) {
+
+ return vtlist.vt_systime;
+}
+
+/**
+ * @brief Suspends the invoking thread for the specified time.
+ *
+ * @param[in] time the delay in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE is allowed but interpreted as a
+ * normal time specification.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ *
+ * @sclass
+ */
+void osalThreadSleepS(sysinterval_t time) {
+ virtual_timer_t vt;
+ thread_reference_t tr;
+
+ tr = NULL;
+ vtSetI(&vt, time, callback_timeout, (void *)&tr);
+ osalThreadSuspendS(&tr);
+}
+
+/**
+ * @brief Suspends the invoking thread for the specified time.
+ *
+ * @param[in] time the delay in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE is allowed but interpreted as a
+ * normal time specification.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ *
+ * @api
+ */
+void osalThreadSleep(sysinterval_t time) {
+
+ osalSysLock();
+ osalThreadSleepS(time);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Sends the current thread sleeping and sets a reference variable.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @return The wake up message.
+ *
+ * @sclass
+ */
+msg_t osalThreadSuspendS(thread_reference_t *trp) {
+ thread_t self = {MSG_WAIT};
+
+ osalDbgCheck(trp != NULL);
+
+ *trp = &self;
+ while (self.message == MSG_WAIT) {
+ osalSysUnlock();
+ /* A state-changing interrupt could occur here and cause the loop to
+ terminate, an hook macro is executed while waiting.*/
+ OSAL_IDLE_HOOK();
+ osalSysLock();
+ }
+
+ return self.message;
+}
+
+/**
+ * @brief Sends the current thread sleeping and sets a reference variable.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] timeout the timeout in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE the thread enters an infinite sleep
+ * state.
+ * - @a TIME_IMMEDIATE the thread is not enqueued and
+ * the function returns @p MSG_TIMEOUT as if a timeout
+ * occurred.
+ * .
+ * @return The wake up message.
+ * @retval MSG_TIMEOUT if the operation timed out.
+ *
+ * @sclass
+ */
+msg_t osalThreadSuspendTimeoutS(thread_reference_t *trp, sysinterval_t timeout) {
+ msg_t msg;
+ virtual_timer_t vt;
+
+ osalDbgCheck(trp != NULL);
+
+ if (TIME_INFINITE == timeout)
+ return osalThreadSuspendS(trp);
+
+ vtSetI(&vt, timeout, callback_timeout, (void *)trp);
+ msg = osalThreadSuspendS(trp);
+ if (vtIsArmedI(&vt))
+ vtResetI(&vt);
+
+ return msg;
+}
+
+/**
+ * @brief Wakes up a thread waiting on a thread reference object.
+ * @note This function must not reschedule because it can be called from
+ * ISR context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void osalThreadResumeI(thread_reference_t *trp, msg_t msg) {
+
+ osalDbgCheck(trp != NULL);
+
+ if (*trp != NULL) {
+ (*trp)->message = msg;
+ *trp = NULL;
+ }
+}
+
+/**
+ * @brief Wakes up a thread waiting on a thread reference object.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void osalThreadResumeS(thread_reference_t *trp, msg_t msg) {
+
+ osalDbgCheck(trp != NULL);
+
+ if (*trp != NULL) {
+ (*trp)->message = msg;
+ *trp = NULL;
+ }
+}
+
+/**
+ * @brief Enqueues the caller thread.
+ * @details The caller thread is enqueued and put to sleep until it is
+ * dequeued or the specified timeouts expires.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] timeout the timeout in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE the thread enters an infinite sleep
+ * state.
+ * - @a TIME_IMMEDIATE the thread is not enqueued and
+ * the function returns @p MSG_TIMEOUT as if a timeout
+ * occurred.
+ * .
+ * @return The message from @p osalQueueWakeupOneI() or
+ * @p osalQueueWakeupAllI() functions.
+ * @retval MSG_TIMEOUT if the thread has not been dequeued within the
+ * specified timeout or if the function has been
+ * invoked with @p TIME_IMMEDIATE as timeout
+ * specification.
+ *
+ * @sclass
+ */
+msg_t osalThreadEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout) {
+ msg_t msg;
+ virtual_timer_t vt;
+
+ osalDbgCheck(tqp != NULL);
+
+ if (TIME_IMMEDIATE == timeout)
+ return MSG_TIMEOUT;
+
+ tqp->tr = NULL;
+
+ if (TIME_INFINITE == timeout)
+ return osalThreadSuspendS(&tqp->tr);
+
+ vtSetI(&vt, timeout, callback_timeout, (void *)&tqp->tr);
+ msg = osalThreadSuspendS(&tqp->tr);
+ if (vtIsArmedI(&vt))
+ vtResetI(&vt);
+
+ return msg;
+}
+
+/**
+ * @brief Dequeues and wakes up one thread from the queue, if any.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg) {
+
+ osalDbgCheck(tqp != NULL);
+
+ osalThreadResumeI(&tqp->tr, msg);
+}
+
+/**
+ * @brief Dequeues and wakes up all threads from the queue.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg) {
+
+ osalDbgCheck(tqp != NULL);
+
+ osalThreadResumeI(&tqp->tr, msg);
+}
+
+/**
+ * @brief Add flags to an event source object.
+ *
+ * @param[in] esp pointer to the event flags object
+ * @param[in] flags flags to be ORed to the flags mask
+ *
+ * @iclass
+ */
+void osalEventBroadcastFlagsI(event_source_t *esp, eventflags_t flags) {
+
+ osalDbgCheck(esp != NULL);
+
+ esp->flags |= flags;
+ if (esp->cb != NULL) {
+ esp->cb(esp);
+ }
+}
+
+/**
+ * @brief Add flags to an event source object.
+ *
+ * @param[in] esp pointer to the event flags object
+ * @param[in] flags flags to be ORed to the flags mask
+ *
+ * @iclass
+ */
+void osalEventBroadcastFlags(event_source_t *esp, eventflags_t flags) {
+
+ osalDbgCheck(esp != NULL);
+
+ osalSysLock();
+ osalEventBroadcastFlagsI(esp, flags);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Event callback setup.
+ * @note The callback is invoked from ISR context and can
+ * only invoke I-Class functions. The callback is meant
+ * to wakeup the task that will handle the event by
+ * calling @p osalEventGetAndClearFlagsI().
+ * @note This function is not part of the OSAL API and is provided
+ * exclusively as an example and for convenience.
+ *
+ * @param[in] esp pointer to the event flags object
+ * @param[in] cb pointer to the callback function
+ * @param[in] param parameter to be passed to the callback function
+ *
+ * @api
+ */
+void osalEventSetCallback(event_source_t *esp,
+ eventcallback_t cb,
+ void *param) {
+
+ osalDbgCheck(esp != NULL);
+
+ esp->cb = cb;
+ esp->param = param;
+}
+
+/**
+ * @brief Locks the specified mutex.
+ * @post The mutex is locked and inserted in the per-thread stack of owned
+ * mutexes.
+ *
+ * @param[in,out] mp pointer to the @p mutex_t object
+ *
+ * @api
+ */
+void osalMutexLock(mutex_t *mp) {
+
+ osalDbgCheck(mp != NULL);
+
+ *mp = 1;
+}
+
+/**
+ * @brief Unlocks the specified mutex.
+ * @note The HAL guarantees to release mutex in reverse lock order. The
+ * mutex being unlocked is guaranteed to be the last locked mutex
+ * by the invoking thread.
+ * The implementation can rely on this behavior and eventually
+ * ignore the @p mp parameter which is supplied in order to support
+ * those OSes not supporting a stack of the owned mutexes.
+ *
+ * @param[in,out] mp pointer to the @p mutex_t object
+ *
+ * @api
+ */
+void osalMutexUnlock(mutex_t *mp) {
+
+ osalDbgCheck(mp != NULL);
+
+ *mp = 0;
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/osal/os-less/ARMCMx/osal.h b/ChibiOS_20.3.2/os/hal/osal/os-less/ARMCMx/osal.h
new file mode 100644
index 0000000..362a30c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/osal/os-less/ARMCMx/osal.h
@@ -0,0 +1,754 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file osal.h
+ * @brief OSAL module header.
+ *
+ * @addtogroup OSAL
+ * @{
+ */
+
+#ifndef OSAL_H
+#define OSAL_H
+
+#include
+#include
+#include
+
+#include "cmparams.h"
+
+#include "osalconf.h"
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Common constants
+ * @{
+ */
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+
+#define OSAL_SUCCESS false
+#define OSAL_FAILED true
+/** @} */
+
+/**
+ * @name Messages
+ * @{
+ */
+#define MSG_OK (msg_t)0
+#define MSG_RESET (msg_t)-1
+#define MSG_TIMEOUT (msg_t)-2
+#define MSG_WAIT (msg_t)-10
+/** @} */
+
+/**
+ * @name Special time constants
+ * @{
+ */
+#define TIME_IMMEDIATE ((sysinterval_t)0)
+#define TIME_INFINITE ((sysinterval_t)-1)
+/** @} */
+
+/**
+ * @name Systick modes.
+ * @{
+ */
+#define OSAL_ST_MODE_NONE 0
+#define OSAL_ST_MODE_PERIODIC 1
+#define OSAL_ST_MODE_FREERUNNING 2
+/** @} */
+
+/**
+ * @name Systick parameters.
+ * @{
+ */
+/**
+ * @brief Size in bits of the @p systick_t type.
+ */
+#define OSAL_ST_RESOLUTION 32
+
+/**
+ * @brief Systick mode required by the underlying OS.
+ */
+#define OSAL_ST_MODE OSAL_ST_MODE_PERIODIC
+/** @} */
+
+/**
+ * @name IRQ-related constants
+ * @{
+ */
+/**
+ * @brief Total priority levels.
+ */
+#define OSAL_IRQ_PRIORITY_LEVELS (1U << CORTEX_PRIORITY_BITS)
+
+/**
+ * @brief Highest IRQ priority for HAL drivers.
+ */
+#if (CORTEX_MODEL == 0) || defined(__DOXYGEN__)
+#define OSAL_IRQ_MAXIMUM_PRIORITY 0
+#else
+#define OSAL_IRQ_MAXIMUM_PRIORITY 1
+#endif
+
+/**
+ * @brief Converts from numeric priority to BASEPRI register value.
+ */
+#define OSAL_BASEPRI(priority) ((priority) << (8U - CORTEX_PRIORITY_BITS))
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Frequency in Hertz of the system tick.
+ */
+#if !defined(OSAL_ST_FREQUENCY) || defined(__DOXYGEN__)
+#define OSAL_ST_FREQUENCY 1000
+#endif
+
+/**
+ * @brief Enables OSAL assertions.
+ */
+#if !defined(OSAL_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)
+#define OSAL_DBG_ENABLE_ASSERTS FALSE
+#endif
+
+/**
+ * @brief Enables OSAL functions parameters checks.
+ */
+#if !defined(OSAL_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)
+#define OSAL_DBG_ENABLE_CHECKS FALSE
+#endif
+
+/**
+ * @brief OSAL initialization hook.
+ */
+#if !defined(OSAL_INIT_HOOK) || defined(__DOXYGEN__)
+#define OSAL_INIT_HOOK()
+#endif
+
+/**
+ * @brief Idle loop hook macro.
+ */
+#if !defined(OSAL_IDLE_HOOK) || defined(__DOXYGEN__)
+#define OSAL_IDLE_HOOK()
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a system status word.
+ */
+typedef uint32_t syssts_t;
+
+/**
+ * @brief Type of a message.
+ */
+typedef int32_t msg_t;
+
+/**
+ * @brief Type of system time counter.
+ */
+typedef uint32_t systime_t;
+
+/**
+ * @brief Type of system time interval.
+ */
+typedef uint32_t sysinterval_t;
+
+/**
+ * @brief Type of realtime counter.
+ */
+typedef uint32_t rtcnt_t;
+
+/**
+ * @brief Type of a thread.
+ * @note The content of this structure is not part of the API and should
+ * not be relied upon. Implementers may define this structure in
+ * an entirely different way.
+ */
+typedef struct {
+ volatile msg_t message;
+} thread_t;
+
+/**
+ * @brief Type of a thread reference.
+ */
+typedef thread_t * thread_reference_t;
+
+/**
+ * @brief Type of an event flags mask.
+ */
+typedef uint32_t eventflags_t;
+
+/**
+ * @brief Type of an event flags object.
+ * @note The content of this structure is not part of the API and should
+ * not be relied upon. Implementers may define this structure in
+ * an entirely different way.
+ * @note Retrieval and clearing of the flags are not defined in this
+ * API and are implementation-dependent.
+ */
+typedef struct event_source event_source_t;
+
+/**
+ * @brief Type of an event source callback.
+ * @note This type is not part of the OSAL API and is provided
+ * exclusively as an example and for convenience.
+ */
+typedef void (*eventcallback_t)(event_source_t *esp);
+
+/**
+ * @brief Events source object.
+ * @note The content of this structure is not part of the API and should
+ * not be relied upon. Implementers may define this structure in
+ * an entirely different way.
+ * @note Retrieval and clearing of the flags are not defined in this
+ * API and are implementation-dependent.
+ */
+struct event_source {
+ volatile eventflags_t flags; /**< @brief Stored event flags. */
+ eventcallback_t cb; /**< @brief Event source callback. */
+ void *param; /**< @brief User defined field. */
+};
+
+/**
+ * @brief Type of a mutex.
+ * @note If the OS does not support mutexes or there is no OS then them
+ * mechanism can be simulated.
+ */
+typedef uint32_t mutex_t;
+
+/**
+ * @brief Type of a thread queue.
+ * @details A thread queue is a queue of sleeping threads, queued threads
+ * can be dequeued one at time or all together.
+ * @note If the OSAL is implemented on a bare metal machine without RTOS
+ * then the queue can be implemented as a single thread reference.
+ */
+typedef struct {
+ thread_reference_t tr;
+} threads_queue_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @name Debug related macros
+ * @{
+ */
+/**
+ * @brief Condition assertion.
+ * @details If the condition check fails then the OSAL panics with a
+ * message and halts.
+ * @note The condition is tested only if the @p OSAL_ENABLE_ASSERTIONS
+ * switch is enabled.
+ * @note The remark string is not currently used except for putting a
+ * comment in the code about the assertion.
+ *
+ * @param[in] c the condition to be verified to be true
+ * @param[in] remark a remark string
+ *
+ * @api
+ */
+#define osalDbgAssert(c, remark) do { \
+ /*lint -save -e506 -e774 [2.1, 14.3] Can be a constant by design.*/ \
+ if (OSAL_DBG_ENABLE_ASSERTS != FALSE) { \
+ if (!(c)) { \
+ /*lint -restore*/ \
+ osalSysHalt(__func__); \
+ } \
+ } \
+} while (false)
+
+/**
+ * @brief Function parameters check.
+ * @details If the condition check fails then the OSAL panics and halts.
+ * @note The condition is tested only if the @p OSAL_ENABLE_CHECKS switch
+ * is enabled.
+ *
+ * @param[in] c the condition to be verified to be true
+ *
+ * @api
+ */
+#define osalDbgCheck(c) do { \
+ /*lint -save -e506 -e774 [2.1, 14.3] Can be a constant by design.*/ \
+ if (OSAL_DBG_ENABLE_CHECKS != FALSE) { \
+ if (!(c)) { \
+ /*lint -restore*/ \
+ osalSysHalt(__func__); \
+ } \
+ } \
+} while (false)
+
+/**
+ * @brief I-Class state check.
+ * @note Implementation is optional.
+ */
+#define osalDbgCheckClassI()
+
+/**
+ * @brief S-Class state check.
+ * @note Implementation is optional.
+ */
+#define osalDbgCheckClassS()
+/** @} */
+
+/**
+ * @name IRQ service routines wrappers
+ * @{
+ */
+/**
+ * @brief Priority level verification macro.
+ */
+#define OSAL_IRQ_IS_VALID_PRIORITY(n) \
+ (((n) >= OSAL_IRQ_MAXIMUM_PRIORITY) && ((n) < OSAL_IRQ_PRIORITY_LEVELS))
+
+/**
+ * @brief IRQ prologue code.
+ * @details This macro must be inserted at the start of all IRQ handlers.
+ */
+#define OSAL_IRQ_PROLOGUE()
+
+/**
+ * @brief IRQ epilogue code.
+ * @details This macro must be inserted at the end of all IRQ handlers.
+ */
+#define OSAL_IRQ_EPILOGUE()
+
+/**
+ * @brief IRQ handler function declaration.
+ * @details This macro hides the details of an ISR function declaration.
+ *
+ * @param[in] id a vector name as defined in @p vectors.s
+ */
+#define OSAL_IRQ_HANDLER(id) void id(void)
+/** @} */
+
+/**
+ * @name Time conversion utilities
+ * @{
+ */
+/**
+ * @brief Seconds to system ticks.
+ * @details Converts from seconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ *
+ * @param[in] secs number of seconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define OSAL_S2I(secs) \
+ ((sysinterval_t)((uint32_t)(secs) * (uint32_t)OSAL_ST_FREQUENCY))
+
+/**
+ * @brief Milliseconds to system ticks.
+ * @details Converts from milliseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ *
+ * @param[in] msecs number of milliseconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define OSAL_MS2I(msecs) \
+ ((sysinterval_t)((((((uint32_t)(msecs)) * \
+ ((uint32_t)OSAL_ST_FREQUENCY)) - 1UL) / 1000UL) + 1UL))
+
+/**
+ * @brief Microseconds to system ticks.
+ * @details Converts from microseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ *
+ * @param[in] usecs number of microseconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define OSAL_US2I(usecs) \
+ ((sysinterval_t)((((((uint32_t)(usecs)) * \
+ ((uint32_t)OSAL_ST_FREQUENCY)) - 1UL) / 1000000UL) + 1UL))
+/** @} */
+
+/**
+ * @name Time conversion utilities for the realtime counter
+ * @{
+ */
+/**
+ * @brief Seconds to realtime counter.
+ * @details Converts from seconds to realtime counter cycles.
+ * @note The macro assumes that @p freq >= @p 1.
+ *
+ * @param[in] freq clock frequency, in Hz, of the realtime counter
+ * @param[in] sec number of seconds
+ * @return The number of cycles.
+ *
+ * @api
+ */
+#define OSAL_S2RTC(freq, sec) ((freq) * (sec))
+
+/**
+ * @brief Milliseconds to realtime counter.
+ * @details Converts from milliseconds to realtime counter cycles.
+ * @note The result is rounded upward to the next millisecond boundary.
+ * @note The macro assumes that @p freq >= @p 1000.
+ *
+ * @param[in] freq clock frequency, in Hz, of the realtime counter
+ * @param[in] msec number of milliseconds
+ * @return The number of cycles.
+ *
+ * @api
+ */
+#define OSAL_MS2RTC(freq, msec) (rtcnt_t)((((freq) + 999UL) / 1000UL) * (msec))
+
+/**
+ * @brief Microseconds to realtime counter.
+ * @details Converts from microseconds to realtime counter cycles.
+ * @note The result is rounded upward to the next microsecond boundary.
+ * @note The macro assumes that @p freq >= @p 1000000.
+ *
+ * @param[in] freq clock frequency, in Hz, of the realtime counter
+ * @param[in] usec number of microseconds
+ * @return The number of cycles.
+ *
+ * @api
+ */
+#define OSAL_US2RTC(freq, usec) (rtcnt_t)((((freq) + 999999UL) / 1000000UL) * (usec))
+/** @} */
+
+/**
+ * @name Sleep macros using absolute time
+ * @{
+ */
+/**
+ * @brief Delays the invoking thread for the specified number of seconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system tick clock.
+ * @note The maximum specifiable value is implementation dependent.
+ *
+ * @param[in] secs time in seconds, must be different from zero
+ *
+ * @api
+ */
+#define osalThreadSleepSeconds(secs) osalThreadSleep(OSAL_S2I(secs))
+
+/**
+ * @brief Delays the invoking thread for the specified number of
+ * milliseconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system tick clock.
+ * @note The maximum specifiable value is implementation dependent.
+ *
+ * @param[in] msecs time in milliseconds, must be different from zero
+ *
+ * @api
+ */
+#define osalThreadSleepMilliseconds(msecs) osalThreadSleep(OSAL_MS2I(msecs))
+
+/**
+ * @brief Delays the invoking thread for the specified number of
+ * microseconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system tick clock.
+ * @note The maximum specifiable value is implementation dependent.
+ *
+ * @param[in] usecs time in microseconds, must be different from zero
+ *
+ * @api
+ */
+#define osalThreadSleepMicroseconds(usecs) osalThreadSleep(OSAL_US2I(usecs))
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+extern const char *osal_halt_msg;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void osalInit(void);
+ void osalSysHalt(const char *reason);
+ void osalSysPolledDelayX(rtcnt_t cycles);
+ void osalOsTimerHandlerI(void);
+ void osalOsRescheduleS(void);
+ systime_t osalOsGetSystemTimeX(void);
+ void osalThreadSleepS(sysinterval_t time);
+ void osalThreadSleep(sysinterval_t time);
+ msg_t osalThreadSuspendS(thread_reference_t *trp);
+ msg_t osalThreadSuspendTimeoutS(thread_reference_t *trp, sysinterval_t timeout);
+ void osalThreadResumeI(thread_reference_t *trp, msg_t msg);
+ void osalThreadResumeS(thread_reference_t *trp, msg_t msg);
+ msg_t osalThreadEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout);
+ void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg);
+ void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg);
+ void osalEventBroadcastFlagsI(event_source_t *esp, eventflags_t flags);
+ void osalEventBroadcastFlags(event_source_t *esp, eventflags_t flags);
+ void osalEventSetCallback(event_source_t *esp,
+ eventcallback_t cb,
+ void *param);
+ void osalMutexLock(mutex_t *mp);
+ void osalMutexUnlock(mutex_t *mp);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Disables interrupts globally.
+ *
+ * @special
+ */
+static inline void osalSysDisable(void) {
+
+ __disable_irq();
+}
+
+/**
+ * @brief Enables interrupts globally.
+ *
+ * @special
+ */
+static inline void osalSysEnable(void) {
+
+ __enable_irq();
+}
+
+/**
+ * @brief Enters a critical zone from thread context.
+ * @note This function cannot be used for reentrant critical zones.
+ *
+ * @special
+ */
+static inline void osalSysLock(void) {
+
+#if CORTEX_MODEL == 0
+ __disable_irq();
+#else
+ __set_BASEPRI(OSAL_BASEPRI(OSAL_IRQ_MAXIMUM_PRIORITY));
+#endif
+}
+
+/**
+ * @brief Leaves a critical zone from thread context.
+ * @note This function cannot be used for reentrant critical zones.
+ *
+ * @special
+ */
+static inline void osalSysUnlock(void) {
+
+#if CORTEX_MODEL == 0
+ __enable_irq();
+#else
+ __set_BASEPRI(0);
+#endif
+}
+
+/**
+ * @brief Enters a critical zone from ISR context.
+ * @note This function cannot be used for reentrant critical zones.
+ *
+ * @special
+ */
+static inline void osalSysLockFromISR(void) {
+
+#if CORTEX_MODEL == 0
+ __disable_irq();
+#else
+ __set_BASEPRI(OSAL_BASEPRI(OSAL_IRQ_MAXIMUM_PRIORITY));
+#endif
+}
+
+/**
+ * @brief Leaves a critical zone from ISR context.
+ * @note This function cannot be used for reentrant critical zones.
+ *
+ * @special
+ */
+static inline void osalSysUnlockFromISR(void) {
+
+#if CORTEX_MODEL == 0
+ __enable_irq();
+#else
+ __set_BASEPRI(0);
+#endif
+}
+
+/**
+ * @brief Returns the execution status and enters a critical zone.
+ * @details This functions enters into a critical zone and can be called
+ * from any context. Because its flexibility it is less efficient
+ * than @p chSysLock() which is preferable when the calling context
+ * is known.
+ * @post The system is in a critical zone.
+ *
+ * @return The previous system status, the encoding of this
+ * status word is architecture-dependent and opaque.
+ *
+ * @xclass
+ */
+static inline syssts_t osalSysGetStatusAndLockX(void) {
+ syssts_t sts;
+
+#if CORTEX_MODEL == 0
+ sts = (syssts_t)__get_PRIMASK();
+ __disable_irq();
+#else
+ sts = (syssts_t)__get_BASEPRI();
+ __set_BASEPRI(OSAL_BASEPRI(OSAL_IRQ_MAXIMUM_PRIORITY));
+#endif
+ return sts;
+}
+
+/**
+ * @brief Restores the specified execution status and leaves a critical zone.
+ * @note A call to @p chSchRescheduleS() is automatically performed
+ * if exiting the critical zone and if not in ISR context.
+ *
+ * @param[in] sts the system status to be restored.
+ *
+ * @xclass
+ */
+static inline void osalSysRestoreStatusX(syssts_t sts) {
+
+#if CORTEX_MODEL == 0
+ if ((sts & (syssts_t)1) == (syssts_t)0) {
+ __enable_irq();
+ }
+#else
+ __set_BASEPRI(sts);
+#endif
+}
+
+/**
+ * @brief Adds an interval to a system time returning a system time.
+ *
+ * @param[in] systime base system time
+ * @param[in] interval interval to be added
+ * @return The new system time.
+ *
+ * @xclass
+ */
+static inline systime_t osalTimeAddX(systime_t systime,
+ sysinterval_t interval) {
+
+ return systime + (systime_t)interval;
+}
+
+/**
+ * @brief Subtracts two system times returning an interval.
+ *
+ * @param[in] start first system time
+ * @param[in] end second system time
+ * @return The interval representing the time difference.
+ *
+ * @xclass
+ */
+static inline sysinterval_t osalTimeDiffX(systime_t start, systime_t end) {
+
+ return (sysinterval_t)((systime_t)(end - start));
+}
+
+/**
+ * @brief Checks if the specified time is within the specified time window.
+ * @note When start==end then the function returns always false because the
+ * time window has zero size.
+ * @note This function can be called from any context.
+ *
+ * @param[in] time the time to be verified
+ * @param[in] start the start of the time window (inclusive)
+ * @param[in] end the end of the time window (non inclusive)
+ * @retval true current time within the specified time window.
+ * @retval false current time not within the specified time window.
+ *
+ * @xclass
+ */
+static inline bool osalTimeIsInRangeX(systime_t time,
+ systime_t start,
+ systime_t end) {
+
+ return (bool)((systime_t)((systime_t)time - (systime_t)start) <
+ (systime_t)((systime_t)end - (systime_t)start));
+}
+
+/**
+ * @brief Initializes a threads queue object.
+ *
+ * @param[out] tqp pointer to the threads queue object
+ *
+ * @init
+ */
+static inline void osalThreadQueueObjectInit(threads_queue_t *tqp) {
+
+ osalDbgCheck(tqp != NULL);
+}
+
+/**
+ * @brief Initializes an event source object.
+ *
+ * @param[out] esp pointer to the event source object
+ *
+ * @init
+ */
+static inline void osalEventObjectInit(event_source_t *esp) {
+
+ osalDbgCheck(esp != NULL);
+
+ esp->flags = (eventflags_t)0;
+ esp->cb = NULL;
+ esp->param = NULL;
+}
+
+/**
+ * @brief Initializes s @p mutex_t object.
+ *
+ * @param[out] mp pointer to the @p mutex_t object
+ *
+ * @init
+ */
+static inline void osalMutexObjectInit(mutex_t *mp) {
+
+ osalDbgCheck(mp != NULL);
+
+ *mp = 0;
+}
+
+#endif /* OSAL_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/osal/os-less/ARMCMx/osal.mk b/ChibiOS_20.3.2/os/hal/osal/os-less/ARMCMx/osal.mk
new file mode 100644
index 0000000..e2cd7ad
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/osal/os-less/ARMCMx/osal.mk
@@ -0,0 +1,11 @@
+# OSAL files.
+OSALSRC += ${CHIBIOS}/os/hal/osal/os-less/ARMCMx/osal.c \
+ ${CHIBIOS}/os/hal/osal/lib/osal_vt.c
+
+# Required include directories
+OSALINC += ${CHIBIOS}/os/hal/osal/os-less/ARMCMx \
+ ${CHIBIOS}/os/hal/osal/lib
+
+# Shared variables
+ALLCSRC += $(OSALSRC)
+ALLINC += $(OSALINC)
diff --git a/ChibiOS_20.3.2/os/hal/osal/os-less/AVR/osal.c b/ChibiOS_20.3.2/os/hal/osal/os-less/AVR/osal.c
new file mode 100644
index 0000000..616beaf
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/osal/os-less/AVR/osal.c
@@ -0,0 +1,467 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file osal.c
+ * @brief OSAL module code.
+ *
+ * @addtogroup OSAL
+ * @{
+ */
+
+#include "osal.h"
+#include "osal_vt.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief Pointer to a halt error message.
+ * @note The message is meant to be retrieved by the debugger after the
+ * system halt caused by an unexpected error.
+ */
+const char *osal_halt_msg;
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+static void callback_timeout(void *p) {
+ osalSysLockFromISR();
+ osalThreadResumeI((thread_reference_t *)p, MSG_TIMEOUT);
+ osalSysUnlockFromISR();
+}
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief OSAL module initialization.
+ *
+ * @api
+ */
+void osalInit(void) {
+
+ vtInit();
+
+ OSAL_INIT_HOOK();
+}
+
+/**
+ * @brief System halt with error message.
+ *
+ * @param[in] reason the halt message pointer
+ *
+ * @api
+ */
+#if !defined(__DOXYGEN__)
+__attribute__((weak, noreturn))
+#endif
+void osalSysHalt(const char *reason) {
+
+ osalSysDisable();
+ osal_halt_msg = reason;
+ while (true) {
+ }
+}
+
+/**
+ * @brief Polled delay.
+ * @note The real delay is always few cycles in excess of the specified
+ * value.
+ *
+ * @param[in] cycles number of cycles
+ *
+ * @xclass
+ */
+void osalSysPolledDelayX(rtcnt_t cycles) {
+
+ (void)cycles;
+}
+
+/**
+ * @brief System timer handler.
+ * @details The handler is used for scheduling and Virtual Timers management.
+ *
+ * @iclass
+ */
+void osalOsTimerHandlerI(void) {
+
+ osalDbgCheckClassI();
+
+ vtDoTickI();
+}
+
+/**
+ * @brief Checks if a reschedule is required and performs it.
+ * @note I-Class functions invoked from thread context must not reschedule
+ * by themselves, an explicit reschedule using this function is
+ * required in this scenario.
+ * @note Not implemented in this simplified OSAL.
+ *
+ * @sclass
+ */
+void osalOsRescheduleS(void) {
+
+}
+
+/**
+ * @brief Current system time.
+ * @details Returns the number of system ticks since the @p osalInit()
+ * invocation.
+ * @note The counter can reach its maximum and then restart from zero.
+ * @note This function can be called from any context but its atomicity
+ * is not guaranteed on architectures whose word size is less than
+ * @p systime_t size.
+ *
+ * @return The system time in ticks.
+ *
+ * @xclass
+ */
+systime_t osalOsGetSystemTimeX(void) {
+
+ return vtlist.vt_systime;
+}
+
+/**
+ * @brief Suspends the invoking thread for the specified time.
+ *
+ * @param[in] time the delay in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE is allowed but interpreted as a
+ * normal time specification.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ *
+ * @sclass
+ */
+void osalThreadSleepS(systime_t time) {
+ virtual_timer_t vt;
+ thread_reference_t tr;
+
+ tr = NULL;
+ vtSetI(&vt, time, callback_timeout, (void *)&tr);
+ osalThreadSuspendS(&tr);
+}
+
+/**
+ * @brief Suspends the invoking thread for the specified time.
+ *
+ * @param[in] time the delay in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE is allowed but interpreted as a
+ * normal time specification.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ *
+ * @api
+ */
+void osalThreadSleep(systime_t time) {
+
+ osalSysLock();
+ osalThreadSleepS(time);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Sends the current thread sleeping and sets a reference variable.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @return The wake up message.
+ *
+ * @sclass
+ */
+msg_t osalThreadSuspendS(thread_reference_t *trp) {
+ thread_t self = {MSG_WAIT};
+
+ osalDbgCheck(trp != NULL);
+
+ *trp = &self;
+ while (self.message == MSG_WAIT) {
+ osalSysUnlock();
+ /* A state-changing interrupt could occur here and cause the loop to
+ terminate, an hook macro is executed while waiting.*/
+ OSAL_IDLE_HOOK();
+ osalSysLock();
+ }
+
+ return self.message;
+}
+
+/**
+ * @brief Sends the current thread sleeping and sets a reference variable.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] timeout the timeout in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE the thread enters an infinite sleep
+ * state.
+ * - @a TIME_IMMEDIATE the thread is not enqueued and
+ * the function returns @p MSG_TIMEOUT as if a timeout
+ * occurred.
+ * .
+ * @return The wake up message.
+ * @retval MSG_TIMEOUT if the operation timed out.
+ *
+ * @sclass
+ */
+msg_t osalThreadSuspendTimeoutS(thread_reference_t *trp, systime_t timeout) {
+ msg_t msg;
+ virtual_timer_t vt;
+
+ osalDbgCheck(trp != NULL);
+
+ if (TIME_INFINITE == timeout)
+ return osalThreadSuspendS(trp);
+
+ vtSetI(&vt, timeout, callback_timeout, (void *)trp);
+ msg = osalThreadSuspendS(trp);
+ if (vtIsArmedI(&vt))
+ vtResetI(&vt);
+
+ return msg;
+}
+
+/**
+ * @brief Wakes up a thread waiting on a thread reference object.
+ * @note This function must not reschedule because it can be called from
+ * ISR context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void osalThreadResumeI(thread_reference_t *trp, msg_t msg) {
+
+ osalDbgCheck(trp != NULL);
+
+ if (*trp != NULL) {
+ (*trp)->message = msg;
+ *trp = NULL;
+ }
+}
+
+/**
+ * @brief Wakes up a thread waiting on a thread reference object.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void osalThreadResumeS(thread_reference_t *trp, msg_t msg) {
+
+ osalDbgCheck(trp != NULL);
+
+ if (*trp != NULL) {
+ (*trp)->message = msg;
+ *trp = NULL;
+ }
+}
+
+/**
+ * @brief Enqueues the caller thread.
+ * @details The caller thread is enqueued and put to sleep until it is
+ * dequeued or the specified timeouts expires.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] timeout the timeout in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE the thread enters an infinite sleep
+ * state.
+ * - @a TIME_IMMEDIATE the thread is not enqueued and
+ * the function returns @p MSG_TIMEOUT as if a timeout
+ * occurred.
+ * .
+ * @return The message from @p osalQueueWakeupOneI() or
+ * @p osalQueueWakeupAllI() functions.
+ * @retval MSG_TIMEOUT if the thread has not been dequeued within the
+ * specified timeout or if the function has been
+ * invoked with @p TIME_IMMEDIATE as timeout
+ * specification.
+ *
+ * @sclass
+ */
+msg_t osalThreadEnqueueTimeoutS(threads_queue_t *tqp, systime_t timeout) {
+ msg_t msg;
+ virtual_timer_t vt;
+
+ osalDbgCheck(tqp != NULL);
+
+ if (TIME_IMMEDIATE == timeout)
+ return MSG_TIMEOUT;
+
+ tqp->tr = NULL;
+
+ if (TIME_INFINITE == timeout)
+ return osalThreadSuspendS(&tqp->tr);
+
+ vtSetI(&vt, timeout, callback_timeout, (void *)&tqp->tr);
+ msg = osalThreadSuspendS(&tqp->tr);
+ if (vtIsArmedI(&vt))
+ vtResetI(&vt);
+
+ return msg;
+}
+
+/**
+ * @brief Dequeues and wakes up one thread from the queue, if any.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg) {
+
+ osalDbgCheck(tqp != NULL);
+
+ osalThreadResumeI(&tqp->tr, msg);
+}
+
+/**
+ * @brief Dequeues and wakes up all threads from the queue.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg) {
+
+ osalDbgCheck(tqp != NULL);
+
+ osalThreadResumeI(&tqp->tr, msg);
+}
+
+/**
+ * @brief Add flags to an event source object.
+ *
+ * @param[in] esp pointer to the event flags object
+ * @param[in] flags flags to be ORed to the flags mask
+ *
+ * @iclass
+ */
+void osalEventBroadcastFlagsI(event_source_t *esp, eventflags_t flags) {
+
+ osalDbgCheck(esp != NULL);
+
+ esp->flags |= flags;
+ if (esp->cb != NULL) {
+ esp->cb(esp);
+ }
+}
+
+/**
+ * @brief Add flags to an event source object.
+ *
+ * @param[in] esp pointer to the event flags object
+ * @param[in] flags flags to be ORed to the flags mask
+ *
+ * @iclass
+ */
+void osalEventBroadcastFlags(event_source_t *esp, eventflags_t flags) {
+
+ osalDbgCheck(esp != NULL);
+
+ osalSysLock();
+ osalEventBroadcastFlagsI(esp, flags);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Event callback setup.
+ * @note The callback is invoked from ISR context and can
+ * only invoke I-Class functions. The callback is meant
+ * to wakeup the task that will handle the event by
+ * calling @p osalEventGetAndClearFlagsI().
+ * @note This function is not part of the OSAL API and is provided
+ * exclusively as an example and for convenience.
+ *
+ * @param[in] esp pointer to the event flags object
+ * @param[in] cb pointer to the callback function
+ * @param[in] param parameter to be passed to the callback function
+ *
+ * @api
+ */
+void osalEventSetCallback(event_source_t *esp,
+ eventcallback_t cb,
+ void *param) {
+
+ osalDbgCheck(esp != NULL);
+
+ esp->cb = cb;
+ esp->param = param;
+}
+
+/**
+ * @brief Locks the specified mutex.
+ * @post The mutex is locked and inserted in the per-thread stack of owned
+ * mutexes.
+ *
+ * @param[in,out] mp pointer to the @p mutex_t object
+ *
+ * @api
+ */
+void osalMutexLock(mutex_t *mp) {
+
+ osalDbgCheck(mp != NULL);
+
+ *mp = 1;
+}
+
+/**
+ * @brief Unlocks the specified mutex.
+ * @note The HAL guarantees to release mutex in reverse lock order. The
+ * mutex being unlocked is guaranteed to be the last locked mutex
+ * by the invoking thread.
+ * The implementation can rely on this behavior and eventually
+ * ignore the @p mp parameter which is supplied in order to support
+ * those OSes not supporting a stack of the owned mutexes.
+ *
+ * @param[in,out] mp pointer to the @p mutex_t object
+ *
+ * @api
+ */
+void osalMutexUnlock(mutex_t *mp) {
+
+ osalDbgCheck(mp != NULL);
+
+ *mp = 0;
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/osal/os-less/AVR/osal.h b/ChibiOS_20.3.2/os/hal/osal/os-less/AVR/osal.h
new file mode 100644
index 0000000..79b4046
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/osal/os-less/AVR/osal.h
@@ -0,0 +1,677 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file osal.h
+ * @brief OSAL module header.
+ *
+ * @addtogroup OSAL
+ * @{
+ */
+
+#ifndef OSAL_H
+#define OSAL_H
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include "osalconf.h"
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Common constants
+ * @{
+ */
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+
+#define OSAL_SUCCESS false
+#define OSAL_FAILED true
+/** @} */
+
+/**
+ * @name Messages
+ * @{
+ */
+#define MSG_OK (msg_t)0
+#define MSG_RESET (msg_t)-1
+#define MSG_TIMEOUT (msg_t)-2
+#define MSG_WAIT (msg_t)-10
+/** @} */
+
+/**
+ * @name Special time constants
+ * @{
+ */
+#define TIME_IMMEDIATE ((systime_t)0)
+#define TIME_INFINITE ((systime_t)-1)
+/** @} */
+
+/**
+ * @name Systick modes.
+ * @{
+ */
+#define OSAL_ST_MODE_NONE 0
+#define OSAL_ST_MODE_PERIODIC 1
+#define OSAL_ST_MODE_FREERUNNING 2
+/** @} */
+
+/**
+ * @name Systick parameters.
+ * @{
+ */
+/**
+ * @brief Size in bits of the @p systick_t type.
+ */
+#define OSAL_ST_RESOLUTION 32
+
+/**
+ * @brief Systick mode required by the underlying OS.
+ */
+#define OSAL_ST_MODE OSAL_ST_MODE_PERIODIC
+/** @} */
+
+/**
+ * @brief ROM constant modifier.
+ * @note It is set to use the "const" keyword in this port.
+ */
+#define ROMCONST const
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Frequency in Hertz of the system tick.
+ */
+#if !defined(OSAL_ST_FREQUENCY) || defined(__DOXYGEN__)
+#define OSAL_ST_FREQUENCY 1000
+#endif
+
+/**
+ * @brief Enables OSAL assertions.
+ */
+#if !defined(OSAL_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)
+#define OSAL_DBG_ENABLE_ASSERTS FALSE
+#endif
+
+/**
+ * @brief Enables OSAL functions parameters checks.
+ */
+#if !defined(OSAL_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)
+#define OSAL_DBG_ENABLE_CHECKS FALSE
+#endif
+
+/**
+ * @brief OSAL initialization hook.
+ */
+#if !defined(OSAL_INIT_HOOK) || defined(__DOXYGEN__)
+#define OSAL_INIT_HOOK()
+#endif
+
+/**
+ * @brief Idle loop hook macro.
+ */
+#if !defined(OSAL_IDLE_HOOK) || defined(__DOXYGEN__)
+#define OSAL_IDLE_HOOK()
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a system status word.
+ */
+typedef uint8_t syssts_t;
+
+/**
+ * @brief Type of a message.
+ */
+typedef int16_t msg_t;
+
+/**
+ * @brief Type of system time counter.
+ */
+typedef uint32_t systime_t;
+
+/**
+ * @brief Type of realtime counter.
+ */
+typedef uint32_t rtcnt_t;
+
+/**
+ * @brief Type of a thread.
+ * @note The content of this structure is not part of the API and should
+ * not be relied upon. Implementers may define this structure in
+ * an entirely different way.
+ */
+typedef struct {
+ volatile msg_t message;
+} thread_t;
+
+/**
+ * @brief Type of a thread reference.
+ */
+typedef thread_t * thread_reference_t;
+
+/**
+ * @brief Type of an event flags object.
+ * @note The content of this structure is not part of the API and should
+ * not be relied upon. Implementers may define this structure in
+ * an entirely different way.
+ * @note Retrieval and clearing of the flags are not defined in this
+ * API and are implementation-dependent.
+ */
+typedef struct event_source event_source_t;
+
+/**
+ * @brief Type of an event source callback.
+ * @note This type is not part of the OSAL API and is provided
+ * exclusively as an example and for convenience.
+ */
+typedef void (*eventcallback_t)(event_source_t *esp);
+
+/**
+ * @brief Type of an event flags mask.
+ */
+typedef uint8_t eventflags_t;
+
+/**
+ * @brief Events source object.
+ * @note The content of this structure is not part of the API and should
+ * not be relied upon. Implementers may define this structure in
+ * an entirely different way.
+ * @note Retrieval and clearing of the flags are not defined in this
+ * API and are implementation-dependent.
+ */
+struct event_source {
+ volatile eventflags_t flags; /**< @brief Stored event flags. */
+ eventcallback_t cb; /**< @brief Event source callback. */
+ void *param; /**< @brief User defined field. */
+};
+
+/**
+ * @brief Type of a mutex.
+ * @note If the OS does not support mutexes or there is no OS then them
+ * mechanism can be simulated.
+ */
+typedef uint8_t mutex_t;
+
+/**
+ * @brief Type of a thread queue.
+ * @details A thread queue is a queue of sleeping threads, queued threads
+ * can be dequeued one at time or all together.
+ * @note If the OSAL is implemented on a bare metal machine without RTOS
+ * then the queue can be implemented as a single thread reference.
+ */
+typedef struct {
+ thread_reference_t tr;
+} threads_queue_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @name Debug related macros
+ * @{
+ */
+/**
+ * @brief Condition assertion.
+ * @details If the condition check fails then the OSAL panics with a
+ * message and halts.
+ * @note The condition is tested only if the @p OSAL_ENABLE_ASSERTIONS
+ * switch is enabled.
+ * @note The remark string is not currently used except for putting a
+ * comment in the code about the assertion.
+ *
+ * @param[in] c the condition to be verified to be true
+ * @param[in] remark a remark string
+ *
+ * @api
+ */
+#define osalDbgAssert(c, remark) do { \
+ /*lint -save -e506 -e774 [2.1, 14.3] Can be a constant by design.*/ \
+ if (OSAL_DBG_ENABLE_ASSERTS != FALSE) { \
+ if (!(c)) { \
+ /*lint -restore*/ \
+ osalSysHalt(__func__); \
+ } \
+ } \
+} while (false)
+
+/**
+ * @brief Function parameters check.
+ * @details If the condition check fails then the OSAL panics and halts.
+ * @note The condition is tested only if the @p OSAL_ENABLE_CHECKS switch
+ * is enabled.
+ *
+ * @param[in] c the condition to be verified to be true
+ *
+ * @api
+ */
+#define osalDbgCheck(c) do { \
+ /*lint -save -e506 -e774 [2.1, 14.3] Can be a constant by design.*/ \
+ if (OSAL_DBG_ENABLE_CHECKS != FALSE) { \
+ if (!(c)) { \
+ /*lint -restore*/ \
+ osalSysHalt(__func__); \
+ } \
+ } \
+} while (false)
+
+/**
+ * @brief I-Class state check.
+ * @note Implementation is optional.
+ */
+#define osalDbgCheckClassI()
+
+/**
+ * @brief S-Class state check.
+ * @note Implementation is optional.
+ */
+#define osalDbgCheckClassS()
+/** @} */
+
+/**
+ * @name IRQ service routines wrappers
+ * @{
+ */
+/**
+ * @brief IRQ prologue code.
+ * @details This macro must be inserted at the start of all IRQ handlers.
+ */
+#define OSAL_IRQ_PROLOGUE()
+
+/**
+ * @brief IRQ epilogue code.
+ * @details This macro must be inserted at the end of all IRQ handlers.
+ */
+#define OSAL_IRQ_EPILOGUE()
+
+/**
+ * @brief IRQ handler function declaration.
+ * @details This macro hides the details of an ISR function declaration.
+ *
+ * @param[in] id a vector name as defined in @p vectors.s
+ */
+#define OSAL_IRQ_HANDLER(id) ISR(id)
+/** @} */
+
+/**
+ * @name Time conversion utilities
+ * @{
+ */
+/**
+ * @brief Seconds to system ticks.
+ * @details Converts from seconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ *
+ * @param[in] sec number of seconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define OSAL_S2ST(sec) \
+ ((systime_t)((uint32_t)(sec) * (uint32_t)OSAL_ST_FREQUENCY))
+
+/**
+ * @brief Milliseconds to system ticks.
+ * @details Converts from milliseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ *
+ * @param[in] msec number of milliseconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define OSAL_MS2ST(msec) \
+ ((systime_t)((((uint32_t)(msec)) * \
+ ((uint32_t)OSAL_ST_FREQUENCY) + 999UL) / 1000UL))
+
+/**
+ * @brief Microseconds to system ticks.
+ * @details Converts from microseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ *
+ * @param[in] usec number of microseconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define OSAL_US2ST(usec) \
+ ((systime_t)((((uint32_t)(usec)) * \
+ ((uint32_t)OSAL_ST_FREQUENCY) + 999999UL) / 1000000UL))
+/** @} */
+
+/**
+ * @name Time conversion utilities for the realtime counter
+ * @{
+ */
+/**
+ * @brief Seconds to realtime counter.
+ * @details Converts from seconds to realtime counter cycles.
+ * @note The macro assumes that @p freq >= @p 1.
+ *
+ * @param[in] freq clock frequency, in Hz, of the realtime counter
+ * @param[in] sec number of seconds
+ * @return The number of cycles.
+ *
+ * @api
+ */
+#define OSAL_S2RTC(freq, sec) ((freq) * (sec))
+
+/**
+ * @brief Milliseconds to realtime counter.
+ * @details Converts from milliseconds to realtime counter cycles.
+ * @note The result is rounded upward to the next millisecond boundary.
+ * @note The macro assumes that @p freq >= @p 1000.
+ *
+ * @param[in] freq clock frequency, in Hz, of the realtime counter
+ * @param[in] msec number of milliseconds
+ * @return The number of cycles.
+ *
+ * @api
+ */
+#define OSAL_MS2RTC(freq, msec) (rtcnt_t)((((freq) + 999UL) / 1000UL) * (msec))
+
+/**
+ * @brief Microseconds to realtime counter.
+ * @details Converts from microseconds to realtime counter cycles.
+ * @note The result is rounded upward to the next microsecond boundary.
+ * @note The macro assumes that @p freq >= @p 1000000.
+ *
+ * @param[in] freq clock frequency, in Hz, of the realtime counter
+ * @param[in] usec number of microseconds
+ * @return The number of cycles.
+ *
+ * @api
+ */
+#define OSAL_US2RTC(freq, usec) (rtcnt_t)((((freq) + 999999UL) / 1000000UL) * (usec))
+/** @} */
+
+/**
+ * @name Sleep macros using absolute time
+ * @{
+ */
+/**
+ * @brief Delays the invoking thread for the specified number of seconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system tick clock.
+ * @note The maximum specifiable value is implementation dependent.
+ *
+ * @param[in] sec time in seconds, must be different from zero
+ *
+ * @api
+ */
+#define osalThreadSleepSeconds(sec) osalThreadSleep(OSAL_S2ST(sec))
+
+/**
+ * @brief Delays the invoking thread for the specified number of
+ * milliseconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system tick clock.
+ * @note The maximum specifiable value is implementation dependent.
+ *
+ * @param[in] msec time in milliseconds, must be different from zero
+ *
+ * @api
+ */
+#define osalThreadSleepMilliseconds(msec) osalThreadSleep(OSAL_MS2ST(msec))
+
+/**
+ * @brief Delays the invoking thread for the specified number of
+ * microseconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system tick clock.
+ * @note The maximum specifiable value is implementation dependent.
+ *
+ * @param[in] usec time in microseconds, must be different from zero
+ *
+ * @api
+ */
+#define osalThreadSleepMicroseconds(usec) osalThreadSleep(OSAL_US2ST(usec))
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+extern const char *osal_halt_msg;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void osalInit(void);
+ void osalSysHalt(const char *reason);
+ void osalSysPolledDelayX(rtcnt_t cycles);
+ void osalOsTimerHandlerI(void);
+ void osalOsRescheduleS(void);
+ systime_t osalOsGetSystemTimeX(void);
+ void osalThreadSleepS(systime_t time);
+ void osalThreadSleep(systime_t time);
+ msg_t osalThreadSuspendS(thread_reference_t *trp);
+ msg_t osalThreadSuspendTimeoutS(thread_reference_t *trp, systime_t timeout);
+ void osalThreadResumeI(thread_reference_t *trp, msg_t msg);
+ void osalThreadResumeS(thread_reference_t *trp, msg_t msg);
+ msg_t osalThreadEnqueueTimeoutS(threads_queue_t *tqp, systime_t timeout);
+ void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg);
+ void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg);
+ void osalEventBroadcastFlagsI(event_source_t *esp, eventflags_t flags);
+ void osalEventBroadcastFlags(event_source_t *esp, eventflags_t flags);
+ void osalEventSetCallback(event_source_t *esp,
+ eventcallback_t cb,
+ void *param);
+ void osalMutexLock(mutex_t *mp);
+ void osalMutexUnlock(mutex_t *mp);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Disables interrupts globally.
+ *
+ * @special
+ */
+static inline void osalSysDisable(void) {
+
+ asm volatile ("cli" : : : "memory");
+}
+
+/**
+ * @brief Enables interrupts globally.
+ *
+ * @special
+ */
+static inline void osalSysEnable(void) {
+
+ asm volatile ("sei" : : : "memory");
+ asm volatile ("nop");
+}
+
+/**
+ * @brief Enters a critical zone from thread context.
+ * @note This function cannot be used for reentrant critical zones.
+ *
+ * @special
+ */
+static inline void osalSysLock(void) {
+
+ asm volatile ("cli" : : : "memory");
+}
+
+/**
+ * @brief Leaves a critical zone from thread context.
+ * @note This function cannot be used for reentrant critical zones.
+ *
+ * @special
+ */
+static inline void osalSysUnlock(void) {
+
+ asm volatile ("sei" : : : "memory");
+ asm volatile ("nop");
+}
+
+/**
+ * @brief Enters a critical zone from ISR context.
+ * @note This function cannot be used for reentrant critical zones.
+ * @note This function is empty in this port.
+ *
+ * @special
+ */
+static inline void osalSysLockFromISR(void) {
+
+}
+
+/**
+ * @brief Leaves a critical zone from ISR context.
+ * @note This function cannot be used for reentrant critical zones.
+ * @note This function is empty in this port.
+ *
+ * @special
+ */
+static inline void osalSysUnlockFromISR(void) {
+
+}
+
+/**
+ * @brief Returns the execution status and enters a critical zone.
+ * @details This functions enters into a critical zone and can be called
+ * from any context. Because its flexibility it is less efficient
+ * than @p chSysLock() which is preferable when the calling context
+ * is known.
+ * @post The system is in a critical zone.
+ *
+ * @return The previous system status, the encoding of this
+ * status word is architecture-dependent and opaque.
+ *
+ * @xclass
+ */
+static inline syssts_t osalSysGetStatusAndLockX(void) {
+ syssts_t sts;
+
+ sts = SREG;
+ asm volatile ("cli" : : : "memory");
+
+ return sts;
+}
+
+/**
+ * @brief Restores the specified execution status and leaves a critical zone.
+ * @note A call to @p chSchRescheduleS() is automatically performed
+ * if exiting the critical zone and if not in ISR context.
+ *
+ * @param[in] sts the system status to be restored.
+ *
+ * @xclass
+ */
+static inline void osalSysRestoreStatusX(syssts_t sts) {
+
+ if ((sts & 0x80) != 0) {
+ asm volatile ("sei" : : : "memory");
+ asm volatile ("nop");
+ }
+}
+
+/**
+ * @brief Checks if the specified time is within the specified time window.
+ * @note When start==end then the function returns always false because the
+ * time window has zero size.
+ * @note This function can be called from any context.
+ *
+ * @param[in] time the time to be verified
+ * @param[in] start the start of the time window (inclusive)
+ * @param[in] end the end of the time window (non inclusive)
+ * @retval true current time within the specified time window.
+ * @retval false current time not within the specified time window.
+ *
+ * @xclass
+ */
+static inline bool osalOsIsTimeWithinX(systime_t time,
+ systime_t start,
+ systime_t end) {
+
+ return (bool)((time - start) < (end - start));
+}
+
+/**
+ * @brief Initializes a threads queue object.
+ *
+ * @param[out] tqp pointer to the threads queue object
+ *
+ * @init
+ */
+static inline void osalThreadQueueObjectInit(threads_queue_t *tqp) {
+
+ osalDbgCheck(tqp != NULL);
+
+ (void)tqp;
+}
+
+/**
+ * @brief Initializes an event flags object.
+ *
+ * @param[out] esp pointer to the event flags object
+ *
+ * @init
+ */
+static inline void osalEventObjectInit(event_source_t *esp) {
+
+ osalDbgCheck(esp != NULL);
+
+ esp->flags = (eventflags_t)0;
+ esp->cb = NULL;
+ esp->param = NULL;
+}
+
+/**
+ * @brief Initializes s @p mutex_t object.
+ *
+ * @param[out] mp pointer to the @p mutex_t object
+ *
+ * @init
+ */
+static inline void osalMutexObjectInit(mutex_t *mp) {
+
+ osalDbgCheck(mp != NULL);
+
+ *mp = 0;
+}
+
+#endif /* OSAL_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/osal/os-less/AVR/osal.mk b/ChibiOS_20.3.2/os/hal/osal/os-less/AVR/osal.mk
new file mode 100644
index 0000000..4f929d7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/osal/os-less/AVR/osal.mk
@@ -0,0 +1,9 @@
+# OSAL files.
+OSALSRC += ${CHIBIOS}/os/hal/osal/os-less/AVR/osal.c
+
+# Required include directories
+OSALINC += ${CHIBIOS}/os/hal/osal/os-less/AVR
+
+# Shared variables
+ALLCSRC += $(OSALSRC)
+ALLINC += $(OSALINC)
diff --git a/ChibiOS_20.3.2/os/hal/osal/rt-nil/osal.c b/ChibiOS_20.3.2/os/hal/osal/rt-nil/osal.c
new file mode 100644
index 0000000..7f4103b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/osal/rt-nil/osal.c
@@ -0,0 +1,51 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file osal.c
+ * @brief OSAL module code.
+ *
+ * @addtogroup OSAL
+ * @{
+ */
+
+#include "osal.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/osal/rt-nil/osal.h b/ChibiOS_20.3.2/os/hal/osal/rt-nil/osal.h
new file mode 100644
index 0000000..73e8e3f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/osal/rt-nil/osal.h
@@ -0,0 +1,1028 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file osal.h
+ * @brief OSAL module header.
+ *
+ * @addtogroup OSAL
+ * @{
+ */
+
+#ifndef OSAL_H
+#define OSAL_H
+
+#include
+#include
+#include
+
+#include "ch.h"
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Common constants
+ * @{
+ */
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+
+#define OSAL_SUCCESS false
+#define OSAL_FAILED true
+/** @} */
+
+#if 0
+/**
+ * @name Messages
+ * @{
+ */
+#define MSG_OK (msg_t)0
+#define MSG_TIMEOUT (msg_t)-1
+#define MSG_RESET (msg_t)-2
+/** @} */
+#endif
+
+#if 0
+/**
+ * @name Special time constants
+ * @{
+ */
+#define TIME_IMMEDIATE ((sysinterval_t)0)
+#define TIME_INFINITE ((sysinterval_t)-1)
+/** @} */
+#endif
+
+/**
+ * @name Systick modes.
+ * @{
+ */
+#define OSAL_ST_MODE_NONE 0
+#define OSAL_ST_MODE_PERIODIC 1
+#define OSAL_ST_MODE_FREERUNNING 2
+/** @} */
+
+/**
+ * @name Systick parameters.
+ * @{
+ */
+/**
+ * @brief Size in bits of the @p systick_t type.
+ */
+#define OSAL_ST_RESOLUTION CH_CFG_ST_RESOLUTION
+
+/**
+ * @brief Required systick frequency or resolution.
+ */
+#define OSAL_ST_FREQUENCY CH_CFG_ST_FREQUENCY
+
+/**
+ * @brief Systick mode required by the underlying OS.
+ */
+#if (CH_CFG_ST_TIMEDELTA == 0) || defined(__DOXYGEN__)
+#define OSAL_ST_MODE OSAL_ST_MODE_PERIODIC
+#else
+#define OSAL_ST_MODE OSAL_ST_MODE_FREERUNNING
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !(OSAL_ST_MODE == OSAL_ST_MODE_NONE) && \
+ !(OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) && \
+ !(OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING)
+#error "invalid OSAL_ST_MODE setting in osal.h"
+#endif
+
+#if (OSAL_ST_RESOLUTION != 16) && (OSAL_ST_RESOLUTION != 32)
+#error "invalid OSAL_ST_RESOLUTION, must be 16 or 32"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+#if 0
+/**
+ * @brief Type of a system status word.
+ */
+typedef uint32_t syssts_t;
+#endif
+
+#if 0
+/**
+ * @brief Type of a message.
+ */
+typedef int32_t msg_t;
+#endif
+
+#if 0
+/**
+ * @brief Type of system time counter.
+ */
+typedef uint32_t systime_t;
+#endif
+
+#if 0
+/**
+ * @brief Type of system time interval.
+ */
+typedef uint32_t sysinterval_t;
+#endif
+
+#if 0
+/**
+ * @brief Type of realtime counter.
+ */
+typedef uint32_t rtcnt_t;
+#endif
+
+#if 0
+/**
+ * @brief Type of a thread reference.
+ */
+typedef thread_t * thread_reference_t;
+#endif
+
+#if 0
+/**
+ * @brief Type of an event flags mask.
+ */
+typedef uint32_t eventflags_t;
+#endif
+
+#if (CH_CFG_USE_EVENTS == FALSE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of an event flags object.
+ * @note The content of this structure is not part of the API and should
+ * not be relied upon. Implementers may define this structure in
+ * an entirely different way.
+ * @note Retrieval and clearing of the flags are not defined in this
+ * API and are implementation-dependent.
+ */
+typedef struct event_source event_source_t;
+
+/**
+ * @brief Type of an event source callback.
+ * @note This type is not part of the OSAL API and is provided
+ * exclusively as an example and for convenience.
+ */
+typedef void (*eventcallback_t)(event_source_t *esp);
+
+/**
+ * @brief Events source object.
+ * @note The content of this structure is not part of the API and should
+ * not be relied upon. Implementers may define this structure in
+ * an entirely different way.
+ * @note Retrieval and clearing of the flags are not defined in this
+ * API and are implementation-dependent.
+ */
+struct event_source {
+ volatile eventflags_t flags; /**< @brief Stored event flags. */
+ eventcallback_t cb; /**< @brief Event source callback. */
+ void *param; /**< @brief User defined field. */
+};
+#endif /* CH_CFG_USE_EVENTS == FALSE */
+
+/**
+ * @brief Type of a mutex.
+ * @note If the OS does not support mutexes or there is no OS then the
+ * mechanism can be simulated.
+ */
+#if CH_CFG_USE_MUTEXES || defined(__DOXYGEN__)
+#elif CH_CFG_USE_SEMAPHORES
+typedef semaphore_t mutex_t;
+#else
+typedef uint32_t mutex_t;
+#endif
+
+#if 0
+/**
+ * @brief Type of a thread queue.
+ * @details A thread queue is a queue of sleeping threads, queued threads
+ * can be dequeued one at time or all together.
+ * @note In this implementation it is implemented as a single reference
+ * because there are no real threads.
+ */
+typedef struct {
+ thread_reference_t tr;
+} threads_queue_t;
+#endif
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @name Debug related macros
+ * @{
+ */
+/**
+ * @brief Condition assertion.
+ * @details If the condition check fails then the OSAL panics with a
+ * message and halts.
+ * @note The condition is tested only if the @p OSAL_ENABLE_ASSERTIONS
+ * switch is enabled.
+ * @note The remark string is not currently used except for putting a
+ * comment in the code about the assertion.
+ *
+ * @param[in] c the condition to be verified to be true
+ * @param[in] remark a remark string
+ *
+ * @api
+ */
+#define osalDbgAssert(c, remark) chDbgAssert(c, remark)
+
+/**
+ * @brief Function parameters check.
+ * @details If the condition check fails then the OSAL panics and halts.
+ * @note The condition is tested only if the @p OSAL_ENABLE_CHECKS switch
+ * is enabled.
+ *
+ * @param[in] c the condition to be verified to be true
+ *
+ * @api
+ */
+#define osalDbgCheck(c) chDbgCheck(c)
+
+/**
+ * @brief I-Class state check.
+ * @note Not implemented in this simplified OSAL.
+ */
+#define osalDbgCheckClassI() chDbgCheckClassI()
+
+/**
+ * @brief S-Class state check.
+ * @note Not implemented in this simplified OSAL.
+ */
+#define osalDbgCheckClassS() chDbgCheckClassS()
+/** @} */
+
+/**
+ * @name IRQ service routines wrappers
+ * @{
+ */
+/**
+ * @brief Priority level verification macro.
+ */
+#define OSAL_IRQ_IS_VALID_PRIORITY(n) CH_IRQ_IS_VALID_KERNEL_PRIORITY(n)
+
+/**
+ * @brief IRQ prologue code.
+ * @details This macro must be inserted at the start of all IRQ handlers.
+ */
+#define OSAL_IRQ_PROLOGUE() CH_IRQ_PROLOGUE()
+
+/**
+ * @brief IRQ epilogue code.
+ * @details This macro must be inserted at the end of all IRQ handlers.
+ */
+#define OSAL_IRQ_EPILOGUE() CH_IRQ_EPILOGUE()
+
+/**
+ * @brief IRQ handler function declaration.
+ * @details This macro hides the details of an ISR function declaration.
+ *
+ * @param[in] id a vector name as defined in @p vectors.s
+ */
+#define OSAL_IRQ_HANDLER(id) CH_IRQ_HANDLER(id)
+/** @} */
+
+/**
+ * @name Time conversion utilities
+ * @{
+ */
+/**
+ * @brief Seconds to system ticks.
+ * @details Converts from seconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ *
+ * @param[in] secs number of seconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define OSAL_S2I(secs) TIME_S2I(secs)
+
+/**
+ * @brief Milliseconds to system ticks.
+ * @details Converts from milliseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ *
+ * @param[in] msecs number of milliseconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define OSAL_MS2I(msecs) TIME_MS2I(msecs)
+
+/**
+ * @brief Microseconds to system ticks.
+ * @details Converts from microseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ *
+ * @param[in] usecs number of microseconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define OSAL_US2I(usecs) TIME_US2I(usecs)
+/** @} */
+
+/**
+ * @name Time conversion utilities for the realtime counter
+ * @{
+ */
+/**
+ * @brief Seconds to realtime counter.
+ * @details Converts from seconds to realtime counter cycles.
+ * @note The macro assumes that @p freq >= @p 1.
+ *
+ * @param[in] freq clock frequency, in Hz, of the realtime counter
+ * @param[in] sec number of seconds
+ * @return The number of cycles.
+ *
+ * @api
+ */
+#define OSAL_S2RTC(freq, sec) S2RTC(freq, sec)
+
+/**
+ * @brief Milliseconds to realtime counter.
+ * @details Converts from milliseconds to realtime counter cycles.
+ * @note The result is rounded upward to the next millisecond boundary.
+ * @note The macro assumes that @p freq >= @p 1000.
+ *
+ * @param[in] freq clock frequency, in Hz, of the realtime counter
+ * @param[in] msec number of milliseconds
+ * @return The number of cycles.
+ *
+ * @api
+ */
+#define OSAL_MS2RTC(freq, msec) MS2RTC(freq, msec)
+
+/**
+ * @brief Microseconds to realtime counter.
+ * @details Converts from microseconds to realtime counter cycles.
+ * @note The result is rounded upward to the next microsecond boundary.
+ * @note The macro assumes that @p freq >= @p 1000000.
+ *
+ * @param[in] freq clock frequency, in Hz, of the realtime counter
+ * @param[in] usec number of microseconds
+ * @return The number of cycles.
+ *
+ * @api
+ */
+#define OSAL_US2RTC(freq, usec) US2RTC(freq, usec)
+/** @} */
+
+/**
+ * @name Sleep macros using absolute time
+ * @{
+ */
+/**
+ * @brief Delays the invoking thread for the specified number of seconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system tick clock.
+ * @note The maximum specifiable value is implementation dependent.
+ *
+ * @param[in] secs time in seconds, must be different from zero
+ *
+ * @api
+ */
+#define osalThreadSleepSeconds(secs) osalThreadSleep(OSAL_S2I(secs))
+
+/**
+ * @brief Delays the invoking thread for the specified number of
+ * milliseconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system tick clock.
+ * @note The maximum specifiable value is implementation dependent.
+ *
+ * @param[in] msecs time in milliseconds, must be different from zero
+ *
+ * @api
+ */
+#define osalThreadSleepMilliseconds(msecs) osalThreadSleep(OSAL_MS2I(msecs))
+
+/**
+ * @brief Delays the invoking thread for the specified number of
+ * microseconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system tick clock.
+ * @note The maximum specifiable value is implementation dependent.
+ *
+ * @param[in] usecs time in microseconds, must be different from zero
+ *
+ * @api
+ */
+#define osalThreadSleepMicroseconds(usecs) osalThreadSleep(OSAL_US2I(usecs))
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief OSAL module initialization.
+ *
+ * @api
+ */
+static inline void osalInit(void) {
+
+}
+
+/**
+ * @brief System halt with error message.
+ *
+ * @param[in] reason the halt message pointer
+ *
+ * @api
+ */
+static inline void osalSysHalt(const char *reason) {
+
+ chSysHalt(reason);
+}
+
+/**
+ * @brief Disables interrupts globally.
+ *
+ * @special
+ */
+static inline void osalSysDisable(void) {
+
+ chSysDisable();
+}
+
+/**
+ * @brief Enables interrupts globally.
+ *
+ * @special
+ */
+static inline void osalSysEnable(void) {
+
+ chSysEnable();
+}
+
+/**
+ * @brief Enters a critical zone from thread context.
+ * @note This function cannot be used for reentrant critical zones.
+ *
+ * @special
+ */
+static inline void osalSysLock(void) {
+
+ chSysLock();
+}
+
+/**
+ * @brief Leaves a critical zone from thread context.
+ * @note This function cannot be used for reentrant critical zones.
+ *
+ * @special
+ */
+static inline void osalSysUnlock(void) {
+
+ chSysUnlock();
+}
+
+/**
+ * @brief Enters a critical zone from ISR context.
+ * @note This function cannot be used for reentrant critical zones.
+ *
+ * @special
+ */
+static inline void osalSysLockFromISR(void) {
+
+ chSysLockFromISR();
+}
+
+/**
+ * @brief Leaves a critical zone from ISR context.
+ * @note This function cannot be used for reentrant critical zones.
+ *
+ * @special
+ */
+static inline void osalSysUnlockFromISR(void) {
+
+ chSysUnlockFromISR();
+}
+
+/**
+ * @brief Returns the execution status and enters a critical zone.
+ * @details This functions enters into a critical zone and can be called
+ * from any context. Because its flexibility it is less efficient
+ * than @p chSysLock() which is preferable when the calling context
+ * is known.
+ * @post The system is in a critical zone.
+ *
+ * @return The previous system status, the encoding of this
+ * status word is architecture-dependent and opaque.
+ *
+ * @xclass
+ */
+static inline syssts_t osalSysGetStatusAndLockX(void) {
+
+ return chSysGetStatusAndLockX();
+}
+
+/**
+ * @brief Restores the specified execution status and leaves a critical zone.
+ * @note A call to @p chSchRescheduleS() is automatically performed
+ * if exiting the critical zone and if not in ISR context.
+ *
+ * @param[in] sts the system status to be restored.
+ *
+ * @xclass
+ */
+static inline void osalSysRestoreStatusX(syssts_t sts) {
+
+ chSysRestoreStatusX(sts);
+}
+
+/**
+ * @brief Polled delay.
+ * @note The real delay is always few cycles in excess of the specified
+ * value.
+ *
+ * @param[in] cycles number of cycles
+ *
+ * @xclass
+ */
+#if (PORT_SUPPORTS_RT == TRUE) || defined(__DOXYGEN__)
+static inline void osalSysPolledDelayX(rtcnt_t cycles) {
+
+ chSysPolledDelayX(cycles);
+}
+#endif
+
+/**
+ * @brief Systick callback for the underlying OS.
+ * @note This callback is only defined if the OSAL requires such a
+ * service from the HAL.
+ */
+#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__)
+static inline void osalOsTimerHandlerI(void) {
+
+ chSysTimerHandlerI();
+}
+#endif
+
+/**
+ * @brief Checks if a reschedule is required and performs it.
+ * @note I-Class functions invoked from thread context must not reschedule
+ * by themselves, an explicit reschedule using this function is
+ * required in this scenario.
+ * @note Not implemented in this simplified OSAL.
+ *
+ * @sclass
+ */
+static inline void osalOsRescheduleS(void) {
+
+ chSchRescheduleS();
+}
+
+/**
+ * @brief Current system time.
+ * @details Returns the number of system ticks since the @p osalInit()
+ * invocation.
+ * @note The counter can reach its maximum and then restart from zero.
+ * @note This function can be called from any context but its atomicity
+ * is not guaranteed on architectures whose word size is less than
+ * @p systime_t size.
+ *
+ * @return The system time in ticks.
+ *
+ * @xclass
+ */
+static inline systime_t osalOsGetSystemTimeX(void) {
+
+ return chVTGetSystemTimeX();
+}
+
+/**
+ * @brief Adds an interval to a system time returning a system time.
+ *
+ * @param[in] systime base system time
+ * @param[in] interval interval to be added
+ * @return The new system time.
+ *
+ * @xclass
+ */
+static inline systime_t osalTimeAddX(systime_t systime,
+ sysinterval_t interval) {
+
+ return chTimeAddX(systime, interval);
+}
+
+/**
+ * @brief Subtracts two system times returning an interval.
+ *
+ * @param[in] start first system time
+ * @param[in] end second system time
+ * @return The interval representing the time difference.
+ *
+ * @xclass
+ */
+static inline sysinterval_t osalTimeDiffX(systime_t start, systime_t end) {
+
+ return chTimeDiffX(start, end);
+}
+
+/**
+ * @brief Checks if the specified time is within the specified time window.
+ * @note When start==end then the function returns always true because the
+ * whole time range is specified.
+ * @note This function can be called from any context.
+ *
+ * @param[in] time the time to be verified
+ * @param[in] start the start of the time window (inclusive)
+ * @param[in] end the end of the time window (non inclusive)
+ * @retval true current time within the specified time window.
+ * @retval false current time not within the specified time window.
+ *
+ * @xclass
+ */
+static inline bool osalTimeIsInRangeX(systime_t time,
+ systime_t start,
+ systime_t end) {
+
+ return chTimeIsInRangeX(time, start, end);
+}
+
+/**
+ * @brief Suspends the invoking thread for the specified time.
+ *
+ * @param[in] delay the delay in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE is allowed but interpreted as a
+ * normal time specification.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ *
+ * @sclass
+ */
+static inline void osalThreadSleepS(sysinterval_t delay) {
+
+ chThdSleepS(delay);
+}
+
+/**
+ * @brief Suspends the invoking thread for the specified time.
+ *
+ * @param[in] delay the delay in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE is allowed but interpreted as a
+ * normal time specification.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ *
+ * @api
+ */
+static inline void osalThreadSleep(sysinterval_t delay) {
+
+ chThdSleep(delay);
+}
+
+/**
+ * @brief Sends the current thread sleeping and sets a reference variable.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @return The wake up message.
+ *
+ * @sclass
+ */
+static inline msg_t osalThreadSuspendS(thread_reference_t *trp) {
+
+ return chThdSuspendTimeoutS(trp, TIME_INFINITE);
+}
+
+/**
+ * @brief Sends the current thread sleeping and sets a reference variable.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] timeout the timeout in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE the thread enters an infinite sleep
+ * state.
+ * - @a TIME_IMMEDIATE the thread is not enqueued and
+ * the function returns @p MSG_TIMEOUT as if a timeout
+ * occurred.
+ * .
+ * @return The wake up message.
+ * @retval MSG_TIMEOUT if the operation timed out.
+ *
+ * @sclass
+ */
+static inline msg_t osalThreadSuspendTimeoutS(thread_reference_t *trp,
+ sysinterval_t timeout) {
+
+ return chThdSuspendTimeoutS(trp, timeout);
+}
+
+/**
+ * @brief Wakes up a thread waiting on a thread reference object.
+ * @note This function must not reschedule because it can be called from
+ * ISR context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+static inline void osalThreadResumeI(thread_reference_t *trp, msg_t msg) {
+
+ chThdResumeI(trp, msg);
+}
+
+/**
+ * @brief Wakes up a thread waiting on a thread reference object.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+static inline void osalThreadResumeS(thread_reference_t *trp, msg_t msg) {
+
+ chThdResumeS(trp, msg);
+}
+
+/**
+ * @brief Initializes a threads queue object.
+ *
+ * @param[out] tqp pointer to the threads queue object
+ *
+ * @init
+ */
+static inline void osalThreadQueueObjectInit(threads_queue_t *tqp) {
+
+ chThdQueueObjectInit(tqp);
+}
+
+/**
+ * @brief Enqueues the caller thread.
+ * @details The caller thread is enqueued and put to sleep until it is
+ * dequeued or the specified timeouts expires.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] timeout the timeout in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE the thread enters an infinite sleep
+ * state.
+ * - @a TIME_IMMEDIATE the thread is not enqueued and
+ * the function returns @p MSG_TIMEOUT as if a timeout
+ * occurred.
+ * .
+ * @return The message from @p osalQueueWakeupOneI() or
+ * @p osalQueueWakeupAllI() functions.
+ * @retval MSG_TIMEOUT if the thread has not been dequeued within the
+ * specified timeout or if the function has been
+ * invoked with @p TIME_IMMEDIATE as timeout
+ * specification.
+ *
+ * @sclass
+ */
+static inline msg_t osalThreadEnqueueTimeoutS(threads_queue_t *tqp,
+ sysinterval_t timeout) {
+
+ return chThdEnqueueTimeoutS(tqp, timeout);
+}
+
+/**
+ * @brief Dequeues and wakes up one thread from the queue, if any.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+static inline void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg) {
+
+ chThdDequeueNextI(tqp, msg);
+}
+
+/**
+ * @brief Dequeues and wakes up all threads from the queue.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+static inline void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg) {
+
+ chThdDequeueAllI(tqp, msg);
+}
+
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Initializes an event source object.
+ *
+ * @param[out] esp pointer to the event source object
+ *
+ * @init
+ */
+static inline void osalEventObjectInit(event_source_t *esp) {
+
+ chEvtObjectInit(esp);
+}
+#else
+static inline void osalEventObjectInit(event_source_t *esp) {
+
+ osalDbgCheck(esp != NULL);
+
+ esp->flags = (eventflags_t)0;
+ esp->cb = NULL;
+ esp->param = NULL;
+}
+#endif
+
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Add flags to an event source object.
+ *
+ * @param[in] esp pointer to the event flags object
+ * @param[in] flags flags to be ORed to the flags mask
+ *
+ * @iclass
+ */
+static inline void osalEventBroadcastFlagsI(event_source_t *esp,
+ eventflags_t flags) {
+
+ chEvtBroadcastFlagsI(esp, flags);
+}
+#else
+static inline void osalEventBroadcastFlagsI(event_source_t *esp,
+ eventflags_t flags) {
+
+ osalDbgCheck(esp != NULL);
+
+ esp->flags |= flags;
+ if (esp->cb != NULL) {
+ esp->cb(esp);
+ }
+}
+#endif
+
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Add flags to an event source object.
+ *
+ * @param[in] esp pointer to the event flags object
+ * @param[in] flags flags to be ORed to the flags mask
+ *
+ * @iclass
+ */
+static inline void osalEventBroadcastFlags(event_source_t *esp,
+ eventflags_t flags) {
+
+ chEvtBroadcastFlags(esp, flags);
+}
+#else
+static inline void osalEventBroadcastFlags(event_source_t *esp,
+ eventflags_t flags) {
+
+ osalDbgCheck(esp != NULL);
+
+ osalSysLock();
+ esp->flags |= flags;
+ if (esp->cb != NULL) {
+ esp->cb(esp);
+ }
+ osalSysUnlock();
+}
+#endif
+
+#if (CH_CFG_USE_EVENTS == FALSE) || defined(__DOXYGEN__)
+/**
+ * @brief Event callback setup.
+ * @note The callback is invoked from ISR context and can
+ * only invoke I-Class functions. The callback is meant
+ * to wakeup the task that will handle the event by
+ * calling @p osalEventGetAndClearFlagsI().
+ *
+ * @param[in] esp pointer to the event flags object
+ * @param[in] cb pointer to the callback function
+ * @param[in] param parameter to be passed to the callback function
+ *
+ * @api
+ */
+static inline void osalEventSetCallback(event_source_t *esp,
+ eventcallback_t cb,
+ void *param) {
+
+ osalDbgCheck(esp != NULL);
+
+ esp->cb = cb;
+ esp->param = param;
+}
+#endif
+
+/**
+ * @brief Initializes s @p mutex_t object.
+ *
+ * @param[out] mp pointer to the @p mutex_t object
+ *
+ * @init
+ */
+static inline void osalMutexObjectInit(mutex_t *mp) {
+
+#if CH_CFG_USE_MUTEXES
+ chMtxObjectInit(mp);
+#elif CH_CFG_USE_SEMAPHORES
+ chSemObjectInit((semaphore_t *)mp, 1);
+#else
+ *mp = 0;
+#endif
+}
+
+/**
+ * @brief Locks the specified mutex.
+ * @post The mutex is locked and inserted in the per-thread stack of owned
+ * mutexes.
+ *
+ * @param[in,out] mp pointer to the @p mutex_t object
+ *
+ * @api
+ */
+static inline void osalMutexLock(mutex_t *mp) {
+
+#if CH_CFG_USE_MUTEXES
+ chMtxLock(mp);
+#elif CH_CFG_USE_SEMAPHORES
+ chSemWait((semaphore_t *)mp);
+#else
+ *mp = 1;
+#endif
+}
+
+/**
+ * @brief Unlocks the specified mutex.
+ * @note The HAL guarantees to release mutex in reverse lock order. The
+ * mutex being unlocked is guaranteed to be the last locked mutex
+ * by the invoking thread.
+ * The implementation can rely on this behavior and eventually
+ * ignore the @p mp parameter which is supplied in order to support
+ * those OSes not supporting a stack of the owned mutexes.
+ *
+ * @param[in,out] mp pointer to the @p mutex_t object
+ *
+ * @api
+ */
+static inline void osalMutexUnlock(mutex_t *mp) {
+
+#if CH_CFG_USE_MUTEXES
+ chMtxUnlock(mp);
+#elif CH_CFG_USE_SEMAPHORES
+ chSemSignal((semaphore_t *)mp);
+#else
+ *mp = 0;
+#endif
+}
+
+#endif /* OSAL_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/osal/rt-nil/osal.mk b/ChibiOS_20.3.2/os/hal/osal/rt-nil/osal.mk
new file mode 100644
index 0000000..f408d12
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/osal/rt-nil/osal.mk
@@ -0,0 +1,9 @@
+# OSAL files.
+OSALSRC += ${CHIBIOS}/os/hal/osal/rt-nil/osal.c
+
+# Required include directories
+OSALINC += ${CHIBIOS}/os/hal/osal/rt-nil
+
+# Shared variables
+ALLCSRC += $(OSALSRC)
+ALLINC += $(OSALINC)
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv1/driver.mk
new file mode 100644
index 0000000..a3b7649
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv1/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.c
new file mode 100644
index 0000000..a8733f9
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.c
@@ -0,0 +1,485 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ADCv1/hal_adc_lld.c
+ * @brief STM32 ADC subsystem low level driver source.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_ADC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define ADC1_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_CHN)
+
+/* Headers differences patches.*/
+#if defined(ADC_IER_AWDIE) && !defined(ADC_IER_AWD1IE)
+#define ADC_IER_AWD1IE ADC_IER_AWDIE
+#endif
+
+#if defined(ADC_ISR_AWD) && !defined(ADC_ISR_AWD1)
+#define ADC_ISR_AWD1 ADC_ISR_AWD
+#endif
+
+#define TR1 TR
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief ADC1 driver identifier.*/
+#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__)
+ADCDriver ADCD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC voltage regulator enable.
+ *
+ * @param[in] adc pointer to the ADC registers block
+ */
+NOINLINE static void adc_lld_vreg_on(ADC_TypeDef *adc) {
+
+ osalDbgAssert(adc->CR == 0, "invalid register state");
+
+#if defined(ADC_CR_ADVREGEN)
+ adc->CR = ADC_CR_ADVREGEN;
+ volatile uint32_t loop = (STM32_HCLK >> 20) << 4;
+ do {
+ loop--;
+ } while (loop > 0);
+#else
+#endif
+}
+
+/**
+ * @brief Stops an ongoing conversion, if any.
+ *
+ * @param[in] adc pointer to the ADC registers block
+ */
+static void adc_lld_stop_adc(ADC_TypeDef *adc) {
+
+ if (adc->CR & ADC_CR_ADSTART) {
+ adc->CR |= ADC_CR_ADSTP;
+ while (adc->CR & ADC_CR_ADSTP)
+ ;
+ adc->IER = 0;
+ }
+}
+
+/**
+ * @brief ADC DMA service routine.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ /* DMA, this could help only if the DMA tries to access an unmapped
+ address space or violates alignment rules.*/
+ _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE);
+ }
+ else {
+ /* It is possible that the conversion group has already be reset by the
+ ADC error handler, in this case this interrupt is spurious.*/
+ if (adcp->grpp != NULL) {
+ if ((flags & STM32_DMA_ISR_TCIF) != 0) {
+ /* Transfer complete processing.*/
+ _adc_isr_full_code(adcp);
+ }
+ else if ((flags & STM32_DMA_ISR_HTIF) != 0) {
+ /* Half transfer processing.*/
+ _adc_isr_half_code(adcp);
+ }
+ }
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__)
+#if !defined(STM32_ADC1_HANDLER)
+#error "STM32_ADC1_HANDLER not defined"
+#endif
+/**
+ * @brief ADC interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_ADC1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ adc_lld_serve_interrupt(&ADCD1);
+
+#if defined(STM32_ADC_ADC1_IRQ_HOOK)
+ STM32_ADC_ADC1_IRQ_HOOK
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level ADC driver initialization.
+ *
+ * @notapi
+ */
+void adc_lld_init(void) {
+
+#if STM32_ADC_USE_ADC1
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD1);
+ ADCD1.adc = ADC1;
+ ADCD1.dmastp = NULL;
+ ADCD1.dmamode = STM32_DMA_CR_CHSEL(ADC1_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+
+ /* The vector is initialized on driver initialization and never
+ disabled.*/
+ nvicEnableVector(12, STM32_ADC_ADC1_IRQ_PRIORITY);
+#endif
+
+ /* Calibration procedure.*/
+ rccEnableADC1(true);
+
+ /* CCR setup.*/
+#if STM32_ADC_SUPPORTS_PRESCALER
+ ADC->CCR = STM32_ADC_PRESC << 18;
+#else
+ ADC->CCR = 0;
+#endif
+
+ /* Regulator enabled and stabilized before calibration.*/
+ adc_lld_vreg_on(ADC1);
+
+ ADC1->CR |= ADC_CR_ADCAL;
+ while (ADC1->CR & ADC_CR_ADCAL)
+ ;
+ ADC1->CR = 0;
+ rccDisableADC1();
+}
+
+/**
+ * @brief Configures and activates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start(ADCDriver *adcp) {
+
+ /* If in stopped state then enables the ADC and DMA clocks.*/
+ if (adcp->state == ADC_STOP) {
+#if STM32_ADC_USE_ADC1
+ if (&ADCD1 == adcp) {
+ adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC1_DMA_STREAM,
+ STM32_ADC_ADC1_DMA_IRQ_PRIORITY,
+ (stm32_dmaisr_t)adc_lld_serve_rx_interrupt,
+ (void *)adcp);
+ osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
+ rccEnableADC1(true);
+
+ /* DMA setup.*/
+ dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(adcp->dmastp, STM32_DMAMUX1_ADC1);
+#endif
+
+ /* Clock settings.*/
+ adcp->adc->CFGR2 = STM32_ADC_ADC1_CKMODE;
+ }
+#endif /* STM32_ADC_USE_ADC1 */
+
+ /* Regulator enabled and stabilized before calibration.*/
+ adc_lld_vreg_on(ADC1);
+
+ /* ADC initial setup, starting the analog part here in order to reduce
+ the latency when starting a conversion.*/
+ adcp->adc->CR = ADC_CR_ADEN;
+ while (!(adcp->adc->ISR & ADC_ISR_ADRDY))
+ ;
+ }
+}
+
+/**
+ * @brief Deactivates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop(ADCDriver *adcp) {
+
+ /* If in ready state then disables the ADC clock and analog part.*/
+ if (adcp->state == ADC_READY) {
+
+ dmaStreamFreeI(adcp->dmastp);
+ adcp->dmastp = NULL;
+
+ /* Restoring CCR default.*/
+#if STM32_ADC_SUPPORTS_PRESCALER
+ ADC->CCR = STM32_ADC_PRESC << 18;
+#else
+ ADC->CCR = 0;
+#endif
+
+ /* Disabling ADC.*/
+ if (adcp->adc->CR & ADC_CR_ADEN) {
+ adc_lld_stop_adc(adcp->adc);
+ adcp->adc->CR |= ADC_CR_ADDIS;
+ while (adcp->adc->CR & ADC_CR_ADDIS)
+ ;
+ }
+
+ /* Regulator and anything else off.*/
+ adcp->adc->CR = 0;
+
+#if STM32_ADC_USE_ADC1
+ if (&ADCD1 == adcp)
+ rccDisableADC1();
+#endif
+ }
+}
+
+/**
+ * @brief Starts an ADC conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start_conversion(ADCDriver *adcp) {
+ uint32_t mode, cfgr1;
+ const ADCConversionGroup *grpp = adcp->grpp;
+
+ /* DMA setup.*/
+ mode = adcp->dmamode;
+ cfgr1 = grpp->cfgr1 | ADC_CFGR1_DMAEN;
+ if (grpp->circular) {
+ mode |= STM32_DMA_CR_CIRC;
+ cfgr1 |= ADC_CFGR1_DMACFG;
+ if (adcp->depth > 1) {
+ /* If circular buffer depth > 1, then the half transfer interrupt
+ is enabled in order to allow streaming processing.*/
+ mode |= STM32_DMA_CR_HTIE;
+ }
+ }
+ dmaStreamSetMemory0(adcp->dmastp, adcp->samples);
+ dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels *
+ (uint32_t)adcp->depth);
+ dmaStreamSetMode(adcp->dmastp, mode);
+ dmaStreamEnable(adcp->dmastp);
+
+ /* ADC setup, if it is defined a callback for the analog watch dog then it
+ is enabled.*/
+ adcp->adc->ISR = adcp->adc->ISR;
+ adcp->adc->IER = ADC_IER_OVRIE | ADC_IER_AWD1IE;
+ adcp->adc->TR1 = grpp->tr;
+ adcp->adc->SMPR = grpp->smpr;
+ adcp->adc->CHSELR = grpp->chselr;
+
+ /* ADC configuration and start.*/
+ adcp->adc->CFGR1 = cfgr1;
+#if STM32_ADC_SUPPORTS_OVERSAMPLING == TRUE
+ {
+ uint32_t cfgr2 = adcp->adc->CFGR2 & STM32_ADC_CKMODE_MASK;
+ adcp->adc->CFGR2 = cfgr2 | grpp->cfgr2;
+ }
+#endif
+
+ /* ADC conversion start.*/
+ adcp->adc->CR |= ADC_CR_ADSTART;
+}
+
+/**
+ * @brief Stops an ongoing conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop_conversion(ADCDriver *adcp) {
+
+ dmaStreamDisable(adcp->dmastp);
+ adc_lld_stop_adc(adcp->adc);
+}
+
+/**
+ * @brief ISR code.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_serve_interrupt(ADCDriver *adcp) {
+ uint32_t isr;
+
+ isr = adcp->adc->ISR;
+ adcp->adc->ISR = isr;
+
+ /* It could be a spurious interrupt caused by overflows after DMA disabling,
+ just ignore it in this case.*/
+ if (adcp->grpp != NULL) {
+ /* Note, an overflow may occur after the conversion ended before the driver
+ is able to stop the ADC, this is why the DMA channel is checked too.*/
+ if ((isr & ADC_ISR_OVR) &&
+ (dmaStreamGetTransactionSize(adcp->dmastp) > 0)) {
+ /* ADC overflow condition, this could happen only if the DMA is unable
+ to read data fast enough.*/
+ _adc_isr_error_code(adcp, ADC_ERR_OVERFLOW);
+ }
+ if (isr & ADC_ISR_AWD1) {
+ /* Analog watchdog error.*/
+ _adc_isr_error_code(adcp, ADC_ERR_AWD);
+ }
+ }
+}
+
+/**
+ * @brief Enables the VREFEN bit.
+ * @details The VREFEN bit is required in order to sample the VREF channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32EnableVREF(ADCDriver *adcp) {
+
+ (void)adcp;
+
+ ADC->CCR |= ADC_CCR_VREFEN;
+}
+
+/**
+ * @brief Disables the VREFEN bit.
+ * @details The VREFEN bit is required in order to sample the VREF channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32DisableVREF(ADCDriver *adcp) {
+
+ (void)adcp;
+
+ ADC->CCR &= ~ADC_CCR_VREFEN;
+}
+
+/**
+ * @brief Enables the TSEN bit.
+ * @details The TSEN bit is required in order to sample the internal
+ * temperature sensor and internal reference voltage.
+ * @note This is an STM32-only functionality.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32EnableTS(ADCDriver *adcp) {
+
+ (void)adcp;
+
+ ADC->CCR |= ADC_CCR_TSEN;
+}
+
+/**
+ * @brief Disables the TSEN bit.
+ * @details The TSEN bit is required in order to sample the internal
+ * temperature sensor and internal reference voltage.
+ * @note This is an STM32-only functionality.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32DisableTS(ADCDriver *adcp) {
+
+ (void)adcp;
+
+ ADC->CCR &= ~ADC_CCR_TSEN;
+}
+
+#if defined(ADC_CCR_VBATEN) || defined(__DOXYGEN__)
+/**
+ * @brief Enables the VBATEN bit.
+ * @details The VBATEN bit is required in order to sample the VBAT channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32EnableVBAT(ADCDriver *adcp) {
+
+ (void)adcp;
+
+ ADC->CCR |= ADC_CCR_VBATEN;
+}
+
+/**
+ * @brief Disables the VBATEN bit.
+ * @details The VBATEN bit is required in order to sample the VBAT channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32DisableVBAT(ADCDriver *adcp) {
+
+ (void)adcp;
+
+ ADC->CCR &= ~ADC_CCR_VBATEN;
+}
+#endif /* defined(ADC_CCR_VBATEN) */
+
+#endif /* HAL_USE_ADC */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.h
new file mode 100644
index 0000000..cc478d5
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv1/hal_adc_lld.h
@@ -0,0 +1,415 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ADCv1/hal_adc_lld.h
+ * @brief STM32 ADC subsystem low level driver header.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#ifndef HAL_ADC_LLD_H
+#define HAL_ADC_LLD_H
+
+#if HAL_USE_ADC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Sampling rates
+ * @{
+ */
+#if defined(STM32F0XX) || defined(__DOXYGEN__)
+#define ADC_SMPR_SMP_1P5 0U /**< @brief 14 cycles conversion time */
+#define ADC_SMPR_SMP_7P5 1U /**< @brief 21 cycles conversion time. */
+#define ADC_SMPR_SMP_13P5 2U /**< @brief 28 cycles conversion time. */
+#define ADC_SMPR_SMP_28P5 3U /**< @brief 41 cycles conversion time. */
+#define ADC_SMPR_SMP_41P5 4U /**< @brief 54 cycles conversion time. */
+#define ADC_SMPR_SMP_55P5 5U /**< @brief 68 cycles conversion time. */
+#define ADC_SMPR_SMP_71P5 6U /**< @brief 84 cycles conversion time. */
+#define ADC_SMPR_SMP_239P5 7U /**< @brief 252 cycles conversion time. */
+#elif defined(STM32L0XX)
+#define ADC_SMPR_SMP_1P5 0U /**< @brief 14 cycles conversion time */
+#define ADC_SMPR_SMP_3P5 1U /**< @brief 16 cycles conversion time. */
+#define ADC_SMPR_SMP_7P5 2U /**< @brief 20 cycles conversion time. */
+#define ADC_SMPR_SMP_12P5 3U /**< @brief 25 cycles conversion time. */
+#define ADC_SMPR_SMP_19P5 4U /**< @brief 31 cycles conversion time. */
+#define ADC_SMPR_SMP_39P5 5U /**< @brief 52 cycles conversion time. */
+#define ADC_SMPR_SMP_79P5 6U /**< @brief 92 cycles conversion time. */
+#define ADC_SMPR_SMP_160P5 7U /**< @brief 173 cycles conversion time. */
+#endif
+/** @} */
+
+/**
+ * @name CFGR1 register configuration helpers
+ * @{
+ */
+#define ADC_CFGR1_RES_12BIT (0U << 3U)
+#define ADC_CFGR1_RES_10BIT (1U << 3U)
+#define ADC_CFGR1_RES_8BIT (2U << 3U)
+#define ADC_CFGR1_RES_6BIT (3U << 3U)
+
+#define ADC_CFGR1_EXTSEL_MASK (15U << 6U)
+#define ADC_CFGR1_EXTSEL_SRC(n) ((n) << 6U)
+
+#define ADC_CFGR1_EXTEN_MASK (3U << 10U)
+#define ADC_CFGR1_EXTEN_DISABLED (0U << 10U)
+#define ADC_CFGR1_EXTEN_RISING (1U << 10U)
+#define ADC_CFGR1_EXTEN_FALLING (2U << 10U)
+#define ADC_CFGR1_EXTEN_BOTH (3U << 10U)
+/** @} */
+
+/**
+ * @name CFGR2 register configuration helpers
+ * @{
+ */
+#define STM32_ADC_CKMODE_MASK (3U << 30U)
+#define STM32_ADC_CKMODE_ADCCLK (0U << 30U)
+#define STM32_ADC_CKMODE_PCLK_DIV2 (1U << 30U)
+#define STM32_ADC_CKMODE_PCLK_DIV4 (2U << 30U)
+#define STM32_ADC_CKMODE_PCLK (3U << 30U)
+
+#if (STM32_ADC_SUPPORTS_OVERSAMPLING == TRUE) || defined(__DOXYGEN__)
+#define ADC_CFGR2_OVSR_MASK (7U << 2U)
+#define ADC_CFGR2_OVSR_2X (0U << 2U)
+#define ADC_CFGR2_OVSR_4X (1U << 2U)
+#define ADC_CFGR2_OVSR_8X (2U << 2U)
+#define ADC_CFGR2_OVSR_16X (3U << 2U)
+#define ADC_CFGR2_OVSR_32X (4U << 2U)
+#define ADC_CFGR2_OVSR_64X (5U << 2U)
+#define ADC_CFGR2_OVSR_128X (6U << 2U)
+#define ADC_CFGR2_OVSR_256X (7U << 2U)
+
+#define ADC_CFGR2_OVSS_MASK (15 << 5U)
+#define ADC_CFGR2_OVSS_SHIFT(n) ((n) << 5U)
+#endif
+/** @} */
+
+/**
+ * @name Threashold register initializer
+ * @{
+ */
+#define ADC_TR(low, high) (((uint32_t)(high) << 16U) | \
+ (uint32_t)(low))
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief ADC1 driver enable switch.
+ * @details If set to @p TRUE the support for ADC1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__)
+#define STM32_ADC_USE_ADC1 FALSE
+#endif
+
+/**
+ * @brief ADC1 clock source selection.
+ */
+#if !defined(STM32_ADC_ADC1_CKMODE) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC1_CKMODE STM32_ADC_CKMODE_ADCCLK
+#endif
+
+/**
+ * @brief ADC1 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC1_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC1_IRQ_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC1 DMA interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 2
+#endif
+
+#if (STM32_ADC_SUPPORTS_PRESCALER == TRUE) || defined(__DOXYGEN__)
+/*
+ * @brief ADC prescaler setting.
+ * @note This setting has effect only in asynchronous clock mode (the
+ * default, @p STM32_ADC_CKMODE_ADCCLK).
+ */
+#if !defined(STM32_ADC_PRESCALER_VALUE) || defined(__DOXYGEN__)
+#define STM32_ADC_PRESCALER_VALUE 2
+#endif
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Supported devices checks.*/
+#if !defined(STM32F0XX) && !defined(STM32L0XX)
+#error "ADCv1 only supports F0 and L0 STM32 devices"
+#endif
+
+#if defined(STM32L0XX) || defined(__DOXYGEN__)
+#define STM32_ADCV1_OVERSAMPLING TRUE
+#else
+#define STM32_ADCV1_OVERSAMPLING FALSE
+#endif
+
+/* Registry checks.*/
+#if !defined(STM32_HAS_ADC1)
+#error "STM32_HAS_ADC1 not defined in registry"
+#endif
+
+#if !defined(STM32_ADC_SUPPORTS_PRESCALER)
+#error "STM32_ADC_SUPPORTS_PRESCALER not defined in registry"
+#endif
+
+#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_HANDLER))
+#error "STM32_ADC1_HANDLER not defined in registry"
+#endif
+
+#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_NUMBER))
+#error "STM32_ADC1_NUMBER not defined in registry"
+#endif
+
+#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1
+#error "ADC1 not present in the selected device"
+#endif
+
+/* Units checks.*/
+#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1
+#error "ADC1 not present in the selected device"
+#endif
+
+/* At least one ADC must be assigned.*/
+#if !STM32_ADC_USE_ADC1
+#error "ADC driver activated but no ADC peripheral assigned"
+#endif
+
+/* ADC IRQ priority tests.*/
+#if STM32_ADC_USE_ADC1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to ADC1"
+#endif
+
+/* DMA IRQ priority tests.*/
+#if STM32_ADC_USE_ADC1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to ADC1 DMA"
+#endif
+
+/* DMA priority tests.*/
+#if STM32_ADC_USE_ADC1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to ADC1"
+#endif
+
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if STM32_ADC_USE_ADC1 && !defined(STM32_ADC_ADC1_DMA_STREAM)
+#error "ADC DMA stream not defined"
+#endif
+#if STM32_DMA_SUPPORTS_DMAMUX
+
+#else /* !STM32_DMA_SUPPORTS_DMAMUX */
+
+/* Check on the validity of the assigned DMA channels.*/
+#if STM32_ADC_USE_ADC1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_MSK)
+#error "invalid DMA stream associated to ADC1"
+#endif
+
+#endif /* !STM32_DMA_SUPPORTS_DMAMUX */
+
+/* ADC clock source checks.*/
+#if STM32_ADC_SUPPORTS_PRESCALER == TRUE
+#if STM32_ADC_PRESCALER_VALUE == 2
+#define STM32_ADC_PRESC 1U
+#elif STM32_ADC_PRESCALER_VALUE == 4
+#define STM32_ADC_PRESC 2U
+#elif STM32_ADC_PRESCALER_VALUE == 6
+#define STM32_ADC_PRESC 3U
+#elif STM32_ADC_PRESCALER_VALUE == 8
+#define STM32_ADC_PRESC 4U
+#elif STM32_ADC_PRESCALER_VALUE == 10
+#define STM32_ADC_PRESC 5U
+#elif STM32_ADC_PRESCALER_VALUE == 12
+#define STM32_ADC_PRESC 6U
+#elif STM32_ADC_PRESCALER_VALUE == 16
+#define STM32_ADC_PRESC 7U
+#elif STM32_ADC_PRESCALER_VALUE == 32
+#define STM32_ADC_PRESC 8U
+#elif STM32_ADC_PRESCALER_VALUE == 64
+#define STM32_ADC_PRESC 9U
+#elif STM32_ADC_PRESCALER_VALUE == 128
+#define STM32_ADC_PRESC 10U
+#elif STM32_ADC_PRESCALER_VALUE == 256
+#define STM32_ADC_PRESC 11U
+#else
+#error "Invalid value assigned to STM32_ADC_PRESCALER_VALUE"
+#endif
+#endif
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC sample data type.
+ */
+typedef uint16_t adcsample_t;
+
+/**
+ * @brief Channels number in a conversion group.
+ */
+typedef uint16_t adc_channels_num_t;
+
+/**
+ * @brief Possible ADC failure causes.
+ * @note Error codes are architecture dependent and should not relied
+ * upon.
+ */
+typedef enum {
+ ADC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */
+ ADC_ERR_OVERFLOW = 1, /**< ADC overflow condition. */
+ ADC_ERR_AWD = 2 /**< Analog watchdog triggered. */
+} adcerror_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the ADC driver structure.
+ */
+#define adc_lld_driver_fields \
+ /* Pointer to the ADCx registers block.*/ \
+ ADC_TypeDef *adc; \
+ /* Pointer to associated DMA channel.*/ \
+ const stm32_dma_stream_t *dmastp; \
+ /* DMA mode bit mask.*/ \
+ uint32_t dmamode
+
+/**
+ * @brief Low level fields of the ADC configuration structure.
+ */
+#define adc_lld_config_fields \
+ /* Dummy configuration, it is not needed.*/ \
+ uint32_t dummy
+
+/**
+ * @brief Low level fields of the ADC configuration structure.
+ */
+#if (STM32_ADC_SUPPORTS_OVERSAMPLING == TRUE) || defined(__DOXYGEN__)
+#define adc_lld_configuration_group_fields \
+ /* ADC CFGR1 register initialization data. \
+ NOTE: The bits DMAEN and DMACFG are enforced internally \
+ to the driver, keep them to zero. \
+ NOTE: The bits @p ADC_CFGR1_CONT or @p ADC_CFGR1_DISCEN must be \
+ specified in continuous more or if the buffer depth is \
+ greater than one.*/ \
+ uint32_t cfgr1; \
+ /* ADC CFGR2 register initialization data. \
+ NOTE: CKMODE bits must not be specified in this field and left to \
+ zero.*/ \
+ uint32_t cfgr2; \
+ /* ADC TR register initialization data.*/ \
+ uint32_t tr; \
+ /* ADC SMPR register initialization data.*/ \
+ uint32_t smpr; \
+ /* ADC CHSELR register initialization data. \
+ NOTE: The number of bits at logic level one in this register must \
+ be equal to the number in the @p num_channels field.*/ \
+ uint32_t chselr
+#else
+#define adc_lld_configuration_group_fields \
+ /* ADC CFGR1 register initialization data. \
+ NOTE: The bits DMAEN and DMACFG are enforced internally \
+ to the driver, keep them to zero. \
+ NOTE: The bits @p ADC_CFGR1_CONT or @p ADC_CFGR1_DISCEN must be \
+ specified in continuous more or if the buffer depth is \
+ greater than one.*/ \
+ uint32_t cfgr1; \
+ /* ADC TR register initialization data.*/ \
+ uint32_t tr; \
+ /* ADC SMPR register initialization data.*/ \
+ uint32_t smpr; \
+ /* ADC CHSELR register initialization data. \
+ NOTE: The number of bits at logic level one in this register must \
+ be equal to the number in the @p num_channels field.*/ \
+ uint32_t chselr
+#endif
+
+/**
+ * @brief Changes the value of the ADC CCR register.
+ * @details Use this function in order to enable or disable the internal
+ * analog sources. See the documentation in the STM32 Reference
+ * Manual.
+ * @note PRESC bits must not be specified and left to zero.
+ */
+#define adcSTM32SetCCR(ccr) (ADC->CCR = (ccr))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__)
+extern ADCDriver ADCD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void adc_lld_init(void);
+ void adc_lld_start(ADCDriver *adcp);
+ void adc_lld_stop(ADCDriver *adcp);
+ void adc_lld_start_conversion(ADCDriver *adcp);
+ void adc_lld_stop_conversion(ADCDriver *adcp);
+ void adc_lld_serve_interrupt(ADCDriver *adcp);
+ void adcSTM32EnableVREF(ADCDriver *adcp);
+ void adcSTM32DisableVREF(ADCDriver *adcp);
+ void adcSTM32EnableTS(ADCDriver *adcp);
+ void adcSTM32DisableTS(ADCDriver *adcp);
+#if defined(ADC_CCR_VBATEN)
+ void adcSTM32EnableVBAT(ADCDriver *adcp);
+ void adcSTM32DisableVBAT(ADCDriver *adcp);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_ADC */
+
+#endif /* HAL_ADC_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv1/notes.txt b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv1/notes.txt
new file mode 100644
index 0000000..9224117
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv1/notes.txt
@@ -0,0 +1,16 @@
+STM32 ADCv1 driver.
+
+Driver capability:
+
+- Supports the STM32 "simple" ADC, the one found on small devices (F0, L0).
+
+The file registry must export:
+
+STM32_HAS_ADC1 - ADC1 presence flag.
+STM32_ADC_SUPPORTS_PRESCALER - Support of CCR PRESC field.
+STM32_ADC_SUPPORTS_OVERSAMPLING - Support of oversampling-related fields.
+STM32_ADC1_IRQ_SHARED_WITH_EXTI - TRUE if the IRQ is shared with EXTI.
+STM32_ADC1_HANDLER - IRQ vector name.
+STM32_ADC1_NUMBER - IRQ vector number.
+STM32_ADC1_DMA_MSK - Mask of the compatible DMA channels.
+STM32_ADC1_DMA_CHN - Mask of the channels mapping.
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv2/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv2/driver.mk
new file mode 100644
index 0000000..9be6513
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv2/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv2
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.c
new file mode 100644
index 0000000..53a5439
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.c
@@ -0,0 +1,452 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ADCv2/hal_adc_lld.c
+ * @brief STM32 ADC subsystem low level driver source.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_ADC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define ADC1_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_CHN)
+
+#define ADC2_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_ADC_ADC2_DMA_STREAM, STM32_ADC2_DMA_CHN)
+
+#define ADC3_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_ADC_ADC3_DMA_STREAM, STM32_ADC3_DMA_CHN)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief ADC1 driver identifier.*/
+#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__)
+ADCDriver ADCD1;
+#endif
+
+/** @brief ADC2 driver identifier.*/
+#if STM32_ADC_USE_ADC2 || defined(__DOXYGEN__)
+ADCDriver ADCD2;
+#endif
+
+/** @brief ADC3 driver identifier.*/
+#if STM32_ADC_USE_ADC3 || defined(__DOXYGEN__)
+ADCDriver ADCD3;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC DMA service routine.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ /* DMA, this could help only if the DMA tries to access an unmapped
+ address space or violates alignment rules.*/
+ _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE);
+ }
+ else {
+ /* It is possible that the conversion group has already be reset by the
+ ADC error handler, in this case this interrupt is spurious.*/
+ if (adcp->grpp != NULL) {
+
+ if ((flags & STM32_DMA_ISR_TCIF) != 0) {
+ /* Transfer complete processing.*/
+ _adc_isr_full_code(adcp);
+ }
+ else if ((flags & STM32_DMA_ISR_HTIF) != 0) {
+ /* Half transfer processing.*/
+ _adc_isr_half_code(adcp);
+ }
+ }
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2 || STM32_ADC_USE_ADC3 || \
+ defined(__DOXYGEN__)
+/**
+ * @brief ADC interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_ADC_HANDLER) {
+ uint32_t sr;
+
+ OSAL_IRQ_PROLOGUE();
+
+#if STM32_ADC_USE_ADC1
+ sr = ADC1->SR;
+ ADC1->SR = 0;
+ /* Note, an overflow may occur after the conversion ended before the driver
+ is able to stop the ADC, this is why the DMA channel is checked too.*/
+ if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD1.dmastp) > 0)) {
+ /* ADC overflow condition, this could happen only if the DMA is unable
+ to read data fast enough.*/
+ if (ADCD1.grpp != NULL)
+ _adc_isr_error_code(&ADCD1, ADC_ERR_OVERFLOW);
+ }
+ if (sr & ADC_SR_AWD) {
+ if (ADCD1.grpp != NULL) {
+ _adc_isr_error_code(&ADCD1, ADC_ERR_WATCHDOG);
+ }
+ }
+#if defined(STM32_ADC_ADC1_IRQ_HOOK)
+ STM32_ADC_ADC1_IRQ_HOOK
+#endif
+#endif /* STM32_ADC_USE_ADC1 */
+
+#if STM32_ADC_USE_ADC2
+ sr = ADC2->SR;
+ ADC2->SR = 0;
+ /* Note, an overflow may occur after the conversion ended before the driver
+ is able to stop the ADC, this is why the DMA channel is checked too.*/
+ if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD2.dmastp) > 0)) {
+ /* ADC overflow condition, this could happen only if the DMA is unable
+ to read data fast enough.*/
+ if (ADCD2.grpp != NULL)
+ _adc_isr_error_code(&ADCD2, ADC_ERR_OVERFLOW);
+ }
+ if (sr & ADC_SR_AWD) {
+ if (ADCD2.grpp != NULL) {
+ _adc_isr_error_code(&ADCD2, ADC_ERR_WATCHDOG);
+ }
+ }
+#if defined(STM32_ADC_ADC2_IRQ_HOOK)
+ STM32_ADC_ADC2_IRQ_HOOK
+#endif
+#endif /* STM32_ADC_USE_ADC2 */
+
+#if STM32_ADC_USE_ADC3
+ sr = ADC3->SR;
+ ADC3->SR = 0;
+ /* Note, an overflow may occur after the conversion ended before the driver
+ is able to stop the ADC, this is why the DMA channel is checked too.*/
+ if ((sr & ADC_SR_OVR) && (dmaStreamGetTransactionSize(ADCD3.dmastp) > 0)) {
+ /* ADC overflow condition, this could happen only if the DMA is unable
+ to read data fast enough.*/
+ if (ADCD3.grpp != NULL)
+ _adc_isr_error_code(&ADCD3, ADC_ERR_OVERFLOW);
+ }
+ if (sr & ADC_SR_AWD) {
+ if (ADCD3.grpp != NULL) {
+ _adc_isr_error_code(&ADCD3, ADC_ERR_WATCHDOG);
+ }
+ }
+#if defined(STM32_ADC_ADC3_IRQ_HOOK)
+ STM32_ADC_ADC3_IRQ_HOOK
+#endif
+#endif /* STM32_ADC_USE_ADC3 */
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level ADC driver initialization.
+ *
+ * @notapi
+ */
+void adc_lld_init(void) {
+
+#if STM32_ADC_USE_ADC1
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD1);
+ ADCD1.adc = ADC1;
+ ADCD1.dmastp = NULL;
+ ADCD1.dmamode = STM32_DMA_CR_CHSEL(ADC1_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+#endif
+
+#if STM32_ADC_USE_ADC2
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD2);
+ ADCD2.adc = ADC2;
+ ADCD2.dmastp = NULL;
+ ADCD2.dmamode = STM32_DMA_CR_CHSEL(ADC2_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_ADC_ADC2_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+#endif
+
+#if STM32_ADC_USE_ADC3
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD3);
+ ADCD3.adc = ADC3;
+ ADCD3.dmastp = NULL;
+ ADCD3.dmamode = STM32_DMA_CR_CHSEL(ADC3_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_ADC_ADC3_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+#endif
+
+ /* The shared vector is initialized on driver initialization and never
+ disabled because sharing.*/
+ nvicEnableVector(STM32_ADC_NUMBER, STM32_ADC_IRQ_PRIORITY);
+}
+
+/**
+ * @brief Configures and activates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start(ADCDriver *adcp) {
+
+ /* If in stopped state then enables the ADC and DMA clocks.*/
+ if (adcp->state == ADC_STOP) {
+#if STM32_ADC_USE_ADC1
+ if (&ADCD1 == adcp) {
+ adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC1_DMA_STREAM,
+ STM32_ADC_ADC1_DMA_IRQ_PRIORITY,
+ (stm32_dmaisr_t)adc_lld_serve_rx_interrupt,
+ (void *)adcp);
+ osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
+ dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR);
+ rccEnableADC1(true);
+ }
+#endif /* STM32_ADC_USE_ADC1 */
+
+#if STM32_ADC_USE_ADC2
+ if (&ADCD2 == adcp) {
+ adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC2_DMA_STREAM,
+ STM32_ADC_ADC2_DMA_IRQ_PRIORITY,
+ (stm32_dmaisr_t)adc_lld_serve_rx_interrupt,
+ (void *)adcp);
+ osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
+ dmaStreamSetPeripheral(adcp->dmastp, &ADC2->DR);
+ rccEnableADC2(true);
+ }
+#endif /* STM32_ADC_USE_ADC2 */
+
+#if STM32_ADC_USE_ADC3
+ if (&ADCD3 == adcp) {
+ adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC3_DMA_STREAM,
+ STM32_ADC_ADC3_DMA_IRQ_PRIORITY,
+ (stm32_dmaisr_t)adc_lld_serve_rx_interrupt,
+ (void *)adcp);
+ osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
+ dmaStreamSetPeripheral(adcp->dmastp, &ADC3->DR);
+ rccEnableADC3(true);
+ }
+#endif /* STM32_ADC_USE_ADC3 */
+
+ /* This is a common register but apparently it requires that at least one
+ of the ADCs is clocked in order to allow writing, see bug 3575297.*/
+ ADC->CCR = (ADC->CCR & (ADC_CCR_TSVREFE | ADC_CCR_VBATE)) |
+ (STM32_ADC_ADCPRE << 16);
+
+ /* ADC initial setup, starting the analog part here in order to reduce
+ the latency when starting a conversion.*/
+ adcp->adc->CR1 = 0;
+ adcp->adc->CR2 = 0;
+ adcp->adc->CR2 = ADC_CR2_ADON;
+ }
+}
+
+/**
+ * @brief Deactivates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop(ADCDriver *adcp) {
+
+ /* If in ready state then disables the ADC clock.*/
+ if (adcp->state == ADC_READY) {
+
+ dmaStreamFreeI(adcp->dmastp);
+ adcp->dmastp = NULL;
+
+ adcp->adc->CR1 = 0;
+ adcp->adc->CR2 = 0;
+
+#if STM32_ADC_USE_ADC1
+ if (&ADCD1 == adcp)
+ rccDisableADC1();
+#endif
+
+#if STM32_ADC_USE_ADC2
+ if (&ADCD2 == adcp)
+ rccDisableADC2();
+#endif
+
+#if STM32_ADC_USE_ADC3
+ if (&ADCD3 == adcp)
+ rccDisableADC3();
+#endif
+ }
+}
+
+/**
+ * @brief Starts an ADC conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start_conversion(ADCDriver *adcp) {
+ uint32_t mode;
+ uint32_t cr2;
+ const ADCConversionGroup *grpp = adcp->grpp;
+
+ /* DMA setup.*/
+ mode = adcp->dmamode;
+ if (grpp->circular) {
+ mode |= STM32_DMA_CR_CIRC;
+ if (adcp->depth > 1) {
+ /* If circular buffer depth > 1, then the half transfer interrupt
+ is enabled in order to allow streaming processing.*/
+ mode |= STM32_DMA_CR_HTIE;
+ }
+ }
+ dmaStreamSetMemory0(adcp->dmastp, adcp->samples);
+ dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels *
+ (uint32_t)adcp->depth);
+ dmaStreamSetMode(adcp->dmastp, mode);
+ dmaStreamEnable(adcp->dmastp);
+
+ /* ADC setup.*/
+ adcp->adc->SR = 0;
+ adcp->adc->SMPR1 = grpp->smpr1;
+ adcp->adc->SMPR2 = grpp->smpr2;
+ adcp->adc->HTR = grpp->htr;
+ adcp->adc->LTR = grpp->ltr;
+ adcp->adc->SQR1 = grpp->sqr1 | ADC_SQR1_NUM_CH(grpp->num_channels);
+ adcp->adc->SQR2 = grpp->sqr2;
+ adcp->adc->SQR3 = grpp->sqr3;
+
+ /* ADC configuration and start.*/
+ adcp->adc->CR1 = grpp->cr1 | ADC_CR1_OVRIE | ADC_CR1_SCAN;
+
+ /* Enforcing the mandatory bits in CR2.*/
+ cr2 = grpp->cr2 | ADC_CR2_DMA | ADC_CR2_DDS | ADC_CR2_ADON;
+
+ /* The start method is different dependign if HW or SW triggered, the
+ start is performed using the method specified in the CR2 configuration.*/
+ if ((cr2 & ADC_CR2_SWSTART) != 0) {
+ /* Initializing CR2 while keeping ADC_CR2_SWSTART at zero.*/
+ adcp->adc->CR2 = (cr2 | ADC_CR2_CONT) & ~ADC_CR2_SWSTART;
+
+ /* Finally enabling ADC_CR2_SWSTART.*/
+ adcp->adc->CR2 = (cr2 | ADC_CR2_CONT);
+ }
+ else
+ adcp->adc->CR2 = cr2;
+}
+
+/**
+ * @brief Stops an ongoing conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop_conversion(ADCDriver *adcp) {
+
+ dmaStreamDisable(adcp->dmastp);
+ adcp->adc->CR1 = 0;
+ /* Because ticket #822, preserving injected conversions.*/
+ adcp->adc->CR2 &= ~(ADC_CR2_SWSTART);
+ adcp->adc->CR2 = ADC_CR2_ADON;
+}
+
+/**
+ * @brief Enables the TSVREFE bit.
+ * @details The TSVREFE bit is required in order to sample the internal
+ * temperature sensor and internal reference voltage.
+ * @note This is an STM32-only functionality.
+ */
+void adcSTM32EnableTSVREFE(void) {
+
+ ADC->CCR |= ADC_CCR_TSVREFE;
+}
+
+/**
+ * @brief Disables the TSVREFE bit.
+ * @details The TSVREFE bit is required in order to sample the internal
+ * temperature sensor and internal reference voltage.
+ * @note This is an STM32-only functionality.
+ */
+void adcSTM32DisableTSVREFE(void) {
+
+ ADC->CCR &= ~ADC_CCR_TSVREFE;
+}
+
+/**
+ * @brief Enables the VBATE bit.
+ * @details The VBATE bit is required in order to sample the VBAT channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ */
+void adcSTM32EnableVBATE(void) {
+
+ ADC->CCR |= ADC_CCR_VBATE;
+}
+
+/**
+ * @brief Disables the VBATE bit.
+ * @details The VBATE bit is required in order to sample the VBAT channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ */
+void adcSTM32DisableVBATE(void) {
+
+ ADC->CCR &= ~ADC_CCR_VBATE;
+}
+
+#endif /* HAL_USE_ADC */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.h
new file mode 100644
index 0000000..5202f94
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv2/hal_adc_lld.h
@@ -0,0 +1,486 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ADCv2/hal_adc_lld.h
+ * @brief STM32 ADC subsystem low level driver header.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#ifndef HAL_ADC_LLD_H
+#define HAL_ADC_LLD_H
+
+#if HAL_USE_ADC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Absolute Maximum Ratings
+ * @{
+ */
+/**
+ * @brief Minimum ADC clock frequency.
+ */
+#define STM32_ADCCLK_MIN 600000
+
+/**
+ * @brief Maximum ADC clock frequency.
+ */
+#if defined(STM32F4XX) || defined(__DOXYGEN__)
+#define STM32_ADCCLK_MAX 36000000
+#else
+#define STM32_ADCCLK_MAX 30000000
+#endif
+/** @} */
+
+/**
+ * @name Triggers selection
+ * @{
+ */
+#define ADC_CR2_EXTEN_MASK (3U << 28U)
+#define ADC_CR2_EXTEN_DISABLED (0U << 28U)
+#define ADC_CR2_EXTEN_RISING (1U << 28U)
+#define ADC_CR2_EXTEN_FALLING (2U << 28U)
+#define ADC_CR2_EXTEN_BOTH (3U << 28U)
+
+#define ADC_CR2_EXTSEL_MASK (15U << 24U)
+#define ADC_CR2_EXTSEL_SRC(n) ((n) << 24U)
+/** @} */
+
+/**
+ * @name ADC clock divider settings
+ * @{
+ */
+#define ADC_CCR_ADCPRE_DIV2 0
+#define ADC_CCR_ADCPRE_DIV4 1
+#define ADC_CCR_ADCPRE_DIV6 2
+#define ADC_CCR_ADCPRE_DIV8 3
+/** @} */
+
+/**
+ * @name Available analog channels
+ * @{
+ */
+#define ADC_CHANNEL_IN0 0 /**< @brief External analog input 0. */
+#define ADC_CHANNEL_IN1 1 /**< @brief External analog input 1. */
+#define ADC_CHANNEL_IN2 2 /**< @brief External analog input 2. */
+#define ADC_CHANNEL_IN3 3 /**< @brief External analog input 3. */
+#define ADC_CHANNEL_IN4 4 /**< @brief External analog input 4. */
+#define ADC_CHANNEL_IN5 5 /**< @brief External analog input 5. */
+#define ADC_CHANNEL_IN6 6 /**< @brief External analog input 6. */
+#define ADC_CHANNEL_IN7 7 /**< @brief External analog input 7. */
+#define ADC_CHANNEL_IN8 8 /**< @brief External analog input 8. */
+#define ADC_CHANNEL_IN9 9 /**< @brief External analog input 9. */
+#define ADC_CHANNEL_IN10 10 /**< @brief External analog input 10. */
+#define ADC_CHANNEL_IN11 11 /**< @brief External analog input 11. */
+#define ADC_CHANNEL_IN12 12 /**< @brief External analog input 12. */
+#define ADC_CHANNEL_IN13 13 /**< @brief External analog input 13. */
+#define ADC_CHANNEL_IN14 14 /**< @brief External analog input 14. */
+#define ADC_CHANNEL_IN15 15 /**< @brief External analog input 15. */
+#define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor.
+ @note Available onADC1 only. */
+#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference.
+ @note Available onADC1 only. */
+#define ADC_CHANNEL_VBAT 18 /**< @brief VBAT.
+ @note Available onADC1 only. */
+/** @} */
+
+/**
+ * @name Sampling rates
+ * @{
+ */
+#define ADC_SAMPLE_3 0 /**< @brief 3 cycles sampling time. */
+#define ADC_SAMPLE_15 1 /**< @brief 15 cycles sampling time. */
+#define ADC_SAMPLE_28 2 /**< @brief 28 cycles sampling time. */
+#define ADC_SAMPLE_56 3 /**< @brief 56 cycles sampling time. */
+#define ADC_SAMPLE_84 4 /**< @brief 84 cycles sampling time. */
+#define ADC_SAMPLE_112 5 /**< @brief 112 cycles sampling time. */
+#define ADC_SAMPLE_144 6 /**< @brief 144 cycles sampling time. */
+#define ADC_SAMPLE_480 7 /**< @brief 480 cycles sampling time. */
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief ADC common clock divider.
+ * @note This setting is influenced by the VDDA voltage and other
+ * external conditions, please refer to the datasheet for more
+ * info.
+ * See section 5.3.20 "12-bit ADC characteristics".
+ */
+#if !defined(STM32_ADC_ADCPRE) || defined(__DOXYGEN__)
+#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV2
+#endif
+
+/**
+ * @brief ADC1 driver enable switch.
+ * @details If set to @p TRUE the support for ADC1 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__)
+#define STM32_ADC_USE_ADC1 FALSE
+#endif
+
+/**
+ * @brief ADC2 driver enable switch.
+ * @details If set to @p TRUE the support for ADC2 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_ADC_USE_ADC2) || defined(__DOXYGEN__)
+#define STM32_ADC_USE_ADC2 FALSE
+#endif
+
+/**
+ * @brief ADC3 driver enable switch.
+ * @details If set to @p TRUE the support for ADC3 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_ADC_USE_ADC3) || defined(__DOXYGEN__)
+#define STM32_ADC_USE_ADC3 FALSE
+#endif
+
+/**
+ * @brief DMA stream used for ADC1 operations.
+ */
+#if !defined(STM32_ADC_ADC1_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4)
+#endif
+
+/**
+ * @brief DMA stream used for ADC2 operations.
+ */
+#if !defined(STM32_ADC_ADC2_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
+#endif
+
+/**
+ * @brief DMA stream used for ADC3 operations.
+ */
+#if !defined(STM32_ADC_ADC3_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1)
+#endif
+
+/**
+ * @brief ADC1 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC1_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC2 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_ADC_ADC2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC2_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC3 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_ADC_ADC3_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC3_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC interrupt priority level setting.
+ * @note This setting is shared among ADC1, ADC2 and ADC3 because
+ * all ADCs share the same vector.
+ */
+#if !defined(STM32_ADC_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_IRQ_PRIORITY 5
+#endif
+
+/**
+ * @brief ADC1 DMA interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5
+#endif
+
+/**
+ * @brief ADC2 DMA interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC2_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5
+#endif
+
+/**
+ * @brief ADC3 DMA interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC3_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1
+#error "ADC1 not present in the selected device"
+#endif
+
+#if STM32_ADC_USE_ADC2 && !STM32_HAS_ADC2
+#error "ADC2 not present in the selected device"
+#endif
+
+#if STM32_ADC_USE_ADC3 && !STM32_HAS_ADC3
+#error "ADC3 not present in the selected device"
+#endif
+
+#if !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC2 && !STM32_ADC_USE_ADC3
+#error "ADC driver activated but no ADC peripheral assigned"
+#endif
+
+#if STM32_ADC_USE_ADC1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_MSK)
+#error "invalid DMA stream associated to ADC1"
+#endif
+
+#if STM32_ADC_USE_ADC2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC2_DMA_STREAM, STM32_ADC2_DMA_MSK)
+#error "invalid DMA stream associated to ADC2"
+#endif
+
+#if STM32_ADC_USE_ADC3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC3_DMA_STREAM, STM32_ADC3_DMA_MSK)
+#error "invalid DMA stream associated to ADC3"
+#endif
+
+/* ADC clock related settings and checks.*/
+#if STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV2
+#define STM32_ADCCLK (STM32_PCLK2 / 2)
+#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV4
+#define STM32_ADCCLK (STM32_PCLK2 / 4)
+#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV6
+#define STM32_ADCCLK (STM32_PCLK2 / 6)
+#elif STM32_ADC_ADCPRE == ADC_CCR_ADCPRE_DIV8
+#define STM32_ADCCLK (STM32_PCLK2 / 8)
+#else
+#error "invalid STM32_ADC_ADCPRE value specified"
+#endif
+
+#if (STM32_ADCCLK < STM32_ADCCLK_MIN) || (STM32_ADCCLK > STM32_ADCCLK_MAX)
+#error "STM32_ADCCLK outside acceptable range (STM32_ADCCLK_MIN...STM32_ADCCLK_MAX)"
+#endif
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC sample data type.
+ */
+typedef uint16_t adcsample_t;
+
+/**
+ * @brief Channels number in a conversion group.
+ */
+typedef uint16_t adc_channels_num_t;
+
+/**
+ * @brief Possible ADC failure causes.
+ * @note Error codes are architecture dependent and should not relied
+ * upon.
+ */
+typedef enum {
+ ADC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */
+ ADC_ERR_OVERFLOW = 1, /**< ADC overflow condition. */
+ ADC_ERR_WATCHDOG = 2 /**< ADC watchdog condition. */
+} adcerror_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the ADC driver structure.
+ */
+#define adc_lld_driver_fields \
+ /* Pointer to the ADCx registers block.*/ \
+ ADC_TypeDef *adc; \
+ /* Pointer to associated DMA channel.*/ \
+ const stm32_dma_stream_t *dmastp; \
+ /* DMA mode bit mask.*/ \
+ uint32_t dmamode
+
+/**
+ * @brief Low level fields of the ADC configuration structure.
+ */
+#define adc_lld_config_fields \
+ /* Dummy configuration, it is not needed.*/ \
+ uint32_t dummy
+
+/**
+ * @brief Low level fields of the ADC configuration structure.
+ */
+#define adc_lld_configuration_group_fields \
+ /* ADC CR1 register initialization data. \
+ NOTE: All the required bits must be defined into this field except \
+ @p ADC_CR1_SCAN that is enforced inside the driver.*/ \
+ uint32_t cr1; \
+ /* ADC CR2 register initialization data. \
+ NOTE: All the required bits must be defined into this field except \
+ @p ADC_CR2_DMA, @p ADC_CR2_CONT and @p ADC_CR2_ADON that are \
+ enforced inside the driver.*/ \
+ uint32_t cr2; \
+ /* ADC SMPR1 register initialization data. \
+ NOTE: In this field must be specified the sample times for channels \
+ 10...18.*/ \
+ uint32_t smpr1; \
+ /* ADC SMPR2 register initialization data. \
+ NOTE: In this field must be specified the sample times for channels \
+ 0...9.*/ \
+ uint32_t smpr2; \
+ /* ADC watchdog high threshold register. \
+ NOTE: This field defines the high threshold of the analog watchdog.*/ \
+ uint16_t htr; \
+ /* ADC watchdog low threshold register. \
+ NOTE: This field defines the low threshold of the analog watchdog.*/ \
+ uint16_t ltr; \
+ /* ADC SQR1 register initialization data. \
+ NOTE: Conversion group sequence 13...16 + sequence length.*/ \
+ uint32_t sqr1; \
+ /* ADC SQR2 register initialization data. \
+ NOTE: Conversion group sequence 7...12.*/ \
+ uint32_t sqr2; \
+ /* ADC SQR3 register initialization data. \
+ NOTE: Conversion group sequence 1...6.*/ \
+ uint32_t sqr3
+
+/**
+ * @name Sequences building helper macros
+ * @{
+ */
+/**
+ * @brief Number of channels in a conversion sequence.
+ */
+#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20)
+
+#define ADC_SQR3_SQ1_N(n) ((n) << 0) /**< @brief 1st channel in seq. */
+#define ADC_SQR3_SQ2_N(n) ((n) << 5) /**< @brief 2nd channel in seq. */
+#define ADC_SQR3_SQ3_N(n) ((n) << 10) /**< @brief 3rd channel in seq. */
+#define ADC_SQR3_SQ4_N(n) ((n) << 15) /**< @brief 4th channel in seq. */
+#define ADC_SQR3_SQ5_N(n) ((n) << 20) /**< @brief 5th channel in seq. */
+#define ADC_SQR3_SQ6_N(n) ((n) << 25) /**< @brief 6th channel in seq. */
+
+#define ADC_SQR2_SQ7_N(n) ((n) << 0) /**< @brief 7th channel in seq. */
+#define ADC_SQR2_SQ8_N(n) ((n) << 5) /**< @brief 8th channel in seq. */
+#define ADC_SQR2_SQ9_N(n) ((n) << 10) /**< @brief 9th channel in seq. */
+#define ADC_SQR2_SQ10_N(n) ((n) << 15) /**< @brief 10th channel in seq.*/
+#define ADC_SQR2_SQ11_N(n) ((n) << 20) /**< @brief 11th channel in seq.*/
+#define ADC_SQR2_SQ12_N(n) ((n) << 25) /**< @brief 12th channel in seq.*/
+
+#define ADC_SQR1_SQ13_N(n) ((n) << 0) /**< @brief 13th channel in seq.*/
+#define ADC_SQR1_SQ14_N(n) ((n) << 5) /**< @brief 14th channel in seq.*/
+#define ADC_SQR1_SQ15_N(n) ((n) << 10) /**< @brief 15th channel in seq.*/
+#define ADC_SQR1_SQ16_N(n) ((n) << 15) /**< @brief 16th channel in seq.*/
+/** @} */
+
+/**
+ * @name Sampling rate settings helper macros
+ * @{
+ */
+#define ADC_SMPR2_SMP_AN0(n) ((n) << 0) /**< @brief AN0 sampling time. */
+#define ADC_SMPR2_SMP_AN1(n) ((n) << 3) /**< @brief AN1 sampling time. */
+#define ADC_SMPR2_SMP_AN2(n) ((n) << 6) /**< @brief AN2 sampling time. */
+#define ADC_SMPR2_SMP_AN3(n) ((n) << 9) /**< @brief AN3 sampling time. */
+#define ADC_SMPR2_SMP_AN4(n) ((n) << 12) /**< @brief AN4 sampling time. */
+#define ADC_SMPR2_SMP_AN5(n) ((n) << 15) /**< @brief AN5 sampling time. */
+#define ADC_SMPR2_SMP_AN6(n) ((n) << 18) /**< @brief AN6 sampling time. */
+#define ADC_SMPR2_SMP_AN7(n) ((n) << 21) /**< @brief AN7 sampling time. */
+#define ADC_SMPR2_SMP_AN8(n) ((n) << 24) /**< @brief AN8 sampling time. */
+#define ADC_SMPR2_SMP_AN9(n) ((n) << 27) /**< @brief AN9 sampling time. */
+
+#define ADC_SMPR1_SMP_AN10(n) ((n) << 0) /**< @brief AN10 sampling time. */
+#define ADC_SMPR1_SMP_AN11(n) ((n) << 3) /**< @brief AN11 sampling time. */
+#define ADC_SMPR1_SMP_AN12(n) ((n) << 6) /**< @brief AN12 sampling time. */
+#define ADC_SMPR1_SMP_AN13(n) ((n) << 9) /**< @brief AN13 sampling time. */
+#define ADC_SMPR1_SMP_AN14(n) ((n) << 12) /**< @brief AN14 sampling time. */
+#define ADC_SMPR1_SMP_AN15(n) ((n) << 15) /**< @brief AN15 sampling time. */
+#define ADC_SMPR1_SMP_SENSOR(n) ((n) << 18) /**< @brief Temperature Sensor
+ sampling time. */
+#define ADC_SMPR1_SMP_VREF(n) ((n) << 21) /**< @brief Voltage Reference
+ sampling time. */
+#define ADC_SMPR1_SMP_VBAT(n) ((n) << 24) /**< @brief VBAT sampling time. */
+/** @} */
+
+/**
+ * @name Threshold settings helper macros
+ * @{
+ */
+/**
+ * @brief High threshold limitation.
+ */
+#define ADC_HTR(n) ((n > ADC_HTR_HT) ? ADC_HTR_HT : n)
+/**
+ * @brief Low threshold limitation.
+ */
+#define ADC_LTR(n) ((n > ADC_LTR_LT) ? ADC_LTR_LT : n)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__)
+extern ADCDriver ADCD1;
+#endif
+
+#if STM32_ADC_USE_ADC2 && !defined(__DOXYGEN__)
+extern ADCDriver ADCD2;
+#endif
+
+#if STM32_ADC_USE_ADC3 && !defined(__DOXYGEN__)
+extern ADCDriver ADCD3;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void adc_lld_init(void);
+ void adc_lld_start(ADCDriver *adcp);
+ void adc_lld_stop(ADCDriver *adcp);
+ void adc_lld_start_conversion(ADCDriver *adcp);
+ void adc_lld_stop_conversion(ADCDriver *adcp);
+ void adcSTM32EnableTSVREFE(void);
+ void adcSTM32DisableTSVREFE(void);
+ void adcSTM32EnableVBATE(void);
+ void adcSTM32DisableVBATE(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_ADC */
+
+#endif /* HAL_ADC_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv2/notes.txt b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv2/notes.txt
new file mode 100644
index 0000000..a13d327
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv2/notes.txt
@@ -0,0 +1,13 @@
+STM32 ADCv2 driver.
+
+Driver capability:
+
+- Supports the STM32 "advanced" ADC found on F2, F4 and F7 sub-families.
+
+The file registry must export:
+
+STM32_HAS_ADCx - ADCx presence flag (1..3).
+STM32_ADC_HANDLER - IRQ vector name for ADCs (shared).
+STM32_ADC_NUMBER - IRQ vector number for ADCs (shared).
+STM32_ADCx_DMA_MSK - Mask of the compatible DMA channels.
+STM32_ADCx_DMA_CHN - Mask of the channels mapping.
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv3/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv3/driver.mk
new file mode 100644
index 0000000..049021c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv3/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.c
new file mode 100644
index 0000000..8df21bf
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.c
@@ -0,0 +1,1009 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ADCv3/hal_adc_lld.c
+ * @brief STM32 ADC subsystem low level driver source.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_ADC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define ADC1_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_CHN)
+
+#define ADC2_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_ADC_ADC2_DMA_STREAM, STM32_ADC2_DMA_CHN)
+
+#define ADC3_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_ADC_ADC3_DMA_STREAM, STM32_ADC3_DMA_CHN)
+
+#define ADC4_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_ADC_ADC4_DMA_STREAM, STM32_ADC4_DMA_CHN)
+
+#if STM32_ADC_DUAL_MODE
+#if STM32_ADC_COMPACT_SAMPLES
+/* Compact type dual mode.*/
+#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD)
+#define ADC_DMA_MDMA ADC_CCR_MDMA_HWORD
+
+#else /* !STM32_ADC_COMPACT_SAMPLES */
+/* Large type dual mode.*/
+#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD)
+#define ADC_DMA_MDMA ADC_CCR_MDMA_WORD
+#endif /* !STM32_ADC_COMPACT_SAMPLES */
+
+#else /* !STM32_ADC_DUAL_MODE */
+#if STM32_ADC_COMPACT_SAMPLES
+/* Compact type single mode.*/
+#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_PSIZE_BYTE)
+#define ADC_DMA_MDMA ADC_CCR_MDMA_DISABLED
+
+#else /* !STM32_ADC_COMPACT_SAMPLES */
+/* Large type single mode.*/
+#define ADC_DMA_SIZE (STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD)
+#define ADC_DMA_MDMA ADC_CCR_MDMA_DISABLED
+#endif /* !STM32_ADC_COMPACT_SAMPLES */
+#endif /* !STM32_ADC_DUAL_MODE */
+
+/* Addressing header differences.*/
+#if !defined(ADC_IER_OVRIE)
+#define ADC_IER_OVRIE ADC_IER_OVR
+#endif
+
+#if !defined(ADC_IER_AWD1IE)
+#define ADC_IER_AWD1IE ADC_IER_AWD1
+#endif
+
+#if !defined(ADC_CR_ADVREGEN)
+#define ADC_CR_ADVREGEN ADC_CR_ADVREGEN_0
+#endif
+
+#if !defined(ADC_CR_DEEPPWD)
+#define ADC_CR_DEEPPWD ADC_CR_ADVREGEN_1
+#endif
+
+#if !defined(ADC_ISR_ADRDY)
+#define ADC_ISR_ADRDY ADC_ISR_ADRD
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief ADC1 driver identifier.*/
+#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__)
+ADCDriver ADCD1;
+#endif
+
+/** @brief ADC2 driver identifier.*/
+#if STM32_ADC_USE_ADC2 || defined(__DOXYGEN__)
+ADCDriver ADCD2;
+#endif
+
+/** @brief ADC3 driver identifier.*/
+#if STM32_ADC_USE_ADC3 || defined(__DOXYGEN__)
+ADCDriver ADCD3;
+#endif
+
+/** @brief ADC4 driver identifier.*/
+#if STM32_ADC_USE_ADC4 || defined(__DOXYGEN__)
+ADCDriver ADCD4;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+static const ADCConfig default_config = {
+ .difsel = 0
+};
+
+static uint32_t clkmask;
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the ADC voltage regulator.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ */
+static void adc_lld_vreg_on(ADCDriver *adcp) {
+
+ adcp->adcm->CR = 0; /* See RM.*/
+ adcp->adcm->CR = ADC_CR_ADVREGEN;
+#if STM32_ADC_DUAL_MODE
+ adcp->adcs->CR = ADC_CR_ADVREGEN;
+#endif
+ osalSysPolledDelayX(OSAL_US2RTC(STM32_HCLK, 20));
+}
+
+/**
+ * @brief Disables the ADC voltage regulator.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ */
+static void adc_lld_vreg_off(ADCDriver *adcp) {
+
+ adcp->adcm->CR = 0; /* See RM.*/
+ adcp->adcm->CR = ADC_CR_DEEPPWD;
+#if STM32_ADC_DUAL_MODE
+ adcp->adcs->CR = 0;
+ adcp->adcs->CR = ADC_CR_DEEPPWD;
+#endif
+}
+
+/**
+ * @brief Calibrates and ADC unit.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ */
+static void adc_lld_calibrate(ADCDriver *adcp) {
+
+ osalDbgAssert(adcp->adcm->CR == ADC_CR_ADVREGEN, "invalid register state");
+
+ /* Differential calibration for master ADC.*/
+ adcp->adcm->CR = ADC_CR_ADVREGEN | ADC_CR_ADCALDIF;
+ adcp->adcm->CR = ADC_CR_ADVREGEN | ADC_CR_ADCALDIF | ADC_CR_ADCAL;
+ while ((adcp->adcm->CR & ADC_CR_ADCAL) != 0)
+ ;
+
+ /* Single-ended calibration for master ADC.*/
+ adcp->adcm->CR = ADC_CR_ADVREGEN;
+ adcp->adcm->CR = ADC_CR_ADVREGEN | ADC_CR_ADCAL;
+ while ((adcp->adcm->CR & ADC_CR_ADCAL) != 0)
+ ;
+
+#if STM32_ADC_DUAL_MODE
+ osalDbgAssert(adcp->adcs->CR == ADC_CR_ADVREGEN, "invalid register state");
+
+ /* Differential calibration for slave ADC.*/
+ adcp->adcs->CR = ADC_CR_ADVREGEN | ADC_CR_ADCALDIF;
+ adcp->adcs->CR = ADC_CR_ADVREGEN | ADC_CR_ADCALDIF | ADC_CR_ADCAL;
+ while ((adcp->adcs->CR & ADC_CR_ADCAL) != 0)
+ ;
+
+ /* Single-ended calibration for slave ADC.*/
+ adcp->adcs->CR = ADC_CR_ADVREGEN;
+ adcp->adcs->CR = ADC_CR_ADVREGEN | ADC_CR_ADCAL;
+ while ((adcp->adcs->CR & ADC_CR_ADCAL) != 0)
+ ;
+#endif
+}
+
+/**
+ * @brief Enables the ADC analog circuit.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ */
+static void adc_lld_analog_on(ADCDriver *adcp) {
+
+ adcp->adcm->CR |= ADC_CR_ADEN;
+ while ((adcp->adcm->ISR & ADC_ISR_ADRDY) == 0)
+ ;
+#if STM32_ADC_DUAL_MODE
+ adcp->adcs->CR |= ADC_CR_ADEN;
+ while ((adcp->adcs->ISR & ADC_ISR_ADRDY) == 0)
+ ;
+#endif
+}
+
+/**
+ * @brief Disables the ADC analog circuit.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ */
+static void adc_lld_analog_off(ADCDriver *adcp) {
+
+ adcp->adcm->CR |= ADC_CR_ADDIS;
+ while ((adcp->adcm->CR & ADC_CR_ADDIS) != 0)
+ ;
+#if STM32_ADC_DUAL_MODE
+ adcp->adcs->CR |= ADC_CR_ADDIS;
+ while ((adcp->adcs->CR & ADC_CR_ADDIS) != 0)
+ ;
+#endif
+}
+
+/**
+ * @brief Stops an ongoing conversion, if any.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ */
+static void adc_lld_stop_adc(ADCDriver *adcp) {
+
+ if (adcp->adcm->CR & ADC_CR_ADSTART) {
+ adcp->adcm->CR |= ADC_CR_ADSTP;
+ while (adcp->adcm->CR & ADC_CR_ADSTP)
+ ;
+ adcp->adcm->IER = 0;
+ }
+}
+
+/**
+ * @brief ADC DMA service routine.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void adc_lld_serve_dma_interrupt(ADCDriver *adcp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ /* DMA, this could help only if the DMA tries to access an unmapped
+ address space or violates alignment rules.*/
+ _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE);
+ }
+ else {
+ /* It is possible that the conversion group has already be reset by the
+ ADC error handler, in this case this interrupt is spurious.*/
+ if (adcp->grpp != NULL) {
+ if ((flags & STM32_DMA_ISR_TCIF) != 0) {
+ /* Transfer complete processing.*/
+ _adc_isr_full_code(adcp);
+ }
+ else if ((flags & STM32_DMA_ISR_HTIF) != 0) {
+ /* Half transfer processing.*/
+ _adc_isr_half_code(adcp);
+ }
+ }
+ }
+}
+
+/**
+ * @brief ADC IRQ service routine.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ * @param[in] isr content of the ISR register
+ */
+static void adc_lld_serve_interrupt(ADCDriver *adcp, uint32_t isr) {
+
+ /* It could be a spurious interrupt caused by overflows after DMA disabling,
+ just ignore it in this case.*/
+ if (adcp->grpp != NULL) {
+ /* Note, an overflow may occur after the conversion ended before the driver
+ is able to stop the ADC, this is why the DMA channel is checked too.*/
+ if ((isr & ADC_ISR_OVR) &&
+ (dmaStreamGetTransactionSize(adcp->dmastp) > 0)) {
+ /* ADC overflow condition, this could happen only if the DMA is unable
+ to read data fast enough.*/
+ _adc_isr_error_code(adcp, ADC_ERR_OVERFLOW);
+ }
+ if (isr & ADC_ISR_AWD1) {
+ /* Analog watchdog error.*/
+ _adc_isr_error_code(adcp, ADC_ERR_AWD1);
+ }
+ if (isr & ADC_ISR_AWD2) {
+ /* Analog watchdog error.*/
+ _adc_isr_error_code(adcp, ADC_ERR_AWD2);
+ }
+ if (isr & ADC_ISR_AWD3) {
+ /* Analog watchdog error.*/
+ _adc_isr_error_code(adcp, ADC_ERR_AWD3);
+ }
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2 || defined(__DOXYGEN__)
+/**
+ * @brief ADC1/ADC2 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_ADC1_HANDLER) {
+ uint32_t isr;
+
+ OSAL_IRQ_PROLOGUE();
+
+#if STM32_ADC_DUAL_MODE
+
+ isr = ADC1->ISR;
+ isr |= ADC2->ISR;
+ ADC1->ISR = isr;
+ ADC2->ISR = isr;
+#if defined(STM32_ADC_ADC12_IRQ_HOOK)
+ STM32_ADC_ADC12_IRQ_HOOK
+#endif
+ adc_lld_serve_interrupt(&ADCD1, isr);
+
+#else /* !STM32_ADC_DUAL_MODE */
+
+#if STM32_ADC_USE_ADC1
+ isr = ADC1->ISR;
+ ADC1->ISR = isr;
+#if defined(STM32_ADC_ADC1_IRQ_HOOK)
+ STM32_ADC_ADC1_IRQ_HOOK
+#endif
+ adc_lld_serve_interrupt(&ADCD1, isr);
+#endif
+
+#if STM32_ADC_USE_ADC2
+ isr = ADC2->ISR;
+ ADC2->ISR = isr;
+#if defined(STM32_ADC_ADC2_IRQ_HOOK)
+ STM32_ADC_ADC2_IRQ_HOOK
+#endif
+ adc_lld_serve_interrupt(&ADCD2, isr);
+#endif
+
+#endif /* !STM32_ADC_DUAL_MODE */
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* STM32_ADC_USE_ADC1 */
+
+#if STM32_ADC_USE_ADC3 || defined(__DOXYGEN__)
+/**
+ * @brief ADC3 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_ADC3_HANDLER) {
+ uint32_t isr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ isr = ADC3->ISR;
+ ADC3->ISR = isr;
+#if defined(STM32_ADC_ADC3_IRQ_HOOK)
+ STM32_ADC_ADC3_IRQ_HOOK
+#endif
+ adc_lld_serve_interrupt(&ADCD3, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#if STM32_ADC_DUAL_MODE
+/**
+ * @brief ADC4 interrupt handler (as ADC3 slave).
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_ADC4_HANDLER) {
+ uint32_t isr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ isr = ADC4->ISR;
+ ADC4->ISR = isr;
+
+ adc_lld_serve_interrupt(&ADCD3, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* STM32_ADC_DUAL_MODE */
+#endif /* STM32_ADC_USE_ADC3 */
+
+#if STM32_ADC_USE_ADC4 || defined(__DOXYGEN__)
+/**
+ * @brief ADC4 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_ADC4_HANDLER) {
+ uint32_t isr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ isr = ADC4->ISR;
+ ADC4->ISR = isr;
+
+ adc_lld_serve_interrupt(&ADCD4, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* STM32_ADC_USE_ADC4 */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level ADC driver initialization.
+ *
+ * @notapi
+ */
+void adc_lld_init(void) {
+
+ clkmask = 0;
+
+#if STM32_ADC_USE_ADC1
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD1);
+#if defined(ADC1_2_COMMON)
+ ADCD1.adcc = ADC1_2_COMMON;
+#elif defined(ADC12_COMMON)
+ ADCD1.adcc = ADC12_COMMON;
+#elif defined(ADC123_COMMON)
+ ADCD1.adcc = ADC123_COMMON;
+#else
+ ADCD1.adcc = ADC1_COMMON;
+#endif
+ ADCD1.adcm = ADC1;
+#if STM32_ADC_DUAL_MODE
+ ADCD1.adcs = ADC2;
+#endif
+ ADCD1.dmastp = NULL;
+ ADCD1.dmamode = ADC_DMA_SIZE |
+ STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+#endif /* STM32_ADC_USE_ADC1 */
+
+#if STM32_ADC_USE_ADC2
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD2);
+#if defined(ADC1_2_COMMON)
+ ADCD2.adcc = ADC1_2_COMMON;
+#elif defined(ADC12_COMMON)
+ ADCD2.adcc = ADC12_COMMON;
+#elif defined(ADC123_COMMON)
+ ADCD2.adcc = ADC123_COMMON;
+#endif
+ ADCD2.adcm = ADC2;
+ ADCD2.dmastp = NULL;
+ ADCD2.dmamode = ADC_DMA_SIZE |
+ STM32_DMA_CR_PL(STM32_ADC_ADC2_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+#endif /* STM32_ADC_USE_ADC2 */
+
+#if STM32_ADC_USE_ADC3
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD3);
+#if defined(ADC3_4_COMMON)
+ ADCD3.adcc = ADC3_4_COMMON;
+#elif defined(ADC345_COMMON)
+ ADCD3.adcc = ADC345_COMMON;
+#elif defined(ADC123_COMMON)
+ ADCD3.adcc = ADC123_COMMON;
+#else
+ ADCD3.adcc = ADC3_COMMON;
+#endif
+ ADCD3.adcm = ADC3;
+#if STM32_ADC_DUAL_MODE
+ ADCD3.adcs = ADC4;
+#endif
+ ADCD3.dmastp = NULL;
+ ADCD3.dmamode = ADC_DMA_SIZE |
+ STM32_DMA_CR_PL(STM32_ADC_ADC3_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+#endif /* STM32_ADC_USE_ADC3 */
+
+#if STM32_ADC_USE_ADC4
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD4);
+#if defined(ADC3_4_COMMON)
+ ADCD4.adcc = ADC3_4_COMMON;
+#elif defined(ADC345_COMMON)
+ ADCD4.adcc = ADC345_COMMON;
+#endif
+ ADCD4.adcm = ADC4;
+ ADCD4.dmastp = NULL;
+ ADCD4.dmamode = ADC_DMA_SIZE |
+ STM32_DMA_CR_PL(STM32_ADC_ADC4_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+#endif /* STM32_ADC_USE_ADC4 */
+
+ /* IRQs setup.*/
+#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2
+ nvicEnableVector(STM32_ADC1_NUMBER, STM32_ADC_ADC12_IRQ_PRIORITY);
+#endif
+#if STM32_ADC_USE_ADC3
+ nvicEnableVector(STM32_ADC3_NUMBER, STM32_ADC_ADC3_IRQ_PRIORITY);
+#if STM32_ADC_DUAL_MODE
+ nvicEnableVector(STM32_ADC4_NUMBER, STM32_ADC_ADC3_IRQ_PRIORITY);
+#endif
+#endif
+#if STM32_ADC_USE_ADC4
+ nvicEnableVector(STM32_ADC4_NUMBER, STM32_ADC_ADC4_IRQ_PRIORITY);
+#endif
+
+ /* ADC units pre-initializations.*/
+#if defined(STM32F3XX)
+#if STM32_HAS_ADC1 && STM32_HAS_ADC2
+#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2
+ rccEnableADC12(true);
+ rccResetADC12();
+ ADC1_2_COMMON->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_MDMA;
+ rccDisableADC12();
+#endif
+#else
+#if STM32_ADC_USE_ADC1
+ rccEnableADC12(true);
+ rccResetADC12();
+ ADC1_COMMON->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_MDMA;
+ rccDisableADC12();
+#endif
+#endif
+#if STM32_ADC_USE_ADC3 || STM32_ADC_USE_ADC4
+ rccEnableADC34(true);
+ rccResetADC34();
+ ADC3_4_COMMON->CCR = STM32_ADC_ADC34_CLOCK_MODE | ADC_DMA_MDMA;
+ rccDisableADC34();
+#endif
+#endif
+
+#if defined(STM32L4XX) || defined(STM32L4XXP)
+ rccEnableADC123(true);
+ rccResetADC123();
+#if defined(ADC1_2_COMMON)
+ ADC1_2_COMMON->CCR = STM32_ADC_ADC123_PRESC | STM32_ADC_ADC123_CLOCK_MODE | ADC_DMA_MDMA;
+#elif defined(ADC123_COMMON)
+ ADC123_COMMON->CCR = STM32_ADC_ADC123_PRESC | STM32_ADC_ADC123_CLOCK_MODE | ADC_DMA_MDMA;
+#else
+ ADC1_COMMON->CCR = STM32_ADC_ADC123_PRESC | STM32_ADC_ADC123_CLOCK_MODE | ADC_DMA_MDMA;
+#endif
+
+ rccDisableADC123();
+#endif
+
+#if defined(STM32G4XX)
+#if STM32_ADC_USE_ADC1 || STM32_ADC_USE_ADC2
+ rccEnableADC12(true);
+ rccResetADC12();
+ ADC12_COMMON->CCR = STM32_ADC_ADC12_PRESC | STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_MDMA;
+ rccDisableADC12();
+#endif
+#if STM32_ADC_USE_ADC3 || STM32_ADC_USE_ADC4
+ rccEnableADC345(true);
+ rccResetADC345();
+ ADC345_COMMON->CCR = STM32_ADC_ADC345_PRESC | STM32_ADC_ADC345_CLOCK_MODE | ADC_DMA_MDMA;
+ rccDisableADC345();
+#endif
+#endif
+}
+
+/**
+ * @brief Configures and activates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start(ADCDriver *adcp) {
+
+ /* Handling the default configuration.*/
+ if (adcp->config == NULL) {
+ adcp->config = &default_config;
+ }
+
+ /* If in stopped state then enables the ADC and DMA clocks.*/
+ if (adcp->state == ADC_STOP) {
+#if STM32_ADC_USE_ADC1
+ if (&ADCD1 == adcp) {
+ adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC1_DMA_STREAM,
+ STM32_ADC_ADC1_DMA_IRQ_PRIORITY,
+ (stm32_dmaisr_t)adc_lld_serve_dma_interrupt,
+ (void *)adcp);
+ osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
+
+ clkmask |= (1 << 0);
+#if defined(STM32F3XX) || defined(STM32G4XX)
+ rccEnableADC12(true);
+#endif
+#if defined(STM32L4XX) || defined(STM32L4XXP)
+ rccEnableADC123(true);
+#endif
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(adcp->dmastp, STM32_DMAMUX1_ADC1);
+#endif
+ }
+#endif /* STM32_ADC_USE_ADC1 */
+
+#if STM32_ADC_USE_ADC2
+ if (&ADCD2 == adcp) {
+ adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC2_DMA_STREAM,
+ STM32_ADC_ADC2_DMA_IRQ_PRIORITY,
+ (stm32_dmaisr_t)adc_lld_serve_dma_interrupt,
+ (void *)adcp);
+ osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
+
+ clkmask |= (1 << 1);
+#if defined(STM32F3XX) || defined(STM32G4XX)
+ rccEnableADC12(true);
+#endif
+#if defined(STM32L4XX) || defined(STM32L4XXP)
+ rccEnableADC123(true);
+#endif
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(adcp->dmastp, STM32_DMAMUX1_ADC2);
+#endif
+ }
+#endif /* STM32_ADC_USE_ADC2 */
+
+#if STM32_ADC_USE_ADC3
+ if (&ADCD3 == adcp) {
+ adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC3_DMA_STREAM,
+ STM32_ADC_ADC3_DMA_IRQ_PRIORITY,
+ (stm32_dmaisr_t)adc_lld_serve_dma_interrupt,
+ (void *)adcp);
+ osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
+
+ clkmask |= (1 << 2);
+#if defined(STM32F3XX)
+ rccEnableADC34(true);
+#endif
+#if defined(STM32L4XX) || defined(STM32L4XXP)
+ rccEnableADC123(true);
+#endif
+#if defined(STM32G4XX)
+ rccEnableADC345(true);
+#endif
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(adcp->dmastp, STM32_DMAMUX1_ADC3);
+#endif
+ }
+#endif /* STM32_ADC_USE_ADC3 */
+
+#if STM32_ADC_USE_ADC4
+ if (&ADCD4 == adcp) {
+ adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC4_DMA_STREAM,
+ STM32_ADC_ADC4_DMA_IRQ_PRIORITY,
+ (stm32_dmaisr_t)adc_lld_serve_dma_interrupt,
+ (void *)adcp);
+ osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
+
+ clkmask |= (1 << 3);
+#if defined(STM32F3XX)
+ rccEnableADC34(true);
+#endif
+#if defined(STM32L4XX) || defined(STM32L4XXP)
+ rccEnableADC123(true);
+#endif
+#if defined(STM32G4XX)
+ rccEnableADC345(true);
+#endif
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(adcp->dmastp, STM32_DMAMUX1_ADC4);
+#endif
+ }
+#endif /* STM32_ADC_USE_ADC4 */
+
+ /* Setting DMA peripheral-side pointer.*/
+#if STM32_ADC_DUAL_MODE
+ dmaStreamSetPeripheral(adcp->dmastp, &adcp->adcc->CDR);
+#else
+ dmaStreamSetPeripheral(adcp->dmastp, &adcp->adcm->DR);
+#endif
+
+ /* Differential channels setting.*/
+#if STM32_ADC_DUAL_MODE
+ adcp->adcm->DIFSEL = adcp->config->difsel;
+ adcp->adcs->DIFSEL = adcp->config->difsel;
+#else
+ adcp->adcm->DIFSEL = adcp->config->difsel;
+#endif
+
+ /* Master ADC calibration.*/
+ adc_lld_vreg_on(adcp);
+ adc_lld_calibrate(adcp);
+
+ /* Master ADC enabled here in order to reduce conversions latencies.*/
+ adc_lld_analog_on(adcp);
+ }
+}
+
+/**
+ * @brief Deactivates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop(ADCDriver *adcp) {
+
+ /* If in ready state then disables the ADC clock and analog part.*/
+ if (adcp->state == ADC_READY) {
+
+ /* Releasing the associated DMA channel.*/
+ dmaStreamFreeI(adcp->dmastp);
+ adcp->dmastp = NULL;
+
+ /* Stopping the ongoing conversion, if any.*/
+ adc_lld_stop_adc(adcp);
+
+ /* Disabling ADC analog circuit and regulator.*/
+ adc_lld_analog_off(adcp);
+ adc_lld_vreg_off(adcp);
+
+#if STM32_ADC_USE_ADC1
+ if (&ADCD1 == adcp) {
+ /* Resetting CCR options except default ones.*/
+ clkmask &= ~(1 << 0);
+ }
+#endif
+
+#if STM32_ADC_USE_ADC2
+ if (&ADCD2 == adcp) {
+ clkmask &= ~(1 << 1);
+ }
+#endif
+
+#if STM32_ADC_USE_ADC3
+ if (&ADCD3 == adcp) {
+ clkmask &= ~(1 << 2);
+ }
+#endif
+
+#if STM32_ADC_USE_ADC4
+ if (&ADCD4 == adcp) {
+ clkmask &= ~(1 << 3);
+ }
+#endif
+
+#if defined(STM32F3XX)
+#if STM32_HAS_ADC1 || STM32_HAS_ADC2
+ if ((clkmask & 0x3) == 0) {
+ rccDisableADC12();
+ }
+#endif
+
+#if STM32_HAS_ADC3 || STM32_HAS_ADC4
+ if ((clkmask & 0xC) == 0) {
+ rccDisableADC34();
+ }
+#endif
+#endif
+
+#if defined(STM32L4XX) || defined(STM32L4XXP)
+ if ((clkmask & 0x7) == 0) {
+ rccDisableADC123();
+ }
+#endif
+
+#if defined(STM32G4XX)
+#if STM32_HAS_ADC1 || STM32_HAS_ADC2
+ if ((clkmask & 0x3) == 0) {
+ rccDisableADC12();
+ }
+#endif
+
+#if STM32_HAS_ADC3 || STM32_HAS_ADC4
+ if ((clkmask & 0xC) == 0) {
+ rccDisableADC345();
+ }
+#endif
+#endif
+ }
+}
+
+/**
+ * @brief Starts an ADC conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start_conversion(ADCDriver *adcp) {
+ uint32_t dmamode, cfgr;
+ const ADCConversionGroup *grpp = adcp->grpp;
+#if STM32_ADC_DUAL_MODE
+ uint32_t ccr = grpp->ccr & ~(ADC_CCR_CKMODE_MASK | ADC_CCR_MDMA_MASK);
+#endif
+
+ osalDbgAssert(!STM32_ADC_DUAL_MODE || ((grpp->num_channels & 1) == 0),
+ "odd number of channels in dual mode");
+
+ /* Calculating control registers values.*/
+ dmamode = adcp->dmamode;
+ cfgr = grpp->cfgr | ADC_CFGR_DMAEN;
+ if (grpp->circular) {
+ dmamode |= STM32_DMA_CR_CIRC;
+#if STM32_ADC_DUAL_MODE
+ ccr |= ADC_CCR_DMACFG_CIRCULAR;
+#else
+ cfgr |= ADC_CFGR_DMACFG_CIRCULAR;
+#endif
+ if (adcp->depth > 1) {
+ /* If circular buffer depth > 1, then the half transfer interrupt
+ is enabled in order to allow streaming processing.*/
+ dmamode |= STM32_DMA_CR_HTIE;
+ }
+ }
+
+ /* DMA setup.*/
+ dmaStreamSetMemory0(adcp->dmastp, adcp->samples);
+#if STM32_ADC_DUAL_MODE
+ dmaStreamSetTransactionSize(adcp->dmastp, ((uint32_t)grpp->num_channels/2) *
+ (uint32_t)adcp->depth);
+#else
+ dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels *
+ (uint32_t)adcp->depth);
+#endif
+ dmaStreamSetMode(adcp->dmastp, dmamode);
+ dmaStreamEnable(adcp->dmastp);
+
+ /* ADC setup, if it is defined a callback for the analog watch dog then it
+ is enabled.*/
+ adcp->adcm->ISR = adcp->adcm->ISR;
+ if (grpp->error_cb != NULL) {
+ adcp->adcm->IER = ADC_IER_OVRIE | ADC_IER_AWD1IE
+ | ADC_IER_AWD2IE
+ | ADC_IER_AWD3IE;
+ adcp->adcm->TR1 = grpp->tr1;
+ adcp->adcm->TR2 = grpp->tr2;
+ adcp->adcm->TR3 = grpp->tr3;
+ adcp->adcm->AWD2CR = grpp->awd2cr;
+ adcp->adcm->AWD3CR = grpp->awd3cr;
+ }
+
+#if STM32_ADC_DUAL_MODE
+
+ /* Configuring the CCR register with the user-specified settings
+ in the conversion group configuration structure, static settings are
+ preserved.*/
+ adcp->adcc->CCR = (adcp->adcc->CCR &
+ (ADC_CCR_CKMODE_MASK | ADC_CCR_MDMA_MASK)) | ccr;
+
+ adcp->adcm->SMPR1 = grpp->smpr[0];
+ adcp->adcm->SMPR2 = grpp->smpr[1];
+ adcp->adcm->SQR1 = grpp->sqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels / 2);
+ adcp->adcm->SQR2 = grpp->sqr[1];
+ adcp->adcm->SQR3 = grpp->sqr[2];
+ adcp->adcm->SQR4 = grpp->sqr[3];
+ adcp->adcs->SMPR1 = grpp->ssmpr[0];
+ adcp->adcs->SMPR2 = grpp->ssmpr[1];
+ adcp->adcs->SQR1 = grpp->ssqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels / 2);
+ adcp->adcs->SQR2 = grpp->ssqr[1];
+ adcp->adcs->SQR3 = grpp->ssqr[2];
+ adcp->adcs->SQR4 = grpp->ssqr[3];
+
+#else /* !STM32_ADC_DUAL_MODE */
+ adcp->adcm->SMPR1 = grpp->smpr[0];
+ adcp->adcm->SMPR2 = grpp->smpr[1];
+ adcp->adcm->SQR1 = grpp->sqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels);
+ adcp->adcm->SQR2 = grpp->sqr[1];
+ adcp->adcm->SQR3 = grpp->sqr[2];
+ adcp->adcm->SQR4 = grpp->sqr[3];
+#endif /* !STM32_ADC_DUAL_MODE */
+
+ /* ADC configuration.*/
+ adcp->adcm->CFGR = cfgr;
+#if (STM32_ADCV3_OVERSAMPLING == TRUE) || defined(__DOXYGEN__)
+ adcp->adcm->CFGR2 = grpp->cfgr2;
+#endif
+
+ /* Starting conversion.*/
+ adcp->adcm->CR |= ADC_CR_ADSTART;
+}
+
+/**
+ * @brief Stops an ongoing conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop_conversion(ADCDriver *adcp) {
+
+ dmaStreamDisable(adcp->dmastp);
+ adc_lld_stop_adc(adcp);
+}
+
+/**
+ * @brief Enables the VREFEN bit.
+ * @details The VREFEN bit is required in order to sample the VREF channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32EnableVREF(ADCDriver *adcp) {
+
+ adcp->adcc->CCR |= ADC_CCR_VREFEN;
+}
+
+/**
+ * @brief Disables the VREFEN bit.
+ * @details The VREFEN bit is required in order to sample the VREF channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32DisableVREF(ADCDriver *adcp) {
+
+ adcp->adcc->CCR &= ~ADC_CCR_VREFEN;
+}
+
+/**
+ * @brief Enables the TSEN bit.
+ * @details The TSEN bit is required in order to sample the internal
+ * temperature sensor and internal reference voltage.
+ * @note This is an STM32-only functionality.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32EnableTS(ADCDriver *adcp) {
+
+ adcp->adcc->CCR |= ADC_CCR_TSEN;
+}
+
+/**
+ * @brief Disables the TSEN bit.
+ * @details The TSEN bit is required in order to sample the internal
+ * temperature sensor and internal reference voltage.
+ * @note This is an STM32-only functionality.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32DisableTS(ADCDriver *adcp) {
+
+ adcp->adcc->CCR &= ~ADC_CCR_TSEN;
+}
+
+/**
+ * @brief Enables the VBATEN bit.
+ * @details The VBATEN bit is required in order to sample the VBAT channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32EnableVBAT(ADCDriver *adcp) {
+
+ adcp->adcc->CCR |= ADC_CCR_VBATEN;
+}
+
+/**
+ * @brief Disables the VBATEN bit.
+ * @details The VBATEN bit is required in order to sample the VBAT channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32DisableVBAT(ADCDriver *adcp) {
+
+ adcp->adcc->CCR &= ~ADC_CCR_VBATEN;
+}
+
+#endif /* HAL_USE_ADC */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.h
new file mode 100644
index 0000000..8d6c615
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv3/hal_adc_lld.h
@@ -0,0 +1,1026 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ADCv3/hal_adc_lld.h
+ * @brief STM32 ADC subsystem low level driver header.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#ifndef HAL_ADC_LLD_H
+#define HAL_ADC_LLD_H
+
+#if HAL_USE_ADC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Available analog channels
+ * @{
+ */
+#define ADC_CHANNEL_IN0 0 /**< @brief External analog input 0. */
+#define ADC_CHANNEL_IN1 1 /**< @brief External analog input 1. */
+#define ADC_CHANNEL_IN2 2 /**< @brief External analog input 2. */
+#define ADC_CHANNEL_IN3 3 /**< @brief External analog input 3. */
+#define ADC_CHANNEL_IN4 4 /**< @brief External analog input 4. */
+#define ADC_CHANNEL_IN5 5 /**< @brief External analog input 5. */
+#define ADC_CHANNEL_IN6 6 /**< @brief External analog input 6. */
+#define ADC_CHANNEL_IN7 7 /**< @brief External analog input 7. */
+#define ADC_CHANNEL_IN8 8 /**< @brief External analog input 8. */
+#define ADC_CHANNEL_IN9 9 /**< @brief External analog input 9. */
+#define ADC_CHANNEL_IN10 10 /**< @brief External analog input 10. */
+#define ADC_CHANNEL_IN11 11 /**< @brief External analog input 11. */
+#define ADC_CHANNEL_IN12 12 /**< @brief External analog input 12. */
+#define ADC_CHANNEL_IN13 13 /**< @brief External analog input 13. */
+#define ADC_CHANNEL_IN14 14 /**< @brief External analog input 14. */
+#define ADC_CHANNEL_IN15 15 /**< @brief External analog input 15. */
+#define ADC_CHANNEL_IN16 16 /**< @brief External analog input 16. */
+#define ADC_CHANNEL_IN17 17 /**< @brief External analog input 17. */
+#define ADC_CHANNEL_IN18 18 /**< @brief External analog input 18. */
+/** @} */
+
+/**
+ * @name Sampling rates
+ * @{
+ */
+#if defined(STM32F3XX) || defined(__DOXYGEN__)
+#define ADC_SMPR_SMP_1P5 0 /**< @brief 14 cycles conversion time */
+#define ADC_SMPR_SMP_2P5 1 /**< @brief 15 cycles conversion time. */
+#define ADC_SMPR_SMP_4P5 2 /**< @brief 17 cycles conversion time. */
+#define ADC_SMPR_SMP_7P5 3 /**< @brief 20 cycles conversion time. */
+#define ADC_SMPR_SMP_19P5 4 /**< @brief 32 cycles conversion time. */
+#define ADC_SMPR_SMP_61P5 5 /**< @brief 74 cycles conversion time. */
+#define ADC_SMPR_SMP_181P5 6 /**< @brief 194 cycles conversion time. */
+#define ADC_SMPR_SMP_601P5 7 /**< @brief 614 cycles conversion time. */
+#endif
+#if defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX)
+#define ADC_SMPR_SMP_2P5 0 /**< @brief 15 cycles conversion time */
+#define ADC_SMPR_SMP_6P5 1 /**< @brief 19 cycles conversion time. */
+#define ADC_SMPR_SMP_12P5 2 /**< @brief 25 cycles conversion time. */
+#define ADC_SMPR_SMP_24P5 3 /**< @brief 37 cycles conversion time. */
+#define ADC_SMPR_SMP_47P5 4 /**< @brief 60 cycles conversion time. */
+#define ADC_SMPR_SMP_92P5 5 /**< @brief 105 cycles conversion time. */
+#define ADC_SMPR_SMP_247P5 6 /**< @brief 260 cycles conversion time. */
+#define ADC_SMPR_SMP_640P5 7 /**< @brief 653 cycles conversion time. */
+#endif
+/** @} */
+
+/**
+ * @name CFGR register configuration helpers
+ * @{
+ */
+#define ADC_CFGR_DMACFG_MASK (1 << 1)
+#define ADC_CFGR_DMACFG_ONESHOT (0 << 1)
+#define ADC_CFGR_DMACFG_CIRCULAR (1 << 1)
+
+#define ADC_CFGR_RES_MASK (3 << 3)
+#define ADC_CFGR_RES_12BITS (0 << 3)
+#define ADC_CFGR_RES_10BITS (1 << 3)
+#define ADC_CFGR_RES_8BITS (2 << 3)
+#define ADC_CFGR_RES_6BITS (3 << 3)
+
+#if defined(STM32F3XX) || defined(STM32L4XX) || defined(STM32L4XXP) || \
+ defined(__DOXYGEN__)
+#define ADC_CFGR_ALIGN_MASK (1 << 5)
+#define ADC_CFGR_ALIGN_RIGHT (0 << 5)
+#define ADC_CFGR_ALIGN_LEFT (1 << 5)
+
+#define ADC_CFGR_EXTSEL_MASK (15 << 6)
+#define ADC_CFGR_EXTSEL_SRC(n) ((n) << 6)
+#endif
+#if defined(STM32G4XX)
+#define ADC_CFGR_ALIGN_MASK (1 << 15)
+#define ADC_CFGR_ALIGN_RIGHT (0 << 15)
+#define ADC_CFGR_ALIGN_LEFT (1 << 15)
+
+#define ADC_CFGR_EXTSEL_MASK (31 << 5)
+#define ADC_CFGR_EXTSEL_SRC(n) ((n) << 5)
+#endif
+
+#define ADC_CFGR_EXTEN_MASK (3 << 10)
+#define ADC_CFGR_EXTEN_DISABLED (0 << 10)
+#define ADC_CFGR_EXTEN_RISING (1 << 10)
+#define ADC_CFGR_EXTEN_FALLING (2 << 10)
+#define ADC_CFGR_EXTEN_BOTH (3 << 10)
+
+#define ADC_CFGR_DISCEN_MASK (1 << 16)
+#define ADC_CFGR_DISCEN_DISABLED (0 << 16)
+#define ADC_CFGR_DISCEN_ENABLED (1 << 16)
+
+#define ADC_CFGR_DISCNUM_MASK (7 << 17)
+#define ADC_CFGR_DISCNUM_VAL(n) ((n) << 17)
+
+#define ADC_CFGR_AWD1_DISABLED 0
+#define ADC_CFGR_AWD1_ALL (1 << 23)
+#define ADC_CFGR_AWD1_SINGLE(n) (((n) << 26) | (1 << 23) | (1 << 22))
+/** @} */
+
+/**
+ * @name CCR register configuration helpers
+ * @{
+ */
+#define ADC_CCR_DUAL_MASK (31 << 0)
+#define ADC_CCR_DUAL_FIELD(n) ((n) << 0)
+
+#define ADC_CCR_DELAY_MASK (15 << 8)
+#define ADC_CCR_DELAY_FIELD(n) ((n) << 8)
+
+#define ADC_CCR_DMACFG_MASK (1 << 13)
+#define ADC_CCR_DMACFG_ONESHOT (0 << 13)
+#define ADC_CCR_DMACFG_CIRCULAR (1 << 13)
+
+#define ADC_CCR_MDMA_MASK (3 << 14)
+#define ADC_CCR_MDMA_DISABLED (0 << 14)
+#define ADC_CCR_MDMA_WORD (2 << 14)
+#define ADC_CCR_MDMA_HWORD (3 << 14)
+
+#define ADC_CCR_CKMODE_MASK (3 << 16)
+#define ADC_CCR_CKMODE_ADCCK (0 << 16)
+#define ADC_CCR_CKMODE_AHB_DIV1 (1 << 16)
+#define ADC_CCR_CKMODE_AHB_DIV2 (2 << 16)
+#define ADC_CCR_CKMODE_AHB_DIV4 (3 << 16)
+
+#if !defined(STM32F3XX)
+#define ADC_CCR_PRESC_MASK (15 << 18)
+#define ADC_CCR_PRESC_NOCLOCK (0 << 18)
+#define ADC_CCR_PRESC_DIV2 (1 << 18)
+#define ADC_CCR_PRESC_DIV4 (2 << 18)
+#define ADC_CCR_PRESC_DIV6 (3 << 18)
+#define ADC_CCR_PRESC_DIV8 (4 << 18)
+#define ADC_CCR_PRESC_DIV10 (5 << 18)
+#define ADC_CCR_PRESC_DIV12 (6 << 18)
+#define ADC_CCR_PRESC_DIV16 (7 << 18)
+#define ADC_CCR_PRESC_DIV32 (8 << 18)
+#define ADC_CCR_PRESC_DIV64 (9 << 18)
+#define ADC_CCR_PRESC_DIV128 (10 << 18)
+#define ADC_CCR_PRESC_DIV256 (11 << 18)
+#endif /* !defined(STM32F3XX) */
+
+/* F3 headers do not define the following macros, L4 headers do.*/
+#if !defined(ADC_CCR_VREFEN) || defined(__DOXYGEN__)
+#define ADC_CCR_VREFEN (1 << 22)
+#endif
+
+#if !defined(ADC_CCR_TSEN) || defined(__DOXYGEN__)
+#define ADC_CCR_TSEN (1 << 23)
+#endif
+
+#if !defined(ADC_CCR_VBATEN) || defined(__DOXYGEN__)
+#define ADC_CCR_VBATEN (1 << 24)
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief Enables the ADC master/slave mode.
+ * @note In dual mode only ADCD1 and ADCD3 are available.
+ */
+#if !defined(STM32_ADC_DUAL_MODE) || defined(__DOXYGEN__)
+#define STM32_ADC_DUAL_MODE FALSE
+#endif
+
+/**
+ * @brief Makes the ADC samples type an 8bits one.
+ * @note 10 and 12 bits sampling mode must not be used when this option
+ * is enabled.
+ */
+#if !defined(STM32_ADC_COMPACT_SAMPLES) || defined(__DOXYGEN__)
+#define STM32_ADC_COMPACT_SAMPLES FALSE
+#endif
+
+/**
+ * @brief ADC1 driver enable switch.
+ * @details If set to @p TRUE the support for ADC1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__)
+#define STM32_ADC_USE_ADC1 FALSE
+#endif
+
+/**
+ * @brief ADC2 driver enable switch.
+ * @details If set to @p TRUE the support for ADC2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ADC_USE_ADC2) || defined(__DOXYGEN__)
+#define STM32_ADC_USE_ADC2 FALSE
+#endif
+
+/**
+ * @brief ADC3 driver enable switch.
+ * @details If set to @p TRUE the support for ADC3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ADC_USE_ADC3) || defined(__DOXYGEN__)
+#define STM32_ADC_USE_ADC3 FALSE
+#endif
+/**
+ * @brief ADC4 driver enable switch.
+ * @details If set to @p TRUE the support for ADC4 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ADC_USE_ADC4) || defined(__DOXYGEN__)
+#define STM32_ADC_USE_ADC4 FALSE
+#endif
+
+/**
+ * @brief ADC1 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC1_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC2 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_ADC_ADC2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC2_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC3 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_ADC_ADC3_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC3_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC4 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_ADC_ADC4_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC4_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC1/ADC2 interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC12_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC12_IRQ_PRIORITY 5
+#endif
+
+/**
+ * @brief ADC3 interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC3_IRQ_PRIORITY 5
+#endif
+
+/**
+ * @brief ADC4 interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC4_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC4_IRQ_PRIORITY 5
+#endif
+
+/**
+ * @brief ADC1 DMA interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5
+#endif
+
+/**
+ * @brief ADC2 DMA interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC2_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5
+#endif
+
+/**
+ * @brief ADC3 DMA interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC3_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5
+#endif
+
+/**
+ * @brief ADC4 DMA interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC4_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC4_DMA_IRQ_PRIORITY 5
+#endif
+
+#if defined(STM32F3XX) || defined(__DOXYGEN__)
+/**
+ * @brief ADC1/ADC2 clock source and mode.
+ */
+#if !defined(STM32_ADC_ADC12_CLOCK_MODE) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1
+#endif
+
+/**
+ * @brief ADC3/ADC4 clock source and mode.
+ */
+#if !defined(STM32_ADC_ADC34_CLOCK_MODE) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC34_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1
+#endif
+#endif /* defined(STM32F3XX) */
+
+#if defined(STM32L4XX) || defined(STM32L4XXP) || defined(__DOXYGEN__)
+/**
+ * @brief ADC1/ADC2/ADC3 clock source and mode.
+ */
+#if !defined(STM32_ADC_ADC123_CLOCK_MODE) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC123_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1
+#endif
+
+/**
+ * @brief ADC1/ADC2/ADC3 clock prescaler.
+ */
+#if !defined(STM32_ADC_ADC123_PRESC) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC123_PRESC ADC_CCR_PRESC_DIV2
+#endif
+#endif /* defined(STM32L4XX) || defined(STM32L4XXP) */
+
+#if defined(STM32G4XX) || defined(__DOXYGEN__)
+/**
+ * @brief ADC1/ADC2 clock source and mode.
+ */
+#if !defined(STM32_ADC_ADC12_CLOCK_MODE) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4
+#endif
+
+/**
+ * @brief ADC3/ADC4/ADC5 clock source and mode.
+ */
+#if !defined(STM32_ADC_ADC345_CLOCK_MODE) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC345_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4
+#endif
+
+/**
+ * @brief ADC1/ADC2 clock prescaler.
+ */
+#if !defined(STM32_ADC_ADC12_PRESC) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC12_PRESC ADC_CCR_PRESC_DIV2
+#endif
+
+/**
+ * @brief ADC3/ADC4/ADC5 clock prescaler.
+ */
+#if !defined(STM32_ADC_ADC345_PRESC) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC345_PRESC ADC_CCR_PRESC_DIV2
+#endif
+#endif /* defined(STM32G4XX) */
+
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Supported devices checks.*/
+#if !defined(STM32F3XX) && !defined(STM32L4XX) && !defined(STM32L4XXP) && \
+ !defined(STM32G4XX)
+#error "ADCv3 only supports F3, L4, L4+ and G4 STM32 devices"
+#endif
+
+#if defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX) || \
+ defined(__DOXYGEN__)
+#define STM32_ADCV3_OVERSAMPLING TRUE
+#else
+#define STM32_ADCV3_OVERSAMPLING FALSE
+#endif
+
+/* Registry checks.*/
+#if !defined(STM32_HAS_ADC1) || !defined(STM32_HAS_ADC2) || \
+ !defined(STM32_HAS_ADC3) || !defined(STM32_HAS_ADC4)
+#error "STM32_HAS_ADCx not defined in registry"
+#endif
+
+#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_HANDLER)) || \
+ (STM32_ADC_USE_ADC2 && !defined(STM32_ADC2_HANDLER)) || \
+ (STM32_ADC_USE_ADC3 && !defined(STM32_ADC3_HANDLER)) || \
+ (STM32_ADC_USE_ADC4 && !defined(STM32_ADC4_HANDLER))
+#error "STM32_ADCx_HANDLER not defined in registry"
+#endif
+
+#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_NUMBER)) || \
+ (STM32_ADC_USE_ADC2 && !defined(STM32_ADC2_NUMBER)) || \
+ (STM32_ADC_USE_ADC3 && !defined(STM32_ADC3_NUMBER)) || \
+ (STM32_ADC_USE_ADC4 && !defined(STM32_ADC4_NUMBER))
+#error "STM32_ADCx_NUMBER not defined in registry"
+#endif
+
+#if !STM32_DMA_SUPPORTS_DMAMUX
+#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_DMA_MSK)) || \
+ (STM32_ADC_USE_ADC2 && !defined(STM32_ADC2_DMA_MSK)) || \
+ (STM32_ADC_USE_ADC3 && !defined(STM32_ADC3_DMA_MSK)) || \
+ (STM32_ADC_USE_ADC4 && !defined(STM32_ADC4_DMA_MSK))
+#error "STM32_ADCx_DMA_MSK not defined in registry"
+#endif
+
+#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_DMA_CHN)) || \
+ (STM32_ADC_USE_ADC2 && !defined(STM32_ADC2_DMA_CHN)) || \
+ (STM32_ADC_USE_ADC3 && !defined(STM32_ADC3_DMA_CHN)) || \
+ (STM32_ADC_USE_ADC4 && !defined(STM32_ADC4_DMA_CHN))
+#error "STM32_ADCx_DMA_CHN not defined in registry"
+#endif
+#endif /* !STM32_DMA_SUPPORTS_DMAMUX */
+
+/* Units checks.*/
+#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1
+#error "ADC1 not present in the selected device"
+#endif
+
+#if STM32_ADC_USE_ADC2 && !STM32_HAS_ADC2
+#error "ADC2 not present in the selected device"
+#endif
+
+#if STM32_ADC_USE_ADC3 && !STM32_HAS_ADC3
+#error "ADC3 not present in the selected device"
+#endif
+
+#if STM32_ADC_USE_ADC4 && !STM32_HAS_ADC4
+#error "ADC4 not present in the selected device"
+#endif
+
+/* Units checks related to dual mode.*/
+#if STM32_ADC_DUAL_MODE && STM32_ADC_USE_ADC1 && !STM32_HAS_ADC2
+#error "ADC2 not present in the selected device, required for dual mode"
+#endif
+
+#if STM32_ADC_DUAL_MODE && STM32_ADC_USE_ADC3 && !STM32_HAS_ADC4
+#error "ADC4 not present in the selected device, required for dual mode"
+#endif
+
+#if STM32_ADC_DUAL_MODE && STM32_ADC_USE_ADC2
+#error "ADC2 cannot be used in dual mode"
+#endif
+
+#if STM32_ADC_DUAL_MODE && STM32_ADC_USE_ADC4
+#error "ADC4 cannot be used in dual mode"
+#endif
+
+/* At least one ADC must be assigned.*/
+#if !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC2 && \
+ !STM32_ADC_USE_ADC3 && !STM32_ADC_USE_ADC4
+#error "ADC driver activated but no ADC peripheral assigned"
+#endif
+
+/* ISR arrangements checks.*/
+#if STM32_HAS_ADC1 && STM32_HAS_ADC2
+#if STM32_ADC1_NUMBER != STM32_ADC2_NUMBER
+#error "ADCv3 driver expects STM32_ADC1_NUMBER == STM32_ADC2_NUMBER from registry"
+#endif
+#endif
+
+/* ADC IRQ priority tests.*/
+#if STM32_ADC_USE_ADC1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC12_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to ADC1"
+#endif
+
+#if STM32_ADC_USE_ADC2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC12_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to ADC2"
+#endif
+
+#if STM32_ADC_USE_ADC3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to ADC3"
+#endif
+
+#if STM32_ADC_USE_ADC4 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC4_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to ADC4"
+#endif
+
+/* DMA IRQ priority tests.*/
+#if STM32_ADC_USE_ADC1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to ADC1 DMA"
+#endif
+
+#if STM32_ADC_USE_ADC2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC2_DMA_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to ADC2 DMA"
+#endif
+
+#if STM32_ADC_USE_ADC3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC3_DMA_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to ADC3 DMA"
+#endif
+
+#if STM32_ADC_USE_ADC4 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC4_DMA_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to ADC4 DMA"
+#endif
+
+/* DMA priority tests.*/
+#if STM32_ADC_USE_ADC1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to ADC1"
+#endif
+
+#if STM32_ADC_USE_ADC2 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to ADC2"
+#endif
+
+#if STM32_ADC_USE_ADC3 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC3_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to ADC3"
+#endif
+
+#if STM32_ADC_USE_ADC4 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC4_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to ADC4"
+#endif
+
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if STM32_ADC_USE_ADC1 && !defined(STM32_ADC_ADC1_DMA_STREAM)
+#error "ADC1 DMA stream not defined"
+#endif
+
+#if STM32_ADC_USE_ADC2 && !defined(STM32_ADC_ADC2_DMA_STREAM)
+#error "ADC2 DMA stream not defined"
+#endif
+
+#if STM32_ADC_USE_ADC3 && !defined(STM32_ADC_ADC3_DMA_STREAM)
+#error "ADC3 DMA stream not defined"
+#endif
+
+#if STM32_ADC_USE_ADC4 && !defined(STM32_ADC_ADC4_DMA_STREAM)
+#error "ADC4 DMA stream not defined"
+#endif
+
+#if STM32_DMA_SUPPORTS_DMAMUX
+
+#else /* !STM32_DMA_SUPPORTS_DMAMUX */
+
+/* Check on the validity of the assigned DMA channels.*/
+#if STM32_ADC_USE_ADC1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_MSK)
+#error "invalid DMA stream associated to ADC1"
+#endif
+
+#if STM32_ADC_USE_ADC2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC2_DMA_STREAM, STM32_ADC2_DMA_MSK)
+#error "invalid DMA stream associated to ADC2"
+#endif
+
+#if STM32_ADC_USE_ADC3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC3_DMA_STREAM, STM32_ADC3_DMA_MSK)
+#error "invalid DMA stream associated to ADC3"
+#endif
+
+#if STM32_ADC_USE_ADC4 && \
+ !STM32_DMA_IS_VALID_ID(STM32_ADC_ADC4_DMA_STREAM, STM32_ADC4_DMA_MSK)
+#error "invalid DMA stream associated to ADC4"
+#endif
+
+#endif /* !STM32_DMA_SUPPORTS_DMAMUX */
+
+/* ADC clock prescaler checks.*/
+#if defined(STM32F3XX)
+#endif /* defined(STM32F3XX) */
+
+#if defined(STM32L4XX) || defined(STM32L4XXP)
+#if STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV2
+#define ADC123_PRESC_VALUE 2
+#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV4
+#define ADC123_PRESC_VALUE 4
+#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV6
+#define ADC123_PRESC_VALUE 6
+#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV8
+#define ADC123_PRESC_VALUE 8
+#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV10
+#define ADC123_PRESC_VALUE 10
+#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV12
+#define ADC123_PRESC_VALUE 12
+#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV16
+#define ADC123_PRESC_VALUE 16
+#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV32
+#define ADC123_PRESC_VALUE 32
+#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV64
+#define ADC123_PRESC_VALUE 64
+#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV128
+#define ADC123_PRESC_VALUE 128
+#elif STM32_ADC_ADC123_PRESC == ADC_CCR_PRESC_DIV256
+#define ADC123_PRESC_VALUE 256
+#error "invalid clock divider selected for STM32_ADC_ADC12_PRESC"
+#endif
+#endif /* defined(STM32L4XX) || defined(STM32L4XXP) */
+
+#if defined(STM32G4XX)
+#if STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV2
+#define ADC12_PRESC_VALUE 2
+#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV4
+#define ADC12_PRESC_VALUE 4
+#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV6
+#define ADC12_PRESC_VALUE 6
+#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV8
+#define ADC12_PRESC_VALUE 8
+#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV10
+#define ADC12_PRESC_VALUE 10
+#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV12
+#define ADC12_PRESC_VALUE 12
+#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV16
+#define ADC12_PRESC_VALUE 16
+#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV32
+#define ADC12_PRESC_VALUE 32
+#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV64
+#define ADC12_PRESC_VALUE 64
+#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV128
+#define ADC12_PRESC_VALUE 128
+#elif STM32_ADC_ADC12_PRESC == ADC_CCR_PRESC_DIV256
+#define ADC12_PRESC_VALUE 256
+#error "invalid clock divider selected for STM32_ADC_ADC12_PRESC"
+#endif
+
+#if STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV2
+#define ADC345_PRESC_VALUE 2
+#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV4
+#define ADC345_PRESC_VALUE 4
+#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV6
+#define ADC345_PRESC_VALUE 6
+#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV8
+#define ADC345_PRESC_VALUE 8
+#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV10
+#define ADC345_PRESC_VALUE 10
+#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV12
+#define ADC345_PRESC_VALUE 12
+#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV16
+#define ADC345_PRESC_VALUE 16
+#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV32
+#define ADC345_PRESC_VALUE 32
+#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV64
+#define ADC345_PRESC_VALUE 64
+#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV128
+#define ADC345_PRESC_VALUE 128
+#elif STM32_ADC_ADC345_PRESC == ADC_CCR_PRESC_DIV256
+#define ADC345_PRESC_VALUE 256
+#error "invalid clock divider selected for STM32_ADC_ADC345_PRESC"
+#endif
+#endif /* defined(STM32G4XX) */
+
+/* ADC clock source checks.*/
+#if defined(STM32F3XX)
+#if STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK
+#define STM32_ADC12_CLOCK STM32_ADC12CLK
+#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1
+#define STM32_ADC12_CLOCK (STM32_HCLK / 1)
+#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2
+#define STM32_ADC12_CLOCK (STM32_HCLK / 2)
+#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4
+#define STM32_ADC12_CLOCK (STM32_HCLK / 4)
+#else
+#error "invalid clock mode selected for STM32_ADC_ADC12_CLOCK_MODE"
+#endif
+
+#if STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK
+#define STM32_ADC34_CLOCK STM32_ADC34CLK
+#elif STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1
+#define STM32_ADC34_CLOCK (STM32_HCLK / 1)
+#elif STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2
+#define STM32_ADC34_CLOCK (STM32_HCLK / 2)
+#elif STM32_ADC_ADC34_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4
+#define STM32_ADC34_CLOCK (STM32_HCLK / 4)
+#else
+#error "invalid clock mode selected for STM32_ADC_ADC34_CLOCK_MODE"
+#endif
+
+#if STM32_ADC12_CLOCK > STM32_ADCCLK_MAX
+#error "STM32_ADC12_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)"
+#endif
+
+#if STM32_ADC34_CLOCK > STM32_ADCCLK_MAX
+#error "STM32_ADC34_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)"
+#endif
+#endif /* defined(STM32F3XX) */
+
+#if defined(STM32L4XX) || defined(STM32L4XXP)
+#if STM32_ADC_ADC123_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK
+#define STM32_ADC123_CLOCK (STM32_ADCCLK / ADC123_PRESC_VALUE)
+#elif STM32_ADC_ADC123_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1
+#define STM32_ADC123_CLOCK (STM32_ADCCLK / 1)
+#elif STM32_ADC_ADC123_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2
+#define STM32_ADC123_CLOCK (STM32_ADCCLK / 2)
+#elif STM32_ADC_ADC123_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4
+#define STM32_ADC123_CLOCK (STM32_ADCCLK / 4)
+#else
+#error "invalid clock mode selected for STM32_ADC_ADC123_CLOCK_MODE"
+#endif
+
+#if STM32_ADC123_CLOCK > STM32_ADCCLK_MAX
+#error "STM32_ADC123_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)"
+#endif
+#endif /* defined(STM32L4XX) || defined(STM32L4XXP) */
+
+#if defined(STM32G4XX)
+#if STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK
+#define STM32_ADC12_CLOCK (STM32_ADC12CLK / ADC12_PRESC_VALUE)
+#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1
+#define STM32_ADC12_CLOCK (STM32_HCLK / 1)
+#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2
+#define STM32_ADC12_CLOCK (STM32_HCLK / 2)
+#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4
+#define STM32_ADC12_CLOCK (STM32_HCLK / 4)
+#else
+#error "invalid clock mode selected for STM32_ADC_ADC12_CLOCK_MODE"
+#endif
+
+#if STM32_ADC_ADC345_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK
+#define STM32_ADC345_CLOCK (STM32_ADC345CLK / ADC345_PRESC_VALUE)
+#elif STM32_ADC_ADC345_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1
+#define STM32_ADC345_CLOCK (STM32_HCLK / 1)
+#elif STM32_ADC_ADC345_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2
+#define STM32_ADC345_CLOCK (STM32_HCLK / 2)
+#elif STM32_ADC_ADC345_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4
+#define STM32_ADC345_CLOCK (STM32_HCLK / 4)
+#else
+#error "invalid clock mode selected for STM32_ADC_ADC345_CLOCK_MODE"
+#endif
+
+#if STM32_ADC12_CLOCK > STM32_ADCCLK_MAX
+#error "STM32_ADC12_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)"
+#endif
+
+#if STM32_ADC345_CLOCK > STM32_ADCCLK_MAX
+#error "STM32_ADC345_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)"
+#endif
+#endif /* defined(STM32G4XX) */
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC sample data type.
+ */
+#if !STM32_ADC_COMPACT_SAMPLES || defined(__DOXYGEN__)
+typedef uint16_t adcsample_t;
+#else
+typedef uint8_t adcsample_t;
+#endif
+
+/**
+ * @brief Channels number in a conversion group.
+ */
+typedef uint16_t adc_channels_num_t;
+
+/**
+ * @brief Possible ADC failure causes.
+ * @note Error codes are architecture dependent and should not relied
+ * upon.
+ */
+typedef enum {
+ ADC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */
+ ADC_ERR_OVERFLOW = 1, /**< ADC overflow condition. */
+ ADC_ERR_AWD1 = 2, /**< Watchdog 1 triggered. */
+ ADC_ERR_AWD2 = 3, /**< Watchdog 2 triggered. */
+ ADC_ERR_AWD3 = 4 /**< Watchdog 3 triggered. */
+} adcerror_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the ADC driver structure.
+ */
+#if (STM32_ADC_DUAL_MODE == TRUE) || defined(__DOXYGEN__)
+#define adc_lld_driver_fields \
+ /* Pointer to the master ADCx registers block.*/ \
+ ADC_TypeDef *adcm; \
+ /* Pointer to the slave ADCx registers block.*/ \
+ ADC_TypeDef *adcs; \
+ /* Pointer to the common ADCx_y registers block.*/ \
+ ADC_Common_TypeDef *adcc; \
+ /* Pointer to associated DMA channel.*/ \
+ const stm32_dma_stream_t *dmastp; \
+ /* DMA mode bit mask.*/ \
+ uint32_t dmamode
+#else
+#define adc_lld_driver_fields \
+ /* Pointer to the master ADCx registers block.*/ \
+ ADC_TypeDef *adcm; \
+ /* Pointer to the slave ADCx registers block.*/ \
+ ADC_Common_TypeDef *adcc; \
+ /* Pointer to associated DMA channel.*/ \
+ const stm32_dma_stream_t *dmastp; \
+ /* DMA mode bit mask.*/ \
+ uint32_t dmamode
+#endif
+
+/**
+ * @brief Low level fields of the ADC configuration structure.
+ */
+#define adc_lld_config_fields \
+ /* ADC DIFSEL register initialization data.*/ \
+ uint32_t difsel
+
+/**
+ * @brief Low level fields of the ADC group configuration structure.
+ */
+#if (STM32_ADCV3_OVERSAMPLING == TRUE) || defined(__DOXYGEN__)
+#if (STM32_ADC_DUAL_MODE == TRUE) || defined(__DOXYGEN__)
+#define adc_lld_configuration_group_fields \
+ /* ADC CFGR register initialization data. \
+ NOTE: The bits DMAEN and DMACFG are enforced internally \
+ to the driver, keep them to zero. \
+ NOTE: The bits @p ADC_CFGR_CONT or @p ADC_CFGR_DISCEN must be \
+ specified in continuous mode or if the buffer depth is \
+ greater than one.*/ \
+ uint32_t cfgr; \
+ /* ADC CFGR2 register initialization data.*/ \
+ uint32_t cfgr2; \
+ /* ADC TR1 register initialization data.*/ \
+ uint32_t tr1; \
+ /* ADC TR2 register initialization data.*/ \
+ uint32_t tr2; \
+ /* ADC TR3 register initialization data.*/ \
+ uint32_t tr3; \
+ /* ADC AWD2CR register initialization data.*/ \
+ uint32_t awd2cr; \
+ /* ADC AWD3CR register initialization data.*/ \
+ uint32_t awd3cr; \
+ /* ADC CCR register initialization data. \
+ NOTE: Put this field to zero if not using oversampling.*/ \
+ uint32_t ccr; \
+ /* ADC SMPRx registers initialization data.*/ \
+ uint32_t smpr[2]; \
+ /* ADC SQRx register initialization data.*/ \
+ uint32_t sqr[4]; \
+ /* Slave ADC SMPRx registers initialization data. \
+ NOTE: This field is only present in dual mode.*/ \
+ uint32_t ssmpr[2]; \
+ /* Slave ADC SQRx register initialization data. \
+ NOTE: This field is only present in dual mode.*/ \
+ uint32_t ssqr[4]
+#else /* STM32_ADC_DUAL_MODE == FALSE */
+#define adc_lld_configuration_group_fields \
+ uint32_t cfgr; \
+ uint32_t cfgr2; \
+ uint32_t tr1; \
+ uint32_t tr2; \
+ uint32_t tr3; \
+ uint32_t awd2cr; \
+ uint32_t awd3cr; \
+ uint32_t smpr[2]; \
+ uint32_t sqr[4]
+#endif /* STM32_ADC_DUAL_MODE == FALSE */
+
+#else /* STM32_ADCV3_OVERSAMPLING == FALSE */
+#if (STM32_ADC_DUAL_MODE == TRUE) || defined(__DOXYGEN__)
+#define adc_lld_configuration_group_fields \
+ uint32_t cfgr; \
+ uint32_t tr1; \
+ uint32_t tr2; \
+ uint32_t tr3; \
+ uint32_t awd2cr; \
+ uint32_t awd3cr; \
+ uint32_t ccr; \
+ uint32_t smpr[2]; \
+ uint32_t sqr[4]; \
+ uint32_t ssmpr[2]; \
+ uint32_t ssqr[4]
+#else /* STM32_ADC_DUAL_MODE == FALSE */
+#define adc_lld_configuration_group_fields \
+ uint32_t cfgr; \
+ uint32_t tr1; \
+ uint32_t tr2; \
+ uint32_t tr3; \
+ uint32_t awd2cr; \
+ uint32_t awd3cr; \
+ uint32_t smpr[2]; \
+ uint32_t sqr[4]
+#endif /* STM32_ADC_DUAL_MODE == FALSE */
+#endif /* STM32_ADCV3_OVERSAMPLING == FALSE */
+
+/**
+ * @name Threshold registers initializers
+ * @{
+ */
+#define ADC_TR(low, high) (((uint32_t)(high) << 16) | (uint32_t)(low))
+#define ADC_TR_DISABLED ADC_TR(0U, 0x0FFFU)
+#define ADC_AWDCR_ENABLE(n) (1U << (n))
+/** @} */
+
+/**
+ * @name Sequences building helper macros
+ * @{
+ */
+/**
+ * @brief Number of channels in a conversion sequence.
+ */
+#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 0)
+
+#define ADC_SQR1_SQ1_N(n) ((n) << 6) /**< @brief 1st channel in seq. */
+#define ADC_SQR1_SQ2_N(n) ((n) << 12) /**< @brief 2nd channel in seq. */
+#define ADC_SQR1_SQ3_N(n) ((n) << 18) /**< @brief 3rd channel in seq. */
+#define ADC_SQR1_SQ4_N(n) ((n) << 24) /**< @brief 4th channel in seq. */
+
+#define ADC_SQR2_SQ5_N(n) ((n) << 0) /**< @brief 5th channel in seq. */
+#define ADC_SQR2_SQ6_N(n) ((n) << 6) /**< @brief 6th channel in seq. */
+#define ADC_SQR2_SQ7_N(n) ((n) << 12) /**< @brief 7th channel in seq. */
+#define ADC_SQR2_SQ8_N(n) ((n) << 18) /**< @brief 8th channel in seq. */
+#define ADC_SQR2_SQ9_N(n) ((n) << 24) /**< @brief 9th channel in seq. */
+
+#define ADC_SQR3_SQ10_N(n) ((n) << 0) /**< @brief 10th channel in seq.*/
+#define ADC_SQR3_SQ11_N(n) ((n) << 6) /**< @brief 11th channel in seq.*/
+#define ADC_SQR3_SQ12_N(n) ((n) << 12) /**< @brief 12th channel in seq.*/
+#define ADC_SQR3_SQ13_N(n) ((n) << 18) /**< @brief 13th channel in seq.*/
+#define ADC_SQR3_SQ14_N(n) ((n) << 24) /**< @brief 14th channel in seq.*/
+
+#define ADC_SQR4_SQ15_N(n) ((n) << 0) /**< @brief 15th channel in seq.*/
+#define ADC_SQR4_SQ16_N(n) ((n) << 6) /**< @brief 16th channel in seq.*/
+/** @} */
+
+/**
+ * @name Sampling rate settings helper macros
+ * @{
+ */
+#define ADC_SMPR1_SMP_AN0(n) ((n) << 0) /**< @brief AN0 sampling time. */
+#define ADC_SMPR1_SMP_AN1(n) ((n) << 3) /**< @brief AN1 sampling time. */
+#define ADC_SMPR1_SMP_AN2(n) ((n) << 6) /**< @brief AN2 sampling time. */
+#define ADC_SMPR1_SMP_AN3(n) ((n) << 9) /**< @brief AN3 sampling time. */
+#define ADC_SMPR1_SMP_AN4(n) ((n) << 12) /**< @brief AN4 sampling time. */
+#define ADC_SMPR1_SMP_AN5(n) ((n) << 15) /**< @brief AN5 sampling time. */
+#define ADC_SMPR1_SMP_AN6(n) ((n) << 18) /**< @brief AN6 sampling time. */
+#define ADC_SMPR1_SMP_AN7(n) ((n) << 21) /**< @brief AN7 sampling time. */
+#define ADC_SMPR1_SMP_AN8(n) ((n) << 24) /**< @brief AN8 sampling time. */
+#define ADC_SMPR1_SMP_AN9(n) ((n) << 27) /**< @brief AN9 sampling time. */
+
+#define ADC_SMPR2_SMP_AN10(n) ((n) << 0) /**< @brief AN10 sampling time. */
+#define ADC_SMPR2_SMP_AN11(n) ((n) << 3) /**< @brief AN11 sampling time. */
+#define ADC_SMPR2_SMP_AN12(n) ((n) << 6) /**< @brief AN12 sampling time. */
+#define ADC_SMPR2_SMP_AN13(n) ((n) << 9) /**< @brief AN13 sampling time. */
+#define ADC_SMPR2_SMP_AN14(n) ((n) << 12) /**< @brief AN14 sampling time. */
+#define ADC_SMPR2_SMP_AN15(n) ((n) << 15) /**< @brief AN15 sampling time. */
+#define ADC_SMPR2_SMP_AN16(n) ((n) << 18) /**< @brief AN16 sampling time. */
+#define ADC_SMPR2_SMP_AN17(n) ((n) << 21) /**< @brief AN17 sampling time. */
+#define ADC_SMPR2_SMP_AN18(n) ((n) << 24) /**< @brief AN18 sampling time. */
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__)
+extern ADCDriver ADCD1;
+#endif
+
+#if STM32_ADC_USE_ADC2 && !defined(__DOXYGEN__)
+extern ADCDriver ADCD2;
+#endif
+
+#if STM32_ADC_USE_ADC3 && !defined(__DOXYGEN__)
+extern ADCDriver ADCD3;
+#endif
+
+#if STM32_ADC_USE_ADC4 && !defined(__DOXYGEN__)
+extern ADCDriver ADCD4;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void adc_lld_init(void);
+ void adc_lld_start(ADCDriver *adcp);
+ void adc_lld_stop(ADCDriver *adcp);
+ void adc_lld_start_conversion(ADCDriver *adcp);
+ void adc_lld_stop_conversion(ADCDriver *adcp);
+ void adcSTM32EnableVREF(ADCDriver *adcp);
+ void adcSTM32DisableVREF(ADCDriver *adcp);
+ void adcSTM32EnableTS(ADCDriver *adcp);
+ void adcSTM32DisableTS(ADCDriver *adcp);
+ void adcSTM32EnableVBAT(ADCDriver *adcp);
+ void adcSTM32DisableVBAT(ADCDriver *adcp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_ADC */
+
+#endif /* HAL_ADC_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv3/notes.txt b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv3/notes.txt
new file mode 100644
index 0000000..fbfe6c2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv3/notes.txt
@@ -0,0 +1,22 @@
+STM32 ADCv3 driver.
+
+Driver capability:
+
+- Supports the STM32 "fast" ADC found on F3, L4, L4+ and G4 sub-families.
+
+The file registry must export:
+
+STM32_HAS_ADCx - ADCx presence flag (1..4).
+STM32_ADC1_HANDLER - IRQ vector name for ADC1.
+STM32_ADC1_NUMBER - IRQ vector number for ADC1.
+STM32_ADC2_HANDLER - IRQ vector name for ADC2.
+STM32_ADC2_NUMBER - IRQ vector number for ADC2.
+STM32_ADC3_HANDLER - IRQ vector name for ADC3.
+STM32_ADC3_NUMBER - IRQ vector number for ADC3.
+STM32_ADC4_HANDLER - IRQ vector name for ADC4.
+STM32_ADC4_NUMBER - IRQ vector number for ADC4.
+
+If there is no DMAMUX then the file registry must export also:
+
+STM32_ADCx_DMA_MSK - Mask of the compatible DMA channels (1..4).
+STM32_ADCx_DMA_CHN - Mask of the channels mapping (1..4).
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv4/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv4/driver.mk
new file mode 100644
index 0000000..91bc885
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv4/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv4
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.c
new file mode 100644
index 0000000..bba3fee
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.c
@@ -0,0 +1,822 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ADCv4/hal_adc_lld.c
+ * @brief STM32 ADC subsystem low level driver source.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_ADC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#if STM32_ADC_DUAL_MODE == TRUE
+#if STM32_ADC_COMPACT_SAMPLES == TRUE
+/* Compact type dual mode, 2x8-bit.*/
+#define ADC12_DMA_SIZE (STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD)
+#define ADC3_BDMA_SIZE (STM32_BDMA_CR_MSIZE_BYTE | STM32_BDMA_CR_PSIZE_BYTE)
+#define ADC_DMA_DAMDF ADC_CCR_DAMDF_BYTE
+
+#else /* STM32_ADC_COMPACT_SAMPLES == FALSE */
+/* Large type dual mode, 2x16bit.*/
+#define ADC12_DMA_SIZE (STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD)
+#define ADC3_BDMA_SIZE (STM32_BDMA_CR_MSIZE_HWORD | STM32_BDMA_CR_PSIZE_HWORD)
+#define ADC_DMA_DAMDF ADC_CCR_DAMDF_HWORD
+#endif /* !STM32_ADC_COMPACT_SAMPLES */
+
+#else /* STM32_ADC_DUAL_MODE == FALSE */
+#if STM32_ADC_COMPACT_SAMPLES
+/* Compact type single mode, 8-bit.*/
+#define ADC12_DMA_SIZE (STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_PSIZE_BYTE)
+#define ADC3_BDMA_SIZE (STM32_BDMA_CR_MSIZE_BYTE | STM32_BDMA_CR_PSIZE_BYTE)
+#define ADC_DMA_DAMDF ADC_CCR_DAMDF_DISABLED
+
+#else /* STM32_ADC_COMPACT_SAMPLES == FALSE */
+/* Large type single mode, 16-bit.*/
+#define ADC12_DMA_SIZE (STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD)
+#define ADC3_BDMA_SIZE (STM32_BDMA_CR_MSIZE_HWORD | STM32_BDMA_CR_PSIZE_HWORD)
+#define ADC_DMA_DAMDF ADC_CCR_DAMDF_DISABLED
+#endif /* STM32_ADC_COMPACT_SAMPLES == FALSE */
+#endif /* STM32_ADC_DUAL_MODE == FALSE */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief ADC1 driver identifier.*/
+#if STM32_ADC_USE_ADC12 || defined(__DOXYGEN__)
+ADCDriver ADCD1;
+#endif
+
+/** @brief ADC3 driver identifier.*/
+#if STM32_ADC_USE_ADC3 || defined(__DOXYGEN__)
+ADCDriver ADCD3;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+static const ADCConfig default_config = {
+ .difsel = 0U
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the ADC voltage regulator.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ */
+static void adc_lld_vreg_on(ADCDriver *adcp) {
+
+ adcp->adcm->CR = ADC_CR_ADVREGEN;
+#if STM32_ADC_DUAL_MODE
+ if (&ADCD1 == adcp) {
+ adcp->adcs->CR = ADC_CR_ADVREGEN;
+ }
+#endif
+ osalSysPolledDelayX(OSAL_US2RTC(STM32_SYS_CK, 10U));
+}
+
+/**
+ * @brief Disables the ADC voltage regulator.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ */
+static void adc_lld_vreg_off(ADCDriver *adcp) {
+
+ adcp->adcm->CR = ADC_CR_DEEPPWD;
+#if STM32_ADC_DUAL_MODE
+ if (&ADCD1 == adcp) {
+ adcp->adcs->CR = ADC_CR_DEEPPWD;
+ }
+#endif
+}
+
+/**
+ * @brief Enables the ADC analog circuit.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ */
+static void adc_lld_analog_on(ADCDriver *adcp) {
+
+ adcp->adcm->ISR = ADC_ISR_ADRDY;
+ adcp->adcm->CR |= ADC_CR_ADEN;
+ while ((adcp->adcm->ISR & ADC_ISR_ADRDY) == 0U)
+ ;
+#if STM32_ADC_DUAL_MODE
+ if (&ADCD1 == adcp) {
+ adcp->adcs->ISR = ADC_ISR_ADRDY;
+ adcp->adcs->CR |= ADC_CR_ADEN;
+ while ((adcp->adcs->ISR & ADC_ISR_ADRDY) == 0U)
+ ;
+ }
+#endif
+}
+
+/**
+ * @brief Disables the ADC analog circuit.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ */
+static void adc_lld_analog_off(ADCDriver *adcp) {
+
+ adcp->adcm->CR |= ADC_CR_ADDIS;
+ while ((adcp->adcm->CR & ADC_CR_ADDIS) != 0U)
+ ;
+#if STM32_ADC_DUAL_MODE
+ if (&ADCD1 == adcp) {
+ adcp->adcs->CR |= ADC_CR_ADDIS;
+ while ((adcp->adcs->CR & ADC_CR_ADDIS) != 0U)
+ ;
+ }
+#endif
+}
+
+/**
+ * @brief Calibrates and ADC unit.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ */
+static void adc_lld_calibrate(ADCDriver *adcp) {
+
+ osalDbgAssert(adcp->adcm->CR == ADC_CR_ADVREGEN, "invalid register state");
+
+ adcp->adcm->CR &= ~(ADC_CR_ADCALDIF | ADC_CR_ADCALLIN);
+ adcp->adcm->CR |= adcp->config->calibration & (ADC_CR_ADCALDIF |
+ ADC_CR_ADCALLIN);
+ adcp->adcm->CR |= ADC_CR_ADCAL;
+ while ((adcp->adcm->CR & ADC_CR_ADCAL) != 0U)
+ ;
+#if STM32_ADC_DUAL_MODE
+ if (&ADCD1 == adcp) {
+ osalDbgAssert(adcp->adcs->CR == ADC_CR_ADVREGEN, "invalid register state");
+
+ adcp->adcs->CR &= ~(ADC_CR_ADCALDIF | ADC_CR_ADCALLIN);
+ adcp->adcs->CR |= adcp->config->calibration & (ADC_CR_ADCALDIF |
+ ADC_CR_ADCALLIN);
+ adcp->adcs->CR |= ADC_CR_ADCAL;
+ while ((adcp->adcs->CR & ADC_CR_ADCAL) != 0U)
+ ;
+ }
+#endif
+}
+
+/**
+ * @brief Stops an ongoing conversion, if any.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ */
+static void adc_lld_stop_adc(ADCDriver *adcp) {
+
+ if (adcp->adcm->CR & ADC_CR_ADSTART) {
+ adcp->adcm->CR |= ADC_CR_ADSTP;
+ while (adcp->adcm->CR & ADC_CR_ADSTP)
+ ;
+ }
+#if (STM32_ADC_USE_ADC12 == TRUE)
+ adcp->adcm->PCSEL = 0U;
+#endif
+}
+
+#if (STM32_ADC_USE_ADC12 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief ADC DMA service routine.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void adc_lld_serve_dma_interrupt(ADCDriver *adcp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ /* DMA, this could help only if the DMA tries to access an unmapped
+ address space or violates alignment rules.*/
+ _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE);
+ }
+ else {
+ /* It is possible that the conversion group has already be reset by the
+ ADC error handler, in this case this interrupt is spurious.*/
+ if (adcp->grpp != NULL) {
+ if ((flags & STM32_DMA_ISR_TCIF) != 0) {
+ /* Transfer complete processing.*/
+ _adc_isr_full_code(adcp);
+ }
+ else if ((flags & STM32_DMA_ISR_HTIF) != 0) {
+ /* Half transfer processing.*/
+ _adc_isr_half_code(adcp);
+ }
+ }
+ }
+}
+#endif /* STM32_ADC_USE_ADC12 == TRUE */
+
+#if (STM32_ADC_USE_ADC3 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief ADC BDMA service routine.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void adc_lld_serve_bdma_interrupt(ADCDriver *adcp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+ if ((flags & STM32_BDMA_ISR_TEIF) != 0) {
+ /* DMA, this could help only if the DMA tries to access an unmapped
+ address space or violates alignment rules.*/
+ _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE);
+ }
+ else {
+ /* It is possible that the conversion group has already be reset by the
+ ADC error handler, in this case this interrupt is spurious.*/
+ if (adcp->grpp != NULL) {
+ if ((flags & STM32_BDMA_ISR_TCIF) != 0) {
+ /* Transfer complete processing.*/
+ _adc_isr_full_code(adcp);
+ }
+ else if ((flags & STM32_BDMA_ISR_HTIF) != 0) {
+ /* Half transfer processing.*/
+ _adc_isr_half_code(adcp);
+ }
+ }
+ }
+}
+#endif /* STM32_ADC_USE_ADC3 == TRUE */
+
+/**
+ * @brief ADC IRQ service routine.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ * @param[in] isr content of the ISR register
+ */
+static void adc_lld_serve_interrupt(ADCDriver *adcp, uint32_t isr) {
+
+ /* It could be a spurious interrupt caused by overflows after DMA disabling,
+ just ignore it in this case.*/
+ if (adcp->grpp != NULL) {
+ /* Note, an overflow may occur after the conversion ended before the driver
+ is able to stop the ADC, this is why the state is checked too.*/
+ if ((isr & ADC_ISR_OVR) && (adcp->state == ADC_ACTIVE)) {
+ /* ADC overflow condition, this could happen only if the DMA is unable
+ to read data fast enough.*/
+ _adc_isr_error_code(adcp, ADC_ERR_OVERFLOW);
+ }
+ if (isr & ADC_ISR_AWD1) {
+ /* Analog watchdog error.*/
+ _adc_isr_error_code(adcp, ADC_ERR_AWD1);
+ }
+ if (isr & ADC_ISR_AWD2) {
+ /* Analog watchdog error.*/
+ _adc_isr_error_code(adcp, ADC_ERR_AWD2);
+ }
+ if (isr & ADC_ISR_AWD3) {
+ /* Analog watchdog error.*/
+ _adc_isr_error_code(adcp, ADC_ERR_AWD3);
+ }
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if (STM32_ADC_USE_ADC12 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief ADC1/ADC2 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_ADC12_HANDLER) {
+ uint32_t isr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ isr = ADC1->ISR;
+#if STM32_ADC_DUAL_MODE
+ isr |= ADC2->ISR;
+#endif
+ ADC1->ISR = isr;
+#if STM32_ADC_DUAL_MODE
+ ADC2->ISR = isr;
+#endif
+#if defined(STM32_ADC_ADC12_IRQ_HOOK)
+ STM32_ADC_ADC12_IRQ_HOOK
+#endif
+ adc_lld_serve_interrupt(&ADCD1, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* STM32_ADC_USE_ADC12 == TRUE */
+
+#if (STM32_ADC_USE_ADC3 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief ADC3 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_ADC3_HANDLER) {
+ uint32_t isr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ isr = ADC3->ISR;
+ ADC3->ISR = isr;
+#if defined(STM32_ADC_ADC3_IRQ_HOOK)
+ STM32_ADC_ADC3_IRQ_HOOK
+#endif
+ adc_lld_serve_interrupt(&ADCD3, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* STM32_ADC_USE_ADC3 == TRUE */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level ADC driver initialization.
+ *
+ * @notapi
+ */
+void adc_lld_init(void) {
+
+#if STM32_ADC_USE_ADC12 == TRUE
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD1);
+ ADCD1.adcc = ADC12_COMMON;
+ ADCD1.adcm = ADC1;
+#if STM32_ADC_DUAL_MODE
+ ADCD1.adcs = ADC2;
+#endif
+ ADCD1.data.dma = NULL;
+ ADCD1.dmamode = ADC12_DMA_SIZE |
+ STM32_DMA_CR_PL(STM32_ADC_ADC12_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ nvicEnableVector(STM32_ADC12_NUMBER, STM32_ADC_ADC12_IRQ_PRIORITY);
+#endif /* STM32_ADC_USE_ADC12 == TRUE */
+
+#if STM32_ADC_USE_ADC3 == TRUE
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD3);
+ ADCD3.adcc = ADC3_COMMON;
+ ADCD3.adcm = ADC3;
+ ADCD3.data.bdma = NULL;
+ ADCD3.dmamode = ADC3_BDMA_SIZE |
+ STM32_BDMA_CR_PL(STM32_ADC_ADC3_DMA_PRIORITY) |
+ STM32_BDMA_CR_DIR_P2M |
+ STM32_BDMA_CR_MINC | STM32_BDMA_CR_TCIE |
+ STM32_BDMA_CR_TEIE;
+ nvicEnableVector(STM32_ADC3_NUMBER, STM32_ADC_ADC3_IRQ_PRIORITY);
+#endif /* STM32_ADC_USE_ADC3 == TRUE */
+
+ /* ADC units pre-initializations.*/
+#if (STM32_HAS_ADC1 == TRUE) && (STM32_HAS_ADC2 == TRUE)
+#if STM32_ADC_USE_ADC12 == TRUE
+ rccEnableADC12(true);
+ rccResetADC12();
+ ADC12_COMMON->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_DAMDF;
+ rccDisableADC12();
+#endif
+#if STM32_ADC_USE_ADC3 == TRUE
+ rccEnableADC3(true);
+ rccResetADC3();
+ ADC3_COMMON->CCR = STM32_ADC_ADC3_CLOCK_MODE;
+ rccDisableADC3();
+#endif
+#endif
+}
+
+/**
+ * @brief Configures and activates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start(ADCDriver *adcp) {
+
+ /* Handling the default configuration.*/
+ if (adcp->config == NULL) {
+ adcp->config = &default_config;
+ }
+
+ /* If in stopped state then enables the ADC and DMA clocks.*/
+ if (adcp->state == ADC_STOP) {
+#if STM32_ADC_USE_ADC12 == TRUE
+ if (&ADCD1 == adcp) {
+ adcp->data.dma = dmaStreamAllocI(STM32_ADC_ADC12_DMA_STREAM,
+ STM32_ADC_ADC12_IRQ_PRIORITY,
+ (stm32_dmaisr_t)adc_lld_serve_dma_interrupt,
+ (void *)adcp);
+ osalDbgAssert(adcp->data.dma != NULL, "unable to allocate stream");
+ rccEnableADC12(true);
+ dmaSetRequestSource(adcp->data.dma, STM32_DMAMUX1_ADC1);
+
+ /* Setting DMA peripheral-side pointer.*/
+#if STM32_ADC_DUAL_MODE
+ dmaStreamSetPeripheral(adcp->data.dma, &adcp->adcc->CDR);
+#else
+ dmaStreamSetPeripheral(adcp->data.dma, &adcp->adcm->DR);
+#endif
+
+ /* Differential channels setting.*/
+#if STM32_ADC_DUAL_MODE
+ adcp->adcm->DIFSEL = adcp->config->difsel;
+ adcp->adcs->DIFSEL = adcp->config->difsel;
+#else
+ adcp->adcm->DIFSEL = adcp->config->difsel;
+#endif
+ }
+#endif /* STM32_ADC_USE_ADC12 == TRUE */
+
+#if STM32_ADC_USE_ADC3 == TRUE
+ if (&ADCD3 == adcp) {
+ adcp->data.bdma = bdmaStreamAllocI(STM32_ADC_ADC3_BDMA_STREAM,
+ STM32_ADC_ADC3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)adc_lld_serve_bdma_interrupt,
+ (void *)adcp);
+ osalDbgAssert(adcp->data.bdma != NULL, "unable to allocate stream");
+ rccEnableADC3(true);
+ bdmaSetRequestSource(adcp->data.bdma, STM32_DMAMUX2_ADC3_REQ);
+
+ /* Setting DMA peripheral-side pointer.*/
+ bdmaStreamSetPeripheral(adcp->data.bdma, &adcp->adcm->DR);
+
+ /* Differential channels setting.*/
+ adcp->adcm->DIFSEL = adcp->config->difsel;
+ }
+#endif /* STM32_ADC_USE_ADC3 == TRUE */
+
+ /* Master ADC calibration.*/
+ adc_lld_vreg_on(adcp);
+ adc_lld_calibrate(adcp);
+
+ /* Configure the ADC boost. */
+#if STM32_ADC_USE_ADC12 == TRUE
+ if (&ADCD1 == adcp) {
+ adcp->adcm->CR |= STM32_ADC12_BOOST;
+#if STM32_ADC_DUAL_MODE
+ adcp->adcs->CR |= STM32_ADC12_BOOST;
+#endif
+ }
+#endif
+
+#if STM32_ADC_USE_ADC3 == TRUE
+ if (&ADCD3 == adcp) {
+ adcp->adcm->CR |= STM32_ADC3_BOOST;
+ }
+#endif
+
+ /* Master ADC enabled here in order to reduce conversions latencies.*/
+ adc_lld_analog_on(adcp);
+ }
+}
+
+/**
+ * @brief Deactivates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop(ADCDriver *adcp) {
+
+ /* If in ready state then disables the ADC clock and analog part.*/
+ if (adcp->state == ADC_READY) {
+
+ /* Stopping the ongoing conversion, if any.*/
+ adc_lld_stop_adc(adcp);
+
+ /* Disabling ADC analog circuit and regulator.*/
+ adc_lld_analog_off(adcp);
+ adc_lld_vreg_off(adcp);
+
+#if STM32_ADC_USE_ADC12 == TRUE
+ if (&ADCD1 == adcp) {
+
+ /* Releasing the associated DMA channel.*/
+ dmaStreamFreeI(adcp->data.dma);
+ adcp->data.dma = NULL;
+
+ /* Resetting CCR options except default ones.*/
+ adcp->adcc->CCR = STM32_ADC_ADC12_CLOCK_MODE | ADC_DMA_DAMDF;
+ rccDisableADC12();
+ }
+#endif
+
+#if STM32_ADC_USE_ADC3 == TRUE
+ if (&ADCD3 == adcp) {
+
+ /* Releasing the associated BDMA channel.*/
+ bdmaStreamFreeI(adcp->data.bdma);
+ adcp->data.bdma = NULL;
+
+ /* Resetting CCR options except default ones.*/
+ adcp->adcc->CCR = STM32_ADC_ADC3_CLOCK_MODE;
+ rccDisableADC3();
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Starts an ADC conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start_conversion(ADCDriver *adcp) {
+ uint32_t dmamode, cfgr;
+ const ADCConversionGroup *grpp = adcp->grpp;
+
+#if STM32_ADC_USE_ADC12 == TRUE
+#if STM32_ADC_DUAL_MODE
+ uint32_t ccr;
+#endif
+ if (&ADCD1 == adcp) {
+#if STM32_ADC_DUAL_MODE
+ ccr = grpp->ccr & ~(ADC_CCR_CKMODE_MASK | ADC_CCR_DAMDF_MASK);
+ osalDbgAssert(!STM32_ADC_DUAL_MODE || ((grpp->num_channels & 1) == 0),
+ "odd number of channels in dual mode");
+#endif
+
+ /* Calculating control registers values.*/
+ dmamode = adcp->dmamode;
+ if (grpp->circular) {
+ dmamode |= STM32_DMA_CR_CIRC;
+ cfgr = grpp->cfgr | ADC_CFGR_DMNGT_CIRCULAR;
+ if (adcp->depth > 1) {
+ /* If circular buffer depth > 1, then the half transfer interrupt
+ is enabled in order to allow streaming processing.*/
+ dmamode |= STM32_DMA_CR_HTIE;
+ }
+ }
+ else {
+ cfgr = grpp->cfgr | ADC_CFGR_DMNGT_ONESHOT;
+ }
+
+ /* DMA setup.*/
+ dmaStreamSetMemory0(adcp->data.dma, adcp->samples);
+#if STM32_ADC_DUAL_MODE
+ dmaStreamSetTransactionSize(adcp->data.dma, ((uint32_t)grpp->num_channels / 2U) *
+ (uint32_t)adcp->depth);
+#else
+ dmaStreamSetTransactionSize(adcp->data.dma, (uint32_t)grpp->num_channels *
+ (uint32_t)adcp->depth);
+#endif
+ dmaStreamSetMode(adcp->data.dma, dmamode);
+ dmaStreamEnable(adcp->data.dma);
+ }
+#endif /* STM32_ADC_USE_ADC12 == TRUE */
+
+#if STM32_ADC_USE_ADC3 == TRUE
+ if (&ADCD3 == adcp) {
+ /* Calculating control registers values.*/
+ dmamode = adcp->dmamode;
+ if (grpp->circular) {
+ dmamode |= STM32_BDMA_CR_CIRC;
+ cfgr = grpp->cfgr | ADC_CFGR_DMNGT_CIRCULAR;
+ if (adcp->depth > 1) {
+ /* If circular buffer depth > 1, then the half transfer interrupt
+ is enabled in order to allow streaming processing.*/
+ dmamode |= STM32_BDMA_CR_HTIE;
+ }
+ }
+ else {
+ cfgr = grpp->cfgr | ADC_CFGR_DMNGT_ONESHOT;
+ }
+
+ /* DMA setup.*/
+ bdmaStreamSetMemory(adcp->data.bdma, adcp->samples);
+ bdmaStreamSetTransactionSize(adcp->data.bdma, (uint32_t)grpp->num_channels *
+ (uint32_t)adcp->depth);
+ bdmaStreamSetMode(adcp->data.bdma, dmamode);
+ bdmaStreamEnable(adcp->data.bdma);
+ }
+#endif /* STM32_ADC_USE_ADC3 == TRUE */
+
+ /* ADC setup, if it is defined a callback for the analog watch dog then it
+ is enabled.*/
+ adcp->adcm->ISR = adcp->adcm->ISR;
+ adcp->adcm->IER = ADC_IER_OVRIE | ADC_IER_AWD1IE;
+#if STM32_ADC_DUAL_MODE == TRUE && STM32_ADC_USE_ADC12 == TRUE
+ /* Configuration for dual mode ADC12 */
+ if (&ADCD1 == adcp) {
+ /* Configuring the CCR register with the user-specified settings
+ in the conversion group configuration structure, static settings are
+ preserved.*/
+ adcp->adcc->CCR = (adcp->adcc->CCR &
+ (ADC_CCR_CKMODE_MASK | ADC_CCR_DAMDF_MASK)) | ccr;
+
+ adcp->adcm->CFGR2 = grpp->cfgr2;
+ adcp->adcm->PCSEL = grpp->pcsel;
+ adcp->adcm->LTR1 = grpp->ltr1;
+ adcp->adcm->HTR1 = grpp->htr1;
+ adcp->adcm->LTR1 = grpp->ltr2;
+ adcp->adcm->HTR1 = grpp->htr2;
+ adcp->adcm->LTR1 = grpp->ltr3;
+ adcp->adcm->HTR1 = grpp->htr3;
+ adcp->adcm->SMPR1 = grpp->smpr[0];
+ adcp->adcm->SMPR2 = grpp->smpr[1];
+ adcp->adcm->SQR1 = grpp->sqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels / 2);
+ adcp->adcm->SQR2 = grpp->sqr[1];
+ adcp->adcm->SQR3 = grpp->sqr[2];
+ adcp->adcm->SQR4 = grpp->sqr[3];
+ adcp->adcs->CFGR2 = grpp->cfgr2;
+ adcp->adcs->PCSEL = grpp->pcsel;
+ adcp->adcs->LTR1 = grpp->ltr1;
+ adcp->adcs->HTR1 = grpp->htr1;
+ adcp->adcs->LTR1 = grpp->ltr2;
+ adcp->adcs->HTR1 = grpp->htr2;
+ adcp->adcs->LTR1 = grpp->ltr3;
+ adcp->adcs->HTR1 = grpp->htr3;
+ adcp->adcs->SMPR1 = grpp->ssmpr[0];
+ adcp->adcs->SMPR2 = grpp->ssmpr[1];
+ adcp->adcs->SQR1 = grpp->ssqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels / 2);
+ adcp->adcs->SQR2 = grpp->ssqr[1];
+ adcp->adcs->SQR3 = grpp->ssqr[2];
+ adcp->adcs->SQR4 = grpp->ssqr[3];
+
+ /* ADC configuration.*/
+ adcp->adcm->CFGR = cfgr;
+ adcp->adcs->CFGR = cfgr;
+ }
+
+#endif /* STM32_ADC_DUAL_MODE == TRUE && STM32_ADC_USE_ADC12 == TRUE */
+
+#if STM32_ADC_DUAL_MODE == FALSE || STM32_ADC_USE_ADC3 == TRUE
+ /* Configuration for ADC3 and single mode ADC1 */
+#if STM32_ADC_DUAL_MODE == TRUE && STM32_ADC_USE_ADC3 == TRUE
+ if (&ADCD3 == adcp)
+#endif
+ {
+ adcp->adcm->CFGR2 = grpp->cfgr2;
+#if (STM32_ADC_USE_ADC12 == TRUE)
+ adcp->adcm->PCSEL = grpp->pcsel;
+#endif
+ adcp->adcm->LTR1 = grpp->ltr1;
+ adcp->adcm->HTR1 = grpp->htr1;
+ adcp->adcm->LTR1 = grpp->ltr2;
+ adcp->adcm->HTR1 = grpp->htr2;
+ adcp->adcm->LTR1 = grpp->ltr3;
+ adcp->adcm->HTR1 = grpp->htr3;
+ adcp->adcm->SMPR1 = grpp->smpr[0];
+ adcp->adcm->SMPR2 = grpp->smpr[1];
+ adcp->adcm->SQR1 = grpp->sqr[0] | ADC_SQR1_NUM_CH(grpp->num_channels);
+ adcp->adcm->SQR2 = grpp->sqr[1];
+ adcp->adcm->SQR3 = grpp->sqr[2];
+ adcp->adcm->SQR4 = grpp->sqr[3];
+
+ /* ADC configuration.*/
+ adcp->adcm->CFGR = cfgr;
+ }
+#endif
+
+ /* Starting conversion.*/
+ adcp->adcm->CR |= ADC_CR_ADSTART;
+}
+
+/**
+ * @brief Stops an ongoing conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop_conversion(ADCDriver *adcp) {
+
+#if STM32_ADC_USE_ADC12 == TRUE
+ if (&ADCD1 == adcp) {
+ dmaStreamDisable(adcp->data.dma);
+ }
+#endif /* STM32_ADC_USE_ADC12 == TRUE */
+
+#if STM32_ADC_USE_ADC3 == TRUE
+ if (&ADCD3 == adcp) {
+ bdmaStreamDisable(adcp->data.bdma);
+ }
+#endif /* STM32_ADC_USE_ADC12 == TRUE */
+
+ adc_lld_stop_adc(adcp);
+}
+
+/**
+ * @brief Enables the VREFEN bit.
+ * @details The VREFEN bit is required in order to sample the VREF channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32EnableVREF(ADCDriver *adcp) {
+
+ adcp->adcc->CCR |= ADC_CCR_VREFEN;
+}
+
+/**
+ * @brief Disables the VREFEN bit.
+ * @details The VREFEN bit is required in order to sample the VREF channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32DisableVREF(ADCDriver *adcp) {
+
+ adcp->adcc->CCR &= ~ADC_CCR_VREFEN;
+}
+
+/**
+ * @brief Enables the TSEN bit.
+ * @details The TSEN bit is required in order to sample the internal
+ * temperature sensor and internal reference voltage.
+ * @note This is an STM32-only functionality.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32EnableTS(ADCDriver *adcp) {
+
+ adcp->adcc->CCR |= ADC_CCR_TSEN;
+}
+
+/**
+ * @brief Disables the TSEN bit.
+ * @details The TSEN bit is required in order to sample the internal
+ * temperature sensor and internal reference voltage.
+ * @note This is an STM32-only functionality.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32DisableTS(ADCDriver *adcp) {
+
+ adcp->adcc->CCR &= ~ADC_CCR_TSEN;
+}
+
+/**
+ * @brief Enables the VBATEN bit.
+ * @details The VBATEN bit is required in order to sample the VBAT channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32EnableVBAT(ADCDriver *adcp) {
+
+ adcp->adcc->CCR |= ADC_CCR_VBATEN;
+}
+
+/**
+ * @brief Disables the VBATEN bit.
+ * @details The VBATEN bit is required in order to sample the VBAT channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32DisableVBAT(ADCDriver *adcp) {
+
+ adcp->adcc->CCR &= ~ADC_CCR_VBATEN;
+}
+
+#endif /* HAL_USE_ADC */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.h
new file mode 100644
index 0000000..2740421
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv4/hal_adc_lld.h
@@ -0,0 +1,741 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ADCv4/hal_adc_lld.h
+ * @brief STM32 ADC subsystem low level driver header.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#ifndef HAL_ADC_LLD_H
+#define HAL_ADC_LLD_H
+
+#if HAL_USE_ADC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Available analog channels
+ * @{
+ */
+#define ADC_CHANNEL_IN0 0U /**< @brief External analog input 0. */
+#define ADC_CHANNEL_IN1 1U /**< @brief External analog input 1. */
+#define ADC_CHANNEL_IN2 2U /**< @brief External analog input 2. */
+#define ADC_CHANNEL_IN3 3U /**< @brief External analog input 3. */
+#define ADC_CHANNEL_IN4 4U /**< @brief External analog input 4. */
+#define ADC_CHANNEL_IN5 5U /**< @brief External analog input 5. */
+#define ADC_CHANNEL_IN6 6U /**< @brief External analog input 6. */
+#define ADC_CHANNEL_IN7 7U /**< @brief External analog input 7. */
+#define ADC_CHANNEL_IN8 8U /**< @brief External analog input 8. */
+#define ADC_CHANNEL_IN9 9U /**< @brief External analog input 9. */
+#define ADC_CHANNEL_IN10 10U /**< @brief External analog input 10. */
+#define ADC_CHANNEL_IN11 11U /**< @brief External analog input 11. */
+#define ADC_CHANNEL_IN12 12U /**< @brief External analog input 12. */
+#define ADC_CHANNEL_IN13 13U /**< @brief External analog input 13. */
+#define ADC_CHANNEL_IN14 14U /**< @brief External analog input 14. */
+#define ADC_CHANNEL_IN15 15U /**< @brief External analog input 15. */
+#define ADC_CHANNEL_IN16 16U /**< @brief External analog input 16. */
+#define ADC_CHANNEL_IN17 17U /**< @brief External analog input 17. */
+#define ADC_CHANNEL_IN18 18U /**< @brief External analog input 18. */
+#define ADC_CHANNEL_IN19 19U /**< @brief External analog input 19. */
+/** @} */
+
+/**
+ * @name ADC channels selection masks
+ * @{
+ */
+#define ADC_SELMASK_IN0 (1U << ADC_CHANNEL_IN0)
+#define ADC_SELMASK_IN1 (1U << ADC_CHANNEL_IN1)
+#define ADC_SELMASK_IN2 (1U << ADC_CHANNEL_IN2)
+#define ADC_SELMASK_IN3 (1U << ADC_CHANNEL_IN3)
+#define ADC_SELMASK_IN4 (1U << ADC_CHANNEL_IN4)
+#define ADC_SELMASK_IN5 (1U << ADC_CHANNEL_IN5)
+#define ADC_SELMASK_IN6 (1U << ADC_CHANNEL_IN6)
+#define ADC_SELMASK_IN7 (1U << ADC_CHANNEL_IN7)
+#define ADC_SELMASK_IN8 (1U << ADC_CHANNEL_IN8)
+#define ADC_SELMASK_IN9 (1U << ADC_CHANNEL_IN9)
+#define ADC_SELMASK_IN10 (1U << ADC_CHANNEL_IN10)
+#define ADC_SELMASK_IN11 (1U << ADC_CHANNEL_IN11)
+#define ADC_SELMASK_IN12 (1U << ADC_CHANNEL_IN12)
+#define ADC_SELMASK_IN13 (1U << ADC_CHANNEL_IN13)
+#define ADC_SELMASK_IN14 (1U << ADC_CHANNEL_IN14)
+#define ADC_SELMASK_IN15 (1U << ADC_CHANNEL_IN15)
+#define ADC_SELMASK_IN16 (1U << ADC_CHANNEL_IN16)
+#define ADC_SELMASK_IN17 (1U << ADC_CHANNEL_IN17)
+#define ADC_SELMASK_IN18 (1U << ADC_CHANNEL_IN18)
+#define ADC_SELMASK_IN19 (1U << ADC_CHANNEL_IN19)
+/** @} */
+
+/**
+ * @name Sampling rates
+ * @{
+ */
+#if defined(STM32H7XX)
+#if !defined(STM32H723xx) || STM32_ADC_USE_ADC3 == FALSE
+#define ADC_SMPR_SMP_1P5 0U /**< @brief 9 cycles conversion time */
+#define ADC_SMPR_SMP_2P5 1U /**< @brief 10 cycles conversion time. */
+#define ADC_SMPR_SMP_8P5 2U /**< @brief 16 cycles conversion time. */
+#define ADC_SMPR_SMP_16P5 3U /**< @brief 24 cycles conversion time. */
+#define ADC_SMPR_SMP_32P5 4U /**< @brief 40 cycles conversion time. */
+#define ADC_SMPR_SMP_64P5 5U /**< @brief 72 cycles conversion time. */
+#define ADC_SMPR_SMP_384P5 6U /**< @brief 392 cycles conversion time. */
+#define ADC_SMPR_SMP_810P5 7U /**< @brief 818 cycles conversion time. */
+#else
+#define ADC_SMPR_SMP_2P5 0U /**< @brief cycles conversion time */
+#define ADC_SMPR_SMP_6P5 1U /**< @brief cycles conversion time. */
+#define ADC_SMPR_SMP_12P5 2U /**< @brief cycles conversion time. */
+#define ADC_SMPR_SMP_24P5 3U /**< @brief cycles conversion time. */
+#define ADC_SMPR_SMP_47P5 4U /**< @brief cycles conversion time. */
+#define ADC_SMPR_SMP_92P5 5U /**< @brief cycles conversion time. */
+#define ADC_SMPR_SMP_247P5 6U /**< @brief cycles conversion time. */
+#define ADC_SMPR_SMP_640P5 7U /**< @brief cycles conversion time. */
+#endif
+#endif
+/** @} */
+
+/**
+ * @name CFGR register configuration helpers
+ * @{
+ */
+#define ADC_CFGR_DMNGT_MASK (3U << 0U)
+#define ADC_CFGR_DMNGT_NODMA (0U << 0U)
+#define ADC_CFGR_DMNGT_ONESHOT (1U << 0U)
+#define ADC_CFGR_DMNGT_DFSDM (2U << 0U)
+#define ADC_CFGR_DMNGT_CIRCULAR (3U << 0U)
+
+#define ADC_CFGR_RES_MASK (7U << 2U)
+#define ADC_CFGR_RES_16BITS (0U << 2U)
+#define ADC_CFGR_RES_10BITS (3U << 2U)
+#if !defined(STM32_ENFORCE_H7_REV_XY)
+#define ADC_CFGR_RES_14BITS (5U << 2U)
+#define ADC_CFGR_RES_12BITS (6U << 2U)
+#define ADC_CFGR_RES_8BITS (7U << 2U)
+#else
+#define ADC_CFGR_RES_14BITS (1U << 2U)
+#define ADC_CFGR_RES_12BITS (2U << 2U)
+#define ADC_CFGR_RES_8BITS (4U << 2U)
+#endif
+
+#define ADC_CFGR_EXTSEL_MASK (15U << 5U)
+#define ADC_CFGR_EXTSEL_SRC(n) ((n) << 5U)
+
+#define ADC_CFGR_EXTEN_MASK (3U << 10U)
+#define ADC_CFGR_EXTEN_DISABLED (0U << 10U)
+#define ADC_CFGR_EXTEN_RISING (1U << 10U)
+#define ADC_CFGR_EXTEN_FALLING (2U << 10U)
+#define ADC_CFGR_EXTEN_BOTH (3U << 10U)
+
+#define ADC_CFGR_DISCEN_MASK (1U << 16U)
+#define ADC_CFGR_DISCEN_DISABLED (0U << 16U)
+#define ADC_CFGR_DISCEN_ENABLED (1U << 16U)
+
+#define ADC_CFGR_DISCNUM_MASK (7U << 17U)
+#define ADC_CFGR_DISCNUM_VAL(n) ((n) << 17U)
+/** @} */
+
+/**
+ * @name CCR register configuration helpers
+ * @{
+ */
+#define ADC_CCR_DUAL_MASK (31U << 0U)
+#define ADC_CCR_DUAL_FIELD(n) ((n) << 0U)
+#define ADC_CCR_DUAL_INDEPENDENT (0U << 0U) /**< @brief Independent, dual mode disabled. */
+#define ADC_CCR_DUAL_REG_SIMULT (6U << 0U) /**< @brief Regular simultaneous. */
+#define ADC_CCR_DUAL_REG_INTERL (7U << 0U) /**< @brief Regular interleaved. */
+#define ADC_CCR_DUAL_INJ_SIMULT (5U << 0U) /**< @brief Injected simultaneous. */
+#define ADC_CCR_DUAL_INJ_ALTERNATE (9U << 0U) /**< @brief Injected alternate trigger. */
+#define ADC_CCR_DUAL_REG_SIM_INJ_SIM (1U << 0U) /**< @brief Combined regular simultaneous + injected simultaneous. */
+#define ADC_CCR_DUAL_REG_SIM_INJ_ALT (2U << 0U) /**< @brief Combined regular simultaneous + injected alternate trigger. */
+#define ADC_CCR_DUAL_REG_INT_INJ_SIM (3U << 0U) /**< @brief Combined regular interleaved + injected simultaneous. */
+#define ADC_CCR_DELAY_MASK (15U << 8U)
+#define ADC_CCR_DELAY_FIELD(n) ((n) << 8U)
+#define ADC_CCR_DAMDF_MASK (3U << 14U)
+#define ADC_CCR_DAMDF_DISABLED (0U << 14U)
+#define ADC_CCR_DAMDF_HWORD (2U << 14U)
+#define ADC_CCR_DAMDF_BYTE (3U << 14U)
+#define ADC_CCR_CKMODE_MASK (3U << 16U)
+#define ADC_CCR_CKMODE_ADCCK (0U << 16U)
+#define ADC_CCR_CKMODE_AHB_DIV1 (1U << 16U)
+#define ADC_CCR_CKMODE_AHB_DIV2 (2U << 16U)
+#define ADC_CCR_CKMODE_AHB_DIV4 (3U << 16U)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief Enables the ADC1 and ADC2 master/slave mode.
+ */
+#if !defined(STM32_ADC_DUAL_MODE) || defined(__DOXYGEN__)
+#define STM32_ADC_DUAL_MODE FALSE
+#endif
+
+/**
+ * @brief Makes the ADC samples type an 8bits one.
+ * @note 10, 12, 14 and 16 bits sampling mode must not be used when this
+ * option is enabled.
+ */
+#if !defined(STM32_ADC_COMPACT_SAMPLES) || defined(__DOXYGEN__)
+#define STM32_ADC_COMPACT_SAMPLES FALSE
+#endif
+
+/**
+ * @brief ADC1/ADC2 driver enable switch.
+ * @details If set to @p TRUE the support for ADC1/ADC2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ADC_USE_ADC12) || defined(__DOXYGEN__)
+#define STM32_ADC_USE_ADC12 FALSE
+#endif
+
+/**
+ * @brief ADC3 driver enable switch.
+ * @details If set to @p TRUE the support for ADC3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ADC_USE_ADC3) || defined(__DOXYGEN__)
+#define STM32_ADC_USE_ADC3 FALSE
+#endif
+
+/**
+ * @brief ADC1/ADC2 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_ADC_ADC12_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC12_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC3 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_ADC_ADC3_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC3_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC1/ADC2 interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC12_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC12_IRQ_PRIORITY 5
+#endif
+
+/**
+ * @brief ADC3 interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC3_IRQ_PRIORITY 5
+#endif
+
+/**
+ * @brief ADC1/ADC2 clock source and mode.
+ */
+#if !defined(STM32_ADC_ADC12_CLOCK_MODE) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4
+#endif
+
+/**
+ * @brief ADC3 clock source and mode.
+ */
+#if !defined(STM32_ADC_ADC3_CLOCK_MODE) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC3_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV4
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Supported devices checks.*/
+#if !defined(STM32H7XX)
+#error "ADCv4 only supports H7 STM32 devices"
+#endif
+
+/* Registry checks.*/
+#if !defined(STM32_HAS_ADC1) || !defined(STM32_HAS_ADC2) || \
+ !defined(STM32_HAS_ADC3)
+#error "STM32_HAS_ADCx not defined in registry"
+#endif
+
+/* Units checks.*/
+#if STM32_ADC_USE_ADC12 && !STM32_HAS_ADC1
+#error "ADC1 not present in the selected device"
+#endif
+
+#if STM32_ADC_DUAL_MODE && !STM32_HAS_ADC2
+#error "ADC2 not present in the selected device"
+#endif
+
+#if STM32_ADC_USE_ADC3 && !STM32_HAS_ADC3
+#error "ADC3 not present in the selected device"
+#endif
+
+/* IRQ handlers checks.*/
+#if STM32_HAS_ADC1 && !defined(STM32_ADC12_HANDLER)
+#error "STM32_ADC12_HANDLER not defined in registry"
+#endif
+
+#if STM32_HAS_ADC2 && !defined(STM32_ADC12_HANDLER)
+#error "STM32_ADC12_HANDLER not defined in registry"
+#endif
+
+#if STM32_HAS_ADC3 && !defined(STM32_ADC3_HANDLER)
+#error "STM32_ADC3_HANDLER not defined in registry"
+#endif
+
+/* IRQ vector numbers checks.*/
+#if STM32_HAS_ADC1 && !defined(STM32_ADC12_NUMBER)
+#error "STM32_ADC12_NUMBER not defined in registry"
+#endif
+
+#if STM32_HAS_ADC2 && !defined(STM32_ADC12_NUMBER)
+#error "STM32_ADC12_NUMBER not defined in registry"
+#endif
+
+#if STM32_HAS_ADC3 && !defined(STM32_ADC3_NUMBER)
+#error "STM32_ADC3_NUMBER not defined in registry"
+#endif
+
+/* At least one ADC must be assigned.*/
+#if !STM32_ADC_USE_ADC12 && !STM32_ADC_USE_ADC3
+#error "ADC driver activated but no ADC peripheral assigned"
+#endif
+
+/* Dual mode is only supported with ADC12.*/
+#if !STM32_ADC_USE_ADC12 && STM32_ADC_DUAL_MODE
+#error "STM32_ADC_DUAL_MODE only supported with ADC12"
+#endif
+
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if STM32_ADC_USE_ADC12 && !defined(STM32_ADC_ADC12_DMA_STREAM)
+#error "STM32_ADC_ADC12_DMA_STREAM not defined"
+#endif
+
+#if STM32_ADC_USE_ADC3 && !defined(STM32_ADC_ADC3_BDMA_STREAM)
+#error "STM32_ADC_ADC3_BDMA_STREAM not defined"
+#endif
+
+/* DMA channel range tests.*/
+#if STM32_ADC_USE_ADC12 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_ADC_ADC12_DMA_STREAM)
+#error "Invalid DMA channel assigned to ADC12"
+#endif
+
+#if STM32_ADC_USE_ADC3 && \
+ !STM32_BDMA_IS_VALID_STREAM(STM32_ADC_ADC3_BDMA_STREAM)
+#error "Invalid DMA channel assigned to ADC3"
+#endif
+
+/* DMA priority tests.*/
+#if STM32_ADC_USE_ADC12 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC12_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to ADC1"
+#endif
+
+#if STM32_ADC_USE_ADC3 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC3_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to ADC3"
+#endif
+
+/* ADC IRQ priority tests.*/
+#if STM32_ADC_USE_ADC12 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC12_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to ADC1"
+#endif
+
+#if STM32_ADC_USE_ADC3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to ADC3"
+#endif
+
+#if !defined(STM32_ENFORCE_H7_REV_XY)
+/* ADC clock source checks.*/
+#if (STM32_D1HPRE == STM32_D1HPRE_DIV1)
+#define STM32_ADC_SCLK STM32_HCLK
+#else
+#define STM32_ADC_SCLK (STM32_HCLK / 2)
+#endif
+
+#if STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK
+/* CHTODO: also check ADC_CCR_PRESC.*/
+#define STM32_ADC12_CLOCK (STM32_ADCCLK / 2)
+#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1
+#define STM32_ADC12_CLOCK (STM32_ADC_SCLK / 1 / 2)
+#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2
+#define STM32_ADC12_CLOCK (STM32_ADC_SCLK / 2 / 2)
+#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4
+#define STM32_ADC12_CLOCK (STM32_ADC_SCLK / 4 / 2)
+#else
+#error "invalid clock mode selected for STM32_ADC_ADC12_CLOCK_MODE"
+#endif
+
+#if STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK
+/* CHTODO: also check ADC_CCR_PRESC.*/
+#define STM32_ADC3_CLOCK (STM32_ADCCLK / 2)
+#elif STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1
+#define STM32_ADC3_CLOCK (STM32_ADC_SCLK / 1 / 2)
+#elif STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2
+#define STM32_ADC3_CLOCK (STM32_ADC_SCLK / 2 / 2)
+#elif STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4
+#define STM32_ADC3_CLOCK (STM32_ADC_SCLK / 4 / 2)
+#else
+#error "invalid clock mode selected for STM32_ADC_ADC3_CLOCK_MODE"
+#endif
+
+#else /* defined(STM32_ENFORCE_H7_REV_XY) */
+
+#if STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK
+#define STM32_ADC12_CLOCK STM32_ADCCLK
+#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1
+#define STM32_ADC12_CLOCK (STM32_HCLK / 1)
+#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2
+#define STM32_ADC12_CLOCK (STM32_HCLK / 2)
+#elif STM32_ADC_ADC12_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4
+#define STM32_ADC12_CLOCK (STM32_HCLK / 4)
+#else
+#error "invalid clock mode selected for STM32_ADC_ADC12_CLOCK_MODE"
+#endif
+
+#if STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_ADCCK
+#define STM32_ADC3_CLOCK STM32_ADCCLK
+#elif STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV1
+#define STM32_ADC3_CLOCK (STM32_HCLK / 1)
+#elif STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV2
+#define STM32_ADC3_CLOCK (STM32_HCLK / 2)
+#elif STM32_ADC_ADC3_CLOCK_MODE == ADC_CCR_CKMODE_AHB_DIV4
+#define STM32_ADC3_CLOCK (STM32_HCLK / 4)
+#else
+#error "invalid clock mode selected for STM32_ADC_ADC3_CLOCK_MODE"
+#endif
+
+#endif /* defined(STM32_ENFORCE_H7_REV_XY) */
+
+#if STM32_ADC12_CLOCK > STM32_ADCCLK_MAX
+#error "STM32_ADC12_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)"
+#endif
+
+#if STM32_ADC3_CLOCK > STM32_ADCCLK_MAX
+#error "STM32_ADC3_CLOCK exceeding maximum frequency (STM32_ADCCLK_MAX)"
+#endif
+
+#if !defined(STM32_ENFORCE_H7_REV_XY)
+/* ADC boost checks.*/
+#if STM32_ADC12_CLOCK > 6250000
+#define STM32_ADC12_BOOST (1U << 8U)
+#elif STM32_ADC12_CLOCK > 12500000
+#define STM32_ADC12_BOOST (2U << 8U)
+#elif STM32_ADC12_CLOCK > 25000000
+#define STM32_ADC12_BOOST (3U << 8U)
+#else
+#define STM32_ADC12_BOOST (0U << 8U)
+#endif
+
+#if STM32_ADC3_CLOCK > 6250000
+#define STM32_ADC3_BOOST (1U << 8U)
+#elif STM32_ADC3_CLOCK > 12500000
+#define STM32_ADC3_BOOST (2U << 8U)
+#elif STM32_ADC3_CLOCK > 25000000
+#define STM32_ADC3_BOOST (3U << 8U)
+#else
+#define STM32_ADC3_BOOST (0U << 8U)
+#endif
+
+#else /* defined(STM32_ENFORCE_H7_REV_XY) */
+
+#if STM32_ADC12_CLOCK > 20000000
+#define STM32_ADC12_BOOST (1U << 8U)
+#else
+#define STM32_ADC12_BOOST (0U << 8U)
+#endif
+
+#if STM32_ADC3_CLOCK > 20000000
+#define STM32_ADC3_BOOST (1U << 8U)
+#else
+#define STM32_ADC3_BOOST (0U << 8U)
+#endif
+
+#endif /* defined(STM32_ENFORCE_H7_REV_XY) */
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+#if STM32_ADC_USE_ADC12
+#define STM32_ADC_DMA_REQUIRED
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+#endif
+
+#if STM32_ADC_USE_ADC3
+#define STM32_ADC_BDMA_REQUIRED
+#if !defined(STM32_BDMA_REQUIRED)
+#define STM32_BDMA_REQUIRED
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC sample data type.
+ */
+#if !STM32_ADC_COMPACT_SAMPLES || defined(__DOXYGEN__)
+typedef uint16_t adcsample_t;
+#else
+typedef uint8_t adcsample_t;
+#endif
+
+/**
+ * @brief Channels number in a conversion group.
+ */
+typedef uint32_t adc_channels_num_t;
+
+/**
+ * @brief Possible ADC failure causes.
+ * @note Error codes are architecture dependent and should not relied
+ * upon.
+ */
+typedef enum {
+ ADC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */
+ ADC_ERR_OVERFLOW = 1, /**< ADC overflow condition. */
+ ADC_ERR_AWD1 = 2, /**< Watchdog 1 triggered. */
+ ADC_ERR_AWD2 = 3, /**< Watchdog 2 triggered. */
+ ADC_ERR_AWD3 = 4 /**< Watchdog 3 triggered. */
+} adcerror_t;
+
+/**
+ * @brief Type of a DMA channel pointer choice.
+ */
+typedef union {
+#if defined(STM32_ADC_DMA_REQUIRED) || defined(__DOXYGEN__)
+ /**
+ * @brief DMA stream.
+ */
+ const stm32_dma_stream_t *dma;
+#endif
+#if defined(STM32_ADC_BDMA_REQUIRED) || defined(__DOXYGEN__)
+ /**
+ * @brief BDMA stream.
+ */
+ const stm32_bdma_stream_t *bdma;
+#endif
+} adc_ldd_dma_reference_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the ADC driver structure.
+ */
+#if (STM32_ADC_DUAL_MODE == TRUE) || defined(__DOXYGEN__)
+#define adc_lld_driver_fields \
+ /* Pointer to the master ADCx registers block.*/ \
+ ADC_TypeDef *adcm; \
+ /* Pointer to the slave ADCx registers block.*/ \
+ ADC_TypeDef *adcs; \
+ /* Pointer to the common ADCx_y registers block.*/ \
+ ADC_Common_TypeDef *adcc; \
+ /* Pointer to associated DMA channel.*/ \
+ adc_ldd_dma_reference_t data; \
+ /* DMA mode bit mask.*/ \
+ uint32_t dmamode
+#elif (STM32_ADC_USE_ADC3 == TRUE)
+#define adc_lld_driver_fields \
+ /* Pointer to the master ADCx registers block.*/ \
+ ADC3_TypeDef *adcm; \
+ /* Pointer to the slave ADCx registers block.*/ \
+ ADC_Common_TypeDef *adcc; \
+ /* Pointer to associated DMA channel.*/ \
+ adc_ldd_dma_reference_t data; \
+ /* DMA mode bit mask.*/ \
+ uint32_t dmamode
+#else
+#define adc_lld_driver_fields \
+ /* Pointer to the master ADCx registers block.*/ \
+ ADC12_TypeDef *adcm; \
+ /* Pointer to the slave ADCx registers block.*/ \
+ ADC_Common_TypeDef *adcc; \
+ /* Pointer to associated DMA channel.*/ \
+ adc_ldd_dma_reference_t data; \
+ /* DMA mode bit mask.*/ \
+ uint32_t dmamode
+#endif
+
+/**
+ * @brief Low level fields of the ADC configuration structure.
+ */
+#define adc_lld_config_fields \
+ /* ADC DIFSEL register initialization data.*/ \
+ uint32_t difsel; \
+ /* Calibration mode, specify ADCCALIN and/or ADCCALDIF bits in here.*/ \
+ uint32_t calibration
+
+#if (STM32_ADC_DUAL_MODE == TRUE) || defined(__DOXYGEN__)
+#define adc_lld_configuration_group_fields \
+ /* ADC CFGR register initialization data. \
+ NOTE: The bits DMAEN and DMACFG are enforced internally \
+ to the driver, keep them to zero. \
+ NOTE: The bits @p ADC_CFGR_CONT or @p ADC_CFGR_DISCEN must be \
+ specified in continuous mode or if the buffer depth is \
+ greater than one.*/ \
+ uint32_t cfgr; \
+ /* ADC CFGR2 register initialization data. \
+ NOTE: Put this field to zero if not using oversampling.*/ \
+ uint32_t cfgr2; \
+ /* ADC CCR register initialization data*/ \
+ uint32_t ccr; \
+ /* ADC PCSEL register initialization data.*/ \
+ uint32_t pcsel; \
+ /* ADC LTR1 register initialization data.*/ \
+ uint32_t ltr1; \
+ /* ADC HTR1 register initialization data.*/ \
+ uint32_t htr1; \
+ /* ADC LTR2 register initialization data.*/ \
+ uint32_t ltr2; \
+ /* ADC HTR2 register initialization data.*/ \
+ uint32_t htr2; \
+ /* ADC LTR3 register initialization data.*/ \
+ uint32_t ltr3; \
+ /* ADC HTR3 register initialization data.*/ \
+ uint32_t htr3; \
+ /* ADC SMPRx registers initialization data.*/ \
+ uint32_t smpr[2]; \
+ /* ADC SQRx register initialization data.*/ \
+ uint32_t sqr[4]; \
+ /* Slave ADC SMPRx registers initialization data. \
+ NOTE: This field is only present in dual mode.*/ \
+ uint32_t ssmpr[2]; \
+ /* Slave ADC SQRx register initialization data. \
+ NOTE: This field is only present in dual mode.*/ \
+ uint32_t ssqr[4]
+#else /* STM32_ADC_DUAL_MODE == FALSE */
+#define adc_lld_configuration_group_fields \
+ uint32_t cfgr; \
+ uint32_t cfgr2; \
+ uint32_t ccr; \
+ uint32_t pcsel; \
+ uint32_t ltr1; \
+ uint32_t htr1; \
+ uint32_t ltr2; \
+ uint32_t htr2; \
+ uint32_t ltr3; \
+ uint32_t htr3; \
+ uint32_t smpr[2]; \
+ uint32_t sqr[4]
+#endif /* STM32_ADC_DUAL_MODE == FALSE */
+
+/**
+ * @name Sequences building helper macros
+ * @{
+ */
+/**
+ * @brief Number of channels in a conversion sequence.
+ */
+#define ADC_SQR1_NUM_CH(n) (((n) - 1U) << 0U)
+
+#define ADC_SQR1_SQ1_N(n) ((n) << 6U) /**< @brief 1st channel in seq. */
+#define ADC_SQR1_SQ2_N(n) ((n) << 12U)/**< @brief 2nd channel in seq. */
+#define ADC_SQR1_SQ3_N(n) ((n) << 18U)/**< @brief 3rd channel in seq. */
+#define ADC_SQR1_SQ4_N(n) ((n) << 24U)/**< @brief 4th channel in seq. */
+
+#define ADC_SQR2_SQ5_N(n) ((n) << 0U) /**< @brief 5th channel in seq. */
+#define ADC_SQR2_SQ6_N(n) ((n) << 6U) /**< @brief 6th channel in seq. */
+#define ADC_SQR2_SQ7_N(n) ((n) << 12U)/**< @brief 7th channel in seq. */
+#define ADC_SQR2_SQ8_N(n) ((n) << 18U)/**< @brief 8th channel in seq. */
+#define ADC_SQR2_SQ9_N(n) ((n) << 24U)/**< @brief 9th channel in seq. */
+
+#define ADC_SQR3_SQ10_N(n) ((n) << 0U) /**< @brief 10th channel in seq.*/
+#define ADC_SQR3_SQ11_N(n) ((n) << 6U) /**< @brief 11th channel in seq.*/
+#define ADC_SQR3_SQ12_N(n) ((n) << 12U)/**< @brief 12th channel in seq.*/
+#define ADC_SQR3_SQ13_N(n) ((n) << 18U)/**< @brief 13th channel in seq.*/
+#define ADC_SQR3_SQ14_N(n) ((n) << 24U)/**< @brief 14th channel in seq.*/
+
+#define ADC_SQR4_SQ15_N(n) ((n) << 0U) /**< @brief 15th channel in seq.*/
+#define ADC_SQR4_SQ16_N(n) ((n) << 6U) /**< @brief 16th channel in seq.*/
+/** @} */
+
+/**
+ * @name Sampling rate settings helper macros
+ * @{
+ */
+#define ADC_SMPR1_SMP_AN0(n) ((n) << 0U) /**< @brief AN0 sampling time. */
+#define ADC_SMPR1_SMP_AN1(n) ((n) << 3U) /**< @brief AN1 sampling time. */
+#define ADC_SMPR1_SMP_AN2(n) ((n) << 6U) /**< @brief AN2 sampling time. */
+#define ADC_SMPR1_SMP_AN3(n) ((n) << 9U) /**< @brief AN3 sampling time. */
+#define ADC_SMPR1_SMP_AN4(n) ((n) << 12U)/**< @brief AN4 sampling time. */
+#define ADC_SMPR1_SMP_AN5(n) ((n) << 15U)/**< @brief AN5 sampling time. */
+#define ADC_SMPR1_SMP_AN6(n) ((n) << 18U)/**< @brief AN6 sampling time. */
+#define ADC_SMPR1_SMP_AN7(n) ((n) << 21U)/**< @brief AN7 sampling time. */
+#define ADC_SMPR1_SMP_AN8(n) ((n) << 24U)/**< @brief AN8 sampling time. */
+#define ADC_SMPR1_SMP_AN9(n) ((n) << 27U)/**< @brief AN9 sampling time. */
+
+#define ADC_SMPR2_SMP_AN10(n) ((n) << 0U) /**< @brief AN10 sampling time. */
+#define ADC_SMPR2_SMP_AN11(n) ((n) << 3U) /**< @brief AN11 sampling time. */
+#define ADC_SMPR2_SMP_AN12(n) ((n) << 6U) /**< @brief AN12 sampling time. */
+#define ADC_SMPR2_SMP_AN13(n) ((n) << 9U) /**< @brief AN13 sampling time. */
+#define ADC_SMPR2_SMP_AN14(n) ((n) << 12U)/**< @brief AN14 sampling time. */
+#define ADC_SMPR2_SMP_AN15(n) ((n) << 15U)/**< @brief AN15 sampling time. */
+#define ADC_SMPR2_SMP_AN16(n) ((n) << 18U)/**< @brief AN16 sampling time. */
+#define ADC_SMPR2_SMP_AN17(n) ((n) << 21U)/**< @brief AN17 sampling time. */
+#define ADC_SMPR2_SMP_AN18(n) ((n) << 24U)/**< @brief AN18 sampling time. */
+#define ADC_SMPR2_SMP_AN19(n) ((n) << 27U)/**< @brief AN19 sampling time. */
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_ADC_USE_ADC12 && !defined(__DOXYGEN__)
+extern ADCDriver ADCD1;
+#endif
+
+#if STM32_ADC_USE_ADC3 && !defined(__DOXYGEN__)
+extern ADCDriver ADCD3;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void adc_lld_init(void);
+ void adc_lld_start(ADCDriver *adcp);
+ void adc_lld_stop(ADCDriver *adcp);
+ void adc_lld_start_conversion(ADCDriver *adcp);
+ void adc_lld_stop_conversion(ADCDriver *adcp);
+ void adcSTM32EnableVREF(ADCDriver *adcp);
+ void adcSTM32DisableVREF(ADCDriver *adcp);
+ void adcSTM32EnableTS(ADCDriver *adcp);
+ void adcSTM32DisableTS(ADCDriver *adcp);
+ void adcSTM32EnableVBAT(ADCDriver *adcp);
+ void adcSTM32DisableVBAT(ADCDriver *adcp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_ADC */
+
+#endif /* HAL_ADC_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv4/notes.txt b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv4/notes.txt
new file mode 100644
index 0000000..d0b59b7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv4/notes.txt
@@ -0,0 +1,13 @@
+STM32 ADCv4 driver.
+
+Driver capability:
+
+- Supports the STM32 "fast" ADC found on H7 sub-family.
+
+The file registry must export:
+
+STM32_HAS_ADCx - ADCx presence flag (1..4).
+STM32_ADC12_HANDLER - IRQ vector name for ADC1 and ADC2.
+STM32_ADC12_NUMBER - IRQ vector number for ADC1 and ADC2.
+STM32_ADC34_HANDLER - IRQ vector name for ADC3 and ADC4.
+STM32_ADC34_NUMBER - IRQ vector number for ADC3 and ADC4.
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv5/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv5/driver.mk
new file mode 100644
index 0000000..1774fca
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv5/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv5
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.c
new file mode 100644
index 0000000..d4d52a0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.c
@@ -0,0 +1,476 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ADCv1/hal_adc_lld.c
+ * @brief STM32 ADC subsystem low level driver source.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_ADC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define ADC1_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_ADC_ADC1_DMA_STREAM, STM32_ADC1_DMA_CHN)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief ADC1 driver identifier.*/
+#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__)
+ADCDriver ADCD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC voltage regulator enable.
+ *
+ * @param[in] adc pointer to the ADC registers block
+ */
+NOINLINE static void adc_lld_vreg_on(ADC_TypeDef *adc) {
+
+ osalDbgAssert(adc->CR == 0, "invalid register state");
+
+#if defined(ADC_CR_ADVREGEN)
+ adc->CR = ADC_CR_ADVREGEN;
+ volatile uint32_t loop = (STM32_HCLK >> 20) << 4;
+ do {
+ loop--;
+ } while (loop > 0);
+#else
+#endif
+}
+
+/**
+ * @brief Stops an ongoing conversion, if any.
+ *
+ * @param[in] adc pointer to the ADC registers block
+ */
+static void adc_lld_stop_adc(ADC_TypeDef *adc) {
+
+ if (adc->CR & ADC_CR_ADSTART) {
+ adc->CR |= ADC_CR_ADSTP;
+ while (adc->CR & ADC_CR_ADSTP)
+ ;
+ adc->IER = 0;
+ }
+}
+
+/**
+ * @brief ADC DMA service routine.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ /* DMA, this could help only if the DMA tries to access an unmapped
+ address space or violates alignment rules.*/
+ _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE);
+ }
+ else {
+ /* It is possible that the conversion group has already be reset by the
+ ADC error handler, in this case this interrupt is spurious.*/
+ if (adcp->grpp != NULL) {
+ if ((flags & STM32_DMA_ISR_TCIF) != 0) {
+ /* Transfer complete processing.*/
+ _adc_isr_full_code(adcp);
+ }
+ else if ((flags & STM32_DMA_ISR_HTIF) != 0) {
+ /* Half transfer processing.*/
+ _adc_isr_half_code(adcp);
+ }
+ }
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__)
+#if !defined(STM32_ADC1_HANDLER)
+#error "STM32_ADC1_HANDLER not defined"
+#endif
+/**
+ * @brief ADC interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_ADC1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ adc_lld_serve_interrupt(&ADCD1);
+
+#if defined(STM32_ADC_ADC1_IRQ_HOOK)
+ STM32_ADC_ADC1_IRQ_HOOK
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level ADC driver initialization.
+ *
+ * @notapi
+ */
+void adc_lld_init(void) {
+
+#if STM32_ADC_USE_ADC1
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD1);
+ ADCD1.adc = ADC1;
+ ADCD1.dmastp = NULL;
+ ADCD1.dmamode = STM32_DMA_CR_CHSEL(ADC1_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_ADC_ADC1_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+
+ /* The vector is initialized on driver initialization and never
+ disabled.*/
+ nvicEnableVector(12, STM32_ADC_ADC1_IRQ_PRIORITY);
+#endif
+
+ /* Calibration procedure.*/
+ rccEnableADC1(true);
+
+ /* CCR setup.*/
+ ADC->CCR = STM32_ADC_PRESC << 18;
+
+ /* Regulator enabled and stabilized before calibration.*/
+ adc_lld_vreg_on(ADC1);
+
+ ADC1->CR |= ADC_CR_ADCAL;
+ while (ADC1->CR & ADC_CR_ADCAL)
+ ;
+ ADC1->CR = 0;
+ rccDisableADC1();
+}
+
+/**
+ * @brief Configures and activates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start(ADCDriver *adcp) {
+
+ /* If in stopped state then enables the ADC and DMA clocks.*/
+ if (adcp->state == ADC_STOP) {
+#if STM32_ADC_USE_ADC1
+ if (&ADCD1 == adcp) {
+ adcp->dmastp = dmaStreamAllocI(STM32_ADC_ADC1_DMA_STREAM,
+ STM32_ADC_ADC1_DMA_IRQ_PRIORITY,
+ (stm32_dmaisr_t)adc_lld_serve_rx_interrupt,
+ (void *)adcp);
+ osalDbgAssert(adcp->dmastp != NULL, "unable to allocate stream");
+ rccEnableADC1(true);
+
+ /* DMA setup.*/
+ dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR);
+ dmaSetRequestSource(adcp->dmastp, STM32_DMAMUX1_ADC1);
+
+ /* Clock settings.*/
+ adcp->adc->CFGR2 = STM32_ADC_ADC1_CKMODE;
+ }
+#endif /* STM32_ADC_USE_ADC1 */
+
+ /* Regulator enabled and stabilized before calibration.*/
+ adc_lld_vreg_on(ADC1);
+
+ /* ADC initial setup, starting the analog part here in order to reduce
+ the latency when starting a conversion.*/
+ adcp->adc->CR = ADC_CR_ADEN;
+ while (!(adcp->adc->ISR & ADC_ISR_ADRDY))
+ ;
+ }
+}
+
+/**
+ * @brief Deactivates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop(ADCDriver *adcp) {
+
+ /* If in ready state then disables the ADC clock and analog part.*/
+ if (adcp->state == ADC_READY) {
+
+ dmaStreamFreeI(adcp->dmastp);
+ adcp->dmastp = NULL;
+
+ /* Restoring CCR default.*/
+ ADC->CCR = STM32_ADC_PRESC << 18;
+
+ /* Disabling ADC.*/
+ if (adcp->adc->CR & ADC_CR_ADEN) {
+ adc_lld_stop_adc(adcp->adc);
+ adcp->adc->CR |= ADC_CR_ADDIS;
+ while (adcp->adc->CR & ADC_CR_ADDIS)
+ ;
+ }
+
+ /* Regulator and anything else off.*/
+ adcp->adc->CR = 0;
+
+#if STM32_ADC_USE_ADC1
+ if (&ADCD1 == adcp)
+ rccDisableADC1();
+#endif
+ }
+}
+
+/**
+ * @brief Starts an ADC conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start_conversion(ADCDriver *adcp) {
+ uint32_t mode, cfgr1, cfgr2;
+ const ADCConversionGroup *grpp = adcp->grpp;
+
+ /* DMA setup.*/
+ mode = adcp->dmamode;
+ cfgr1 = grpp->cfgr1 | ADC_CFGR1_DMAEN;
+ cfgr2 = adcp->adc->CFGR2 & STM32_ADC_CKMODE_MASK;
+ if (grpp->circular) {
+ mode |= STM32_DMA_CR_CIRC;
+ cfgr1 |= ADC_CFGR1_DMACFG;
+ if (adcp->depth > 1) {
+ /* If circular buffer depth > 1, then the half transfer interrupt
+ is enabled in order to allow streaming processing.*/
+ mode |= STM32_DMA_CR_HTIE;
+ }
+ }
+ dmaStreamSetMemory0(adcp->dmastp, adcp->samples);
+ dmaStreamSetTransactionSize(adcp->dmastp, (uint32_t)grpp->num_channels *
+ (uint32_t)adcp->depth);
+ dmaStreamSetMode(adcp->dmastp, mode);
+ dmaStreamEnable(adcp->dmastp);
+
+ /* ADC setup, if it is defined a callback for the analog watch dog then it
+ is enabled.*/
+ adcp->adc->ISR = adcp->adc->ISR;
+ if (grpp->error_cb != NULL) {
+ adcp->adc->IER = ADC_IER_OVRIE | ADC_IER_AWD1IE
+ | ADC_IER_AWD2IE
+ | ADC_IER_AWD3IE;
+ adcp->adc->TR1 = grpp->tr1;
+ adcp->adc->TR2 = grpp->tr2;
+ adcp->adc->TR3 = grpp->tr3;
+ adcp->adc->AWD2CR = grpp->awd2cr;
+ adcp->adc->AWD3CR = grpp->awd3cr;
+ }
+ adcp->adc->SMPR = grpp->smpr;
+ adcp->adc->CHSELR = grpp->chselr;
+
+ /* ADC configuration and start.*/
+ adcp->adc->CFGR1 = cfgr1;
+ adcp->adc->CFGR2 = cfgr2 | grpp->cfgr2;
+
+ /* ADC conversion start.*/
+ adcp->adc->CR |= ADC_CR_ADSTART;
+}
+
+/**
+ * @brief Stops an ongoing conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop_conversion(ADCDriver *adcp) {
+
+ dmaStreamDisable(adcp->dmastp);
+ adc_lld_stop_adc(adcp->adc);
+}
+
+/**
+ * @brief ISR code.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_serve_interrupt(ADCDriver *adcp) {
+ uint32_t isr;
+
+ isr = adcp->adc->ISR;
+ adcp->adc->ISR = isr;
+
+ /* It could be a spurious interrupt caused by overflows after DMA disabling,
+ just ignore it in this case.*/
+ if (adcp->grpp != NULL) {
+ /* Note, an overflow may occur after the conversion ended before the driver
+ is able to stop the ADC, this is why the DMA channel is checked too.*/
+ if ((isr & ADC_ISR_OVR) &&
+ (dmaStreamGetTransactionSize(adcp->dmastp) > 0)) {
+ /* ADC overflow condition, this could happen only if the DMA is unable
+ to read data fast enough.*/
+ _adc_isr_error_code(adcp, ADC_ERR_OVERFLOW);
+ }
+ if (isr & ADC_ISR_AWD1) {
+ /* Analog watchdog 1 error.*/
+ _adc_isr_error_code(adcp, ADC_ERR_AWD1);
+ }
+ if (isr & ADC_ISR_AWD2) {
+ /* Analog watchdog 2 error.*/
+ _adc_isr_error_code(adcp, ADC_ERR_AWD2);
+ }
+ if (isr & ADC_ISR_AWD3) {
+ /* Analog watchdog 3 error.*/
+ _adc_isr_error_code(adcp, ADC_ERR_AWD3);
+ }
+ }
+}
+
+/**
+ * @brief Enables the VREFEN bit.
+ * @details The VREFEN bit is required in order to sample the VREF channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32EnableVREF(ADCDriver *adcp) {
+
+ (void)adcp;
+
+ ADC->CCR |= ADC_CCR_VREFEN;
+}
+
+/**
+ * @brief Disables the VREFEN bit.
+ * @details The VREFEN bit is required in order to sample the VREF channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32DisableVREF(ADCDriver *adcp) {
+
+ (void)adcp;
+
+ ADC->CCR &= ~ADC_CCR_VREFEN;
+}
+
+/**
+ * @brief Enables the TSEN bit.
+ * @details The TSEN bit is required in order to sample the internal
+ * temperature sensor and internal reference voltage.
+ * @note This is an STM32-only functionality.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32EnableTS(ADCDriver *adcp) {
+
+ (void)adcp;
+
+ ADC->CCR |= ADC_CCR_TSEN;
+}
+
+/**
+ * @brief Disables the TSEN bit.
+ * @details The TSEN bit is required in order to sample the internal
+ * temperature sensor and internal reference voltage.
+ * @note This is an STM32-only functionality.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32DisableTS(ADCDriver *adcp) {
+
+ (void)adcp;
+
+ ADC->CCR &= ~ADC_CCR_TSEN;
+}
+
+#if defined(ADC_CCR_VBATEN) || defined(__DOXYGEN__)
+/**
+ * @brief Enables the VBATEN bit.
+ * @details The VBATEN bit is required in order to sample the VBAT channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32EnableVBAT(ADCDriver *adcp) {
+
+ (void)adcp;
+
+ ADC->CCR |= ADC_CCR_VBATEN;
+}
+
+/**
+ * @brief Disables the VBATEN bit.
+ * @details The VBATEN bit is required in order to sample the VBAT channel.
+ * @note This is an STM32-only functionality.
+ * @note This function is meant to be called after @p adcStart().
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adcSTM32DisableVBAT(ADCDriver *adcp) {
+
+ (void)adcp;
+
+ ADC->CCR &= ~ADC_CCR_VBATEN;
+}
+#endif /* defined(ADC_CCR_VBATEN) */
+
+#endif /* HAL_USE_ADC */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.h
new file mode 100644
index 0000000..45ea1e0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv5/hal_adc_lld.h
@@ -0,0 +1,401 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ADCv1/hal_adc_lld.h
+ * @brief STM32 ADC subsystem low level driver header.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#ifndef HAL_ADC_LLD_H
+#define HAL_ADC_LLD_H
+
+#if HAL_USE_ADC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Sampling rates
+ * @{
+ */
+#define ADC_SMPR_SMP_1P5 0U /**< @brief 14 cycles conversion time */
+#define ADC_SMPR_SMP_3P5 1U /**< @brief 16 cycles conversion time. */
+#define ADC_SMPR_SMP_7P5 2U /**< @brief 20 cycles conversion time. */
+#define ADC_SMPR_SMP_12P5 3U /**< @brief 25 cycles conversion time. */
+#define ADC_SMPR_SMP_19P5 4U /**< @brief 31 cycles conversion time. */
+#define ADC_SMPR_SMP_39P5 5U /**< @brief 52 cycles conversion time. */
+#define ADC_SMPR_SMP_79P5 6U /**< @brief 92 cycles conversion time. */
+#define ADC_SMPR_SMP_160P5 7U /**< @brief 173 cycles conversion time. */
+/** @} */
+
+/**
+ * @name CFGR1 register configuration helpers
+ * @{
+ */
+#define ADC_CFGR1_RES_12BIT (0U << 3U)
+#define ADC_CFGR1_RES_10BIT (1U << 3U)
+#define ADC_CFGR1_RES_8BIT (2U << 3U)
+#define ADC_CFGR1_RES_6BIT (3U << 3U)
+
+#define ADC_CFGR1_EXTSEL_MASK (15U << 6U)
+#define ADC_CFGR1_EXTSEL_SRC(n) ((n) << 6U)
+
+#define ADC_CFGR1_EXTEN_MASK (3U << 10U)
+#define ADC_CFGR1_EXTEN_DISABLED (0U << 10U)
+#define ADC_CFGR1_EXTEN_RISING (1U << 10U)
+#define ADC_CFGR1_EXTEN_FALLING (2U << 10U)
+#define ADC_CFGR1_EXTEN_BOTH (3U << 10U)
+/** @} */
+
+/**
+ * @name CFGR2 register configuration helpers
+ * @{
+ */
+#define STM32_ADC_CKMODE_MASK (3U << 30U)
+#define STM32_ADC_CKMODE_ADCCLK (0U << 30U)
+#define STM32_ADC_CKMODE_PCLK_DIV2 (1U << 30U)
+#define STM32_ADC_CKMODE_PCLK_DIV4 (2U << 30U)
+#define STM32_ADC_CKMODE_PCLK (3U << 30U)
+
+#define ADC_CFGR2_OVSR_MASK (7U << 2U)
+#define ADC_CFGR2_OVSR_2X (0U << 2U)
+#define ADC_CFGR2_OVSR_4X (1U << 2U)
+#define ADC_CFGR2_OVSR_8X (2U << 2U)
+#define ADC_CFGR2_OVSR_16X (3U << 2U)
+#define ADC_CFGR2_OVSR_32X (4U << 2U)
+#define ADC_CFGR2_OVSR_64X (5U << 2U)
+#define ADC_CFGR2_OVSR_128X (6U << 2U)
+#define ADC_CFGR2_OVSR_256X (7U << 2U)
+
+#define ADC_CFGR2_OVSS_MASK (15 << 5U)
+#define ADC_CFGR2_OVSS_SHIFT(n) ((n) << 5U)
+/** @} */
+
+/**
+ * @name CHSELR register initializers for CHSELRMOD=0
+ * @{
+ */
+#define ADC_CHSELR_CHSEL_N(n) (1U << (n))
+/** @} */
+
+/**
+ * @name CHSELR register initializers for CHSELRMOD=1
+ * @{
+ */
+#define ADC_CHSELR_SQ1_N(n) ((uint32_t)(n) << 0U)
+#define ADC_CHSELR_SQ2_N(n) ((uint32_t)(n) << 4U)
+#define ADC_CHSELR_SQ3_N(n) ((uint32_t)(n) << 8U)
+#define ADC_CHSELR_SQ4_N(n) ((uint32_t)(n) << 12U)
+#define ADC_CHSELR_SQ5_N(n) ((uint32_t)(n) << 16U)
+#define ADC_CHSELR_SQ6_N(n) ((uint32_t)(n) << 20U)
+#define ADC_CHSELR_SQ7_N(n) ((uint32_t)(n) << 24U)
+#define ADC_CHSELR_SQ8_N(n) ((uint32_t)(n) << 28U)
+
+#define ADC_CHSELR_SQ1_END (15U << 0U)
+#define ADC_CHSELR_SQ2_END (15U << 4U)
+#define ADC_CHSELR_SQ3_END (15U << 8U)
+#define ADC_CHSELR_SQ4_END (15U << 12U)
+#define ADC_CHSELR_SQ5_END (15U << 16U)
+#define ADC_CHSELR_SQ6_END (15U << 20U)
+#define ADC_CHSELR_SQ7_END (15U << 24U)
+#define ADC_CHSELR_SQ8_END (15U << 28U)
+/** @} */
+
+/**
+ * @name Threshold registers initializers
+ * @{
+ */
+#define ADC_TR(low, high) (((uint32_t)(high) << 16U) | \
+ (uint32_t)(low))
+#define ADC_TR_DISABLED ADC_TR(0U, 0x0FFFU)
+#define ADC_AWDCR_ENABLE(n) (1U << (n))
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief ADC1 driver enable switch.
+ * @details If set to @p TRUE the support for ADC1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ADC_USE_ADC1) || defined(__DOXYGEN__)
+#define STM32_ADC_USE_ADC1 FALSE
+#endif
+
+/**
+ * @brief ADC1 clock source selection.
+ */
+#if !defined(STM32_ADC_ADC1_CKMODE) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC1_CKMODE STM32_ADC_CKMODE_ADCCLK
+#endif
+
+/**
+ * @brief ADC1 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_ADC_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC1_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC1_IRQ_PRIORITY 2
+#endif
+
+/**
+ * @brief ADC1 DMA interrupt priority level setting.
+ */
+#if !defined(STM32_ADC_ADC1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 2
+#endif
+
+/*
+ * @brief ADC prescaler setting.
+ * @note This setting has effect only in asynchronous clock mode (the
+ * default, @p STM32_ADC_CKMODE_ADCCLK).
+ */
+#if !defined(STM32_ADC_PRESCALER_VALUE) || defined(__DOXYGEN__)
+#define STM32_ADC_PRESCALER_VALUE 2
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Supported devices checks.*/
+#if !defined(STM32G0XX)
+#error "ADCv5 only supports G0 STM32 devices"
+#endif
+
+/* Registry checks.*/
+#if !defined(STM32_HAS_ADC1)
+#error "STM32_HAS_ADC1 not defined in registry"
+#endif
+
+#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_HANDLER))
+#error "STM32_ADC1_HANDLER not defined in registry"
+#endif
+
+#if (STM32_ADC_USE_ADC1 && !defined(STM32_ADC1_NUMBER))
+#error "STM32_ADC1_NUMBER not defined in registry"
+#endif
+
+#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1
+#error "ADC1 not present in the selected device"
+#endif
+
+/* Units checks.*/
+#if STM32_ADC_USE_ADC1 && !STM32_HAS_ADC1
+#error "ADC1 not present in the selected device"
+#endif
+
+/* At least one ADC must be assigned.*/
+#if !STM32_ADC_USE_ADC1
+#error "ADC driver activated but no ADC peripheral assigned"
+#endif
+
+/* ADC IRQ priority tests.*/
+#if STM32_ADC_USE_ADC1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to ADC1"
+#endif
+
+/* DMA IRQ priority tests.*/
+#if STM32_ADC_USE_ADC1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to ADC1 DMA"
+#endif
+
+/* DMA priority tests.*/
+#if STM32_ADC_USE_ADC1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_ADC_ADC1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to ADC1"
+#endif
+
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if STM32_ADC_USE_ADC1 && !defined(STM32_ADC_ADC1_DMA_STREAM)
+#error "ADC DMA stream not defined"
+#endif
+
+
+/* ADC clock source checks.*/
+#if STM32_ADC_PRESCALER_VALUE == 2
+#define STM32_ADC_PRESC 1U
+#elif STM32_ADC_PRESCALER_VALUE == 4
+#define STM32_ADC_PRESC 2U
+#elif STM32_ADC_PRESCALER_VALUE == 6
+#define STM32_ADC_PRESC 3U
+#elif STM32_ADC_PRESCALER_VALUE == 8
+#define STM32_ADC_PRESC 4U
+#elif STM32_ADC_PRESCALER_VALUE == 10
+#define STM32_ADC_PRESC 5U
+#elif STM32_ADC_PRESCALER_VALUE == 12
+#define STM32_ADC_PRESC 6U
+#elif STM32_ADC_PRESCALER_VALUE == 16
+#define STM32_ADC_PRESC 7U
+#elif STM32_ADC_PRESCALER_VALUE == 32
+#define STM32_ADC_PRESC 8U
+#elif STM32_ADC_PRESCALER_VALUE == 64
+#define STM32_ADC_PRESC 9U
+#elif STM32_ADC_PRESCALER_VALUE == 128
+#define STM32_ADC_PRESC 10U
+#elif STM32_ADC_PRESCALER_VALUE == 256
+#define STM32_ADC_PRESC 11U
+#else
+#error "Invalid value assigned to STM32_ADC_PRESCALER_VALUE"
+#endif
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC sample data type.
+ */
+typedef uint16_t adcsample_t;
+
+/**
+ * @brief Channels number in a conversion group.
+ */
+typedef uint16_t adc_channels_num_t;
+
+/**
+ * @brief Possible ADC failure causes.
+ * @note Error codes are architecture dependent and should not relied
+ * upon.
+ */
+typedef enum {
+ ADC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */
+ ADC_ERR_OVERFLOW = 1, /**< ADC overflow condition. */
+ ADC_ERR_AWD1 = 2, /**< Analog watchdog 1. */
+ ADC_ERR_AWD2 = 3, /**< Analog watchdog 2. */
+ ADC_ERR_AWD3 = 4 /**< Analog watchdog 3. */
+} adcerror_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the ADC driver structure.
+ */
+#define adc_lld_driver_fields \
+ /* Pointer to the ADCx registers block.*/ \
+ ADC_TypeDef *adc; \
+ /* Pointer to associated DMA channel.*/ \
+ const stm32_dma_stream_t *dmastp; \
+ /* DMA mode bit mask.*/ \
+ uint32_t dmamode
+
+/**
+ * @brief Low level fields of the ADC configuration structure.
+ */
+#define adc_lld_config_fields \
+ /* Dummy configuration, it is not needed.*/ \
+ uint32_t dummy
+
+/**
+ * @brief Low level fields of the ADC configuration structure.
+ */
+#define adc_lld_configuration_group_fields \
+ /* ADC CFGR1 register initialization data. \
+ NOTE: The bits DMAEN and DMACFG are enforced internally \
+ to the driver, keep them to zero. \
+ NOTE: The bits @p ADC_CFGR1_CONT or @p ADC_CFGR1_DISCEN must be \
+ specified in continuous more or if the buffer depth is \
+ greater than one.*/ \
+ uint32_t cfgr1; \
+ /* ADC CFGR2 register initialization data. \
+ NOTE: CKMODE bits must not be specified in this field and left to \
+ zero.*/ \
+ uint32_t cfgr2; \
+ /* ADC TR1 register initialization data.*/ \
+ uint32_t tr1; \
+ /* ADC TR2 register initialization data.*/ \
+ uint32_t tr2; \
+ /* ADC TR3 register initialization data.*/ \
+ uint32_t tr3; \
+ /* ADC AWD2CR register initialization data.*/ \
+ uint32_t awd2cr; \
+ /* ADC AWD3CR register initialization data.*/ \
+ uint32_t awd3cr; \
+ /* ADC SMPR register initialization data.*/ \
+ uint32_t smpr; \
+ /* ADC CHSELR register initialization data. \
+ NOTE: The number of bits at logic level one in this register must \
+ be equal to the number in the @p num_channels field.*/ \
+ uint32_t chselr
+
+/**
+ * @brief Changes the value of the ADC CCR register.
+ * @details Use this function in order to enable or disable the internal
+ * analog sources. See the documentation in the STM32 Reference
+ * Manual.
+ * @note PRESC bits must not be specified and left to zero.
+ */
+#define adcSTM32SetCCR(ccr) (ADC->CCR = (ccr))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_ADC_USE_ADC1 && !defined(__DOXYGEN__)
+extern ADCDriver ADCD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void adc_lld_init(void);
+ void adc_lld_start(ADCDriver *adcp);
+ void adc_lld_stop(ADCDriver *adcp);
+ void adc_lld_start_conversion(ADCDriver *adcp);
+ void adc_lld_stop_conversion(ADCDriver *adcp);
+ void adc_lld_serve_interrupt(ADCDriver *adcp);
+ void adcSTM32EnableVREF(ADCDriver *adcp);
+ void adcSTM32DisableVREF(ADCDriver *adcp);
+ void adcSTM32EnableTS(ADCDriver *adcp);
+ void adcSTM32DisableTS(ADCDriver *adcp);
+#if defined(ADC_CCR_VBATEN)
+ void adcSTM32EnableVBAT(ADCDriver *adcp);
+ void adcSTM32DisableVBAT(ADCDriver *adcp);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_ADC */
+
+#endif /* HAL_ADC_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv5/notes.txt b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv5/notes.txt
new file mode 100644
index 0000000..283e5c3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/ADCv5/notes.txt
@@ -0,0 +1,16 @@
+STM32 ADCv1 driver.
+
+Driver capability:
+
+- Supports the STM32 "simple" ADC, the one found on small devices (G0).
+
+The file registry must export:
+
+STM32_HAS_ADC1 - ADC1 presence flag.
+STM32_ADC_SUPPORTS_PRESCALER - Support of CCR PRESC field.
+STM32_ADC_SUPPORTS_OVERSAMPLING - Support of oversampling-related fields.
+STM32_ADC1_IRQ_SHARED_WITH_EXTI - TRUE if the IRQ is shared with EXTI.
+STM32_ADC1_HANDLER - IRQ vector name.
+STM32_ADC1_NUMBER - IRQ vector number.
+STM32_ADC1_DMA_MSK - Mask of the compatible DMA channels.
+STM32_ADC1_DMA_CHN - Mask of the channels mapping.
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/BDMAv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/BDMAv1/driver.mk
new file mode 100644
index 0000000..1146b41
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/BDMAv1/driver.mk
@@ -0,0 +1,2 @@
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/BDMAv1/stm32_bdma.c
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/BDMAv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/BDMAv1/notes.txt b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/BDMAv1/notes.txt
new file mode 100644
index 0000000..e7fe3ad
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/BDMAv1/notes.txt
@@ -0,0 +1,11 @@
+STM32 BDMAv1 driver.
+
+Driver capability:
+
+- The driver supports the "basic" DMA controller.
+
+The file registry must export:
+
+STM32_BDMAn_CHx_HANDLER - Vector name for IRQ "x" (1..7). If the macro
+ is not exported then the ISR is not declared.
+STM32_BDMAn_CHx_NUMBER - Vector number for IRQ "x" (1..7).
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/BDMAv1/stm32_bdma.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/BDMAv1/stm32_bdma.c
new file mode 100644
index 0000000..4ca2e41
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/BDMAv1/stm32_bdma.c
@@ -0,0 +1,455 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file BDMAv1/stm32_bdma.c
+ * @brief BDMA helper driver code.
+ *
+ * @addtogroup STM32_BDMA
+ * @details BDMA sharing helper driver. In the STM32 the BDMA streams are a
+ * shared resource, this driver allows to allocate and free BDMA
+ * streams at runtime in order to allow all the other device
+ * drivers to coordinate the access to the resource.
+ * @note The BDMA ISR handlers are all declared into this module because
+ * sharing, the various device drivers can associate a callback to
+ * ISRs when allocating streams.
+ * @{
+ */
+
+#include "hal.h"
+
+/* The following macro is only defined if some driver requiring BDMA services
+ has been enabled.*/
+#if defined(STM32_BDMA_REQUIRED) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/**
+ * @brief Mask of the BDMA streams in @p bdma_allocated_mask.
+ */
+#define STM32_BDMA_STREAMS_MASK 0x000000FFU
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief BDMA streams descriptors.
+ * @details This table keeps the association between an unique stream
+ * identifier and the involved physical registers.
+ * @note Don't use this array directly, use the appropriate wrapper macros
+ * instead: @p STM32_BDMA1_STREAM1, @p STM32_BDMA1_STREAM2 etc.
+ */
+const stm32_bdma_stream_t _stm32_bdma_streams[STM32_BDMA_STREAMS] = {
+ {BDMA, BDMA_Channel0, 0, DMAMUX2_Channel0, 0, STM32_BDMA1_CH0_NUMBER},
+ {BDMA, BDMA_Channel1, 4, DMAMUX2_Channel1, 1, STM32_BDMA1_CH1_NUMBER},
+ {BDMA, BDMA_Channel2, 8, DMAMUX2_Channel2, 2, STM32_BDMA1_CH2_NUMBER},
+ {BDMA, BDMA_Channel3, 12, DMAMUX2_Channel3, 3, STM32_BDMA1_CH3_NUMBER},
+ {BDMA, BDMA_Channel4, 16, DMAMUX2_Channel4, 4, STM32_BDMA1_CH4_NUMBER},
+ {BDMA, BDMA_Channel5, 20, DMAMUX2_Channel5, 5, STM32_BDMA1_CH5_NUMBER},
+ {BDMA, BDMA_Channel6, 24, DMAMUX2_Channel6, 6, STM32_BDMA1_CH6_NUMBER},
+ {BDMA, BDMA_Channel7, 28, DMAMUX2_Channel7, 7, STM32_BDMA1_CH7_NUMBER}
+};
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief BDMA ISR redirector type.
+ */
+typedef struct {
+ stm32_bdmaisr_t func; /**< @brief BDMA callback function. */
+ void *param; /**< @brief BDMA callback parameter.*/
+} bdma_isr_redir_t;
+
+/**
+ * @brief BDMA driver base structure.
+ */
+static struct {
+ /**
+ * @brief Mask of the allocated streams.
+ */
+ uint32_t allocated_mask;
+ /**
+ * @brief DMA IRQ redirectors.
+ */
+ struct {
+ /**
+ * @brief DMA callback function.
+ */
+ stm32_bdmaisr_t func;
+ /**
+ * @brief DMA callback parameter.
+ */
+ void *param;
+ } streams[STM32_BDMA_STREAMS];
+} bdma;
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/**
+ * @brief BDMA1 stream 0 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_BDMA1_CH0_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (BDMA->ISR >> 0U) & STM32_BDMA_ISR_MASK;
+ BDMA->IFCR = flags << 0U;
+ if (bdma.streams[0].func)
+ bdma.streams[0].func(bdma.streams[0].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief BDMA1 stream 1 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_BDMA1_CH1_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (BDMA->ISR >> 4U) & STM32_BDMA_ISR_MASK;
+ BDMA->IFCR = flags << 4U;
+ if (bdma.streams[1].func)
+ bdma.streams[1].func(bdma.streams[1].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief BDMA1 stream 2 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_BDMA1_CH2_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (BDMA->ISR >> 8U) & STM32_BDMA_ISR_MASK;
+ BDMA->IFCR = flags << 8U;
+ if (bdma.streams[2].func)
+ bdma.streams[2].func(bdma.streams[2].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief BDMA1 stream 3 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_BDMA1_CH3_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (BDMA->ISR >> 12U) & STM32_BDMA_ISR_MASK;
+ BDMA->IFCR = flags << 12U;
+ if (bdma.streams[3].func)
+ bdma.streams[3].func(bdma.streams[3].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief BDMA1 stream 4 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_BDMA1_CH4_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (BDMA->ISR >> 16U) & STM32_BDMA_ISR_MASK;
+ BDMA->IFCR = flags << 16U;
+ if (bdma.streams[4].func)
+ bdma.streams[4].func(bdma.streams[4].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief BDMA1 stream 5 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_BDMA1_CH5_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (BDMA->ISR >> 20U) & STM32_BDMA_ISR_MASK;
+ BDMA->IFCR = flags << 20U;
+ if (bdma.streams[5].func)
+ bdma.streams[5].func(bdma.streams[5].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief BDMA1 stream 6 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_BDMA1_CH6_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (BDMA->ISR >> 24U) & STM32_BDMA_ISR_MASK;
+ BDMA->IFCR = flags << 24U;
+ if (bdma.streams[6].func)
+ bdma.streams[6].func(bdma.streams[6].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief BDMA1 stream 7 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_BDMA1_CH7_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (BDMA->ISR >> 28U) & STM32_BDMA_ISR_MASK;
+ BDMA->IFCR = flags << 28U;
+ if (bdma.streams[7].func)
+ bdma.streams[7].func(bdma.streams[7].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 BDMA helper initialization.
+ *
+ * @init
+ */
+void bdmaInit(void) {
+ unsigned i;
+
+ bdma.allocated_mask = 0U;
+ for (i = 0; i < STM32_BDMA_STREAMS; i++) {
+ _stm32_bdma_streams[i].channel->CCR = 0U;
+ bdma.streams[i].func = NULL;
+ bdma.streams[i].param = NULL;
+ }
+ BDMA->IFCR = 0xFFFFFFFFU;
+}
+
+/**
+ * @brief Allocates a BDMA stream.
+ * @details The stream is allocated and, if required, the BDMA clock enabled.
+ * The function also enables the IRQ vector associated to the stream
+ * and initializes its priority.
+ *
+ * @param[in] id numeric identifiers of a specific stream or:
+ * - @p STM32_BDMA_STREAM_ID_ANY for any stream.
+ * .
+ * @param[in] priority IRQ priority for the BDMA stream
+ * @param[in] func handling function pointer, can be @p NULL
+ * @param[in] param a parameter to be passed to the handling function
+ * @return Pointer to the allocated @p stm32_bdma_stream_t
+ * structure.
+ * @retval NULL if a/the stream is not available.
+ *
+ * @iclass
+ */
+const stm32_bdma_stream_t *bdmaStreamAllocI(uint32_t id,
+ uint32_t priority,
+ stm32_bdmaisr_t func,
+ void *param) {
+ uint32_t i, startid, endid;
+
+ osalDbgCheckClassI();
+
+ if (id < STM32_BDMA_STREAMS) {
+ startid = id;
+ endid = id;
+ }
+ else if (id == STM32_BDMA_STREAM_ID_ANY) {
+ startid = 0U;
+ endid = STM32_BDMA_STREAMS - 1U;
+ }
+ else {
+ osalDbgCheck(false);
+ return NULL;
+ }
+
+ for (i = startid; i <= endid; i++) {
+ uint32_t mask = (1U << i);
+ if ((bdma.allocated_mask & mask) == 0U) {
+ const stm32_bdma_stream_t *stp = STM32_BDMA_STREAM(i);
+
+ /* Installs the DMA handler.*/
+ bdma.streams[i].func = func;
+ bdma.streams[i].param = param;
+ bdma.allocated_mask |= mask;
+
+ /* Enabling DMA clocks required by the current streams set.*/
+ if ((STM32_BDMA_STREAMS_MASK & mask) != 0U) {
+ rccEnableBDMA1(true);
+ }
+
+#if defined(rccEnableDMAMUX)
+ /* Enabling DMAMUX if present.*/
+ if (bdma.allocated_mask != 0U) {
+ rccEnableDMAMUX(true);
+ }
+#endif
+
+ /* Enables the associated IRQ vector if not already enabled and if a
+ callback is defined.*/
+ if (func != NULL) {
+ nvicEnableVector(stp->vector, priority);
+ }
+
+ /* Putting the stream in a known state.*/
+ bdmaStreamDisable(stp);
+ stp->channel->CCR = STM32_BDMA_CR_RESET_VALUE;
+
+ return stp;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * @brief Allocates a BDMA stream.
+ * @details The stream is allocated and, if required, the BDMA clock enabled.
+ * The function also enables the IRQ vector associated to the stream
+ * and initializes its priority.
+ *
+ * @param[in] id numeric identifiers of a specific stream or:
+ * - @p STM32_BDMA_STREAM_ID_ANY for any stream.
+ * .
+ * @param[in] priority IRQ priority for the BDMA stream
+ * @param[in] func handling function pointer, can be @p NULL
+ * @param[in] param a parameter to be passed to the handling function
+ * @return Pointer to the allocated @p stm32_bdma_stream_t
+ * structure.
+ * @retval NULL if a/the stream is not available.
+ *
+ * @api
+ */
+const stm32_bdma_stream_t *bdmaStreamAlloc(uint32_t id,
+ uint32_t priority,
+ stm32_bdmaisr_t func,
+ void *param) {
+ const stm32_bdma_stream_t *stp;
+
+ osalSysLock();
+ stp = bdmaStreamAllocI(id, priority, func, param);
+ osalSysUnlock();
+
+ return stp;
+}
+
+/**
+ * @brief Releases a BDMA stream.
+ * @details The stream is freed and, if required, the BDMA clock disabled.
+ * Trying to release a unallocated stream is an illegal operation
+ * and is trapped if assertions are enabled.
+ *
+ * @param[in] stp pointer to an @p stm32_bdma_stream_t structure
+ *
+ * @iclass
+ */
+void bdmaStreamFreeI(const stm32_bdma_stream_t *stp) {
+
+ osalDbgCheck(stp != NULL);
+
+ /* Check if the streams is not taken.*/
+ osalDbgAssert((bdma.allocated_mask & (1U << stp->selfindex)) != 0U,
+ "not allocated");
+
+ /* Disables the associated IRQ vector.*/
+ nvicDisableVector(stp->vector);
+
+ /* Marks the stream as not allocated.*/
+ bdma.allocated_mask &= ~(1U << stp->selfindex);
+
+ /* Clearing associated handler and parameter.*/
+ bdma.streams->func = NULL;
+ bdma.streams->param = NULL;
+
+ /* Shutting down clocks that are no more required, if any.*/
+ if ((bdma.allocated_mask & STM32_BDMA_STREAMS_MASK) == 0U) {
+ rccDisableBDMA1();
+ }
+}
+
+/**
+ * @brief Releases a BDMA stream.
+ * @details The stream is freed and, if required, the BDMA clock disabled.
+ * Trying to release a unallocated stream is an illegal operation
+ * and is trapped if assertions are enabled.
+ *
+ * @param[in] stp pointer to an @p stm32_bdma_stream_t structure
+ *
+ * @api
+ */
+void bdmaStreamFree(const stm32_bdma_stream_t *stp) {
+
+ osalSysLock();
+ bdmaStreamFreeI(stp);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Associates a peripheral request to a BDMA stream.
+ * @note This function can be invoked in both ISR or thread context.
+ *
+ * @param[in] stp pointer to a @p stm32_bdma_stream_t structure
+ * @param[in] per peripheral identifier
+ *
+ * @special
+ */
+void bdmaSetRequestSource(const stm32_bdma_stream_t *stp, uint32_t per) {
+
+ osalDbgCheck(per < 256U);
+
+ stp->mux->CCR = per;
+}
+
+#endif /* STM32_BDMA_REQUIRED */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/BDMAv1/stm32_bdma.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/BDMAv1/stm32_bdma.h
new file mode 100644
index 0000000..6ed63f1
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/BDMAv1/stm32_bdma.h
@@ -0,0 +1,441 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file BDMAv1/stm32_bdma.h
+ * @brief BDMA helper driver header.
+ * @note This driver uses the new naming convention used for the STM32F2xx
+ * so the "BDMA channels" are referred as "BDMA streams".
+ *
+ * @addtogroup STM32_BDMA
+ * @{
+ */
+
+#ifndef STM32_BDMA_H
+#define STM32_BDMA_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Total number of BDMA streams.
+ * @details This is the total number of streams among all the BDMA units.
+ */
+#define STM32_BDMA_STREAMS 8U
+
+/**
+ * @brief Mask of the ISR bits passed to the BDMA callback functions.
+ */
+#define STM32_BDMA_ISR_MASK 0x0EU
+
+/**
+ * @brief Checks if a BDMA priority is within the valid range.
+ *
+ * @param[in] prio BDMA priority
+ * @retval The check result.
+ * @retval false invalid BDMA priority.
+ * @retval true correct BDMA priority.
+ */
+#define STM32_BDMA_IS_VALID_PRIORITY(prio) (((prio) >= 0U) && ((prio) <= 3U))
+
+/**
+ * @brief Checks if a BDMA stream id is within the valid range.
+ *
+ * @param[in] id BDMA stream id
+ * @retval The check result.
+ * @retval false invalid DMA stream.
+ * @retval true correct DMA stream.
+ */
+#define STM32_BDMA_IS_VALID_STREAM(id) (((id) >= 0U) && \
+ ((id) <= STM32_BDMA_STREAMS))
+
+/**
+ * @name Special stream identifiers
+ * @{
+ */
+#define STM32_BDMA_STREAM_ID_ANY STM32_BDMA_STREAMS
+/** @} */
+
+/**
+ * @name BDMA streams identifiers
+ * @{
+ */
+/**
+ * @brief Returns a pointer to a stm32_dma_stream_t structure.
+ *
+ * @param[in] id the stream numeric identifier
+ * @return A pointer to the stm32_bdma_stream_t constant structure
+ * associated to the BDMA stream.
+ */
+#define STM32_BDMA_STREAM(id) (&_stm32_bdma_streams[id])
+
+#define STM32_BDMA1_STREAM0 STM32_BDMA_STREAM(0)
+#define STM32_BDMA1_STREAM1 STM32_BDMA_STREAM(1)
+#define STM32_BDMA1_STREAM2 STM32_BDMA_STREAM(2)
+#define STM32_BDMA1_STREAM3 STM32_BDMA_STREAM(3)
+#define STM32_BDMA1_STREAM4 STM32_BDMA_STREAM(4)
+#define STM32_BDMA1_STREAM5 STM32_BDMA_STREAM(5)
+#define STM32_BDMA1_STREAM6 STM32_BDMA_STREAM(6)
+#define STM32_BDMA1_STREAM7 STM32_BDMA_STREAM(7)
+/** @} */
+
+/**
+ * @name CR register constants
+ * @{
+ */
+#define STM32_BDMA_CR_RESET_VALUE 0x00000000U
+#define STM32_BDMA_CR_EN BDMA_CCR_EN_Msk
+#define STM32_BDMA_CR_TCIE BDMA_CCR_TCIE
+#define STM32_BDMA_CR_HTIE BDMA_CCR_HTIE
+#define STM32_BDMA_CR_TEIE BDMA_CCR_TEIE
+#define STM32_BDMA_CR_DIR_MASK (BDMA_CCR_DIR | BDMA_CCR_MEM2MEM)
+#define STM32_BDMA_CR_DIR_P2M 0U
+#define STM32_BDMA_CR_DIR_M2P BDMA_CCR_DIR
+#define STM32_BDMA_CR_DIR_M2M BDMA_CCR_MEM2MEM
+#define STM32_BDMA_CR_CIRC BDMA_CCR_CIRC
+#define STM32_BDMA_CR_PINC BDMA_CCR_PINC
+#define STM32_BDMA_CR_MINC BDMA_CCR_MINC
+#define STM32_BDMA_CR_PSIZE_MASK BDMA_CCR_PSIZE_Msk
+#define STM32_BDMA_CR_PSIZE_BYTE 0U
+#define STM32_BDMA_CR_PSIZE_HWORD BDMA_CCR_PSIZE_0
+#define STM32_BDMA_CR_PSIZE_WORD BDMA_CCR_PSIZE_1
+#define STM32_BDMA_CR_MSIZE_MASK BDMA_CCR_MSIZE_Msk
+#define STM32_BDMA_CR_MSIZE_BYTE 0U
+#define STM32_BDMA_CR_MSIZE_HWORD BDMA_CCR_MSIZE_0
+#define STM32_BDMA_CR_MSIZE_WORD BDMA_CCR_MSIZE_1
+#define STM32_BDMA_CR_SIZE_MASK (STM32_BDMA_CR_PSIZE_MASK | \
+ STM32_BDMA_CR_MSIZE_MASK)
+#define STM32_BDMA_CR_PL_MASK BDMA_CCR_PL_Msk
+#define STM32_BDMA_CR_PL(n) ((n) << 12U)
+#if !defined(STM32_ENFORCE_H7_REV_XY)
+#define STM32_BDMA_CR_DBM BDMA_CCR_DBM
+#define STM32_BDMA_CR_CM BDMA_CCR_CT
+#endif
+/** @} */
+
+/**
+ * @name Status flags passed to the ISR callbacks
+ * @{
+ */
+#define STM32_BDMA_ISR_TEIF BDMA_ISR_TEIF0
+#define STM32_BDMA_ISR_HTIF BDMA_ISR_HTIF0
+#define STM32_BDMA_ISR_TCIF BDMA_ISR_TCIF0
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+#if !defined(STM32_HAS_BDMA1)
+#error "STM32_HAS_BDMA1 missing in registry"
+#endif
+
+#if !defined(STM32_BDMA1_CH0_HANDLER)
+#error "STM32_BDMA1_CH0_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_BDMA1_CH1_HANDLER)
+#error "STM32_BDMA1_CH1_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_BDMA1_CH2_HANDLER)
+#error "STM32_BDMA1_CH2_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_BDMA1_CH3_HANDLER)
+#error "STM32_BDMA1_CH3_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_BDMA1_CH4_HANDLER)
+#error "STM32_BDMA1_CH4_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_BDMA1_CH5_HANDLER)
+#error "STM32_BDMA1_CH5_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_BDMA1_CH6_HANDLER)
+#error "STM32_BDMA1_CH6_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_BDMA1_CH7_HANDLER)
+#error "STM32_BDMA1_CH7_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_BDMA1_CH0_NUMBER)
+#error "STM32_BDMA1_CH0_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_BDMA1_CH1_NUMBER)
+#error "STM32_BDMA1_CH1_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_BDMA1_CH2_NUMBER)
+#error "STM32_BDMA1_CH2_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_BDMA1_CH3_NUMBER)
+#error "STM32_BDMA1_CH3_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_BDMA1_CH4_NUMBER)
+#error "STM32_BDMA1_CH4_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_BDMA1_CH5_NUMBER)
+#error "STM32_BDMA1_CH5_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_BDMA1_CH6_NUMBER)
+#error "STM32_BDMA1_CH6_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_BDMA1_CH7_NUMBER)
+#error "STM32_BDMA1_CH7_NUMBER missing in registry"
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 BDMA ISR function type.
+ *
+ * @param[in] p parameter for the registered function
+ * @param[in] flags pre-shifted content of the ISR register, the bits
+ * are aligned to bit zero
+ */
+typedef void (*stm32_bdmaisr_t)(void *p, uint32_t flags);
+
+/**
+ * @brief STM32 BDMA stream descriptor structure.
+ */
+typedef struct {
+ BDMA_TypeDef *bdma; /**< @brief Associated BDMA. */
+ BDMA_Channel_TypeDef *channel; /**< @brief Associated BDMA channel.*/
+ uint8_t shift; /**< @brief Bit offset in ISR and
+ IFCR registers. */
+ DMAMUX_Channel_TypeDef *mux; /**< @brief Associated BDMA stream. */
+ uint8_t selfindex; /**< @brief Index to self in array. */
+ uint8_t vector; /**< @brief Associated IRQ vector. */
+} stm32_bdma_stream_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Associates a peripheral data register to a BDMA stream.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p bdmaStreamAllocate().
+ * @post After use the stream can be released using @p bdmaStreamRelease().
+ *
+ * @param[in] stp pointer to an @p stm32_bdma_stream_t structure
+ * @param[in] addr value to be written in the CPAR register
+ *
+ * @special
+ */
+#define bdmaStreamSetPeripheral(stp, addr) { \
+ (stp)->channel->CPAR = (uint32_t)(addr); \
+}
+
+/**
+ * @brief Associates a memory destination to a BDMA stream.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p bdmaStreamAllocate().
+ * @post After use the stream can be released using @p bdmaStreamRelease().
+ *
+ * @param[in] stp pointer to an @p stm32_bdma_stream_t structure
+ * @param[in] addr value to be written in the CMAR register
+ *
+ * @special
+ */
+#define bdmaStreamSetMemory(stp, addr) { \
+ (stp)->channel->CM0AR = (uint32_t)(addr); \
+}
+
+/**
+ * @brief Sets the number of transfers to be performed.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p bdmaStreamAllocate().
+ * @post After use the stream can be released using @p bdmaStreamRelease().
+ *
+ * @param[in] stp pointer to an @p stm32_bdma_stream_t structure
+ * @param[in] size value to be written in the CNDTR register
+ *
+ * @special
+ */
+#define bdmaStreamSetTransactionSize(stp, size) { \
+ (stp)->channel->CNDTR = (uint32_t)(size); \
+}
+
+/**
+ * @brief Returns the number of transfers to be performed.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p bdmaStreamAllocate().
+ * @post After use the stream can be released using @p bdmaStreamRelease().
+ *
+ * @param[in] stp pointer to an @p stm32_bdma_stream_t structure
+ * @return The number of transfers to be performed.
+ *
+ * @special
+ */
+#define bdmaStreamGetTransactionSize(stp) ((size_t)((stp)->channel->CNDTR))
+
+/**
+ * @brief Programs the stream mode settings.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p bdmaStreamAllocate().
+ * @post After use the stream can be released using @p bdmaStreamRelease().
+ *
+ * @param[in] stp pointer to an @p stm32_bdma_stream_t structure
+ * @param[in] mode value to be written in the CCR register
+ *
+ * @special
+ */
+#define bdmaStreamSetMode(stp, mode) { \
+ (stp)->channel->CCR = (uint32_t)(mode); \
+}
+
+/**
+ * @brief BDMA stream enable.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p bdmaStreamAllocate().
+ * @post After use the stream can be released using @p bdmaStreamRelease().
+ *
+ * @param[in] stp pointer to an @p stm32_bdma_stream_t structure
+ *
+ * @special
+ */
+#define bdmaStreamEnable(stp) { \
+ (stp)->channel->CCR |= STM32_BDMA_CR_EN; \
+}
+
+/**
+ * @brief BDMA stream disable.
+ * @details The function disables the specified stream and then clears any
+ * pending interrupt.
+ * @note This function can be invoked in both ISR or thread context.
+ * @note Interrupts enabling flags are set to zero after this call, see
+ * bug 3607518.
+ * @pre The stream must have been allocated using @p bdmaStreamAllocate().
+ * @post After use the stream can be released using @p bdmaStreamRelease().
+ *
+ * @param[in] stp pointer to an @p stm32_bdma_stream_t structure
+ *
+ * @special
+ */
+#define bdmaStreamDisable(stp) { \
+ (stp)->channel->CCR &= ~(STM32_BDMA_CR_TCIE | STM32_BDMA_CR_HTIE | \
+ STM32_BDMA_CR_TEIE | STM32_BDMA_CR_EN); \
+ bdmaStreamClearInterrupt(stp); \
+}
+
+/**
+ * @brief BDMA stream interrupt sources clear.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p bdmaStreamAllocate().
+ * @post After use the stream can be released using @p bdmaStreamRelease().
+ *
+ * @param[in] stp pointer to an @p stm32_bdma_stream_t structure
+ *
+ * @special
+ */
+#define bdmaStreamClearInterrupt(stp) { \
+ (stp)->bdma->IFCR = STM32_BDMA_ISR_MASK << (stp)->shift; \
+}
+
+/**
+ * @brief Starts a memory to memory operation using the specified stream.
+ * @note The default transfer data mode is "byte to byte" but it can be
+ * changed by specifying extra options in the @p mode parameter.
+ * @pre The stream must have been allocated using @p bdmaStreamAllocate().
+ * @post After use the stream can be released using @p bdmaStreamRelease().
+ *
+ * @param[in] stp pointer to an @p stm32_bdma_stream_t structure
+ * @param[in] mode value to be written in the CCR register, this value
+ * is implicitly ORed with:
+ * - @p STM32_BDMA_CR_MINC
+ * - @p STM32_BDMA_CR_PINC
+ * - @p STM32_BDMA_CR_DIR_M2M
+ * - @p STM32_BDMA_CR_EN
+ * .
+ * @param[in] src source address
+ * @param[in] dst destination address
+ * @param[in] n number of data units to copy
+ */
+#define bdmaStartMemCopy(stp, mode, src, dst, n) { \
+ bdmaStreamSetPeripheral(stp, src); \
+ bdmaStreamSetMemory0(stp, dst); \
+ bdmaStreamSetTransactionSize(stp, n); \
+ bdmaStreamSetMode(stp, (mode) | \
+ STM32_BDMA_CR_MINC | STM32_BDMA_CR_PINC | \
+ STM32_BDMA_CR_DIR_M2M | STM32_BDMA_CR_EN); \
+}
+
+/**
+ * @brief Polled wait for BDMA transfer end.
+ * @pre The stream must have been allocated using @p bdmaStreamAllocate().
+ * @post After use the stream can be released using @p bdmaStreamRelease().
+ *
+ * @param[in] stp pointer to an @p stm32_bdma_stream_t structure
+ */
+#define bdmaWaitCompletion(stp) { \
+ while ((stp)->channel->CNDTR > 0U) \
+ ; \
+ bdmaStreamDisable(stp); \
+}
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern const stm32_bdma_stream_t _stm32_bdma_streams[STM32_BDMA_STREAMS];
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void bdmaInit(void);
+ const stm32_bdma_stream_t *bdmaStreamAllocI(uint32_t id,
+ uint32_t priority,
+ stm32_bdmaisr_t func,
+ void *param);
+ const stm32_bdma_stream_t *bdmaStreamAlloc(uint32_t id,
+ uint32_t priority,
+ stm32_bdmaisr_t func,
+ void *param);
+ void bdmaStreamFreeI(const stm32_bdma_stream_t *stp);
+ void bdmaStreamFree(const stm32_bdma_stream_t *stp);
+ void bdmaSetRequestSource(const stm32_bdma_stream_t *stp, uint32_t per);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32_BDMA_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/CANv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/CANv1/driver.mk
new file mode 100644
index 0000000..608a927
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/CANv1/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_CAN TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.c
new file mode 100644
index 0000000..4d4e76a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.c
@@ -0,0 +1,1032 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file CANv1/hal_can_lld.c
+ * @brief STM32 CAN subsystem low level driver source.
+ *
+ * @addtogroup CAN
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_CAN || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*
+ * Addressing differences in the headers, they seem unable to agree on names.
+ */
+#if STM32_CAN_USE_CAN1
+#if !defined(CAN1)
+#define CAN1 CAN
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief CAN1 driver identifier.*/
+#if STM32_CAN_USE_CAN1 || defined(__DOXYGEN__)
+CANDriver CAND1;
+#endif
+
+/** @brief CAN2 driver identifier.*/
+#if STM32_CAN_USE_CAN2 || defined(__DOXYGEN__)
+CANDriver CAND2;
+#endif
+
+/** @brief CAN3 driver identifier.*/
+#if STM32_CAN_USE_CAN3 || defined(__DOXYGEN__)
+CANDriver CAND3;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+/**
+ * @brief Programs the filters of CAN 1 and CAN 2.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] can2sb number of the first filter assigned to CAN2
+ * @param[in] num number of entries in the filters array, if zero then
+ * a default filter is programmed
+ * @param[in] cfp pointer to the filters array, can be @p NULL if
+ * (num == 0)
+ *
+ * @notapi
+ */
+static void can_lld_set_filters(CANDriver* canp,
+ uint32_t can2sb,
+ uint32_t num,
+ const CANFilter *cfp) {
+
+#if STM32_CAN_USE_CAN2
+ if (canp == &CAND2) {
+ /* Set handle to CAN1, because CAN1 manages the filters of CAN2.*/
+ canp = &CAND1;
+ }
+#endif
+
+ /* Temporarily enabling CAN clock.*/
+#if STM32_CAN_USE_CAN1
+ if (canp == &CAND1) {
+ rccEnableCAN1(true);
+ /* Filters initialization.*/
+ canp->can->FMR = (canp->can->FMR & 0xFFFF0000) | CAN_FMR_FINIT;
+ canp->can->FMR = (canp->can->FMR & 0xFFFF0000) | (can2sb << 8) | CAN_FMR_FINIT;
+ }
+#endif
+
+#if STM32_CAN_USE_CAN3
+ if (canp == &CAND3) {
+ rccEnableCAN3(true);
+ /* Filters initialization.*/
+ canp->can->FMR = (canp->can->FMR & 0xFFFF0000) | CAN_FMR_FINIT;
+ }
+#endif
+
+ if (num > 0) {
+ uint32_t i, fmask;
+
+ /* All filters cleared.*/
+ canp->can->FA1R = 0;
+ canp->can->FM1R = 0;
+ canp->can->FS1R = 0;
+ canp->can->FFA1R = 0;
+
+#if STM32_CAN_USE_CAN1
+ if (canp == &CAND1) {
+ for (i = 0; i < STM32_CAN_MAX_FILTERS; i++) {
+ canp->can->sFilterRegister[i].FR1 = 0;
+ canp->can->sFilterRegister[i].FR2 = 0;
+ }
+ }
+#endif
+
+#if STM32_CAN_USE_CAN3
+ if (canp == &CAND3) {
+ for (i = 0; i < STM32_CAN3_MAX_FILTERS; i++) {
+ canp->can->sFilterRegister[i].FR1 = 0;
+ canp->can->sFilterRegister[i].FR2 = 0;
+ }
+ }
+#endif
+
+ /* Scanning the filters array.*/
+ for (i = 0; i < num; i++) {
+ fmask = 1 << cfp->filter;
+ if (cfp->mode)
+ canp->can->FM1R |= fmask;
+ if (cfp->scale)
+ canp->can->FS1R |= fmask;
+ if (cfp->assignment)
+ canp->can->FFA1R |= fmask;
+ canp->can->sFilterRegister[cfp->filter].FR1 = cfp->register1;
+ canp->can->sFilterRegister[cfp->filter].FR2 = cfp->register2;
+ canp->can->FA1R |= fmask;
+ cfp++;
+ }
+ }
+ else {
+ /* Setting up a single default filter that enables everything for both
+ CANs.*/
+ canp->can->sFilterRegister[0].FR1 = 0;
+ canp->can->sFilterRegister[0].FR2 = 0;
+#if STM32_CAN_USE_CAN2
+ if (canp == &CAND1) {
+ canp->can->sFilterRegister[can2sb].FR1 = 0;
+ canp->can->sFilterRegister[can2sb].FR2 = 0;
+ }
+#endif
+ canp->can->FM1R = 0;
+ canp->can->FFA1R = 0;
+ canp->can->FS1R = 1;
+ canp->can->FA1R = 1;
+#if STM32_CAN_USE_CAN2
+ if (canp == &CAND1) {
+ canp->can->FS1R |= 1 << can2sb;
+ canp->can->FA1R |= 1 << can2sb;
+ }
+#endif
+ }
+ canp->can->FMR &= ~CAN_FMR_FINIT;
+
+ /* Clock disabled, it will be enabled again in can_lld_start().*/
+ /* Temporarily enabling CAN clock.*/
+#if STM32_CAN_USE_CAN1
+ if (canp == &CAND1) {
+ rccDisableCAN1();
+ }
+#endif
+#if STM32_CAN_USE_CAN3
+ if (canp == &CAND3) {
+ rccDisableCAN3();
+ }
+#endif
+}
+
+/**
+ * @brief Common TX ISR handler.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+static void can_lld_tx_handler(CANDriver *canp) {
+ uint32_t tsr;
+ eventflags_t flags;
+
+ /* Clearing IRQ sources.*/
+ tsr = canp->can->TSR;
+ canp->can->TSR = tsr;
+
+ /* Flags to be signaled through the TX event source.*/
+ flags = 0U;
+
+ /* Checking mailbox 0.*/
+ if ((tsr & CAN_TSR_RQCP0) != 0U) {
+ if ((tsr & (CAN_TSR_ALST0 | CAN_TSR_TERR0)) != 0U) {
+ flags |= CAN_MAILBOX_TO_MASK(1U) << 16U;
+ }
+ else {
+ flags |= CAN_MAILBOX_TO_MASK(1U);
+ }
+ }
+
+ /* Checking mailbox 1.*/
+ if ((tsr & CAN_TSR_RQCP1) != 0U) {
+ if ((tsr & (CAN_TSR_ALST1 | CAN_TSR_TERR1)) != 0U) {
+ flags |= CAN_MAILBOX_TO_MASK(2U) << 16U;
+ }
+ else {
+ flags |= CAN_MAILBOX_TO_MASK(2U);
+ }
+ }
+
+ /* Checking mailbox 2.*/
+ if ((tsr & CAN_TSR_RQCP2) != 0U) {
+ if ((tsr & (CAN_TSR_ALST2 | CAN_TSR_TERR2)) != 0U) {
+ flags |= CAN_MAILBOX_TO_MASK(3U) << 16U;
+ }
+ else {
+ flags |= CAN_MAILBOX_TO_MASK(3U);
+ }
+ }
+
+ /* Signaling flags and waking up threads waiting for a transmission slot.*/
+ _can_tx_empty_isr(canp, flags);
+}
+
+/**
+ * @brief Common RX0 ISR handler.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+static void can_lld_rx0_handler(CANDriver *canp) {
+ uint32_t rf0r;
+
+ rf0r = canp->can->RF0R;
+ if ((rf0r & CAN_RF0R_FMP0) > 0) {
+ /* No more receive events until the queue 0 has been emptied.*/
+ canp->can->IER &= ~CAN_IER_FMPIE0;
+ _can_rx_full_isr(canp, CAN_MAILBOX_TO_MASK(1U));
+ }
+ if ((rf0r & CAN_RF0R_FOVR0) > 0) {
+ /* Overflow events handling.*/
+ canp->can->RF0R = CAN_RF0R_FOVR0;
+ _can_error_isr(canp, CAN_OVERFLOW_ERROR);
+ }
+}
+
+/**
+ * @brief Common RX1 ISR handler.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+static void can_lld_rx1_handler(CANDriver *canp) {
+ uint32_t rf1r;
+
+ rf1r = canp->can->RF1R;
+ if ((rf1r & CAN_RF1R_FMP1) > 0) {
+ /* No more receive events until the queue 0 has been emptied.*/
+ canp->can->IER &= ~CAN_IER_FMPIE1;
+ _can_rx_full_isr(canp, CAN_MAILBOX_TO_MASK(2U));
+ }
+ if ((rf1r & CAN_RF1R_FOVR1) > 0) {
+ /* Overflow events handling.*/
+ canp->can->RF1R = CAN_RF1R_FOVR1;
+ _can_error_isr(canp, CAN_OVERFLOW_ERROR);
+ }
+}
+
+/**
+ * @brief Common SCE ISR handler.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+static void can_lld_sce_handler(CANDriver *canp) {
+ uint32_t msr;
+
+ /* Clearing IRQ sources.*/
+ msr = canp->can->MSR;
+ canp->can->MSR = msr;
+
+ /* Wakeup event.*/
+#if CAN_USE_SLEEP_MODE
+ if (msr & CAN_MSR_WKUI) {
+ canp->state = CAN_READY;
+ canp->can->MCR &= ~CAN_MCR_SLEEP;
+ _can_wakeup_isr(canp);
+ }
+#endif /* CAN_USE_SLEEP_MODE */
+ /* Error event.*/
+ if (msr & CAN_MSR_ERRI) {
+ eventflags_t flags;
+ uint32_t esr = canp->can->ESR;
+
+#if STM32_CAN_REPORT_ALL_ERRORS
+ flags = (eventflags_t)(esr & 7);
+ if ((esr & CAN_ESR_LEC) > 0)
+ flags |= CAN_FRAMING_ERROR;
+#else
+ flags = 0;
+#endif
+
+ /* The content of the ESR register is copied unchanged in the upper
+ half word of the listener flags mask.*/
+ _can_error_isr(canp, flags | (eventflags_t)(esr << 16U));
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_CAN_USE_CAN1 || defined(__DOXYGEN__)
+#if defined(STM32_CAN1_UNIFIED_HANDLER)
+/**
+ * @brief CAN1 unified interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_CAN1_UNIFIED_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ can_lld_tx_handler(&CAND1);
+ can_lld_rx0_handler(&CAND1);
+ can_lld_rx1_handler(&CAND1);
+ can_lld_sce_handler(&CAND1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#else /* !defined(STM32_CAN1_UNIFIED_HANDLER) */
+
+#if !defined(STM32_CAN1_TX_HANDLER)
+#error "STM32_CAN1_TX_HANDLER not defined"
+#endif
+#if !defined(STM32_CAN1_RX0_HANDLER)
+#error "STM32_CAN1_RX0_HANDLER not defined"
+#endif
+#if !defined(STM32_CAN1_RX1_HANDLER)
+#error "STM32_CAN1_RX1_HANDLER not defined"
+#endif
+#if !defined(STM32_CAN1_SCE_HANDLER)
+#error "STM32_CAN1_SCE_HANDLER not defined"
+#endif
+
+/**
+ * @brief CAN1 TX interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_CAN1_TX_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ can_lld_tx_handler(&CAND1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief CAN1 RX0 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_CAN1_RX0_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ can_lld_rx0_handler(&CAND1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief CAN1 RX1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_CAN1_RX1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ can_lld_rx1_handler(&CAND1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief CAN1 SCE interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_CAN1_SCE_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ can_lld_sce_handler(&CAND1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_CAN1_UNIFIED_HANDLER) */
+#endif /* STM32_CAN_USE_CAN1 */
+
+#if STM32_CAN_USE_CAN2 || defined(__DOXYGEN__)
+#if defined(STM32_CAN2_UNIFIED_HANDLER)
+/**
+ * @brief CAN1 unified interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_CAN2_UNIFIED_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ can_lld_tx_handler(&CAND2);
+ can_lld_rx0_handler(&CAND2);
+ can_lld_rx1_handler(&CAND2);
+ can_lld_sce_handler(&CAND2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#else /* !defined(STM32_CAN2_UNIFIED_HANDLER) */
+
+#if !defined(STM32_CAN1_TX_HANDLER)
+#error "STM32_CAN1_TX_HANDLER not defined"
+#endif
+#if !defined(STM32_CAN1_RX0_HANDLER)
+#error "STM32_CAN1_RX0_HANDLER not defined"
+#endif
+#if !defined(STM32_CAN1_RX1_HANDLER)
+#error "STM32_CAN1_RX1_HANDLER not defined"
+#endif
+#if !defined(STM32_CAN1_SCE_HANDLER)
+#error "STM32_CAN1_SCE_HANDLER not defined"
+#endif
+
+/**
+ * @brief CAN2 TX interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_CAN2_TX_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ can_lld_tx_handler(&CAND2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief CAN2 RX0 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_CAN2_RX0_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ can_lld_rx0_handler(&CAND2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief CAN2 RX1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_CAN2_RX1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ can_lld_rx1_handler(&CAND2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief CAN2 SCE interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_CAN2_SCE_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ can_lld_sce_handler(&CAND2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_CAN2_UNIFIED_HANDLER) */
+#endif /* STM32_CAN_USE_CAN2 */
+
+#if STM32_CAN_USE_CAN3 || defined(__DOXYGEN__)
+#if defined(STM32_CAN3_UNIFIED_HANDLER)
+/**
+ * @brief CAN1 unified interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_CAN3_UNIFIED_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ can_lld_tx_handler(&CAND3);
+ can_lld_rx0_handler(&CAND3);
+ can_lld_rx1_handler(&CAND3);
+ can_lld_sce_handler(&CAND3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#else /* !defined(STM32_CAN3_UNIFIED_HANDLER) */
+
+#if !defined(STM32_CAN3_TX_HANDLER)
+#error "STM32_CAN3_TX_HANDLER not defined"
+#endif
+#if !defined(STM32_CAN3_RX0_HANDLER)
+#error "STM32_CAN3_RX0_HANDLER not defined"
+#endif
+#if !defined(STM32_CAN3_RX1_HANDLER)
+#error "STM32_CAN3_RX1_HANDLER not defined"
+#endif
+#if !defined(STM32_CAN3_SCE_HANDLER)
+#error "STM32_CAN3_SCE_HANDLER not defined"
+#endif
+
+/**
+ * @brief CAN3 TX interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_CAN3_TX_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ can_lld_tx_handler(&CAND3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief CAN3 RX0 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_CAN3_RX0_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ can_lld_rx0_handler(&CAND3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief CAN1 RX3 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_CAN3_RX1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ can_lld_rx1_handler(&CAND3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief CAN1 SCE interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_CAN3_SCE_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ can_lld_sce_handler(&CAND3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_CAN1_UNIFIED_HANDLER) */
+#endif /* STM32_CAN_USE_CAN1 */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level CAN driver initialization.
+ *
+ * @notapi
+ */
+void can_lld_init(void) {
+
+#if STM32_CAN_USE_CAN1
+ /* Driver initialization.*/
+ canObjectInit(&CAND1);
+ CAND1.can = CAN1;
+#if defined(STM32_CAN1_UNIFIED_NUMBER)
+ nvicEnableVector(STM32_CAN1_UNIFIED_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY);
+#else
+ nvicEnableVector(STM32_CAN1_TX_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY);
+ nvicEnableVector(STM32_CAN1_RX0_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY);
+ nvicEnableVector(STM32_CAN1_RX1_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY);
+ nvicEnableVector(STM32_CAN1_SCE_NUMBER, STM32_CAN_CAN1_IRQ_PRIORITY);
+#endif
+#endif
+
+#if STM32_CAN_USE_CAN2
+ /* Driver initialization.*/
+ canObjectInit(&CAND2);
+ CAND2.can = CAN2;
+#if defined(STM32_CAN2_UNIFIED_NUMBER)
+ nvicEnableVector(STM32_CAN2_UNIFIED_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY);
+#else
+ nvicEnableVector(STM32_CAN2_TX_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY);
+ nvicEnableVector(STM32_CAN2_RX0_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY);
+ nvicEnableVector(STM32_CAN2_RX1_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY);
+ nvicEnableVector(STM32_CAN2_SCE_NUMBER, STM32_CAN_CAN2_IRQ_PRIORITY);
+#endif
+#endif
+
+#if STM32_CAN_USE_CAN3
+ /* Driver initialization.*/
+ canObjectInit(&CAND3);
+ CAND3.can = CAN3;
+#if defined(STM32_CAN3_UNIFIED_NUMBER)
+ nvicEnableVector(STM32_CAN3_UNIFIED_NUMBER, STM32_CAN_CAN3_IRQ_PRIORITY);
+#else
+ nvicEnableVector(STM32_CAN3_TX_NUMBER, STM32_CAN_CAN3_IRQ_PRIORITY);
+ nvicEnableVector(STM32_CAN3_RX0_NUMBER, STM32_CAN_CAN3_IRQ_PRIORITY);
+ nvicEnableVector(STM32_CAN3_RX1_NUMBER, STM32_CAN_CAN3_IRQ_PRIORITY);
+ nvicEnableVector(STM32_CAN3_SCE_NUMBER, STM32_CAN_CAN3_IRQ_PRIORITY);
+#endif
+#endif
+
+ /* Filters initialization.*/
+#if STM32_CAN_USE_CAN1
+#if STM32_HAS_CAN2
+ can_lld_set_filters(&CAND1, STM32_CAN_MAX_FILTERS / 2, 0, NULL);
+#else
+ can_lld_set_filters(&CAND1, STM32_CAN_MAX_FILTERS, 0, NULL);
+#endif
+#endif
+
+#if STM32_HAS_CAN3
+#if STM32_CAN_USE_CAN3
+ can_lld_set_filters(&CAND3, STM32_CAN3_MAX_FILTERS, 0, NULL);
+#endif
+#endif
+}
+
+/**
+ * @brief Configures and activates the CAN peripheral.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+void can_lld_start(CANDriver *canp) {
+
+ /* Clock activation.*/
+#if STM32_CAN_USE_CAN1
+ if (&CAND1 == canp) {
+ rccEnableCAN1(true);
+ }
+#endif
+
+#if STM32_CAN_USE_CAN2
+ if (&CAND2 == canp) {
+ rccEnableCAN1(true); /* CAN 2 requires CAN1, so enabling it first.*/
+ rccEnableCAN2(true);
+ }
+#endif
+
+#if STM32_CAN_USE_CAN3
+ if (&CAND3 == canp) {
+ rccEnableCAN3(true);
+ }
+#endif
+
+ /* Configuring CAN. */
+ canp->can->MCR = CAN_MCR_INRQ;
+ while ((canp->can->MSR & CAN_MSR_INAK) == 0)
+ osalThreadSleepS(1);
+ canp->can->BTR = canp->config->btr;
+ canp->can->MCR = canp->config->mcr;
+
+ /* Interrupt sources initialization.*/
+#if STM32_CAN_REPORT_ALL_ERRORS
+ canp->can->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_FMPIE1 |
+ CAN_IER_WKUIE | CAN_IER_ERRIE | CAN_IER_LECIE |
+ CAN_IER_BOFIE | CAN_IER_EPVIE | CAN_IER_EWGIE |
+ CAN_IER_FOVIE0 | CAN_IER_FOVIE1;
+#else
+ canp->can->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_FMPIE1 |
+ CAN_IER_WKUIE | CAN_IER_ERRIE |
+ CAN_IER_BOFIE | CAN_IER_EPVIE | CAN_IER_EWGIE |
+ CAN_IER_FOVIE0 | CAN_IER_FOVIE1;
+#endif
+}
+
+/**
+ * @brief Deactivates the CAN peripheral.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+void can_lld_stop(CANDriver *canp) {
+
+ /* If in ready state then disables the CAN peripheral.*/
+ if (canp->state == CAN_READY) {
+#if STM32_CAN_USE_CAN1
+ if (&CAND1 == canp) {
+ CAN1->MCR = 0x00010002; /* Register reset value. */
+ CAN1->IER = 0x00000000; /* All sources disabled. */
+#if STM32_CAN_USE_CAN2
+ /* If CAND2 is stopped then CAN1 clock is stopped here.*/
+ if (CAND2.state == CAN_STOP)
+#endif
+ {
+ rccDisableCAN1();
+ }
+ }
+#endif
+
+#if STM32_CAN_USE_CAN2
+ if (&CAND2 == canp) {
+ CAN2->MCR = 0x00010002; /* Register reset value. */
+ CAN2->IER = 0x00000000; /* All sources disabled. */
+#if STM32_CAN_USE_CAN1
+ /* If CAND1 is stopped then CAN1 clock is stopped here.*/
+ if (CAND1.state == CAN_STOP)
+#endif
+ {
+ rccDisableCAN1();
+ }
+ rccDisableCAN2();
+ }
+#endif
+
+#if STM32_CAN_USE_CAN3
+ if (&CAND3 == canp) {
+ CAN3->MCR = 0x00010002; /* Register reset value. */
+ CAN3->IER = 0x00000000; /* All sources disabled. */
+ rccDisableCAN3();
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Determines whether a frame can be transmitted.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
+ *
+ * @return The queue space availability.
+ * @retval false no space in the transmit queue.
+ * @retval true transmit slot available.
+ *
+ * @notapi
+ */
+bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) {
+
+ switch (mailbox) {
+ case CAN_ANY_MAILBOX:
+ return (canp->can->TSR & CAN_TSR_TME) != 0;
+ case 1:
+ return (canp->can->TSR & CAN_TSR_TME0) != 0;
+ case 2:
+ return (canp->can->TSR & CAN_TSR_TME1) != 0;
+ case 3:
+ return (canp->can->TSR & CAN_TSR_TME2) != 0;
+ default:
+ return false;
+ }
+}
+
+/**
+ * @brief Inserts a frame into the transmit queue.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] ctfp pointer to the CAN frame to be transmitted
+ * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
+ *
+ * @notapi
+ */
+void can_lld_transmit(CANDriver *canp,
+ canmbx_t mailbox,
+ const CANTxFrame *ctfp) {
+ uint32_t tir;
+ CAN_TxMailBox_TypeDef *tmbp;
+
+ /* Pointer to a free transmission mailbox.*/
+ switch (mailbox) {
+ case CAN_ANY_MAILBOX:
+ tmbp = &canp->can->sTxMailBox[(canp->can->TSR & CAN_TSR_CODE) >> 24];
+ break;
+ case 1:
+ tmbp = &canp->can->sTxMailBox[0];
+ break;
+ case 2:
+ tmbp = &canp->can->sTxMailBox[1];
+ break;
+ case 3:
+ tmbp = &canp->can->sTxMailBox[2];
+ break;
+ default:
+ return;
+ }
+
+ /* Preparing the message.*/
+ if (ctfp->IDE)
+ tir = ((uint32_t)ctfp->EID << 3) | ((uint32_t)ctfp->RTR << 1) |
+ CAN_TI0R_IDE;
+ else
+ tir = ((uint32_t)ctfp->SID << 21) | ((uint32_t)ctfp->RTR << 1);
+ tmbp->TDTR = ctfp->DLC;
+ tmbp->TDLR = ctfp->data32[0];
+ tmbp->TDHR = ctfp->data32[1];
+ tmbp->TIR = tir | CAN_TI0R_TXRQ;
+}
+
+/**
+ * @brief Determines whether a frame has been received.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
+ *
+ * @return The queue space availability.
+ * @retval false no space in the transmit queue.
+ * @retval true transmit slot available.
+ *
+ * @notapi
+ */
+bool can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox) {
+
+ switch (mailbox) {
+ case CAN_ANY_MAILBOX:
+ return ((canp->can->RF0R & CAN_RF0R_FMP0) != 0 ||
+ (canp->can->RF1R & CAN_RF1R_FMP1) != 0);
+ case 1:
+ return (canp->can->RF0R & CAN_RF0R_FMP0) != 0;
+ case 2:
+ return (canp->can->RF1R & CAN_RF1R_FMP1) != 0;
+ default:
+ return false;
+ }
+}
+
+/**
+ * @brief Receives a frame from the input queue.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
+ * @param[out] crfp pointer to the buffer where the CAN frame is copied
+ *
+ * @notapi
+ */
+void can_lld_receive(CANDriver *canp,
+ canmbx_t mailbox,
+ CANRxFrame *crfp) {
+ uint32_t rir, rdtr;
+
+ if (mailbox == CAN_ANY_MAILBOX) {
+ if ((canp->can->RF0R & CAN_RF0R_FMP0) != 0)
+ mailbox = 1;
+ else if ((canp->can->RF1R & CAN_RF1R_FMP1) != 0)
+ mailbox = 2;
+ else {
+ /* Should not happen, do nothing.*/
+ return;
+ }
+ }
+ switch (mailbox) {
+ case 1:
+ /* Fetches the message.*/
+ rir = canp->can->sFIFOMailBox[0].RIR;
+ rdtr = canp->can->sFIFOMailBox[0].RDTR;
+ crfp->data32[0] = canp->can->sFIFOMailBox[0].RDLR;
+ crfp->data32[1] = canp->can->sFIFOMailBox[0].RDHR;
+
+ /* Releases the mailbox.*/
+ canp->can->RF0R = CAN_RF0R_RFOM0;
+
+ /* If the queue is empty re-enables the interrupt in order to generate
+ events again.*/
+ if ((canp->can->RF0R & CAN_RF0R_FMP0) == 0)
+ canp->can->IER |= CAN_IER_FMPIE0;
+ break;
+ case 2:
+ /* Fetches the message.*/
+ rir = canp->can->sFIFOMailBox[1].RIR;
+ rdtr = canp->can->sFIFOMailBox[1].RDTR;
+ crfp->data32[0] = canp->can->sFIFOMailBox[1].RDLR;
+ crfp->data32[1] = canp->can->sFIFOMailBox[1].RDHR;
+
+ /* Releases the mailbox.*/
+ canp->can->RF1R = CAN_RF1R_RFOM1;
+
+ /* If the queue is empty re-enables the interrupt in order to generate
+ events again.*/
+ if ((canp->can->RF1R & CAN_RF1R_FMP1) == 0)
+ canp->can->IER |= CAN_IER_FMPIE1;
+ break;
+ default:
+ /* Should not happen, do nothing.*/
+ return;
+ }
+
+ /* Decodes the various fields in the RX frame.*/
+ crfp->RTR = (rir & CAN_RI0R_RTR) >> 1;
+ crfp->IDE = (rir & CAN_RI0R_IDE) >> 2;
+ if (crfp->IDE)
+ crfp->EID = rir >> 3;
+ else
+ crfp->SID = rir >> 21;
+ crfp->DLC = rdtr & CAN_RDT0R_DLC;
+ crfp->FMI = (uint8_t)(rdtr >> 8);
+ crfp->TIME = (uint16_t)(rdtr >> 16);
+}
+
+/**
+ * @brief Tries to abort an ongoing transmission.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] mailbox mailbox number
+ *
+ * @notapi
+ */
+void can_lld_abort(CANDriver *canp,
+ canmbx_t mailbox) {
+
+ canp->can->TSR = 128U << ((mailbox - 1U) * 8U);
+}
+
+#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__)
+/**
+ * @brief Enters the sleep mode.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+void can_lld_sleep(CANDriver *canp) {
+
+ canp->can->MCR |= CAN_MCR_SLEEP;
+}
+
+/**
+ * @brief Enforces leaving the sleep mode.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+void can_lld_wakeup(CANDriver *canp) {
+
+ canp->can->MCR &= ~CAN_MCR_SLEEP;
+}
+#endif /* CAN_USE_SLEEP_MODE */
+
+/**
+ * @brief Programs the filters.
+ * @note This is an STM32-specific API.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] can2sb number of the first filter assigned to CAN2
+ * @param[in] num number of entries in the filters array, if zero then
+ * a default filter is programmed
+ * @param[in] cfp pointer to the filters array, can be @p NULL if
+ * (num == 0)
+ *
+ * @api
+ */
+void canSTM32SetFilters(CANDriver *canp, uint32_t can2sb,
+ uint32_t num, const CANFilter *cfp) {
+
+#if STM32_CAN_USE_CAN2
+ osalDbgCheck((can2sb <= STM32_CAN_MAX_FILTERS) &&
+ (num <= STM32_CAN_MAX_FILTERS));
+#endif
+
+#if STM32_CAN_USE_CAN1
+ osalDbgAssert(CAND1.state == CAN_STOP, "invalid state");
+#endif
+#if STM32_CAN_USE_CAN2
+ osalDbgAssert(CAND2.state == CAN_STOP, "invalid state");
+#endif
+#if STM32_CAN_USE_CAN3
+ osalDbgAssert(CAND3.state == CAN_STOP, "invalid state");
+#endif
+
+#if STM32_CAN_USE_CAN1
+ if (canp == &CAND1) {
+ can_lld_set_filters(canp, can2sb, num, cfp);
+ }
+#endif
+#if STM32_CAN_USE_CAN3
+ if (canp == &CAND3) {
+ can_lld_set_filters(canp, can2sb, num, cfp);
+ }
+#endif
+}
+
+#endif /* HAL_USE_CAN */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.h
new file mode 100644
index 0000000..e4eb6f6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/CANv1/hal_can_lld.h
@@ -0,0 +1,471 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file CANv1/hal_can_lld.h
+ * @brief STM32 CAN subsystem low level driver header.
+ *
+ * @addtogroup CAN
+ * @{
+ */
+
+#ifndef HAL_CAN_LLD_H
+#define HAL_CAN_LLD_H
+
+#if HAL_USE_CAN || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*
+ * The following macros from the ST header file are replaced with better
+ * equivalents.
+ */
+#undef CAN_BTR_BRP
+#undef CAN_BTR_TS1
+#undef CAN_BTR_TS2
+#undef CAN_BTR_SJW
+
+/**
+ * @brief This switch defines whether the driver implementation supports
+ * a low power switch mode with automatic an wakeup feature.
+ */
+#define CAN_SUPPORTS_SLEEP TRUE
+
+/**
+ * @brief This implementation supports three transmit mailboxes.
+ */
+#define CAN_TX_MAILBOXES 3
+
+/**
+ * @brief This implementation supports two receive mailboxes.
+ */
+#define CAN_RX_MAILBOXES 2
+
+/**
+ * @name CAN registers helper macros
+ * @{
+ */
+#define CAN_BTR_BRP(n) (n) /**< @brief BRP field macro.*/
+#define CAN_BTR_TS1(n) ((n) << 16) /**< @brief TS1 field macro.*/
+#define CAN_BTR_TS2(n) ((n) << 20) /**< @brief TS2 field macro.*/
+#define CAN_BTR_SJW(n) ((n) << 24) /**< @brief SJW field macro.*/
+
+#define CAN_IDE_STD 0 /**< @brief Standard id. */
+#define CAN_IDE_EXT 1 /**< @brief Extended id. */
+
+#define CAN_RTR_DATA 0 /**< @brief Data frame. */
+#define CAN_RTR_REMOTE 1 /**< @brief Remote frame. */
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief CAN pedantic errors report.
+ * @details Use of this option is IRQ-intensive.
+ */
+#if !defined(STM32_CAN_REPORT_ALL_ERRORS) || defined(__DOXYGEN__)
+#define STM32_CAN_REPORT_ALL_ERRORS FALSE
+#endif
+
+/**
+ * @brief CAN1 driver enable switch.
+ * @details If set to @p TRUE the support for CAN1 is included.
+ */
+#if !defined(STM32_CAN_USE_CAN1) || defined(__DOXYGEN__)
+#define STM32_CAN_USE_CAN1 FALSE
+#endif
+
+/**
+ * @brief CAN2 driver enable switch.
+ * @details If set to @p TRUE the support for CAN2 is included.
+ */
+#if !defined(STM32_CAN_USE_CAN2) || defined(__DOXYGEN__)
+#define STM32_CAN_USE_CAN2 FALSE
+#endif
+
+/**
+ * @brief CAN3 driver enable switch.
+ * @details If set to @p TRUE the support for CAN3 is included.
+ */
+#if !defined(STM32_CAN_USE_CAN3) || defined(__DOXYGEN__)
+#define STM32_CAN_USE_CAN3 FALSE
+#endif
+
+/**
+ * @brief CAN1 interrupt priority level setting.
+ */
+#if !defined(STM32_CAN_CAN1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_CAN_CAN1_IRQ_PRIORITY 11
+#endif
+/** @} */
+
+/**
+ * @brief CAN2 interrupt priority level setting.
+ */
+#if !defined(STM32_CAN_CAN2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_CAN_CAN2_IRQ_PRIORITY 11
+#endif
+/** @} */
+
+/**
+ * @brief CAN3 interrupt priority level setting.
+ */
+#if !defined(STM32_CAN_CAN3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_CAN_CAN3_IRQ_PRIORITY 11
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !defined(STM32_HAS_CAN1)
+#error "STM32_HAS_CAN1 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_CAN2)
+#error "STM32_HAS_CAN2 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_CAN3)
+#error "STM32_HAS_CAN3 not defined in registry"
+#endif
+
+#if (STM32_HAS_CAN1 | STM32_HAS_CAN2) && !defined(STM32_CAN_MAX_FILTERS)
+#error "STM32_CAN_MAX_FILTERS not defined in registry"
+#endif
+
+#if STM32_HAS_CAN3 && !defined(STM32_CAN3_MAX_FILTERS)
+#error "STM32_CAN3_MAX_FILTERS not defined in registry"
+#endif
+
+#if STM32_CAN_USE_CAN1 && !STM32_HAS_CAN1
+#error "CAN1 not present in the selected device"
+#endif
+
+#if STM32_CAN_USE_CAN2 && !STM32_HAS_CAN2
+#error "CAN2 not present in the selected device"
+#endif
+
+#if STM32_CAN_USE_CAN3 && !STM32_HAS_CAN3
+#error "CAN2 not present in the selected device"
+#endif
+
+#if !STM32_CAN_USE_CAN1 && !STM32_CAN_USE_CAN2 && !STM32_CAN_USE_CAN3
+#error "CAN driver activated but no CAN peripheral assigned"
+#endif
+
+#if !STM32_CAN_USE_CAN1 && STM32_CAN_USE_CAN2
+#error "CAN2 requires CAN1, it cannot operate independently"
+#endif
+
+#if CAN_USE_SLEEP_MODE && !CAN_SUPPORTS_SLEEP
+#error "CAN sleep mode not supported in this architecture"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a structure representing an CAN driver.
+ */
+typedef struct CANDriver CANDriver;
+
+/**
+ * @brief Type of a transmission mailbox index.
+ */
+typedef uint32_t canmbx_t;
+
+#if (CAN_ENFORCE_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a CAN notification callback.
+ *
+ * @param[in] canp pointer to the @p CANDriver object triggering the
+ * callback
+ * @param[in] flags flags associated to the mailbox callback
+ */
+typedef void (*can_callback_t)(CANDriver *canp, uint32_t flags);
+#endif
+
+/**
+ * @brief CAN transmission frame.
+ * @note Accessing the frame data as word16 or word32 is not portable because
+ * machine data endianness, it can be still useful for a quick filling.
+ */
+typedef struct {
+ struct {
+ uint8_t DLC:4; /**< @brief Data length. */
+ uint8_t RTR:1; /**< @brief Frame type. */
+ uint8_t IDE:1; /**< @brief Identifier type. */
+ };
+ union {
+ struct {
+ uint32_t SID:11; /**< @brief Standard identifier.*/
+ };
+ struct {
+ uint32_t EID:29; /**< @brief Extended identifier.*/
+ };
+ };
+ union {
+ uint8_t data8[8]; /**< @brief Frame data. */
+ uint16_t data16[4]; /**< @brief Frame data. */
+ uint32_t data32[2]; /**< @brief Frame data. */
+ uint64_t data64[1]; /**< @brief Frame data. */
+ };
+} CANTxFrame;
+
+/**
+ * @brief CAN received frame.
+ * @note Accessing the frame data as word16 or word32 is not portable because
+ * machine data endianness, it can be still useful for a quick filling.
+ */
+typedef struct {
+ struct {
+ uint8_t FMI; /**< @brief Filter id. */
+ uint16_t TIME; /**< @brief Time stamp. */
+ };
+ struct {
+ uint8_t DLC:4; /**< @brief Data length. */
+ uint8_t RTR:1; /**< @brief Frame type. */
+ uint8_t IDE:1; /**< @brief Identifier type. */
+ };
+ union {
+ struct {
+ uint32_t SID:11; /**< @brief Standard identifier.*/
+ };
+ struct {
+ uint32_t EID:29; /**< @brief Extended identifier.*/
+ };
+ };
+ union {
+ uint8_t data8[8]; /**< @brief Frame data. */
+ uint16_t data16[4]; /**< @brief Frame data. */
+ uint32_t data32[2]; /**< @brief Frame data. */
+ uint64_t data64[1]; /**< @brief Frame data. */
+ };
+} CANRxFrame;
+
+/**
+ * @brief CAN filter.
+ * @note Refer to the STM32 reference manual for info about filters.
+ */
+typedef struct {
+ /**
+ * @brief Number of the filter bank to be programmed.
+ */
+ uint32_t filter:16;
+ /**
+ * @brief Filter mode.
+ * @note This bit represent the CAN_FM1R register bit associated to this
+ * filter (0=mask mode, 1=list mode).
+ */
+ uint32_t mode:1;
+ /**
+ * @brief Filter scale.
+ * @note This bit represent the CAN_FS1R register bit associated to this
+ * filter (0=16 bits mode, 1=32 bits mode).
+ */
+ uint32_t scale:1;
+ /**
+ * @brief Filter mode.
+ * @note This bit represent the CAN_FFA1R register bit associated to this
+ * filter, must be set to zero in this version of the driver.
+ */
+ uint32_t assignment:1;
+ /**
+ * @brief Filter register 1 (identifier).
+ */
+ uint32_t register1;
+ /**
+ * @brief Filter register 2 (mask/identifier depending on mode=0/1).
+ */
+ uint32_t register2;
+} CANFilter;
+
+/**
+ * @brief Driver configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief CAN MCR register initialization data.
+ * @note Some bits in this register are enforced by the driver regardless
+ * their status in this field.
+ */
+ uint32_t mcr;
+ /**
+ * @brief CAN BTR register initialization data.
+ * @note Some bits in this register are enforced by the driver regardless
+ * their status in this field.
+ */
+ uint32_t btr;
+} CANConfig;
+
+/**
+ * @brief Structure representing an CAN driver.
+ */
+struct CANDriver {
+ /**
+ * @brief Driver state.
+ */
+ canstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const CANConfig *config;
+ /**
+ * @brief Transmission threads queue.
+ */
+ threads_queue_t txqueue;
+ /**
+ * @brief Receive threads queue.
+ */
+ threads_queue_t rxqueue;
+#if (CAN_ENFORCE_USE_CALLBACKS == FALSE) || defined(__DOXYGEN__)
+ /**
+ * @brief One or more frames become available.
+ * @note After broadcasting this event it will not be broadcasted again
+ * until the received frames queue has been completely emptied. It
+ * is not broadcasted for each received frame. It is
+ * responsibility of the application to empty the queue by
+ * repeatedly invoking @p canReceive() when listening to this event.
+ * This behavior minimizes the interrupt served by the system
+ * because CAN traffic.
+ * @note The flags associated to the listeners will indicate which
+ * receive mailboxes become non-empty.
+ */
+ event_source_t rxfull_event;
+ /**
+ * @brief One or more transmission mailbox become available.
+ * @note The flags associated to the listeners will indicate which
+ * transmit mailboxes become empty.
+ * @note The upper 16 bits are transmission error flags associated
+ * to the transmit mailboxes.
+ */
+ event_source_t txempty_event;
+ /**
+ * @brief A CAN bus error happened.
+ * @note The flags associated to the listeners will indicate that
+ * receive error(s) have occurred.
+ * @note In this implementation the upper 16 bits are filled with the
+ * unprocessed content of the ESR register.
+ */
+ event_source_t error_event;
+#if CAN_USE_SLEEP_MODE || defined (__DOXYGEN__)
+ /**
+ * @brief Entering sleep state event.
+ */
+ event_source_t sleep_event;
+ /**
+ * @brief Exiting sleep state event.
+ */
+ event_source_t wakeup_event;
+#endif /* CAN_USE_SLEEP_MODE */
+#else /* CAN_ENFORCE_USE_CALLBACKS == TRUE */
+ /**
+ * @brief One or more frames become available.
+ * @note After calling this function it will not be called again
+ * until the received frames queue has been completely emptied. It
+ * is not called for each received frame. It is
+ * responsibility of the application to empty the queue by
+ * repeatedly invoking @p chTryReceiveI().
+ * This behavior minimizes the interrupt served by the system
+ * because CAN traffic.
+ */
+ can_callback_t rxfull_cb;
+ /**
+ * @brief One or more transmission mailbox become available.
+ * @note The flags associated to the callback will indicate which
+ * transmit mailboxes become empty.
+ */
+ can_callback_t txempty_cb;
+ /**
+ * @brief A CAN bus error happened.
+ */
+ can_callback_t error_cb;
+#if (CAN_USE_SLEEP_MODE == TRUE) || defined (__DOXYGEN__)
+ /**
+ * @brief Exiting sleep state.
+ */
+ can_callback_t wakeup_cb;
+#endif
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Pointer to the CAN registers.
+ */
+ CAN_TypeDef *can;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_CAN_USE_CAN1 && !defined(__DOXYGEN__)
+extern CANDriver CAND1;
+#endif
+
+#if STM32_CAN_USE_CAN2 && !defined(__DOXYGEN__)
+extern CANDriver CAND2;
+#endif
+
+#if STM32_CAN_USE_CAN3 && !defined(__DOXYGEN__)
+extern CANDriver CAND3;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void can_lld_init(void);
+ void can_lld_start(CANDriver *canp);
+ void can_lld_stop(CANDriver *canp);
+ bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox);
+ void can_lld_transmit(CANDriver *canp,
+ canmbx_t mailbox,
+ const CANTxFrame *crfp);
+ bool can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox);
+ void can_lld_receive(CANDriver *canp,
+ canmbx_t mailbox,
+ CANRxFrame *ctfp);
+ void can_lld_abort(CANDriver *canp,
+ canmbx_t mailbox);
+#if CAN_USE_SLEEP_MODE
+ void can_lld_sleep(CANDriver *canp);
+ void can_lld_wakeup(CANDriver *canp);
+#endif /* CAN_USE_SLEEP_MODE */
+ void canSTM32SetFilters(CANDriver *canp, uint32_t can2sb,
+ uint32_t num, const CANFilter *cfp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_CAN */
+
+#endif /* HAL_CAN_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/CRYPv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/CRYPv1/driver.mk
new file mode 100644
index 0000000..43936d3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/CRYPv1/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_CRY TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.c
new file mode 100644
index 0000000..6bb0448
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.c
@@ -0,0 +1,1901 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file CRYPv1/hal_crypto_lld.c
+ * @brief STM32 cryptographic subsystem low level driver source.
+ *
+ * @addtogroup CRYPTO
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+
+#if (HAL_USE_CRY == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define CRYP1_IN_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_CRY_CRYP1_IN_DMA_STREAM, \
+ STM32_CRYP1_IN_DMA_CHN)
+
+#define CRYP1_OUT_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_CRY_CRYP1_OUT_DMA_STREAM, \
+ STM32_CRYP1_OUT_DMA_CHN)
+
+#define HASH1_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_CRY_HASH1_DMA_STREAM, \
+ STM32_HASH1_DMA_CHN)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief CRY1 driver identifier.*/
+#if (STM32_CRY_ENABLED1 == TRUE) || defined(__DOXYGEN__)
+CRYDriver CRYD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#if (STM32_CRY_USE_CRYP1 == TRUE) || defined (__DOXYGEN__)
+/**
+ * @brief Setting AES key for encryption.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] algomode algorithm mode field of CR register
+ */
+static inline void cryp_set_key_encrypt(CRYDriver *cryp, uint32_t algomode) {
+ uint32_t cr;
+
+ /* Loading key data.*/
+ CRYP->K0LR = cryp->cryp_k[0];
+ CRYP->K0RR = cryp->cryp_k[1];
+ CRYP->K1LR = cryp->cryp_k[2];
+ CRYP->K1RR = cryp->cryp_k[3];
+ CRYP->K2LR = cryp->cryp_k[4];
+ CRYP->K2RR = cryp->cryp_k[5];
+ CRYP->K3LR = cryp->cryp_k[6];
+ CRYP->K3RR = cryp->cryp_k[7];
+
+ /* Setting up then starting operation.*/
+ cr = CRYP->CR;
+ cr &= ~(CRYP_CR_KEYSIZE_Msk | CRYP_CR_ALGOMODE_Msk | CRYP_CR_ALGODIR_Msk);
+ cr |= cryp->cryp_ksize | algomode | CRYP_CR_CRYPEN;
+ CRYP->CR = cr;
+
+ cryp->cryp_ktype = cryp_key_aes_encrypt;
+}
+
+/**
+ * @brief Setting AES key for decryption.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] algomode algorithm field of CR register
+ */
+static inline void cryp_set_key_decrypt(CRYDriver *cryp, uint32_t algomode) {
+ uint32_t cr;
+
+ /* Loading key data then doing transformation for decrypt.*/
+ cryp_set_key_encrypt(cryp, CRYP_CR_ALGOMODE_AES_KEY);
+ while ((CRYP->CR & CRYP_CR_CRYPEN) != 0U) {
+ }
+
+ /* Setting up then starting operation.*/
+ cr = CRYP->CR;
+ cr &= ~(CRYP_CR_KEYSIZE_Msk | CRYP_CR_ALGOMODE_Msk | CRYP_CR_ALGODIR_Msk);
+ cr |= cryp->cryp_ksize | algomode | CRYP_CR_ALGODIR | CRYP_CR_CRYPEN;
+ CRYP->CR = cr;
+
+ cryp->cryp_ktype = cryp_key_aes_decrypt;
+}
+
+/**
+ * @brief Setting IV.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] iv 128 bits initial vector
+ */
+static inline void cryp_set_iv(CRYDriver *cryp, const uint8_t *iv) {
+
+ (void)cryp;
+
+ CRYP->IV0LR = __REV(__UNALIGNED_UINT32_READ(&iv[0]));
+ CRYP->IV0RR = __REV(__UNALIGNED_UINT32_READ(&iv[4]));
+ CRYP->IV1LR = __REV(__UNALIGNED_UINT32_READ(&iv[8]));
+ CRYP->IV1RR = __REV(__UNALIGNED_UINT32_READ(&iv[12]));
+}
+
+/**
+ * @brief Performs a CRYP operation using DMA.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] size size of both buffers, this number must be a
+ * multiple of 16
+ * @param[in] in input buffer
+ * @param[out] out output buffer
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ */
+static cryerror_t cryp_do_transfer(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out) {
+ uint32_t szw;
+
+ szw = (uint32_t)(size / sizeof (uint32_t));
+#if STM32_CRY_CRYP_SIZE_THRESHOLD > 1
+ if (size >= STM32_CRY_CRYP_SIZE_THRESHOLD)
+#endif
+#if STM32_CRY_CRYP_SIZE_THRESHOLD != 0
+ {
+ /* DMA limitation.*/
+ osalDbgCheck(size < 0x10000U * 4U);
+
+ osalSysLock();
+
+ /* Preparing DMAs.*/
+ dmaStreamSetTransactionSize(cryp->cryp_dma_in, szw);
+ dmaStreamSetTransactionSize(cryp->cryp_dma_out, szw);
+ dmaStreamSetMemory0(cryp->cryp_dma_in, in);
+ dmaStreamSetMemory0(cryp->cryp_dma_out, out);
+ dmaStreamEnable(cryp->cryp_dma_in);
+ dmaStreamEnable(cryp->cryp_dma_out);
+
+ (void) osalThreadSuspendS(&cryp->cryp_tr);
+
+ osalSysUnlock();
+ }
+#endif
+#if STM32_CRY_CRYP_SIZE_THRESHOLD > 1
+ else
+#endif
+#if STM32_CRY_CRYP_SIZE_THRESHOLD != 1
+ {
+ uint32_t nr, nw;
+
+ nr = 0U;
+ nw = 0U;
+ while (nw < szw) {
+
+ if ((CRYP->SR & CRYP_SR_OFNE) != 0U) {
+ __UNALIGNED_UINT32_WRITE(out, CRYP->DOUT);
+ out += 4;
+ nw++;
+ continue; /* Priority to output FIFO.*/
+ }
+
+ if ((nr < szw) && ((CRYP->SR & CRYP_SR_IFNF) != 0U)) {
+ CRYP->DR = __UNALIGNED_UINT32_READ(in);
+ in += 4;
+ nr++;
+ }
+ }
+ }
+#endif
+
+ /* Disabling unit.*/
+ CRYP->CR &= ~CRYP_CR_CRYPEN;
+
+ return CRY_NOERROR;
+}
+
+/**
+ * @brief CRYP-IN DMA ISR.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void cry_lld_serve_cryp_in_interrupt(CRYDriver *cryp, uint32_t flags) {
+
+ (void)cryp;
+
+ /* DMA errors handling.*/
+#if defined(STM32_CRY_CRYP_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0U) {
+ STM32_CRY_CRYP_DMA_ERROR_HOOK(cryp);
+ }
+#endif
+}
+
+/**
+ * @brief CRYP-OUT DMA ISR.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void cry_lld_serve_cryp_out_interrupt(CRYDriver *cryp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(STM32_CRY_CRYP_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0U) {
+ STM32_CRY_CRYP_DMA_ERROR_HOOK(cryp);
+ }
+#endif
+
+ /* End buffer interrupt.*/
+ if ((flags & STM32_DMA_ISR_TCIF) != 0U) {
+
+ /* Clearing flags of the other stream too.*/
+ dmaStreamClearInterrupt(cryp->cryp_dma_in);
+
+ /* Resuming waiting thread.*/
+ osalSysLockFromISR();
+ osalThreadResumeI(&cryp->cryp_tr, MSG_OK);
+ osalSysUnlockFromISR();
+ }
+}
+#endif
+
+#if (STM32_CRY_USE_HASH1 == TRUE) || defined (__DOXYGEN__)
+#if (STM32_CRY_HASH_SIZE_THRESHOLD != 0) || defined (__DOXYGEN__)
+/**
+ * @brief HASH DMA ISR.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void cry_lld_serve_hash_interrupt(CRYDriver *cryp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(STM32_HASH_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0U) {
+ STM32_CRY_HASH_DMA_ERROR_HOOK(cryp);
+ }
+#endif
+
+ /* End buffer interrupt.*/
+ if ((flags & STM32_DMA_ISR_TCIF) != 0U) {
+
+ /* Resuming waiting thread.*/
+ osalSysLockFromISR();
+ osalThreadResumeI(&cryp->hash_tr, MSG_OK);
+ osalSysUnlockFromISR();
+ }
+}
+#endif
+#endif
+
+/**
+ * @brief Pushes a series of words into the hash engine.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] n the number of words to be pushed
+ * @param[in] p pointer to the words buffer
+ */
+static void cry_lld_hash_push(CRYDriver *cryp, uint32_t n, const uint32_t *p) {
+
+ (void)cryp; /* Not touched in some cases, needs this.*/
+
+ /* Data is processed in 32kB blocks because DMA size limitations.*/
+ while (n > 0U) {
+ uint32_t chunk = n > 0x8000U ? 0x8000U : n;
+ n -= chunk;
+
+#if STM32_CRY_HASH_SIZE_THRESHOLD > 1
+ if (chunk >= STM32_CRY_HASH_SIZE_THRESHOLD)
+#endif
+#if STM32_CRY_HASH_SIZE_THRESHOLD != 0
+ {
+ /* Setting up transfer.*/
+ dmaStreamSetTransactionSize(cryp->hash_dma, chunk);
+ dmaStreamSetPeripheral(cryp->hash_dma, p);
+ p += chunk;
+
+ osalSysLock();
+
+ /* Enabling DMA channel then HASH engine.*/
+ dmaStreamEnable(cryp->hash_dma);
+
+ /* Waiting for DMA operation completion.*/
+ osalThreadSuspendS(&cryp->hash_tr);
+
+ osalSysUnlock();
+ }
+#endif
+#if STM32_CRY_HASH_SIZE_THRESHOLD > 1
+ else
+#endif
+#if STM32_CRY_HASH_SIZE_THRESHOLD != 1
+ {
+ /* Small chunk, just pushing data without touching DMA.*/
+ do {
+ HASH->DIN = *p++;
+ chunk--;
+ } while (chunk > 0U);
+ }
+#endif
+ }
+
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level crypto driver initialization.
+ *
+ * @notapi
+ */
+void cry_lld_init(void) {
+
+#if STM32_CRY_ENABLED1
+ cryObjectInit(&CRYD1);
+
+#if STM32_CRY_USE_CRYP1
+#if STM32_CRY_CRYP_SIZE_THRESHOLD != 0
+ CRYD1.cryp_tr = NULL;
+ CRYD1.cryp_dma_in = NULL;
+ CRYD1.cryp_dma_out = NULL;
+#endif
+#endif
+
+#if STM32_CRY_USE_HASH1
+#if STM32_CRY_HASH_SIZE_THRESHOLD != 0
+ CRYD1.hash_tr = NULL;
+ CRYD1.hash_dma = NULL;
+#endif /* STM32_CRY_HASH_SIZE_THRESHOLD != 0 */
+#endif /* STM32_CRY_USE_HASH1 */
+
+#endif /* STM32_CRY_ENABLED1 */
+}
+
+/**
+ * @brief Configures and activates the crypto peripheral.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ *
+ * @notapi
+ */
+void cry_lld_start(CRYDriver *cryp) {
+
+ if (cryp->state == CRY_STOP) {
+
+#if STM32_CRY_ENABLED1
+ if (&CRYD1 == cryp) {
+#if STM32_CRY_USE_CRYP1 == TRUE
+#if STM32_CRY_CRYP_SIZE_THRESHOLD != 0
+ /* Allocating DMA channels.*/
+ cryp->cryp_dma_in = dmaStreamAllocI(STM32_CRY_CRYP1_IN_DMA_STREAM,
+ STM32_CRY_CRYP1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)cry_lld_serve_cryp_in_interrupt,
+ (void *)cryp);
+ osalDbgAssert(cryp->cryp_dma_in != NULL, "unable to allocate stream");
+ cryp->cryp_dma_out = dmaStreamAllocI(STM32_CRY_CRYP1_OUT_DMA_STREAM,
+ STM32_CRY_CRYP1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)cry_lld_serve_cryp_out_interrupt,
+ (void *)cryp);
+ osalDbgAssert(cryp->cryp_dma_out != NULL, "unable to allocate stream");
+
+ /* Preparing the DMA channels.*/
+ dmaStreamSetMode(cryp->cryp_dma_in,
+ STM32_DMA_CR_CHSEL(CRYP1_IN_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_CRY_CRYP1_IN_DMA_PRIORITY) |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE);
+ dmaStreamSetMode(cryp->cryp_dma_out,
+ STM32_DMA_CR_CHSEL(CRYP1_OUT_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_CRY_CRYP1_OUT_DMA_PRIORITY) |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE |
+ STM32_DMA_CR_TCIE);
+ dmaStreamSetPeripheral(cryp->cryp_dma_in, &CRYP->DR);
+ dmaStreamSetPeripheral(cryp->cryp_dma_out, &CRYP->DOUT);
+ dmaStreamSetFIFO(cryp->cryp_dma_in, STM32_DMA_FCR_DMDIS);
+ dmaStreamSetFIFO(cryp->cryp_dma_out, STM32_DMA_FCR_DMDIS);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(cryp->dma_cryp_in, STM32_DMAMUX1_CRYP_IN);
+ dmaSetRequestSource(cryp->dma_cryp_out, STM32_DMAMUX1_CRYP_OUT);
+#endif
+#endif /* STM32_CRY_CRYP_SIZE_THRESHOLD != 0 */
+ rccEnableCRYP(true);
+#endif /* STM32_CRY_USE_CRYP1 == TRUE */
+
+#if STM32_CRY_USE_HASH1 == TRUE
+#if STM32_CRY_HASH_SIZE_THRESHOLD != 0
+ cryp->hash_dma = dmaStreamAllocI(STM32_CRY_HASH1_DMA_STREAM,
+ STM32_CRY_HASH1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)cry_lld_serve_hash_interrupt,
+ (void *)cryp);
+ osalDbgAssert(cryp->hash_dma != NULL, "unable to allocate stream");
+
+ /* Preparing the DMA channel.*/
+ dmaStreamSetMode(cryp->hash_dma,
+ STM32_DMA_CR_CHSEL(HASH1_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_CRY_HASH1_DMA_PRIORITY) |
+ STM32_DMA_CR_PINC | STM32_DMA_CR_DIR_M2M |
+ STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE |
+ STM32_DMA_CR_TCIE);
+ dmaStreamSetMemory0(cryp->hash_dma, &HASH->DIN);
+ dmaStreamSetFIFO(cryp->hash_dma, STM32_DMA_FCR_DMDIS);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(cryp->dma_hash, STM32_DMAMUX1_HASH);
+#endif
+#endif /* STM32_CRY_HASH_SIZE_THRESHOLD != 0 */
+ rccEnableHASH(true);
+#endif /* STM32_CRY_USE_HASH1 == TRUE */
+ }
+#endif
+ }
+
+ /* Resetting trasient key data.*/
+ cryp->cryp_ktype = cryp_key_none;
+ cryp->cryp_ksize = 0U;
+ cryp->cryp_k[0] = 0U;
+ cryp->cryp_k[1] = 0U;
+ cryp->cryp_k[2] = 0U;
+ cryp->cryp_k[3] = 0U;
+ cryp->cryp_k[4] = 0U;
+ cryp->cryp_k[5] = 0U;
+ cryp->cryp_k[6] = 0U;
+ cryp->cryp_k[7] = 0U;
+
+#if STM32_CRY_USE_CRYP1
+ /* CRYP setup.*/
+ CRYP->CR = CRYP_CR_DATATYPE_1;
+ CRYP->DMACR = CRYP_DMACR_DIEN | CRYP_DMACR_DOEN;
+#endif
+
+#if STM32_CRY_USE_HASH1
+ /* HASH setup and enable.*/
+#endif
+}
+
+/**
+ * @brief Deactivates the crypto peripheral.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ *
+ * @notapi
+ */
+void cry_lld_stop(CRYDriver *cryp) {
+
+ if (cryp->state == CRY_READY) {
+
+ /* Resetting CRYP.*/
+ CRYP->CR = 0U;
+ CRYP->DMACR = 0U;
+
+#if STM32_CRY_ENABLED1
+ if (&CRYD1 == cryp) {
+#if STM32_CRY_USE_CRYP1
+#if STM32_CRY_CRYP_SIZE_THRESHOLD != 0
+ dmaStreamFreeI(cryp->cryp_dma_in);
+ dmaStreamFreeI(cryp->cryp_dma_out);
+ cryp->cryp_dma_in = NULL;
+ cryp->cryp_dma_out = NULL;
+#endif
+ rccDisableCRYP();
+#endif
+
+#if STM32_CRY_USE_HASH1
+#if STM32_CRY_HASH_SIZE_THRESHOLD != 0
+ dmaStreamFreeI(cryp->hash_dma);
+ cryp->hash_dma = NULL;
+#endif
+ rccDisableHASH();
+#endif
+ }
+#endif
+ }
+}
+
+#if (CRY_LLD_SUPPORTS_AES == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Initializes the AES transient key.
+ * @note It is the underlying implementation to decide which key sizes are
+ * allowable.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] size key size in bytes
+ * @param[in] keyp pointer to the key data
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the algorithm is unsupported.
+ * @retval CRY_ERR_INV_KEY_SIZE if the specified key size is invalid for
+ * the specified algorithm.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_aes_loadkey(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *keyp) {
+
+ /* Fetching key data.*/
+ if (size == (size_t)32) {
+ cryp->cryp_ksize = CRYP_CR_KEYSIZE_1;
+ cryp->cryp_k[0] = __REV(__UNALIGNED_UINT32_READ(&keyp[0]));
+ cryp->cryp_k[1] = __REV(__UNALIGNED_UINT32_READ(&keyp[4]));
+ cryp->cryp_k[2] = __REV(__UNALIGNED_UINT32_READ(&keyp[8]));
+ cryp->cryp_k[3] = __REV(__UNALIGNED_UINT32_READ(&keyp[12]));
+ cryp->cryp_k[4] = __REV(__UNALIGNED_UINT32_READ(&keyp[16]));
+ cryp->cryp_k[5] = __REV(__UNALIGNED_UINT32_READ(&keyp[20]));
+ cryp->cryp_k[6] = __REV(__UNALIGNED_UINT32_READ(&keyp[24]));
+ cryp->cryp_k[7] = __REV(__UNALIGNED_UINT32_READ(&keyp[28]));
+ }
+ else if (size == (size_t)24) {
+ cryp->cryp_ksize = CRYP_CR_KEYSIZE_0;
+ cryp->cryp_k[0] = 0U;
+ cryp->cryp_k[1] = 0U;
+ cryp->cryp_k[2] = __REV(__UNALIGNED_UINT32_READ(&keyp[8]));
+ cryp->cryp_k[3] = __REV(__UNALIGNED_UINT32_READ(&keyp[12]));
+ cryp->cryp_k[4] = __REV(__UNALIGNED_UINT32_READ(&keyp[16]));
+ cryp->cryp_k[5] = __REV(__UNALIGNED_UINT32_READ(&keyp[20]));
+ cryp->cryp_k[6] = __REV(__UNALIGNED_UINT32_READ(&keyp[24]));
+ cryp->cryp_k[7] = __REV(__UNALIGNED_UINT32_READ(&keyp[28]));
+ }
+ else if (size == (size_t)16) {
+ cryp->cryp_ksize = 0U;
+ cryp->cryp_k[0] = 0U;
+ cryp->cryp_k[1] = 0U;
+ cryp->cryp_k[2] = 0U;
+ cryp->cryp_k[3] = 0U;
+ cryp->cryp_k[4] = __REV(__UNALIGNED_UINT32_READ(&keyp[16]));
+ cryp->cryp_k[5] = __REV(__UNALIGNED_UINT32_READ(&keyp[20]));
+ cryp->cryp_k[6] = __REV(__UNALIGNED_UINT32_READ(&keyp[24]));
+ cryp->cryp_k[7] = __REV(__UNALIGNED_UINT32_READ(&keyp[28]));
+ }
+ else {
+ return CRY_ERR_INV_KEY_SIZE;
+ }
+
+ return CRY_NOERROR;
+}
+
+/**
+ * @brief Encryption of a single block using AES.
+ * @note The implementation of this function must guarantee that it can
+ * be called from any context.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_AES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out) {
+ unsigned i;
+
+ /* Only key zero is supported.*/
+ if (key_id != 0U) {
+ return CRY_ERR_INV_KEY_ID;
+ }
+
+ /* Setting the stored key.*/
+ if (cryp->cryp_ktype != cryp_key_aes_encrypt) {
+ cryp_set_key_encrypt(cryp, CRYP_CR_ALGOMODE_AES_ECB);
+ }
+
+ /* Pushing the AES block in the FIFO, it is assumed to be empty.*/
+ CRYP->DR = __UNALIGNED_UINT32_READ(&in[0]);
+ CRYP->DR = __UNALIGNED_UINT32_READ(&in[4]);
+ CRYP->DR = __UNALIGNED_UINT32_READ(&in[8]);
+ CRYP->DR = __UNALIGNED_UINT32_READ(&in[12]);
+
+ /* Reading the result.*/
+ for (i = 0U; i < 4; i++, out += 4) {
+ while ((CRYP->SR & CRYP_SR_OFNE) == 0U) {
+ }
+ __UNALIGNED_UINT32_WRITE(out, CRYP->DOUT);
+ }
+
+ /* Disabling unit.*/
+ CRYP->CR &= ~CRYP_CR_CRYPEN;
+
+ return CRY_NOERROR;
+}
+
+/**
+ * @brief Decryption of a single block using AES.
+ * @note The implementation of this function must guarantee that it can
+ * be called from any context.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] in buffer containing the input ciphertext
+ * @param[out] out buffer for the output plaintext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_AES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out) {
+ unsigned i;
+
+ /* Only key zero is supported.*/
+ if (key_id != 0U) {
+ return CRY_ERR_INV_KEY_ID;
+ }
+
+ /* Setting the stored key.*/
+ if (cryp->cryp_ktype != cryp_key_aes_decrypt) {
+ cryp_set_key_decrypt(cryp, CRYP_CR_ALGOMODE_AES_ECB);
+ }
+
+ /* Pushing the AES block in the FIFO, it is assumed to be empty.*/
+ CRYP->DR = __UNALIGNED_UINT32_READ(&in[0]);
+ CRYP->DR = __UNALIGNED_UINT32_READ(&in[4]);
+ CRYP->DR = __UNALIGNED_UINT32_READ(&in[8]);
+ CRYP->DR = __UNALIGNED_UINT32_READ(&in[12]);
+
+ /* Reading the result.*/
+ for (i = 0U; i < 4; i++, out += 4) {
+ while ((CRYP->SR & CRYP_SR_OFNE) == 0U) {
+ }
+ __UNALIGNED_UINT32_WRITE(out, CRYP->DOUT);
+ }
+
+ /* Disabling unit.*/
+ CRYP->CR &= ~CRYP_CR_CRYPEN;
+
+ return CRY_NOERROR;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_AES_ECB == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Encryption operation using AES-ECB.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers, this number must be a
+ * multiple of 16
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_AES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ /* Only key zero is supported.*/
+ if (key_id != 0U) {
+ return CRY_ERR_INV_KEY_ID;
+ }
+
+ /* Setting the stored key.*/
+ if (cryp->cryp_ktype != cryp_key_aes_encrypt) {
+ cryp_set_key_encrypt(cryp, CRYP_CR_ALGOMODE_AES_ECB);
+ }
+
+ return cryp_do_transfer(cryp, size, in, out);
+}
+
+/**
+ * @brief Decryption operation using AES-ECB.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers, this number must be a
+ * multiple of 16
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_AES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ /* Only key zero is supported.*/
+ if (key_id != 0U) {
+ return CRY_ERR_INV_KEY_ID;
+ }
+
+ /* Setting the stored key.*/
+ if (cryp->cryp_ktype != cryp_key_aes_decrypt) {
+ cryp_set_key_decrypt(cryp, CRYP_CR_ALGOMODE_AES_ECB);
+ }
+
+ return cryp_do_transfer(cryp, size, in, out);
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_AES_CBC == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Encryption operation using AES-CBC.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers, this number must be a
+ * multiple of 16
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @param[in] iv 128 bits initial vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_AES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ /* Only key zero is supported.*/
+ if (key_id != 0U) {
+ return CRY_ERR_INV_KEY_ID;
+ }
+
+ /* Setting the stored key and IV.*/
+ cryp_set_iv(cryp, iv);
+ if (cryp->cryp_ktype != cryp_key_aes_encrypt) {
+ cryp_set_key_encrypt(cryp, CRYP_CR_ALGOMODE_AES_CBC);
+ }
+
+ return cryp_do_transfer(cryp, size, in, out);
+}
+
+/**
+ * @brief Decryption operation using AES-CBC.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers, this number must be a
+ * multiple of 16
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @param[in] iv 128 bits initial vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_AES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ /* Only key zero is supported.*/
+ if (key_id != 0U) {
+ return CRY_ERR_INV_KEY_ID;
+ }
+
+ /* Setting the stored key and IV.*/
+ cryp_set_iv(cryp, iv);
+ if (cryp->cryp_ktype != cryp_key_aes_decrypt) {
+ cryp_set_key_decrypt(cryp, CRYP_CR_ALGOMODE_AES_CBC);
+ }
+
+ return cryp_do_transfer(cryp, size, in, out);
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_AES_CFB == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Encryption operation using AES-CFB.
+ * @note This is a stream cipher, there are no size restrictions.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @param[in] iv 128 bits initial vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_AES_CFB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Decryption operation using AES-CFB.
+ * @note This is a stream cipher, there are no size restrictions.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @param[in] iv 128 bits initial vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_AES_CFB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_AES_CTR == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Encryption operation using AES-CTR.
+ * @note This is a stream cipher, there are no size restrictions.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @param[in] iv 128 bits initial vector + counter, it contains
+ * a 96 bits IV and a 32 bits counter
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_AES_CTR(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Decryption operation using AES-CTR.
+ * @note This is a stream cipher, there are no size restrictions.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers
+ * @param[in] in buffer containing the input ciphertext
+ * @param[out] out buffer for the output plaintext
+ * @param[in] iv 128 bits initial vector + counter, it contains
+ * a 96 bits IV and a 32 bits counter
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_AES_CTR(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_AES_GCM == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Encryption operation using AES-GCM.
+ * @note This is a stream cipher, there are no size restrictions.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] auth_size size of the data buffer to be authenticated
+ * @param[in] auth_in buffer containing the data to be authenticated
+ * @param[in] text_size size of the text buffer
+ * @param[in] text_in buffer containing the input plaintext
+ * @param[out] text_out buffer for the output ciphertext
+ * @param[in] iv 128 bits input vector
+ * @param[in] tag_size size of the authentication tag, this number
+ * must be between 1 and 16
+ * @param[out] tag_out buffer for the generated authentication tag
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_AES_GCM(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t auth_size,
+ const uint8_t *auth_in,
+ size_t text_size,
+ const uint8_t *text_in,
+ uint8_t *text_out,
+ const uint8_t *iv,
+ size_t tag_size,
+ uint8_t *tag_out) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)auth_size;
+ (void)auth_in;
+ (void)text_size;
+ (void)text_in;
+ (void)text_out;
+ (void)iv;
+ (void)tag_size;
+ (void)tag_out;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Decryption operation using AES-GCM.
+ * @note This is a stream cipher, there are no size restrictions.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] auth_size size of the data buffer to be authenticated
+ * @param[in] auth_in buffer containing the data to be authenticated
+ * @param[in] text_size size of the text buffer
+ * @param[in] text_in buffer containing the input plaintext
+ * @param[out] text_out buffer for the output ciphertext
+ * @param[in] iv 128 bits input vector
+ * @param[in] tag_size size of the authentication tag, this number
+ * must be between 1 and 16
+ * @param[in] tag_in buffer for the generated authentication tag
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_AUTH_FAILED authentication failed
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_AES_GCM(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t auth_size,
+ const uint8_t *auth_in,
+ size_t text_size,
+ const uint8_t *text_in,
+ uint8_t *text_out,
+ const uint8_t *iv,
+ size_t tag_size,
+ const uint8_t *tag_in) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)auth_size;
+ (void)auth_in;
+ (void)text_size;
+ (void)text_in;
+ (void)text_out;
+ (void)iv;
+ (void)tag_size;
+ (void)tag_in;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_DES == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Initializes the DES transient key.
+ * @note It is the underlying implementation to decide which key sizes are
+ * allowable.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] size key size in bytes
+ * @param[in] keyp pointer to the key data
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the algorithm is unsupported.
+ * @retval CRY_ERR_INV_KEY_SIZE if the specified key size is invalid for
+ * the specified algorithm.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_des_loadkey(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *keyp) {
+
+ (void)cryp;
+ (void)size;
+ (void)keyp;
+
+ return CRY_NOERROR;
+}
+
+/**
+ * @brief Encryption of a single block using (T)DES.
+ * @note The implementation of this function must guarantee that it can
+ * be called from any context.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_DES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Decryption of a single block using (T)DES.
+ * @note The implementation of this function must guarantee that it can
+ * be called from any context.
+ *
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] in buffer containing the input ciphertext
+ * @param[out] out buffer for the output plaintext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_DES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_DES_ECB == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Encryption operation using (T)DES-ECB.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an DES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of the plaintext buffer, this number must
+ * be a multiple of 8
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_DES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Decryption operation using (T)DES-ECB.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an DES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of the plaintext buffer, this number must
+ * be a multiple of 8
+ * @param[in] in buffer containing the input ciphertext
+ * @param[out] out buffer for the output plaintext
+ * @return T he operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_DES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_DES_CBC == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Encryption operation using (T)DES-CBC.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an DES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of the plaintext buffer, this number must
+ * be a multiple of 8
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @param[in] iv 64 bits input vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_DES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Decryption operation using (T)DES-CBC.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an DES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of the plaintext buffer, this number must
+ * be a multiple of 8
+ * @param[in] in buffer containing the input ciphertext
+ * @param[out] out buffer for the output plaintext
+ * @param[in] iv 64 bits input vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_DES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_SHA1 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Hash initialization using SHA1.
+ * @note Use of this algorithm is not recommended because proven weak.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[out] sha1ctxp pointer to a SHA1 context to be initialized
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_SHA1_init(CRYDriver *cryp, SHA1Context *sha1ctxp) {
+
+ (void)cryp;
+ (void)sha1ctxp;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash update using SHA1.
+ * @note Use of this algorithm is not recommended because proven weak.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] sha1ctxp pointer to a SHA1 context
+ * @param[in] size size of input buffer
+ * @param[in] in buffer containing the input text
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_SHA1_update(CRYDriver *cryp, SHA1Context *sha1ctxp,
+ size_t size, const uint8_t *in) {
+
+ (void)cryp;
+ (void)sha1ctxp;
+ (void)size;
+ (void)in;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash finalization using SHA1.
+ * @note Use of this algorithm is not recommended because proven weak.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] sha1ctxp pointer to a SHA1 context
+ * @param[out] out 160 bits output buffer
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_SHA1_final(CRYDriver *cryp, SHA1Context *sha1ctxp,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)sha1ctxp;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_SHA256 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Hash initialization using SHA256.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[out] sha256ctxp pointer to a SHA256 context to be initialized
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_SHA256_init(CRYDriver *cryp, SHA256Context *sha256ctxp) {
+
+ (void)cryp;
+
+ /* Initializing context structure.*/
+ sha256ctxp->last_data = 0U;
+ sha256ctxp->last_size = 0U;
+
+ /* Initializing operation.*/
+ HASH->CR = /*HASH_CR_MDMAT |*/ HASH_CR_ALGO_1 | HASH_CR_ALGO_0 |
+ HASH_CR_DATATYPE_1 | HASH_CR_INIT;
+
+ return CRY_NOERROR;
+}
+
+/**
+ * @brief Hash update using SHA256.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] sha256ctxp pointer to a SHA256 context
+ * @param[in] size size of input buffer
+ * @param[in] in buffer containing the input text
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_SHA256_update(CRYDriver *cryp, SHA256Context *sha256ctxp,
+ size_t size, const uint8_t *in) {
+ const uint32_t *wp = (const uint32_t *)(const void *)in;
+
+ /* This HW is unable to hash blocks that are not a multiple of 4 bytes
+ except for the last block in the stream which is handled in the
+ "final" function.*/
+ if (sha256ctxp->last_size != 0U) {
+ return CRY_ERR_OP_FAILURE;
+ }
+
+ /* Any unaligned data is deferred to the "final" function.*/
+ sha256ctxp->last_size = 8U * (size % sizeof (uint32_t));
+ if (sha256ctxp->last_size > 0U) {
+ sha256ctxp->last_data = wp[size / sizeof (uint32_t)];
+ }
+
+ /* Pushing data.*/
+ cry_lld_hash_push(cryp, (uint32_t)(size / sizeof (uint32_t)), wp);
+
+ return CRY_NOERROR;
+}
+
+/**
+ * @brief Hash finalization using SHA256.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] sha256ctxp pointer to a SHA256 context
+ * @param[out] out 256 bits output buffer
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_SHA256_final(CRYDriver *cryp, SHA256Context *sha256ctxp,
+ uint8_t *out) {
+ uint32_t digest[8];
+
+ (void)cryp;
+
+ if (sha256ctxp->last_size > 0U) {
+ HASH->DIN = sha256ctxp->last_data;
+ }
+
+ /* Triggering final calculation and wait for result.*/
+ HASH->SR = 0U;
+ HASH->STR = sha256ctxp->last_size;
+ HASH->STR = sha256ctxp->last_size | HASH_STR_DCAL;
+ while ((HASH->SR & HASH_SR_DCIS) == 0U) {
+ }
+
+ /* Reading digest.*/
+ digest[0] = HASH_DIGEST->HR[0];
+ digest[1] = HASH_DIGEST->HR[1];
+ digest[2] = HASH_DIGEST->HR[2];
+ digest[3] = HASH_DIGEST->HR[3];
+ digest[4] = HASH_DIGEST->HR[4];
+ digest[5] = HASH_DIGEST->HR[5];
+ digest[6] = HASH_DIGEST->HR[6];
+ digest[7] = HASH_DIGEST->HR[7];
+ memcpy((void *)out, (const void *)digest, sizeof digest);
+
+ return CRY_NOERROR;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_SHA512 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Hash initialization using SHA512.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[out] sha512ctxp pointer to a SHA512 context to be initialized
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_SHA512_init(CRYDriver *cryp, SHA512Context *sha512ctxp) {
+
+ (void)cryp;
+ (void)sha512ctxp;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash update using SHA512.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] sha512ctxp pointer to a SHA512 context
+ * @param[in] size size of input buffer
+ * @param[in] in buffer containing the input text
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_SHA512_update(CRYDriver *cryp, SHA512Context *sha512ctxp,
+ size_t size, const uint8_t *in) {
+
+ (void)cryp;
+ (void)sha512ctxp;
+ (void)size;
+ (void)in;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash finalization using SHA512.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] sha512ctxp pointer to a SHA512 context
+ * @param[out] out 512 bits output buffer
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_SHA512_final(CRYDriver *cryp, SHA512Context *sha512ctxp,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)sha512ctxp;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Initializes the HMAC transient key.
+ * @note It is the underlying implementation to decide which key sizes are
+ * allowable.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] size key size in bytes
+ * @param[in] keyp pointer to the key data
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the algorithm is unsupported.
+ * @retval CRY_ERR_INV_KEY_SIZE if the specified key size is invalid for
+ * the specified algorithm.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_hmac_loadkey(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *keyp) {
+
+ (void)cryp;
+ (void)size;
+ (void)keyp;
+
+ return CRY_NOERROR;
+}
+
+/**
+ * @brief Hash initialization using HMAC_SHA256.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[out] hmacsha256ctxp pointer to a HMAC_SHA256 context to be
+ * initialized
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_HMACSHA256_init(CRYDriver *cryp,
+ HMACSHA256Context *hmacsha256ctxp) {
+
+ (void)cryp;
+ (void)hmacsha256ctxp;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash update using HMAC.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] hmacsha256ctxp pointer to a HMAC_SHA256 context
+ * @param[in] size size of input buffer
+ * @param[in] in buffer containing the input text
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_HMACSHA256_update(CRYDriver *cryp,
+ HMACSHA256Context *hmacsha256ctxp,
+ size_t size,
+ const uint8_t *in) {
+
+ (void)cryp;
+ (void)hmacsha256ctxp;
+ (void)size;
+ (void)in;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash finalization using HMAC.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] hmacsha256ctxp pointer to a HMAC_SHA256 context
+ * @param[out] out 256 bits output buffer
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_HMACSHA256_final(CRYDriver *cryp,
+ HMACSHA256Context *hmacsha256ctxp,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)hmacsha256ctxp;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Hash initialization using HMAC_SHA512.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[out] hmacsha512ctxp pointer to a HMAC_SHA512 context to be
+ * initialized
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_HMACSHA512_init(CRYDriver *cryp,
+ HMACSHA512Context *hmacsha512ctxp) {
+
+ (void)cryp;
+ (void)hmacsha512ctxp;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash update using HMAC.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] hmacsha512ctxp pointer to a HMAC_SHA512 context
+ * @param[in] size size of input buffer
+ * @param[in] in buffer containing the input text
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_HMACSHA512_update(CRYDriver *cryp,
+ HMACSHA512Context *hmacsha512ctxp,
+ size_t size,
+ const uint8_t *in) {
+
+ (void)cryp;
+ (void)hmacsha512ctxp;
+ (void)size;
+ (void)in;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash finalization using HMAC.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] hmacsha512ctxp pointer to a HMAC_SHA512 context
+ * @param[out] out 512 bits output buffer
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_HMACSHA512_final(CRYDriver *cryp,
+ HMACSHA512Context *hmacsha512ctxp,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)hmacsha512ctxp;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#endif /* HAL_USE_CRY == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.h
new file mode 100644
index 0000000..257d396
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/CRYPv1/hal_crypto_lld.h
@@ -0,0 +1,618 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file CRYPv1/hal_cry_lld.h
+ * @brief STM32 cryptographic subsystem low level driver header.
+ *
+ * @addtogroup CRYPTO
+ * @{
+ */
+
+#ifndef HAL_CRYPTO_LLD_H
+#define HAL_CRYPTO_LLD_H
+
+#if (HAL_USE_CRY == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name STM32 configuration options
+ * @{
+ */
+/**
+ * @brief CRYP1 driver enable switch.
+ * @details If set to @p TRUE the support for CRYP1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_CRY_USE_CRYP1) || defined(__DOXYGEN__)
+#define STM32_CRY_USE_CRYP1 FALSE
+#endif
+
+/**
+ * @brief HASH1 driver enable switch.
+ * @details If set to @p TRUE the support for HASH1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_CRY_USE_HASH1) || defined(__DOXYGEN__)
+#define STM32_CRY_USE_HASH1 FALSE
+#endif
+
+/**
+ * @brief CRYP1 interrupt priority level setting.
+ */
+#if !defined(STM32_CRY_CRYP1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_CRY_CRYP1_IRQ_PRIORITY 9
+#endif
+
+/**
+ * @brief HASH1 interrupt priority level setting.
+ */
+#if !defined(STM32_CRY_HASH1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_CRY_HASH1_IRQ_PRIORITY 9
+#endif
+
+/**
+ * @brief HASH1 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_CRY_CRYP1_OUT_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_CRY_CRYP1_OUT_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief HASH1 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_CRY_HASH1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_CRY_HASH1_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief Minimum message size (in words) for DMA use.
+ * @note If set to zero then DMA is never used.
+ * @note If set to one then DMA is always used.
+ */
+#if !defined(STM32_CRY_HASH_SIZE_THRESHOLD) || defined(__DOXYGEN__)
+#define STM32_CRY_HASH_SIZE_THRESHOLD 1024
+#endif
+
+/**
+ * @brief Minimum text size (in bytes) for DMA use.
+ * @note If set to zero then DMA is never used.
+ * @note If set to one then DMA is always used.
+ */
+#if !defined(STM32_CRY_CRYP_SIZE_THRESHOLD) || defined(__DOXYGEN__)
+#define STM32_CRY_CRYP_SIZE_THRESHOLD 1024
+#endif
+
+/**
+ * @brief Hash DMA error hook.
+ * @note The default action for DMA errors is a system halt because DMA
+ * error can only happen because programming errors.
+ */
+#if !defined(STM32_CRY_HASH_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define STM32_CRY_HASH_DMA_ERROR_HOOK(cryp) osalSysHalt("DMA failure")
+#endif
+
+/**
+ * @brief CRYP DMA error hook.
+ * @note The default action for DMA errors is a system halt because DMA
+ * error can only happen because programming errors.
+ */
+#if !defined(STM32_CRY_CRYP_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define STM32_CRY_CRYP_DMA_ERROR_HOOK(cryp) osalSysHalt("DMA failure")
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if (STM32_CRY_USE_CRYP1 == TRUE) || (STM32_CRY_USE_HASH1 == TRUE) || \
+ defined (__DOXYGEN__)
+#define STM32_CRY_ENABLED1 TRUE
+#else
+#define STM32_CRY_ENABLED1 FALSE
+#endif
+
+#if !defined (STM32_HAS_CRYP1)
+#define STM32_HAS_CRYP1 FALSE
+#endif
+
+#if !defined (STM32_HAS_HASH1)
+#define STM32_HAS_HASH1 FALSE
+#endif
+
+#if STM32_CRY_USE_CRYP1 && !STM32_HAS_CRYP1
+#error "CRYP1 not present in the selected device"
+#endif
+
+#if STM32_CRY_USE_HASH1 && !STM32_HAS_HASH1
+#error "HASH1 not present in the selected device"
+#endif
+
+#if !STM32_CRY_ENABLED1
+#error "CRY driver activated but no CRYP nor HASH peripheral assigned"
+#endif
+
+#if STM32_CRY_USE_HASH1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_CRY_HASH1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to HASH1"
+#endif
+
+#if STM32_CRY_USE_CRYP1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_CRY_CRYP1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to CRYP1"
+#endif
+
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if !defined(STM32_CRY_HASH1_DMA_STREAM)
+#error "HASH1 DMA streams not defined"
+#endif
+
+/* Sanity checks on DMA streams settings in mcuconf.h.*/
+#if STM32_CRY_USE_HASH1 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_CRY_HASH1_DMA_STREAM)
+#error "Invalid DMA stream assigned to HASH1"
+#endif
+
+/* Devices without DMAMUX require an additional check.*/
+#if !STM32_DMA_SUPPORTS_DMAMUX
+#if STM32_CRY_USE_CRYP1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_CRY_CRYP1_IN_DMA_STREAM, \
+ STM32_CRYP1_IN_DMA_MSK)
+#error "invalid DMA stream associated to CRYP1_IN"
+#endif
+
+#if STM32_CRY_USE_CRYP1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_CRY_CRYP1_OUT_DMA_STREAM, \
+ STM32_CRYP1_OUT_DMA_MSK)
+#error "invalid DMA stream associated to CRYP1_OUT"
+#endif
+
+#if STM32_CRY_USE_HASH1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_CRY_HASH1_DMA_STREAM, STM32_HASH1_DMA_MSK)
+#error "invalid DMA stream associated to HASH1"
+#endif
+#endif /* !STM32_DMA_SUPPORTS_DMAMUX */
+
+/* DMA priority check.*/
+#if !STM32_DMA_IS_VALID_PRIORITY(STM32_CRY_CRYP1_IN_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to CRYP1_IN"
+#endif
+
+/* DMA priority check.*/
+#if !STM32_DMA_IS_VALID_PRIORITY(STM32_CRY_CRYP1_OUT_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to CRYP1_OUT"
+#endif
+
+/* DMA priority check.*/
+#if !STM32_DMA_IS_VALID_PRIORITY(STM32_CRY_HASH1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to HASH1"
+#endif
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+#if STM32_CRY_HASH_SIZE_THRESHOLD < 0
+#error "invalid STM32_CRY_HASH_SIZE_THRESHOLD value"
+#endif
+
+/**
+ * @name Driver capability switches
+ * @{
+ */
+#if STM32_CRY_USE_CRYP1 || defined (__DOXYGEN__)
+#define CRY_LLD_SUPPORTS_AES TRUE
+#define CRY_LLD_SUPPORTS_AES_ECB TRUE
+#define CRY_LLD_SUPPORTS_AES_CBC TRUE
+#define CRY_LLD_SUPPORTS_AES_CFB FALSE
+#define CRY_LLD_SUPPORTS_AES_CTR TRUE
+#define CRY_LLD_SUPPORTS_AES_GCM TRUE
+#define CRY_LLD_SUPPORTS_DES TRUE
+#define CRY_LLD_SUPPORTS_DES_ECB TRUE
+#define CRY_LLD_SUPPORTS_DES_CBC TRUE
+#else
+#define CRY_LLD_SUPPORTS_AES FALSE
+#define CRY_LLD_SUPPORTS_AES_ECB FALSE
+#define CRY_LLD_SUPPORTS_AES_CBC FALSE
+#define CRY_LLD_SUPPORTS_AES_CFB FALSE
+#define CRY_LLD_SUPPORTS_AES_CTR FALSE
+#define CRY_LLD_SUPPORTS_AES_GCM FALSE
+#define CRY_LLD_SUPPORTS_DES FALSE
+#define CRY_LLD_SUPPORTS_DES_ECB FALSE
+#define CRY_LLD_SUPPORTS_DES_CBC FALSE
+#endif
+#if STM32_CRY_USE_HASH1 || defined (__DOXYGEN__)
+#define CRY_LLD_SUPPORTS_SHA1 FALSE
+#define CRY_LLD_SUPPORTS_SHA256 TRUE
+#define CRY_LLD_SUPPORTS_SHA512 FALSE
+#define CRY_LLD_SUPPORTS_HMAC_SHA256 TRUE
+#define CRY_LLD_SUPPORTS_HMAC_SHA512 FALSE
+#else
+#define CRY_LLD_SUPPORTS_SHA1 FALSE
+#define CRY_LLD_SUPPORTS_SHA256 FALSE
+#define CRY_LLD_SUPPORTS_SHA512 FALSE
+#define CRY_LLD_SUPPORTS_HMAC_SHA256 FALSE
+#define CRY_LLD_SUPPORTS_HMAC_SHA512 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief CRY key identifier type.
+ */
+typedef uint32_t crykey_t;
+
+/**
+ * @brief Type of a structure representing an CRY driver.
+ */
+typedef struct CRYDriver CRYDriver;
+
+/**
+ * @brief Type of key stored in CRYP.
+ */
+typedef enum {
+ cryp_key_none = 0,
+ cryp_key_des = 1,
+ cryp_key_tdes = 2,
+ cryp_key_aes_encrypt = 3,
+ cryp_key_aes_decrypt = 4
+} cryp_ktype_t;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+ uint32_t dummy;
+} CRYConfig;
+
+/**
+ * @brief Structure representing an CRY driver.
+ */
+struct CRYDriver {
+ /**
+ * @brief Driver state.
+ */
+ crystate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const CRYConfig *config;
+#if defined(CRY_DRIVER_EXT_FIELDS)
+ CRY_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+#if (STM32_CRY_USE_CRYP1 == TRUE) || defined (__DOXYGEN__)
+ /**
+ * @brief Type of the key currently stored in CRYP.
+ */
+ cryp_ktype_t cryp_ktype;
+ /**
+ * @brief Key size setup value for CR register.
+ */
+ uint32_t cryp_ksize;
+ /**
+ * @brief Transient key data.
+ */
+ uint32_t cryp_k[8];
+#if (STM32_CRY_CRYP_SIZE_THRESHOLD != 0) || defined (__DOXYGEN__)
+ /**
+ * @brief Thread reference for CRYP operations.
+ */
+ thread_reference_t cryp_tr;
+ /**
+ * @brief CRYP IN DMA stream.
+ */
+ const stm32_dma_stream_t *cryp_dma_in;
+ /**
+ * @brief CRYP OUT DMA stream.
+ */
+ const stm32_dma_stream_t *cryp_dma_out;
+#endif /* STM32_CRY_CRYP_SIZE_THRESHOLD != 0 */
+#endif /* STM32_CRY_USE_CRYP1 == TRUE */
+#if (STM32_CRY_USE_HASH1 == TRUE) || defined (__DOXYGEN__)
+#if (STM32_CRY_HASH_SIZE_THRESHOLD != 0) || defined (__DOXYGEN__)
+ /**
+ * @brief Thread reference for hash operations.
+ */
+ thread_reference_t hash_tr;
+ /**
+ * @brief Hash DMA stream.
+ */
+ const stm32_dma_stream_t *hash_dma;
+#endif /* STM32_CRY_HASH_SIZE_THRESHOLD != 0 */
+#endif /* STM32_CRY_USE_HASH1 == TRUE */
+};
+
+#if (CRY_LLD_SUPPORTS_SHA1 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a SHA1 context.
+ */
+typedef struct {
+ uint32_t dummy;
+} SHA1Context;
+#endif
+
+#if (CRY_LLD_SUPPORTS_SHA256 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a SHA256 context.
+ */
+typedef struct {
+ /**
+ * @brief Last data to be hashed on finalization.
+ */
+ uint32_t last_data;
+ /**
+ * @brief Size, in bits, of the last data.
+ */
+ uint32_t last_size;
+} SHA256Context;
+#endif
+
+#if (CRY_LLD_SUPPORTS_SHA512 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a SHA512 context.
+ */
+typedef struct {
+ uint32_t dummy;
+} SHA512Context;
+#endif
+
+#if (CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a HMAC_SHA256 context.
+ */
+typedef struct {
+ uint32_t dummy;
+} HMACSHA256Context;
+#endif
+
+#if (CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a HMAC_SHA512 context.
+ */
+typedef struct {
+ uint32_t dummy;
+} HMACSHA512Context;
+#endif
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (STM32_CRY_ENABLED1 == TRUE) && !defined(__DOXYGEN__)
+extern CRYDriver CRYD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void cry_lld_init(void);
+ void cry_lld_start(CRYDriver *cryp);
+ void cry_lld_stop(CRYDriver *cryp);
+#if (CRY_LLD_SUPPORTS_AES == TRUE) || \
+ (CRY_LLD_SUPPORTS_AES_ECB == TRUE) || \
+ (CRY_LLD_SUPPORTS_AES_CBC == TRUE) || \
+ (CRY_LLD_SUPPORTS_AES_CFB == TRUE) || \
+ (CRY_LLD_SUPPORTS_AES_CTR == TRUE) || \
+ (CRY_LLD_SUPPORTS_AES_GCM == TRUE) || \
+ defined(__DOXYGEN__)
+ cryerror_t cry_lld_aes_loadkey(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *keyp);
+#endif
+#if (CRY_LLD_SUPPORTS_AES == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_encrypt_AES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cry_lld_decrypt_AES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out);
+#endif
+#if (CRY_LLD_SUPPORTS_AES_ECB == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_encrypt_AES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cry_lld_decrypt_AES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out);
+#endif
+#if (CRY_LLD_SUPPORTS_AES_CBC == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_encrypt_AES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cry_lld_decrypt_AES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+#endif
+#if (CRY_LLD_SUPPORTS_AES_CFB == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_encrypt_AES_CFB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cry_lld_decrypt_AES_CFB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+#endif
+#if (CRY_LLD_SUPPORTS_AES_CTR == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_encrypt_AES_CTR(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cry_lld_decrypt_AES_CTR(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+#endif
+#if (CRY_LLD_SUPPORTS_AES_GCM == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_encrypt_AES_GCM(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t auth_size,
+ const uint8_t *auth_in,
+ size_t text_size,
+ const uint8_t *text_in,
+ uint8_t *text_out,
+ const uint8_t *iv,
+ size_t tag_size,
+ uint8_t *tag_out);
+ cryerror_t cry_lld_decrypt_AES_GCM(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t auth_size,
+ const uint8_t *auth_in,
+ size_t text_size,
+ const uint8_t *text_in,
+ uint8_t *text_out,
+ const uint8_t *iv,
+ size_t tag_size,
+ const uint8_t *tag_in);
+#endif
+#if (CRY_LLD_SUPPORTS_DES == TRUE) || \
+ (CRY_LLD_SUPPORTS_DES_ECB == TRUE) || \
+ (CRY_LLD_SUPPORTS_DES_CBC == TRUE) || \
+ defined(__DOXYGEN__)
+ cryerror_t cry_lld_des_loadkey(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *keyp);
+#endif
+#if (CRY_LLD_SUPPORTS_DES == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_encrypt_DES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cry_lld_decrypt_DES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out);
+#endif
+#if (CRY_LLD_SUPPORTS_DES_ECB == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_encrypt_DES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cry_lld_decrypt_DES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out);
+#endif
+#if (CRY_LLD_SUPPORTS_DES_CBC == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_encrypt_DES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cry_lld_decrypt_DES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+#endif
+#if (CRY_LLD_SUPPORTS_SHA1 == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_SHA1_init(CRYDriver *cryp, SHA1Context *sha1ctxp);
+ cryerror_t cry_lld_SHA1_update(CRYDriver *cryp, SHA1Context *sha1ctxp,
+ size_t size, const uint8_t *in);
+ cryerror_t cry_lld_SHA1_final(CRYDriver *cryp, SHA1Context *sha1ctxp,
+ uint8_t *out);
+#endif
+#if (CRY_LLD_SUPPORTS_SHA256 == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_SHA256_init(CRYDriver *cryp, SHA256Context *sha256ctxp);
+ cryerror_t cry_lld_SHA256_update(CRYDriver *cryp, SHA256Context *sha256ctxp,
+ size_t size, const uint8_t *in);
+ cryerror_t cry_lld_SHA256_final(CRYDriver *cryp, SHA256Context *sha256ctxp,
+ uint8_t *out);
+#endif
+#if (CRY_LLD_SUPPORTS_SHA512 == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_SHA512_init(CRYDriver *cryp, SHA512Context *sha512ctxp);
+ cryerror_t cry_lld_SHA512_update(CRYDriver *cryp, SHA512Context *sha512ctxp,
+ size_t size, const uint8_t *in);
+ cryerror_t cry_lld_SHA512_final(CRYDriver *cryp, SHA512Context *sha512ctxp,
+ uint8_t *out);
+#endif
+#if (CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE) || \
+ (CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE) || \
+ defined(__DOXYGEN__)
+ cryerror_t cry_lld_hmac_loadkey(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *keyp);
+#endif
+#if (CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_HMACSHA256_init(CRYDriver *cryp,
+ HMACSHA256Context *hmacsha256ctxp);
+ cryerror_t cry_lld_HMACSHA256_update(CRYDriver *cryp,
+ HMACSHA256Context *hmacsha256ctxp,
+ size_t size, const uint8_t *in);
+ cryerror_t cry_lld_HMACSHA256_final(CRYDriver *cryp,
+ HMACSHA256Context *hmacsha256ctxp,
+ uint8_t *out);
+#endif
+#if (CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_HMACSHA512_init(CRYDriver *cryp,
+ HMACSHA512Context *hmacsha512ctxp);
+ cryerror_t cry_lld_HMACSHA512_update(CRYDriver *cryp,
+ HMACSHA512Context *hmacsha512ctxp,
+ size_t size, const uint8_t *in);
+ cryerror_t cry_lld_HMACSHA512_final(CRYDriver *cryp,
+ HMACSHA512Context *hmacsha512ctxp,
+ uint8_t *out);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_CRY == TRUE */
+
+#endif /* HAL_CRYPTO_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DACv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DACv1/driver.mk
new file mode 100644
index 0000000..da95148
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DACv1/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_DAC TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.c
new file mode 100644
index 0000000..b4180d3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.c
@@ -0,0 +1,769 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file DACv1/hal_dac_lld.c
+ * @brief STM32 DAC subsystem low level driver source.
+ *
+ * @addtogroup DAC
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_DAC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/* Because ST headers naming inconsistencies.*/
+#if !defined(DAC1)
+#define DAC1 DAC
+#endif
+
+#define DAC1_CH1_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_DAC_DAC1_CH1_DMA_STREAM, \
+ STM32_DAC1_CH1_DMA_CHN)
+
+#define DAC1_CH2_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_DAC_DAC1_CH2_DMA_STREAM, \
+ STM32_DAC1_CH2_DMA_CHN)
+
+#define DAC2_CH1_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_DAC_DAC2_CH1_DMA_STREAM, \
+ STM32_DAC2_CH1_DMA_CHN)
+
+#define DAC2_CH2_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_DAC_DAC2_CH2_DMA_STREAM, \
+ STM32_DAC2_CH2_DMA_CHN)
+
+#define DAC3_CH1_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_DAC_DAC3_CH1_DMA_STREAM, \
+ STM32_DAC3_CH1_DMA_CHN)
+
+#define DAC3_CH2_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_DAC_DAC3_CH2_DMA_STREAM, \
+ STM32_DAC3_CH2_DMA_CHN)
+
+#define DAC4_CH1_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_DAC_DAC4_CH1_DMA_STREAM, \
+ STM32_DAC4_CH1_DMA_CHN)
+
+#define DAC4_CH2_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_DAC_DAC4_CH2_DMA_STREAM, \
+ STM32_DAC4_CH2_DMA_CHN)
+
+#define CHANNEL_DATA_OFFSET 3U
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief DAC1 CH1 driver identifier.*/
+#if STM32_DAC_USE_DAC1_CH1 || defined(__DOXYGEN__)
+DACDriver DACD1;
+#endif
+
+/** @brief DAC1 CH2 driver identifier.*/
+#if (STM32_DAC_USE_DAC1_CH2 && !STM32_DAC_DUAL_MODE) || defined(__DOXYGEN__)
+DACDriver DACD2;
+#endif
+
+/** @brief DAC2 CH1 driver identifier.*/
+#if STM32_DAC_USE_DAC2_CH1 || defined(__DOXYGEN__)
+DACDriver DACD3;
+#endif
+
+/** @brief DAC2 CH2 driver identifier.*/
+#if (STM32_DAC_USE_DAC2_CH2 && !STM32_DAC_DUAL_MODE) || defined(__DOXYGEN__)
+DACDriver DACD4;
+#endif
+
+/** @brief DAC3 CH1 driver identifier.*/
+#if STM32_DAC_USE_DAC3_CH1 || defined(__DOXYGEN__)
+DACDriver DACD5;
+#endif
+
+/** @brief DAC3 CH2 driver identifier.*/
+#if (STM32_DAC_USE_DAC3_CH2 && !STM32_DAC_DUAL_MODE) || defined(__DOXYGEN__)
+DACDriver DACD6;
+#endif
+
+/** @brief DAC4 CH1 driver identifier.*/
+#if STM32_DAC_USE_DAC4_CH1 || defined(__DOXYGEN__)
+DACDriver DACD7;
+#endif
+
+/** @brief DAC4 CH2 driver identifier.*/
+#if (STM32_DAC_USE_DAC4_CH2 && !STM32_DAC_DUAL_MODE) || defined(__DOXYGEN__)
+DACDriver DACD8;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+#if STM32_DAC_USE_DAC1_CH1 == TRUE
+static const dacparams_t dac1_ch1_params = {
+ .dac = DAC1,
+ .dataoffset = 0U,
+ .regshift = 0U,
+ .regmask = 0xFFFF0000U,
+ .dmastream = STM32_DAC_DAC1_CH1_DMA_STREAM,
+#if STM32_DMA_SUPPORTS_DMAMUX
+ .peripheral = STM32_DMAMUX1_DAC1_CH1,
+#endif
+ .dmamode = STM32_DMA_CR_CHSEL(DAC1_CH1_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_DAC_DAC1_CH1_DMA_PRIORITY) |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE,
+ .dmairqprio = STM32_DAC_DAC1_CH1_IRQ_PRIORITY
+};
+#endif
+
+#if STM32_DAC_USE_DAC1_CH2 == TRUE
+static const dacparams_t dac1_ch2_params = {
+ .dac = DAC1,
+ .dataoffset = CHANNEL_DATA_OFFSET,
+ .regshift = 16U,
+ .regmask = 0x0000FFFFU,
+ .dmastream = STM32_DAC_DAC1_CH2_DMA_STREAM,
+#if STM32_DMA_SUPPORTS_DMAMUX
+ .peripheral = STM32_DMAMUX1_DAC1_CH2,
+#endif
+ .dmamode = STM32_DMA_CR_CHSEL(DAC1_CH2_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_DAC_DAC1_CH2_DMA_PRIORITY) |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE,
+ .dmairqprio = STM32_DAC_DAC1_CH2_IRQ_PRIORITY
+};
+#endif
+
+#if STM32_DAC_USE_DAC2_CH1 == TRUE
+static const dacparams_t dac2_ch1_params = {
+ .dac = DAC2,
+ .dataoffset = 0U,
+ .regshift = 0U,
+ .regmask = 0xFFFF0000U,
+ .dmastream = STM32_DAC_DAC2_CH1_DMA_STREAM,
+#if STM32_DMA_SUPPORTS_DMAMUX
+ .peripheral = STM32_DMAMUX1_DAC2_CH1,
+#endif
+ .dmamode = STM32_DMA_CR_CHSEL(DAC2_CH1_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_DAC_DAC2_CH1_DMA_PRIORITY) |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE,
+ .dmairqprio = STM32_DAC_DAC2_CH1_IRQ_PRIORITY
+};
+#endif
+
+#if STM32_DAC_USE_DAC2_CH2 == TRUE
+static const dacparams_t dac2_ch2_params = {
+ .dac = DAC2,
+ .dataoffset = CHANNEL_DATA_OFFSET,
+ .regshift = 16U,
+ .regmask = 0x0000FFFFU,
+ .dmastream = STM32_DAC_DAC2_CH2_DMA_STREAM,
+#if STM32_DMA_SUPPORTS_DMAMUX
+ .peripheral = STM32_DMAMUX1_DAC2_CH2,
+#endif
+ .dmamode = STM32_DMA_CR_CHSEL(DAC2_CH2_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_DAC_DAC2_CH2_DMA_PRIORITY) |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE,
+ .dmairqprio = STM32_DAC_DAC2_CH2_IRQ_PRIORITY
+};
+#endif
+
+#if STM32_DAC_USE_DAC3_CH1 == TRUE
+static const dacparams_t dac3_ch1_params = {
+ .dac = DAC3,
+ .dataoffset = 0U,
+ .regshift = 0U,
+ .regmask = 0xFFFF0000U,
+ .dmastream = STM32_DAC_DAC3_CH1_DMA_STREAM,
+#if STM32_DMA_SUPPORTS_DMAMUX
+ .peripheral = STM32_DMAMUX1_DAC3_CH1,
+#endif
+ .dmamode = STM32_DMA_CR_CHSEL(DAC3_CH1_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_DAC_DAC3_CH1_DMA_PRIORITY) |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE,
+ .dmairqprio = STM32_DAC_DAC3_CH1_IRQ_PRIORITY
+};
+#endif
+
+#if STM32_DAC_USE_DAC3_CH2 == TRUE
+static const dacparams_t dac3_ch2_params = {
+ .dac = DAC3,
+ .dataoffset = CHANNEL_DATA_OFFSET,
+ .regshift = 16U,
+ .regmask = 0x0000FFFFU,
+ .dmastream = STM32_DAC_DAC3_CH2_DMA_STREAM,
+#if STM32_DMA_SUPPORTS_DMAMUX
+ .peripheral = STM32_DMAMUX1_DAC3_CH2,
+#endif
+ .dmamode = STM32_DMA_CR_CHSEL(DAC3_CH2_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_DAC_DAC3_CH2_DMA_PRIORITY) |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE,
+ .dmairqprio = STM32_DAC_DAC3_CH2_IRQ_PRIORITY
+};
+#endif
+
+#if STM32_DAC_USE_DAC4_CH1 == TRUE
+static const dacparams_t dac4_ch1_params = {
+ .dac = DAC4,
+ .dataoffset = 0U,
+ .regshift = 0U,
+ .regmask = 0xFFFF0000U,
+ .dmastream = STM32_DAC_DAC4_CH1_DMA_STREAM,
+#if STM32_DMA_SUPPORTS_DMAMUX
+ .peripheral = STM32_DMAMUX1_DAC4_CH1,
+#endif
+ .dmamode = STM32_DMA_CR_CHSEL(DAC4_CH1_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_DAC_DAC4_CH1_DMA_PRIORITY) |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE,
+ .dmairqprio = STM32_DAC_DAC4_CH1_IRQ_PRIORITY
+};
+#endif
+
+#if STM32_DAC_USE_DAC4_CH2 == TRUE
+static const dacparams_t dac4_ch2_params = {
+ .dac = DAC4,
+ .dataoffset = CHANNEL_DATA_OFFSET,
+ .regshift = 16U,
+ .regmask = 0x0000FFFFU,
+ .dmastream = STM32_DAC_DAC4_CH2_DMA_STREAM,
+#if STM32_DMA_SUPPORTS_DMAMUX
+ .peripheral = STM32_DMAMUX1_DAC4_CH2,
+#endif
+ .dmamode = STM32_DMA_CR_CHSEL(DAC4_CH2_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_DAC_DAC4_CH2_DMA_PRIORITY) |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE | STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE,
+ .dmairqprio = STM32_DAC_DAC4_CH2_IRQ_PRIORITY
+};
+#endif
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Shared end/half-of-tx service routine.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void dac_lld_serve_tx_interrupt(DACDriver *dacp, uint32_t flags) {
+
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ /* DMA errors handling.*/
+ dac_lld_stop_conversion(dacp);
+ _dac_isr_error_code(dacp, DAC_ERR_DMAFAILURE);
+ }
+ else {
+ if ((flags & STM32_DMA_ISR_HTIF) != 0) {
+ /* Half transfer processing.*/
+ _dac_isr_half_code(dacp);
+ }
+ if ((flags & STM32_DMA_ISR_TCIF) != 0) {
+ /* Transfer complete processing.*/
+ _dac_isr_full_code(dacp);
+ }
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level DAC driver initialization.
+ *
+ * @notapi
+ */
+void dac_lld_init(void) {
+
+#if STM32_DAC_USE_DAC1_CH1
+ dacObjectInit(&DACD1);
+ DACD1.params = &dac1_ch1_params;
+ DACD1.dma = NULL;
+#endif
+
+#if STM32_DAC_USE_DAC1_CH2
+ dacObjectInit(&DACD2);
+ DACD2.params = &dac1_ch2_params;
+ DACD2.dma = NULL;
+#endif
+
+#if STM32_DAC_USE_DAC2_CH1
+ dacObjectInit(&DACD3);
+ DACD3.params = &dac2_ch1_params;
+ DACD3.dma = NULL;
+#endif
+
+#if STM32_DAC_USE_DAC2_CH2
+ dacObjectInit(&DACD4);
+ DACD4.params = &dac2_ch2_params;
+ DACD4.dma = NULL;
+#endif
+
+#if STM32_DAC_USE_DAC3_CH1
+ dacObjectInit(&DACD5);
+ DACD5.params = &dac3_ch1_params;
+ DACD5.dma = NULL;
+#endif
+
+#if STM32_DAC_USE_DAC3_CH2
+ dacObjectInit(&DACD6);
+ DACD6.params = &dac3_ch2_params;
+ DACD6.dma = NULL;
+#endif
+
+#if STM32_DAC_USE_DAC4_CH1
+ dacObjectInit(&DACD7);
+ DACD7.params = &dac4_ch1_params;
+ DACD7.dma = NULL;
+#endif
+
+#if STM32_DAC_USE_DAC4_CH2
+ dacObjectInit(&DACD8);
+ DACD8.params = &dac4_ch2_params;
+ DACD8.dma = NULL;
+#endif
+}
+
+/**
+ * @brief Configures and activates the DAC peripheral.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @notapi
+ */
+void dac_lld_start(DACDriver *dacp) {
+
+ /* If the driver is in DAC_STOP state then a full initialization is
+ required.*/
+ if (dacp->state == DAC_STOP) {
+ dacchannel_t channel = 0;
+
+ /* Enabling the clock source.*/
+#if STM32_DAC_USE_DAC1_CH1
+ if (&DACD1 == dacp) {
+ rccEnableDAC1(true);
+ }
+#endif
+
+#if STM32_DAC_USE_DAC1_CH2
+ if (&DACD2 == dacp) {
+ rccEnableDAC1(true);
+ channel = 1;
+ }
+#endif
+
+#if STM32_DAC_USE_DAC2_CH1
+ if (&DACD3 == dacp) {
+ rccEnableDAC2(true);
+ }
+#endif
+
+#if STM32_DAC_USE_DAC2_CH2
+ if (&DACD4 == dacp) {
+ rccEnableDAC2(true);
+ channel = 1;
+ }
+#endif
+
+#if STM32_DAC_USE_DAC3_CH1
+ if (&DACD5 == dacp) {
+ rccEnableDAC3(true);
+ }
+#endif
+
+#if STM32_DAC_USE_DAC3_CH2
+ if (&DACD6 == dacp) {
+ rccEnableDAC3(true);
+ channel = 1;
+ }
+#endif
+
+#if STM32_DAC_USE_DAC4_CH1
+ if (&DACD7 == dacp) {
+ rccEnableDAC4(true);
+ }
+#endif
+
+#if STM32_DAC_USE_DAC4_CH2
+ if (&DACD8 == dacp) {
+ rccEnableDAC4(true);
+ channel = 1;
+ }
+#endif
+
+ /* Enabling DAC in SW triggering mode initially, initializing data to
+ zero.*/
+#if STM32_DAC_DUAL_MODE == FALSE
+ {
+ uint32_t cr;
+
+ cr = dacp->params->dac->CR;
+ cr &= dacp->params->regmask;
+ cr |= (DAC_CR_EN1 | dacp->config->cr) << dacp->params->regshift;
+ dacp->params->dac->CR = cr;
+ dac_lld_put_channel(dacp, channel, dacp->config->init);
+ }
+#else
+ if ((dacp->config->datamode == DAC_DHRM_12BIT_RIGHT_DUAL) ||
+ (dacp->config->datamode == DAC_DHRM_12BIT_LEFT_DUAL) ||
+ (dacp->config->datamode == DAC_DHRM_8BIT_RIGHT_DUAL)) {
+ dacp->params->dac->CR = DAC_CR_EN2 | (dacp->config->cr << 16) | DAC_CR_EN1 | dacp->config->cr;
+ dac_lld_put_channel(dacp, 1U, dacp->config->init);
+ }
+ else {
+ dacp->params->dac->CR = DAC_CR_EN1 | dacp->config->cr;
+ }
+ dac_lld_put_channel(dacp, channel, dacp->config->init);
+#endif
+ }
+}
+
+/**
+ * @brief Deactivates the DAC peripheral.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @notapi
+ */
+void dac_lld_stop(DACDriver *dacp) {
+
+ /* If in ready state then disables the DAC clock.*/
+ if (dacp->state == DAC_READY) {
+
+ /* Disabling DAC.*/
+ dacp->params->dac->CR &= dacp->params->regmask;
+
+#if STM32_DAC_USE_DAC1_CH1
+ if (&DACD1 == dacp) {
+ if ((dacp->params->dac->CR & DAC_CR_EN2) == 0U) {
+ rccDisableDAC1();
+ }
+ }
+#endif
+
+#if STM32_DAC_USE_DAC1_CH2
+ if (&DACD2 == dacp) {
+ if ((dacp->params->dac->CR & DAC_CR_EN1) == 0U) {
+ rccDisableDAC1();
+ }
+ }
+#endif
+
+#if STM32_DAC_USE_DAC2_CH1
+ if (&DACD3 == dacp) {
+ if ((dacp->params->dac->CR & DAC_CR_EN2) == 0U) {
+ rccDisableDAC2();
+ }
+ }
+#endif
+
+#if STM32_DAC_USE_DAC2_CH2
+ if (&DACD4 == dacp) {
+ if ((dacp->params->dac->CR & DAC_CR_EN1) == 0U) {
+ rccDisableDAC2();
+ }
+ }
+#endif
+
+#if STM32_DAC_USE_DAC3_CH1
+ if (&DACD5 == dacp) {
+ if ((dacp->params->dac->CR & DAC_CR_EN2) == 0U) {
+ rccDisableDAC3();
+ }
+ }
+#endif
+
+#if STM32_DAC_USE_DAC3_CH2
+ if (&DACD6 == dacp) {
+ if ((dacp->params->dac->CR & DAC_CR_EN1) == 0U) {
+ rccDisableDAC3();
+ }
+ }
+#endif
+
+#if STM32_DAC_USE_DAC4_CH1
+ if (&DACD7 == dacp) {
+ if ((dacp->params->dac->CR & DAC_CR_EN2) == 0U) {
+ rccDisableDAC4();
+ }
+ }
+#endif
+
+#if STM32_DAC_USE_DAC4_CH2
+ if (&DACD8 == dacp) {
+ if ((dacp->params->dac->CR & DAC_CR_EN1) == 0U) {
+ rccDisableDAC4();
+ }
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Outputs a value directly on a DAC channel.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ * @param[in] channel DAC channel number
+ * @param[in] sample value to be output
+ *
+ * @api
+ */
+void dac_lld_put_channel(DACDriver *dacp,
+ dacchannel_t channel,
+ dacsample_t sample) {
+
+ switch (dacp->config->datamode) {
+ case DAC_DHRM_12BIT_RIGHT:
+#if STM32_DAC_DUAL_MODE
+ case DAC_DHRM_12BIT_RIGHT_DUAL:
+#endif
+ if (channel == 0U) {
+#if STM32_DAC_DUAL_MODE
+ dacp->params->dac->DHR12R1 = (uint32_t)sample;
+#else
+ *(&dacp->params->dac->DHR12R1 + dacp->params->dataoffset) = (uint32_t)sample;
+#endif
+ }
+#if (STM32_HAS_DAC1_CH2 || STM32_HAS_DAC2_CH2 || \
+ STM32_HAS_DAC3_CH2 || STM32_HAS_DAC4_CH2)
+ else {
+ dacp->params->dac->DHR12R2 = (uint32_t)sample;
+ }
+#endif
+ break;
+ case DAC_DHRM_12BIT_LEFT:
+#if STM32_DAC_DUAL_MODE
+ case DAC_DHRM_12BIT_LEFT_DUAL:
+#endif
+ if (channel == 0U) {
+#if STM32_DAC_DUAL_MODE
+ dacp->params->dac->DHR12L1 = (uint32_t)sample;
+#else
+ *(&dacp->params->dac->DHR12L1 + dacp->params->dataoffset) = (uint32_t)sample;
+#endif
+ }
+#if (STM32_HAS_DAC1_CH2 || STM32_HAS_DAC2_CH2 || \
+ STM32_HAS_DAC3_CH2 || STM32_HAS_DAC4_CH2)
+ else {
+ dacp->params->dac->DHR12L2 = (uint32_t)sample;
+ }
+#endif
+ break;
+ case DAC_DHRM_8BIT_RIGHT:
+#if STM32_DAC_DUAL_MODE
+ case DAC_DHRM_8BIT_RIGHT_DUAL:
+#endif
+ if (channel == 0U) {
+#if STM32_DAC_DUAL_MODE
+ dacp->params->dac->DHR8R1 = (uint32_t)sample;
+#else
+ *(&dacp->params->dac->DHR8R1 + dacp->params->dataoffset) = (uint32_t)sample;
+#endif
+ }
+#if (STM32_HAS_DAC1_CH2 || STM32_HAS_DAC2_CH2 || \
+ STM32_HAS_DAC3_CH2 || STM32_HAS_DAC4_CH2)
+ else {
+ dacp->params->dac->DHR8R2 = (uint32_t)sample;
+ }
+#endif
+ break;
+ default:
+ osalDbgAssert(false, "unexpected DAC mode");
+ break;
+ }
+}
+
+/**
+ * @brief Starts a DAC conversion.
+ * @details Starts an asynchronous conversion operation.
+ * @note In @p DAC_DHRM_8BIT_RIGHT mode the parameters passed to the
+ * callback are wrong because two samples are packed in a single
+ * dacsample_t element. This will not be corrected, do not rely
+ * on those parameters.
+ * @note In @p DAC_DHRM_8BIT_RIGHT_DUAL mode two samples are treated
+ * as a single 16 bits sample and packed into a single dacsample_t
+ * element. The num_channels must be set to one in the group
+ * conversion configuration structure.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @notapi
+ */
+void dac_lld_start_conversion(DACDriver *dacp) {
+ uint32_t n, cr, dmamode;
+
+ /* Number of DMA operations per buffer.*/
+ n = dacp->depth * dacp->grpp->num_channels;
+
+ /* Allocating the DMA channel.*/
+ dacp->dma = dmaStreamAllocI(dacp->params->dmastream,
+ dacp->params->dmairqprio,
+ (stm32_dmaisr_t)dac_lld_serve_tx_interrupt,
+ (void *)dacp);
+ osalDbgAssert(dacp->dma != NULL, "unable to allocate stream");
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(dacp->dma, dacp->params->peripheral);
+#endif
+
+ /* DMA settings depend on the chosen DAC mode.*/
+ switch (dacp->config->datamode) {
+ /* Sets the DAC data register */
+ case DAC_DHRM_12BIT_RIGHT:
+ osalDbgAssert(dacp->grpp->num_channels == 1, "invalid number of channels");
+
+ dmaStreamSetPeripheral(dacp->dma, &dacp->params->dac->DHR12R1 +
+ dacp->params->dataoffset);
+ dmamode = dacp->params->dmamode |
+ STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
+ break;
+ case DAC_DHRM_12BIT_LEFT:
+ osalDbgAssert(dacp->grpp->num_channels == 1, "invalid number of channels");
+
+ dmaStreamSetPeripheral(dacp->dma, &dacp->params->dac->DHR12L1 +
+ dacp->params->dataoffset);
+ dmamode = dacp->params->dmamode |
+ STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
+ break;
+ case DAC_DHRM_8BIT_RIGHT:
+ osalDbgAssert(dacp->grpp->num_channels == 1, "invalid number of channels");
+
+ dmaStreamSetPeripheral(dacp->dma, &dacp->params->dac->DHR8R1 +
+ dacp->params->dataoffset);
+ dmamode = dacp->params->dmamode |
+ STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE;
+
+ /* In this mode the size of the buffer is halved because two samples
+ packed in a single dacsample_t element.*/
+ n = (n + 1) / 2;
+ break;
+#if STM32_DAC_DUAL_MODE == TRUE
+ case DAC_DHRM_12BIT_RIGHT_DUAL:
+ osalDbgAssert(dacp->grpp->num_channels == 2, "invalid number of channels");
+
+ dmaStreamSetPeripheral(dacp->dma, &dacp->params->dac->DHR12RD);
+ dmamode = dacp->params->dmamode |
+ STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD;
+ n /= 2;
+ break;
+ case DAC_DHRM_12BIT_LEFT_DUAL:
+ osalDbgAssert(dacp->grpp->num_channels == 2, "invalid number of channels");
+
+ dmaStreamSetPeripheral(dacp->dma, &dacp->params->dac->DHR12LD);
+ dmamode = dacp->params->dmamode |
+ STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD;
+ n /= 2;
+ break;
+ case DAC_DHRM_8BIT_RIGHT_DUAL:
+ osalDbgAssert(dacp->grpp->num_channels == 1, "invalid number of channels");
+
+ dmaStreamSetPeripheral(dacp->dma, &dacp->params->dac->DHR8RD);
+ dmamode = dacp->params->dmamode |
+ STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
+ n /= 2;
+ break;
+#endif
+ default:
+ osalDbgAssert(false, "unexpected DAC mode");
+ return;
+ }
+
+ dmaStreamSetMemory0(dacp->dma, dacp->samples);
+ dmaStreamSetTransactionSize(dacp->dma, n);
+ dmaStreamSetMode(dacp->dma, dmamode |
+ STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE |
+ STM32_DMA_CR_HTIE | STM32_DMA_CR_TCIE);
+ dmaStreamEnable(dacp->dma);
+
+ /* DAC configuration.*/
+ cr = dacp->params->dac->CR;
+
+#if STM32_DAC_DUAL_MODE == FALSE
+ cr &= dacp->params->regmask;
+ cr |= (DAC_CR_DMAEN1 | (dacp->grpp->trigger << DAC_CR_TSEL1_Pos) | DAC_CR_TEN1 | DAC_CR_EN1 | dacp->config->cr) << dacp->params->regshift;
+#else
+ cr = DAC_CR_DMAEN1 | (dacp->grpp->trigger << DAC_CR_TSEL1_Pos) | DAC_CR_TEN1 | DAC_CR_EN1 | dacp->config->cr
+ | (dacp->grpp->trigger << DAC_CR_TSEL2_Pos) | DAC_CR_TEN2 | DAC_CR_EN2 | (dacp->config->cr << 16);
+#endif
+
+ dacp->params->dac->CR = cr;
+}
+
+/**
+ * @brief Stops an ongoing conversion.
+ * @details This function stops the currently ongoing conversion and returns
+ * the driver in the @p DAC_READY state. If there was no conversion
+ * being processed then the function does nothing.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @iclass
+ */
+void dac_lld_stop_conversion(DACDriver *dacp) {
+ uint32_t cr;
+
+ /* DMA channel disabled and released.*/
+ dmaStreamDisable(dacp->dma);
+ dmaStreamFreeI(dacp->dma);
+ dacp->dma = NULL;
+
+ cr = dacp->params->dac->CR;
+
+#if STM32_DAC_DUAL_MODE == FALSE
+ cr &= dacp->params->regmask;
+ cr |= (DAC_CR_EN1 | dacp->config->cr) << dacp->params->regshift;
+#else
+ if ((dacp->config->datamode == DAC_DHRM_12BIT_RIGHT_DUAL) ||
+ (dacp->config->datamode == DAC_DHRM_12BIT_LEFT_DUAL) ||
+ (dacp->config->datamode == DAC_DHRM_8BIT_RIGHT_DUAL)) {
+ cr = DAC_CR_EN2 | (dacp->config->cr << 16) |
+ DAC_CR_EN1 | dacp->config->cr;
+ }
+ else {
+ cr = DAC_CR_EN1 | dacp->config->cr;
+ }
+#endif
+
+ dacp->params->dac->CR = cr;
+}
+
+#endif /* HAL_USE_DAC */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.h
new file mode 100644
index 0000000..09550fa
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DACv1/hal_dac_lld.h
@@ -0,0 +1,662 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file DACv1/hal_dac_lld.h
+ * @brief STM32 DAC subsystem low level driver header.
+ *
+ * @addtogroup DAC
+ * @{
+ */
+
+#ifndef HAL_DAC_LLD_H
+#define HAL_DAC_LLD_H
+
+#if HAL_USE_DAC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name DAC trigger modes
+ * @{
+ */
+#define DAC_TRG_MASK 7U
+#define DAC_TRG(n) (n)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief Enables the DAC dual mode.
+ * @note In dual mode DAC second channels cannot be accessed individually.
+ */
+#if !defined(STM32_DAC_DUAL_MODE) || defined(__DOXYGEN__)
+#define STM32_DAC_DUAL_MODE FALSE
+#endif
+
+/**
+ * @brief DAC1 CH1 driver enable switch.
+ * @details If set to @p TRUE the support for DAC1 channel 1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_DAC_USE_DAC1_CH1) || defined(__DOXYGEN__)
+#define STM32_DAC_USE_DAC1_CH1 FALSE
+#endif
+
+/**
+ * @brief DAC1 CH2 driver enable switch.
+ * @details If set to @p TRUE the support for DAC1 channel 2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_DAC_USE_DAC1_CH2) || defined(__DOXYGEN__)
+#define STM32_DAC_USE_DAC1_CH2 FALSE
+#endif
+
+/**
+ * @brief DAC2 CH1 driver enable switch.
+ * @details If set to @p TRUE the support for DAC2 channel 1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_DAC_USE_DAC2_CH1) || defined(__DOXYGEN__)
+#define STM32_DAC_USE_DAC2_CH1 FALSE
+#endif
+
+/**
+ * @brief DAC2 CH2 driver enable switch.
+ * @details If set to @p TRUE the support for DAC2 channel 2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_DAC_USE_DAC2_CH2) || defined(__DOXYGEN__)
+#define STM32_DAC_USE_DAC2_CH2 FALSE
+#endif
+
+/**
+ * @brief DAC3 CH1 driver enable switch.
+ * @details If set to @p TRUE the support for DAC3 channel 1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_DAC_USE_DAC3_CH1) || defined(__DOXYGEN__)
+#define STM32_DAC_USE_DAC3_CH1 FALSE
+#endif
+
+/**
+ * @brief DAC3 CH2 driver enable switch.
+ * @details If set to @p TRUE the support for DAC3 channel 2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_DAC_USE_DAC3_CH2) || defined(__DOXYGEN__)
+#define STM32_DAC_USE_DAC3_CH2 FALSE
+#endif
+
+/**
+ * @brief DAC4 CH1 driver enable switch.
+ * @details If set to @p TRUE the support for DAC4 channel 1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_DAC_USE_DAC4_CH1) || defined(__DOXYGEN__)
+#define STM32_DAC_USE_DAC4_CH1 FALSE
+#endif
+
+/**
+ * @brief DAC4 CH2 driver enable switch.
+ * @details If set to @p TRUE the support for DAC4 channel 2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_DAC_USE_DAC4_CH2) || defined(__DOXYGEN__)
+#define STM32_DAC_USE_DAC4_CH2 FALSE
+#endif
+
+/**
+ * @brief DAC1 CH1 interrupt priority level setting.
+ */
+#if !defined(STM32_DAC_DAC1_CH1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief DAC1 CH2 interrupt priority level setting.
+ */
+#if !defined(STM32_DAC_DAC1_CH2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief DAC2 CH1 interrupt priority level setting.
+ */
+#if !defined(STM32_DAC_DAC2_CH1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_DAC_DAC2_CH1_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief DAC2 CH2 interrupt priority level setting.
+ */
+#if !defined(STM32_DAC_DAC2_CH2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_DAC_DAC2_CH2_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief DAC3 CH1 interrupt priority level setting.
+ */
+#if !defined(STM32_DAC_DAC3_CH1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_DAC_DAC3_CH1_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief DAC3 CH2 interrupt priority level setting.
+ */
+#if !defined(STM32_DAC_DAC3_CH2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_DAC_DAC3_CH2_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief DAC4 CH1 interrupt priority level setting.
+ */
+#if !defined(STM32_DAC_DAC4_CH1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_DAC_DAC4_CH1_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief DAC4 CH2 interrupt priority level setting.
+ */
+#if !defined(STM32_DAC_DAC4_CH2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_DAC_DAC4_CH2_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief DAC1 CH1 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_DAC_DAC1_CH1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief DAC1 CH2 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_DAC_DAC1_CH2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief DAC2 CH1 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_DAC_DAC2_CH1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_DAC_DAC2_CH1_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief DAC2 CH2 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_DAC_DAC2_CH2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_DAC_DAC2_CH2_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief DAC3 CH1 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_DAC_DAC3_CH1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_DAC_DAC3_CH1_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief DAC3 CH2 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_DAC_DAC3_CH2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_DAC_DAC3_CH2_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief DAC4 CH1 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_DAC_DAC4_CH1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_DAC_DAC4_CH1_DMA_PRIORITY 2
+#endif
+
+/**
+ * @brief DAC4 CH2 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_DAC_DAC4_CH2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_DAC_DAC4_CH2_DMA_PRIORITY 2
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Handling missing registry keys.*/
+#if !defined(STM32_HAS_DAC1_CH1)
+#define STM32_HAS_DAC1_CH1 FALSE
+#endif
+#if !defined(STM32_HAS_DAC1_CH2)
+#define STM32_HAS_DAC1_CH2 FALSE
+#endif
+#if !defined(STM32_HAS_DAC2_CH1)
+#define STM32_HAS_DAC2_CH1 FALSE
+#endif
+#if !defined(STM32_HAS_DAC2_CH2)
+#define STM32_HAS_DAC2_CH2 FALSE
+#endif
+#if !defined(STM32_HAS_DAC3_CH1)
+#define STM32_HAS_DAC3_CH1 FALSE
+#endif
+#if !defined(STM32_HAS_DAC3_CH2)
+#define STM32_HAS_DAC3_CH2 FALSE
+#endif
+#if !defined(STM32_HAS_DAC4_CH1)
+#define STM32_HAS_DAC4_CH1 FALSE
+#endif
+#if !defined(STM32_HAS_DAC4_CH2)
+#define STM32_HAS_DAC4_CH2 FALSE
+#endif
+
+#if STM32_DAC_USE_DAC1_CH1 && !STM32_HAS_DAC1_CH1
+#error "DAC1 CH1 not present in the selected device"
+#endif
+
+#if STM32_DAC_USE_DAC1_CH2 && !STM32_HAS_DAC1_CH2
+#error "DAC1 CH2 not present in the selected device"
+#endif
+
+#if STM32_DAC_USE_DAC2_CH1 && !STM32_HAS_DAC2_CH1
+#error "DAC2 CH1 not present in the selected device"
+#endif
+
+#if STM32_DAC_USE_DAC2_CH2 && !STM32_HAS_DAC2_CH2
+#error "DAC2 CH2 not present in the selected device"
+#endif
+
+#if STM32_DAC_USE_DAC3_CH1 && !STM32_HAS_DAC3_CH1
+#error "DAC3 CH1 not present in the selected device"
+#endif
+
+#if STM32_DAC_USE_DAC3_CH2 && !STM32_HAS_DAC3_CH2
+#error "DAC3 CH2 not present in the selected device"
+#endif
+
+#if STM32_DAC_USE_DAC4_CH1 && !STM32_HAS_DAC4_CH1
+#error "DAC4 CH1 not present in the selected device"
+#endif
+
+#if STM32_DAC_USE_DAC4_CH2 && !STM32_HAS_DAC4_CH2
+#error "DAC4 CH2 not present in the selected device"
+#endif
+
+#if (STM32_DAC_USE_DAC1_CH2 || STM32_DAC_USE_DAC2_CH2 || \
+ STM32_DAC_USE_DAC3_CH2 || STM32_DAC_USE_DAC4_CH2) && STM32_DAC_DUAL_MODE
+#error "DACx CH2 cannot be used independently in dual mode"
+#endif
+
+#if !STM32_DAC_USE_DAC1_CH1 && !STM32_DAC_USE_DAC1_CH2 && \
+ !STM32_DAC_USE_DAC2_CH1 && !STM32_DAC_USE_DAC2_CH2 && \
+ !STM32_DAC_USE_DAC3_CH1 && !STM32_DAC_USE_DAC3_CH2 && \
+ !STM32_DAC_USE_DAC4_CH1 && !STM32_DAC_USE_DAC4_CH2
+#error "DAC driver activated but no DAC peripheral assigned"
+#endif
+
+#if STM32_DAC_USE_DAC1_CH1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC1_CH1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to DAC1 CH1"
+#endif
+
+#if STM32_DAC_USE_DAC1_CH2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC1_CH2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to DAC1 CH2"
+#endif
+
+#if STM32_DAC_USE_DAC2_CH1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC2_CH1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to DAC2 CH1"
+#endif
+
+#if STM32_DAC_USE_DAC2_CH2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC2_CH2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to DAC2 CH2"
+#endif
+
+#if STM32_DAC_USE_DAC3_CH1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC3_CH1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to DAC3 CH1"
+#endif
+
+#if STM32_DAC_USE_DAC3_CH2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC3_CH2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to DAC3 CH2"
+#endif
+
+#if STM32_DAC_USE_DAC4_CH1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC4_CH1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to DAC4 CH1"
+#endif
+
+#if STM32_DAC_USE_DAC4_CH2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_DAC_DAC4_CH2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to DAC4 CH2"
+#endif
+
+/* The following checks are only required when there is a DMA able to
+ reassign streams to different channels.*/
+#if STM32_ADVANCED_DMA
+
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if STM32_DAC_USE_DAC1_CH1 && !defined(STM32_DAC_DAC1_CH1_DMA_STREAM)
+#error "DAC1 CH1 DMA stream not defined"
+#endif
+
+#if STM32_DAC_USE_DAC1_CH2 && !defined(STM32_DAC_DAC1_CH2_DMA_STREAM)
+#error "DAC1 CH2 DMA stream not defined"
+#endif
+
+#if STM32_DAC_USE_DAC2_CH1 && !defined(STM32_DAC_DAC2_CH1_DMA_STREAM)
+#error "DAC2 CH1 DMA stream not defined"
+#endif
+
+#if STM32_DAC_USE_DAC2_CH2 && !defined(STM32_DAC_DAC2_CH2_DMA_STREAM)
+#error "DAC2 CH2 DMA stream not defined"
+#endif
+
+#if STM32_DAC_USE_DAC3_CH1 && !defined(STM32_DAC_DAC3_CH1_DMA_STREAM)
+#error "DAC3 CH1 DMA stream not defined"
+#endif
+
+#if STM32_DAC_USE_DAC3_CH2 && !defined(STM32_DAC_DAC3_CH2_DMA_STREAM)
+#error "DAC3 CH2 DMA stream not defined"
+#endif
+
+#if STM32_DAC_USE_DAC4_CH1 && !defined(STM32_DAC_DAC4_CH1_DMA_STREAM)
+#error "DAC4 CH1 DMA stream not defined"
+#endif
+
+#if STM32_DAC_USE_DAC4_CH2 && !defined(STM32_DAC_DAC4_CH2_DMA_STREAM)
+#error "DAC4 CH2 DMA stream not defined"
+#endif
+
+#if STM32_DMA_SUPPORTS_DMAMUX
+
+#else /* !STM32_DMA_SUPPORTS_DMAMUX */
+
+/* Check on the validity of the assigned DMA streams.*/
+#if STM32_DAC_USE_DAC1_CH1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC1_CH1_DMA_STREAM, STM32_DAC1_CH1_DMA_MSK)
+#error "invalid DMA stream associated to DAC1 CH1"
+#endif
+
+#if STM32_DAC_USE_DAC1_CH2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC1_CH2_DMA_STREAM, STM32_DAC1_CH2_DMA_MSK)
+#error "invalid DMA stream associated to DAC1 CH2"
+#endif
+
+#if STM32_DAC_USE_DAC2_CH1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC2_CH1_DMA_STREAM, STM32_DAC2_CH1_DMA_MSK)
+#error "invalid DMA stream associated to DAC2 CH1"
+#endif
+
+#if STM32_DAC_USE_DAC2_CH2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC2_CH2_DMA_STREAM, STM32_DAC2_CH2_DMA_MSK)
+#error "invalid DMA stream associated to DAC2 CH2"
+#endif
+
+#if STM32_DAC_USE_DAC3_CH1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC3_CH1_DMA_STREAM, STM32_DAC3_CH1_DMA_MSK)
+#error "invalid DMA stream associated to DAC1 CH1"
+#endif
+
+#if STM32_DAC_USE_DAC3_CH2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC3_CH2_DMA_STREAM, STM32_DAC3_CH2_DMA_MSK)
+#error "invalid DMA stream associated to DAC1 CH2"
+#endif
+
+#if STM32_DAC_USE_DAC4_CH1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC4_CH1_DMA_STREAM, STM32_DAC4_CH1_DMA_MSK)
+#error "invalid DMA stream associated to DAC2 CH1"
+#endif
+
+#if STM32_DAC_USE_DAC4_CH2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_DAC_DAC4_CH2_DMA_STREAM, STM32_DAC4_CH2_DMA_MSK)
+#error "invalid DMA stream associated to DAC2 CH2"
+#endif
+
+#endif /* !STM32_DMA_SUPPORTS_DMAMUX */
+
+#endif /* STM32_ADVANCED_DMA */
+
+#if STM32_DAC_USE_DAC1_CH1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC1_CH1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to DAC1 CH1"
+#endif
+
+#if STM32_DAC_USE_DAC1_CH2 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC1_CH2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to DAC1 CH2"
+#endif
+
+#if STM32_DAC_USE_DAC2_CH1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC2_CH1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to DAC2 CH1"
+#endif
+
+#if STM32_DAC_USE_DAC2_CH2 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC2_CH2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to DAC2 CH2"
+#endif
+
+#if STM32_DAC_USE_DAC3_CH1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC3_CH1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to DAC3 CH1"
+#endif
+
+#if STM32_DAC_USE_DAC3_CH2 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC3_CH2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to DAC3 CH2"
+#endif
+
+#if STM32_DAC_USE_DAC4_CH1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC4_CH1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to DAC4 CH1"
+#endif
+
+#if STM32_DAC_USE_DAC4_CH2 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_DAC_DAC4_CH2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to DAC4 CH2"
+#endif
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+/**
+ * @brief Max DAC channels.
+ */
+#if STM32_DAC_DUAL_MODE == FALSE
+#define DAC_MAX_CHANNELS 2
+#else
+#define DAC_MAX_CHANNELS 1
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a DAC channel index.
+ */
+typedef uint32_t dacchannel_t;
+
+/**
+ * @brief Type representing a DAC sample.
+ */
+typedef uint16_t dacsample_t;
+
+/**
+ * @brief DAC channel parameters type.
+ */
+typedef struct {
+ /**
+ * @brief Pointer to the DAC registers block.
+ */
+ DAC_TypeDef *dac;
+ /**
+ * @brief DAC data registers offset.
+ */
+ uint32_t dataoffset;
+ /**
+ * @brief DAC CR register bit offset.
+ */
+ uint32_t regshift;
+ /**
+ * @brief DAC CR register mask.
+ */
+ uint32_t regmask;
+ /**
+ * @brief Associated DMA stream.
+ */
+ uint32_t dmastream;
+ /**
+ * @brief Mode bits for the DMA.
+ */
+ uint32_t dmamode;
+ /**
+ * @brief DMA channel IRQ priority.
+ */
+ uint32_t dmairqprio;
+#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief DMAMUX peripheral selector.
+ */
+ uint32_t peripheral;
+#endif
+} dacparams_t;
+
+/**
+ * @brief Possible DAC failure causes.
+ * @note Error codes are architecture dependent and should not relied
+ * upon.
+ */
+typedef enum {
+ DAC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */
+ DAC_ERR_UNDERFLOW = 1 /**< DAC overflow condition. */
+} dacerror_t;
+
+/**
+ * @brief Samples alignment and size mode.
+ */
+typedef enum {
+ DAC_DHRM_12BIT_RIGHT = 0,
+ DAC_DHRM_12BIT_LEFT = 1,
+ DAC_DHRM_8BIT_RIGHT = 2,
+#if STM32_DAC_DUAL_MODE && !defined(__DOXYGEN__)
+ DAC_DHRM_12BIT_RIGHT_DUAL = 3,
+ DAC_DHRM_12BIT_LEFT_DUAL = 4,
+ DAC_DHRM_8BIT_RIGHT_DUAL = 5
+#endif
+} dacdhrmode_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the DAC driver structure.
+ */
+#define dac_lld_driver_fields \
+ /* DAC channel parameters.*/ \
+ const dacparams_t *params; \
+ /* Associated DMA.*/ \
+ const stm32_dma_stream_t *dma
+
+/**
+ * @brief Low level fields of the DAC configuration structure.
+ */
+#define dac_lld_config_fields \
+ /* Initial output on DAC channels.*/ \
+ dacsample_t init; \
+ /* DAC data holding register mode.*/ \
+ dacdhrmode_t datamode; \
+ /* DAC control register lower 16 bits.*/ \
+ uint32_t cr
+
+/**
+ * @brief Low level fields of the DAC group configuration structure.
+ */
+#define dac_lld_conversion_group_fields \
+ /* DAC initialization data. This field contains the (not shifted) value \
+ to be put into the TSEL field of the DAC CR register during \
+ initialization. All other fields are handled internally.*/ \
+ uint32_t trigger
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_DAC_USE_DAC1_CH1 && !defined(__DOXYGEN__)
+extern DACDriver DACD1;
+#endif
+
+#if STM32_DAC_USE_DAC1_CH2 && !STM32_DAC_DUAL_MODE && !defined(__DOXYGEN__)
+extern DACDriver DACD2;
+#endif
+
+#if STM32_DAC_USE_DAC2_CH1 && !defined(__DOXYGEN__)
+extern DACDriver DACD3;
+#endif
+
+#if STM32_DAC_USE_DAC2_CH2 && !STM32_DAC_DUAL_MODE && !defined(__DOXYGEN__)
+extern DACDriver DACD4;
+#endif
+
+#if STM32_DAC_USE_DAC3_CH1 && !defined(__DOXYGEN__)
+extern DACDriver DACD5;
+#endif
+
+#if STM32_DAC_USE_DAC3_CH2 && !STM32_DAC_DUAL_MODE && !defined(__DOXYGEN__)
+extern DACDriver DACD6;
+#endif
+
+#if STM32_DAC_USE_DAC4_CH1 && !defined(__DOXYGEN__)
+extern DACDriver DACD7;
+#endif
+
+#if STM32_DAC_USE_DAC4_CH2 && !STM32_DAC_DUAL_MODE && !defined(__DOXYGEN__)
+extern DACDriver DACD8;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void dac_lld_init(void);
+ void dac_lld_start(DACDriver *dacp);
+ void dac_lld_stop(DACDriver *dacp);
+ void dac_lld_put_channel(DACDriver *dacp,
+ dacchannel_t channel,
+ dacsample_t sample);
+ void dac_lld_start_conversion(DACDriver *dacp);
+ void dac_lld_stop_conversion(DACDriver *dacp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_DAC */
+
+#endif /* HAL_DAC_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv1/driver.mk
new file mode 100644
index 0000000..6080cec
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv1/driver.mk
@@ -0,0 +1,2 @@
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv1/notes.txt b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv1/notes.txt
new file mode 100644
index 0000000..dc46638
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv1/notes.txt
@@ -0,0 +1,26 @@
+STM32 DMAv1 driver.
+
+Driver capability:
+
+- The driver supports the STM32 traditional DMA controller in the following
+ configurations: 5ch, 7ch, 7ch+5ch, 7ch+7ch.
+- Support for automatic the channel selection through the CSELR register.
+- For devices without CSELR register it is possible to select channels but
+ the SYSCFG CFGR register is not configured, the user has to configure it
+ before starting the DMA driver.
+- The driver supports shared ISR handlers with a quirk: the IRQ priority is
+ established by the first allocated channel among the channels sharing the
+ ISR.
+
+The file registry must export:
+
+STM32_ADVANCED_DMA - TRUE not used by the DMA drivers but other
+ drivers use it to enable checks on DMA
+ channels. Probably will be removed in the
+ future.
+STM32_DMA_SUPPORTS_CSELR - TRUE if the DMA have a CSELR register.
+STM32_DMA_SUPPORTS_DMAMUX - TRUE if the DMA is riven by a DMAMUX.
+STM32_DMAn_NUM_CHANNELS - Number of channels in DMAs "n" (1..2).
+STM32_DMAn_CHx_HANDLER - Vector name for IRQ "x" (1..7). If the macro
+ is not exported then the ISR is not declared.
+STM32_DMAn_CHx_NUMBER - Vector number for IRQ "x" (1..7).
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c
new file mode 100644
index 0000000..141b4ff
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c
@@ -0,0 +1,816 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file DMAv1/stm32_dma.c
+ * @brief DMA helper driver code.
+ *
+ * @addtogroup STM32_DMA
+ * @details DMA sharing helper driver. In the STM32 the DMA streams are a
+ * shared resource, this driver allows to allocate and free DMA
+ * streams at runtime in order to allow all the other device
+ * drivers to coordinate the access to the resource.
+ * @note The DMA ISR handlers are all declared into this module because
+ * sharing, the various device drivers can associate a callback to
+ * ISRs when allocating streams.
+ * @{
+ */
+
+#include "hal.h"
+
+/* The following macro is only defined if some driver requiring DMA services
+ has been enabled.*/
+#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/**
+ * @brief Mask of the DMA1 streams in @p dma_streams_mask.
+ */
+#define STM32_DMA1_STREAMS_MASK ((1U << STM32_DMA1_NUM_CHANNELS) - 1U)
+
+/**
+ * @brief Mask of the DMA2 streams in @p dma_streams_mask.
+ */
+#define STM32_DMA2_STREAMS_MASK (((1U << STM32_DMA2_NUM_CHANNELS) - \
+ 1U) << STM32_DMA1_NUM_CHANNELS)
+
+#if STM32_DMA_SUPPORTS_CSELR == TRUE
+
+#if defined(DMA1_CSELR)
+#define __DMA1_CSELR &DMA1_CSELR->CSELR
+#else
+#define __DMA1_CSELR &DMA1->CSELR
+#endif
+
+#if defined(DMA2_CSELR)
+#define __DMA2_CSELR &DMA2_CSELR->CSELR
+#else
+#define __DMA2_CSELR &DMA2->CSELR
+#endif
+
+#define DMA1_CH1_VARIANT __DMA1_CSELR
+#define DMA1_CH2_VARIANT __DMA1_CSELR
+#define DMA1_CH3_VARIANT __DMA1_CSELR
+#define DMA1_CH4_VARIANT __DMA1_CSELR
+#define DMA1_CH5_VARIANT __DMA1_CSELR
+#define DMA1_CH6_VARIANT __DMA1_CSELR
+#define DMA1_CH7_VARIANT __DMA1_CSELR
+#define DMA1_CH8_VARIANT __DMA1_CSELR
+#define DMA2_CH1_VARIANT __DMA2_CSELR
+#define DMA2_CH2_VARIANT __DMA2_CSELR
+#define DMA2_CH3_VARIANT __DMA2_CSELR
+#define DMA2_CH4_VARIANT __DMA2_CSELR
+#define DMA2_CH5_VARIANT __DMA2_CSELR
+#define DMA2_CH6_VARIANT __DMA2_CSELR
+#define DMA2_CH7_VARIANT __DMA2_CSELR
+#define DMA2_CH8_VARIANT __DMA2_CSELR
+
+#elif STM32_DMA_SUPPORTS_DMAMUX == TRUE
+
+#define DMAMUX1_CHANNEL(id) (DMAMUX1_BASE + ((id) * 4U))
+
+#define DMA1_CH1_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(0))
+#define DMA1_CH2_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(1))
+#define DMA1_CH3_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(2))
+#define DMA1_CH4_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(3))
+#define DMA1_CH5_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(4))
+#define DMA1_CH6_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(5))
+#define DMA1_CH7_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(6))
+#define DMA1_CH8_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(7))
+#define DMA2_CH1_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(8))
+#define DMA2_CH2_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(9))
+#define DMA2_CH3_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(10))
+#define DMA2_CH4_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(11))
+#define DMA2_CH5_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(12))
+#define DMA2_CH6_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(13))
+#define DMA2_CH7_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(14))
+#define DMA2_CH8_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(15))
+
+#else /* !(STM32_DMA_SUPPORTS_DMAMUX == TRUE) */
+
+#define DMA1_CH1_VARIANT 0
+#define DMA1_CH2_VARIANT 0
+#define DMA1_CH3_VARIANT 0
+#define DMA1_CH4_VARIANT 0
+#define DMA1_CH5_VARIANT 0
+#define DMA1_CH6_VARIANT 0
+#define DMA1_CH7_VARIANT 0
+#define DMA2_CH1_VARIANT 0
+#define DMA2_CH2_VARIANT 0
+#define DMA2_CH3_VARIANT 0
+#define DMA2_CH4_VARIANT 0
+#define DMA2_CH5_VARIANT 0
+#define DMA2_CH6_VARIANT 0
+#define DMA2_CH7_VARIANT 0
+
+#endif /* !(STM32_DMA_SUPPORTS_DMAMUX == TRUE) */
+
+/*
+ * Default ISR collision masks.
+ */
+#if !defined(STM32_DMA1_CH1_CMASK)
+#define STM32_DMA1_CH1_CMASK (1U << 0U)
+#endif
+
+#if !defined(STM32_DMA1_CH2_CMASK)
+#define STM32_DMA1_CH2_CMASK (1U << 1U)
+#endif
+
+#if !defined(STM32_DMA1_CH3_CMASK)
+#define STM32_DMA1_CH3_CMASK (1U << 2U)
+#endif
+
+#if !defined(STM32_DMA1_CH4_CMASK)
+#define STM32_DMA1_CH4_CMASK (1U << 3U)
+#endif
+
+#if !defined(STM32_DMA1_CH5_CMASK)
+#define STM32_DMA1_CH5_CMASK (1U << 4U)
+#endif
+
+#if !defined(STM32_DMA1_CH6_CMASK)
+#define STM32_DMA1_CH6_CMASK (1U << 5U)
+#endif
+
+#if !defined(STM32_DMA1_CH7_CMASK)
+#define STM32_DMA1_CH7_CMASK (1U << 6U)
+#endif
+
+#if !defined(STM32_DMA1_CH8_CMASK)
+#define STM32_DMA1_CH8_CMASK (1U << 7U)
+#endif
+
+#if !defined(STM32_DMA2_CH1_CMASK)
+#define STM32_DMA2_CH1_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 0U))
+#endif
+
+#if !defined(STM32_DMA2_CH2_CMASK)
+#define STM32_DMA2_CH2_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 1U))
+#endif
+
+#if !defined(STM32_DMA2_CH3_CMASK)
+#define STM32_DMA2_CH3_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 2U))
+#endif
+
+#if !defined(STM32_DMA2_CH4_CMASK)
+#define STM32_DMA2_CH4_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 3U))
+#endif
+
+#if !defined(STM32_DMA2_CH5_CMASK)
+#define STM32_DMA2_CH5_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 4U))
+#endif
+
+#if !defined(STM32_DMA2_CH6_CMASK)
+#define STM32_DMA2_CH6_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 5U))
+#endif
+
+#if !defined(STM32_DMA2_CH7_CMASK)
+#define STM32_DMA2_CH7_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 6U))
+#endif
+
+#if !defined(STM32_DMA2_CH8_CMASK)
+#define STM32_DMA2_CH8_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 7U))
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief DMA streams descriptors.
+ * @details This table keeps the association between an unique stream
+ * identifier and the involved physical registers.
+ * @note Don't use this array directly, use the appropriate wrapper macros
+ * instead: @p STM32_DMA1_STREAM1, @p STM32_DMA1_STREAM2 etc.
+ */
+const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = {
+#if STM32_DMA1_NUM_CHANNELS > 0
+ {DMA1, DMA1_Channel1, STM32_DMA1_CH1_CMASK, DMA1_CH1_VARIANT, 0, 0, STM32_DMA1_CH1_NUMBER},
+#endif
+#if STM32_DMA1_NUM_CHANNELS > 1
+ {DMA1, DMA1_Channel2, STM32_DMA1_CH2_CMASK, DMA1_CH2_VARIANT, 4, 1, STM32_DMA1_CH2_NUMBER},
+#endif
+#if STM32_DMA1_NUM_CHANNELS > 2
+ {DMA1, DMA1_Channel3, STM32_DMA1_CH3_CMASK, DMA1_CH3_VARIANT, 8, 2, STM32_DMA1_CH3_NUMBER},
+#endif
+#if STM32_DMA1_NUM_CHANNELS > 3
+ {DMA1, DMA1_Channel4, STM32_DMA1_CH4_CMASK, DMA1_CH4_VARIANT, 12, 3, STM32_DMA1_CH4_NUMBER},
+#endif
+#if STM32_DMA1_NUM_CHANNELS > 4
+ {DMA1, DMA1_Channel5, STM32_DMA1_CH5_CMASK, DMA1_CH5_VARIANT, 16, 4, STM32_DMA1_CH5_NUMBER},
+#endif
+#if STM32_DMA1_NUM_CHANNELS > 5
+ {DMA1, DMA1_Channel6, STM32_DMA1_CH6_CMASK, DMA1_CH6_VARIANT, 20, 5, STM32_DMA1_CH6_NUMBER},
+#endif
+#if STM32_DMA1_NUM_CHANNELS > 6
+ {DMA1, DMA1_Channel7, STM32_DMA1_CH7_CMASK, DMA1_CH7_VARIANT, 24, 6, STM32_DMA1_CH7_NUMBER},
+#endif
+#if STM32_DMA1_NUM_CHANNELS > 7
+ {DMA1, DMA1_Channel8, STM32_DMA1_CH8_CMASK, DMA1_CH8_VARIANT, 28, 7, STM32_DMA1_CH8_NUMBER},
+#endif
+#if STM32_DMA2_NUM_CHANNELS > 0
+ {DMA2, DMA2_Channel1, STM32_DMA2_CH1_CMASK, DMA2_CH1_VARIANT, 0, 0 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH1_NUMBER},
+#endif
+#if STM32_DMA2_NUM_CHANNELS > 1
+ {DMA2, DMA2_Channel2, STM32_DMA2_CH2_CMASK, DMA2_CH2_VARIANT, 4, 1 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH2_NUMBER},
+#endif
+#if STM32_DMA2_NUM_CHANNELS > 2
+ {DMA2, DMA2_Channel3, STM32_DMA2_CH3_CMASK, DMA2_CH3_VARIANT, 8, 2 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH3_NUMBER},
+#endif
+#if STM32_DMA2_NUM_CHANNELS > 3
+ {DMA2, DMA2_Channel4, STM32_DMA2_CH4_CMASK, DMA2_CH4_VARIANT, 12, 3 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH4_NUMBER},
+#endif
+#if STM32_DMA2_NUM_CHANNELS > 4
+ {DMA2, DMA2_Channel5, STM32_DMA2_CH5_CMASK, DMA2_CH5_VARIANT, 16, 4 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH5_NUMBER},
+#endif
+#if STM32_DMA2_NUM_CHANNELS > 5
+ {DMA2, DMA2_Channel6, STM32_DMA2_CH6_CMASK, DMA2_CH6_VARIANT, 20, 5 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH6_NUMBER},
+#endif
+#if STM32_DMA2_NUM_CHANNELS > 6
+ {DMA2, DMA2_Channel7, STM32_DMA2_CH7_CMASK, DMA2_CH7_VARIANT, 24, 6 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH7_NUMBER},
+#endif
+#if STM32_DMA2_NUM_CHANNELS > 7
+ {DMA2, DMA2_Channel8, STM32_DMA2_CH8_CMASK, DMA2_CH8_VARIANT, 28, 7 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH8_NUMBER},
+#endif
+};
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Global DMA-related data structures.
+ */
+static struct {
+ /**
+ * @brief Mask of the allocated streams.
+ */
+ uint32_t allocated_mask;
+ /**
+ * @brief Mask of the enabled streams ISRs.
+ */
+ uint32_t isr_mask;
+ /**
+ * @brief DMA IRQ redirectors.
+ */
+ struct {
+ /**
+ * @brief DMA callback function.
+ */
+ stm32_dmaisr_t func;
+ /**
+ * @brief DMA callback parameter.
+ */
+ void *param;
+ } streams[STM32_DMA_STREAMS];
+} dma;
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_DMA1_CH1_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA1 stream 1 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA1_CH1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(STM32_DMA1_STREAM1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_DMA1_CH2_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA1 stream 2 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA1_CH2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(STM32_DMA1_STREAM2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_DMA1_CH3_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA1 stream 3 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA1_CH3_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(STM32_DMA1_STREAM3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_DMA1_CH4_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA1 stream 4 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA1_CH4_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(STM32_DMA1_STREAM4);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_DMA1_CH5_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA1 stream 5 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA1_CH5_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(STM32_DMA1_STREAM5);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_DMA1_CH6_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA1 stream 6 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA1_CH6_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(STM32_DMA1_STREAM6);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_DMA1_CH7_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA1 stream 7 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA1_CH7_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(STM32_DMA1_STREAM7);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_DMA1_CH8_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA1 stream 8 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA1_CH8_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(STM32_DMA1_STREAM8);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_DMA2_CH1_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA2 stream 1 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA2_CH1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(STM32_DMA2_STREAM1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_DMA2_CH2_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA2 stream 2 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA2_CH2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(STM32_DMA2_STREAM2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_DMA2_CH3_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA2 stream 3 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA2_CH3_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(STM32_DMA2_STREAM3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_DMA2_CH4_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA2 stream 4 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA2_CH4_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(STM32_DMA2_STREAM4);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_DMA2_CH5_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA2 stream 5 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA2_CH5_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(STM32_DMA2_STREAM5);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_DMA2_CH6_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA2 stream 6 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA2_CH6_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(STM32_DMA2_STREAM6);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_DMA2_CH7_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA2 stream 7 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA2_CH7_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(STM32_DMA2_STREAM7);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_DMA2_CH8_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief DMA2 stream 8 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA2_CH8_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmaServeInterrupt(STM32_DMA2_STREAM8);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 DMA helper initialization.
+ *
+ * @init
+ */
+void dmaInit(void) {
+ int i;
+
+ dma.allocated_mask = 0U;
+ dma.isr_mask = 0U;
+ for (i = 0; i < STM32_DMA_STREAMS; i++) {
+ _stm32_dma_streams[i].channel->CCR = STM32_DMA_CCR_RESET_VALUE;
+ dma.streams[i].func = NULL;
+ }
+ DMA1->IFCR = 0xFFFFFFFFU;
+#if STM32_DMA2_NUM_CHANNELS > 0
+ DMA2->IFCR = 0xFFFFFFFFU;
+#endif
+}
+
+/**
+ * @brief Allocates a DMA stream.
+ * @details The stream is allocated and, if required, the DMA clock enabled.
+ * The function also enables the IRQ vector associated to the stream
+ * and initializes its priority.
+ *
+ * @param[in] id numeric identifiers of a specific stream or:
+ * - @p STM32_DMA_STREAM_ID_ANY for any stream.
+ * - @p STM32_DMA_STREAM_ID_ANY_DMA1 for any stream
+ * on DMA1.
+ * - @p STM32_DMA_STREAM_ID_ANY_DMA2 for any stream
+ * on DMA2.
+ * .
+ * @param[in] priority IRQ priority for the DMA stream
+ * @param[in] func handling function pointer, can be @p NULL
+ * @param[in] param a parameter to be passed to the handling function
+ * @return Pointer to the allocated @p stm32_dma_stream_t
+ * structure.
+ * @retval NULL if a/the stream is not available.
+ *
+ * @iclass
+ */
+const stm32_dma_stream_t *dmaStreamAllocI(uint32_t id,
+ uint32_t priority,
+ stm32_dmaisr_t func,
+ void *param) {
+ uint32_t i, startid, endid;
+
+ osalDbgCheckClassI();
+
+ if (id < STM32_DMA_STREAMS) {
+ startid = id;
+ endid = id;
+ }
+#if STM32_DMA_SUPPORTS_DMAMUX == TRUE
+ else if (id == STM32_DMA_STREAM_ID_ANY) {
+ startid = 0U;
+ endid = STM32_DMA_STREAMS - 1U;
+ }
+ else if (id == STM32_DMA_STREAM_ID_ANY_DMA1) {
+ startid = 0U;
+ endid = STM32_DMA1_NUM_CHANNELS - 1U;
+ }
+#if STM32_DMA2_NUM_CHANNELS > 0
+ else if (id == STM32_DMA_STREAM_ID_ANY_DMA2) {
+ startid = STM32_DMA1_NUM_CHANNELS;
+ endid = STM32_DMA_STREAMS - 1U;
+ }
+#endif
+#endif
+ else {
+ osalDbgCheck(false);
+ return NULL;
+ }
+
+ for (i = startid; i <= endid; i++) {
+ uint32_t mask = (1U << i);
+ if ((dma.allocated_mask & mask) == 0U) {
+ const stm32_dma_stream_t *dmastp = STM32_DMA_STREAM(i);
+
+ /* Installs the DMA handler.*/
+ dma.streams[i].func = func;
+ dma.streams[i].param = param;
+ dma.allocated_mask |= mask;
+
+ /* Enabling DMA clocks required by the current streams set.*/
+ if ((STM32_DMA1_STREAMS_MASK & mask) != 0U) {
+ rccEnableDMA1(true);
+ }
+#if STM32_DMA2_NUM_CHANNELS > 0
+ if ((STM32_DMA2_STREAMS_MASK & mask) != 0U) {
+ rccEnableDMA2(true);
+ }
+#endif
+
+#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && defined(rccEnableDMAMUX)
+ /* Enabling DMAMUX if present.*/
+ if (dma.allocated_mask != 0U) {
+ rccEnableDMAMUX(true);
+ }
+#endif
+
+ /* Enables the associated IRQ vector if not already enabled and if a
+ callback is defined.*/
+ if (func != NULL) {
+ if ((dma.isr_mask & dmastp->cmask) == 0U) {
+ nvicEnableVector(dmastp->vector, priority);
+ }
+ dma.isr_mask |= mask;
+ }
+
+ /* Putting the stream in a known state.*/
+ dmaStreamDisable(dmastp);
+ dmastp->channel->CCR = STM32_DMA_CCR_RESET_VALUE;
+
+ return dmastp;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * @brief Allocates a DMA stream.
+ * @details The stream is allocated and, if required, the DMA clock enabled.
+ * The function also enables the IRQ vector associated to the stream
+ * and initializes its priority.
+ *
+ * @param[in] id numeric identifiers of a specific stream or:
+ * - @p STM32_DMA_STREAM_ID_ANY for any stream.
+ * - @p STM32_DMA_STREAM_ID_ANY_DMA1 for any stream
+ * on DMA1.
+ * - @p STM32_DMA_STREAM_ID_ANY_DMA2 for any stream
+ * on DMA2.
+ * .
+ * @param[in] priority IRQ priority for the DMA stream
+ * @param[in] func handling function pointer, can be @p NULL
+ * @param[in] param a parameter to be passed to the handling function
+ * @return Pointer to the allocated @p stm32_dma_stream_t
+ * structure.
+ * @retval NULL if a/the stream is not available.
+ *
+ * @api
+ */
+const stm32_dma_stream_t *dmaStreamAlloc(uint32_t id,
+ uint32_t priority,
+ stm32_dmaisr_t func,
+ void *param) {
+ const stm32_dma_stream_t *dmastp;
+
+ osalSysLock();
+ dmastp = dmaStreamAllocI(id, priority, func, param);
+ osalSysUnlock();
+
+ return dmastp;
+}
+
+/**
+ * @brief Releases a DMA stream.
+ * @details The stream is freed and, if required, the DMA clock disabled.
+ * Trying to release a unallocated stream is an illegal operation
+ * and is trapped if assertions are enabled.
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @iclass
+ */
+void dmaStreamFreeI(const stm32_dma_stream_t *dmastp) {
+ uint32_t selfindex = (uint32_t)dmastp->selfindex;
+
+ osalDbgCheck(dmastp != NULL);
+
+ /* Check if the streams is not taken.*/
+ osalDbgAssert((dma.allocated_mask & (1 << selfindex)) != 0U,
+ "not allocated");
+
+ /* Marks the stream as not allocated.*/
+ dma.allocated_mask &= ~(1U << selfindex);
+ dma.isr_mask &= ~(1U << selfindex);
+
+ /* Disables the associated IRQ vector if it is no more in use.*/
+ if ((dma.isr_mask & dmastp->cmask) == 0U) {
+ nvicDisableVector(dmastp->vector);
+ }
+
+ /* Removes the DMA handler.*/
+ dma.streams[selfindex].func = NULL;
+ dma.streams[selfindex].param = NULL;
+
+ /* Shutting down clocks that are no more required, if any.*/
+ if ((dma.allocated_mask & STM32_DMA1_STREAMS_MASK) == 0U) {
+ rccDisableDMA1();
+ }
+#if STM32_DMA2_NUM_CHANNELS > 0
+ if ((dma.allocated_mask & STM32_DMA2_STREAMS_MASK) == 0U) {
+ rccDisableDMA2();
+ }
+#endif
+
+#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && defined(rccDisableDMAMUX)
+ /* Shutting down DMAMUX if present.*/
+ if (dma.allocated_mask == 0U) {
+ rccDisableDMAMUX();
+ }
+#endif
+}
+
+/**
+ * @brief Releases a DMA stream.
+ * @details The stream is freed and, if required, the DMA clock disabled.
+ * Trying to release a unallocated stream is an illegal operation
+ * and is trapped if assertions are enabled.
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @api
+ */
+void dmaStreamFree(const stm32_dma_stream_t *dmastp) {
+
+ osalSysLock();
+ dmaStreamFreeI(dmastp);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Serves a DMA IRQ.
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @special
+ */
+void dmaServeInterrupt(const stm32_dma_stream_t *dmastp) {
+ uint32_t flags;
+ uint32_t selfindex = (uint32_t)dmastp->selfindex;
+
+ flags = (dmastp->dma->ISR >> dmastp->shift) & STM32_DMA_ISR_MASK;
+ if (flags & dmastp->channel->CCR) {
+ dmastp->dma->IFCR = flags << dmastp->shift;
+ if (dma.streams[selfindex].func) {
+ dma.streams[selfindex].func(dma.streams[selfindex].param, flags);
+ }
+ }
+}
+
+#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Associates a peripheral request to a DMA stream.
+ * @note This function can be invoked in both ISR or thread context.
+ *
+ * @param[in] dmastp pointer to a @p stm32_dma_stream_t structure
+ * @param[in] per peripheral identifier
+ *
+ * @special
+ */
+void dmaSetRequestSource(const stm32_dma_stream_t *dmastp, uint32_t per) {
+
+ osalDbgCheck(per < 256U);
+
+ dmastp->mux->CCR = per;
+}
+#endif
+
+#endif /* STM32_DMA_REQUIRED */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.h
new file mode 100644
index 0000000..54b6bde
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.h
@@ -0,0 +1,554 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file DMAv1/stm32_dma.h
+ * @brief DMA helper driver header.
+ * @note This driver uses the new naming convention used for the STM32F2xx
+ * so the "DMA channels" are referred as "DMA streams".
+ *
+ * @addtogroup STM32_DMA
+ * @{
+ */
+
+#ifndef STM32_DMA_H
+#define STM32_DMA_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief DMA capability.
+ * @details if @p TRUE then the DMA is able of burst transfers, FIFOs,
+ * scatter gather and other advanced features.
+ */
+#define STM32_DMA_ADVANCED FALSE
+
+/**
+ * @brief Total number of DMA streams.
+ * @details This is the total number of streams among all the DMA units.
+ */
+#define STM32_DMA_STREAMS (STM32_DMA1_NUM_CHANNELS + \
+ STM32_DMA2_NUM_CHANNELS)
+
+/**
+ * @brief Mask of the ISR bits passed to the DMA callback functions.
+ */
+#define STM32_DMA_ISR_MASK 0x0E
+
+/**
+ * @brief Returns the request line associated to the specified stream.
+ * @note In some STM32 manuals the request line is named confusingly
+ * channel.
+ *
+ * @param[in] id the unique numeric stream identifier
+ * @param[in] c a stream/request association word, one request per
+ * nibble
+ * @return Returns the request associated to the stream.
+ */
+#define STM32_DMA_GETCHANNEL(id, c) \
+ (((uint32_t)(c) >> (((uint32_t)(id) % (uint32_t)STM32_DMA1_NUM_CHANNELS) * 4U)) & 15U)
+
+/**
+ * @brief Checks if a DMA priority is within the valid range.
+ * @param[in] prio DMA priority
+ *
+ * @retval The check result.
+ * @retval false invalid DMA priority.
+ * @retval true correct DMA priority.
+ */
+#define STM32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0U) && ((prio) <= 3U))
+
+#if (STM32_DMA_SUPPORTS_DMAMUX == FALSE) || defined(_DOXYGEN__)
+/**
+ * @brief Checks if a DMA stream id is within the valid range.
+ *
+ * @param[in] id DMA stream id
+ * @retval The check result.
+ * @retval false invalid DMA channel.
+ * @retval true correct DMA channel.
+ */
+#define STM32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \
+ ((id) < STM32_DMA_STREAMS))
+#else /* STM32_DMA_SUPPORTS_DMAMUX == FALSE */
+#if STM32_DMA2_NUM_CHANNELS > 0
+#define STM32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \
+ ((id) <= (STM32_DMA_STREAMS + 2)))
+#else
+#define STM32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \
+ ((id) <= (STM32_DMA_STREAMS + 1)))
+#endif
+#endif /* STM32_DMA_SUPPORTS_DMAMUX == FALSE */
+
+/**
+ * @brief Returns an unique numeric identifier for a DMA stream.
+ *
+ * @param[in] dma the DMA unit number
+ * @param[in] stream the stream number
+ * @return An unique numeric stream identifier.
+ */
+#define STM32_DMA_STREAM_ID(dma, stream) \
+ ((((dma) - 1) * STM32_DMA1_NUM_CHANNELS) + ((stream) - 1))
+
+/**
+ * @brief Returns a DMA stream identifier mask.
+ *
+ *
+ * @param[in] dma the DMA unit number
+ * @param[in] stream the stream number
+ * @return A DMA stream identifier mask.
+ */
+#define STM32_DMA_STREAM_ID_MSK(dma, stream) \
+ (1U << STM32_DMA_STREAM_ID(dma, stream))
+
+/**
+ * @brief Checks if a DMA stream unique identifier belongs to a mask.
+ *
+ * @param[in] id the stream numeric identifier
+ * @param[in] mask the stream numeric identifiers mask
+ *
+ * @retval The check result.
+ * @retval false id does not belong to the mask.
+ * @retval true id belongs to the mask.
+ */
+#define STM32_DMA_IS_VALID_ID(id, mask) (((1U << (id)) & (mask)))
+
+#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(_DOXYGEN__)
+/**
+ * @name Special stream identifiers
+ * @{
+ */
+#define STM32_DMA_STREAM_ID_ANY STM32_DMA_STREAMS
+#define STM32_DMA_STREAM_ID_ANY_DMA1 (STM32_DMA_STREAM_ID_ANY + 1)
+#if STM32_DMA2_NUM_CHANNELS > 0
+#define STM32_DMA_STREAM_ID_ANY_DMA2 (STM32_DMA_STREAM_ID_ANY_DMA1 + 1)
+#endif
+/** @} */
+#endif
+
+/**
+ * @name DMA streams identifiers
+ * @{
+ */
+/**
+ * @brief Returns a pointer to a stm32_dma_stream_t structure.
+ *
+ * @param[in] id the stream numeric identifier
+ * @return A pointer to the stm32_dma_stream_t constant structure
+ * associated to the DMA stream.
+ */
+#define STM32_DMA_STREAM(id) (&_stm32_dma_streams[id])
+
+#if STM32_DMA1_NUM_CHANNELS > 0
+#define STM32_DMA1_STREAM1 STM32_DMA_STREAM(0)
+#endif
+#if STM32_DMA1_NUM_CHANNELS > 1
+#define STM32_DMA1_STREAM2 STM32_DMA_STREAM(1)
+#endif
+#if STM32_DMA1_NUM_CHANNELS > 2
+#define STM32_DMA1_STREAM3 STM32_DMA_STREAM(2)
+#endif
+#if STM32_DMA1_NUM_CHANNELS > 3
+#define STM32_DMA1_STREAM4 STM32_DMA_STREAM(3)
+#endif
+#if STM32_DMA1_NUM_CHANNELS > 4
+#define STM32_DMA1_STREAM5 STM32_DMA_STREAM(4)
+#endif
+#if STM32_DMA1_NUM_CHANNELS > 5
+#define STM32_DMA1_STREAM6 STM32_DMA_STREAM(5)
+#endif
+#if STM32_DMA1_NUM_CHANNELS > 6
+#define STM32_DMA1_STREAM7 STM32_DMA_STREAM(6)
+#endif
+#if STM32_DMA1_NUM_CHANNELS > 7
+#define STM32_DMA1_STREAM8 STM32_DMA_STREAM(7)
+#endif
+#if STM32_DMA2_NUM_CHANNELS > 0
+#define STM32_DMA2_STREAM1 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 0)
+#endif
+#if STM32_DMA2_NUM_CHANNELS > 1
+#define STM32_DMA2_STREAM2 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 1)
+#endif
+#if STM32_DMA2_NUM_CHANNELS > 2
+#define STM32_DMA2_STREAM3 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 2)
+#endif
+#if STM32_DMA2_NUM_CHANNELS > 3
+#define STM32_DMA2_STREAM4 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 3)
+#endif
+#if STM32_DMA2_NUM_CHANNELS > 4
+#define STM32_DMA2_STREAM5 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 4)
+#endif
+#if STM32_DMA2_NUM_CHANNELS > 5
+#define STM32_DMA2_STREAM6 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 5)
+#endif
+#if STM32_DMA2_NUM_CHANNELS > 6
+#define STM32_DMA2_STREAM7 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 6)
+#endif
+#if STM32_DMA2_NUM_CHANNELS > 7
+#define STM32_DMA2_STREAM8 STM32_DMA_STREAM(STM32_DMA1_NUM_CHANNELS + 7)
+#endif
+/** @} */
+
+/**
+ * @name CR register constants common to all DMA types
+ * @{
+ */
+#define STM32_DMA_CCR_RESET_VALUE 0x00000000U
+#define STM32_DMA_CR_EN DMA_CCR_EN
+#define STM32_DMA_CR_TEIE DMA_CCR_TEIE
+#define STM32_DMA_CR_HTIE DMA_CCR_HTIE
+#define STM32_DMA_CR_TCIE DMA_CCR_TCIE
+#define STM32_DMA_CR_DIR_MASK (DMA_CCR_DIR | DMA_CCR_MEM2MEM)
+#define STM32_DMA_CR_DIR_P2M 0U
+#define STM32_DMA_CR_DIR_M2P DMA_CCR_DIR
+#define STM32_DMA_CR_DIR_M2M DMA_CCR_MEM2MEM
+#define STM32_DMA_CR_CIRC DMA_CCR_CIRC
+#define STM32_DMA_CR_PINC DMA_CCR_PINC
+#define STM32_DMA_CR_MINC DMA_CCR_MINC
+#define STM32_DMA_CR_PSIZE_MASK DMA_CCR_PSIZE
+#define STM32_DMA_CR_PSIZE_BYTE 0U
+#define STM32_DMA_CR_PSIZE_HWORD DMA_CCR_PSIZE_0
+#define STM32_DMA_CR_PSIZE_WORD DMA_CCR_PSIZE_1
+#define STM32_DMA_CR_MSIZE_MASK DMA_CCR_MSIZE
+#define STM32_DMA_CR_MSIZE_BYTE 0U
+#define STM32_DMA_CR_MSIZE_HWORD DMA_CCR_MSIZE_0
+#define STM32_DMA_CR_MSIZE_WORD DMA_CCR_MSIZE_1
+#define STM32_DMA_CR_SIZE_MASK (STM32_DMA_CR_PSIZE_MASK | \
+ STM32_DMA_CR_MSIZE_MASK)
+#define STM32_DMA_CR_PL_MASK DMA_CCR_PL
+#define STM32_DMA_CR_PL(n) ((n) << 12U)
+/** @} */
+
+/**
+ * @name Request line selector macro
+ * @{
+ */
+#if STM32_DMA_SUPPORTS_CSELR || defined(__DOXYGEN__)
+#define STM32_DMA_CR_CHSEL_MASK (15U << 16U)
+#define STM32_DMA_CR_CHSEL(n) ((n) << 16U)
+#else
+#define STM32_DMA_CR_CHSEL_MASK 0U
+#define STM32_DMA_CR_CHSEL(n) 0U
+#endif
+/** @} */
+
+/**
+ * @name CR register constants only found in enhanced DMA
+ * @{
+ */
+#define STM32_DMA_CR_DMEIE 0U /**< @brief Ignored by normal DMA. */
+/** @} */
+
+/**
+ * @name Status flags passed to the ISR callbacks
+ * @{
+ */
+#define STM32_DMA_ISR_FEIF 0U
+#define STM32_DMA_ISR_DMEIF 0U
+#define STM32_DMA_ISR_TEIF DMA_ISR_TEIF1
+#define STM32_DMA_ISR_HTIF DMA_ISR_HTIF1
+#define STM32_DMA_ISR_TCIF DMA_ISR_TCIF1
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !defined(STM32_DMA_SUPPORTS_DMAMUX)
+#error "STM32_DMA_SUPPORTS_DMAMUX not defined in registry"
+#endif
+
+#if !defined(STM32_DMA_SUPPORTS_CSELR)
+#error "STM32_DMA_SUPPORTS_CSELR not defined in registry"
+#endif
+
+#if STM32_DMA_SUPPORTS_DMAMUX && STM32_DMA_SUPPORTS_CSELR
+#error "STM32_DMA_SUPPORTS_DMAMUX and STM32_DMA_SUPPORTS_CSELR both TRUE"
+#endif
+
+#if !defined(STM32_DMA1_NUM_CHANNELS)
+#error "STM32_DMA1_NUM_CHANNELS not defined in registry"
+#endif
+
+#if !defined(STM32_DMA2_NUM_CHANNELS)
+#error "STM32_DMA2_NUM_CHANNELS not defined in registry"
+#endif
+
+#if (STM32_DMA1_NUM_CHANNELS < 0) || (STM32_DMA1_NUM_CHANNELS > 8)
+#error "unsupported channels configuration"
+#endif
+
+#if (STM32_DMA2_NUM_CHANNELS < 0) || (STM32_DMA2_NUM_CHANNELS > 8)
+#error "unsupported channels configuration"
+#endif
+
+#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__)
+#include "stm32_dmamux.h"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a DMA callback.
+ *
+ * @param[in] p parameter for the registered function
+ * @param[in] flags pre-shifted content of the ISR register, the bits
+ * are aligned to bit zero
+ */
+typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags);
+
+/**
+ * @brief STM32 DMA stream descriptor structure.
+ */
+typedef struct {
+ DMA_TypeDef *dma; /**< @brief Associated DMA. */
+ DMA_Channel_TypeDef *channel; /**< @brief Associated DMA channel. */
+ uint32_t cmask; /**< @brief Mask of streams sharing
+ the same ISR. */
+#if (STM32_DMA_SUPPORTS_CSELR == TRUE) || defined(__DOXYGEN__)
+ volatile uint32_t *cselr; /**< @brief Associated CSELR reg. */
+#elif STM32_DMA_SUPPORTS_DMAMUX == TRUE
+ DMAMUX_Channel_TypeDef *mux; /**< @brief Associated DMA mux. */
+#else
+ uint8_t dummy; /**< @brief Filler. */
+#endif
+ uint8_t shift; /**< @brief Bit offset in ISR, IFCR
+ and CSELR registers. */
+ uint8_t selfindex; /**< @brief Index to self in array. */
+ uint8_t vector; /**< @brief Associated IRQ vector. */
+} stm32_dma_stream_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Associates a peripheral data register to a DMA stream.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] addr value to be written in the CPAR register
+ *
+ * @special
+ */
+#define dmaStreamSetPeripheral(dmastp, addr) { \
+ (dmastp)->channel->CPAR = (uint32_t)(addr); \
+}
+
+/**
+ * @brief Associates a memory destination to a DMA stream.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] addr value to be written in the CMAR register
+ *
+ * @special
+ */
+#define dmaStreamSetMemory0(dmastp, addr) { \
+ (dmastp)->channel->CMAR = (uint32_t)(addr); \
+}
+
+/**
+ * @brief Sets the number of transfers to be performed.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] size value to be written in the CNDTR register
+ *
+ * @special
+ */
+#define dmaStreamSetTransactionSize(dmastp, size) { \
+ (dmastp)->channel->CNDTR = (uint32_t)(size); \
+}
+
+/**
+ * @brief Returns the number of transfers to be performed.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @return The number of transfers to be performed.
+ *
+ * @special
+ */
+#define dmaStreamGetTransactionSize(dmastp) ((size_t)((dmastp)->channel->CNDTR))
+
+/**
+ * @brief Programs the stream mode settings.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] mode value to be written in the CCR register
+ *
+ * @special
+ */
+#if STM32_DMA_SUPPORTS_CSELR || defined(__DOXYGEN__)
+#define dmaStreamSetMode(dmastp, mode) { \
+ uint32_t cselr = *(dmastp)->cselr; \
+ cselr &= ~(0x0000000FU << (dmastp)->shift); \
+ cselr |= (((uint32_t)(mode) >> 16U) << (dmastp)->shift); \
+ *(dmastp)->cselr = cselr; \
+ (dmastp)->channel->CCR = (uint32_t)(mode); \
+}
+#else
+#define dmaStreamSetMode(dmastp, mode) { \
+ (dmastp)->channel->CCR = (uint32_t)(mode); \
+}
+#endif
+
+/**
+ * @brief DMA stream enable.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @special
+ */
+#define dmaStreamEnable(dmastp) { \
+ (dmastp)->channel->CCR |= STM32_DMA_CR_EN; \
+}
+
+/**
+ * @brief DMA stream disable.
+ * @details The function disables the specified stream and then clears any
+ * pending interrupt.
+ * @note This function can be invoked in both ISR or thread context.
+ * @note Interrupts enabling flags are set to zero after this call, see
+ * bug 3607518.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @special
+ */
+#define dmaStreamDisable(dmastp) { \
+ (dmastp)->channel->CCR &= ~(STM32_DMA_CR_TCIE | STM32_DMA_CR_HTIE | \
+ STM32_DMA_CR_TEIE | STM32_DMA_CR_EN); \
+ dmaStreamClearInterrupt(dmastp); \
+}
+
+/**
+ * @brief DMA stream interrupt sources clear.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @special
+ */
+#define dmaStreamClearInterrupt(dmastp) { \
+ (dmastp)->dma->IFCR = STM32_DMA_ISR_MASK << (dmastp)->shift; \
+}
+
+/**
+ * @brief Starts a memory to memory operation using the specified stream.
+ * @note The default transfer data mode is "byte to byte" but it can be
+ * changed by specifying extra options in the @p mode parameter.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] mode value to be written in the CCR register, this value
+ * is implicitly ORed with:
+ * - @p STM32_DMA_CR_MINC
+ * - @p STM32_DMA_CR_PINC
+ * - @p STM32_DMA_CR_DIR_M2M
+ * - @p STM32_DMA_CR_EN
+ * .
+ * @param[in] src source address
+ * @param[in] dst destination address
+ * @param[in] n number of data units to copy
+ */
+#define dmaStartMemCopy(dmastp, mode, src, dst, n) { \
+ dmaStreamSetPeripheral(dmastp, src); \
+ dmaStreamSetMemory0(dmastp, dst); \
+ dmaStreamSetTransactionSize(dmastp, n); \
+ dmaStreamSetMode(dmastp, (mode) | \
+ STM32_DMA_CR_MINC | STM32_DMA_CR_PINC | \
+ STM32_DMA_CR_DIR_M2M | STM32_DMA_CR_EN); \
+}
+
+/**
+ * @brief Polled wait for DMA transfer end.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamRelease().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ */
+#define dmaWaitCompletion(dmastp) { \
+ while ((dmastp)->channel->CNDTR > 0U) \
+ ; \
+ dmaStreamDisable(dmastp); \
+}
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS];
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void dmaInit(void);
+ const stm32_dma_stream_t *dmaStreamAllocI(uint32_t id,
+ uint32_t priority,
+ stm32_dmaisr_t func,
+ void *param);
+ const stm32_dma_stream_t *dmaStreamAlloc(uint32_t id,
+ uint32_t priority,
+ stm32_dmaisr_t func,
+ void *param);
+ void dmaStreamFreeI(const stm32_dma_stream_t *dmastp);
+ void dmaStreamFree(const stm32_dma_stream_t *dmastp);
+ void dmaServeInterrupt(const stm32_dma_stream_t *dmastp);
+#if STM32_DMA_SUPPORTS_DMAMUX == TRUE
+ void dmaSetRequestSource(const stm32_dma_stream_t *dmastp, uint32_t per);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32_DMA_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv1/stm32_dma1_ch23.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv1/stm32_dma1_ch23.inc
new file mode 100644
index 0000000..c67f5b4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv1/stm32_dma1_ch23.inc
@@ -0,0 +1,78 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file DMAv1/stm32_dma1_ch23.inc
+ * @brief Shared DMA1 Channels 2 and 3 handler.
+ *
+ * @addtogroup STM32_DMA1_CH23_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Other checks.*/
+#if !defined(STM32_DMA1_CH23_HANDLER)
+#error "STM32_DMA1_CH23_HANDLER not defined in stm32_isr.h"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__)
+/**
+ * @brief DMA1 streams 2 and 3 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA1_CH23_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Check on channel 2.*/
+ dmaServeInterrupt(STM32_DMA1_STREAM2);
+
+ /* Check on channel 3.*/
+ dmaServeInterrupt(STM32_DMA1_STREAM3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv1/stm32_dma1_ch4567.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv1/stm32_dma1_ch4567.inc
new file mode 100644
index 0000000..1de4597
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv1/stm32_dma1_ch4567.inc
@@ -0,0 +1,84 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file DMAv1/stm32_dma1_ch4567.inc
+ * @brief Shared DMA1 Channels 4, 5, 6 and 7 handler.
+ *
+ * @addtogroup STM32_DMA1_CH4567_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Other checks.*/
+#if !defined(STM32_DMA1_CH4567_HANDLER)
+#error "STM32_DMA1_CH4567_HANDLER not defined in stm32_isr.h"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__)
+/**
+ * @brief DMA1 streams 4, 5, 6 and 7 shared ISR.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA1_CH4567_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Check on channel 4.*/
+ dmaServeInterrupt(STM32_DMA1_STREAM4);
+
+ /* Check on channel 5.*/
+ dmaServeInterrupt(STM32_DMA1_STREAM5);
+
+ /* Check on channel 6.*/
+ dmaServeInterrupt(STM32_DMA1_STREAM6);
+
+ /* Check on channel 7.*/
+ dmaServeInterrupt(STM32_DMA1_STREAM7);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv2/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv2/driver.mk
new file mode 100644
index 0000000..bdc468a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv2/driver.mk
@@ -0,0 +1,2 @@
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.c
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv2
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv2/notes.txt b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv2/notes.txt
new file mode 100644
index 0000000..4c01d83
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv2/notes.txt
@@ -0,0 +1,18 @@
+STM32 DMAv2 driver.
+
+Driver capability:
+
+- The driver supports the STM32 enhanced DMA controller found on F2, F4 and
+ F7 sub-families.
+- Support for automatic the channel selection.
+- Support for cache flushing and invalidation.
+
+The file registry must export:
+
+STM32_ADVANCED_DMA - TRUE not used by the DMA drivers but other
+ drivers use it to enable checks on DMA
+ channels. Probably will be removed in the
+ future.
+STM32_HAS_DMAx - Support for DMA unit "x" (1..2).
+STM32_DMAx_CHn_HANDLER - Vector name for channel "n" (0..7).
+STM32_DMAn_CHx_NUMBER - Vector number for channel "n" (0..7).
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.c
new file mode 100644
index 0000000..10b4b68
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.c
@@ -0,0 +1,675 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file DMAv2/stm32_dma.c
+ * @brief Enhanced DMA helper driver code.
+ *
+ * @addtogroup STM32_DMA
+ * @details DMA sharing helper driver. In the STM32 the DMA streams are a
+ * shared resource, this driver allows to allocate and free DMA
+ * streams at runtime in order to allow all the other device
+ * drivers to coordinate the access to the resource.
+ * @note The DMA ISR handlers are all declared into this module because
+ * sharing, the various device drivers can associate a callback to
+ * ISRs when allocating streams.
+ * @{
+ */
+
+#include "hal.h"
+
+/* The following macro is only defined if some driver requiring DMA services
+ has been enabled.*/
+#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/**
+ * @brief Mask of the DMA1 streams in @p dma.allocated_mask.
+ */
+#define STM32_DMA1_STREAMS_MASK 0x000000FFU
+
+/**
+ * @brief Mask of the DMA2 streams in @p dma.allocated_mask.
+ */
+#define STM32_DMA2_STREAMS_MASK 0x0000FF00U
+
+#if STM32_DMA_SUPPORTS_DMAMUX == TRUE
+
+#define DMA1_CH0_VARIANT DMAMUX1_Channel0
+#define DMA1_CH1_VARIANT DMAMUX1_Channel1
+#define DMA1_CH2_VARIANT DMAMUX1_Channel2
+#define DMA1_CH3_VARIANT DMAMUX1_Channel3
+#define DMA1_CH4_VARIANT DMAMUX1_Channel4
+#define DMA1_CH5_VARIANT DMAMUX1_Channel5
+#define DMA1_CH6_VARIANT DMAMUX1_Channel6
+#define DMA1_CH7_VARIANT DMAMUX1_Channel7
+#define DMA2_CH0_VARIANT DMAMUX1_Channel8
+#define DMA2_CH1_VARIANT DMAMUX1_Channel9
+#define DMA2_CH2_VARIANT DMAMUX1_Channel10
+#define DMA2_CH3_VARIANT DMAMUX1_Channel11
+#define DMA2_CH4_VARIANT DMAMUX1_Channel12
+#define DMA2_CH5_VARIANT DMAMUX1_Channel13
+#define DMA2_CH6_VARIANT DMAMUX1_Channel14
+#define DMA2_CH7_VARIANT DMAMUX1_Channel15
+
+#else /* !(STM32_DMA_SUPPORTS_DMAMUX == TRUE) */
+
+#define DMA1_CH0_VARIANT 0
+#define DMA1_CH1_VARIANT 0
+#define DMA1_CH2_VARIANT 0
+#define DMA1_CH3_VARIANT 0
+#define DMA1_CH4_VARIANT 0
+#define DMA1_CH5_VARIANT 0
+#define DMA1_CH6_VARIANT 0
+#define DMA1_CH7_VARIANT 0
+#define DMA2_CH0_VARIANT 0
+#define DMA2_CH1_VARIANT 0
+#define DMA2_CH2_VARIANT 0
+#define DMA2_CH3_VARIANT 0
+#define DMA2_CH4_VARIANT 0
+#define DMA2_CH5_VARIANT 0
+#define DMA2_CH6_VARIANT 0
+#define DMA2_CH7_VARIANT 0
+
+#endif /* !(STM32_DMA_SUPPORTS_DMAMUX == TRUE) */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief DMA streams descriptors.
+ * @details This table keeps the association between an unique stream
+ * identifier and the involved physical registers.
+ * @note Don't use this array directly, use the appropriate wrapper macros
+ * instead: @p STM32_DMA1_STREAM0, @p STM32_DMA1_STREAM1 etc.
+ */
+const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = {
+ {DMA1_Stream0, &DMA1->LIFCR, DMA1_CH0_VARIANT, 0, 0, STM32_DMA1_CH0_NUMBER},
+ {DMA1_Stream1, &DMA1->LIFCR, DMA1_CH1_VARIANT, 6, 1, STM32_DMA1_CH1_NUMBER},
+ {DMA1_Stream2, &DMA1->LIFCR, DMA1_CH2_VARIANT, 16, 2, STM32_DMA1_CH2_NUMBER},
+ {DMA1_Stream3, &DMA1->LIFCR, DMA1_CH3_VARIANT, 22, 3, STM32_DMA1_CH3_NUMBER},
+ {DMA1_Stream4, &DMA1->HIFCR, DMA1_CH4_VARIANT, 0, 4, STM32_DMA1_CH4_NUMBER},
+ {DMA1_Stream5, &DMA1->HIFCR, DMA1_CH5_VARIANT, 6, 5, STM32_DMA1_CH5_NUMBER},
+ {DMA1_Stream6, &DMA1->HIFCR, DMA1_CH6_VARIANT, 16, 6, STM32_DMA1_CH6_NUMBER},
+ {DMA1_Stream7, &DMA1->HIFCR, DMA1_CH7_VARIANT, 22, 7, STM32_DMA1_CH7_NUMBER},
+ {DMA2_Stream0, &DMA2->LIFCR, DMA2_CH0_VARIANT, 0, 8, STM32_DMA2_CH0_NUMBER},
+ {DMA2_Stream1, &DMA2->LIFCR, DMA2_CH1_VARIANT, 6, 9, STM32_DMA2_CH1_NUMBER},
+ {DMA2_Stream2, &DMA2->LIFCR, DMA2_CH2_VARIANT, 16, 10, STM32_DMA2_CH2_NUMBER},
+ {DMA2_Stream3, &DMA2->LIFCR, DMA2_CH3_VARIANT, 22, 11, STM32_DMA2_CH3_NUMBER},
+ {DMA2_Stream4, &DMA2->HIFCR, DMA2_CH4_VARIANT, 0, 12, STM32_DMA2_CH4_NUMBER},
+ {DMA2_Stream5, &DMA2->HIFCR, DMA2_CH5_VARIANT, 6, 13, STM32_DMA2_CH5_NUMBER},
+ {DMA2_Stream6, &DMA2->HIFCR, DMA2_CH6_VARIANT, 16, 14, STM32_DMA2_CH6_NUMBER},
+ {DMA2_Stream7, &DMA2->HIFCR, DMA2_CH7_VARIANT, 22, 15, STM32_DMA2_CH7_NUMBER},
+};
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Global DMA-related data structures.
+ */
+static struct {
+ /**
+ * @brief Mask of the allocated streams.
+ */
+ uint32_t allocated_mask;
+ /**
+ * @brief DMA IRQ redirectors.
+ */
+ struct {
+ /**
+ * @brief DMA callback function.
+ */
+ stm32_dmaisr_t func;
+ /**
+ * @brief DMA callback parameter.
+ */
+ void *param;
+ } streams[STM32_DMA_STREAMS];
+} dma;
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/**
+ * @brief DMA1 stream 0 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA1_CH0_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA1->LISR >> 0U) & STM32_DMA_ISR_MASK;
+ DMA1->LIFCR = flags << 0U;
+ if (dma.streams[0].func)
+ dma.streams[0].func(dma.streams[0].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 1 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA1_CH1_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA1->LISR >> 6U) & STM32_DMA_ISR_MASK;
+ DMA1->LIFCR = flags << 6U;
+ if (dma.streams[1].func)
+ dma.streams[1].func(dma.streams[1].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 2 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA1_CH2_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA1->LISR >> 16U) & STM32_DMA_ISR_MASK;
+ DMA1->LIFCR = flags << 16U;
+ if (dma.streams[2].func)
+ dma.streams[2].func(dma.streams[2].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 3 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA1_CH3_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA1->LISR >> 22U) & STM32_DMA_ISR_MASK;
+ DMA1->LIFCR = flags << 22U;
+ if (dma.streams[3].func)
+ dma.streams[3].func(dma.streams[3].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 4 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA1_CH4_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA1->HISR >> 0U) & STM32_DMA_ISR_MASK;
+ DMA1->HIFCR = flags << 0U;
+ if (dma.streams[4].func)
+ dma.streams[4].func(dma.streams[4].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 5 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA1_CH5_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA1->HISR >> 6U) & STM32_DMA_ISR_MASK;
+ DMA1->HIFCR = flags << 6U;
+ if (dma.streams[5].func)
+ dma.streams[5].func(dma.streams[5].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 6 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA1_CH6_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA1->HISR >> 16U) & STM32_DMA_ISR_MASK;
+ DMA1->HIFCR = flags << 16U;
+ if (dma.streams[6].func)
+ dma.streams[6].func(dma.streams[6].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA1 stream 7 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA1_CH7_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA1->HISR >> 22U) & STM32_DMA_ISR_MASK;
+ DMA1->HIFCR = flags << 22U;
+ if (dma.streams[7].func)
+ dma.streams[7].func(dma.streams[7].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA2 stream 0 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA2_CH0_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA2->LISR >> 0U) & STM32_DMA_ISR_MASK;
+ DMA2->LIFCR = flags << 0U;
+ if (dma.streams[8].func)
+ dma.streams[8].func(dma.streams[8].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA2 stream 1 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA2_CH1_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA2->LISR >> 6U) & STM32_DMA_ISR_MASK;
+ DMA2->LIFCR = flags << 6U;
+ if (dma.streams[9].func)
+ dma.streams[9].func(dma.streams[9].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA2 stream 2 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA2_CH2_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA2->LISR >> 16U) & STM32_DMA_ISR_MASK;
+ DMA2->LIFCR = flags << 16U;
+ if (dma.streams[10].func)
+ dma.streams[10].func(dma.streams[10].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA2 stream 3 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA2_CH3_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA2->LISR >> 22U) & STM32_DMA_ISR_MASK;
+ DMA2->LIFCR = flags << 22U;
+ if (dma.streams[11].func)
+ dma.streams[11].func(dma.streams[11].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA2 stream 4 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA2_CH4_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA2->HISR >> 0U) & STM32_DMA_ISR_MASK;
+ DMA2->HIFCR = flags << 0U;
+ if (dma.streams[12].func)
+ dma.streams[12].func(dma.streams[12].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA2 stream 5 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA2_CH5_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA2->HISR >> 6U) & STM32_DMA_ISR_MASK;
+ DMA2->HIFCR = flags << 6U;
+ if (dma.streams[13].func)
+ dma.streams[13].func(dma.streams[13].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA2 stream 6 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA2_CH6_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA2->HISR >> 16U) & STM32_DMA_ISR_MASK;
+ DMA2->HIFCR = flags << 16U;
+ if (dma.streams[14].func)
+ dma.streams[14].func(dma.streams[14].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief DMA2 stream 7 shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_DMA2_CH7_HANDLER) {
+ uint32_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ flags = (DMA2->HISR >> 22U) & STM32_DMA_ISR_MASK;
+ DMA2->HIFCR = flags << 22U;
+ if (dma.streams[15].func)
+ dma.streams[15].func(dma.streams[15].param, flags);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 DMA helper initialization.
+ *
+ * @init
+ */
+void dmaInit(void) {
+ unsigned i;
+
+ dma.allocated_mask = 0U;
+ for (i = 0U; i < STM32_DMA_STREAMS; i++) {
+ _stm32_dma_streams[i].stream->CR = STM32_DMA_CR_RESET_VALUE;
+ dma.streams[i].func = NULL;
+ }
+ DMA1->LIFCR = 0xFFFFFFFFU;
+ DMA1->HIFCR = 0xFFFFFFFFU;
+ DMA2->LIFCR = 0xFFFFFFFFU;
+ DMA2->HIFCR = 0xFFFFFFFFU;
+}
+
+/**
+ * @brief Allocates a DMA stream.
+ * @details The stream is allocated and, if required, the DMA clock enabled.
+ * The function also enables the IRQ vector associated to the stream
+ * and initializes its priority.
+ *
+ * @param[in] id numeric identifiers of a specific stream or:
+ * - @p STM32_DMA_STREAM_ID_ANY for any stream.
+ * - @p STM32_DMA_STREAM_ID_ANY_DMA1 for any stream
+ * on DMA1.
+ * - @p STM32_DMA_STREAM_ID_ANY_DMA2 for any stream
+ * on DMA2.
+ * .
+ * @param[in] priority IRQ priority for the DMA stream
+ * @param[in] func handling function pointer, can be @p NULL
+ * @param[in] param a parameter to be passed to the handling function
+ * @return Pointer to the allocated @p stm32_dma_stream_t
+ * structure.
+ * @retval NULL if a/the stream is not available.
+ *
+ * @iclass
+ */
+const stm32_dma_stream_t *dmaStreamAllocI(uint32_t id,
+ uint32_t priority,
+ stm32_dmaisr_t func,
+ void *param) {
+ uint32_t i, startid, endid;
+
+ osalDbgCheckClassI();
+
+ if (id < STM32_DMA_STREAMS) {
+ startid = id;
+ endid = id;
+ }
+#if STM32_DMA_SUPPORTS_DMAMUX == TRUE
+ else if (id == STM32_DMA_STREAM_ID_ANY) {
+ startid = 0U;
+ endid = STM32_DMA_STREAMS - 1U;
+ }
+ else if (id == STM32_DMA_STREAM_ID_ANY_DMA1) {
+ startid = 0U;
+ endid = (STM32_DMA_STREAMS / 2U) - 1U;
+ }
+ else if (id == STM32_DMA_STREAM_ID_ANY_DMA2) {
+ startid = (STM32_DMA_STREAMS / 2U) - 1U;
+ endid = STM32_DMA_STREAMS - 1U;
+ }
+#endif
+ else {
+ osalDbgCheck(false);
+ return NULL;
+ }
+
+ for (i = startid; i <= endid; i++) {
+ uint32_t mask = (1U << i);
+ if ((dma.allocated_mask & mask) == 0U) {
+ const stm32_dma_stream_t *dmastp = STM32_DMA_STREAM(i);
+
+ /* Installs the DMA handler.*/
+ dma.streams[i].func = func;
+ dma.streams[i].param = param;
+ dma.allocated_mask |= mask;
+
+ /* Enabling DMA clocks required by the current streams set.*/
+ if ((STM32_DMA1_STREAMS_MASK & mask) != 0U) {
+ rccEnableDMA1(true);
+ }
+ if ((STM32_DMA2_STREAMS_MASK & mask) != 0U) {
+ rccEnableDMA2(true);
+ }
+
+#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && defined(rccEnableDMAMUX)
+ /* Enabling DMAMUX if present.*/
+ if (dma.allocated_mask != 0U) {
+ rccEnableDMAMUX(true);
+ }
+#endif
+
+ /* Putting the stream in a safe state.*/
+ dmaStreamDisable(dmastp);
+ dmastp->stream->CR = STM32_DMA_CR_RESET_VALUE;
+ dmastp->stream->FCR = STM32_DMA_FCR_RESET_VALUE;
+
+ /* Enables the associated IRQ vector if a callback is defined.*/
+ if (func != NULL) {
+ nvicEnableVector(dmastp->vector, priority);
+ }
+
+ return dmastp;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * @brief Allocates a DMA stream.
+ * @details The stream is allocated and, if required, the DMA clock enabled.
+ * The function also enables the IRQ vector associated to the stream
+ * and initializes its priority.
+ *
+ * @param[in] id numeric identifiers of a specific stream or:
+ * - @p STM32_DMA_STREAM_ID_ANY for any stream.
+ * - @p STM32_DMA_STREAM_ID_ANY_DMA1 for any stream
+ * on DMA1.
+ * - @p STM32_DMA_STREAM_ID_ANY_DMA2 for any stream
+ * on DMA2.
+ * .
+ * @param[in] priority IRQ priority for the DMA stream
+ * @param[in] func handling function pointer, can be @p NULL
+ * @param[in] param a parameter to be passed to the handling function
+ * @return Pointer to the allocated @p stm32_dma_stream_t
+ * structure.
+ * @retval NULL if a/the stream is not available.
+ *
+ * @api
+ */
+const stm32_dma_stream_t *dmaStreamAlloc(uint32_t id,
+ uint32_t priority,
+ stm32_dmaisr_t func,
+ void *param) {
+ const stm32_dma_stream_t *dmastp;
+
+ osalSysLock();
+ dmastp = dmaStreamAllocI(id, priority, func, param);
+ osalSysUnlock();
+
+ return dmastp;
+}
+
+/**
+ * @brief Releases a DMA stream.
+ * @details The stream is freed and, if required, the DMA clock disabled.
+ * Trying to release a unallocated stream is an illegal operation
+ * and is trapped if assertions are enabled.
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @iclass
+ */
+void dmaStreamFreeI(const stm32_dma_stream_t *dmastp) {
+
+ osalDbgCheck(dmastp != NULL);
+
+ /* Check if the streams is not taken.*/
+ osalDbgAssert((dma.allocated_mask & (1U << dmastp->selfindex)) != 0U,
+ "not allocated");
+
+ /* Disables the associated IRQ vector.*/
+ nvicDisableVector(dmastp->vector);
+
+ /* Marks the stream as not allocated.*/
+ dma.allocated_mask &= ~(1U << dmastp->selfindex);
+
+ /* Shutting down clocks that are no more required, if any.*/
+ if ((dma.allocated_mask & STM32_DMA1_STREAMS_MASK) == 0U) {
+ rccDisableDMA1();
+ }
+ if ((dma.allocated_mask & STM32_DMA2_STREAMS_MASK) == 0U) {
+ rccDisableDMA2();
+ }
+
+#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && defined(rccDisableDMAMUX)
+ /* Shutting down DMAMUX if present.*/
+ if (dma.allocated_mask == 0U) {
+ rccDisableDMAMUX();
+ }
+#endif
+}
+
+/**
+ * @brief Releases a DMA stream.
+ * @details The stream is freed and, if required, the DMA clock disabled.
+ * Trying to release a unallocated stream is an illegal operation
+ * and is trapped if assertions are enabled.
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @api
+ */
+void dmaStreamFree(const stm32_dma_stream_t *dmastp) {
+
+ osalSysLock();
+ dmaStreamFreeI(dmastp);
+ osalSysUnlock();
+}
+
+#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Associates a peripheral request to a DMA stream.
+ * @note This function can be invoked in both ISR or thread context.
+ *
+ * @param[in] dmastp pointer to a @p stm32_dma_stream_t structure
+ * @param[in] per peripheral identifier
+ *
+ * @special
+ */
+void dmaSetRequestSource(const stm32_dma_stream_t *dmastp, uint32_t per) {
+
+ osalDbgCheck(per < 256U);
+
+ dmastp->mux->CCR = per;
+}
+#endif
+
+#endif /* STM32_DMA_REQUIRED */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.h
new file mode 100644
index 0000000..2562039
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.h
@@ -0,0 +1,682 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file DMAv2/stm32_dma.h
+ * @brief Enhanced-DMA helper driver header.
+ *
+ * @addtogroup STM32_DMA
+ * @{
+ */
+
+#ifndef STM32_DMA_H
+#define STM32_DMA_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief DMA capability.
+ * @details if @p TRUE then the DMA is able of burst transfers, FIFOs,
+ * scatter gather and other advanced features.
+ */
+#define STM32_DMA_ADVANCED TRUE
+
+/**
+ * @brief Total number of DMA streams.
+ * @details This is the total number of streams among all the DMA units.
+ */
+#define STM32_DMA_STREAMS 16U
+
+/**
+ * @brief Mask of the ISR bits passed to the DMA callback functions.
+ */
+#define STM32_DMA_ISR_MASK 0x3DU
+
+/**
+ * @brief Returns the channel associated to the specified stream.
+ *
+ * @param[in] id the unique numeric stream identifier
+ * @param[in] c a stream/channel association word, one channel per
+ * nibble
+ * @return Returns the channel associated to the stream.
+ */
+#define STM32_DMA_GETCHANNEL(id, c) (((c) >> (((id) & 7U) * 4U)) & 15U)
+
+/**
+ * @brief Checks if a DMA priority is within the valid range.
+ * @param[in] prio DMA priority
+ *
+ * @retval The check result.
+ * @retval false invalid DMA priority.
+ * @retval true correct DMA priority.
+ */
+#define STM32_DMA_IS_VALID_PRIORITY(prio) (((prio) >= 0U) && ((prio) <= 3U))
+
+#if (STM32_DMA_SUPPORTS_DMAMUX == FALSE) || defined(_DOXYGEN__)
+/**
+ * @brief Checks if a DMA stream id is within the valid range.
+ *
+ * @param[in] id DMA stream id
+ * @retval The check result.
+ * @retval false invalid DMA stream.
+ * @retval true correct DMA stream.
+ */
+#define STM32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \
+ ((id) <= STM32_DMA_STREAMS))
+#else /* STM32_DMA_SUPPORTS_DMAMUX == FALSE */
+#if STM32_HAS_DMA2 == TRUE
+#define STM32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \
+ ((id) <= (STM32_DMA_STREAMS + 2)))
+#else
+#define STM32_DMA_IS_VALID_STREAM(id) (((id) >= 0U) && \
+ ((id) <= (STM32_DMA_STREAMS + 1)))
+#endif
+#endif /* STM32_DMA_SUPPORTS_DMAMUX == FALSE */
+
+/**
+ * @brief Returns an unique numeric identifier for a DMA stream.
+ *
+ * @param[in] dma the DMA unit number
+ * @param[in] stream the stream number
+ * @return An unique numeric stream identifier.
+ */
+#define STM32_DMA_STREAM_ID(dma, stream) ((((dma) - 1U) * 8U) + (stream))
+
+/**
+ * @brief Returns a DMA stream identifier mask.
+ *
+ *
+ * @param[in] dma the DMA unit number
+ * @param[in] stream the stream number
+ * @return A DMA stream identifier mask.
+ */
+#define STM32_DMA_STREAM_ID_MSK(dma, stream) \
+ (1U << STM32_DMA_STREAM_ID(dma, stream))
+
+/**
+ * @brief Checks if a DMA stream unique identifier belongs to a mask.
+ * @param[in] id the stream numeric identifier
+ * @param[in] mask the stream numeric identifiers mask
+ *
+ * @retval The check result.
+ * @retval false id does not belong to the mask.
+ * @retval true id belongs to the mask.
+ */
+#define STM32_DMA_IS_VALID_ID(id, mask) (((1U << (id)) & (mask)))
+
+#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(_DOXYGEN__)
+/**
+ * @name Special stream identifiers
+ * @{
+ */
+#define STM32_DMA_STREAM_ID_ANY STM32_DMA_STREAMS
+#define STM32_DMA_STREAM_ID_ANY_DMA1 (STM32_DMA_STREAM_ID_ANY + 1)
+#if STM32_HAS_DMA2 == TRUE
+#define STM32_DMA_STREAM_ID_ANY_DMA2 (STM32_DMA_STREAM_ID_ANY_DMA1 + 1)
+#endif
+/** @} */
+#endif
+
+/**
+ * @name DMA streams identifiers
+ * @{
+ */
+/**
+ * @brief Returns a pointer to a stm32_dma_stream_t structure.
+ *
+ * @param[in] id the stream numeric identifier
+ * @return A pointer to the stm32_dma_stream_t constant structure
+ * associated to the DMA stream.
+ */
+#define STM32_DMA_STREAM(id) (&_stm32_dma_streams[id])
+
+#define STM32_DMA1_STREAM0 STM32_DMA_STREAM(0)
+#define STM32_DMA1_STREAM1 STM32_DMA_STREAM(1)
+#define STM32_DMA1_STREAM2 STM32_DMA_STREAM(2)
+#define STM32_DMA1_STREAM3 STM32_DMA_STREAM(3)
+#define STM32_DMA1_STREAM4 STM32_DMA_STREAM(4)
+#define STM32_DMA1_STREAM5 STM32_DMA_STREAM(5)
+#define STM32_DMA1_STREAM6 STM32_DMA_STREAM(6)
+#define STM32_DMA1_STREAM7 STM32_DMA_STREAM(7)
+#define STM32_DMA2_STREAM0 STM32_DMA_STREAM(8)
+#define STM32_DMA2_STREAM1 STM32_DMA_STREAM(9)
+#define STM32_DMA2_STREAM2 STM32_DMA_STREAM(10)
+#define STM32_DMA2_STREAM3 STM32_DMA_STREAM(11)
+#define STM32_DMA2_STREAM4 STM32_DMA_STREAM(12)
+#define STM32_DMA2_STREAM5 STM32_DMA_STREAM(13)
+#define STM32_DMA2_STREAM6 STM32_DMA_STREAM(14)
+#define STM32_DMA2_STREAM7 STM32_DMA_STREAM(15)
+/** @} */
+
+/**
+ * @name CR register constants common to all DMA types
+ * @{
+ */
+#define STM32_DMA_CR_RESET_VALUE 0x00000000U
+#define STM32_DMA_CR_EN DMA_SxCR_EN
+#define STM32_DMA_CR_TEIE DMA_SxCR_TEIE
+#define STM32_DMA_CR_HTIE DMA_SxCR_HTIE
+#define STM32_DMA_CR_TCIE DMA_SxCR_TCIE
+#define STM32_DMA_CR_PFCTRL DMA_SxCR_PFCTRL
+#define STM32_DMA_CR_DIR_MASK DMA_SxCR_DIR
+#define STM32_DMA_CR_DIR_P2M 0
+#define STM32_DMA_CR_DIR_M2P DMA_SxCR_DIR_0
+#define STM32_DMA_CR_DIR_M2M DMA_SxCR_DIR_1
+#define STM32_DMA_CR_CIRC DMA_SxCR_CIRC
+#define STM32_DMA_CR_PINC DMA_SxCR_PINC
+#define STM32_DMA_CR_MINC DMA_SxCR_MINC
+#define STM32_DMA_CR_PSIZE_MASK DMA_SxCR_PSIZE
+#define STM32_DMA_CR_PSIZE_BYTE 0
+#define STM32_DMA_CR_PSIZE_HWORD DMA_SxCR_PSIZE_0
+#define STM32_DMA_CR_PSIZE_WORD DMA_SxCR_PSIZE_1
+#define STM32_DMA_CR_MSIZE_MASK DMA_SxCR_MSIZE
+#define STM32_DMA_CR_MSIZE_BYTE 0
+#define STM32_DMA_CR_MSIZE_HWORD DMA_SxCR_MSIZE_0
+#define STM32_DMA_CR_MSIZE_WORD DMA_SxCR_MSIZE_1
+#define STM32_DMA_CR_SIZE_MASK (STM32_DMA_CR_PSIZE_MASK | \
+ STM32_DMA_CR_MSIZE_MASK)
+#define STM32_DMA_CR_PL_MASK DMA_SxCR_PL
+#define STM32_DMA_CR_PL(n) ((n) << 16U)
+/** @} */
+
+/**
+ * @name CR register constants only found in DMAv2
+ * @{
+ */
+#define STM32_DMA_CR_DMEIE DMA_SxCR_DMEIE
+#define STM32_DMA_CR_PFCTRL DMA_SxCR_PFCTRL
+#define STM32_DMA_CR_PINCOS DMA_SxCR_PINCOS
+#define STM32_DMA_CR_DBM DMA_SxCR_DBM
+#define STM32_DMA_CR_CT DMA_SxCR_CT
+#define STM32_DMA_CR_PBURST_MASK DMA_SxCR_PBURST
+#define STM32_DMA_CR_PBURST_SINGLE 0U
+#define STM32_DMA_CR_PBURST_INCR4 DMA_SxCR_PBURST_0
+#define STM32_DMA_CR_PBURST_INCR8 DMA_SxCR_PBURST_1
+#define STM32_DMA_CR_PBURST_INCR16 (DMA_SxCR_PBURST_0 | DMA_SxCR_PBURST_1)
+#define STM32_DMA_CR_MBURST_MASK DMA_SxCR_MBURST
+#define STM32_DMA_CR_MBURST_SINGLE 0U
+#define STM32_DMA_CR_MBURST_INCR4 DMA_SxCR_MBURST_0
+#define STM32_DMA_CR_MBURST_INCR8 DMA_SxCR_MBURST_1
+#define STM32_DMA_CR_MBURST_INCR16 (DMA_SxCR_MBURST_0 | DMA_SxCR_MBURST_1)
+#if (STM32_DMA_SUPPORTS_DMAMUX == FALSE) || defined(__DOXYGEN__)
+#define STM32_DMA_CR_CHSEL_MASK DMA_SxCR_CHSEL
+#define STM32_DMA_CR_CHSEL(n) ((n) << 25U)
+#else
+#define STM32_DMA_CR_CHSEL_MASK 0U
+#define STM32_DMA_CR_CHSEL(n) 0U
+#endif
+/** @} */
+
+/**
+ * @name FCR register constants only found in DMAv2
+ * @{
+ */
+#define STM32_DMA_FCR_RESET_VALUE 0x00000021U
+#define STM32_DMA_FCR_FEIE DMA_SxFCR_FEIE
+#define STM32_DMA_FCR_FS_MASK DMA_SxFCR_FS
+#define STM32_DMA_FCR_DMDIS DMA_SxFCR_DMDIS
+#define STM32_DMA_FCR_FTH_MASK DMA_SxFCR_FTH
+#define STM32_DMA_FCR_FTH_1Q 0
+#define STM32_DMA_FCR_FTH_HALF DMA_SxFCR_FTH_0
+#define STM32_DMA_FCR_FTH_3Q DMA_SxFCR_FTH_1
+#define STM32_DMA_FCR_FTH_FULL (DMA_SxFCR_FTH_0 | DMA_SxFCR_FTH_1)
+/** @} */
+
+/**
+ * @name Status flags passed to the ISR callbacks
+ */
+#define STM32_DMA_ISR_FEIF DMA_LISR_FEIF0
+#define STM32_DMA_ISR_DMEIF DMA_LISR_DMEIF0
+#define STM32_DMA_ISR_TEIF DMA_LISR_TEIF0
+#define STM32_DMA_ISR_HTIF DMA_LISR_HTIF0
+#define STM32_DMA_ISR_TCIF DMA_LISR_TCIF0
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !defined(STM32_DMA_SUPPORTS_DMAMUX)
+#error "STM32_DMA_SUPPORTS_DMAMUX not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_DMA1)
+#error "STM32_HAS_DMA1 missing in registry"
+#endif
+
+#if !defined(STM32_HAS_DMA2)
+#error "STM32_HAS_DMA2 missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH0_HANDLER)
+#error "STM32_DMA1_CH0_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH1_HANDLER)
+#error "STM32_DMA1_CH1_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH2_HANDLER)
+#error "STM32_DMA1_CH2_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH3_HANDLER)
+#error "STM32_DMA1_CH3_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH4_HANDLER)
+#error "STM32_DMA1_CH4_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH5_HANDLER)
+#error "STM32_DMA1_CH5_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH6_HANDLER)
+#error "STM32_DMA1_CH6_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH7_HANDLER)
+#error "STM32_DMA1_CH7_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH0_HANDLER)
+#error "STM32_DMA2_CH0_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH1_HANDLER)
+#error "STM32_DMA2_CH1_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH2_HANDLER)
+#error "STM32_DMA2_CH2_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH3_HANDLER)
+#error "STM32_DMA2_CH3_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH4_HANDLER)
+#error "STM32_DMA2_CH4_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH5_HANDLER)
+#error "STM32_DMA2_CH5_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH6_HANDLER)
+#error "STM32_DMA2_CH6_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH7_HANDLER)
+#error "STM32_DMA2_CH7_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH0_NUMBER)
+#error "STM32_DMA1_CH0_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH1_NUMBER)
+#error "STM32_DMA1_CH1_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH2_NUMBER)
+#error "STM32_DMA1_CH2_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH3_NUMBER)
+#error "STM32_DMA1_CH3_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH4_NUMBER)
+#error "STM32_DMA1_CH4_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH5_NUMBER)
+#error "STM32_DMA1_CH5_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH6_NUMBER)
+#error "STM32_DMA1_CH6_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA1_CH7_NUMBER)
+#error "STM32_DMA1_CH7_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH0_NUMBER)
+#error "STM32_DMA2_CH0_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH1_NUMBER)
+#error "STM32_DMA2_CH1_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH2_NUMBER)
+#error "STM32_DMA2_CH2_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH3_NUMBER)
+#error "STM32_DMA2_CH3_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH4_NUMBER)
+#error "STM32_DMA2_CH4_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH5_NUMBER)
+#error "STM32_DMA2_CH5_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH6_NUMBER)
+#error "STM32_DMA2_CH6_NUMBER missing in registry"
+#endif
+
+#if !defined(STM32_DMA2_CH7_NUMBER)
+#error "STM32_DMA2_CH7_NUMBER missing in registry"
+#endif
+
+#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__)
+#include "stm32_dmamux.h"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 DMA ISR function type.
+ *
+ * @param[in] p parameter for the registered function
+ * @param[in] flags pre-shifted content of the xISR register, the bits
+ * are aligned to bit zero
+ */
+typedef void (*stm32_dmaisr_t)(void *p, uint32_t flags);
+
+/**
+ * @brief STM32 DMA stream descriptor structure.
+ */
+typedef struct {
+ DMA_Stream_TypeDef *stream; /**< @brief Associated DMA stream. */
+ volatile uint32_t *ifcr; /**< @brief Associated IFCR reg. */
+#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__)
+ DMAMUX_Channel_TypeDef *mux; /**< @brief Associated DMA mux. */
+#else
+ uint8_t dummy; /**< @brief Filler. */
+#endif
+ uint8_t shift; /**< @brief Bits offset in xIFCR
+ register. */
+ uint8_t selfindex; /**< @brief Index to self in array. */
+ uint8_t vector; /**< @brief Associated IRQ vector. */
+} stm32_dma_stream_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Associates a peripheral data register to a DMA stream.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamFree().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] addr value to be written in the PAR register
+ *
+ * @special
+ */
+#define dmaStreamSetPeripheral(dmastp, addr) { \
+ (dmastp)->stream->PAR = (uint32_t)(addr); \
+}
+
+/**
+ * @brief Associates a memory destination to a DMA stream.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamFree().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] addr value to be written in the M0AR register
+ *
+ * @special
+ */
+#define dmaStreamSetMemory0(dmastp, addr) { \
+ (dmastp)->stream->M0AR = (uint32_t)(addr); \
+}
+
+/**
+ * @brief Associates an alternate memory destination to a DMA stream.
+ * @note This function can be invoked in both ISR or thread context.
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] addr value to be written in the M1AR register
+ *
+ * @special
+ */
+#define dmaStreamSetMemory1(dmastp, addr) { \
+ (dmastp)->stream->M1AR = (uint32_t)(addr); \
+}
+
+/**
+ * @brief Sets the number of transfers to be performed.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamFree().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] size value to be written in the CNDTR register
+ *
+ * @special
+ */
+#define dmaStreamSetTransactionSize(dmastp, size) { \
+ (dmastp)->stream->NDTR = (uint32_t)(size); \
+}
+
+/**
+ * @brief Returns the number of transfers to be performed.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamFree().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @return The number of transfers to be performed.
+ *
+ * @special
+ */
+#define dmaStreamGetTransactionSize(dmastp) ((size_t)((dmastp)->stream->NDTR))
+
+/**
+ * @brief Programs the stream mode settings.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamFree().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] mode value to be written in the CR register
+ *
+ * @special
+ */
+#define dmaStreamSetMode(dmastp, mode) { \
+ (dmastp)->stream->CR = (uint32_t)(mode); \
+}
+
+/**
+ * @brief Programs the stream FIFO settings.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamFree().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] mode value to be written in the FCR register
+ *
+ * @special
+ */
+#define dmaStreamSetFIFO(dmastp, mode) { \
+ (dmastp)->stream->FCR = (uint32_t)(mode); \
+}
+
+/**
+ * @brief DMA stream enable.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamFree().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @special
+ */
+#define dmaStreamEnable(dmastp) { \
+ (dmastp)->stream->CR |= STM32_DMA_CR_EN; \
+}
+
+/**
+ * @brief DMA stream disable.
+ * @details The function disables the specified stream, waits for the disable
+ * operation to complete and then clears any pending interrupt.
+ * @note This function can be invoked in both ISR or thread context.
+ * @note Interrupts enabling flags are set to zero after this call, see
+ * bug 3607518.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamFree().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @special
+ */
+#define dmaStreamDisable(dmastp) { \
+ (dmastp)->stream->CR &= ~(STM32_DMA_CR_TCIE | STM32_DMA_CR_HTIE | \
+ STM32_DMA_CR_TEIE | STM32_DMA_CR_DMEIE | \
+ STM32_DMA_CR_EN); \
+ while (((dmastp)->stream->CR & STM32_DMA_CR_EN) != 0) \
+ ; \
+ dmaStreamClearInterrupt(dmastp); \
+}
+
+/**
+ * @brief DMA stream interrupt sources clear.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamFree().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ *
+ * @special
+ */
+#define dmaStreamClearInterrupt(dmastp) { \
+ *(dmastp)->ifcr = STM32_DMA_ISR_MASK << (dmastp)->shift; \
+}
+
+/**
+ * @brief Starts a memory to memory operation using the specified stream.
+ * @note The default transfer data mode is "byte to byte" but it can be
+ * changed by specifying extra options in the @p mode parameter.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamFree().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @param[in] mode value to be written in the CCR register, this value
+ * is implicitly ORed with:
+ * - @p STM32_DMA_CR_MINC
+ * - @p STM32_DMA_CR_PINC
+ * - @p STM32_DMA_CR_DIR_M2M
+ * - @p STM32_DMA_CR_EN
+ * .
+ * @param[in] src source address
+ * @param[in] dst destination address
+ * @param[in] n number of data units to copy
+ */
+#define dmaStartMemCopy(dmastp, mode, src, dst, n) { \
+ dmaStreamSetPeripheral(dmastp, src); \
+ dmaStreamSetMemory0(dmastp, dst); \
+ dmaStreamSetTransactionSize(dmastp, n); \
+ dmaStreamSetMode(dmastp, (mode) | \
+ STM32_DMA_CR_MINC | STM32_DMA_CR_PINC | \
+ STM32_DMA_CR_DIR_M2M); \
+ dmaStreamEnable(dmastp); \
+}
+
+/**
+ * @brief Polled wait for DMA transfer end.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamFree().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ */
+#define dmaWaitCompletion(dmastp) { \
+ (dmastp)->stream->CR &= ~(STM32_DMA_CR_TCIE | STM32_DMA_CR_HTIE | \
+ STM32_DMA_CR_TEIE | STM32_DMA_CR_DMEIE); \
+ while ((dmastp)->stream->CR & STM32_DMA_CR_EN) \
+ ; \
+ dmaStreamClearInterrupt(dmastp); \
+}
+
+/**
+ * @brief DMA stream current target.
+ * @note This function can be invoked in both ISR or thread context.
+ * @pre The stream must have been allocated using @p dmaStreamAlloc().
+ * @post After use the stream can be released using @p dmaStreamFree().
+ *
+ * @param[in] dmastp pointer to a stm32_dma_stream_t structure
+ * @return Current memory target index.
+ *
+ * @special
+ */
+#define dmaStreamGetCurrentTarget(dmastp) \
+ (((dmastp)->stream->CR >> DMA_SxCR_CT_Pos) & 1U)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS];
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void dmaInit(void);
+ const stm32_dma_stream_t *dmaStreamAllocI(uint32_t id,
+ uint32_t priority,
+ stm32_dmaisr_t func,
+ void *param);
+ const stm32_dma_stream_t *dmaStreamAlloc(uint32_t id,
+ uint32_t priority,
+ stm32_dmaisr_t func,
+ void *param);
+ void dmaStreamFreeI(const stm32_dma_stream_t *dmastp);
+ void dmaStreamFree(const stm32_dma_stream_t *dmastp);
+#if STM32_DMA_SUPPORTS_DMAMUX == TRUE
+ void dmaSetRequestSource(const stm32_dma_stream_t *dmastp, uint32_t per);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32_DMA_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/driver.mk
new file mode 100644
index 0000000..63016f9
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/driver.mk
@@ -0,0 +1,2 @@
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.c
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/notes.txt b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/notes.txt
new file mode 100644
index 0000000..ac83cf5
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/notes.txt
@@ -0,0 +1,14 @@
+STM32 EXTIv1 driver.
+
+Driver capability:
+
+- Support for the EXTI peripheral.
+
+The file registry must export:
+
+STM32_EXTI_NUM_LINES - Number of EXTI lines, it can be between 0 and 63.
+STM32_EXTI_IMR1_MASK - Mask of the fixed lines that must not be
+ handled by the driver (0..31).
+STM32_EXTI_IMR2_MASK - Mask of the fixed lines that must not be
+ handled by the driver (32..63). Only required
+ if STM32_EXTI_NUM_LINES is greater than 32.
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.c
new file mode 100644
index 0000000..e2877cf
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.c
@@ -0,0 +1,216 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti.c
+ * @brief EXTI helper driver code.
+ *
+ * @addtogroup STM32_EXTI
+ * @details EXTI sharing helper driver.
+ * @{
+ */
+
+#include "hal.h"
+
+/* The following macro is only defined if some driver requiring EXTI services
+ has been enabled.*/
+#if defined(STM32_EXTI_REQUIRED) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 EXTI group 1 lines initialization.
+ *
+ * @param[in] mask mask of group 1 lines to be initialized
+ * @param[in] mode initialization mode
+ *
+ * @api
+ */
+void extiEnableGroup1(uint32_t mask, extimode_t mode) {
+
+ /* Masked out lines must not be touched by this driver.*/
+ osalDbgAssert((mask & STM32_EXTI_IMR1_MASK) == 0U, "fixed lines");
+
+ if ((mode & EXTI_MODE_EDGES_MASK) == 0U) {
+ /* Disabling channels.*/
+ EXTI->IMR1 &= ~mask;
+ EXTI->EMR1 &= ~mask;
+ EXTI->RTSR1 &= ~mask;
+ EXTI->FTSR1 &= ~mask;
+#if STM32_EXTI_SEPARATE_RF == FALSE
+ EXTI->PR1 = mask;
+#else
+ EXTI->RPR1 = mask;
+ EXTI->FPR1 = mask;
+#endif
+ }
+ else {
+ /* Programming edge registers.*/
+ if (mode & EXTI_MODE_RISING_EDGE) {
+ EXTI->RTSR1 |= mask;
+ }
+ else {
+ EXTI->RTSR1 &= ~mask;
+ }
+ if (mode & EXTI_MODE_FALLING_EDGE) {
+ EXTI->FTSR1 |= mask;
+ }
+ else {
+ EXTI->FTSR1 &= ~mask;
+ }
+
+ /* Programming interrupt and event registers.*/
+ if ((mode & EXTI_MODE_ACTION_MASK) == EXTI_MODE_ACTION_INTERRUPT) {
+ EXTI->IMR1 |= mask;
+ EXTI->EMR1 &= ~mask;
+ }
+ else {
+ EXTI->EMR1 |= mask;
+ EXTI->IMR1 &= ~mask;
+ }
+ }
+}
+
+#if (STM32_EXTI_HAS_GROUP2 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief STM32 EXTI group 2 lines initialization.
+ *
+ * @param[in] mask mask of group 2 lines to be initialized
+ * @param[in] mode initialization mode
+ *
+ * @api
+ */
+void extiEnableGroup2(uint32_t mask, extimode_t mode) {
+
+ /* Masked out lines must not be touched by this driver.*/
+ osalDbgAssert((mask & STM32_EXTI_IMR2_MASK) == 0U, "fixed lines");
+
+ if ((mode & EXTI_MODE_EDGES_MASK) == 0U) {
+ /* Disabling channels.*/
+ EXTI->IMR2 &= ~mask;
+ EXTI->EMR2 &= ~mask;
+ EXTI->RTSR2 &= ~mask;
+ EXTI->FTSR2 &= ~mask;
+#if STM32_EXTI_SEPARATE_RF == FALSE
+ EXTI->PR2 = mask;
+#else
+ EXTI->RPR2 = mask;
+ EXTI->FPR2 = mask;
+#endif
+ }
+ else {
+ /* Programming edge registers.*/
+ if (mode & EXTI_MODE_RISING_EDGE) {
+ EXTI->RTSR2 |= mask;
+ }
+ else {
+ EXTI->RTSR2 &= ~mask;
+ }
+ if (mode & EXTI_MODE_FALLING_EDGE) {
+ EXTI->FTSR2 |= mask;
+ }
+ else {
+ EXTI->FTSR2 &= ~mask;
+ }
+
+ /* Programming interrupt and event registers.*/
+ if ((mode & EXTI_MODE_ACTION_MASK) == EXTI_MODE_ACTION_INTERRUPT) {
+ EXTI->IMR2 |= mask;
+ EXTI->EMR2 &= ~mask;
+ }
+ else {
+ EXTI->EMR2 |= mask;
+ EXTI->IMR2 &= ~mask;
+ }
+ }
+}
+#endif /* STM32_EXTI_HAS_GROUP2 == TRUE */
+
+/**
+ * @brief STM32 EXTI line initialization.
+ *
+ * @param[in] line line to be initialized
+ * @param[in] mode initialization mode
+ *
+ * @api
+ */
+void extiEnableLine(extiline_t line, extimode_t mode) {
+ uint32_t mask = (1U << (line & 0x1FU));
+
+ osalDbgCheck(line < STM32_EXTI_NUM_LINES);
+ osalDbgCheck((mode & ~EXTI_MODE_MASK) == 0U);
+
+#if STM32_EXTI_HAS_GROUP2 == TRUE
+ if (line < 32) {
+#endif
+ extiEnableGroup1(mask, mode);
+#if STM32_EXTI_HAS_GROUP2 == TRUE
+ }
+ else {
+ extiEnableGroup2(mask, mode);
+ }
+#endif
+}
+
+/**
+ * @brief STM32 EXTI line IRQ status clearing.
+ *
+ * @param[in] line line to be initialized
+ *
+ * @api
+ */
+void extiClearLine(extiline_t line) {
+ uint32_t mask = (1U << (line & 0x1FU));
+
+ osalDbgCheck(line < STM32_EXTI_NUM_LINES);
+
+#if STM32_EXTI_HAS_GROUP2 == TRUE
+ if (line < 32) {
+#endif
+ extiClearGroup1(mask);
+#if STM32_EXTI_HAS_GROUP2 == TRUE
+ }
+ else {
+ extiClearGroup2(mask);
+ }
+#endif
+}
+
+#endif /* STM32_EXTI_REQUIRED */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.h
new file mode 100644
index 0000000..dadc58c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti.h
@@ -0,0 +1,257 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti.h
+ * @brief EXTI helper driver header.
+ *
+ * @addtogroup STM32_EXTI
+ * @{
+ */
+
+#ifndef STM32_EXTI_H
+#define STM32_EXTI_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name EXTI channel modes
+ * @{
+ */
+#define EXTI_MODE_MASK 7U /**< @brief Mode parameter mask. */
+#define EXTI_MODE_EDGES_MASK 3U /**< @brief Edges field mask. */
+#define EXTI_MODE_DISABLED 0U /**< @brief Channel disabled. */
+#define EXTI_MODE_RISING_EDGE 1U /**< @brief Rising edge callback. */
+#define EXTI_MODE_FALLING_EDGE 2U /**< @brief Falling edge callback. */
+#define EXTI_MODE_BOTH_EDGES 3U /**< @brief Both edges callback. */
+#define EXTI_MODE_ACTION_MASK 4U /**< @brief Action field mask. */
+#define EXTI_MODE_ACTION_INTERRUPT 0U /**< @brief Interrupt mode. */
+#define EXTI_MODE_ACTION_EVENT 4U /**< @brief Event mode. */
+/** @} */
+
+/* Handling differences in ST headers.*/
+#if !defined(STM32H7XX) && !defined(STM32L4XX) && !defined(STM32L4XXP) && \
+ !defined(STM32G0XX) && !defined(STM32G4XX)
+#define EMR1 EMR
+#define IMR1 IMR
+#define PR1 PR
+#define RTSR1 RTSR
+#define FTSR1 FTSR
+#endif
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !defined(STM32_EXTI_NUM_LINES)
+#error "STM32_EXTI_NUM_LINES not defined in registry"
+#endif
+
+/* Checking for presence of bank 2 registers. If the definition is not
+ present in registry then it is inferred by the number of channels (which
+ is not an always-good method, see G0.*/
+#if !defined(STM32_EXTI_HAS_GROUP2)
+#if STM32_EXTI_NUM_LINES <= 32
+#define STM32_EXTI_HAS_GROUP2 FALSE
+#else
+#define STM32_EXTI_HAS_GROUP2 TRUE
+#endif
+#endif /* !defined(STM32_EXTI_HAS_GROUP2) */
+
+/* Determines if EXTI has dedicated CR register or if it is done in
+ SYSCFG (old style).*/
+#if !defined(STM32_EXTI_HAS_CR)
+#define STM32_EXTI_HAS_CR FALSE
+#endif
+
+/* Determines if EXTI has dedicated separate registers for raising and
+ falling edges.*/
+#if !defined(STM32_EXTI_SEPARATE_RF)
+#define STM32_EXTI_SEPARATE_RF FALSE
+#endif
+
+#if (STM32_EXTI_NUM_LINES < 0) || (STM32_EXTI_NUM_LINES > 63)
+#error "invalid STM32_EXTI_NUM_LINES value"
+#endif
+
+#if !defined(STM32_EXTI_IMR1_MASK)
+#error "STM32_EXTI_IMR1_MASK not defined in registry"
+#endif
+
+#if STM32_EXTI_NUM_LINES > 32
+#if !defined(STM32_EXTI_IMR2_MASK)
+#error "STM32_EXTI_IMR2_MASK not defined in registry"
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of an EXTI line identifier.
+ */
+typedef uint32_t extiline_t;
+
+/**
+ * @brief Type of an EXTI line mode.
+ */
+typedef uint32_t extimode_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief From group 1 line number to mask.
+ *
+ * @param[in] line line number in range 0..31
+ */
+#define EXTI_MASK1(line) (uint32_t)(1U << (line))
+
+/**
+ * @brief From group 2 line number to mask.
+ *
+ * @param[in] line line number in range 32..63
+ */
+#define EXTI_MASK2(line) (uint32_t)(1U << ((line) - 32U))
+
+/**
+ * @brief STM32 EXTI group 1 IRQ status clearing.
+ *
+ * @param[in] mask mask of group 1 lines to be initialized
+ *
+ * @special
+ */
+#if (STM32_EXTI_SEPARATE_RF == FALSE) || defined(__DOXYGEN__)
+#define extiClearGroup1(mask) do { \
+ osalDbgAssert(((mask) & STM32_EXTI_IMR1_MASK) == 0U, "fixed lines"); \
+ EXTI->PR1 = (uint32_t)(mask); \
+} while (false)
+#else
+#define extiClearGroup1(mask) do { \
+ osalDbgAssert(((mask) & STM32_EXTI_IMR1_MASK) == 0U, "fixed lines"); \
+ EXTI->RPR1 = (uint32_t)(mask); \
+ EXTI->FPR1 = (uint32_t)(mask); \
+} while (false)
+#endif
+
+#if (STM32_EXTI_HAS_GROUP2 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief STM32 EXTI group 2 IRQ status clearing.
+ *
+ * @param[in] mask mask of group 2 lines to be initialized
+ *
+ * @special
+ */
+#if (STM32_EXTI_SEPARATE_RF == FALSE) || defined(__DOXYGEN__)
+#define extiClearGroup2(mask) do { \
+ osalDbgAssert(((mask) & STM32_EXTI_IMR2_MASK) == 0U, "fixed lines"); \
+ EXTI->PR2 = (uint32_t)(mask); \
+} while (false)
+#else
+#define extiClearGroup2(mask) do { \
+ osalDbgAssert(((mask) & STM32_EXTI_IMR2_MASK) == 0U, "fixed lines"); \
+ EXTI->RPR2 = (uint32_t)(mask); \
+ EXTI->FPR2 = (uint32_t)(mask); \
+} while (false)
+#endif
+#endif /* STM32_EXTI_HAS_GROUP2 == TRUE */
+
+/**
+ * @brief Serves an EXTI interrupt in group 1.
+ *
+ * @param[in] mask mask of lines to be cleared
+ * @param[out] out mask of lines needing processing
+ *
+ * @special
+ */
+#if (STM32_EXTI_SEPARATE_RF == FALSE) || defined(__DOXYGEN__)
+#define extiGetAndClearGroup1(mask, out) do { \
+ uint32_t pr1; \
+ \
+ pr1 = EXTI->PR1 & (mask); \
+ (out) = pr1; \
+ EXTI->PR1 = pr1; \
+} while (false)
+#else
+#define extiGetAndClearGroup1(mask, out) do { \
+ uint32_t rpr1, fpr1; \
+ \
+ rpr1 = EXTI->RPR1 & (mask); \
+ fpr1 = EXTI->FPR1 & (mask); \
+ (out) = rpr1 | fpr1; \
+ EXTI->RPR1 = rpr1; \
+ EXTI->FPR1 = fpr1; \
+} while (false)
+#endif
+
+#if (STM32_EXTI_HAS_GROUP2 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Serves an EXTI interrupt in group 2.
+ *
+ * @param[in] mask mask of lines to be cleared
+ * @param[out] out mask of lines needing processing
+ *
+ * @special
+ */
+#if (STM32_EXTI_SEPARATE_RF == FALSE) || defined(__DOXYGEN__)
+#define extiGetAndClearGroup2(mask, out) do { \
+ uint32_t pr2; \
+ \
+ pr2 = EXTI->PR2 & (mask); \
+ (out) = pr2; \
+ EXTI->PR2 = pr2; \
+} while (false)
+#else
+#define extiGetAndClearGroup2(mask, out) do { \
+ uint32_t rpr2, fpr2; \
+ \
+ rpr2 = EXTI->RPR2 & (mask); \
+ fpr2 = EXTI->FPR2 & (mask); \
+ (out) = rpr2 | fpr2; \
+ EXTI->RPR2 = rpr2; \
+ EXTI->FPR2 = fpr2; \
+} while (false)
+#endif
+#endif /* STM32_EXTI_HAS_GROUP2 == TRUE */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void extiEnableGroup1(uint32_t mask, extimode_t mode);
+#if (STM32_EXTI_HAS_GROUP2 == TRUE) || defined(__DOXYGEN__)
+ void extiEnableGroup2(uint32_t mask, extimode_t mode);
+#endif /* STM32_EXTI_HAS_GROUP2 == TRUE */
+ void extiEnableLine(extiline_t line, extimode_t mode);
+ void extiClearLine(extiline_t line);
+ #ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32_EXTI_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti0.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti0.inc
new file mode 100644
index 0000000..e02707b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti0.inc
@@ -0,0 +1,95 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti0.inc
+ * @brief Shared EXTI0 handler.
+ *
+ * @addtogroup STM32_EXTI0_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI0_PRIORITY)
+#error "STM32_IRQ_EXTI0_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI0_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI0_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti0_irq_init(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicEnableVector(STM32_EXTI0_NUMBER, STM32_IRQ_EXTI0_PRIORITY);
+#endif
+}
+
+static inline void exti0_irq_deinit(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicDisableVector(STM32_EXTI0_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI0_HANDLER)
+/**
+ * @brief EXTI[0] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI0_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1(1U << 0, pr);
+
+ exti_serve_irq(pr, 0);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti0_1.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti0_1.inc
new file mode 100644
index 0000000..d20141b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti0_1.inc
@@ -0,0 +1,96 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti0_1.inc
+ * @brief Shared EXTI0_1 handler.
+ *
+ * @addtogroup STM32_EXTI0_1_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI0_1_PRIORITY)
+#error "STM32_IRQ_EXTI0_1_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI0_1_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI0_1_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti0_1_irq_init(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicEnableVector(STM32_EXTI0_1_NUMBER, STM32_IRQ_EXTI0_1_PRIORITY);
+#endif
+}
+
+static inline void exti0_1_irq_deinit(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicDisableVector(STM32_EXTI0_1_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI0_1_HANDLER)
+/**
+ * @brief EXTI[0], EXTI[1] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI0_1_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1((1U << 0) | (1U << 1), pr);
+
+ exti_serve_irq(pr, 0);
+ exti_serve_irq(pr, 1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti1.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti1.inc
new file mode 100644
index 0000000..c7a9de1
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti1.inc
@@ -0,0 +1,95 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti1.inc
+ * @brief Shared EXTI1 handler.
+ *
+ * @addtogroup STM32_EXTI1_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI1_PRIORITY)
+#error "STM32_IRQ_EXTI1_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI1_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI1_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti1_irq_init(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicEnableVector(STM32_EXTI1_NUMBER, STM32_IRQ_EXTI1_PRIORITY);
+#endif
+}
+
+static inline void exti1_irq_deinit(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicDisableVector(STM32_EXTI1_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI1_HANDLER)
+/**
+ * @brief EXTI[1] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI1_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1(1U << 1, pr);
+
+ exti_serve_irq(pr, 1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti10_15.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti10_15.inc
new file mode 100644
index 0000000..3288dc9
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti10_15.inc
@@ -0,0 +1,101 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti10_15.inc
+ * @brief Shared EXTI10_15 handler.
+ *
+ * @addtogroup STM32_EXTI10_15_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI10_15_PRIORITY)
+#error "STM32_IRQ_EXTI10_15_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI10_15_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI10_15_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti10_15_irq_init(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicEnableVector(STM32_EXTI10_15_NUMBER, STM32_IRQ_EXTI10_15_PRIORITY);
+#endif
+}
+
+static inline void exti10_15_irq_deinit(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicDisableVector(STM32_EXTI10_15_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI10_15_HANDLER)
+/**
+ * @brief EXTI[10]..EXTI[15] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI10_15_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1((1U << 10) | (1U << 11) | (1U << 12) | (1U << 13) |
+ (1U << 14) | (1U << 15), pr);
+
+ exti_serve_irq(pr, 10);
+ exti_serve_irq(pr, 11);
+ exti_serve_irq(pr, 12);
+ exti_serve_irq(pr, 13);
+ exti_serve_irq(pr, 14);
+ exti_serve_irq(pr, 15);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti16-35_38.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti16-35_38.inc
new file mode 100644
index 0000000..aa21235
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti16-35_38.inc
@@ -0,0 +1,130 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti16-35_38.inc
+ * @brief Shared EXTI16-35_38 handler.
+ *
+ * @addtogroup STM32_EXTI1635_38_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI1635_38_PRIORITY)
+#error "STM32_IRQ_EXTI1635_38_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI1635_38_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI1635_38_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti16_exti35_38_irq_init(void) {
+#if defined(STM32_EXTI16_IS_USED) || defined(STM32_EXTI35_IS_USED) || \
+ defined(STM32_EXTI36_IS_USED) || defined(STM32_EXTI37_IS_USED) || \
+ defined(STM32_EXTI38_IS_USED)
+ nvicEnableVector(STM32_EXTI1635_38_NUMBER, STM32_IRQ_EXTI1635_38_PRIORITY);
+#endif
+}
+
+static inline void exti16_exti35_38_irq_deinit(void) {
+#if defined(STM32_EXTI16_IS_USED) || defined(STM32_EXTI35_IS_USED) || \
+ defined(STM32_EXTI36_IS_USED) || defined(STM32_EXTI37_IS_USED) || \
+ defined(STM32_EXTI38_IS_USED)
+ nvicDisableVector(STM32_EXTI1635_38_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_EXTI16_IS_USED) || defined(STM32_EXTI35_IS_USED) || \
+ defined(STM32_EXTI36_IS_USED) || defined(STM32_EXTI37_IS_USED) || \
+ defined(STM32_EXTI38_IS_USED) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI1635_38_HANDLER)
+/**
+ * @brief EXTI[16], EXTI[35], EXTI[38] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI163538_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+#if defined(STM32_EXTI16_IS_USED)
+ extiGetAndClearGroup1(1U << 16, pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI16_ISR)
+ STM32_EXTI16_ISR(pr, 16);
+#endif
+#endif
+
+#if defined(STM32_EXTI35_IS_USED) || defined(STM32_EXTI36_IS_USED) || \
+ defined(STM32_EXTI37_IS_USED) || defined(STM32_EXTI38_IS_USED)
+ extiGetAndClearGroup2((1U << (35 - 32)) | (1U << (36 - 32)) |
+ (1U << (37 - 32)) | (1U << (38 - 32)), pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI35_ISR)
+ STM32_EXTI35_ISR(pr, 35);
+#endif
+#if defined(STM32_EXTI36_ISR)
+ STM32_EXTI35_ISR(pr, 36);
+#endif
+#if defined(STM32_EXTI37_ISR)
+ STM32_EXTI35_ISR(pr, 37);
+#endif
+#if defined(STM32_EXTI38_ISR)
+ STM32_EXTI38_ISR(pr, 38);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti16-40_41.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti16-40_41.inc
new file mode 100644
index 0000000..b8aebe4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti16-40_41.inc
@@ -0,0 +1,119 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti16-40_41.inc
+ * @brief Shared EXTI16-40_41 handler.
+ *
+ * @addtogroup STM32_EXTI164041_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI164041_PRIORITY)
+#error "STM32_IRQ_EXTI164041_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI164041_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI164041_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti16_exti40_exti41_irq_init(void) {
+#if defined(STM32_EXTI16_IS_USED) || defined(STM32_EXTI40_IS_USED) || \
+ defined(STM32_EXTI41_IS_USED)
+ nvicEnableVector(STM32_EXTI164041_NUMBER, STM32_IRQ_EXTI164041_PRIORITY);
+#endif
+}
+
+static inline void exti16_exti40_exti41_irq_deinit(void) {
+#if defined(STM32_EXTI16_IS_USED) || defined(STM32_EXTI40_IS_USED) || \
+ defined(STM32_EXTI41_IS_USED)
+ nvicDisableVector(STM32_EXTI164041_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_EXTI16_IS_USED) || defined(STM32_EXTI40_IS_USED) || \
+ defined(STM32_EXTI41_IS_USED) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI164041_HANDLER)
+/**
+ * @brief EXTI[16], EXTI[40], EXTI[41] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI164041_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+#if defined(STM32_EXTI16_IS_USED)
+ extiGetAndClearGroup1(1U << 16, pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI16_ISR)
+ STM32_EXTI16_ISR(pr, 16);
+#endif
+#endif
+
+#if defined(STM32_EXTI40_IS_USED) || defined(STM32_EXTI41_IS_USED)
+ extiGetAndClearGroup2((1U << (40 - 32)) | (1U << (41 - 32)), pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI40_ISR)
+ STM32_EXTI40_ISR(pr, 40);
+#endif
+#if defined(STM32_EXTI41_ISR)
+ STM32_EXTI41_ISR(pr, 41);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti16.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti16.inc
new file mode 100644
index 0000000..d09ef3a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti16.inc
@@ -0,0 +1,100 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti16.inc
+ * @brief Shared EXTI16 handler.
+ *
+ * @addtogroup STM32_EXTI16_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI16_PRIORITY)
+#error "STM32_IRQ_EXTI16_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI16_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI16_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti16_irq_init(void) {
+#if defined(STM32_EXTI16_IS_USED)
+ nvicEnableVector(STM32_EXTI16_NUMBER, STM32_IRQ_EXTI16_PRIORITY);
+#endif
+}
+
+static inline void exti16_irq_deinit(void) {
+#if defined(STM32_EXTI16_IS_USED)
+ nvicDisableVector(STM32_EXTI16_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_EXTI16_IS_USED) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI16_HANDLER)
+/**
+ * @brief EXTI[16] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI16_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1(1U << 16, pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI16_ISR)
+ STM32_EXTI16_ISR(pr, 16);
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti17.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti17.inc
new file mode 100644
index 0000000..c2bbe0d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti17.inc
@@ -0,0 +1,100 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti17.inc
+ * @brief Shared EXTI17 handler.
+ *
+ * @addtogroup STM32_EXTI17_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI17_PRIORITY)
+#error "STM32_IRQ_EXTI17_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI17_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI17_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti17_irq_init(void) {
+#if defined(STM32_EXTI17_IS_USED)
+ nvicEnableVector(STM32_EXTI17_NUMBER, STM32_IRQ_EXTI17_PRIORITY);
+#endif
+}
+
+static inline void exti17_irq_deinit(void) {
+#if defined(STM32_EXTI17_IS_USED)
+ nvicDisableVector(STM32_EXTI17_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_EXTI17_IS_USED) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI17_HANDLER)
+/**
+ * @brief EXTI[17] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI17_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1(1U << 17, pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI17_ISR)
+ STM32_EXTI17_ISR(pr, 17);
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti18.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti18.inc
new file mode 100644
index 0000000..81e8290
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti18.inc
@@ -0,0 +1,100 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti18.inc
+ * @brief Shared EXTI18 handler.
+ *
+ * @addtogroup STM32_EXTI18_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI18_PRIORITY)
+#error "STM32_IRQ_EXTI18_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI18_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI18_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti18_irq_init(void) {
+#if defined(STM32_EXTI18_IS_USED)
+ nvicEnableVector(STM32_EXTI18_NUMBER, STM32_IRQ_EXTI18_PRIORITY);
+#endif
+}
+
+static inline void exti18_irq_deinit(void) {
+#if defined(STM32_EXTI18_IS_USED)
+ nvicDisableVector(STM32_EXTI18_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_EXTI18_IS_USED) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI18_HANDLER)
+/**
+ * @brief EXTI[18] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI18_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1(1U << 18, pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI18_ISR)
+ STM32_EXTI18_ISR(pr, 18);
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti19-21.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti19-21.inc
new file mode 100644
index 0000000..670fbdf
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti19-21.inc
@@ -0,0 +1,104 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti19-21.inc
+ * @brief Shared EXTI19-21 handler.
+ *
+ * @addtogroup STM32_EXTI1921_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI1921_PRIORITY)
+#error "STM32_IRQ_EXTI1921_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI1921_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI1921_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti19_exti21_irq_init(void) {
+#if defined(STM32_EXTI19_IS_USED) || defined(STM32_EXTI21_IS_USED)
+ nvicEnableVector(STM32_EXTI1921_NUMBER, STM32_IRQ_EXTI1921_PRIORITY);
+#endif
+}
+
+static inline void exti19_exti21_irq_deinit(void) {
+#if defined(STM32_EXTI19_IS_USED) || defined(STM32_EXTI21_IS_USED)
+ nvicDisableVector(STM32_EXTI1921_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_EXTI19_IS_USED) || defined(STM32_EXTI21_IS_USED) || \
+ defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI1921_HANDLER)
+/**
+ * @brief EXTI[0], EXTI[1] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI1921_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1((1U << 19) | (1U << 21), pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI19_ISR)
+ STM32_EXTI16_ISR(pr, 19);
+#endif
+#if defined(STM32_EXTI21_ISR)
+ STM32_EXTI16_ISR(pr, 21);
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti19.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti19.inc
new file mode 100644
index 0000000..ef4b8f8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti19.inc
@@ -0,0 +1,100 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti19.inc
+ * @brief Shared EXTI19 handler.
+ *
+ * @addtogroup STM32_EXTI19_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI19_PRIORITY)
+#error "STM32_IRQ_EXTI19_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI19_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI19_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti19_irq_init(void) {
+#if defined(STM32_EXTI19_IS_USED)
+ nvicEnableVector(STM32_EXTI19_NUMBER, STM32_IRQ_EXTI19_PRIORITY);
+#endif
+}
+
+static inline void exti19_irq_deinit(void) {
+#if defined(STM32_EXTI19_IS_USED)
+ nvicDisableVector(STM32_EXTI19_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_EXTI19_IS_USED) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI19_HANDLER)
+/**
+ * @brief EXTI[19] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI19_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1(1U << 19, pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI19_ISR)
+ STM32_EXTI19_ISR(pr, 19);
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti2.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti2.inc
new file mode 100644
index 0000000..d5ddc40
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti2.inc
@@ -0,0 +1,95 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti2.inc
+ * @brief Shared EXTI2 handler.
+ *
+ * @addtogroup STM32_EXTI2_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI2_PRIORITY)
+#error "STM32_IRQ_EXTI2_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI2_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI2_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti2_irq_init(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicEnableVector(STM32_EXTI2_NUMBER, STM32_IRQ_EXTI2_PRIORITY);
+#endif
+}
+
+static inline void exti2_irq_deinit(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicDisableVector(STM32_EXTI2_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI2_HANDLER)
+/**
+ * @brief EXTI[2] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI2_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1(1U << 2, pr);
+
+ exti_serve_irq(pr, 2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti20.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti20.inc
new file mode 100644
index 0000000..1d1b6af
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti20.inc
@@ -0,0 +1,100 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti20.inc
+ * @brief Shared EXTI20 handler.
+ *
+ * @addtogroup STM32_EXTI20_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI20_PRIORITY)
+#error "STM32_IRQ_EXTI20_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI20_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI20_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti20_irq_init(void) {
+#if defined(STM32_EXTI20_IS_USED)
+ nvicEnableVector(STM32_EXTI20_NUMBER, STM32_IRQ_EXTI20_PRIORITY);
+#endif
+}
+
+static inline void exti20_irq_deinit(void) {
+#if defined(STM32_EXTI20_IS_USED)
+ nvicDisableVector(STM32_EXTI20_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_EXTI20_IS_USED) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI20_HANDLER)
+/**
+ * @brief EXTI[20] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI20_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1(1U << 20, pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI20_ISR)
+ STM32_EXTI20_ISR(pr, 20);
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti20_21.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti20_21.inc
new file mode 100644
index 0000000..500f533
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti20_21.inc
@@ -0,0 +1,104 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti20_21.inc
+ * @brief Shared EXTI20_21 handler.
+ *
+ * @addtogroup STM32_EXTI20_21_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI20_21_PRIORITY)
+#error "STM32_IRQ_EXTI20_21_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI20_21_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI20_21_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti20_exti21_irq_init(void) {
+#if defined(STM32_EXTI20_IS_USED) || defined(STM32_EXTI21_IS_USED)
+ nvicEnableVector(STM32_EXTI20_21_NUMBER, STM32_IRQ_EXTI20_21_PRIORITY);
+#endif
+}
+
+static inline void exti20_exti21_irq_deinit(void) {
+#if defined(STM32_EXTI20_IS_USED) || defined(STM32_EXTI21_IS_USED)
+ nvicDisableVector(STM32_EXTI20_21_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_EXTI20_IS_USED) || defined(STM32_EXTI21_IS_USED) || \
+ defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI20_21_HANDLER)
+/**
+ * @brief EXTI[20], EXTI[21] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI20_21_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1((1U << 20) | (1U << 21), pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI20_ISR)
+ STM32_EXTI20_ISR(pr, 20);
+#endif
+#if defined(STM32_EXTI21_ISR)
+ STM32_EXTI21_ISR(pr, 21);
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti21.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti21.inc
new file mode 100644
index 0000000..350091b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti21.inc
@@ -0,0 +1,100 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti21.inc
+ * @brief Shared EXTI21 handler.
+ *
+ * @addtogroup STM32_EXTI21_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI21_PRIORITY)
+#error "STM32_IRQ_EXTI21_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI21_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI21_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti21_irq_init(void) {
+#if defined(STM32_EXTI21_IS_USED)
+ nvicEnableVector(STM32_EXTI21_NUMBER, STM32_IRQ_EXTI21_PRIORITY);
+#endif
+}
+
+static inline void exti21_irq_deinit(void) {
+#if defined(STM32_EXTI21_IS_USED)
+ nvicDisableVector(STM32_EXTI21_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_EXTI21_IS_USED) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI21_HANDLER)
+/**
+ * @brief EXTI[21] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI21_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1(1U << 21, pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI21_ISR)
+ STM32_EXTI21_ISR(pr, 21);
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti21_22-29.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti21_22-29.inc
new file mode 100644
index 0000000..95ea587
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti21_22-29.inc
@@ -0,0 +1,109 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti21_22-29.inc
+ * @brief Shared EXTI21_22-29 handler.
+ *
+ * @addtogroup STM32_EXTI212229_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI212229_PRIORITY)
+#error "STM32_IRQ_EXTI212229_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI212229_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI212229_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti21_exti22_exti29_irq_init(void) {
+#if defined(STM32_EXTI21_IS_USED) || defined(STM32_EXTI22_IS_USED) || \
+ defined(STM32_EXTI29_IS_USED)
+ nvicEnableVector(STM32_EXTI212229_NUMBER, STM32_IRQ_EXTI212229_PRIORITY);
+#endif
+}
+
+static inline void exti21_exti22_exti29_irq_deinit(void) {
+#if defined(STM32_EXTI21_IS_USED) || defined(STM32_EXTI22_IS_USED) || \
+ defined(STM32_EXTI29_IS_USED)
+ nvicDisableVector(STM32_EXTI212229_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_EXTI21_IS_USED) || defined(STM32_EXTI22_IS_USED) || \
+ defined(STM32_EXTI29_IS_USED) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI212229_HANDLER)
+/**
+ * @brief EXTI[21], EXTI[22], EXTI[29] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI212229_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1((1U << 21) | (1U << 22) | (1U << 29), pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI21_ISR)
+ STM32_EXTI21_ISR(pr, 21);
+#endif
+#if defined(STM32_EXTI22_ISR)
+ STM32_EXTI22_ISR(pr, 22);
+#endif
+#if defined(STM32_EXTI29_ISR)
+ STM32_EXTI29_ISR(pr, 29);
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti21_22.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti21_22.inc
new file mode 100644
index 0000000..973efd5
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti21_22.inc
@@ -0,0 +1,104 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti21_22.inc
+ * @brief Shared EXTI21_22 handler.
+ *
+ * @addtogroup STM32_EXTI21_22_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI21_22_PRIORITY)
+#error "STM32_IRQ_EXTI21_22_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI21_22_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI21_22_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti21_22_irq_init(void) {
+#if defined(STM32_EXTI21_IS_USED) || defined(STM32_EXTI22_IS_USED)
+ nvicEnableVector(STM32_EXTI21_22_NUMBER, STM32_IRQ_EXTI21_22_PRIORITY);
+#endif
+}
+
+static inline void exti21_22_irq_deinit(void) {
+#if defined(STM32_EXTI21_IS_USED) || defined(STM32_EXTI22_IS_USED)
+ nvicDisableVector(STM32_EXTI21_22_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_EXTI21_IS_USED) || defined(STM32_EXTI22_IS_USED) || \
+ defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI21_22_HANDLER)
+/**
+ * @brief EXTI[21], EXTI[22] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI21_22_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1((1U << 21) | (1U << 22), pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI21_ISR)
+ STM32_EXTI21_ISR(pr, 21);
+#endif
+#if defined(STM32_EXTI22_ISR)
+ STM32_EXTI22_ISR(pr, 22);
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti22.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti22.inc
new file mode 100644
index 0000000..e958615
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti22.inc
@@ -0,0 +1,100 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti22.inc
+ * @brief Shared EXTI22 handler.
+ *
+ * @addtogroup STM32_EXTI22_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI22_PRIORITY)
+#error "STM32_IRQ_EXTI22_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI22_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI22_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti22_irq_init(void) {
+#if defined(STM32_EXTI22_IS_USED)
+ nvicEnableVector(STM32_EXTI22_NUMBER, STM32_IRQ_EXTI22_PRIORITY);
+#endif
+}
+
+static inline void exti22_irq_deinit(void) {
+#if defined(STM32_EXTI22_IS_USED)
+ nvicDisableVector(STM32_EXTI22_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_EXTI22_IS_USED) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI22_HANDLER)
+/**
+ * @brief EXTI[22] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI22_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1(1U << 22, pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI22_ISR)
+ STM32_EXTI22_ISR(pr, 22);
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti23.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti23.inc
new file mode 100644
index 0000000..3180234
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti23.inc
@@ -0,0 +1,100 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti23.inc
+ * @brief Shared EXTI23 handler.
+ *
+ * @addtogroup STM32_EXTI23_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI23_PRIORITY)
+#error "STM32_IRQ_EXTI23_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI23_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI23_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti23_irq_init(void) {
+#if defined(STM32_EXTI23_IS_USED)
+ nvicEnableVector(STM32_EXTI23_NUMBER, STM32_IRQ_EXTI23_PRIORITY);
+#endif
+}
+
+static inline void exti23_irq_deinit(void) {
+#if defined(STM32_EXTI23_IS_USED)
+ nvicDisableVector(STM32_EXTI23_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_EXTI23_IS_USED) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI23_HANDLER)
+/**
+ * @brief EXTI[23] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI23_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1(1U << 23, pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI23_ISR)
+ STM32_EXTI23_ISR(pr, 23);
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti2_3.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti2_3.inc
new file mode 100644
index 0000000..5c8ed9a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti2_3.inc
@@ -0,0 +1,96 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti2_3.inc
+ * @brief Shared EXTI2_3 handler.
+ *
+ * @addtogroup STM32_EXTI2_3_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI2_3_PRIORITY)
+#error "STM32_IRQ_EXTI2_3_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI2_3_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI2_3_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti2_3_irq_init(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicEnableVector(STM32_EXTI2_3_NUMBER, STM32_IRQ_EXTI2_3_PRIORITY);
+#endif
+}
+
+static inline void exti2_3_irq_deinit(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicDisableVector(STM32_EXTI2_3_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI2_3_HANDLER)
+/**
+ * @brief EXTI[2], EXTI[3] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI2_3_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1((1U << 2) | (1U << 3), pr);
+
+ exti_serve_irq(pr, 2);
+ exti_serve_irq(pr, 3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti3.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti3.inc
new file mode 100644
index 0000000..9c9be73
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti3.inc
@@ -0,0 +1,95 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti3.inc
+ * @brief Shared EXTI3 handler.
+ *
+ * @addtogroup STM32_EXTI3_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI3_PRIORITY)
+#error "STM32_IRQ_EXTI3_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI3_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI3_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti3_irq_init(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicEnableVector(STM32_EXTI3_NUMBER, STM32_IRQ_EXTI3_PRIORITY);
+#endif
+}
+
+static inline void exti3_irq_deinit(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicDisableVector(STM32_EXTI3_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI3_HANDLER)
+/**
+ * @brief EXTI[3] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI3_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1(1U << 3, pr);
+
+ exti_serve_irq(pr, 3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti30_32.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti30_32.inc
new file mode 100644
index 0000000..b8c1f41
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti30_32.inc
@@ -0,0 +1,119 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti30_32.inc
+ * @brief Shared EXTI30_32 handler.
+ *
+ * @addtogroup STM32_EXTI30_32_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI30_32_PRIORITY)
+#error "STM32_IRQ_EXTI30_32_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI30_32_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI30_32_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti30_32_irq_init(void) {
+#if defined(STM32_EXTI30_IS_USED) || defined(STM32_EXTI31_IS_USED) || \
+ defined(STM32_EXTI32_IS_USED)
+ nvicEnableVector(STM32_EXTI30_32_NUMBER, STM32_IRQ_EXTI30_32_PRIORITY);
+#endif
+}
+
+static inline void exti30_32_irq_deinit(void) {
+#if defined(STM32_EXTI30_IS_USED) || defined(STM32_EXTI31_IS_USED) || \
+ defined(STM32_EXTI32_IS_USED)
+ nvicDisableVector(STM32_EXTI30_32_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_EXTI30_IS_USED) || defined(STM32_EXTI31_IS_USED) || \
+ defined(STM32_EXTI32_IS_USED) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI30_32_HANDLER)
+/**
+ * @brief EXTI[16], EXTI[40], EXTI[41] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI164041_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+#if defined(STM32_EXTI30_IS_USED) || defined(STM32_EXTI31_IS_USED)
+ extiGetAndClearGroup1((1U << 30) | (1U << 31), pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI30_ISR)
+ STM32_EXTI30_ISR(pr, 30);
+#endif
+#if defined(STM32_EXTI31_ISR)
+ STM32_EXTI31_ISR(pr, 31);
+#endif
+#endif
+
+#if defined(STM32_EXTI32_IS_USED)
+ extiGetAndClearGroup2(1U << (32 - 32), pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI32_ISR)
+ STM32_EXTI32_ISR(pr, 32);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti33.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti33.inc
new file mode 100644
index 0000000..3ad874f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti33.inc
@@ -0,0 +1,100 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti33.inc
+ * @brief Shared EXTI33 handler.
+ *
+ * @addtogroup STM32_EXTI33_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI33_PRIORITY)
+#error "STM32_IRQ_EXTI33_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI33_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI33_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti33_irq_init(void) {
+#if defined(STM32_EXTI33_IS_USED)
+ nvicEnableVector(STM32_EXTI33_NUMBER, STM32_IRQ_EXTI33_PRIORITY);
+#endif
+}
+
+static inline void exti33_irq_deinit(void) {
+#if defined(STM32_EXTI33_IS_USED)
+ nvicDisableVector(STM32_EXTI33_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_EXTI33_IS_USED) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI33_HANDLER)
+/**
+ * @brief EXTI[33] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI33_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup2(1U << (33 - 32), pr);
+
+ /* Could be unused.*/
+ (void)pr;
+
+#if defined(STM32_EXTI33_ISR)
+ STM32_EXTI33_ISR(pr, (33 - 32));
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti4.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti4.inc
new file mode 100644
index 0000000..a39e83d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti4.inc
@@ -0,0 +1,95 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti4.inc
+ * @brief Shared EXTI4 handler.
+ *
+ * @addtogroup STM32_EXTI4_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI4_PRIORITY)
+#error "STM32_IRQ_EXTI4_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI4_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI4_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti4_irq_init(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicEnableVector(STM32_EXTI4_NUMBER, STM32_IRQ_EXTI4_PRIORITY);
+#endif
+}
+
+static inline void exti4_irq_deinit(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicDisableVector(STM32_EXTI4_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI4_HANDLER)
+/**
+ * @brief EXTI[4] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI4_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1(1U << 4, pr);
+
+ exti_serve_irq(pr, 4);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti4_15.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti4_15.inc
new file mode 100644
index 0000000..ddb6663
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti4_15.inc
@@ -0,0 +1,108 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti4_15.inc
+ * @brief Shared EXTI4_15 handler.
+ *
+ * @addtogroup STM32_EXTI4_15_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI4_15_PRIORITY)
+#error "STM32_IRQ_EXTI4_15_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI4_15_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI4_15_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti4_15_irq_init(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicEnableVector(STM32_EXTI4_15_NUMBER, STM32_IRQ_EXTI4_15_PRIORITY);
+#endif
+}
+
+static inline void exti4_15_irq_deinit(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicDisableVector(STM32_EXTI4_15_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI4_15_HANDLER)
+/**
+ * @brief EXTI[4]..EXTI[15] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI4_15_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1((1U << 4) | (1U << 5) | (1U << 6) | (1U << 7) |
+ (1U << 8) | (1U << 9) | (1U << 10) | (1U << 11) |
+ (1U << 12) | (1U << 13) | (1U << 14) | (1U << 15), pr);
+
+ exti_serve_irq(pr, 4);
+ exti_serve_irq(pr, 5);
+ exti_serve_irq(pr, 6);
+ exti_serve_irq(pr, 7);
+ exti_serve_irq(pr, 8);
+ exti_serve_irq(pr, 9);
+ exti_serve_irq(pr, 10);
+ exti_serve_irq(pr, 11);
+ exti_serve_irq(pr, 12);
+ exti_serve_irq(pr, 13);
+ exti_serve_irq(pr, 14);
+ exti_serve_irq(pr, 15);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti5_9.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti5_9.inc
new file mode 100644
index 0000000..9a52fa6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/EXTIv1/stm32_exti5_9.inc
@@ -0,0 +1,100 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file EXTIv1/stm32_exti5_9.inc
+ * @brief Shared EXTI5_9 handler.
+ *
+ * @addtogroup STM32_EXTI5_9_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_EXTI5_9_PRIORITY)
+#error "STM32_IRQ_EXTI5_9_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_EXTI5_9_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_EXTI5_9_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void exti5_9_irq_init(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicEnableVector(STM32_EXTI5_9_NUMBER, STM32_IRQ_EXTI5_9_PRIORITY);
+#endif
+}
+
+static inline void exti5_9_irq_deinit(void) {
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS))
+ nvicDisableVector(STM32_EXTI5_9_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if (HAL_USE_PAL && (PAL_USE_WAIT || PAL_USE_CALLBACKS)) || defined(__DOXYGEN__)
+#if !defined(STM32_DISABLE_EXTI5_9_HANDLER)
+/**
+ * @brief EXTI[5]..EXTI[9] interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_EXTI5_9_HANDLER) {
+ uint32_t pr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ extiGetAndClearGroup1((1U << 5) | (1U << 6) | (1U << 7) | (1U << 8) |
+ (1U << 9), pr);
+
+ exti_serve_irq(pr, 5);
+ exti_serve_irq(pr, 6);
+ exti_serve_irq(pr, 7);
+ exti_serve_irq(pr, 8);
+ exti_serve_irq(pr, 9);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/FDCANv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/FDCANv1/driver.mk
new file mode 100644
index 0000000..734c3a0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/FDCANv1/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_CAN TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/FDCANv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c
new file mode 100644
index 0000000..38e5ff6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c
@@ -0,0 +1,566 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file FDCANv1/hal_can_lld.c
+ * @brief STM32 CAN subsystem low level driver source.
+ *
+ * @addtogroup CAN
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_CAN || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/* Filter Standard Element Size in bytes.*/
+#define SRAMCAN_FLS_SIZE (1U * 4U)
+
+/* Filter Extended Element Size in bytes.*/
+#define SRAMCAN_FLE_SIZE (2U * 4U)
+
+/* RX FIFO 0 Elements Size in bytes.*/
+#define SRAMCAN_RF0_SIZE (18U * 4U)
+
+/* RX FIFO 1 Elements Size in bytes.*/
+#define SRAMCAN_RF1_SIZE (18U * 4U)
+
+/* RX Buffer Size in bytes.*/
+#define SRAMCAN_RB_SIZE (18U * 4U)
+
+/* TX Event FIFO Elements Size in bytes.*/
+#define SRAMCAN_TEF_SIZE (2U * 4U)
+
+/* TX FIFO/Queue Elements Size in bytes.*/
+#define SRAMCAN_TB_SIZE (18U * 4U)
+
+/* Trigger Memory Size in bytes.*/
+#define SRAMCAN_TM_SIZE (2U * 4U)
+
+/* Filter List Standard Start Address.*/
+#define SRAMCAN_FLSSA ((uint32_t)0)
+
+/* Filter List Extended Start Address.*/
+#define SRAMCAN_FLESA ((uint32_t)(SRAMCAN_FLSSA + \
+ (STM32_FDCAN_FLS_NBR * SRAMCAN_FLS_SIZE)))
+
+/* RX FIFO 0 Start Address.*/
+#define SRAMCAN_RF0SA ((uint32_t)(SRAMCAN_FLESA + \
+ (STM32_FDCAN_FLE_NBR * SRAMCAN_FLE_SIZE)))
+
+/* RX FIFO 1 Start Address.*/
+#define SRAMCAN_RF1SA ((uint32_t)(SRAMCAN_RF0SA + \
+ (STM32_FDCAN_RF0_NBR * SRAMCAN_RF0_SIZE)))
+
+/* RX Buffer Start Address.*/
+#define SRAMCAN_RBSA ((uint32_t)(SRAMCAN_RF1SA + \
+ (STM32_FDCAN_RF1_NBR * SRAMCAN_RF1_SIZE)))
+
+/* TX Event FIFO Start Address.*/
+#define SRAMCAN_TEFSA ((uint32_t)(SRAMCAN_RBSA + \
+ (STM32_FDCAN_RB_NBR * SRAMCAN_RB_SIZE)))
+
+/* TX Buffers Start Address.*/
+#define SRAMCAN_TBSA ((uint32_t)(SRAMCAN_TEFSA + \
+ (STM32_FDCAN_TEF_NBR * SRAMCAN_TEF_SIZE)))
+
+/* Trigger Memory Start Address.*/
+#define SRAMCAN_TMSA ((uint32_t)(SRAMCAN_TBSA + \
+ (STM32_FDCAN_TB_NBR * SRAMCAN_TB_SIZE)))
+
+/* Message RAM size.*/
+#define SRAMCAN_SIZE ((uint32_t)(SRAMCAN_TMSA + \
+ (STM32_FDCAN_TM_NBR * SRAMCAN_TM_SIZE)))
+
+
+#define TIMEOUT_INIT_MS 250U
+#define TIMEOUT_CSA_MS 250U
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief CAN1 driver identifier.*/
+#if STM32_CAN_USE_FDCAN1 || defined(__DOXYGEN__)
+CANDriver CAND1;
+#endif
+
+/** @brief CAN2 driver identifier.*/
+#if STM32_CAN_USE_FDCAN2 || defined(__DOXYGEN__)
+CANDriver CAND2;
+#endif
+
+/** @brief CAN3 driver identifier.*/
+#if STM32_CAN_USE_FDCAN3 || defined(__DOXYGEN__)
+CANDriver CAND3;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+static const uint8_t dlc_to_bytes[] = {
+ 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U,
+ 8U, 12U, 16U, 20U, 24U, 32U, 48U, 64U
+};
+
+static uint32_t canclk;
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static bool fdcan_clock_stop(CANDriver *canp) {
+ systime_t start, end;
+
+ /* Requesting clock stop then waiting for it to happen.*/
+ canp->fdcan->CCCR |= FDCAN_CCCR_CSR;
+ start = osalOsGetSystemTimeX();
+ end = osalTimeAddX(start, TIME_MS2I(TIMEOUT_INIT_MS));
+ while ((canp->fdcan->CCCR & FDCAN_CCCR_CSA) != 0U) {
+ if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) {
+ return true;
+ }
+ osalThreadSleepS(1);
+ }
+
+ return false;
+}
+
+static bool fdcan_init_mode(CANDriver *canp) {
+ systime_t start, end;
+
+ /* Going in initialization mode then waiting for it to happen.*/
+ canp->fdcan->CCCR |= FDCAN_CCCR_INIT;
+ start = osalOsGetSystemTimeX();
+ end = osalTimeAddX(start, TIME_MS2I(TIMEOUT_INIT_MS));
+ while ((canp->fdcan->CCCR & FDCAN_CCCR_INIT) == 0U) {
+ if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) {
+ return true;
+ }
+ osalThreadSleepS(1);
+ }
+
+ return false;
+}
+
+static bool fdcan_active_mode(CANDriver *canp) {
+ systime_t start, end;
+
+ /* Going in initialization mode then waiting for it to happen.*/
+ canp->fdcan->CCCR &= ~FDCAN_CCCR_INIT;
+ start = osalOsGetSystemTimeX();
+ end = osalTimeAddX(start, TIME_MS2I(TIMEOUT_INIT_MS));
+ while ((canp->fdcan->CCCR & FDCAN_CCCR_INIT) != 0U) {
+ if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) {
+ return true;
+ }
+ osalThreadSleepS(1);
+ }
+
+ return false;
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level CAN driver initialization.
+ *
+ * @notapi
+ */
+void can_lld_init(void) {
+
+ canclk = 0U;
+
+ /* Unit reset.*/
+ rccResetFDCAN();
+
+#if STM32_CAN_USE_FDCAN1
+ /* Driver initialization.*/
+ canObjectInit(&CAND1);
+ CAND1.fdcan = FDCAN1;
+ CAND1.ram_base = (uint32_t *) (SRAMCAN_BASE + 0U * SRAMCAN_SIZE);
+#endif
+
+#if STM32_CAN_USE_FDCAN2
+ /* Driver initialization.*/
+ canObjectInit(&CAND2);
+ CAND2.fdcan = FDCAN2;
+ CAND2.ram_base = (uint32_t *) (SRAMCAN_BASE + 1U * SRAMCAN_SIZE);
+#endif
+
+#if STM32_CAN_USE_FDCAN3
+ /* Driver initialization.*/
+ canObjectInit(&CAND3);
+ CAND3.fdcan = FDCAN3;
+ CAND3.ram_base = (uint32_t *) (SRAMCAN_BASE + 2U * SRAMCAN_SIZE);
+#endif
+}
+
+/**
+ * @brief Configures and activates the CAN peripheral.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @return The operation result.
+ * @retval false if the operation succeeded.
+ * @retval true if the operation failed.
+ *
+ * @notapi
+ */
+bool can_lld_start(CANDriver *canp) {
+
+ /* Clock activation.*/
+ rccEnableFDCAN(true);
+
+ /* If it is the first activation then performing some extra
+ initializations.*/
+ if (canclk == 0U) {
+ for (uint32_t *wp = canp->ram_base;
+ wp < canp->ram_base + SRAMCAN_SIZE;
+ wp += 1U) {
+ *wp = (uint32_t)0U;
+ }
+ }
+
+#if STM32_CAN_USE_FDCAN1
+ if (&CAND1 == canp) {
+ canclk |= 1U;
+ }
+#endif
+
+#if STM32_CAN_USE_FDCAN2
+ if (&CAND2 == canp) {
+ canclk |= 2U;
+ }
+#endif
+
+#if STM32_CAN_USE_FDCAN3
+ if (&CAND3 == canp) {
+ canclk |= 4U;
+ }
+#endif
+
+ /* Requesting clock stop.*/
+ if (fdcan_clock_stop(canp)) {
+ osalDbgAssert(false, "CAN clock stop failed, check clocks and pin config");
+ return true;
+ }
+
+ /* Going in initialization mode.*/
+ if (fdcan_init_mode(canp)) {
+ osalDbgAssert(false, "CAN initialization failed, check clocks and pin config");
+ return true;
+ }
+
+ /* Configuration can be performed now.*/
+ canp->fdcan->CCCR |= FDCAN_CCCR_CCE;
+
+ /* Setting up operation mode except driver-controlled bits.*/
+ canp->fdcan->DBTP = canp->config->DBTP;
+ canp->fdcan->CCCR = canp->config->CCCR & ~(FDCAN_CCCR_CSR | FDCAN_CCCR_CSA |
+ FDCAN_CCCR_CCE | FDCAN_CCCR_INIT);
+ canp->fdcan->TEST = canp->config->TEST;
+
+ /* Enabling interrupts, only using interrupt zero.*/
+ canp->fdcan->IR = (uint32_t)-1;
+ canp->fdcan->IE = FDCAN_IE_RF1NE | FDCAN_IE_RF1LE |
+ FDCAN_IE_RF0NE | FDCAN_IE_RF0LE |
+ FDCAN_IE_TCE;
+ canp->fdcan->ILE = FDCAN_ILE_EINT0;
+
+ /* Going in active mode.*/
+ if (fdcan_active_mode(canp)) {
+ osalDbgAssert(false, "CAN initialization failed, check clocks and pin config");
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * @brief Deactivates the CAN peripheral.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+void can_lld_stop(CANDriver *canp) {
+
+ /* If in ready state then disables the CAN peripheral.*/
+ if (canp->state == CAN_READY) {
+ /* Disabling and clearing interrupts.*/
+ canp->fdcan->IE = 0U;
+ canp->fdcan->IR = (uint32_t)-1;
+ canp->fdcan->ILE = 0U;
+
+ /* Disables the peripheral.*/
+ (void) fdcan_clock_stop(canp);
+
+#if STM32_CAN_USE_FDCAN1
+ if (&CAND1 == canp) {
+ canclk &= ~1U;
+ }
+#endif
+
+#if STM32_CAN_USE_FDCAN2
+ if (&CAND2 == canp) {
+ canclk &= ~2U;
+ }
+#endif
+
+#if STM32_CAN_USE_FDCAN3
+ if (&CAND3 == canp) {
+ canclk &= ~4U;
+ }
+#endif
+
+ if (canclk == 0U) {
+ rccDisableFDCAN();
+ }
+ }
+}
+
+/**
+ * @brief Determines whether a frame can be transmitted.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
+ *
+ * @return The queue space availability.
+ * @retval false no space in the transmit queue.
+ * @retval true transmit slot available.
+ *
+ * @notapi
+ */
+bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) {
+
+ (void)mailbox;
+
+ return (bool)((canp->fdcan->TXFQS & FDCAN_TXFQS_TFQF) == 0U);
+}
+
+/**
+ * @brief Inserts a frame into the transmit queue.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] ctfp pointer to the CAN frame to be transmitted
+ * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
+ *
+ * @notapi
+ */
+void can_lld_transmit(CANDriver *canp,
+ canmbx_t mailbox,
+ const CANTxFrame *ctfp) {
+ uint32_t *tx_address;
+
+ (void)mailbox;
+
+ osalDbgCheck(dlc_to_bytes[ctfp->DLC] <= CAN_MAX_DLC_BYTES);
+
+ /* Writing frame.*/
+ tx_address = canp->ram_base + (SRAMCAN_TBSA / sizeof (uint32_t));
+ *tx_address++ = ctfp->header32[0];
+ *tx_address++ = ctfp->header32[1];
+ for (unsigned i = 0U; i < dlc_to_bytes[ctfp->DLC]; i += 4U) {
+ *tx_address++ = ctfp->data32[i / 4U];
+ }
+}
+
+/**
+ * @brief Determines whether a frame has been received.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
+ *
+ * @return The queue space availability.
+ * @retval false no space in the transmit queue.
+ * @retval true transmit slot available.
+ *
+ * @notapi
+ */
+bool can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox) {
+
+ switch (mailbox) {
+ case CAN_ANY_MAILBOX:
+ return can_lld_is_rx_nonempty(canp, 1U) ||
+ can_lld_is_rx_nonempty(canp, 2U);
+ case 1:
+ return (bool)((canp->fdcan->RXF0S & FDCAN_RXF0S_F0FL) != 0U);
+ case 2:
+ return (bool)((canp->fdcan->RXF1S & FDCAN_RXF1S_F1FL) != 0U);
+ default:
+ return false;
+ }
+}
+
+/**
+ * @brief Receives a frame from the input queue.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
+ * @param[out] crfp pointer to the buffer where the CAN frame is copied
+ *
+ * @notapi
+ */
+void can_lld_receive(CANDriver *canp, canmbx_t mailbox, CANRxFrame *crfp) {
+ uint32_t get_index;
+ uint32_t *rx_address;
+
+ if (mailbox == CAN_ANY_MAILBOX) {
+ if (can_lld_is_rx_nonempty(canp, 1U)) {
+ mailbox = 1U;
+ }
+ else if (can_lld_is_rx_nonempty(canp, 2U)) {
+ mailbox = 2U;
+ }
+ else {
+ return;
+ }
+ }
+
+ /* GET index, add it and the length to the rx_address.*/
+ get_index = (canp->fdcan->RXF0S & FDCAN_RXF0S_F0GI_Msk) >> FDCAN_RXF0S_F0GI_Pos;
+ rx_address = canp->ram_base + (SRAMCAN_RF0SA +
+ (get_index * SRAMCAN_RF0_SIZE)) / sizeof (uint32_t);
+ crfp->header32[0] = *rx_address++;
+ crfp->header32[1] = *rx_address++;
+
+ /* Copy message from FDCAN peripheral's SRAM to structure. RAM is restricted
+ to word aligned accesses, so up to 3 extra bytes may be copied.*/
+ for (unsigned i = 0U; i < dlc_to_bytes[crfp->DLC]; i += 4U) {
+ crfp->data32[i / 4U] = *rx_address++;
+ }
+
+ /* Acknowledge receipt by writing the get-index to the acknowledge
+ register RXFxA then re-enable RX FIFO message arrived interrupt once
+ the FIFO is emptied.*/
+ if (mailbox == 1U) {
+ uint32_t rxf0a = canp->fdcan->RXF0A;
+ rxf0a &= ~FDCAN_RXF0A_F0AI_Msk;
+ rxf0a |= get_index << FDCAN_RXF0A_F0AI_Pos;
+ canp->fdcan->RXF0A = rxf0a;
+
+ if (!can_lld_is_rx_nonempty(canp, mailbox)) {
+// canp->fdcan->IR = FDCAN_IR_RF0N;
+ canp->fdcan->IE |= FDCAN_IE_RF0NE;
+ }
+ }
+ else {
+ uint32_t rxf1a = canp->fdcan->RXF1A;
+ rxf1a &= ~FDCAN_RXF1A_F1AI_Msk;
+ rxf1a |= get_index << FDCAN_RXF1A_F1AI_Pos;
+ canp->fdcan->RXF1A = rxf1a;
+
+ if (!can_lld_is_rx_nonempty(canp, mailbox)) {
+// canp->fdcan->IR = FDCAN_IR_RF1N;
+ canp->fdcan->IE |= FDCAN_IE_RF1NE;
+ }
+ }
+}
+
+/**
+ * @brief Tries to abort an ongoing transmission.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] mailbox mailbox number
+ *
+ * @notapi
+ */
+void can_lld_abort(CANDriver *canp, canmbx_t mailbox) {
+
+ (void)canp;
+ (void)mailbox;
+}
+
+#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__)
+/**
+ * @brief Enters the sleep mode.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+void can_lld_sleep(CANDriver *canp) {
+
+ (void)canp;
+}
+
+/**
+ * @brief Enforces leaving the sleep mode.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+void can_lld_wakeup(CANDriver *canp) {
+
+ (void)canp;
+}
+#endif /* CAN_USE_SLEEP_MODE */
+
+/**
+ * @brief FDCAN IRQ0 service routine.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+void can_lld_serve_interrupt(CANDriver *canp) {
+ uint32_t ir;
+
+ /* Getting and clearing active IRQs.*/
+ ir = canp->fdcan->IR;
+ canp->fdcan->IR = ir;
+
+ /* RX events.*/
+ if ((ir & FDCAN_IR_RF0N) != 0U) {
+ /* Disabling this source until the queue is emptied.*/
+ canp->fdcan->IE &= ~FDCAN_IE_RF0NE;
+ _can_rx_full_isr(canp, CAN_MAILBOX_TO_MASK(1U));
+ }
+ if ((ir & FDCAN_IR_RF1N) != 0U) {
+ /* Disabling this source until the queue is emptied.*/
+ canp->fdcan->IE &= ~FDCAN_IE_RF1NE;
+ _can_rx_full_isr(canp, CAN_MAILBOX_TO_MASK(2U));
+ }
+
+ /* Overflow events.*/
+ if ((ir & FDCAN_IR_RF0N) != 0U) {
+ _can_error_isr(canp, CAN_OVERFLOW_ERROR);
+ }
+
+ /* TX events.*/
+ if ((ir & FDCAN_IR_TC) != 0U) {
+ eventflags_t flags = 0U;
+
+ flags |= 1U;
+ _can_tx_empty_isr(canp, flags);
+ }
+}
+
+#endif /* HAL_USE_CAN */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.h
new file mode 100644
index 0000000..eb02c34
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.h
@@ -0,0 +1,470 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file FDCANv1/hal_can_lld.h
+ * @brief STM32 CAN subsystem low level driver header.
+ *
+ * @addtogroup CAN
+ * @{
+ */
+
+#ifndef HAL_CAN_LLD_H
+#define HAL_CAN_LLD_H
+
+#if HAL_USE_CAN || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Maximum number of bytes in data of CAN packets.
+ */
+#define CAN_MAX_DLC_BYTES 64
+
+/**
+ * @brief Number of transmit mailboxes.
+ */
+#define CAN_TX_MAILBOXES 1
+
+/**
+ * @brief Number of receive mailboxes.
+ */
+#define CAN_RX_MAILBOXES 2
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief CAN1 driver enable switch.
+ * @details If set to @p TRUE the support for FDCAN1 is included.
+ */
+#if !defined(STM32_CAN_USE_FDCAN1) || defined(__DOXYGEN__)
+#define STM32_CAN_USE_FDCAN1 FALSE
+#endif
+
+/**
+ * @brief CAN2 driver enable switch.
+ * @details If set to @p TRUE the support for FDCAN2 is included.
+ */
+#if !defined(STM32_CAN_USE_FDCAN2) || defined(__DOXYGEN__)
+#define STM32_CAN_USE_FDCAN2 FALSE
+#endif
+
+/**
+ * @brief CAN3 driver enable switch.
+ * @details If set to @p TRUE the support for FDCAN3 is included.
+ */
+#if !defined(STM32_CAN_USE_FDCAN3) || defined(__DOXYGEN__)
+#define STM32_CAN_USE_FDCAN3 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !defined(STM32_HAS_FDCAN1)
+#error "STM32_HAS_FDCAN1 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_FDCAN2)
+#error "STM32_HAS_FDCAN2 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_FDCAN3)
+#error "STM32_HAS_FDCAN3 not defined in registry"
+#endif
+
+#if STM32_CAN_USE_FDCAN1 && !STM32_HAS_FDCAN1
+#error "FDCAN1 not present in the selected device"
+#endif
+
+#if STM32_CAN_USE_FDCAN2 && !STM32_HAS_FDCAN2
+#error "FDCAN2 not present in the selected device"
+#endif
+
+#if STM32_CAN_USE_FDCAN3 && !STM32_HAS_FDCAN3
+#error "FDCAN3 not present in the selected device"
+#endif
+
+#if !STM32_CAN_USE_FDCAN1 && !STM32_CAN_USE_FDCAN2 && !STM32_CAN_USE_FDCAN3
+#error "CAN driver activated but no FDCAN peripheral assigned"
+#endif
+
+#if !defined(STM32_FDCAN_FLS_NBR)
+#error "STM32_FDCAN_FLS_NBR not defined in registry"
+#endif
+
+#if !defined(STM32_FDCAN_FLE_NBR)
+#error "STM32_FDCAN_FLE_NBR not defined in registry"
+#endif
+
+#if !defined(STM32_FDCAN_RF0_NBR)
+#error "STM32_FDCAN_RF0_NBR not defined in registry"
+#endif
+
+#if !defined(STM32_FDCAN_RF1_NBR)
+#error "STM32_FDCAN_RF1_NBR not defined in registry"
+#endif
+
+#if !defined(STM32_FDCAN_RB_NBR)
+#error "STM32_FDCAN_RB_NBR not defined in registry"
+#endif
+
+#if !defined(STM32_FDCAN_TEF_NBR)
+#error "STM32_FDCAN_TEF_NBR not defined in registry"
+#endif
+
+#if !defined(STM32_FDCAN_TB_NBR)
+#error "STM32_FDCAN_TB_NBR not defined in registry"
+#endif
+
+#if !defined(STM32_FDCAN_TM_NBR)
+#error "STM32_FDCAN_TM_NBR not defined in registry"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a structure representing an CAN driver.
+ */
+typedef struct CANDriver CANDriver;
+
+/**
+ * @brief Type of a transmission mailbox index.
+ */
+typedef uint32_t canmbx_t;
+
+#if (CAN_ENFORCE_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a CAN notification callback.
+ *
+ * @param[in] canp pointer to the @p CANDriver object triggering the
+ * callback
+ * @param[in] flags flags associated to the mailbox callback
+ */
+typedef void (*can_callback_t)(CANDriver *canp, uint32_t flags);
+#endif
+
+/**
+ * @brief CAN transmission frame.
+ * @note Accessing the frame data as word16 or word32 is not portable
+ * because machine data endianness, it can be still useful for a
+ * quick filling.
+ */
+typedef struct {
+ /**
+ * @brief Frame header.
+ */
+ union {
+ struct {
+ union {
+ uint32_t EID:29; /**< @brief Extended identifier. */
+ struct {
+ uint32_t _R1:18; /**< @brief Reserved for offset. */
+ uint32_t SID:11; /**< @brief Standard identifier. */
+ uint32_t RTR:1; /**< @brief Remote transmit request.*/
+ uint32_t XTD:1; /**< @brief Extended identifier. */
+ uint32_t ESI:1; /**< @brief Error state indicator. */
+ };
+ };
+ uint32_t _R2:16;
+ uint32_t DLC:4; /**< @brief Data length code. */
+ uint32_t BPS:1; /**< @brief Accepted non-matching
+ frame. */
+ uint32_t FDF:1; /**< @brief FDCAN frame format. */
+ uint32_t _R3:1;
+ uint32_t EFC:1; /**< @brief Event FIFO control. */
+ uint32_t MM:8; /**< @brief Message event marker. */
+ };
+ uint32_t header32[2];
+ };
+ /**
+ * @brief Frame data.
+ */
+ union {
+ uint8_t data8[CAN_MAX_DLC_BYTES];
+ uint16_t data16[CAN_MAX_DLC_BYTES / 2];
+ uint32_t data32[CAN_MAX_DLC_BYTES / 4];
+ };
+} CANTxFrame;
+
+/**
+ * @brief CAN received frame.
+ * @note Accessing the frame data as word16 or word32 is not portable
+ * because machine data endianness, it can be still useful for a
+ * quick filling.
+ */
+typedef struct {
+ /**
+ * @brief Frame header.
+ */
+ struct {
+ union {
+ uint32_t EID:29; /**< @brief Extended Identifier. */
+ struct {
+ uint32_t _R1:18;
+ uint32_t SID:11; /**< @brief Standard identifier. */
+ uint32_t RTR:1; /**< @brief Remote transmit request.*/
+ uint32_t XTD:1; /**< @brief Extended identifier. */
+ uint32_t ESI:1; /**< @brief Error state indicator. */
+ };
+ };
+ uint16_t RXTS:16; /**< @brief TX time stamp. */
+ uint8_t DLC:4; /**< @brief Data length code. */
+ uint8_t BRS:1; /**< @brief Bit rate switch. */
+ uint8_t FDF:1; /**< @brief FDCAN frame format. */
+ uint8_t _R2:2;
+ uint8_t FIDX:7; /**< @brief Filter index. */
+ uint8_t ANMF:1; /**< @brief Accepted non-matching
+ frame. */
+ };
+ uint32_t header32[2];
+ /**
+ * @brief Frame data.
+ */
+ union {
+ uint8_t data8[CAN_MAX_DLC_BYTES];
+ uint16_t data16[CAN_MAX_DLC_BYTES / 2];
+ uint32_t data32[CAN_MAX_DLC_BYTES / 4];
+ };
+} CANRxFrame;
+
+/**
+ * @brief CAN standard filter.
+ * @note Accessing the frame data as word16 or word32 is not portable
+ * because machine data endianness, it can be still useful for a
+ * quick filling.
+ */
+typedef struct {
+ union {
+ struct {
+ uint16_t SFID2:11;
+ uint8_t _R1:5;
+ uint16_t SFID1:11;
+ uint8_t SFEC:3;
+ uint8_t SFT:2;
+ };
+ union {
+ uint32_t data32;
+ uint16_t data16[2];
+ uint8_t data8[4];
+ };
+ };
+} CANRxStandardFilter;
+
+
+/**
+ * @brief CAN extended filter.
+ * @note Accessing the frame data as word16 or word32 is not portable
+ * because machine data endianness, it can be still useful for a
+ * quick filling.
+*/
+typedef struct {
+ union {
+ struct {
+ uint32_t EFID1:29;
+ uint8_t EFEC:3;
+ uint32_t EFID2:29;
+ uint8_t _R1:1;
+ uint8_t EFT:2;
+ };
+ union {
+ uint32_t data32[2];
+ uint16_t data16[4];
+ uint8_t data8[8];
+ };
+ };
+} CANRxExtendedFilter;
+
+
+/**
+ * @brief Driver configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief Data bit timing and prescaler register.
+ */
+ uint32_t DBTP;
+ /**
+ * @brief CC control register.
+ */
+ uint32_t CCCR;
+ /**
+ * @brief Test configuration register.
+ */
+ uint32_t TEST;
+} CANConfig;
+
+/**
+ * @brief Structure representing an CAN driver.
+ */
+struct CANDriver {
+ /**
+ * @brief Driver state.
+ */
+ canstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const CANConfig *config;
+ /**
+ * @brief Transmission threads queue.
+ */
+ threads_queue_t txqueue;
+ /**
+ * @brief Receive threads queue.
+ */
+ threads_queue_t rxqueue;
+#if (CAN_ENFORCE_USE_CALLBACKS == FALSE) || defined(__DOXYGEN__)
+ /**
+ * @brief One or more frames become available.
+ * @note After broadcasting this event it will not be broadcasted again
+ * until the received frames queue has been completely emptied. It
+ * is not broadcasted for each received frame. It is
+ * responsibility of the application to empty the queue by
+ * repeatedly invoking @p canReceive() when listening to this event.
+ * This behavior minimizes the interrupt served by the system
+ * because CAN traffic.
+ * @note The flags associated to the listeners will indicate which
+ * receive mailboxes become non-empty.
+ */
+ event_source_t rxfull_event;
+ /**
+ * @brief One or more transmission mailbox become available.
+ * @note The flags associated to the listeners will indicate which
+ * transmit mailboxes become empty.
+ * @note The upper 16 bits are transmission error flags associated
+ * to the transmit mailboxes.
+ */
+ event_source_t txempty_event;
+ /**
+ * @brief A CAN bus error happened.
+ * @note The flags associated to the listeners will indicate that
+ * receive error(s) have occurred.
+ * @note In this implementation the upper 16 bits are filled with the
+ * unprocessed content of the ESR register.
+ */
+ event_source_t error_event;
+#if CAN_USE_SLEEP_MODE || defined (__DOXYGEN__)
+ /**
+ * @brief Entering sleep state event.
+ */
+ event_source_t sleep_event;
+ /**
+ * @brief Exiting sleep state event.
+ */
+ event_source_t wakeup_event;
+#endif /* CAN_USE_SLEEP_MODE */
+#else /* CAN_ENFORCE_USE_CALLBACKS == TRUE */
+ /**
+ * @brief One or more frames become available.
+ * @note After calling this function it will not be called again
+ * until the received frames queue has been completely emptied. It
+ * is not called for each received frame. It is
+ * responsibility of the application to empty the queue by
+ * repeatedly invoking @p chTryReceiveI().
+ * This behavior minimizes the interrupt served by the system
+ * because CAN traffic.
+ */
+ can_callback_t rxfull_cb;
+ /**
+ * @brief One or more transmission mailbox become available.
+ * @note The flags associated to the callback will indicate which
+ * transmit mailboxes become empty.
+ */
+ can_callback_t txempty_cb;
+ /**
+ * @brief A CAN bus error happened.
+ */
+ can_callback_t error_cb;
+#if (CAN_USE_SLEEP_MODE == TRUE) || defined (__DOXYGEN__)
+ /**
+ * @brief Exiting sleep state.
+ */
+ can_callback_t wakeup_cb;
+#endif
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Pointer to the CAN registers.
+ */
+ FDCAN_GlobalTypeDef *fdcan;
+ /**
+ * @brief Pointer to FDCAN RAM base.
+ */
+ uint32_t *ram_base;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_CAN_USE_FDCAN1 && !defined(__DOXYGEN__)
+extern CANDriver CAND1;
+#endif
+
+#if STM32_CAN_USE_FDCAN2 && !defined(__DOXYGEN__)
+extern CANDriver CAND2;
+#endif
+
+#if STM32_CAN_USE_FDCAN3 && !defined(__DOXYGEN__)
+extern CANDriver CAND3;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void can_lld_init(void);
+ bool can_lld_start(CANDriver *canp);
+ void can_lld_stop(CANDriver *canp);
+ bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox);
+ void can_lld_transmit(CANDriver *canp,
+ canmbx_t mailbox,
+ const CANTxFrame *crfp);
+ bool can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox);
+ void can_lld_receive(CANDriver *canp,
+ canmbx_t mailbox,
+ CANRxFrame *ctfp);
+ void can_lld_abort(CANDriver *canp,
+ canmbx_t mailbox);
+#if CAN_USE_SLEEP_MODE
+ void can_lld_sleep(CANDriver *canp);
+ void can_lld_wakeup(CANDriver *canp);
+#endif /* CAN_USE_SLEEP_MODE */
+ void can_lld_serve_interrupt(CANDriver *canp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_CAN */
+
+#endif /* HAL_CAN_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/FDCANv1/stm32_fdcan1.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/FDCANv1/stm32_fdcan1.inc
new file mode 100644
index 0000000..4f6fd37
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/FDCANv1/stm32_fdcan1.inc
@@ -0,0 +1,106 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file FDCANv1/stm32_fdcan1.inc
+ * @brief Shared FDCAN1 handler.
+ *
+ * @addtogroup STM32_FDCAN1_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_FDCAN1)
+#error "STM32_HAS_FDCAN1 not defined in registry"
+#endif
+
+#if STM32_HAS_FDCAN1
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_FDCAN1_PRIORITY)
+#error "STM32_IRQ_FDCAN1_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_FDCAN1_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_FDCAN1_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_FDCAN1 */
+
+/* Other checks.*/
+#if HAL_USE_CAN && STM32_CAN_USE_FDCAN1
+#define STM32_FDCAN1_IS_USED TRUE
+#else
+#define STM32_FDCAN1_IS_USED FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void fdcan1_irq_init(void) {
+#if STM32_FDCAN1_IS_USED
+ nvicEnableVector(STM32_FDCAN1_IT0_NUMBER, STM32_IRQ_FDCAN1_PRIORITY);
+#endif
+}
+
+static inline void fdcan1_irq_deinit(void) {
+#if STM32_FDCAN1_IS_USED
+ nvicDisableVector(STM32_FDCAN1_IT0_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_FDCAN1_IS_USED|| defined(__DOXYGEN__)
+/**
+ * @brief FDCAN1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_FDCAN1_IT0_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ can_lld_serve_interrupt(&CAND1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/FDCANv1/stm32_fdcan2.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/FDCANv1/stm32_fdcan2.inc
new file mode 100644
index 0000000..2226260
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/FDCANv1/stm32_fdcan2.inc
@@ -0,0 +1,106 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file FDCANv1/stm32_fdcan2.inc
+ * @brief Shared FDCAN2 handler.
+ *
+ * @addtogroup STM32_FDCAN2_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_FDCAN2)
+#error "STM32_HAS_FDCAN2 not defined in registry"
+#endif
+
+#if STM32_HAS_FDCAN2
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_FDCAN2_PRIORITY)
+#error "STM32_IRQ_FDCAN2_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_FDCAN2_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_FDCAN2_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_FDCAN2 */
+
+/* Other checks.*/
+#if HAL_USE_CAN && STM32_CAN_USE_FDCAN2
+#define STM32_FDCAN2_IS_USED TRUE
+#else
+#define STM32_FDCAN2_IS_USED FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void fdcan2_irq_init(void) {
+#if STM32_FDCAN2_IS_USED
+ nvicEnableVector(STM32_FDCAN2_IT0_NUMBER, STM32_IRQ_FDCAN2_PRIORITY);
+#endif
+}
+
+static inline void fdcan2_irq_deinit(void) {
+#if STM32_FDCAN2_IS_USED
+ nvicDisableVector(STM32_FDCAN2_IT0_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_FDCAN2_IS_USED|| defined(__DOXYGEN__)
+/**
+ * @brief FDCAN2 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_FDCAN2_IT0_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ can_lld_serve_interrupt(&CAND2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/FDCANv1/stm32_fdcan3.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/FDCANv1/stm32_fdcan3.inc
new file mode 100644
index 0000000..153a29f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/FDCANv1/stm32_fdcan3.inc
@@ -0,0 +1,106 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file FDCANv1/stm32_fdcan3.inc
+ * @brief Shared FDCAN3 handler.
+ *
+ * @addtogroup STM32_FDCAN3_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_FDCAN3)
+#error "STM32_HAS_FDCAN3 not defined in registry"
+#endif
+
+#if STM32_HAS_FDCAN3
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_FDCAN3_PRIORITY)
+#error "STM32_IRQ_FDCAN3_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_FDCAN3_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_FDCAN3_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_FDCAN3 */
+
+/* Other checks.*/
+#if HAL_USE_CAN && STM32_CAN_USE_FDCAN3
+#define STM32_FDCAN3_IS_USED TRUE
+#else
+#define STM32_FDCAN3_IS_USED FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void fdcan3_irq_init(void) {
+#if STM32_FDCAN3_IS_USED
+ nvicEnableVector(STM32_FDCAN3_IT0_NUMBER, STM32_IRQ_FDCAN3_PRIORITY);
+#endif
+}
+
+static inline void fdcan3_irq_deinit(void) {
+#if STM32_FDCAN3_IS_USED
+ nvicDisableVector(STM32_FDCAN3_IT0_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_FDCAN3_IS_USED|| defined(__DOXYGEN__)
+/**
+ * @brief FDCAN3 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_FDCAN3_IT0_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ can_lld_serve_interrupt(&CAND3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv1/driver.mk
new file mode 100644
index 0000000..5e428a7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv1/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_PAL TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.c
new file mode 100644
index 0000000..99106bc
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.c
@@ -0,0 +1,300 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file GPIOv1/hal_pal_lld.c
+ * @brief STM32 PAL low level driver code.
+ *
+ * @addtogroup PAL
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_PAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#if STM32_HAS_GPIOG
+#define APB2_EN_MASK (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \
+ RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | \
+ RCC_APB2ENR_IOPEEN | RCC_APB2ENR_IOPFEN | \
+ RCC_APB2ENR_IOPGEN | RCC_APB2ENR_AFIOEN)
+#elif STM32_HAS_GPIOE
+#define APB2_EN_MASK (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \
+ RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | \
+ RCC_APB2ENR_IOPEEN | RCC_APB2ENR_AFIOEN)
+#else
+#define APB2_EN_MASK (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \
+ RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | \
+ RCC_APB2ENR_AFIOEN)
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Event records for the 16 GPIO EXTI channels.
+ */
+palevent_t _pal_events[16];
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 I/O ports configuration.
+ * @details Ports A-D(E, F, G) clocks enabled, AFIO clock enabled.
+ *
+ * @param[in] config the STM32 ports configuration
+ *
+ * @notapi
+ */
+void _pal_lld_init(const PALConfig *config) {
+
+#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__)
+ unsigned i;
+
+ for (i = 0; i < 16; i++) {
+ _pal_init_event(i);
+ }
+#endif
+
+ /*
+ * Enables the GPIO related clocks.
+ */
+ rccEnableAPB2(APB2_EN_MASK, true);
+
+ /*
+ * Initial GPIO setup.
+ */
+ GPIOA->ODR = config->PAData.odr;
+ GPIOA->CRH = config->PAData.crh;
+ GPIOA->CRL = config->PAData.crl;
+ GPIOB->ODR = config->PBData.odr;
+ GPIOB->CRH = config->PBData.crh;
+ GPIOB->CRL = config->PBData.crl;
+ GPIOC->ODR = config->PCData.odr;
+ GPIOC->CRH = config->PCData.crh;
+ GPIOC->CRL = config->PCData.crl;
+ GPIOD->ODR = config->PDData.odr;
+ GPIOD->CRH = config->PDData.crh;
+ GPIOD->CRL = config->PDData.crl;
+#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
+ GPIOE->ODR = config->PEData.odr;
+ GPIOE->CRH = config->PEData.crh;
+ GPIOE->CRL = config->PEData.crl;
+#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
+ GPIOF->ODR = config->PFData.odr;
+ GPIOF->CRH = config->PFData.crh;
+ GPIOF->CRL = config->PFData.crl;
+#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
+ GPIOG->ODR = config->PGData.odr;
+ GPIOG->CRH = config->PGData.crh;
+ GPIOG->CRL = config->PGData.crl;
+#endif
+#endif
+#endif
+}
+
+/**
+ * @brief Pads mode setup.
+ * @details This function programs a pads group belonging to the same port
+ * with the specified mode.
+ * @note @p PAL_MODE_UNCONNECTED is implemented as push pull output at 2MHz.
+ * @note Writing on pads programmed as pull-up or pull-down has the side
+ * effect to modify the resistor setting because the output latched
+ * data is used for the resistor selection.
+ *
+ * @param[in] port the port identifier
+ * @param[in] mask the group mask
+ * @param[in] mode the mode
+ *
+ * @notapi
+ */
+void _pal_lld_setgroupmode(ioportid_t port,
+ ioportmask_t mask,
+ iomode_t mode) {
+ static const uint8_t cfgtab[] = {
+ 4, /* PAL_MODE_RESET, implemented as input.*/
+ 2, /* PAL_MODE_UNCONNECTED, implemented as push pull output 2MHz.*/
+ 4, /* PAL_MODE_INPUT */
+ 8, /* PAL_MODE_INPUT_PULLUP */
+ 8, /* PAL_MODE_INPUT_PULLDOWN */
+ 0, /* PAL_MODE_INPUT_ANALOG */
+ 3, /* PAL_MODE_OUTPUT_PUSHPULL, 50MHz.*/
+ 7, /* PAL_MODE_OUTPUT_OPENDRAIN, 50MHz.*/
+ 8, /* Reserved.*/
+ 8, /* Reserved.*/
+ 8, /* Reserved.*/
+ 8, /* Reserved.*/
+ 8, /* Reserved.*/
+ 8, /* Reserved.*/
+ 8, /* Reserved.*/
+ 8, /* Reserved.*/
+ 0xB, /* PAL_MODE_STM32_ALTERNATE_PUSHPULL, 50MHz.*/
+ 0xF, /* PAL_MODE_STM32_ALTERNATE_OPENDRAIN, 50MHz.*/
+ };
+ uint32_t mh, ml, crh, crl, cfg;
+ unsigned i;
+
+ if (mode == PAL_MODE_INPUT_PULLUP)
+ port->BSRR = mask;
+ else if (mode == PAL_MODE_INPUT_PULLDOWN)
+ port->BRR = mask;
+ cfg = cfgtab[mode];
+ mh = ml = crh = crl = 0;
+ for (i = 0; i < 8; i++) {
+ ml <<= 4;
+ mh <<= 4;
+ crl <<= 4;
+ crh <<= 4;
+ if ((mask & 0x0080) == 0)
+ ml |= 0xf;
+ else
+ crl |= cfg;
+ if ((mask & 0x8000) == 0)
+ mh |= 0xf;
+ else
+ crh |= cfg;
+ mask <<= 1;
+ }
+ port->CRH = (port->CRH & mh) | crh;
+ port->CRL = (port->CRL & ml) | crl;
+}
+
+#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__)
+/**
+ * @brief Pad event enable.
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] mode pad event mode
+ *
+ * @notapi
+ */
+void _pal_lld_enablepadevent(ioportid_t port,
+ iopadid_t pad,
+ ioeventmode_t mode) {
+
+ uint32_t padmask, cridx, croff, crmask, portidx;
+
+ /* Mask of the pad.*/
+ padmask = 1U << (uint32_t)pad;
+
+ /* Multiple channel setting of the same channel not allowed, first disable
+ it. This is done because on STM32 the same channel cannot be mapped on
+ multiple ports.*/
+ osalDbgAssert(((EXTI->RTSR & padmask) == 0U) &&
+ ((EXTI->FTSR & padmask) == 0U), "channel already in use");
+
+ /* Index and mask of the SYSCFG CR register to be used.*/
+ cridx = (uint32_t)pad >> 2U;
+ croff = ((uint32_t)pad & 3U) * 4U;
+ crmask = ~(0xFU << croff);
+
+ /* Port index is obtained assuming that GPIO ports are placed at regular
+ 0x400 intervals in memory space. So far this is true for all devices.*/
+ portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU;
+
+ /* Port selection in SYSCFG.*/
+ AFIO->EXTICR[cridx] = (AFIO->EXTICR[cridx] & crmask) | (portidx << croff);
+
+ /* Programming edge registers.*/
+ if (mode & PAL_EVENT_MODE_RISING_EDGE)
+ EXTI->RTSR |= padmask;
+ else
+ EXTI->RTSR &= ~padmask;
+ if (mode & PAL_EVENT_MODE_FALLING_EDGE)
+ EXTI->FTSR |= padmask;
+ else
+ EXTI->FTSR &= ~padmask;
+
+ /* Programming interrupt and event registers.*/
+ EXTI->IMR |= padmask;
+ EXTI->EMR &= ~padmask;
+}
+
+/**
+ * @brief Pad event disable.
+ * @details This function disables previously programmed event callbacks.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad) {
+ uint32_t padmask, rtsr1, ftsr1;
+
+ rtsr1 = EXTI->RTSR;
+ ftsr1 = EXTI->FTSR;
+
+ /* Mask of the pad.*/
+ padmask = 1U << (uint32_t)pad;
+
+ /* If either RTRS1 or FTSR1 is enabled then the channel is in use.*/
+ if (((rtsr1 | ftsr1) & padmask) != 0U) {
+ uint32_t cridx, croff, crport, portidx;
+
+ /* Index and mask of the SYSCFG CR register to be used.*/
+ cridx = (uint32_t)pad >> 2U;
+ croff = ((uint32_t)pad & 3U) * 4U;
+
+ /* Port index is obtained assuming that GPIO ports are placed at regular
+ 0x400 intervals in memory space. So far this is true for all devices.*/
+ portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU;
+
+ crport = (AFIO->EXTICR[cridx] >> croff) & 0xFU;
+
+ osalDbgAssert(crport == portidx, "channel mapped on different port");
+
+ /* Disabling channel.*/
+ EXTI->IMR &= ~padmask;
+ EXTI->EMR &= ~padmask;
+ EXTI->RTSR = rtsr1 & ~padmask;
+ EXTI->FTSR = ftsr1 & ~padmask;
+ EXTI->PR = padmask;
+
+#if PAL_USE_CALLBACKS || PAL_USE_WAIT
+ /* Callback cleared and/or thread reset.*/
+ _pal_clear_event(pad);
+#endif
+ }
+}
+#endif /* PAL_USE_CALLBACKS || PAL_USE_WAIT */
+
+#endif /* HAL_USE_PAL */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.h
new file mode 100644
index 0000000..63bc006
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv1/hal_pal_lld.h
@@ -0,0 +1,459 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file GPIOv1/hal_pal_lld.h
+ * @brief STM32 PAL low level driver header.
+ *
+ * @addtogroup PAL
+ * @{
+ */
+
+#ifndef HAL_PAL_LLD_H
+#define HAL_PAL_LLD_H
+
+#if HAL_USE_PAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Unsupported modes and specific modes */
+/*===========================================================================*/
+
+/**
+ * @name STM32-specific I/O mode flags
+ * @{
+ */
+/**
+ * @brief STM32 specific alternate push-pull output mode.
+ */
+#define PAL_MODE_STM32_ALTERNATE_PUSHPULL 16
+
+/**
+ * @brief STM32 specific alternate open-drain output mode.
+ */
+#define PAL_MODE_STM32_ALTERNATE_OPENDRAIN 17
+/** @} */
+
+/*===========================================================================*/
+/* I/O Ports Types and constants. */
+/*===========================================================================*/
+
+/**
+ * @name Port related definitions
+ * @{
+ */
+/**
+ * @brief Width, in bits, of an I/O port.
+ */
+#define PAL_IOPORTS_WIDTH 16
+
+/**
+ * @brief Whole port mask.
+ * @details This macro specifies all the valid bits into a port.
+ */
+#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFF)
+/** @} */
+
+/**
+ * @name Line handling macros
+ * @{
+ */
+/**
+ * @brief Forms a line identifier.
+ * @details A port/pad pair are encoded into an @p ioline_t type. The encoding
+ * of this type is platform-dependent.
+ * @note In this driver the pad number is encoded in the lower 4 bits of
+ * the GPIO address which are guaranteed to be zero.
+ */
+#define PAL_LINE(port, pad) \
+ ((ioline_t)((uint32_t)(port)) | ((uint32_t)(pad)))
+
+/**
+ * @brief Decodes a port identifier from a line identifier.
+ */
+#define PAL_PORT(line) \
+ ((GPIO_TypeDef *)(((uint32_t)(line)) & 0xFFFFFFF0U))
+
+/**
+ * @brief Decodes a pad identifier from a line identifier.
+ */
+#define PAL_PAD(line) \
+ ((uint32_t)((uint32_t)(line) & 0x0000000FU))
+
+/**
+ * @brief Value identifying an invalid line.
+ */
+#define PAL_NOLINE 0U
+/** @} */
+
+/**
+ * @brief GPIO port setup info.
+ */
+typedef struct {
+ /** Initial value for ODR register.*/
+ uint32_t odr;
+ /** Initial value for CRL register.*/
+ uint32_t crl;
+ /** Initial value for CRH register.*/
+ uint32_t crh;
+} stm32_gpio_setup_t;
+
+/**
+ * @brief STM32 GPIO static initializer.
+ * @details An instance of this structure must be passed to @p palInit() at
+ * system startup time in order to initialize the digital I/O
+ * subsystem. This represents only the initial setup, specific pads
+ * or whole ports can be reprogrammed at later time.
+ */
+typedef struct {
+ /** @brief Port A setup data.*/
+ stm32_gpio_setup_t PAData;
+ /** @brief Port B setup data.*/
+ stm32_gpio_setup_t PBData;
+ /** @brief Port C setup data.*/
+ stm32_gpio_setup_t PCData;
+ /** @brief Port D setup data.*/
+ stm32_gpio_setup_t PDData;
+#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
+ /** @brief Port E setup data.*/
+ stm32_gpio_setup_t PEData;
+#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
+ /** @brief Port F setup data.*/
+ stm32_gpio_setup_t PFData;
+#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
+ /** @brief Port G setup data.*/
+ stm32_gpio_setup_t PGData;
+#endif
+#endif
+#endif
+} PALConfig;
+
+/**
+ * @brief Digital I/O port sized unsigned type.
+ */
+typedef uint32_t ioportmask_t;
+
+/**
+ * @brief Digital I/O modes.
+ */
+typedef uint32_t iomode_t;
+
+/**
+ * @brief Type of an I/O line.
+ */
+typedef uint32_t ioline_t;
+
+/**
+ * @brief Type of an event mode.
+ */
+typedef uint32_t ioeventmode_t;
+
+/**
+ * @brief Port Identifier.
+ * @details This type can be a scalar or some kind of pointer, do not make
+ * any assumption about it, use the provided macros when populating
+ * variables of this type.
+ */
+typedef GPIO_TypeDef * ioportid_t;
+
+/**
+ * @brief Type of an pad identifier.
+ */
+typedef uint32_t iopadid_t;
+
+/*===========================================================================*/
+/* I/O Ports Identifiers. */
+/* The low level driver wraps the definitions already present in the STM32 */
+/* firmware library. */
+/*===========================================================================*/
+
+/**
+ * @brief GPIO port A identifier.
+ */
+#if STM32_HAS_GPIOA || defined(__DOXYGEN__)
+#define IOPORT1 GPIOA
+#endif
+
+/**
+ * @brief GPIO port B identifier.
+ */
+#if STM32_HAS_GPIOB || defined(__DOXYGEN__)
+#define IOPORT2 GPIOB
+#endif
+
+/**
+ * @brief GPIO port C identifier.
+ */
+#if STM32_HAS_GPIOC || defined(__DOXYGEN__)
+#define IOPORT3 GPIOC
+#endif
+
+/**
+ * @brief GPIO port D identifier.
+ */
+#if STM32_HAS_GPIOD || defined(__DOXYGEN__)
+#define IOPORT4 GPIOD
+#endif
+
+/**
+ * @brief GPIO port E identifier.
+ */
+#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
+#define IOPORT5 GPIOE
+#endif
+
+/**
+ * @brief GPIO port F identifier.
+ */
+#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
+#define IOPORT6 GPIOF
+#endif
+
+/**
+ * @brief GPIO port G identifier.
+ */
+#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
+#define IOPORT7 GPIOG
+#endif
+
+/*===========================================================================*/
+/* Implementation, some of the following macros could be implemented as */
+/* functions, if so please put them in pal_lld.c. */
+/*===========================================================================*/
+
+/**
+ * @brief GPIO ports subsystem initialization.
+ *
+ * @notapi
+ */
+#define pal_lld_init(config) _pal_lld_init(config)
+
+/**
+ * @brief Reads an I/O port.
+ * @details This function is implemented by reading the GPIO IDR register, the
+ * implementation has no side effects.
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ *
+ * @param[in] port port identifier
+ * @return The port bits.
+ *
+ * @notapi
+ */
+#define pal_lld_readport(port) ((ioportmask_t)((port)->IDR))
+
+/**
+ * @brief Reads the output latch.
+ * @details This function is implemented by reading the GPIO ODR register, the
+ * implementation has no side effects.
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ *
+ * @param[in] port port identifier
+ * @return The latched logical states.
+ *
+ * @notapi
+ */
+#define pal_lld_readlatch(port) ((ioportmask_t)((port)->ODR))
+
+/**
+ * @brief Writes on a I/O port.
+ * @details This function is implemented by writing the GPIO ODR register, the
+ * implementation has no side effects.
+ * @note Writing on pads programmed as pull-up or pull-down has the side
+ * effect to modify the resistor setting because the output latched
+ * data is used for the resistor selection.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be written on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_writeport(port, bits) ((port)->ODR = (uint32_t)(bits))
+
+/**
+ * @brief Sets a bits mask on a I/O port.
+ * @details This function is implemented by writing the GPIO BSRR register, the
+ * implementation has no side effects.
+ * @note Writing on pads programmed as pull-up or pull-down has the side
+ * effect to modify the resistor setting because the output latched
+ * data is used for the resistor selection.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be ORed on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_setport(port, bits) ((port)->BSRR = (uint32_t)(bits))
+
+/**
+ * @brief Clears a bits mask on a I/O port.
+ * @details This function is implemented by writing the GPIO BRR register, the
+ * implementation has no side effects.
+ * @note Writing on pads programmed as pull-up or pull-down has the side
+ * effect to modify the resistor setting because the output latched
+ * data is used for the resistor selection.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be cleared on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_clearport(port, bits) ((port)->BRR = (uint32_t)(bits))
+
+/**
+ * @brief Writes a group of bits.
+ * @details This function is implemented by writing the GPIO BSRR register, the
+ * implementation has no side effects.
+ * @note Writing on pads programmed as pull-up or pull-down has the side
+ * effect to modify the resistor setting because the output latched
+ * data is used for the resistor selection.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask
+ * @param[in] offset the group bit offset within the port
+ * @param[in] bits bits to be written. Values exceeding the group
+ * width are masked.
+ *
+ * @notapi
+ */
+#define pal_lld_writegroup(port, mask, offset, bits) { \
+ uint32_t w = ((~(uint32_t)(bits) & (uint32_t)(mask)) << (16U + (offset))) | \
+ ((uint32_t)(bits) & (uint32_t)(mask)) << (offset); \
+ (port)->BSRR = w; \
+}
+
+/**
+ * @brief Pads group mode setup.
+ * @details This function programs a pads group belonging to the same port
+ * with the specified mode.
+ * @note Writing on pads programmed as pull-up or pull-down has the side
+ * effect to modify the resistor setting because the output latched
+ * data is used for the resistor selection.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask
+ * @param[in] offset group bit offset within the port
+ * @param[in] mode group mode
+ *
+ * @notapi
+ */
+#define pal_lld_setgroupmode(port, mask, offset, mode) \
+ _pal_lld_setgroupmode(port, mask << offset, mode)
+
+/**
+ * @brief Writes a logical state on an output pad.
+ * @note Writing on pads programmed as pull-up or pull-down has the side
+ * effect to modify the resistor setting because the output latched
+ * data is used for the resistor selection.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] bit logical value, the value must be @p PAL_LOW or
+ * @p PAL_HIGH
+ *
+ * @notapi
+ */
+#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit)
+
+/**
+ * @brief Pad event enable.
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] mode pad event mode
+ *
+ * @notapi
+ */
+#define pal_lld_enablepadevent(port, pad, mode) \
+ _pal_lld_enablepadevent(port, pad, mode)
+
+/**
+ * @brief Pad event disable.
+ * @details This function disables previously programmed event callbacks.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+#define pal_lld_disablepadevent(port, pad) \
+ _pal_lld_disablepadevent(port, pad)
+
+/**
+ * @brief Returns a PAL event structure associated to a pad.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+#define pal_lld_get_pad_event(port, pad) \
+ &_pal_events[pad]; (void)(port)
+
+/**
+ * @brief Returns a PAL event structure associated to a line.
+ *
+ * @param[in] line line identifier
+ *
+ * @notapi
+ */
+#define pal_lld_get_line_event(line) \
+ &_pal_events[PAL_PAD(line)]
+
+/**
+ * @brief Pad event enable check.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @return Pad event status.
+ * @retval false if the pad event is disabled.
+ * @retval true if the pad event is enabled.
+ *
+ * @notapi
+ */
+#define pal_lld_ispadeventenabled(port, pad) \
+ (bool)((EXTI->IMR & (1U << (uint32_t)pad)) != 0U)
+
+#if !defined(__DOXYGEN__)
+extern const PALConfig pal_default_config;
+#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE)
+extern palevent_t _pal_events[16];
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void _pal_lld_init(const PALConfig *config);
+ void _pal_lld_setgroupmode(ioportid_t port,
+ ioportmask_t mask,
+ iomode_t mode);
+#if PAL_USE_CALLBACKS || PAL_USE_WAIT
+ void _pal_lld_enablepadevent(ioportid_t port,
+ iopadid_t pad,
+ ioeventmode_t mode);
+ void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_PAL */
+
+#endif /* HAL_PAL_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv2/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv2/driver.mk
new file mode 100644
index 0000000..387ed83
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv2/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_PAL TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c
new file mode 100644
index 0000000..ef2fb9a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.c
@@ -0,0 +1,271 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file GPIOv2/hal_pal_lld.c
+ * @brief STM32 PAL low level driver code.
+ *
+ * @addtogroup PAL
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_PAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Event records for the 16 GPIO EXTI channels.
+ */
+palevent_t _pal_events[16];
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief PAL driver initialization.
+ *
+ * @notapi
+ */
+void _pal_lld_init(void) {
+
+#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__)
+ unsigned i;
+
+ for (i = 0; i < 16; i++) {
+ _pal_init_event(i);
+ }
+#endif
+}
+
+/**
+ * @brief Pads mode setup.
+ * @details This function programs a pads group belonging to the same port
+ * with the specified mode.
+ * @note @p PAL_MODE_UNCONNECTED is implemented as push pull at minimum
+ * speed.
+ *
+ * @param[in] port the port identifier
+ * @param[in] mask the group mask
+ * @param[in] mode the mode
+ *
+ * @notapi
+ */
+void _pal_lld_setgroupmode(ioportid_t port,
+ ioportmask_t mask,
+ iomode_t mode) {
+
+ uint32_t moder = (mode & PAL_STM32_MODE_MASK) >> 0;
+ uint32_t otyper = (mode & PAL_STM32_OTYPE_MASK) >> 2;
+ uint32_t ospeedr = (mode & PAL_STM32_OSPEED_MASK) >> 3;
+ uint32_t pupdr = (mode & PAL_STM32_PUPDR_MASK) >> 5;
+ uint32_t altr = (mode & PAL_STM32_ALTERNATE_MASK) >> 7;
+ uint32_t bit = 0;
+ while (true) {
+ if ((mask & 1) != 0) {
+ uint32_t altrmask, m1, m2, m4;
+
+ altrmask = altr << ((bit & 7) * 4);
+ m1 = 1 << bit;
+ m2 = 3 << (bit * 2);
+ m4 = 15 << ((bit & 7) * 4);
+ port->OTYPER = (port->OTYPER & ~m1) | otyper;
+ port->OSPEEDR = (port->OSPEEDR & ~m2) | ospeedr;
+ port->PUPDR = (port->PUPDR & ~m2) | pupdr;
+ if ((mode & PAL_STM32_MODE_MASK) == PAL_STM32_MODE_ALTERNATE) {
+ /* If going in alternate mode then the alternate number is set
+ before switching mode in order to avoid glitches.*/
+ if (bit < 8)
+ port->AFRL = (port->AFRL & ~m4) | altrmask;
+ else
+ port->AFRH = (port->AFRH & ~m4) | altrmask;
+ port->MODER = (port->MODER & ~m2) | moder;
+ }
+ else {
+ /* If going into a non-alternate mode then the mode is switched
+ before setting the alternate mode in order to avoid glitches.*/
+ port->MODER = (port->MODER & ~m2) | moder;
+ if (bit < 8)
+ port->AFRL = (port->AFRL & ~m4) | altrmask;
+ else
+ port->AFRH = (port->AFRH & ~m4) | altrmask;
+ }
+ }
+ mask >>= 1;
+ if (!mask)
+ return;
+ otyper <<= 1;
+ ospeedr <<= 2;
+ pupdr <<= 2;
+ moder <<= 2;
+ bit++;
+ }
+}
+
+#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__)
+/**
+ * @brief Pad event enable.
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] mode pad event mode
+ *
+ * @notapi
+ */
+void _pal_lld_enablepadevent(ioportid_t port,
+ iopadid_t pad,
+ ioeventmode_t mode) {
+
+ uint32_t padmask, cridx, croff, crmask, portidx;
+
+ /* Mask of the pad.*/
+ padmask = 1U << (uint32_t)pad;
+
+ /* Multiple channel setting of the same channel not allowed, first disable
+ it. This is done because on STM32 the same channel cannot be mapped on
+ multiple ports.*/
+ osalDbgAssert(((EXTI->RTSR1 & padmask) == 0U) &&
+ ((EXTI->FTSR1 & padmask) == 0U), "channel already in use");
+
+ /* Port index is obtained assuming that GPIO ports are placed at regular
+ 0x400 intervals in memory space. So far this is true for all devices.*/
+ portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU;
+
+ /* Index and mask of the CR register to be used.*/
+ cridx = (uint32_t)pad >> 2U;
+#if STM32_EXTI_HAS_CR == FALSE
+ croff = ((uint32_t)pad & 3U) * 4U;
+ crmask = ~(0xFU << croff);
+ SYSCFG->EXTICR[cridx] = (SYSCFG->EXTICR[cridx] & crmask) | (portidx << croff);
+#else
+ croff = ((uint32_t)pad & 3U) * 8U;
+ crmask = ~(0xFFU << croff);
+ EXTI->EXTICR[cridx] = (EXTI->EXTICR[cridx] & crmask) | (portidx << croff);
+#endif
+
+ /* Programming edge registers.*/
+ if (mode & PAL_EVENT_MODE_RISING_EDGE)
+ EXTI->RTSR1 |= padmask;
+ else
+ EXTI->RTSR1 &= ~padmask;
+ if (mode & PAL_EVENT_MODE_FALLING_EDGE)
+ EXTI->FTSR1 |= padmask;
+ else
+ EXTI->FTSR1 &= ~padmask;
+
+ /* Programming interrupt and event registers.*/
+#if defined(STM32_EXTI_ENHANCED)
+ EXTI_D1->IMR1 |= padmask;
+ EXTI_D1->EMR1 &= ~padmask;
+#else
+ EXTI->IMR1 |= padmask;
+ EXTI->EMR1 &= ~padmask;
+#endif
+}
+
+/**
+ * @brief Pad event disable.
+ * @details This function disables previously programmed event callbacks.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad) {
+ uint32_t padmask, rtsr1, ftsr1;
+
+ rtsr1 = EXTI->RTSR1;
+ ftsr1 = EXTI->FTSR1;
+
+ /* Mask of the pad.*/
+ padmask = 1U << (uint32_t)pad;
+
+ /* If either RTRS1 or FTSR1 is enabled then the channel is in use.*/
+ if (((rtsr1 | ftsr1) & padmask) != 0U) {
+ uint32_t cridx, croff, crport, portidx;
+
+ /* Port index is obtained assuming that GPIO ports are placed at regular
+ 0x400 intervals in memory space. So far this is true for all devices.*/
+ portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU;
+
+ /* Index and mask of the CR register to be used.*/
+ cridx = (uint32_t)pad >> 2U;
+#if STM32_EXTI_HAS_CR == FALSE
+ croff = ((uint32_t)pad & 3U) * 4U;
+ crport = (SYSCFG->EXTICR[cridx] >> croff) & 0xFU;
+#else
+ croff = ((uint32_t)pad & 3U) * 8U;
+ crport = (EXTI->EXTICR[cridx] >> croff) & 0xFFU;
+#endif
+
+ osalDbgAssert(crport == portidx, "channel mapped on different port");
+
+#if defined(STM32_EXTI_ENHANCED)
+ /* Disabling channel.*/
+ EXTI_D1->IMR1 &= ~padmask;
+ EXTI_D1->EMR1 &= ~padmask;
+ EXTI->RTSR1 = rtsr1 & ~padmask;
+ EXTI->FTSR1 = ftsr1 & ~padmask;
+ EXTI_D1->PR1 = padmask;
+#else
+ /* Disabling channel.*/
+ EXTI->IMR1 &= ~padmask;
+ EXTI->EMR1 &= ~padmask;
+ EXTI->RTSR1 = rtsr1 & ~padmask;
+ EXTI->FTSR1 = ftsr1 & ~padmask;
+#if STM32_EXTI_SEPARATE_RF == FALSE
+ EXTI->PR1 = padmask;
+#else
+ EXTI->RPR1 = padmask;
+ EXTI->FPR1 = padmask;
+#endif
+#endif
+
+#if PAL_USE_CALLBACKS || PAL_USE_WAIT
+ /* Callback cleared and/or thread reset.*/
+ _pal_clear_event(pad);
+#endif
+ }
+}
+#endif /* PAL_USE_CALLBACKS || PAL_USE_WAIT */
+
+#endif /* HAL_USE_PAL */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.h
new file mode 100644
index 0000000..15b541b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv2/hal_pal_lld.h
@@ -0,0 +1,514 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file GPIOv2/hal_pal_lld.h
+ * @brief STM32 PAL low level driver header.
+ *
+ * @addtogroup PAL
+ * @{
+ */
+
+#ifndef HAL_PAL_LLD_H
+#define HAL_PAL_LLD_H
+
+#include "stm32_gpio.h"
+
+#if HAL_USE_PAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Unsupported modes and specific modes */
+/*===========================================================================*/
+
+/* Specifies palInit() without parameter, required until all platforms will
+ be updated to the new style.*/
+#define PAL_NEW_INIT
+
+#undef PAL_MODE_RESET
+#undef PAL_MODE_UNCONNECTED
+#undef PAL_MODE_INPUT
+#undef PAL_MODE_INPUT_PULLUP
+#undef PAL_MODE_INPUT_PULLDOWN
+#undef PAL_MODE_INPUT_ANALOG
+#undef PAL_MODE_OUTPUT_PUSHPULL
+#undef PAL_MODE_OUTPUT_OPENDRAIN
+
+/**
+ * @name STM32-specific I/O mode flags
+ * @{
+ */
+#define PAL_STM32_MODE_MASK (3U << 0U)
+#define PAL_STM32_MODE_INPUT (0U << 0U)
+#define PAL_STM32_MODE_OUTPUT (1U << 0U)
+#define PAL_STM32_MODE_ALTERNATE (2U << 0U)
+#define PAL_STM32_MODE_ANALOG (3U << 0U)
+
+#define PAL_STM32_OTYPE_MASK (1U << 2U)
+#define PAL_STM32_OTYPE_PUSHPULL (0U << 2U)
+#define PAL_STM32_OTYPE_OPENDRAIN (1U << 2U)
+
+#define PAL_STM32_OSPEED_MASK (3U << 3U)
+#define PAL_STM32_OSPEED_LOWEST (0U << 3U)
+#if defined(STM32F0XX) || defined(STM32F30X) || defined(STM32F37X)
+#define PAL_STM32_OSPEED_MID (1U << 3U)
+#else
+#define PAL_STM32_OSPEED_MID1 (1U << 3U)
+#define PAL_STM32_OSPEED_MID2 (2U << 3U)
+#endif
+#define PAL_STM32_OSPEED_HIGHEST (3U << 3U)
+
+#define PAL_STM32_PUPDR_MASK (3U << 5U)
+#define PAL_STM32_PUPDR_FLOATING (0U << 5U)
+#define PAL_STM32_PUPDR_PULLUP (1U << 5U)
+#define PAL_STM32_PUPDR_PULLDOWN (2U << 5U)
+
+#define PAL_STM32_ALTERNATE_MASK (15U << 7U)
+#define PAL_STM32_ALTERNATE(n) ((n) << 7U)
+
+/**
+ * @brief Alternate function.
+ *
+ * @param[in] n alternate function selector
+ */
+#define PAL_MODE_ALTERNATE(n) (PAL_STM32_MODE_ALTERNATE | \
+ PAL_STM32_ALTERNATE(n))
+/** @} */
+
+/**
+ * @name Standard I/O mode flags
+ * @{
+ */
+/**
+ * @brief Implemented as input.
+ */
+#define PAL_MODE_RESET PAL_STM32_MODE_INPUT
+
+/**
+ * @brief Implemented as input with pull-up.
+ */
+#define PAL_MODE_UNCONNECTED PAL_MODE_INPUT_PULLUP
+
+/**
+ * @brief Regular input high-Z pad.
+ */
+#define PAL_MODE_INPUT PAL_STM32_MODE_INPUT
+
+/**
+ * @brief Input pad with weak pull up resistor.
+ */
+#define PAL_MODE_INPUT_PULLUP (PAL_STM32_MODE_INPUT | \
+ PAL_STM32_PUPDR_PULLUP)
+
+/**
+ * @brief Input pad with weak pull down resistor.
+ */
+#define PAL_MODE_INPUT_PULLDOWN (PAL_STM32_MODE_INPUT | \
+ PAL_STM32_PUPDR_PULLDOWN)
+
+/**
+ * @brief Analog input mode.
+ */
+#define PAL_MODE_INPUT_ANALOG PAL_STM32_MODE_ANALOG
+
+/**
+ * @brief Push-pull output pad.
+ */
+#define PAL_MODE_OUTPUT_PUSHPULL (PAL_STM32_MODE_OUTPUT | \
+ PAL_STM32_OTYPE_PUSHPULL)
+
+/**
+ * @brief Open-drain output pad.
+ */
+#define PAL_MODE_OUTPUT_OPENDRAIN (PAL_STM32_MODE_OUTPUT | \
+ PAL_STM32_OTYPE_OPENDRAIN)
+/** @} */
+
+/*===========================================================================*/
+/* I/O Ports Types and constants. */
+/*===========================================================================*/
+
+/**
+ * @name Port related definitions
+ * @{
+ */
+/**
+ * @brief Width, in bits, of an I/O port.
+ */
+#define PAL_IOPORTS_WIDTH 16
+
+/**
+ * @brief Whole port mask.
+ * @details This macro specifies all the valid bits into a port.
+ */
+#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFF)
+/** @} */
+
+/**
+ * @name Line handling macros
+ * @{
+ */
+/**
+ * @brief Forms a line identifier.
+ * @details A port/pad pair are encoded into an @p ioline_t type. The encoding
+ * of this type is platform-dependent.
+ * @note In this driver the pad number is encoded in the lower 4 bits of
+ * the GPIO address which are guaranteed to be zero.
+ */
+#define PAL_LINE(port, pad) \
+ ((ioline_t)((uint32_t)(port)) | ((uint32_t)(pad)))
+
+/**
+ * @brief Decodes a port identifier from a line identifier.
+ */
+#define PAL_PORT(line) \
+ ((stm32_gpio_t *)(((uint32_t)(line)) & 0xFFFFFFF0U))
+
+/**
+ * @brief Decodes a pad identifier from a line identifier.
+ */
+#define PAL_PAD(line) \
+ ((uint32_t)((uint32_t)(line) & 0x0000000FU))
+
+/**
+ * @brief Value identifying an invalid line.
+ */
+#define PAL_NOLINE 0U
+/** @} */
+
+/**
+ * @brief Type of digital I/O port sized unsigned integer.
+ */
+typedef uint32_t ioportmask_t;
+
+/**
+ * @brief Type of digital I/O modes.
+ */
+typedef uint32_t iomode_t;
+
+/**
+ * @brief Type of an I/O line.
+ */
+typedef uint32_t ioline_t;
+
+/**
+ * @brief Type of an event mode.
+ */
+typedef uint32_t ioeventmode_t;
+
+/**
+ * @brief Type of a port Identifier.
+ * @details This type can be a scalar or some kind of pointer, do not make
+ * any assumption about it, use the provided macros when populating
+ * variables of this type.
+ */
+typedef stm32_gpio_t * ioportid_t;
+
+/**
+ * @brief Type of an pad identifier.
+ */
+typedef uint32_t iopadid_t;
+
+/*===========================================================================*/
+/* I/O Ports Identifiers. */
+/* The low level driver wraps the definitions already present in the STM32 */
+/* firmware library. */
+/*===========================================================================*/
+
+/**
+ * @brief GPIO port A identifier.
+ */
+#if STM32_HAS_GPIOA || defined(__DOXYGEN__)
+#define IOPORT1 GPIOA
+#endif
+
+/**
+ * @brief GPIO port B identifier.
+ */
+#if STM32_HAS_GPIOB || defined(__DOXYGEN__)
+#define IOPORT2 GPIOB
+#endif
+
+/**
+ * @brief GPIO port C identifier.
+ */
+#if STM32_HAS_GPIOC || defined(__DOXYGEN__)
+#define IOPORT3 GPIOC
+#endif
+
+/**
+ * @brief GPIO port D identifier.
+ */
+#if STM32_HAS_GPIOD || defined(__DOXYGEN__)
+#define IOPORT4 GPIOD
+#endif
+
+/**
+ * @brief GPIO port E identifier.
+ */
+#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
+#define IOPORT5 GPIOE
+#endif
+
+/**
+ * @brief GPIO port F identifier.
+ */
+#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
+#define IOPORT6 GPIOF
+#endif
+
+/**
+ * @brief GPIO port G identifier.
+ */
+#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
+#define IOPORT7 GPIOG
+#endif
+
+/**
+ * @brief GPIO port H identifier.
+ */
+#if STM32_HAS_GPIOH || defined(__DOXYGEN__)
+#define IOPORT8 GPIOH
+#endif
+
+/**
+ * @brief GPIO port I identifier.
+ */
+#if STM32_HAS_GPIOI || defined(__DOXYGEN__)
+#define IOPORT9 GPIOI
+#endif
+
+/**
+ * @brief GPIO port J identifier.
+ */
+#if STM32_HAS_GPIOJ || defined(__DOXYGEN__)
+#define IOPORT10 GPIOJ
+#endif
+
+/**
+ * @brief GPIO port K identifier.
+ */
+#if STM32_HAS_GPIOK || defined(__DOXYGEN__)
+#define IOPORT11 GPIOK
+#endif
+
+/*===========================================================================*/
+/* Implementation, some of the following macros could be implemented as */
+/* functions, if so please put them in pal_lld.c. */
+/*===========================================================================*/
+
+/**
+ * @brief GPIO ports subsystem initialization.
+ *
+ * @notapi
+ */
+#define pal_lld_init() _pal_lld_init()
+
+/**
+ * @brief Reads an I/O port.
+ * @details This function is implemented by reading the GPIO IDR register, the
+ * implementation has no side effects.
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ *
+ * @param[in] port port identifier
+ * @return The port bits.
+ *
+ * @notapi
+ */
+#define pal_lld_readport(port) ((ioportmask_t)((port)->IDR))
+
+/**
+ * @brief Reads the output latch.
+ * @details This function is implemented by reading the GPIO ODR register, the
+ * implementation has no side effects.
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ *
+ * @param[in] port port identifier
+ * @return The latched logical states.
+ *
+ * @notapi
+ */
+#define pal_lld_readlatch(port) ((ioportmask_t)((port)->ODR))
+
+/**
+ * @brief Writes on a I/O port.
+ * @details This function is implemented by writing the GPIO ODR register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be written on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_writeport(port, bits) ((port)->ODR = (uint32_t)(bits))
+
+/**
+ * @brief Sets a bits mask on a I/O port.
+ * @details This function is implemented by writing the GPIO BSRR register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be ORed on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_setport(port, bits) ((port)->BSRR.H.set = (uint16_t)(bits))
+
+/**
+ * @brief Clears a bits mask on a I/O port.
+ * @details This function is implemented by writing the GPIO BSRR register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be cleared on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_clearport(port, bits) ((port)->BSRR.H.clear = (uint16_t)(bits))
+
+/**
+ * @brief Writes a group of bits.
+ * @details This function is implemented by writing the GPIO BSRR register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask
+ * @param[in] offset the group bit offset within the port
+ * @param[in] bits bits to be written. Values exceeding the group
+ * width are masked.
+ *
+ * @notapi
+ */
+#define pal_lld_writegroup(port, mask, offset, bits) { \
+ uint32_t w = ((~(uint32_t)(bits) & (uint32_t)(mask)) << (16U + (offset))) | \
+ ((uint32_t)(bits) & (uint32_t)(mask)) << (offset); \
+ (port)->BSRR.W = w; \
+}
+
+/**
+ * @brief Pads group mode setup.
+ * @details This function programs a pads group belonging to the same port
+ * with the specified mode.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask
+ * @param[in] offset group bit offset within the port
+ * @param[in] mode group mode
+ *
+ * @notapi
+ */
+#define pal_lld_setgroupmode(port, mask, offset, mode) \
+ _pal_lld_setgroupmode(port, mask << offset, mode)
+
+/**
+ * @brief Writes a logical state on an output pad.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] bit logical value, the value must be @p PAL_LOW or
+ * @p PAL_HIGH
+ *
+ * @notapi
+ */
+#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit)
+
+/**
+ * @brief Pad event enable.
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] mode pad event mode
+ *
+ * @notapi
+ */
+#define pal_lld_enablepadevent(port, pad, mode) \
+ _pal_lld_enablepadevent(port, pad, mode)
+
+/**
+ * @brief Pad event disable.
+ * @details This function disables previously programmed event callbacks.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+#define pal_lld_disablepadevent(port, pad) \
+ _pal_lld_disablepadevent(port, pad)
+
+/**
+ * @brief Returns a PAL event structure associated to a pad.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+#define pal_lld_get_pad_event(port, pad) \
+ &_pal_events[pad]; (void)(port)
+
+/**
+ * @brief Returns a PAL event structure associated to a line.
+ *
+ * @param[in] line line identifier
+ *
+ * @notapi
+ */
+#define pal_lld_get_line_event(line) \
+ &_pal_events[PAL_PAD(line)]
+
+/**
+ * @brief Pad event enable check.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @return Pad event status.
+ * @retval false if the pad event is disabled.
+ * @retval true if the pad event is enabled.
+ *
+ * @notapi
+ */
+#define pal_lld_ispadeventenabled(port, pad) \
+ (bool)((EXTI->IMR1 & (1U << (uint32_t)pad)) != 0U)
+
+#if !defined(__DOXYGEN__)
+#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE)
+extern palevent_t _pal_events[16];
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void _pal_lld_init(void);
+ void _pal_lld_setgroupmode(ioportid_t port,
+ ioportmask_t mask,
+ iomode_t mode);
+ void _pal_lld_enablepadevent(ioportid_t port,
+ iopadid_t pad,
+ ioeventmode_t mode);
+ void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_PAL */
+
+#endif /* HAL_PAL_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv2/stm32_gpio.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv2/stm32_gpio.h
new file mode 100644
index 0000000..83fd51e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv2/stm32_gpio.h
@@ -0,0 +1,111 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file GPIOv2/stm32_gpio.h
+ * @brief STM32 GPIO units common header.
+ * @note This file requires definitions from the ST STM32 header file.
+ *
+ * @addtogroup STM32_GPIOv2
+ * @{
+ */
+
+#ifndef STM32_GPIO_H
+#define STM32_GPIO_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/* Discarded definitions from the ST headers, the PAL driver uses its own
+ definitions in order to have an unified handling for all devices.
+ Unfortunately the ST headers have no uniform definitions for the same
+ objects across the various sub-families.*/
+#undef GPIOA
+#undef GPIOB
+#undef GPIOC
+#undef GPIOD
+#undef GPIOE
+#undef GPIOF
+#undef GPIOG
+#undef GPIOH
+#undef GPIOI
+#undef GPIOJ
+#undef GPIOK
+
+/**
+ * @name GPIO ports definitions
+ * @{
+ */
+#define GPIOA ((stm32_gpio_t *)GPIOA_BASE)
+#define GPIOB ((stm32_gpio_t *)GPIOB_BASE)
+#define GPIOC ((stm32_gpio_t *)GPIOC_BASE)
+#define GPIOD ((stm32_gpio_t *)GPIOD_BASE)
+#define GPIOE ((stm32_gpio_t *)GPIOE_BASE)
+#define GPIOF ((stm32_gpio_t *)GPIOF_BASE)
+#define GPIOG ((stm32_gpio_t *)GPIOG_BASE)
+#define GPIOH ((stm32_gpio_t *)GPIOH_BASE)
+#define GPIOI ((stm32_gpio_t *)GPIOI_BASE)
+#define GPIOJ ((stm32_gpio_t *)GPIOJ_BASE)
+#define GPIOK ((stm32_gpio_t *)GPIOK_BASE)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 GPIO registers block.
+ */
+typedef struct {
+
+ volatile uint32_t MODER;
+ volatile uint32_t OTYPER;
+ volatile uint32_t OSPEEDR;
+ volatile uint32_t PUPDR;
+ volatile uint32_t IDR;
+ volatile uint32_t ODR;
+ volatile union {
+ uint32_t W;
+ struct {
+ uint16_t set;
+ uint16_t clear;
+ } H;
+ } BSRR;
+ volatile uint32_t LOCKR;
+ volatile uint32_t AFRL;
+ volatile uint32_t AFRH;
+} stm32_gpio_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#endif /* STM32_GPIO_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv3/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv3/driver.mk
new file mode 100644
index 0000000..b2db0f3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv3/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_PAL TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv3
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c
new file mode 100644
index 0000000..92b61b5
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.c
@@ -0,0 +1,249 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file GPIOv3/hal_pal_lld.c
+ * @brief STM32 PAL low level driver code.
+ *
+ * @addtogroup PAL
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_PAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Event records for the 16 GPIO EXTI channels.
+ */
+palevent_t _pal_events[16];
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief PAL driver initialization.
+ *
+ * @notapi
+ */
+void _pal_lld_init(void) {
+
+#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__)
+ unsigned i;
+
+ for (i = 0; i < 16; i++) {
+ _pal_init_event(i);
+ }
+#endif
+}
+
+/**
+ * @brief Pads mode setup.
+ * @details This function programs a pads group belonging to the same port
+ * with the specified mode.
+ * @note @p PAL_MODE_UNCONNECTED is implemented as push pull at minimum
+ * speed.
+ *
+ * @param[in] port the port identifier
+ * @param[in] mask the group mask
+ * @param[in] mode the mode
+ *
+ * @notapi
+ */
+void _pal_lld_setgroupmode(ioportid_t port,
+ ioportmask_t mask,
+ iomode_t mode) {
+
+ uint32_t moder = (mode & PAL_STM32_MODE_MASK) >> 0;
+ uint32_t otyper = (mode & PAL_STM32_OTYPE_MASK) >> 2;
+ uint32_t ospeedr = (mode & PAL_STM32_OSPEED_MASK) >> 3;
+ uint32_t pupdr = (mode & PAL_STM32_PUPDR_MASK) >> 5;
+ uint32_t altr = (mode & PAL_STM32_ALTERNATE_MASK) >> 7;
+ uint32_t ascr = (mode & PAL_STM32_ASCR_MASK) >> 11;
+ uint32_t lockr = (mode & PAL_STM32_LOCKR_MASK) >> 12;
+ uint32_t bit = 0;
+ while (true) {
+ if ((mask & 1) != 0) {
+ uint32_t altrmask, m1, m2, m4;
+
+ altrmask = altr << ((bit & 7) * 4);
+ m1 = 1 << bit;
+ m2 = 3 << (bit * 2);
+ m4 = 15 << ((bit & 7) * 4);
+ port->OTYPER = (port->OTYPER & ~m1) | otyper;
+ port->ASCR = (port->ASCR & ~m1) | ascr;
+ port->OSPEEDR = (port->OSPEEDR & ~m2) | ospeedr;
+ port->PUPDR = (port->PUPDR & ~m2) | pupdr;
+ if ((mode & PAL_STM32_MODE_MASK) == PAL_STM32_MODE_ALTERNATE) {
+ /* If going in alternate mode then the alternate number is set
+ before switching mode in order to avoid glitches.*/
+ if (bit < 8)
+ port->AFRL = (port->AFRL & ~m4) | altrmask;
+ else
+ port->AFRH = (port->AFRH & ~m4) | altrmask;
+ port->MODER = (port->MODER & ~m2) | moder;
+ }
+ else {
+ /* If going into a non-alternate mode then the mode is switched
+ before setting the alternate mode in order to avoid glitches.*/
+ port->MODER = (port->MODER & ~m2) | moder;
+ if (bit < 8)
+ port->AFRL = (port->AFRL & ~m4) | altrmask;
+ else
+ port->AFRH = (port->AFRH & ~m4) | altrmask;
+ }
+ port->LOCKR = (port->LOCKR & ~m1) | lockr;
+ }
+ mask >>= 1;
+ if (!mask)
+ return;
+ otyper <<= 1;
+ ascr <<= 1;
+ ospeedr <<= 2;
+ pupdr <<= 2;
+ moder <<= 2;
+ bit++;
+ }
+}
+
+#if PAL_USE_CALLBACKS || PAL_USE_WAIT || defined(__DOXYGEN__)
+/**
+ * @brief Pad event enable.
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] mode pad event mode
+ *
+ * @notapi
+ */
+void _pal_lld_enablepadevent(ioportid_t port,
+ iopadid_t pad,
+ ioeventmode_t mode) {
+
+ uint32_t padmask, cridx, croff, crmask, portidx;
+
+ /* Mask of the pad.*/
+ padmask = 1U << (uint32_t)pad;
+
+ /* Multiple channel setting of the same channel not allowed, first disable
+ it. This is done because on STM32 the same channel cannot be mapped on
+ multiple ports.*/
+ osalDbgAssert(((EXTI->RTSR1 & padmask) == 0U) &&
+ ((EXTI->FTSR1 & padmask) == 0U), "channel already in use");
+
+ /* Index and mask of the SYSCFG CR register to be used.*/
+ cridx = (uint32_t)pad >> 2U;
+ croff = ((uint32_t)pad & 3U) * 4U;
+ crmask = ~(0xFU << croff);
+
+ /* Port index is obtained assuming that GPIO ports are placed at regular
+ 0x400 intervals in memory space. So far this is true for all devices.*/
+ portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU;
+
+ /* Port selection in SYSCFG.*/
+ SYSCFG->EXTICR[cridx] = (SYSCFG->EXTICR[cridx] & crmask) | (portidx << croff);
+
+ /* Programming edge registers.*/
+ if (mode & PAL_EVENT_MODE_RISING_EDGE)
+ EXTI->RTSR1 |= padmask;
+ else
+ EXTI->RTSR1 &= ~padmask;
+ if (mode & PAL_EVENT_MODE_FALLING_EDGE)
+ EXTI->FTSR1 |= padmask;
+ else
+ EXTI->FTSR1 &= ~padmask;
+
+ /* Programming interrupt and event registers.*/
+ EXTI->IMR1 |= padmask;
+ EXTI->EMR1 &= ~padmask;
+}
+
+/**
+ * @brief Pad event disable.
+ * @details This function disables previously programmed event callbacks.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad) {
+ uint32_t padmask, rtsr1, ftsr1;
+
+ rtsr1 = EXTI->RTSR1;
+ ftsr1 = EXTI->FTSR1;
+
+ /* Mask of the pad.*/
+ padmask = 1U << (uint32_t)pad;
+
+ /* If either RTRS1 or FTSR1 is enabled then the channel is in use.*/
+ if (((rtsr1 | ftsr1) & padmask) != 0U) {
+ uint32_t cridx, croff, crport, portidx;
+
+ /* Index and mask of the SYSCFG CR register to be used.*/
+ cridx = (uint32_t)pad >> 2U;
+ croff = ((uint32_t)pad & 3U) * 4U;
+
+ /* Port index is obtained assuming that GPIO ports are placed at regular
+ 0x400 intervals in memory space. So far this is true for all devices.*/
+ portidx = (((uint32_t)port - (uint32_t)GPIOA) >> 10U) & 0xFU;
+
+ crport = (SYSCFG->EXTICR[cridx] >> croff) & 0xFU;
+
+ osalDbgAssert(crport == portidx, "channel mapped on different port");
+
+ /* Disabling channel.*/
+ EXTI->IMR1 &= ~padmask;
+ EXTI->EMR1 &= ~padmask;
+ EXTI->RTSR1 = rtsr1 & ~padmask;
+ EXTI->FTSR1 = ftsr1 & ~padmask;
+ EXTI->PR1 = padmask;
+
+#if PAL_USE_CALLBACKS || PAL_USE_WAIT
+ /* Callback cleared and/or thread reset.*/
+ _pal_clear_event(pad);
+#endif
+ }
+}
+#endif /* PAL_USE_CALLBACKS || PAL_USE_WAIT */
+
+#endif /* HAL_USE_PAL */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.h
new file mode 100644
index 0000000..9824257
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv3/hal_pal_lld.h
@@ -0,0 +1,554 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file GPIOv3/hal_pal_lld.h
+ * @brief STM32 PAL low level driver header.
+ *
+ * @addtogroup PAL
+ * @{
+ */
+
+#ifndef HAL_PAL_LLD_H
+#define HAL_PAL_LLD_H
+
+#include "stm32_gpio.h"
+
+#if HAL_USE_PAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Unsupported modes and specific modes */
+/*===========================================================================*/
+
+/* Specifies palInit() without parameter, required until all platforms will
+ be updated to the new style.*/
+#define PAL_NEW_INIT
+
+#undef PAL_MODE_RESET
+#undef PAL_MODE_UNCONNECTED
+#undef PAL_MODE_INPUT
+#undef PAL_MODE_INPUT_PULLUP
+#undef PAL_MODE_INPUT_PULLDOWN
+#undef PAL_MODE_INPUT_ANALOG
+#undef PAL_MODE_OUTPUT_PUSHPULL
+#undef PAL_MODE_OUTPUT_OPENDRAIN
+
+/**
+ * @name STM32-specific I/O mode flags
+ * @{
+ */
+#define PAL_STM32_MODE_MASK (3U << 0U)
+#define PAL_STM32_MODE_INPUT (0U << 0U)
+#define PAL_STM32_MODE_OUTPUT (1U << 0U)
+#define PAL_STM32_MODE_ALTERNATE (2U << 0U)
+#define PAL_STM32_MODE_ANALOG (3U << 0U)
+
+#define PAL_STM32_OTYPE_MASK (1U << 2U)
+#define PAL_STM32_OTYPE_PUSHPULL (0U << 2U)
+#define PAL_STM32_OTYPE_OPENDRAIN (1U << 2U)
+
+#define PAL_STM32_OSPEED_MASK (3U << 3U)
+#define PAL_STM32_OSPEED_LOW (0U << 3U)
+#define PAL_STM32_OSPEED_MEDIUM (1U << 3U)
+#define PAL_STM32_OSPEED_FAST (2U << 3U)
+#define PAL_STM32_OSPEED_HIGH (3U << 3U)
+
+#define PAL_STM32_PUPDR_MASK (3U << 5U)
+#define PAL_STM32_PUPDR_FLOATING (0U << 5U)
+#define PAL_STM32_PUPDR_PULLUP (1U << 5U)
+#define PAL_STM32_PUPDR_PULLDOWN (2U << 5U)
+
+#define PAL_STM32_ALTERNATE_MASK (15U << 7U)
+#define PAL_STM32_ALTERNATE(n) ((n) << 7U)
+
+#define PAL_STM32_ASCR_MASK (1U << 11U)
+#define PAL_STM32_ASCR_OFF (0U << 11U)
+#define PAL_STM32_ASCR_ON (1U << 11U)
+
+#define PAL_STM32_LOCKR_MASK (1U << 12U)
+#define PAL_STM32_LOCKR_OFF (0U << 12U)
+#define PAL_STM32_LOCKR_ON (1U << 12U)
+
+/**
+ * @brief Alternate function.
+ *
+ * @param[in] n alternate function selector
+ */
+#define PAL_MODE_ALTERNATE(n) (PAL_STM32_MODE_ALTERNATE | \
+ PAL_STM32_ALTERNATE(n))
+/** @} */
+
+/**
+ * @name Standard I/O mode flags
+ * @{
+ */
+/**
+ * @brief Implemented as input.
+ */
+#define PAL_MODE_RESET PAL_STM32_MODE_INPUT
+
+/**
+ * @brief Implemented as analog with analog switch disabled and lock.
+ */
+#define PAL_MODE_UNCONNECTED (PAL_STM32_MODE_ANALOG | \
+ PAL_STM32_ASCR_OFF | \
+ PAL_STM32_LOCKR_ON)
+
+/**
+ * @brief Regular input high-Z pad.
+ */
+#define PAL_MODE_INPUT PAL_STM32_MODE_INPUT
+
+/**
+ * @brief Input pad with weak pull up resistor.
+ */
+#define PAL_MODE_INPUT_PULLUP (PAL_STM32_MODE_INPUT | \
+ PAL_STM32_PUPDR_PULLUP)
+
+/**
+ * @brief Input pad with weak pull down resistor.
+ */
+#define PAL_MODE_INPUT_PULLDOWN (PAL_STM32_MODE_INPUT | \
+ PAL_STM32_PUPDR_PULLDOWN)
+
+/**
+ * @brief Analog input mode.
+ */
+#define PAL_MODE_INPUT_ANALOG (PAL_STM32_MODE_ANALOG | \
+ PAL_STM32_ASCR_ON)
+
+/**
+ * @brief Push-pull output pad.
+ */
+#define PAL_MODE_OUTPUT_PUSHPULL (PAL_STM32_MODE_OUTPUT | \
+ PAL_STM32_OTYPE_PUSHPULL)
+
+/**
+ * @brief Open-drain output pad.
+ */
+#define PAL_MODE_OUTPUT_OPENDRAIN (PAL_STM32_MODE_OUTPUT | \
+ PAL_STM32_OTYPE_OPENDRAIN)
+/** @} */
+
+/* Discarded definitions from the ST headers, the PAL driver uses its own
+ definitions in order to have an unified handling for all devices.
+ Unfortunately the ST headers have no uniform definitions for the same
+ objects across the various sub-families.*/
+#undef GPIOA
+#undef GPIOB
+#undef GPIOC
+#undef GPIOD
+#undef GPIOE
+#undef GPIOF
+#undef GPIOG
+#undef GPIOH
+#undef GPIOI
+#undef GPIOJ
+#undef GPIOK
+
+/**
+ * @name GPIO ports definitions
+ * @{
+ */
+#define GPIOA ((stm32_gpio_t *)GPIOA_BASE)
+#define GPIOB ((stm32_gpio_t *)GPIOB_BASE)
+#define GPIOC ((stm32_gpio_t *)GPIOC_BASE)
+#define GPIOD ((stm32_gpio_t *)GPIOD_BASE)
+#define GPIOE ((stm32_gpio_t *)GPIOE_BASE)
+#define GPIOF ((stm32_gpio_t *)GPIOF_BASE)
+#define GPIOG ((stm32_gpio_t *)GPIOG_BASE)
+#define GPIOH ((stm32_gpio_t *)GPIOH_BASE)
+#define GPIOI ((stm32_gpio_t *)GPIOI_BASE)
+#define GPIOJ ((stm32_gpio_t *)GPIOJ_BASE)
+#define GPIOK ((stm32_gpio_t *)GPIOK_BASE)
+/** @} */
+
+/*===========================================================================*/
+/* I/O Ports Types and constants. */
+/*===========================================================================*/
+
+/**
+ * @name Port related definitions
+ * @{
+ */
+/**
+ * @brief Width, in bits, of an I/O port.
+ */
+#define PAL_IOPORTS_WIDTH 16
+
+/**
+ * @brief Whole port mask.
+ * @details This macro specifies all the valid bits into a port.
+ */
+#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFF)
+/** @} */
+
+/**
+ * @name Line handling macros
+ * @{
+ */
+/**
+ * @brief Forms a line identifier.
+ * @details A port/pad pair are encoded into an @p ioline_t type. The encoding
+ * of this type is platform-dependent.
+ * @note In this driver the pad number is encoded in the lower 4 bits of
+ * the GPIO address which are guaranteed to be zero.
+ */
+#define PAL_LINE(port, pad) \
+ ((ioline_t)((uint32_t)(port)) | ((uint32_t)(pad)))
+
+/**
+ * @brief Decodes a port identifier from a line identifier.
+ */
+#define PAL_PORT(line) \
+ ((stm32_gpio_t *)(((uint32_t)(line)) & 0xFFFFFFF0U))
+
+/**
+ * @brief Decodes a pad identifier from a line identifier.
+ */
+#define PAL_PAD(line) \
+ ((uint32_t)((uint32_t)(line) & 0x0000000FU))
+
+/**
+ * @brief Value identifying an invalid line.
+ */
+#define PAL_NOLINE 0U
+/** @} */
+
+/**
+ * @brief Type of digital I/O port sized unsigned integer.
+ */
+typedef uint32_t ioportmask_t;
+
+/**
+ * @brief Type of digital I/O modes.
+ */
+typedef uint32_t iomode_t;
+
+/**
+ * @brief Type of an I/O line.
+ */
+typedef uint32_t ioline_t;
+
+/**
+ * @brief Type of an event mode.
+ */
+typedef uint32_t ioeventmode_t;
+
+/**
+ * @brief Type of a port Identifier.
+ * @details This type can be a scalar or some kind of pointer, do not make
+ * any assumption about it, use the provided macros when populating
+ * variables of this type.
+ */
+typedef stm32_gpio_t * ioportid_t;
+
+/**
+ * @brief Type of an pad identifier.
+ */
+typedef uint32_t iopadid_t;
+
+/*===========================================================================*/
+/* I/O Ports Identifiers. */
+/* The low level driver wraps the definitions already present in the STM32 */
+/* firmware library. */
+/*===========================================================================*/
+
+/**
+ * @brief GPIO port A identifier.
+ */
+#if STM32_HAS_GPIOA || defined(__DOXYGEN__)
+#define IOPORT1 GPIOA
+#endif
+
+/**
+ * @brief GPIO port B identifier.
+ */
+#if STM32_HAS_GPIOB || defined(__DOXYGEN__)
+#define IOPORT2 GPIOB
+#endif
+
+/**
+ * @brief GPIO port C identifier.
+ */
+#if STM32_HAS_GPIOC || defined(__DOXYGEN__)
+#define IOPORT3 GPIOC
+#endif
+
+/**
+ * @brief GPIO port D identifier.
+ */
+#if STM32_HAS_GPIOD || defined(__DOXYGEN__)
+#define IOPORT4 GPIOD
+#endif
+
+/**
+ * @brief GPIO port E identifier.
+ */
+#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
+#define IOPORT5 GPIOE
+#endif
+
+/**
+ * @brief GPIO port F identifier.
+ */
+#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
+#define IOPORT6 GPIOF
+#endif
+
+/**
+ * @brief GPIO port G identifier.
+ */
+#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
+#define IOPORT7 GPIOG
+#endif
+
+/**
+ * @brief GPIO port H identifier.
+ */
+#if STM32_HAS_GPIOH || defined(__DOXYGEN__)
+#define IOPORT8 GPIOH
+#endif
+
+/**
+ * @brief GPIO port I identifier.
+ */
+#if STM32_HAS_GPIOI || defined(__DOXYGEN__)
+#define IOPORT9 GPIOI
+#endif
+
+/**
+ * @brief GPIO port J identifier.
+ */
+#if STM32_HAS_GPIOJ || defined(__DOXYGEN__)
+#define IOPORT10 GPIOJ
+#endif
+
+/**
+ * @brief GPIO port K identifier.
+ */
+#if STM32_HAS_GPIOK || defined(__DOXYGEN__)
+#define IOPORT11 GPIOK
+#endif
+
+/*===========================================================================*/
+/* Implementation, some of the following macros could be implemented as */
+/* functions, if so please put them in pal_lld.c. */
+/*===========================================================================*/
+
+/**
+ * @brief GPIO ports subsystem initialization.
+ *
+ * @notapi
+ */
+#define pal_lld_init() _pal_lld_init()
+
+/**
+ * @brief Reads an I/O port.
+ * @details This function is implemented by reading the GPIO IDR register, the
+ * implementation has no side effects.
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ *
+ * @param[in] port port identifier
+ * @return The port bits.
+ *
+ * @notapi
+ */
+#define pal_lld_readport(port) ((ioportmask_t)((port)->IDR))
+
+/**
+ * @brief Reads the output latch.
+ * @details This function is implemented by reading the GPIO ODR register, the
+ * implementation has no side effects.
+ * @note This function is not meant to be invoked directly by the application
+ * code.
+ *
+ * @param[in] port port identifier
+ * @return The latched logical states.
+ *
+ * @notapi
+ */
+#define pal_lld_readlatch(port) ((ioportmask_t)((port)->ODR))
+
+/**
+ * @brief Writes on a I/O port.
+ * @details This function is implemented by writing the GPIO ODR register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be written on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_writeport(port, bits) ((port)->ODR = (uint32_t)(bits))
+
+/**
+ * @brief Sets a bits mask on a I/O port.
+ * @details This function is implemented by writing the GPIO BSRR register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be ORed on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_setport(port, bits) ((port)->BSRR.H.set = (uint16_t)(bits))
+
+/**
+ * @brief Clears a bits mask on a I/O port.
+ * @details This function is implemented by writing the GPIO BSRR register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be cleared on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_clearport(port, bits) ((port)->BSRR.H.clear = (uint16_t)(bits))
+
+/**
+ * @brief Writes a group of bits.
+ * @details This function is implemented by writing the GPIO BSRR register, the
+ * implementation has no side effects.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask
+ * @param[in] offset the group bit offset within the port
+ * @param[in] bits bits to be written. Values exceeding the group
+ * width are masked.
+ *
+ * @notapi
+ */
+#define pal_lld_writegroup(port, mask, offset, bits) { \
+ uint32_t w = ((~(uint32_t)(bits) & (uint32_t)(mask)) << (16U + (offset))) | \
+ ((uint32_t)(bits) & (uint32_t)(mask)) << (offset); \
+ (port)->BSRR.W = w; \
+}
+
+/**
+ * @brief Pads group mode setup.
+ * @details This function programs a pads group belonging to the same port
+ * with the specified mode.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask
+ * @param[in] offset group bit offset within the port
+ * @param[in] mode group mode
+ *
+ * @notapi
+ */
+#define pal_lld_setgroupmode(port, mask, offset, mode) \
+ _pal_lld_setgroupmode(port, mask << offset, mode)
+
+/**
+ * @brief Writes a logical state on an output pad.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] bit logical value, the value must be @p PAL_LOW or
+ * @p PAL_HIGH
+ *
+ * @notapi
+ */
+#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit)
+
+/**
+ * @brief Pad event enable.
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] mode pad event mode
+ *
+ * @notapi
+ */
+#define pal_lld_enablepadevent(port, pad, mode) \
+ _pal_lld_enablepadevent(port, pad, mode)
+
+/**
+ * @brief Pad event disable.
+ * @details This function disables previously programmed event callbacks.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+#define pal_lld_disablepadevent(port, pad) \
+ _pal_lld_disablepadevent(port, pad)
+
+/**
+ * @brief Returns a PAL event structure associated to a pad.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+#define pal_lld_get_pad_event(port, pad) \
+ &_pal_events[pad]; (void)(port)
+
+/**
+ * @brief Returns a PAL event structure associated to a line.
+ *
+ * @param[in] line line identifier
+ *
+ * @notapi
+ */
+#define pal_lld_get_line_event(line) \
+ &_pal_events[PAL_PAD(line)]
+
+/**
+ * @brief Pad event enable check.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @return Pad event status.
+ * @retval false if the pad event is disabled.
+ * @retval true if the pad event is enabled.
+ *
+ * @notapi
+ */
+#define pal_lld_ispadeventenabled(port, pad) \
+ (bool)((EXTI->IMR1 & (1U << (uint32_t)pad)) != 0U)
+
+#if !defined(__DOXYGEN__)
+#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE)
+extern palevent_t _pal_events[16];
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void _pal_lld_init(void);
+ void _pal_lld_setgroupmode(ioportid_t port,
+ ioportmask_t mask,
+ iomode_t mode);
+ void _pal_lld_enablepadevent(ioportid_t port,
+ iopadid_t pad,
+ ioeventmode_t mode);
+ void _pal_lld_disablepadevent(ioportid_t port, iopadid_t pad);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_PAL */
+
+#endif /* HAL_PAL_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv3/stm32_gpio.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv3/stm32_gpio.h
new file mode 100644
index 0000000..c8ce1df
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/GPIOv3/stm32_gpio.h
@@ -0,0 +1,113 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file GPIOv3/stm32_gpio.h
+ * @brief STM32 GPIO units common header.
+ * @note This file requires definitions from the ST STM32 header file.
+ *
+ * @addtogroup STM32_GPIOv3
+ * @{
+ */
+
+#ifndef STM32_GPIO_H
+#define STM32_GPIO_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/* Discarded definitions from the ST headers, the PAL driver uses its own
+ definitions in order to have an unified handling for all devices.
+ Unfortunately the ST headers have no uniform definitions for the same
+ objects across the various sub-families.*/
+#undef GPIOA
+#undef GPIOB
+#undef GPIOC
+#undef GPIOD
+#undef GPIOE
+#undef GPIOF
+#undef GPIOG
+#undef GPIOH
+#undef GPIOI
+#undef GPIOJ
+#undef GPIOK
+
+/**
+ * @name GPIO ports definitions
+ * @{
+ */
+#define GPIOA ((stm32_gpio_t *)GPIOA_BASE)
+#define GPIOB ((stm32_gpio_t *)GPIOB_BASE)
+#define GPIOC ((stm32_gpio_t *)GPIOC_BASE)
+#define GPIOD ((stm32_gpio_t *)GPIOD_BASE)
+#define GPIOE ((stm32_gpio_t *)GPIOE_BASE)
+#define GPIOF ((stm32_gpio_t *)GPIOF_BASE)
+#define GPIOG ((stm32_gpio_t *)GPIOG_BASE)
+#define GPIOH ((stm32_gpio_t *)GPIOH_BASE)
+#define GPIOI ((stm32_gpio_t *)GPIOI_BASE)
+#define GPIOJ ((stm32_gpio_t *)GPIOJ_BASE)
+#define GPIOK ((stm32_gpio_t *)GPIOK_BASE)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 GPIO registers block.
+ */
+typedef struct {
+
+ volatile uint32_t MODER;
+ volatile uint32_t OTYPER;
+ volatile uint32_t OSPEEDR;
+ volatile uint32_t PUPDR;
+ volatile uint32_t IDR;
+ volatile uint32_t ODR;
+ volatile union {
+ uint32_t W;
+ struct {
+ uint16_t set;
+ uint16_t clear;
+ } H;
+ } BSRR;
+ volatile uint32_t LOCKR;
+ volatile uint32_t AFRL;
+ volatile uint32_t AFRH;
+ volatile uint32_t BRR;
+ volatile uint32_t ASCR;
+} stm32_gpio_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#endif /* STM32_GPIO_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv1/driver.mk
new file mode 100644
index 0000000..476dcb8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv1/driver.mk
@@ -0,0 +1,21 @@
+ifeq ($(USE_HAL_I2C_FALLBACK),yes)
+ # Fallback SW driver.
+ ifeq ($(USE_SMART_BUILD),yes)
+ ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),)
+ PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c
+ endif
+ else
+ PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c
+ endif
+ PLATFORMINC += $(CHIBIOS)/os/hal/lib/fallback/I2C
+else
+ # Default HW driver.
+ ifeq ($(USE_SMART_BUILD),yes)
+ ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),)
+ PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c
+ endif
+ else
+ PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c
+ endif
+ PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1
+endif
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c
new file mode 100644
index 0000000..3fc2289
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c
@@ -0,0 +1,889 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file I2Cv1/hal_i2c_lld.c
+ * @brief STM32 I2C subsystem low level driver source.
+ *
+ * @addtogroup I2C
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_I2C || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define I2C1_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \
+ STM32_I2C1_RX_DMA_CHN)
+
+#define I2C1_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_TX_DMA_STREAM, \
+ STM32_I2C1_TX_DMA_CHN)
+
+#define I2C2_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_RX_DMA_STREAM, \
+ STM32_I2C2_RX_DMA_CHN)
+
+#define I2C2_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_TX_DMA_STREAM, \
+ STM32_I2C2_TX_DMA_CHN)
+
+#define I2C3_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_RX_DMA_STREAM, \
+ STM32_I2C3_RX_DMA_CHN)
+
+#define I2C3_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_TX_DMA_STREAM, \
+ STM32_I2C3_TX_DMA_CHN)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+#define I2C_EV5_MASTER_MODE_SELECT \
+ ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY) << 16) | I2C_SR1_SB))
+
+#define I2C_EV5_MASTER_MODE_SELECT_NO_BUSY \
+ ((uint32_t)((I2C_SR2_MSL << 16) | I2C_SR1_SB))
+
+#define I2C_EV6_MASTER_TRA_MODE_SELECTED \
+ ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA) << 16) | \
+ I2C_SR1_ADDR | I2C_SR1_TXE))
+
+#define I2C_EV6_MASTER_REC_MODE_SELECTED \
+ ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY)<< 16) | I2C_SR1_ADDR))
+
+#define I2C_EV8_2_MASTER_BYTE_TRANSMITTED \
+ ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA) << 16) | \
+ I2C_SR1_BTF | I2C_SR1_TXE))
+
+#define I2C_EV9_MASTER_ADD10 \
+ ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY) << 16) | I2C_SR1_ADD10))
+
+#define I2C_EV_MASK 0x00FFFFFF
+
+#define I2C_ERROR_MASK \
+ ((uint16_t)(I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_AF | I2C_SR1_OVR | \
+ I2C_SR1_PECERR | I2C_SR1_TIMEOUT | I2C_SR1_SMBALERT))
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief I2C1 driver identifier.*/
+#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__)
+I2CDriver I2CD1;
+#endif
+
+/** @brief I2C2 driver identifier.*/
+#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__)
+I2CDriver I2CD2;
+#endif
+
+/** @brief I2C3 driver identifier.*/
+#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__)
+I2CDriver I2CD3;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Aborts an I2C transaction.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_abort_operation(I2CDriver *i2cp) {
+ I2C_TypeDef *dp = i2cp->i2c;
+
+ /* Stops the I2C peripheral.*/
+ dp->CR1 = I2C_CR1_SWRST;
+ dp->CR1 = 0;
+ dp->CR2 = 0;
+ dp->SR1 = 0;
+
+ /* Stops the associated DMA streams.*/
+ dmaStreamDisable(i2cp->dmatx);
+ dmaStreamDisable(i2cp->dmarx);
+}
+
+/**
+ * @brief Set clock speed.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_set_clock(I2CDriver *i2cp) {
+ I2C_TypeDef *dp = i2cp->i2c;
+ uint16_t regCCR, clock_div;
+ int32_t clock_speed = i2cp->config->clock_speed;
+ i2cdutycycle_t duty = i2cp->config->duty_cycle;
+
+ osalDbgCheck((i2cp != NULL) &&
+ (clock_speed > 0) &&
+ (clock_speed <= 400000));
+
+ /* CR2 Configuration.*/
+ dp->CR2 &= (uint16_t)~I2C_CR2_FREQ;
+ dp->CR2 |= (uint16_t)I2C_CLK_FREQ;
+
+ /* CCR Configuration.*/
+ regCCR = 0;
+ clock_div = I2C_CCR_CCR;
+
+ if (clock_speed <= 100000) {
+ /* Configure clock_div in standard mode.*/
+ osalDbgAssert(duty == STD_DUTY_CYCLE, "invalid standard mode duty cycle");
+
+ /* Standard mode clock_div calculate: Tlow/Thigh = 1/1.*/
+ osalDbgAssert((STM32_PCLK1 % (clock_speed * 2)) == 0,
+ "PCLK1 must be divisible without remainder");
+ clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 2));
+
+ osalDbgAssert(clock_div >= 0x04,
+ "clock divider less then 0x04 not allowed");
+ regCCR |= (clock_div & I2C_CCR_CCR);
+
+ /* Sets the Maximum Rise Time for standard mode.*/
+ dp->TRISE = I2C_CLK_FREQ + 1;
+ }
+ else if (clock_speed <= 400000) {
+ /* Configure clock_div in fast mode.*/
+ osalDbgAssert((duty == FAST_DUTY_CYCLE_2) ||
+ (duty == FAST_DUTY_CYCLE_16_9),
+ "invalid fast mode duty cycle");
+
+ if (duty == FAST_DUTY_CYCLE_2) {
+ /* Fast mode clock_div calculate: Tlow/Thigh = 2/1.*/
+ osalDbgAssert((STM32_PCLK1 % (clock_speed * 3)) == 0,
+ "PCLK1 must be divided without remainder");
+ clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 3));
+ }
+ else if (duty == FAST_DUTY_CYCLE_16_9) {
+ /* Fast mode clock_div calculate: Tlow/Thigh = 16/9.*/
+ osalDbgAssert((STM32_PCLK1 % (clock_speed * 25)) == 0,
+ "PCLK1 must be divided without remainder");
+ clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 25));
+ regCCR |= I2C_CCR_DUTY;
+ }
+
+ osalDbgAssert(clock_div >= 0x01,
+ "clock divider less then 0x04 not allowed");
+ regCCR |= (I2C_CCR_FS | (clock_div & I2C_CCR_CCR));
+
+ /* Sets the Maximum Rise Time for fast mode.*/
+ dp->TRISE = (I2C_CLK_FREQ * 300 / 1000) + 1;
+ }
+
+ osalDbgAssert((clock_div <= I2C_CCR_CCR), "the selected clock is too low");
+
+ dp->CCR = regCCR;
+}
+
+/**
+ * @brief Set operation mode of I2C hardware.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_set_opmode(I2CDriver *i2cp) {
+ I2C_TypeDef *dp = i2cp->i2c;
+ i2copmode_t opmode = i2cp->config->op_mode;
+ uint16_t regCR1;
+
+ regCR1 = dp->CR1;
+ switch (opmode) {
+ case OPMODE_I2C:
+ regCR1 &= (uint16_t)~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE);
+ break;
+ case OPMODE_SMBUS_DEVICE:
+ regCR1 |= I2C_CR1_SMBUS;
+ regCR1 &= (uint16_t)~(I2C_CR1_SMBTYPE);
+ break;
+ case OPMODE_SMBUS_HOST:
+ regCR1 |= (I2C_CR1_SMBUS|I2C_CR1_SMBTYPE);
+ break;
+ }
+ dp->CR1 = regCR1;
+}
+
+/**
+ * @brief I2C shared ISR code.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) {
+ I2C_TypeDef *dp = i2cp->i2c;
+ uint32_t regSR2 = dp->SR2;
+ uint32_t event = dp->SR1;
+
+ /* Interrupts are disabled just before dmaStreamEnable() because there
+ is no need of interrupts until next transaction begin. All the work is
+ done by the DMA.*/
+ switch (I2C_EV_MASK & (event | (regSR2 << 16))) {
+ case I2C_EV5_MASTER_MODE_SELECT:
+ case I2C_EV5_MASTER_MODE_SELECT_NO_BUSY:
+ if ((i2cp->addr >> 8) > 0) {
+ /* 10-bit address: 1 1 1 1 0 X X R/W */
+ dp->DR = 0xF0 | (0x6 & (i2cp->addr >> 8)) | (0x1 & i2cp->addr);
+ } else {
+ dp->DR = i2cp->addr;
+ }
+ break;
+ case I2C_EV9_MASTER_ADD10:
+ /* Set second addr byte (10-bit addressing)*/
+ dp->DR = (0xFF & (i2cp->addr >> 1));
+ break;
+ case I2C_EV6_MASTER_REC_MODE_SELECTED:
+ dp->CR2 &= ~I2C_CR2_ITEVTEN;
+ dmaStreamEnable(i2cp->dmarx);
+ dp->CR2 |= I2C_CR2_LAST; /* Needed in receiver mode. */
+ if (dmaStreamGetTransactionSize(i2cp->dmarx) < 2)
+ dp->CR1 &= ~I2C_CR1_ACK;
+ break;
+ case I2C_EV6_MASTER_TRA_MODE_SELECTED:
+ dp->CR2 &= ~I2C_CR2_ITEVTEN;
+ dmaStreamEnable(i2cp->dmatx);
+ break;
+ case I2C_EV8_2_MASTER_BYTE_TRANSMITTED:
+ /* Catches BTF event after the end of transmission.*/
+ (void)dp->DR; /* clear BTF.*/
+ if (dmaStreamGetTransactionSize(i2cp->dmarx) > 0) {
+ /* Starts "read after write" operation, LSB = 1 -> receive.*/
+ i2cp->addr |= 0x01;
+ dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK;
+ return;
+ }
+ dp->CR2 &= ~I2C_CR2_ITEVTEN;
+ dp->CR1 |= I2C_CR1_STOP;
+ _i2c_wakeup_isr(i2cp);
+ break;
+ default:
+ break;
+ }
+ /* Clear ADDR flag. */
+ if (event & (I2C_SR1_ADDR | I2C_SR1_ADD10))
+ (void)dp->SR2;
+
+ /* Errata 2.4.6 for STM32F40x, Spurious Bus Error detection in Master mode.*/
+ if (event & I2C_SR1_BERR) {
+ dp->SR1 &= ~I2C_SR1_BERR;
+ }
+}
+
+/**
+ * @brief DMA RX end IRQ handler.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ *
+ * @notapi
+ */
+static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp, uint32_t flags) {
+ I2C_TypeDef *dp = i2cp->i2c;
+
+ /* DMA errors handling.*/
+#if defined(STM32_I2C_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_I2C_DMA_ERROR_HOOK(i2cp);
+ }
+#else
+ (void)flags;
+#endif
+
+ dmaStreamDisable(i2cp->dmarx);
+
+ dp->CR2 &= ~I2C_CR2_LAST;
+ dp->CR1 &= ~I2C_CR1_ACK;
+ dp->CR1 |= I2C_CR1_STOP;
+ _i2c_wakeup_isr(i2cp);
+}
+
+/**
+ * @brief DMA TX end IRQ handler.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) {
+ I2C_TypeDef *dp = i2cp->i2c;
+
+ /* DMA errors handling.*/
+#if defined(STM32_I2C_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_I2C_DMA_ERROR_HOOK(i2cp);
+ }
+#else
+ (void)flags;
+#endif
+
+ dmaStreamDisable(i2cp->dmatx);
+ /* Enables interrupts to catch BTF event meaning transmission part complete.
+ Interrupt handler will decide to generate STOP or to begin receiving part
+ of R/W transaction itself.*/
+ dp->CR2 |= I2C_CR2_ITEVTEN;
+}
+
+/**
+ * @brief I2C error handler.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] sr content of the SR1 register to be decoded
+ *
+ * @notapi
+ */
+static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint16_t sr) {
+
+ /* Clears interrupt flags just to be safe.*/
+ dmaStreamDisable(i2cp->dmatx);
+ dmaStreamDisable(i2cp->dmarx);
+
+ i2cp->errors = I2C_NO_ERROR;
+
+ if (sr & I2C_SR1_BERR) { /* Bus error. */
+ i2cp->errors |= I2C_BUS_ERROR;
+ /* Errata 2.4.6 for STM32F40x, Spurious Bus Error detection in
+ Master mode.*/
+ i2cp->i2c->SR1 &= ~I2C_SR1_BERR;
+ }
+
+ if (sr & I2C_SR1_ARLO) /* Arbitration lost. */
+ i2cp->errors |= I2C_ARBITRATION_LOST;
+
+ if (sr & I2C_SR1_AF) { /* Acknowledge fail. */
+ i2cp->i2c->CR2 &= ~I2C_CR2_ITEVTEN;
+ i2cp->i2c->CR1 |= I2C_CR1_STOP; /* Setting stop bit. */
+ i2cp->errors |= I2C_ACK_FAILURE;
+ }
+
+ if (sr & I2C_SR1_OVR) /* Overrun. */
+ i2cp->errors |= I2C_OVERRUN;
+
+ if (sr & I2C_SR1_TIMEOUT) /* SMBus Timeout. */
+ i2cp->errors |= I2C_TIMEOUT;
+
+ if (sr & I2C_SR1_PECERR) /* PEC error. */
+ i2cp->errors |= I2C_PEC_ERROR;
+
+ if (sr & I2C_SR1_SMBALERT) /* SMBus alert. */
+ i2cp->errors |= I2C_SMB_ALERT;
+
+ /* If some error has been identified then sends wakes the waiting thread.*/
+ if (i2cp->errors != I2C_NO_ERROR)
+ _i2c_wakeup_error_isr(i2cp);
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__)
+/**
+ * @brief I2C1 event interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ i2c_lld_serve_event_interrupt(&I2CD1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief I2C1 error interrupt handler.
+ */
+OSAL_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) {
+ uint16_t sr = I2CD1.i2c->SR1;
+
+ OSAL_IRQ_PROLOGUE();
+
+ I2CD1.i2c->SR1 = ~(sr & I2C_ERROR_MASK);
+ i2c_lld_serve_error_interrupt(&I2CD1, sr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* STM32_I2C_USE_I2C1 */
+
+#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__)
+/**
+ * @brief I2C2 event interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ i2c_lld_serve_event_interrupt(&I2CD2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief I2C2 error interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) {
+ uint16_t sr = I2CD2.i2c->SR1;
+
+ OSAL_IRQ_PROLOGUE();
+
+ I2CD2.i2c->SR1 = ~(sr & I2C_ERROR_MASK);
+ i2c_lld_serve_error_interrupt(&I2CD2, sr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* STM32_I2C_USE_I2C2 */
+
+#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__)
+/**
+ * @brief I2C3 event interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(STM32_I2C3_EVENT_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ i2c_lld_serve_event_interrupt(&I2CD3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief I2C3 error interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(STM32_I2C3_ERROR_HANDLER) {
+ uint16_t sr = I2CD3.i2c->SR1;
+
+ OSAL_IRQ_PROLOGUE();
+
+ I2CD3.i2c->SR1 = ~(sr & I2C_ERROR_MASK);
+ i2c_lld_serve_error_interrupt(&I2CD3, sr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* STM32_I2C_USE_I2C3 */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level I2C driver initialization.
+ *
+ * @notapi
+ */
+void i2c_lld_init(void) {
+
+#if STM32_I2C_USE_I2C1
+ i2cObjectInit(&I2CD1);
+ I2CD1.thread = NULL;
+ I2CD1.i2c = I2C1;
+ I2CD1.dmarx = NULL;
+ I2CD1.dmatx = NULL;
+#endif /* STM32_I2C_USE_I2C1 */
+
+#if STM32_I2C_USE_I2C2
+ i2cObjectInit(&I2CD2);
+ I2CD2.thread = NULL;
+ I2CD2.i2c = I2C2;
+ I2CD2.dmarx = NULL;
+ I2CD2.dmatx = NULL;
+#endif /* STM32_I2C_USE_I2C2 */
+
+#if STM32_I2C_USE_I2C3
+ i2cObjectInit(&I2CD3);
+ I2CD3.thread = NULL;
+ I2CD3.i2c = I2C3;
+ I2CD3.dmarx = NULL;
+ I2CD3.dmatx = NULL;
+#endif /* STM32_I2C_USE_I2C3 */
+}
+
+/**
+ * @brief Configures and activates the I2C peripheral.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+void i2c_lld_start(I2CDriver *i2cp) {
+ I2C_TypeDef *dp = i2cp->i2c;
+
+ /* If in stopped state then enables the I2C and DMA clocks.*/
+ if (i2cp->state == I2C_STOP) {
+
+ i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DIR_M2P;
+ i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DIR_P2M;
+
+#if STM32_I2C_USE_I2C1
+ if (&I2CD1 == i2cp) {
+ rccResetI2C1();
+
+ i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C1_RX_DMA_STREAM,
+ STM32_I2C_I2C1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream");
+ i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C1_TX_DMA_STREAM,
+ STM32_I2C_I2C1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableI2C1(true);
+ nvicEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY);
+ nvicEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY);
+
+ i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY);
+ i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY);
+ }
+#endif /* STM32_I2C_USE_I2C1 */
+
+#if STM32_I2C_USE_I2C2
+ if (&I2CD2 == i2cp) {
+ rccResetI2C2();
+
+ i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C2_RX_DMA_STREAM,
+ STM32_I2C_I2C2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream");
+ i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C2_TX_DMA_STREAM,
+ STM32_I2C_I2C2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableI2C2(true);
+ nvicEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY);
+ nvicEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY);
+
+ i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY);
+ i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY);
+ }
+#endif /* STM32_I2C_USE_I2C2 */
+
+#if STM32_I2C_USE_I2C3
+ if (&I2CD3 == i2cp) {
+ rccResetI2C3();
+
+ i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C3_RX_DMA_STREAM,
+ STM32_I2C_I2C3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream");
+ i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C3_TX_DMA_STREAM,
+ STM32_I2C_I2C3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableI2C3(true);
+ nvicEnableVector(I2C3_EV_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY);
+ nvicEnableVector(I2C3_ER_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY);
+
+ i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY);
+ i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY);
+ }
+#endif /* STM32_I2C_USE_I2C3 */
+ }
+
+ /* I2C registers pointed by the DMA.*/
+ dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR);
+ dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR);
+
+ /* Reset i2c peripheral.*/
+ dp->CR1 = I2C_CR1_SWRST;
+ dp->CR1 = 0;
+ dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN;
+
+ /* Setup I2C parameters.*/
+ i2c_lld_set_clock(i2cp);
+ i2c_lld_set_opmode(i2cp);
+
+ /* Ready to go.*/
+ dp->CR1 |= I2C_CR1_PE;
+}
+
+/**
+ * @brief Deactivates the I2C peripheral.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+void i2c_lld_stop(I2CDriver *i2cp) {
+
+ /* If not in stopped state then disables the I2C clock.*/
+ if (i2cp->state != I2C_STOP) {
+
+ /* I2C disable.*/
+ i2c_lld_abort_operation(i2cp);
+ dmaStreamFreeI(i2cp->dmatx);
+ dmaStreamFreeI(i2cp->dmarx);
+ i2cp->dmatx = NULL;
+ i2cp->dmarx = NULL;
+
+#if STM32_I2C_USE_I2C1
+ if (&I2CD1 == i2cp) {
+ nvicDisableVector(I2C1_EV_IRQn);
+ nvicDisableVector(I2C1_ER_IRQn);
+ rccDisableI2C1();
+ }
+#endif
+
+#if STM32_I2C_USE_I2C2
+ if (&I2CD2 == i2cp) {
+ nvicDisableVector(I2C2_EV_IRQn);
+ nvicDisableVector(I2C2_ER_IRQn);
+ rccDisableI2C2();
+ }
+#endif
+
+#if STM32_I2C_USE_I2C3
+ if (&I2CD3 == i2cp) {
+ nvicDisableVector(I2C3_EV_IRQn);
+ nvicDisableVector(I2C3_ER_IRQn);
+ rccDisableI2C3();
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Receives data via the I2C bus as master.
+ * @details Number of receiving bytes must be more than 1 on STM32F1x. This is
+ * hardware restriction.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] addr slave device address
+ * @param[out] rxbuf pointer to the receive buffer
+ * @param[in] rxbytes number of bytes to be received
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a
+ * timeout the driver must be stopped and restarted
+ * because the bus is in an uncertain state.
+ *
+ * @notapi
+ */
+msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout) {
+ I2C_TypeDef *dp = i2cp->i2c;
+ systime_t start, end;
+ msg_t msg;
+
+#if defined(STM32F1XX_I2C)
+ osalDbgCheck(rxbytes > 1);
+#endif
+
+ /* Resetting error flags for this transfer.*/
+ i2cp->errors = I2C_NO_ERROR;
+
+ /* Initializes driver fields, LSB = 1 -> receive.*/
+ i2cp->addr = (addr << 1) | 0x01;
+
+ /* Releases the lock from high level driver.*/
+ osalSysUnlock();
+
+ /* RX DMA setup.*/
+ dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
+ dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
+ dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
+
+ /* Calculating the time window for the timeout on the busy bus condition.*/
+ start = osalOsGetSystemTimeX();
+ end = osalTimeAddX(start, OSAL_MS2I(STM32_I2C_BUSY_TIMEOUT));
+
+ /* Waits until BUSY flag is reset or, alternatively, for a timeout
+ condition.*/
+ while (true) {
+ osalSysLock();
+
+ /* If the bus is not busy then the operation can continue, note, the
+ loop is exited in the locked state.*/
+ if (!(dp->SR2 & I2C_SR2_BUSY) && !(dp->CR1 & I2C_CR1_STOP))
+ break;
+
+ /* If the system time went outside the allowed window then a timeout
+ condition is returned.*/
+ if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) {
+ dmaStreamDisable(i2cp->dmarx);
+ return MSG_TIMEOUT;
+ }
+
+ osalSysUnlock();
+ }
+
+ /* Starts the operation.*/
+ dp->CR2 |= I2C_CR2_ITEVTEN;
+ dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK;
+
+ /* Waits for the operation completion or a timeout.*/
+ msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout);
+ if (msg != MSG_OK) {
+ dmaStreamDisable(i2cp->dmarx);
+ }
+
+ return msg;
+}
+
+/**
+ * @brief Transmits data via the I2C bus as master.
+ * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x.
+ * This is hardware restriction.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] addr slave device address
+ * @param[in] txbuf pointer to the transmit buffer
+ * @param[in] txbytes number of bytes to be transmitted
+ * @param[out] rxbuf pointer to the receive buffer
+ * @param[in] rxbytes number of bytes to be received
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a
+ * timeout the driver must be stopped and restarted
+ * because the bus is in an uncertain state.
+ *
+ * @notapi
+ */
+msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ const uint8_t *txbuf, size_t txbytes,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout) {
+ I2C_TypeDef *dp = i2cp->i2c;
+ systime_t start, end;
+ msg_t msg;
+
+#if defined(STM32F1XX_I2C)
+ osalDbgCheck((rxbytes == 0) || ((rxbytes > 1) && (rxbuf != NULL)));
+#endif
+
+ /* Resetting error flags for this transfer.*/
+ i2cp->errors = I2C_NO_ERROR;
+
+ /* Initializes driver fields, LSB = 0 -> transmit.*/
+ i2cp->addr = (addr << 1);
+
+ /* Releases the lock from high level driver.*/
+ osalSysUnlock();
+
+ /* TX DMA setup.*/
+ dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
+ dmaStreamSetMemory0(i2cp->dmatx, txbuf);
+ dmaStreamSetTransactionSize(i2cp->dmatx, txbytes);
+
+ /* RX DMA setup.*/
+ dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
+ dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
+ dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
+
+ /* Calculating the time window for the timeout on the busy bus condition.*/
+ start = osalOsGetSystemTimeX();
+ end = osalTimeAddX(start, OSAL_MS2I(STM32_I2C_BUSY_TIMEOUT));
+
+ /* Waits until BUSY flag is reset or, alternatively, for a timeout
+ condition.*/
+ while (true) {
+ osalSysLock();
+
+ /* If the bus is not busy then the operation can continue, note, the
+ loop is exited in the locked state.*/
+ if (!(dp->SR2 & I2C_SR2_BUSY) && !(dp->CR1 & I2C_CR1_STOP))
+ break;
+
+ /* If the system time went outside the allowed window then a timeout
+ condition is returned.*/
+ if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) {
+ dmaStreamDisable(i2cp->dmatx);
+ dmaStreamDisable(i2cp->dmarx);
+ return MSG_TIMEOUT;
+ }
+
+ osalSysUnlock();
+ }
+
+ /* Starts the operation.*/
+ dp->CR2 |= I2C_CR2_ITEVTEN;
+ dp->CR1 |= I2C_CR1_START;
+
+ /* Waits for the operation completion or a timeout.*/
+ msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout);
+ if (msg != MSG_OK) {
+ dmaStreamDisable(i2cp->dmatx);
+ dmaStreamDisable(i2cp->dmarx);
+ }
+
+ return msg;
+}
+
+#endif /* HAL_USE_I2C */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h
new file mode 100644
index 0000000..1328d47
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h
@@ -0,0 +1,513 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file I2Cv1/hal_i2c_lld.h
+ * @brief STM32 I2C subsystem low level driver header.
+ *
+ * @addtogroup I2C
+ * @{
+ */
+
+#ifndef HAL_I2C_LLD_H
+#define HAL_I2C_LLD_H
+
+#if HAL_USE_I2C || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Peripheral clock frequency.
+ */
+#define I2C_CLK_FREQ ((STM32_PCLK1) / 1000000)
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief I2C1 driver enable switch.
+ * @details If set to @p TRUE the support for I2C1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__)
+#define STM32_I2C_USE_I2C1 FALSE
+#endif
+
+/**
+ * @brief I2C2 driver enable switch.
+ * @details If set to @p TRUE the support for I2C2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__)
+#define STM32_I2C_USE_I2C2 FALSE
+#endif
+
+/**
+ * @brief I2C3 driver enable switch.
+ * @details If set to @p TRUE the support for I2C3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_I2C_USE_I2C3) || defined(__DOXYGEN__)
+#define STM32_I2C_USE_I2C3 FALSE
+#endif
+
+/**
+ * @brief I2C timeout on busy condition in milliseconds.
+ */
+#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__)
+#define STM32_I2C_BUSY_TIMEOUT 50
+#endif
+
+/**
+ * @brief I2C1 interrupt priority level setting.
+ */
+#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C1_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief I2C2 interrupt priority level setting.
+ */
+#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C2_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief I2C3 interrupt priority level setting.
+ */
+#if !defined(STM32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C3_IRQ_PRIORITY 10
+#endif
+
+/**
+* @brief I2C1 DMA priority (0..3|lowest..highest).
+* @note The priority level is used for both the TX and RX DMA streams but
+* because of the streams ordering the RX stream has always priority
+* over the TX stream.
+*/
+#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C1_DMA_PRIORITY 1
+#endif
+
+/**
+* @brief I2C2 DMA priority (0..3|lowest..highest).
+* @note The priority level is used for both the TX and RX DMA streams but
+* because of the streams ordering the RX stream has always priority
+* over the TX stream.
+*/
+#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C2_DMA_PRIORITY 1
+#endif
+
+/**
+* @brief I2C3 DMA priority (0..3|lowest..highest).
+* @note The priority level is used for both the TX and RX DMA streams but
+* because of the streams ordering the RX stream has always priority
+* over the TX stream.
+*/
+#if !defined(STM32_I2C_I2C3_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C3_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2C DMA error hook.
+ * @note The default action for DMA errors is a system halt because DMA
+ * error can only happen because programming errors.
+ */
+#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
+#endif
+
+#if STM32_ADVANCED_DMA || defined(__DOXYGEN__)
+
+/**
+ * @brief DMA stream used for I2C1 RX operations.
+ * @note This option is only available on platforms with enhanced DMA.
+ */
+#if !defined(STM32_I2C_I2C1_RX_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0)
+#endif
+
+/**
+ * @brief DMA stream used for I2C1 TX operations.
+ * @note This option is only available on platforms with enhanced DMA.
+ */
+#if !defined(STM32_I2C_I2C1_TX_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
+#endif
+
+/**
+ * @brief DMA stream used for I2C2 RX operations.
+ * @note This option is only available on platforms with enhanced DMA.
+ */
+#if !defined(STM32_I2C_I2C2_RX_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
+#endif
+
+/**
+ * @brief DMA stream used for I2C2 TX operations.
+ * @note This option is only available on platforms with enhanced DMA.
+ */
+#if !defined(STM32_I2C_I2C2_TX_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
+#endif
+
+/**
+ * @brief DMA stream used for I2C3 RX operations.
+ * @note This option is only available on platforms with enhanced DMA.
+ */
+#if !defined(STM32_I2C_I2C3_RX_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
+#endif
+
+/**
+ * @brief DMA stream used for I2C3 TX operations.
+ * @note This option is only available on platforms with enhanced DMA.
+ */
+#if !defined(STM32_I2C_I2C3_TX_DMA_STREAM) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
+#endif
+
+#else /* !STM32_ADVANCED_DMA */
+
+/* Fixed streams for platforms using the old DMA peripheral, the values are
+ valid for both STM32F1xx and STM32L1xx.*/
+#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
+#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
+#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5)
+#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
+
+#endif /* !STM32_ADVANCED_DMA*/
+
+/* Flag for the whole STM32F1XX family. */
+#if defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \
+ defined(STM32F10X_HD_VL) || defined(STM32F10X_LD) || \
+ defined(STM32F10X_MD) || defined(STM32F10X_HD) || \
+ defined(STM32F10X_XL) || defined(STM32F10X_CL)
+#define STM32F1XX_I2C
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/** @brief error checks */
+#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1
+#error "I2C1 not present in the selected device"
+#endif
+
+#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2
+#error "I2C2 not present in the selected device"
+#endif
+
+#if STM32_I2C_USE_I2C3 && !STM32_HAS_I2C3
+#error "I2C3 not present in the selected device"
+#endif
+
+#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 && \
+ !STM32_I2C_USE_I2C3
+#error "I2C driver activated but no I2C peripheral assigned"
+#endif
+
+#if STM32_I2C_USE_I2C1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to I2C1"
+#endif
+
+#if STM32_I2C_USE_I2C2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to I2C2"
+#endif
+
+#if STM32_I2C_USE_I2C3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to I2C3"
+#endif
+
+#if STM32_I2C_USE_I2C1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to I2C1"
+#endif
+
+#if STM32_I2C_USE_I2C2 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to I2C2"
+#endif
+
+#if STM32_I2C_USE_I2C3 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C3_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to I2C3"
+#endif
+
+/* The following checks are only required when there is a DMA able to
+ reassign streams to different channels.*/
+#if STM32_ADVANCED_DMA
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if STM32_I2C_USE_I2C1 && (!defined(STM32_I2C_I2C1_RX_DMA_STREAM) || \
+ !defined(STM32_I2C_I2C1_TX_DMA_STREAM))
+#error "I2C1 DMA streams not defined"
+#endif
+
+#if STM32_I2C_USE_I2C2 && (!defined(STM32_I2C_I2C2_RX_DMA_STREAM) || \
+ !defined(STM32_I2C_I2C2_TX_DMA_STREAM))
+#error "I2C2 DMA streams not defined"
+#endif
+
+/* Check on the validity of the assigned DMA channels.*/
+#if STM32_I2C_USE_I2C1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_RX_DMA_STREAM, \
+ STM32_I2C1_RX_DMA_MSK)
+#error "invalid DMA stream associated to I2C1 RX"
+#endif
+
+#if STM32_I2C_USE_I2C1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_TX_DMA_STREAM, \
+ STM32_I2C1_TX_DMA_MSK)
+#error "invalid DMA stream associated to I2C1 TX"
+#endif
+
+#if STM32_I2C_USE_I2C2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_RX_DMA_STREAM, \
+ STM32_I2C2_RX_DMA_MSK)
+#error "invalid DMA stream associated to I2C2 RX"
+#endif
+
+#if STM32_I2C_USE_I2C2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_TX_DMA_STREAM, \
+ STM32_I2C2_TX_DMA_MSK)
+#error "invalid DMA stream associated to I2C2 TX"
+#endif
+
+#if STM32_I2C_USE_I2C3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_RX_DMA_STREAM, \
+ STM32_I2C3_RX_DMA_MSK)
+#error "invalid DMA stream associated to I2C3 RX"
+#endif
+
+#if STM32_I2C_USE_I2C3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_TX_DMA_STREAM, \
+ STM32_I2C3_TX_DMA_MSK)
+#error "invalid DMA stream associated to I2C3 TX"
+#endif
+#endif /* STM32_ADVANCED_DMA */
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+/* Check clock range. */
+#if defined(STM32F4XX)
+#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 42)
+#error "I2C peripheral clock frequency out of range."
+#endif
+
+#elif defined(STM32L1XX)
+#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 32)
+#error "I2C peripheral clock frequency out of range."
+#endif
+
+#elif defined(STM32F2XX)
+#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 30)
+#error "I2C peripheral clock frequency out of range."
+#endif
+
+#elif defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \
+ defined(STM32F10X_HD_VL)
+#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 24)
+#error "I2C peripheral clock frequency out of range."
+#endif
+
+#elif defined(STM32F10X_LD) || defined(STM32F10X_MD) || \
+ defined(STM32F10X_HD) || defined(STM32F10X_XL) || \
+ defined(STM32F10X_CL)
+#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 36)
+#error "I2C peripheral clock frequency out of range."
+#endif
+#else
+#error "unspecified, unsupported or invalid STM32 platform"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type representing an I2C address.
+ */
+typedef uint16_t i2caddr_t;
+
+/**
+ * @brief Type of I2C driver condition flags.
+ */
+typedef uint32_t i2cflags_t;
+
+/**
+ * @brief Supported modes for the I2C bus.
+ */
+typedef enum {
+ OPMODE_I2C = 1,
+ OPMODE_SMBUS_DEVICE = 2,
+ OPMODE_SMBUS_HOST = 3,
+} i2copmode_t;
+
+/**
+ * @brief Supported duty cycle modes for the I2C bus.
+ */
+typedef enum {
+ STD_DUTY_CYCLE = 1,
+ FAST_DUTY_CYCLE_2 = 2,
+ FAST_DUTY_CYCLE_16_9 = 3,
+} i2cdutycycle_t;
+
+/**
+ * @brief Type of I2C driver configuration structure.
+ */
+typedef struct {
+ /* End of the mandatory fields.*/
+ i2copmode_t op_mode; /**< @brief Specifies the I2C mode. */
+ uint32_t clock_speed; /**< @brief Specifies the clock frequency.
+ @note Must be set to a value lower
+ than 400kHz. */
+ i2cdutycycle_t duty_cycle; /**< @brief Specifies the I2C fast mode
+ duty cycle. */
+} I2CConfig;
+
+/**
+ * @brief Type of a structure representing an I2C driver.
+ */
+typedef struct I2CDriver I2CDriver;
+
+/**
+ * @brief Structure representing an I2C driver.
+ */
+struct I2CDriver {
+ /**
+ * @brief Driver state.
+ */
+ i2cstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const I2CConfig *config;
+ /**
+ * @brief Error flags.
+ */
+ i2cflags_t errors;
+#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
+ /**
+ * @brief Mutex protecting the bus.
+ */
+ mutex_t mutex;
+#endif /* I2C_USE_MUTUAL_EXCLUSION */
+#if defined(I2C_DRIVER_EXT_FIELDS)
+ I2C_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Thread waiting for I/O completion.
+ */
+ thread_reference_t thread;
+ /**
+ * @brief Current slave address without R/W bit.
+ */
+ i2caddr_t addr;
+ /**
+ * @brief RX DMA mode bit mask.
+ */
+ uint32_t rxdmamode;
+ /**
+ * @brief TX DMA mode bit mask.
+ */
+ uint32_t txdmamode;
+ /**
+ * @brief Receive DMA channel.
+ */
+ const stm32_dma_stream_t *dmarx;
+ /**
+ * @brief Transmit DMA channel.
+ */
+ const stm32_dma_stream_t *dmatx;
+ /**
+ * @brief Pointer to the I2Cx registers block.
+ */
+ I2C_TypeDef *i2c;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Get errors from I2C driver.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+#define i2c_lld_get_errors(i2cp) ((i2cp)->errors)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+#if STM32_I2C_USE_I2C1
+extern I2CDriver I2CD1;
+#endif
+
+#if STM32_I2C_USE_I2C2
+extern I2CDriver I2CD2;
+#endif
+
+#if STM32_I2C_USE_I2C3
+extern I2CDriver I2CD3;
+#endif
+#endif /* !defined(__DOXYGEN__) */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void i2c_lld_init(void);
+ void i2c_lld_start(I2CDriver *i2cp);
+ void i2c_lld_stop(I2CDriver *i2cp);
+ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ const uint8_t *txbuf, size_t txbytes,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout);
+ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_I2C */
+
+#endif /* HAL_I2C_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv2/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv2/driver.mk
new file mode 100644
index 0000000..69b63ce
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv2/driver.mk
@@ -0,0 +1,21 @@
+ifeq ($(USE_HAL_I2C_FALLBACK),yes)
+ # Fallback SW driver.
+ ifeq ($(USE_SMART_BUILD),yes)
+ ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),)
+ PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c
+ endif
+ else
+ PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c
+ endif
+ PLATFORMINC += $(CHIBIOS)/os/hal/lib/fallback/I2C
+else
+ # Default HW driver.
+ ifeq ($(USE_SMART_BUILD),yes)
+ ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),)
+ PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c
+ endif
+ else
+ PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c
+ endif
+ PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2
+endif
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c
new file mode 100644
index 0000000..06c2858
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c
@@ -0,0 +1,1169 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file I2Cv2/hal_i2c_lld.c
+ * @brief STM32 I2C subsystem low level driver source.
+ *
+ * @addtogroup I2C
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_I2C || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#if STM32_I2C_USE_DMA == TRUE
+#define DMAMODE_COMMON \
+ (STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | \
+ STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | \
+ STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE)
+
+#define I2C1_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \
+ STM32_I2C1_RX_DMA_CHN)
+
+#define I2C1_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_TX_DMA_STREAM, \
+ STM32_I2C1_TX_DMA_CHN)
+
+#define I2C2_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_RX_DMA_STREAM, \
+ STM32_I2C2_RX_DMA_CHN)
+
+#define I2C2_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_TX_DMA_STREAM, \
+ STM32_I2C2_TX_DMA_CHN)
+
+#define I2C3_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_RX_DMA_STREAM, \
+ STM32_I2C3_RX_DMA_CHN)
+
+#define I2C3_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_TX_DMA_STREAM, \
+ STM32_I2C3_TX_DMA_CHN)
+
+#define I2C4_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2C_I2C4_RX_DMA_STREAM, \
+ STM32_I2C4_RX_DMA_CHN)
+
+#define I2C4_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2C_I2C4_TX_DMA_STREAM, \
+ STM32_I2C4_TX_DMA_CHN)
+#endif /* STM32_I2C_USE_DMA == TRUE */
+
+#if STM32_I2C_USE_DMA == TRUE
+#define i2c_lld_get_rxbytes(i2cp) dmaStreamGetTransactionSize((i2cp)->dmarx)
+#define i2c_lld_get_txbytes(i2cp) dmaStreamGetTransactionSize((i2cp)->dmatx)
+#else
+#define i2c_lld_get_rxbytes(i2cp) (i2cp)->rxbytes
+#define i2c_lld_get_txbytes(i2cp) (i2cp)->txbytes
+#endif
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+#define I2C_ERROR_MASK \
+ ((uint32_t)(I2C_ISR_BERR | I2C_ISR_ARLO | I2C_ISR_OVR | I2C_ISR_PECERR | \
+ I2C_ISR_TIMEOUT | I2C_ISR_ALERT))
+
+#define I2C_INT_MASK \
+ ((uint32_t)(I2C_ISR_TCR | I2C_ISR_TC | I2C_ISR_STOPF | I2C_ISR_NACKF | \
+ I2C_ISR_ADDR | I2C_ISR_RXNE | I2C_ISR_TXIS))
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief I2C1 driver identifier.*/
+#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__)
+I2CDriver I2CD1;
+#endif
+
+/** @brief I2C2 driver identifier.*/
+#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__)
+I2CDriver I2CD2;
+#endif
+
+/** @brief I2C3 driver identifier.*/
+#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__)
+I2CDriver I2CD3;
+#endif
+
+/** @brief I2C4 driver identifier.*/
+#if STM32_I2C_USE_I2C4 || defined(__DOXYGEN__)
+I2CDriver I2CD4;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Slave address setup.
+ * @note The RW bit is set to zero internally.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] addr slave device address
+ *
+ * @notapi
+ */
+static void i2c_lld_set_address(I2CDriver *i2cp, i2caddr_t addr) {
+ I2C_TypeDef *dp = i2cp->i2c;
+
+ /* Address alignment depends on the addressing mode selected.*/
+ if ((i2cp->config->cr2 & I2C_CR2_ADD10) == 0U)
+ dp->CR2 = (uint32_t)addr << 1U;
+ else
+ dp->CR2 = (uint32_t)addr;
+}
+
+/**
+ * @brief I2C RX transfer setup.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_setup_rx_transfer(I2CDriver *i2cp) {
+ I2C_TypeDef *dp = i2cp->i2c;
+ uint32_t reload;
+ size_t n;
+
+ /* The unit can transfer 255 bytes maximum in a single operation.*/
+ n = i2c_lld_get_rxbytes(i2cp);
+ if (n > 255U) {
+ n = 255U;
+ reload = I2C_CR2_RELOAD;
+ }
+ else {
+ reload = 0U;
+ }
+
+ /* Configures the CR2 registers with both the calculated and static
+ settings.*/
+ dp->CR2 = (dp->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | i2cp->config->cr2 |
+ I2C_CR2_RD_WRN | (n << 16U) | reload;
+}
+
+/**
+ * @brief I2C TX transfer setup.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_setup_tx_transfer(I2CDriver *i2cp) {
+ I2C_TypeDef *dp = i2cp->i2c;
+ uint32_t reload;
+ size_t n;
+
+ /* The unit can transfer 255 bytes maximum in a single operation.*/
+ n = i2c_lld_get_txbytes(i2cp);
+ if (n > 255U) {
+ n = 255U;
+ reload = I2C_CR2_RELOAD;
+ }
+ else {
+ reload = 0U;
+ }
+
+ /* Configures the CR2 registers with both the calculated and static
+ settings.*/
+ dp->CR2 = (dp->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | i2cp->config->cr2 |
+ (n << 16U) | reload;
+}
+
+/**
+ * @brief Aborts an I2C transaction.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_abort_operation(I2CDriver *i2cp) {
+ I2C_TypeDef *dp = i2cp->i2c;
+
+ if (dp->CR1 & I2C_CR1_PE) {
+ /* Stops the I2C peripheral.*/
+ dp->CR1 &= ~I2C_CR1_PE;
+ while (dp->CR1 & I2C_CR1_PE)
+ dp->CR1 &= ~I2C_CR1_PE;
+ dp->CR1 |= I2C_CR1_PE;
+ }
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* Stops the associated DMA streams.*/
+ dmaStreamDisable(i2cp->dmatx);
+ dmaStreamDisable(i2cp->dmarx);
+#else
+ dp->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE);
+#endif
+}
+
+/**
+ * @brief I2C shared ISR code.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] isr content of the ISR register to be decoded
+ *
+ * @notapi
+ */
+static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t isr) {
+ I2C_TypeDef *dp = i2cp->i2c;
+
+ /* Special case of a received NACK, the transfer is aborted.*/
+ if ((isr & I2C_ISR_NACKF) != 0U) {
+#if STM32_I2C_USE_DMA == TRUE
+ /* Stops the associated DMA streams.*/
+ dmaStreamDisable(i2cp->dmatx);
+ dmaStreamDisable(i2cp->dmarx);
+#endif
+
+ /* Error flag.*/
+ i2cp->errors |= I2C_ACK_FAILURE;
+
+ /* Transaction finished sending the STOP.*/
+ dp->CR2 |= I2C_CR2_STOP;
+
+ /* Make sure no more interrupts.*/
+ dp->CR1 &= ~(I2C_CR1_TCIE | I2C_CR1_TXIE | I2C_CR1_RXIE);
+
+ /* Errors are signaled to the upper layer.*/
+ _i2c_wakeup_error_isr(i2cp);
+
+ return;
+ }
+
+#if STM32_I2C_USE_DMA == FALSE
+ /* Handling of data transfer if the DMA mode is disabled.*/
+ {
+ uint32_t cr1 = dp->CR1;
+
+ if (i2cp->state == I2C_ACTIVE_TX) {
+ /* Transmission phase.*/
+ if (((cr1 &I2C_CR1_TXIE) != 0U) && ((isr & I2C_ISR_TXIS) != 0U)) {
+ dp->TXDR = (uint32_t)*i2cp->txptr;
+ i2cp->txptr++;
+ i2cp->txbytes--;
+ if (i2cp->txbytes == 0U) {
+ dp->CR1 &= ~I2C_CR1_TXIE;
+ }
+ }
+ }
+ else {
+ /* Receive phase.*/
+ if (((cr1 & I2C_CR1_RXIE) != 0U) && ((isr & I2C_ISR_RXNE) != 0U)) {
+ *i2cp->rxptr = (uint8_t)dp->RXDR;
+ i2cp->rxptr++;
+ i2cp->rxbytes--;
+ if (i2cp->rxbytes == 0U) {
+ dp->CR1 &= ~I2C_CR1_RXIE;
+ }
+ }
+ }
+ }
+#endif
+
+ /* Partial transfer handling, restarting the transfer and returning.*/
+ if ((isr & I2C_ISR_TCR) != 0U) {
+ if (i2cp->state == I2C_ACTIVE_TX) {
+ i2c_lld_setup_tx_transfer(i2cp);
+ }
+ else {
+ i2c_lld_setup_rx_transfer(i2cp);
+ }
+ return;
+ }
+
+ /* The following condition is true if a transfer phase has been completed.*/
+ if ((isr & I2C_ISR_TC) != 0U) {
+ if (i2cp->state == I2C_ACTIVE_TX) {
+ /* End of the transmit phase.*/
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* Disabling TX DMA channel.*/
+ dmaStreamDisable(i2cp->dmatx);
+#endif
+
+ /* Starting receive phase if necessary.*/
+ if (i2c_lld_get_rxbytes(i2cp) > 0U) {
+ /* Setting up the peripheral.*/
+ i2c_lld_setup_rx_transfer(i2cp);
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* Enabling RX DMA.*/
+ dmaStreamEnable(i2cp->dmarx);
+#else
+ /* RX interrupt enabled.*/
+ dp->CR1 |= I2C_CR1_RXIE;
+#endif
+
+ /* Starts the read operation.*/
+ dp->CR2 |= I2C_CR2_START;
+
+ /* State change.*/
+ i2cp->state = I2C_ACTIVE_RX;
+
+ /* Note, returning because the transaction is not over yet.*/
+ return;
+ }
+ }
+ else {
+ /* End of the receive phase.*/
+#if STM32_I2C_USE_DMA == TRUE
+ /* Disabling RX DMA channel.*/
+ dmaStreamDisable(i2cp->dmarx);
+#endif
+ }
+
+ /* Transaction finished sending the STOP.*/
+ dp->CR2 |= I2C_CR2_STOP;
+
+ /* Make sure no more 'Transfer Complete' interrupts.*/
+ dp->CR1 &= ~I2C_CR1_TCIE;
+
+ /* Normal transaction end.*/
+ _i2c_wakeup_isr(i2cp);
+ }
+}
+
+/**
+ * @brief I2C error handler.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] isr content of the ISR register to be decoded
+ *
+ * @notapi
+ */
+static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t isr) {
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* Clears DMA interrupt flags just to be safe.*/
+ dmaStreamDisable(i2cp->dmatx);
+ dmaStreamDisable(i2cp->dmarx);
+#else
+ /* Disabling RX and TX interrupts.*/
+ i2cp->i2c->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE);
+#endif
+
+ if (isr & I2C_ISR_BERR)
+ i2cp->errors |= I2C_BUS_ERROR;
+
+ if (isr & I2C_ISR_ARLO)
+ i2cp->errors |= I2C_ARBITRATION_LOST;
+
+ if (isr & I2C_ISR_OVR)
+ i2cp->errors |= I2C_OVERRUN;
+
+ if (isr & I2C_ISR_TIMEOUT)
+ i2cp->errors |= I2C_TIMEOUT;
+
+ /* If some error has been identified then sends wakes the waiting thread.*/
+ if (i2cp->errors != I2C_NO_ERROR)
+ _i2c_wakeup_error_isr(i2cp);
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__)
+#if defined(STM32_I2C1_GLOBAL_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief I2C1 event interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(STM32_I2C1_GLOBAL_HANDLER) {
+ uint32_t isr = I2CD1.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD1.i2c->ICR = isr;
+
+ if (isr & I2C_ERROR_MASK)
+ i2c_lld_serve_error_interrupt(&I2CD1, isr);
+ else if (isr & I2C_INT_MASK)
+ i2c_lld_serve_interrupt(&I2CD1, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#elif defined(STM32_I2C1_EVENT_HANDLER) && defined(STM32_I2C1_ERROR_HANDLER)
+OSAL_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) {
+ uint32_t isr = I2CD1.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD1.i2c->ICR = isr & I2C_INT_MASK;
+
+ i2c_lld_serve_interrupt(&I2CD1, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+OSAL_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) {
+ uint32_t isr = I2CD1.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD1.i2c->ICR = isr & I2C_ERROR_MASK;
+
+ i2c_lld_serve_error_interrupt(&I2CD1, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#else
+#error "I2C1 interrupt handlers not defined"
+#endif
+#endif /* STM32_I2C_USE_I2C1 */
+
+#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__)
+#if defined(STM32_I2C2_GLOBAL_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief I2C2 event interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(STM32_I2C2_GLOBAL_HANDLER) {
+ uint32_t isr = I2CD2.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD2.i2c->ICR = isr;
+
+ if (isr & I2C_ERROR_MASK)
+ i2c_lld_serve_error_interrupt(&I2CD2, isr);
+ else if (isr & I2C_INT_MASK)
+ i2c_lld_serve_interrupt(&I2CD2, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#elif defined(STM32_I2C2_EVENT_HANDLER) && defined(STM32_I2C2_ERROR_HANDLER)
+OSAL_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) {
+ uint32_t isr = I2CD2.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD2.i2c->ICR = isr & I2C_INT_MASK;
+
+ i2c_lld_serve_interrupt(&I2CD2, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+OSAL_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) {
+ uint32_t isr = I2CD2.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD2.i2c->ICR = isr & I2C_ERROR_MASK;
+
+ i2c_lld_serve_error_interrupt(&I2CD2, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#else
+#error "I2C2 interrupt handlers not defined"
+#endif
+#endif /* STM32_I2C_USE_I2C2 */
+
+#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__)
+#if defined(STM32_I2C3_GLOBAL_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief I2C3 event interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(STM32_I2C3_GLOBAL_HANDLER) {
+ uint32_t isr = I2CD3.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD3.i2c->ICR = isr;
+
+ if (isr & I2C_ERROR_MASK)
+ i2c_lld_serve_error_interrupt(&I2CD3, isr);
+ else if (isr & I2C_INT_MASK)
+ i2c_lld_serve_interrupt(&I2CD3, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#elif defined(STM32_I2C3_EVENT_HANDLER) && defined(STM32_I2C3_ERROR_HANDLER)
+OSAL_IRQ_HANDLER(STM32_I2C3_EVENT_HANDLER) {
+ uint32_t isr = I2CD3.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD3.i2c->ICR = isr & I2C_INT_MASK;
+
+ i2c_lld_serve_interrupt(&I2CD3, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+OSAL_IRQ_HANDLER(STM32_I2C3_ERROR_HANDLER) {
+ uint32_t isr = I2CD3.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD3.i2c->ICR = isr & I2C_ERROR_MASK;
+
+ i2c_lld_serve_error_interrupt(&I2CD3, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#else
+#error "I2C3 interrupt handlers not defined"
+#endif
+#endif /* STM32_I2C_USE_I2C3 */
+
+#if STM32_I2C_USE_I2C4 || defined(__DOXYGEN__)
+#if defined(STM32_I2C4_GLOBAL_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief I2C4 event interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(STM32_I2C4_GLOBAL_HANDLER) {
+ uint32_t isr = I2CD4.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD4.i2c->ICR = isr;
+
+ if (isr & I2C_ERROR_MASK)
+ i2c_lld_serve_error_interrupt(&I2CD4, isr);
+ else if (isr & I2C_INT_MASK)
+ i2c_lld_serve_interrupt(&I2CD4, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#elif defined(STM32_I2C4_EVENT_HANDLER) && defined(STM32_I2C4_ERROR_HANDLER)
+OSAL_IRQ_HANDLER(STM32_I2C4_EVENT_HANDLER) {
+ uint32_t isr = I2CD4.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD4.i2c->ICR = isr & I2C_INT_MASK;
+
+ i2c_lld_serve_interrupt(&I2CD4, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+OSAL_IRQ_HANDLER(STM32_I2C4_ERROR_HANDLER) {
+ uint32_t isr = I2CD4.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD4.i2c->ICR = isr & I2C_ERROR_MASK;
+
+ i2c_lld_serve_error_interrupt(&I2CD4, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#else
+#error "I2C4 interrupt handlers not defined"
+#endif
+#endif /* STM32_I2C_USE_I2C4 */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level I2C driver initialization.
+ *
+ * @notapi
+ */
+void i2c_lld_init(void) {
+
+#if STM32_I2C_USE_I2C1
+ i2cObjectInit(&I2CD1);
+ I2CD1.thread = NULL;
+ I2CD1.i2c = I2C1;
+#if STM32_I2C_USE_DMA == TRUE
+ I2CD1.dmarx = NULL;
+ I2CD1.dmatx = NULL;
+#endif
+#endif /* STM32_I2C_USE_I2C1 */
+
+#if STM32_I2C_USE_I2C2
+ i2cObjectInit(&I2CD2);
+ I2CD2.thread = NULL;
+ I2CD2.i2c = I2C2;
+#if STM32_I2C_USE_DMA == TRUE
+ I2CD2.dmarx = NULL;
+ I2CD2.dmatx = NULL;
+#endif
+#endif /* STM32_I2C_USE_I2C2 */
+
+#if STM32_I2C_USE_I2C3
+ i2cObjectInit(&I2CD3);
+ I2CD3.thread = NULL;
+ I2CD3.i2c = I2C3;
+#if STM32_I2C_USE_DMA == TRUE
+ I2CD3.dmarx = NULL;
+ I2CD3.dmatx = NULL;
+#endif
+#endif /* STM32_I2C_USE_I2C3 */
+
+#if STM32_I2C_USE_I2C4
+ i2cObjectInit(&I2CD4);
+ I2CD4.thread = NULL;
+ I2CD4.i2c = I2C4;
+#if STM32_I2C_USE_DMA == TRUE
+ I2CD4.dmarx = NULL;
+ I2CD4.dmatx = NULL;
+#endif
+#endif /* STM32_I2C_USE_I2C4 */
+}
+
+/**
+ * @brief Configures and activates the I2C peripheral.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+void i2c_lld_start(I2CDriver *i2cp) {
+ I2C_TypeDef *dp = i2cp->i2c;
+
+ /* Make sure I2C peripheral is disabled */
+ dp->CR1 &= ~I2C_CR1_PE;
+
+ /* If in stopped state then enables the I2C and DMA clocks.*/
+ if (i2cp->state == I2C_STOP) {
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* Common DMA modes.*/
+ i2cp->txdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_M2P;
+ i2cp->rxdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_P2M;
+#endif
+
+#if STM32_I2C_USE_I2C1
+ if (&I2CD1 == i2cp) {
+
+ rccResetI2C1();
+ rccEnableI2C1(true);
+#if STM32_I2C_USE_DMA == TRUE
+ {
+ i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C1_RX_DMA_STREAM,
+ STM32_I2C_I2C1_IRQ_PRIORITY,
+ NULL,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream");
+ i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C1_TX_DMA_STREAM,
+ STM32_I2C_I2C1_IRQ_PRIORITY,
+ NULL,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream");
+
+ i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY);
+ i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(i2cp->dmarx, STM32_DMAMUX1_I2C1_RX);
+ dmaSetRequestSource(i2cp->dmatx, STM32_DMAMUX1_I2C1_TX);
+#endif
+ }
+#endif /* STM32_I2C_USE_DMA == TRUE */
+
+#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicEnableVector(STM32_I2C1_GLOBAL_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY);
+#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER)
+ nvicEnableVector(STM32_I2C1_EVENT_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY);
+ nvicEnableVector(STM32_I2C1_ERROR_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY);
+#else
+#error "I2C1 interrupt numbers not defined"
+#endif
+ }
+#endif /* STM32_I2C_USE_I2C1 */
+
+#if STM32_I2C_USE_I2C2
+ if (&I2CD2 == i2cp) {
+
+ rccResetI2C2();
+ rccEnableI2C2(true);
+#if STM32_I2C_USE_DMA == TRUE
+ {
+ i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C2_RX_DMA_STREAM,
+ STM32_I2C_I2C2_IRQ_PRIORITY,
+ NULL,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream");
+ i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C2_TX_DMA_STREAM,
+ STM32_I2C_I2C2_IRQ_PRIORITY,
+ NULL,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream");
+
+ i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY);
+ i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(i2cp->dmarx, STM32_DMAMUX1_I2C2_RX);
+ dmaSetRequestSource(i2cp->dmatx, STM32_DMAMUX1_I2C2_TX);
+#endif
+ }
+#endif /* STM32_I2C_USE_DMA == TRUE */
+
+#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicEnableVector(STM32_I2C2_GLOBAL_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY);
+#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER)
+ nvicEnableVector(STM32_I2C2_EVENT_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY);
+ nvicEnableVector(STM32_I2C2_ERROR_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY);
+#else
+#error "I2C2 interrupt numbers not defined"
+#endif
+ }
+#endif /* STM32_I2C_USE_I2C2 */
+
+#if STM32_I2C_USE_I2C3
+ if (&I2CD3 == i2cp) {
+
+ rccResetI2C3();
+ rccEnableI2C3(true);
+#if STM32_I2C_USE_DMA == TRUE
+ {
+ i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C3_RX_DMA_STREAM,
+ STM32_I2C_I2C3_IRQ_PRIORITY,
+ NULL,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream");
+ i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C3_TX_DMA_STREAM,
+ STM32_I2C_I2C3_IRQ_PRIORITY,
+ NULL,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream");
+
+ i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY);
+ i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(i2cp->dmarx, STM32_DMAMUX1_I2C3_RX);
+ dmaSetRequestSource(i2cp->dmatx, STM32_DMAMUX1_I2C3_TX);
+#endif
+ }
+#endif /* STM32_I2C_USE_DMA == TRUE */
+
+#if defined(STM32_I2C3_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicEnableVector(STM32_I2C3_GLOBAL_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY);
+#elif defined(STM32_I2C3_EVENT_NUMBER) && defined(STM32_I2C3_ERROR_NUMBER)
+ nvicEnableVector(STM32_I2C3_EVENT_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY);
+ nvicEnableVector(STM32_I2C3_ERROR_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY);
+#else
+#error "I2C3 interrupt numbers not defined"
+#endif
+ }
+#endif /* STM32_I2C_USE_I2C3 */
+
+#if STM32_I2C_USE_I2C4
+ if (&I2CD4 == i2cp) {
+
+ rccResetI2C4();
+ rccEnableI2C4(true);
+#if STM32_I2C_USE_DMA == TRUE
+ {
+ i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C4_RX_DMA_STREAM,
+ STM32_I2C_I2C4_IRQ_PRIORITY,
+ NULL,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmarx != NULL, "unable to allocate stream");
+ i2cp->dmatx = dmaStreamAllocI(STM32_I2C_I2C4_TX_DMA_STREAM,
+ STM32_I2C_I2C4_IRQ_PRIORITY,
+ NULL,
+ (void *)i2cp);
+ osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream");
+
+ i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C4_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY);
+ i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C4_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(i2cp->dmarx, STM32_DMAMUX1_I2C4_RX);
+ dmaSetRequestSource(i2cp->dmatx, STM32_DMAMUX1_I2C4_TX);
+#endif
+ }
+#endif /* STM32_I2C_USE_DMA == TRUE */
+
+#if defined(STM32_I2C4_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicEnableVector(STM32_I2C4_GLOBAL_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY);
+#elif defined(STM32_I2C4_EVENT_NUMBER) && defined(STM32_I2C4_ERROR_NUMBER)
+ nvicEnableVector(STM32_I2C4_EVENT_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY);
+ nvicEnableVector(STM32_I2C4_ERROR_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY);
+#else
+#error "I2C4 interrupt numbers not defined"
+#endif
+ }
+#endif /* STM32_I2C_USE_I2C4 */
+ }
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* I2C registers pointed by the DMA.*/
+ dmaStreamSetPeripheral(i2cp->dmarx, &dp->RXDR);
+ dmaStreamSetPeripheral(i2cp->dmatx, &dp->TXDR);
+#endif
+
+ /* Reset i2c peripheral, the TCIE bit will be handled separately.*/
+ dp->CR1 = i2cp->config->cr1 |
+#if STM32_I2C_USE_DMA == TRUE
+ I2C_CR1_TXDMAEN | I2C_CR1_RXDMAEN | /* Enable only if using DMA */
+#endif
+ I2C_CR1_ERRIE | I2C_CR1_NACKIE;
+
+ /* Setup I2C parameters.*/
+ dp->TIMINGR = i2cp->config->timingr;
+
+ /* Ready to go.*/
+ dp->CR1 |= I2C_CR1_PE;
+}
+
+/**
+ * @brief Deactivates the I2C peripheral.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+void i2c_lld_stop(I2CDriver *i2cp) {
+
+ /* If not in stopped state then disables the I2C clock.*/
+ if (i2cp->state != I2C_STOP) {
+
+ /* I2C disable.*/
+ i2c_lld_abort_operation(i2cp);
+#if STM32_I2C_USE_DMA == TRUE
+ dmaStreamFreeI(i2cp->dmatx);
+ dmaStreamFreeI(i2cp->dmarx);
+ i2cp->dmatx = NULL;
+ i2cp->dmarx = NULL;
+#endif
+
+#if STM32_I2C_USE_I2C1
+ if (&I2CD1 == i2cp) {
+#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicDisableVector(STM32_I2C1_GLOBAL_NUMBER);
+#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER)
+ nvicDisableVector(STM32_I2C1_EVENT_NUMBER);
+ nvicDisableVector(STM32_I2C1_ERROR_NUMBER);
+#else
+#error "I2C1 interrupt numbers not defined"
+#endif
+
+ rccDisableI2C1();
+ }
+#endif
+
+#if STM32_I2C_USE_I2C2
+ if (&I2CD2 == i2cp) {
+#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicDisableVector(STM32_I2C2_GLOBAL_NUMBER);
+#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER)
+ nvicDisableVector(STM32_I2C2_EVENT_NUMBER);
+ nvicDisableVector(STM32_I2C2_ERROR_NUMBER);
+#else
+#error "I2C2 interrupt numbers not defined"
+#endif
+
+ rccDisableI2C2();
+ }
+#endif
+
+#if STM32_I2C_USE_I2C3
+ if (&I2CD3 == i2cp) {
+#if defined(STM32_I2C3_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicDisableVector(STM32_I2C3_GLOBAL_NUMBER);
+#elif defined(STM32_I2C3_EVENT_NUMBER) && defined(STM32_I2C3_ERROR_NUMBER)
+ nvicDisableVector(STM32_I2C3_EVENT_NUMBER);
+ nvicDisableVector(STM32_I2C3_ERROR_NUMBER);
+#else
+#error "I2C3 interrupt numbers not defined"
+#endif
+
+ rccDisableI2C3();
+ }
+#endif
+
+#if STM32_I2C_USE_I2C4
+ if (&I2CD4 == i2cp) {
+#if defined(STM32_I2C4_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicDisableVector(STM32_I2C4_GLOBAL_NUMBER);
+#elif defined(STM32_I2C4_EVENT_NUMBER) && defined(STM32_I2C4_ERROR_NUMBER)
+ nvicDisableVector(STM32_I2C4_EVENT_NUMBER);
+ nvicDisableVector(STM32_I2C4_ERROR_NUMBER);
+#else
+#error "I2C4 interrupt numbers not defined"
+#endif
+
+ rccDisableI2C4();
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Receives data via the I2C bus as master.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] addr slave device address
+ * @param[out] rxbuf pointer to the receive buffer
+ * @param[in] rxbytes number of bytes to be received
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a
+ * timeout the driver must be stopped and restarted
+ * because the bus is in an uncertain state.
+ *
+ * @notapi
+ */
+msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout) {
+ msg_t msg;
+ I2C_TypeDef *dp = i2cp->i2c;
+ systime_t start, end;
+
+ /* Resetting error flags for this transfer.*/
+ i2cp->errors = I2C_NO_ERROR;
+
+ /* Releases the lock from high level driver.*/
+ osalSysUnlock();
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* RX DMA setup.*/
+ dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
+ dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
+ dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
+#else
+ i2cp->rxptr = rxbuf;
+ i2cp->rxbytes = rxbytes;
+#endif
+
+ /* Calculating the time window for the timeout on the busy bus condition.*/
+ start = osalOsGetSystemTimeX();
+ end = osalTimeAddX(start, OSAL_MS2I(STM32_I2C_BUSY_TIMEOUT));
+
+ /* Waits until BUSY flag is reset or, alternatively, for a timeout
+ condition.*/
+ while (true) {
+ osalSysLock();
+
+ /* If the bus is not busy then the operation can continue, note, the
+ loop is exited in the locked state.*/
+ if ((dp->ISR & I2C_ISR_BUSY) == 0)
+ break;
+
+ /* If the system time went outside the allowed window then a timeout
+ condition is returned.*/
+ if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) {
+ return MSG_TIMEOUT;
+ }
+
+ osalSysUnlock();
+ }
+
+ /* Setting up the slave address.*/
+ i2c_lld_set_address(i2cp, addr);
+
+ /* Setting up the peripheral.*/
+ i2c_lld_setup_rx_transfer(i2cp);
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* Enabling RX DMA.*/
+ dmaStreamEnable(i2cp->dmarx);
+
+ /* Transfer complete interrupt enabled.*/
+ dp->CR1 |= I2C_CR1_TCIE;
+#else
+
+ /* Transfer complete and RX interrupts enabled.*/
+ dp->CR1 |= I2C_CR1_TCIE | I2C_CR1_RXIE;
+#endif
+
+ /* Starts the operation.*/
+ dp->CR2 |= I2C_CR2_START;
+
+ /* Waits for the operation completion or a timeout.*/
+ msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout);
+
+ /* In case of a software timeout a STOP is sent as an extreme attempt
+ to release the bus and DMA is forcibly disabled.*/
+ if (msg == MSG_TIMEOUT) {
+ dp->CR2 |= I2C_CR2_STOP;
+#if STM32_I2C_USE_DMA == TRUE
+ dmaStreamDisable(i2cp->dmarx);
+#endif
+ }
+
+ return msg;
+}
+
+/**
+ * @brief Transmits data via the I2C bus as master.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] addr slave device address
+ * @param[in] txbuf pointer to the transmit buffer
+ * @param[in] txbytes number of bytes to be transmitted
+ * @param[out] rxbuf pointer to the receive buffer
+ * @param[in] rxbytes number of bytes to be received
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a
+ * timeout the driver must be stopped and restarted
+ * because the bus is in an uncertain state.
+ *
+ * @notapi
+ */
+msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ const uint8_t *txbuf, size_t txbytes,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout) {
+ msg_t msg;
+ I2C_TypeDef *dp = i2cp->i2c;
+ systime_t start, end;
+
+ /* Resetting error flags for this transfer.*/
+ i2cp->errors = I2C_NO_ERROR;
+
+ /* Releases the lock from high level driver.*/
+ osalSysUnlock();
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* TX DMA setup.*/
+ dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
+ dmaStreamSetMemory0(i2cp->dmatx, txbuf);
+ dmaStreamSetTransactionSize(i2cp->dmatx, txbytes);
+
+ /* RX DMA setup, note, rxbytes can be zero but we write the value anyway.*/
+ dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
+ dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
+ dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
+#else
+ i2cp->txptr = txbuf;
+ i2cp->txbytes = txbytes;
+ i2cp->rxptr = rxbuf;
+ i2cp->rxbytes = rxbytes;
+#endif
+
+ /* Calculating the time window for the timeout on the busy bus condition.*/
+ start = osalOsGetSystemTimeX();
+ end = osalTimeAddX(start, OSAL_MS2I(STM32_I2C_BUSY_TIMEOUT));
+
+ /* Waits until BUSY flag is reset or, alternatively, for a timeout
+ condition.*/
+ while (true) {
+ osalSysLock();
+
+ /* If the bus is not busy then the operation can continue, note, the
+ loop is exited in the locked state.*/
+ if ((dp->ISR & I2C_ISR_BUSY) == 0)
+ break;
+
+ /* If the system time went outside the allowed window then a timeout
+ condition is returned.*/
+ if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) {
+ return MSG_TIMEOUT;
+ }
+
+ osalSysUnlock();
+ }
+
+ /* Setting up the slave address.*/
+ i2c_lld_set_address(i2cp, addr);
+
+ /* Preparing the transfer.*/
+ i2c_lld_setup_tx_transfer(i2cp);
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* Enabling TX DMA.*/
+ dmaStreamEnable(i2cp->dmatx);
+
+ /* Transfer complete interrupt enabled.*/
+ dp->CR1 |= I2C_CR1_TCIE;
+#else
+ /* Transfer complete and TX interrupts enabled.*/
+ dp->CR1 |= I2C_CR1_TCIE | I2C_CR1_TXIE;
+#endif
+
+ /* Starts the operation.*/
+ dp->CR2 |= I2C_CR2_START;
+
+ /* Waits for the operation completion or a timeout.*/
+ msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout);
+
+ /* In case of a software timeout a STOP is sent as an extreme attempt
+ to release the bus and DMA is forcibly disabled.*/
+ if (msg == MSG_TIMEOUT) {
+ dp->CR2 |= I2C_CR2_STOP;
+#if STM32_I2C_USE_DMA == TRUE
+ dmaStreamDisable(i2cp->dmarx);
+ dmaStreamDisable(i2cp->dmatx);
+#endif
+ }
+
+ return msg;
+}
+
+#endif /* HAL_USE_I2C */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.h
new file mode 100644
index 0000000..b1004e7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.h
@@ -0,0 +1,509 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file I2Cv2/hal_i2c_lld.h
+ * @brief STM32 I2C subsystem low level driver header.
+ *
+ * @addtogroup I2C
+ * @{
+ */
+
+#ifndef HAL_I2C_LLD_H
+#define HAL_I2C_LLD_H
+
+#if HAL_USE_I2C || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name TIMINGR register definitions
+ * @{
+ */
+#define STM32_TIMINGR_PRESC_MASK (15U << 28)
+#define STM32_TIMINGR_PRESC(n) ((n) << 28)
+#define STM32_TIMINGR_SCLDEL_MASK (15U << 20)
+#define STM32_TIMINGR_SCLDEL(n) ((n) << 20)
+#define STM32_TIMINGR_SDADEL_MASK (15U << 16)
+#define STM32_TIMINGR_SDADEL(n) ((n) << 16)
+#define STM32_TIMINGR_SCLH_MASK (255U << 8)
+#define STM32_TIMINGR_SCLH(n) ((n) << 8)
+#define STM32_TIMINGR_SCLL_MASK (255U << 0)
+#define STM32_TIMINGR_SCLL(n) ((n) << 0)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief I2C1 driver enable switch.
+ * @details If set to @p TRUE the support for I2C1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__)
+#define STM32_I2C_USE_I2C1 FALSE
+#endif
+
+/**
+ * @brief I2C2 driver enable switch.
+ * @details If set to @p TRUE the support for I2C2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__)
+#define STM32_I2C_USE_I2C2 FALSE
+#endif
+
+/**
+ * @brief I2C3 driver enable switch.
+ * @details If set to @p TRUE the support for I2C3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_I2C_USE_I2C3) || defined(__DOXYGEN__)
+#define STM32_I2C_USE_I2C3 FALSE
+#endif
+
+/**
+ * @brief I2C4 driver enable switch.
+ * @details If set to @p TRUE the support for I2C4 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_I2C_USE_I2C4) || defined(__DOXYGEN__)
+#define STM32_I2C_USE_I2C4 FALSE
+#endif
+
+/**
+ * @brief I2C timeout on busy condition in milliseconds.
+ */
+#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__)
+#define STM32_I2C_BUSY_TIMEOUT 50
+#endif
+
+/**
+ * @brief I2C1 interrupt priority level setting.
+ */
+#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C1_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief I2C2 interrupt priority level setting.
+ */
+#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C2_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief I2C3 interrupt priority level setting.
+ */
+#if !defined(STM32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C3_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief I2C4 interrupt priority level setting.
+ */
+#if !defined(STM32_I2C_I2C4_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C4_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief DMA use switch.
+ */
+#if !defined(STM32_I2C_USE_DMA) || defined(__DOXYGEN__)
+#define STM32_I2C_USE_DMA TRUE
+#endif
+
+/**
+ * @brief I2C1 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C1_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2C2 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C2_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2C3 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_I2C_I2C3_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C3_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2C4 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_I2C_I2C4_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C4_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2C DMA error hook.
+ * @note The default action for DMA errors is a system halt because DMA
+ * error can only happen because programming errors.
+ */
+#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/** @brief error checks */
+#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1
+#error "I2C1 not present in the selected device"
+#endif
+
+#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2
+#error "I2C2 not present in the selected device"
+#endif
+
+#if STM32_I2C_USE_I2C3 && !STM32_HAS_I2C3
+#error "I2C3 not present in the selected device"
+#endif
+
+#if STM32_I2C_USE_I2C4 && !STM32_HAS_I2C4
+#error "I2C4 not present in the selected device"
+#endif
+
+#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 && !STM32_I2C_USE_I2C3 && \
+ !STM32_I2C_USE_I2C4
+#error "I2C driver activated but no I2C peripheral assigned"
+#endif
+
+#if STM32_I2C_USE_I2C1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to I2C1"
+#endif
+
+#if STM32_I2C_USE_I2C2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to I2C2"
+#endif
+
+#if STM32_I2C_USE_I2C3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to I2C3"
+#endif
+
+#if STM32_I2C_USE_I2C4 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C4_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to I2C4"
+#endif
+
+#if STM32_I2C_USE_DMA == TRUE
+#if STM32_I2C_USE_I2C1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to I2C1"
+#endif
+
+#if STM32_I2C_USE_I2C2 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to I2C2"
+#endif
+
+#if STM32_I2C_USE_I2C3 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C3_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to I2C3"
+#endif
+
+#if STM32_I2C_USE_I2C4 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C4_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to I2C4"
+#endif
+
+/* The following checks are only required when there is a DMA able to
+ reassign streams to different channels.*/
+#if STM32_ADVANCED_DMA
+
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if STM32_I2C_USE_I2C1 && (!defined(STM32_I2C_I2C1_RX_DMA_STREAM) || \
+ !defined(STM32_I2C_I2C1_TX_DMA_STREAM))
+#error "I2C1 DMA streams not defined"
+#endif
+
+#if STM32_I2C_USE_I2C2 && (!defined(STM32_I2C_I2C2_RX_DMA_STREAM) || \
+ !defined(STM32_I2C_I2C2_TX_DMA_STREAM))
+#error "I2C2 DMA streams not defined"
+#endif
+
+#if STM32_I2C_USE_I2C3 && (!defined(STM32_I2C_I2C3_RX_DMA_STREAM) || \
+ !defined(STM32_I2C_I2C3_TX_DMA_STREAM))
+#error "I2C3 DMA streams not defined"
+#endif
+
+#if STM32_I2C_USE_I2C4 && (!defined(STM32_I2C_I2C4_RX_DMA_STREAM) || \
+ !defined(STM32_I2C_I2C4_TX_DMA_STREAM))
+#error "I2C4 DMA streams not defined"
+#endif
+
+/* Devices without DMAMUX require an additional check.*/
+#if !STM32_DMA_SUPPORTS_DMAMUX
+
+/* Check on the validity of the assigned DMA channels.*/
+#if STM32_I2C_USE_I2C1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_RX_DMA_STREAM, \
+ STM32_I2C1_RX_DMA_MSK)
+#error "invalid DMA stream associated to I2C1 RX"
+#endif
+
+#if STM32_I2C_USE_I2C1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_TX_DMA_STREAM, \
+ STM32_I2C1_TX_DMA_MSK)
+#error "invalid DMA stream associated to I2C1 TX"
+#endif
+
+#if STM32_I2C_USE_I2C2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_RX_DMA_STREAM, \
+ STM32_I2C2_RX_DMA_MSK)
+#error "invalid DMA stream associated to I2C2 RX"
+#endif
+
+#if STM32_I2C_USE_I2C2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_TX_DMA_STREAM, \
+ STM32_I2C2_TX_DMA_MSK)
+#error "invalid DMA stream associated to I2C2 TX"
+#endif
+
+#if STM32_I2C_USE_I2C3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_RX_DMA_STREAM, \
+ STM32_I2C3_RX_DMA_MSK)
+#error "invalid DMA stream associated to I2C3 RX"
+#endif
+
+#if STM32_I2C_USE_I2C3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_TX_DMA_STREAM, \
+ STM32_I2C3_TX_DMA_MSK)
+#error "invalid DMA stream associated to I2C3 TX"
+#endif
+
+#if STM32_I2C_USE_I2C4 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C4_RX_DMA_STREAM, \
+ STM32_I2C4_RX_DMA_MSK)
+#error "invalid DMA stream associated to I2C4 RX"
+#endif
+
+#if STM32_I2C_USE_I2C4 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C4_TX_DMA_STREAM, \
+ STM32_I2C4_TX_DMA_MSK)
+#error "invalid DMA stream associated to I2C4 TX"
+#endif
+
+#endif /* !STM32_DMA_SUPPORTS_DMAMUX */
+
+#endif /* STM32_ADVANCED_DMA */
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+#endif /* STM32_I2C_USE_DMA == TRUE */
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type representing an I2C address.
+ */
+typedef uint16_t i2caddr_t;
+
+/**
+ * @brief Type of I2C driver condition flags.
+ */
+typedef uint32_t i2cflags_t;
+
+/**
+ * @brief Type of I2C driver configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief TIMINGR register initialization.
+ * @note Refer to the STM32 reference manual, the values are affected
+ * by the system clock settings in mcuconf.h.
+ */
+ uint32_t timingr;
+ /**
+ * @brief CR1 register initialization.
+ * @note Leave to zero unless you know what you are doing.
+ */
+ uint32_t cr1;
+ /**
+ * @brief CR2 register initialization.
+ * @note Only the ADD10 bit can eventually be specified here.
+ */
+ uint32_t cr2;
+} I2CConfig;
+
+/**
+ * @brief Type of a structure representing an I2C driver.
+ */
+typedef struct I2CDriver I2CDriver;
+
+/**
+ * @brief Structure representing an I2C driver.
+ */
+struct I2CDriver {
+ /**
+ * @brief Driver state.
+ */
+ i2cstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const I2CConfig *config;
+ /**
+ * @brief Error flags.
+ */
+ i2cflags_t errors;
+#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
+ mutex_t mutex;
+#endif /* I2C_USE_MUTUAL_EXCLUSION */
+#if defined(I2C_DRIVER_EXT_FIELDS)
+ I2C_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Thread waiting for I/O completion.
+ */
+ thread_reference_t thread;
+#if (STM32_I2C_USE_DMA == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief RX DMA mode bit mask.
+ */
+ uint32_t rxdmamode;
+ /**
+ * @brief TX DMA mode bit mask.
+ */
+ uint32_t txdmamode;
+ /**
+ * @brief Receive DMA channel.
+ */
+ const stm32_dma_stream_t *dmarx;
+ /**
+ * @brief Transmit DMA channel.
+ */
+ const stm32_dma_stream_t *dmatx;
+#else /* STM32_I2C_USE_DMA == FALSE */
+ /**
+ * @brief Pointer to the next TX buffer location.
+ */
+ const uint8_t *txptr;
+ /**
+ * @brief Number of bytes in TX phase.
+ */
+ size_t txbytes;
+ /**
+ * @brief Pointer to the next RX buffer location.
+ */
+ uint8_t *rxptr;
+ /**
+ * @brief Number of bytes in RX phase.
+ */
+ size_t rxbytes;
+#endif /* STM32_I2C_USE_DMA == FALSE */
+ /**
+ * @brief Pointer to the I2Cx registers block.
+ */
+ I2C_TypeDef *i2c;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Get errors from I2C driver.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+#define i2c_lld_get_errors(i2cp) ((i2cp)->errors)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+#if STM32_I2C_USE_I2C1
+extern I2CDriver I2CD1;
+#endif
+
+#if STM32_I2C_USE_I2C2
+extern I2CDriver I2CD2;
+#endif
+
+#if STM32_I2C_USE_I2C3
+extern I2CDriver I2CD3;
+#endif
+
+#if STM32_I2C_USE_I2C4
+extern I2CDriver I2CD4;
+#endif
+
+#endif /* !defined(__DOXYGEN__) */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void i2c_lld_init(void);
+ void i2c_lld_start(I2CDriver *i2cp);
+ void i2c_lld_stop(I2CDriver *i2cp);
+ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ const uint8_t *txbuf, size_t txbytes,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout);
+ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_I2C */
+
+#endif /* HAL_I2C_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv3/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv3/driver.mk
new file mode 100644
index 0000000..ef55dfd
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv3/driver.mk
@@ -0,0 +1,21 @@
+ifeq ($(USE_HAL_I2C_FALLBACK),yes)
+ # Fallback SW driver.
+ ifeq ($(USE_SMART_BUILD),yes)
+ ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),)
+ PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c
+ endif
+ else
+ PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c
+ endif
+ PLATFORMINC += $(CHIBIOS)/os/hal/lib/fallback/I2C
+else
+ # Default HW driver.
+ ifeq ($(USE_SMART_BUILD),yes)
+ ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),)
+ PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.c
+ endif
+ else
+ PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.c
+ endif
+ PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv3
+endif
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.c
new file mode 100644
index 0000000..24b1ace
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.c
@@ -0,0 +1,1316 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file I2Cv3/hal_i2c_lld.c
+ * @brief STM32 I2C subsystem low level driver source.
+ *
+ * @addtogroup I2C
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_I2C || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#if STM32_I2C_USE_DMA == TRUE
+
+#if defined(STM32_I2C_DMA_REQUIRED)
+#define DMAMODE_COMMON \
+ (STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | \
+ STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | \
+ STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE)
+#endif
+
+#if defined(STM32_I2C_BDMA_REQUIRED)
+#define BDMAMODE_COMMON \
+ (STM32_BDMA_CR_PSIZE_BYTE | STM32_BDMA_CR_MSIZE_BYTE | \
+ STM32_BDMA_CR_MINC | \
+ STM32_BDMA_CR_TEIE | STM32_BDMA_CR_TCIE)
+#endif
+
+#endif /* STM32_I2C_USE_DMA == TRUE */
+
+#if 0
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ if (i2cp->is_bdma)
+#endif
+#if defined(STM32_I2C_BDMA_REQUIRED)
+ {
+ }
+#endif
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ else
+#endif
+#if defined(STM32_I2C_DMA_REQUIRED)
+ {
+ }
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+#define I2C_ERROR_MASK \
+ ((uint32_t)(I2C_ISR_BERR | I2C_ISR_ARLO | I2C_ISR_OVR | I2C_ISR_PECERR | \
+ I2C_ISR_TIMEOUT | I2C_ISR_ALERT))
+
+#define I2C_INT_MASK \
+ ((uint32_t)(I2C_ISR_TCR | I2C_ISR_TC | I2C_ISR_STOPF | I2C_ISR_NACKF | \
+ I2C_ISR_ADDR | I2C_ISR_RXNE | I2C_ISR_TXIS))
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief I2C1 driver identifier.*/
+#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__)
+I2CDriver I2CD1;
+#endif
+
+/** @brief I2C2 driver identifier.*/
+#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__)
+I2CDriver I2CD2;
+#endif
+
+/** @brief I2C3 driver identifier.*/
+#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__)
+I2CDriver I2CD3;
+#endif
+
+/** @brief I2C4 driver identifier.*/
+#if STM32_I2C_USE_I2C4 || defined(__DOXYGEN__)
+I2CDriver I2CD4;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#if STM32_I2C_USE_DMA == TRUE
+static inline void i2c_lld_start_rx_dma(I2CDriver *i2cp) {
+
+#if STM32_I2C4_USE_BDMA == TRUE
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ if (i2cp->is_bdma)
+#endif
+#if defined(STM32_I2C_BDMA_REQUIRED)
+ {
+ bdmaStreamEnable(i2cp->rx.bdma);
+ }
+#endif
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ else
+#endif
+#endif /* STM32_I2C4_USE_BDMA == TRUE */
+#if defined(STM32_I2C_DMA_REQUIRED)
+ {
+ dmaStreamEnable(i2cp->rx.dma);
+ }
+#endif
+}
+
+static inline void i2c_lld_start_tx_dma(I2CDriver *i2cp) {
+
+#if STM32_I2C4_USE_BDMA == TRUE
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ if (i2cp->is_bdma)
+#endif
+#if defined(STM32_I2C_BDMA_REQUIRED)
+ {
+ bdmaStreamEnable(i2cp->tx.bdma);
+ }
+#endif
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ else
+#endif
+#endif /* STM32_I2C4_USE_BDMA == TRUE */
+#if defined(STM32_I2C_DMA_REQUIRED)
+ {
+ dmaStreamEnable(i2cp->tx.dma);
+ }
+#endif
+}
+
+static inline void i2c_lld_stop_rx_dma(I2CDriver *i2cp) {
+
+#if STM32_I2C4_USE_BDMA == TRUE
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ if (i2cp->is_bdma)
+#endif
+#if defined(STM32_I2C_BDMA_REQUIRED)
+ {
+ bdmaStreamDisable(i2cp->rx.bdma);
+ }
+#endif
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ else
+#endif
+#endif /* STM32_I2C4_USE_BDMA == TRUE */
+#if defined(STM32_I2C_DMA_REQUIRED)
+ {
+ dmaStreamDisable(i2cp->rx.dma);
+ }
+#endif
+}
+
+static inline void i2c_lld_stop_tx_dma(I2CDriver *i2cp) {
+
+#if STM32_I2C4_USE_BDMA == TRUE
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ if (i2cp->is_bdma)
+#endif
+#if defined(STM32_I2C_BDMA_REQUIRED)
+ {
+ bdmaStreamDisable(i2cp->tx.bdma);
+ }
+#endif
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ else
+#endif
+#endif /* STM32_I2C4_USE_BDMA == TRUE */
+#if defined(STM32_I2C_DMA_REQUIRED)
+ {
+ dmaStreamDisable(i2cp->tx.dma);
+ }
+#endif
+}
+#endif /* STM32_I2C_USE_DMA == TRUE */
+
+/**
+ * @brief Slave address setup.
+ * @note The RW bit is set to zero internally.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] addr slave device address
+ *
+ * @notapi
+ */
+static void i2c_lld_set_address(I2CDriver *i2cp, i2caddr_t addr) {
+ I2C_TypeDef *dp = i2cp->i2c;
+
+ /* Address alignment depends on the addressing mode selected.*/
+ if ((i2cp->config->cr2 & I2C_CR2_ADD10) == 0U)
+ dp->CR2 = (uint32_t)addr << 1U;
+ else
+ dp->CR2 = (uint32_t)addr;
+}
+
+/**
+ * @brief I2C RX transfer setup.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_setup_rx_transfer(I2CDriver *i2cp) {
+ I2C_TypeDef *dp = i2cp->i2c;
+ uint32_t reload;
+ size_t n;
+
+ /* The unit can transfer 255 bytes maximum in a single operation.*/
+ n = i2cp->rxbytes;
+ if (n > 255U) {
+ n = 255U;
+ reload = I2C_CR2_RELOAD;
+ }
+ else {
+ reload = 0U;
+ }
+ i2cp->rxbytes -= n;
+
+ /* Configures the CR2 registers with both the calculated and static
+ settings.*/
+ dp->CR2 = (dp->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | i2cp->config->cr2 |
+ I2C_CR2_RD_WRN | (n << 16U) | reload;
+}
+
+/**
+ * @brief I2C TX transfer setup.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_setup_tx_transfer(I2CDriver *i2cp) {
+ I2C_TypeDef *dp = i2cp->i2c;
+ uint32_t reload;
+ size_t n;
+
+ /* The unit can transfer 255 bytes maximum in a single operation.*/
+ n = i2cp->txbytes;
+ if (n > 255U) {
+ n = 255U;
+ reload = I2C_CR2_RELOAD;
+ }
+ else {
+ reload = 0U;
+ }
+ i2cp->txbytes -= n;
+
+ /* Configures the CR2 registers with both the calculated and static
+ settings.*/
+ dp->CR2 = (dp->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | i2cp->config->cr2 |
+ (n << 16U) | reload;
+}
+
+/**
+ * @brief Aborts an I2C transaction.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+static void i2c_lld_abort_operation(I2CDriver *i2cp) {
+ I2C_TypeDef *dp = i2cp->i2c;
+
+ if (dp->CR1 & I2C_CR1_PE) {
+ /* Stops the I2C peripheral.*/
+ dp->CR1 &= ~I2C_CR1_PE;
+ while (dp->CR1 & I2C_CR1_PE)
+ dp->CR1 &= ~I2C_CR1_PE;
+ dp->CR1 |= I2C_CR1_PE;
+ }
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* Stops the associated DMA streams.*/
+ i2c_lld_stop_rx_dma(i2cp);
+ i2c_lld_stop_tx_dma(i2cp);
+#else
+ dp->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE);
+#endif
+}
+
+/**
+ * @brief I2C shared ISR code.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] isr content of the ISR register to be decoded
+ *
+ * @notapi
+ */
+static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t isr) {
+ I2C_TypeDef *dp = i2cp->i2c;
+
+ /* Special case of a received NACK, the transfer is aborted.*/
+ if ((isr & I2C_ISR_NACKF) != 0U) {
+#if STM32_I2C_USE_DMA == TRUE
+ /* Stops the associated DMA streams.*/
+ i2c_lld_stop_rx_dma(i2cp);
+ i2c_lld_stop_tx_dma(i2cp);
+#endif
+
+ /* Error flag.*/
+ i2cp->errors |= I2C_ACK_FAILURE;
+
+ /* Transaction finished sending the STOP.*/
+ dp->CR2 |= I2C_CR2_STOP;
+
+ /* Make sure no more interrupts.*/
+ dp->CR1 &= ~(I2C_CR1_TCIE | I2C_CR1_TXIE | I2C_CR1_RXIE);
+
+ /* Errors are signaled to the upper layer.*/
+ _i2c_wakeup_error_isr(i2cp);
+
+ return;
+ }
+
+#if STM32_I2C_USE_DMA == FALSE
+ /* Handling of data transfer if the DMA mode is disabled.*/
+ {
+ uint32_t cr1 = dp->CR1;
+
+ if (i2cp->state == I2C_ACTIVE_TX) {
+ /* Transmission phase.*/
+ if (((cr1 &I2C_CR1_TXIE) != 0U) && ((isr & I2C_ISR_TXIS) != 0U)) {
+ dp->TXDR = (uint32_t)*i2cp->txptr;
+ i2cp->txptr++;
+ i2cp->txbytes--;
+ if (i2cp->txbytes == 0U) {
+ dp->CR1 &= ~I2C_CR1_TXIE;
+ }
+ }
+ }
+ else {
+ /* Receive phase.*/
+ if (((cr1 & I2C_CR1_RXIE) != 0U) && ((isr & I2C_ISR_RXNE) != 0U)) {
+ *i2cp->rxptr = (uint8_t)dp->RXDR;
+ i2cp->rxptr++;
+ i2cp->rxbytes--;
+ if (i2cp->rxbytes == 0U) {
+ dp->CR1 &= ~I2C_CR1_RXIE;
+ }
+ }
+ }
+ }
+#endif
+
+ /* Partial transfer handling, restarting the transfer and returning.*/
+ if ((isr & I2C_ISR_TCR) != 0U) {
+ if (i2cp->state == I2C_ACTIVE_TX) {
+ i2c_lld_setup_tx_transfer(i2cp);
+ }
+ else {
+ i2c_lld_setup_rx_transfer(i2cp);
+ }
+ return;
+ }
+
+ /* The following condition is true if a transfer phase has been completed.*/
+ if ((isr & I2C_ISR_TC) != 0U) {
+ if (i2cp->state == I2C_ACTIVE_TX) {
+ /* End of the transmit phase.*/
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* Disabling TX DMA channel.*/
+ i2c_lld_stop_tx_dma(i2cp);
+#endif
+
+ /* Starting receive phase if necessary.*/
+ if (i2cp->rxbytes > 0U) {
+ /* Setting up the peripheral.*/
+ i2c_lld_setup_rx_transfer(i2cp);
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* Enabling RX DMA.*/
+ i2c_lld_start_rx_dma(i2cp);
+#else
+ /* RX interrupt enabled.*/
+ dp->CR1 |= I2C_CR1_RXIE;
+#endif
+
+ /* Starts the read operation.*/
+ dp->CR2 |= I2C_CR2_START;
+
+ /* State change.*/
+ i2cp->state = I2C_ACTIVE_RX;
+
+ /* Note, returning because the transaction is not over yet.*/
+ return;
+ }
+ }
+ else {
+ /* End of the receive phase.*/
+#if STM32_I2C_USE_DMA == TRUE
+ /* Disabling RX DMA channel.*/
+ i2c_lld_stop_rx_dma(i2cp);
+#endif
+ }
+
+ /* Transaction finished sending the STOP.*/
+ dp->CR2 |= I2C_CR2_STOP;
+
+ /* Make sure no more 'Transfer Complete' interrupts.*/
+ dp->CR1 &= ~I2C_CR1_TCIE;
+
+ /* Normal transaction end.*/
+ _i2c_wakeup_isr(i2cp);
+ }
+}
+
+/**
+ * @brief I2C error handler.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] isr content of the ISR register to be decoded
+ *
+ * @notapi
+ */
+static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t isr) {
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* Clears DMA interrupt flags just to be safe.*/
+ i2c_lld_stop_rx_dma(i2cp);
+ i2c_lld_stop_tx_dma(i2cp);
+#else
+ /* Disabling RX and TX interrupts.*/
+ i2cp->i2c->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE);
+#endif
+
+ if (isr & I2C_ISR_BERR)
+ i2cp->errors |= I2C_BUS_ERROR;
+
+ if (isr & I2C_ISR_ARLO)
+ i2cp->errors |= I2C_ARBITRATION_LOST;
+
+ if (isr & I2C_ISR_OVR)
+ i2cp->errors |= I2C_OVERRUN;
+
+ if (isr & I2C_ISR_TIMEOUT)
+ i2cp->errors |= I2C_TIMEOUT;
+
+ /* If some error has been identified then wake the waiting thread.*/
+ if (i2cp->errors != I2C_NO_ERROR)
+ _i2c_wakeup_error_isr(i2cp);
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__)
+#if defined(STM32_I2C1_GLOBAL_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief I2C1 event interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(STM32_I2C1_GLOBAL_HANDLER) {
+ uint32_t isr = I2CD1.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD1.i2c->ICR = isr;
+
+ if (isr & I2C_ERROR_MASK)
+ i2c_lld_serve_error_interrupt(&I2CD1, isr);
+ else if (isr & I2C_INT_MASK)
+ i2c_lld_serve_interrupt(&I2CD1, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#elif defined(STM32_I2C1_EVENT_HANDLER) && defined(STM32_I2C1_ERROR_HANDLER)
+OSAL_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) {
+ uint32_t isr = I2CD1.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD1.i2c->ICR = isr & I2C_INT_MASK;
+
+ i2c_lld_serve_interrupt(&I2CD1, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+OSAL_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) {
+ uint32_t isr = I2CD1.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD1.i2c->ICR = isr & I2C_ERROR_MASK;
+
+ i2c_lld_serve_error_interrupt(&I2CD1, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#else
+#error "I2C1 interrupt handlers not defined"
+#endif
+#endif /* STM32_I2C_USE_I2C1 */
+
+#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__)
+#if defined(STM32_I2C2_GLOBAL_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief I2C2 event interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(STM32_I2C2_GLOBAL_HANDLER) {
+ uint32_t isr = I2CD2.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD2.i2c->ICR = isr;
+
+ if (isr & I2C_ERROR_MASK)
+ i2c_lld_serve_error_interrupt(&I2CD2, isr);
+ else if (isr & I2C_INT_MASK)
+ i2c_lld_serve_interrupt(&I2CD2, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#elif defined(STM32_I2C2_EVENT_HANDLER) && defined(STM32_I2C2_ERROR_HANDLER)
+OSAL_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) {
+ uint32_t isr = I2CD2.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD2.i2c->ICR = isr & I2C_INT_MASK;
+
+ i2c_lld_serve_interrupt(&I2CD2, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+OSAL_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) {
+ uint32_t isr = I2CD2.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD2.i2c->ICR = isr & I2C_ERROR_MASK;
+
+ i2c_lld_serve_error_interrupt(&I2CD2, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#else
+#error "I2C2 interrupt handlers not defined"
+#endif
+#endif /* STM32_I2C_USE_I2C2 */
+
+#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__)
+#if defined(STM32_I2C3_GLOBAL_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief I2C3 event interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(STM32_I2C3_GLOBAL_HANDLER) {
+ uint32_t isr = I2CD3.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD3.i2c->ICR = isr;
+
+ if (isr & I2C_ERROR_MASK)
+ i2c_lld_serve_error_interrupt(&I2CD3, isr);
+ else if (isr & I2C_INT_MASK)
+ i2c_lld_serve_interrupt(&I2CD3, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#elif defined(STM32_I2C3_EVENT_HANDLER) && defined(STM32_I2C3_ERROR_HANDLER)
+OSAL_IRQ_HANDLER(STM32_I2C3_EVENT_HANDLER) {
+ uint32_t isr = I2CD3.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD3.i2c->ICR = isr & I2C_INT_MASK;
+
+ i2c_lld_serve_interrupt(&I2CD3, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+OSAL_IRQ_HANDLER(STM32_I2C3_ERROR_HANDLER) {
+ uint32_t isr = I2CD3.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD3.i2c->ICR = isr & I2C_ERROR_MASK;
+
+ i2c_lld_serve_error_interrupt(&I2CD3, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#else
+#error "I2C3 interrupt handlers not defined"
+#endif
+#endif /* STM32_I2C_USE_I2C3 */
+
+#if STM32_I2C_USE_I2C4 || defined(__DOXYGEN__)
+#if defined(STM32_I2C4_GLOBAL_HANDLER) || defined(__DOXYGEN__)
+/**
+ * @brief I2C4 event interrupt handler.
+ *
+ * @notapi
+ */
+OSAL_IRQ_HANDLER(STM32_I2C4_GLOBAL_HANDLER) {
+ uint32_t isr = I2CD4.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD4.i2c->ICR = isr;
+
+ if (isr & I2C_ERROR_MASK)
+ i2c_lld_serve_error_interrupt(&I2CD4, isr);
+ else if (isr & I2C_INT_MASK)
+ i2c_lld_serve_interrupt(&I2CD4, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#elif defined(STM32_I2C4_EVENT_HANDLER) && defined(STM32_I2C4_ERROR_HANDLER)
+OSAL_IRQ_HANDLER(STM32_I2C4_EVENT_HANDLER) {
+ uint32_t isr = I2CD4.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD4.i2c->ICR = isr & I2C_INT_MASK;
+
+ i2c_lld_serve_interrupt(&I2CD4, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+OSAL_IRQ_HANDLER(STM32_I2C4_ERROR_HANDLER) {
+ uint32_t isr = I2CD4.i2c->ISR;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Clearing IRQ bits.*/
+ I2CD4.i2c->ICR = isr & I2C_ERROR_MASK;
+
+ i2c_lld_serve_error_interrupt(&I2CD4, isr);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#else
+#error "I2C4 interrupt handlers not defined"
+#endif
+#endif /* STM32_I2C_USE_I2C4 */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level I2C driver initialization.
+ *
+ * @notapi
+ */
+void i2c_lld_init(void) {
+
+#if STM32_I2C_USE_I2C1
+ i2cObjectInit(&I2CD1);
+ I2CD1.thread = NULL;
+ I2CD1.i2c = I2C1;
+#if STM32_I2C_USE_DMA == TRUE
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ I2CD1.is_bdma = false;
+#endif
+ I2CD1.rx.dma = NULL;
+ I2CD1.tx.dma = NULL;
+#endif
+#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicEnableVector(STM32_I2C1_GLOBAL_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY);
+#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER)
+ nvicEnableVector(STM32_I2C1_EVENT_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY);
+ nvicEnableVector(STM32_I2C1_ERROR_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY);
+#else
+#error "I2C1 interrupt numbers not defined"
+#endif
+#endif /* STM32_I2C_USE_I2C1 */
+
+#if STM32_I2C_USE_I2C2
+ i2cObjectInit(&I2CD2);
+ I2CD2.thread = NULL;
+ I2CD2.i2c = I2C2;
+#if STM32_I2C_USE_DMA == TRUE
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ I2CD2.is_bdma = false;
+#endif
+ I2CD2.rx.dma = NULL;
+ I2CD2.tx.dma = NULL;
+#endif
+#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicEnableVector(STM32_I2C2_GLOBAL_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY);
+#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER)
+ nvicEnableVector(STM32_I2C2_EVENT_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY);
+ nvicEnableVector(STM32_I2C2_ERROR_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY);
+#else
+#error "I2C2 interrupt numbers not defined"
+#endif
+#endif /* STM32_I2C_USE_I2C2 */
+
+#if STM32_I2C_USE_I2C3
+ i2cObjectInit(&I2CD3);
+ I2CD3.thread = NULL;
+ I2CD3.i2c = I2C3;
+#if STM32_I2C_USE_DMA == TRUE
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ I2CD3.is_bdma = false;
+#endif
+ I2CD3.rx.dma = NULL;
+ I2CD3.tx.dma = NULL;
+#endif
+#if defined(STM32_I2C3_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicEnableVector(STM32_I2C3_GLOBAL_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY);
+#elif defined(STM32_I2C3_EVENT_NUMBER) && defined(STM32_I2C3_ERROR_NUMBER)
+ nvicEnableVector(STM32_I2C3_EVENT_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY);
+ nvicEnableVector(STM32_I2C3_ERROR_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY);
+#else
+#error "I2C3 interrupt numbers not defined"
+#endif
+#endif /* STM32_I2C_USE_I2C3 */
+
+#if STM32_I2C_USE_I2C4
+ i2cObjectInit(&I2CD4);
+ I2CD4.thread = NULL;
+ I2CD4.i2c = I2C4;
+#if STM32_I2C_USE_DMA == TRUE
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+#if STM32_I2C4_USE_BDMA == TRUE
+ I2CD4.is_bdma = true;
+ I2CD4.rx.bdma = NULL;
+ I2CD4.tx.bdma = NULL;
+#else
+ I2CD4.is_bdma = false;
+ I2CD4.rx.dma = NULL;
+ I2CD4.tx.dma = NULL;
+#endif /* STM32_I2C4_USE_BDMA == TRUE */
+#endif /* defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED) */
+#endif /* STM32_I2C_USE_DMA == TRUE */
+#if defined(STM32_I2C4_GLOBAL_NUMBER) || defined(__DOXYGEN__)
+ nvicEnableVector(STM32_I2C4_GLOBAL_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY);
+#elif defined(STM32_I2C4_EVENT_NUMBER) && defined(STM32_I2C4_ERROR_NUMBER)
+ nvicEnableVector(STM32_I2C4_EVENT_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY);
+ nvicEnableVector(STM32_I2C4_ERROR_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY);
+#else
+#error "I2C4 interrupt numbers not defined"
+#endif
+#endif /* STM32_I2C_USE_I2C4 */
+}
+
+/**
+ * @brief Configures and activates the I2C peripheral.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+void i2c_lld_start(I2CDriver *i2cp) {
+ I2C_TypeDef *dp = i2cp->i2c;
+
+ /* Make sure I2C peripheral is disabled */
+ dp->CR1 &= ~I2C_CR1_PE;
+
+ /* If in stopped state then enables the I2C and DMA clocks.*/
+ if (i2cp->state == I2C_STOP) {
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* Common DMA modes.*/
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ if (i2cp->is_bdma)
+#endif
+#if defined(STM32_I2C_BDMA_REQUIRED)
+ {
+ i2cp->txdmamode = BDMAMODE_COMMON | STM32_BDMA_CR_DIR_M2P;
+ i2cp->rxdmamode = BDMAMODE_COMMON | STM32_BDMA_CR_DIR_P2M;
+ }
+#endif
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ else
+#endif
+#if defined(STM32_I2C_DMA_REQUIRED)
+ {
+ i2cp->txdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_M2P;
+ i2cp->rxdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_P2M;
+ }
+#endif
+#endif /* STM32_I2C_USE_DMA == TRUE */
+
+#if STM32_I2C_USE_I2C1
+ if (&I2CD1 == i2cp) {
+
+ rccResetI2C1();
+ rccEnableI2C1(true);
+#if STM32_I2C_USE_DMA == TRUE
+ {
+ i2cp->rx.dma = dmaStreamAllocI(STM32_I2C_I2C1_RX_DMA_STREAM,
+ STM32_I2C_I2C1_IRQ_PRIORITY,
+ NULL,
+ NULL);
+ osalDbgAssert(i2cp->rx.dma != NULL, "unable to allocate stream");
+ i2cp->tx.dma = dmaStreamAllocI(STM32_I2C_I2C1_TX_DMA_STREAM,
+ STM32_I2C_I2C1_IRQ_PRIORITY,
+ NULL,
+ NULL);
+ osalDbgAssert(i2cp->tx.dma != NULL, "unable to allocate stream");
+
+ i2cp->rxdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY);
+ i2cp->txdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY);
+ dmaSetRequestSource(i2cp->rx.dma, STM32_DMAMUX1_I2C1_RX);
+ dmaSetRequestSource(i2cp->tx.dma, STM32_DMAMUX1_I2C1_TX);
+ }
+#endif /* STM32_I2C_USE_DMA == TRUE */
+ }
+#endif /* STM32_I2C_USE_I2C1 */
+
+#if STM32_I2C_USE_I2C2
+ if (&I2CD2 == i2cp) {
+
+ rccResetI2C2();
+ rccEnableI2C2(true);
+#if STM32_I2C_USE_DMA == TRUE
+ {
+ i2cp->rx.dma = dmaStreamAllocI(STM32_I2C_I2C2_RX_DMA_STREAM,
+ STM32_I2C_I2C2_IRQ_PRIORITY,
+ NULL,
+ NULL);
+ osalDbgAssert(i2cp->rx.dma != NULL, "unable to allocate stream");
+ i2cp->tx.dma = dmaStreamAllocI(STM32_I2C_I2C2_TX_DMA_STREAM,
+ STM32_I2C_I2C2_IRQ_PRIORITY,
+ NULL,
+ NULL);
+ osalDbgAssert(i2cp->tx.dma != NULL, "unable to allocate stream");
+
+ i2cp->rxdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY);
+ i2cp->txdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY);
+ dmaSetRequestSource(i2cp->rx.dma, STM32_DMAMUX1_I2C2_RX);
+ dmaSetRequestSource(i2cp->tx.dma, STM32_DMAMUX1_I2C2_TX);
+ }
+#endif /* STM32_I2C_USE_DMA == TRUE */
+ }
+#endif /* STM32_I2C_USE_I2C2 */
+
+#if STM32_I2C_USE_I2C3
+ if (&I2CD3 == i2cp) {
+
+ rccResetI2C3();
+ rccEnableI2C3(true);
+#if STM32_I2C_USE_DMA == TRUE
+ {
+ i2cp->rx.dma = dmaStreamAllocI(STM32_I2C_I2C3_RX_DMA_STREAM,
+ STM32_I2C_I2C3_IRQ_PRIORITY,
+ NULL,
+ NULL);
+ osalDbgAssert(i2cp->rx.dma != NULL, "unable to allocate stream");
+ i2cp->tx.dma = dmaStreamAllocI(STM32_I2C_I2C3_TX_DMA_STREAM,
+ STM32_I2C_I2C3_IRQ_PRIORITY,
+ NULL,
+ NULL);
+ osalDbgAssert(i2cp->tx.dma != NULL, "unable to allocate stream");
+
+ i2cp->rxdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY);
+ i2cp->txdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY);
+ dmaSetRequestSource(i2cp->rx.dma, STM32_DMAMUX1_I2C3_RX);
+ dmaSetRequestSource(i2cp->tx.dma, STM32_DMAMUX1_I2C3_TX);
+ }
+#endif /* STM32_I2C_USE_DMA == TRUE */
+ }
+#endif /* STM32_I2C_USE_I2C3 */
+
+#if STM32_I2C_USE_I2C4
+ if (&I2CD4 == i2cp) {
+
+ rccResetI2C4();
+ rccEnableI2C4(true);
+#if STM32_I2C_USE_DMA == TRUE
+ {
+#if STM32_I2C4_USE_BDMA == TRUE
+ i2cp->rx.bdma = bdmaStreamAllocI(STM32_I2C_I2C4_RX_BDMA_STREAM,
+ STM32_I2C_I2C4_IRQ_PRIORITY,
+ NULL,
+ NULL);
+ osalDbgAssert(i2cp->rx.bdma != NULL, "unable to allocate stream");
+ i2cp->tx.bdma = bdmaStreamAllocI(STM32_I2C_I2C4_TX_BDMA_STREAM,
+ STM32_I2C_I2C4_IRQ_PRIORITY,
+ NULL,
+ NULL);
+ osalDbgAssert(i2cp->tx.bdma != NULL, "unable to allocate stream");
+
+ i2cp->rxdmamode |= STM32_BDMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY);
+ i2cp->txdmamode |= STM32_BDMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY);
+ bdmaSetRequestSource(i2cp->rx.bdma, STM32_DMAMUX2_I2C4_RX);
+ bdmaSetRequestSource(i2cp->tx.bdma, STM32_DMAMUX2_I2C4_TX);
+#else /* STM32_I2C4_USE_BDMA != TRUE */
+ i2cp->rx.dma = dmaStreamAllocI(STM32_I2C_I2C4_RX_DMA_STREAM,
+ STM32_I2C_I2C4_IRQ_PRIORITY,
+ NULL,
+ NULL);
+ osalDbgAssert(i2cp->rx.dma != NULL, "unable to allocate stream");
+ i2cp->tx.dma = dmaStreamAllocI(STM32_I2C_I2C4_TX_DMA_STREAM,
+ STM32_I2C_I2C4_IRQ_PRIORITY,
+ NULL,
+ NULL);
+ osalDbgAssert(i2cp->tx.dma != NULL, "unable to allocate stream");
+
+ i2cp->rxdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY);
+ i2cp->txdmamode |= STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY);
+ dmaSetRequestSource(i2cp->rx.dma, STM32_DMAMUX1_I2C4_RX);
+ dmaSetRequestSource(i2cp->tx.dma, STM32_DMAMUX1_I2C4_TX);
+#endif /* STM32_I2C4_USE_BDMA != TRUE */
+ }
+#endif /* STM32_I2C_USE_DMA == TRUE */
+ }
+#endif /* STM32_I2C_USE_I2C4 */
+ }
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* I2C registers pointed by the DMA.*/
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ if (i2cp->is_bdma)
+#endif
+#if defined(STM32_I2C_BDMA_REQUIRED)
+ {
+ bdmaStreamSetPeripheral(i2cp->rx.bdma, &dp->RXDR);
+ bdmaStreamSetPeripheral(i2cp->tx.bdma, &dp->TXDR);
+ }
+#endif
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ else
+#endif
+#if defined(STM32_I2C_DMA_REQUIRED)
+ {
+ dmaStreamSetPeripheral(i2cp->rx.dma, &dp->RXDR);
+ dmaStreamSetPeripheral(i2cp->tx.dma, &dp->TXDR);
+ }
+#endif
+#endif /* STM32_I2C_USE_DMA == TRUE */
+
+ /* Reset i2c peripheral, the TCIE bit will be handled separately.*/
+ dp->CR1 = i2cp->config->cr1 |
+#if STM32_I2C_USE_DMA == TRUE
+ I2C_CR1_TXDMAEN | I2C_CR1_RXDMAEN | /* Enable only if using DMA */
+#endif
+ I2C_CR1_ERRIE | I2C_CR1_NACKIE;
+
+ /* Setup I2C parameters.*/
+ dp->TIMINGR = i2cp->config->timingr;
+
+ /* Ready to go.*/
+ dp->CR1 |= I2C_CR1_PE;
+}
+
+/**
+ * @brief Deactivates the I2C peripheral.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+void i2c_lld_stop(I2CDriver *i2cp) {
+
+ /* If not in stopped state then disables the I2C clock.*/
+ if (i2cp->state != I2C_STOP) {
+
+ /* I2C disable.*/
+ i2c_lld_abort_operation(i2cp);
+
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ if (i2cp->is_bdma)
+#endif
+#if defined(STM32_I2C_BDMA_REQUIRED)
+ {
+ bdmaStreamFreeI(i2cp->rx.bdma);
+ bdmaStreamFreeI(i2cp->tx.bdma);
+ }
+#endif
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ else
+#endif
+#if defined(STM32_I2C_DMA_REQUIRED)
+ {
+ dmaStreamFreeI(i2cp->rx.dma);
+ dmaStreamFreeI(i2cp->tx.dma);
+ }
+#endif
+
+#if STM32_I2C_USE_I2C1
+ if (&I2CD1 == i2cp) {
+ rccDisableI2C1();
+ }
+#endif
+
+#if STM32_I2C_USE_I2C2
+ if (&I2CD2 == i2cp) {
+ rccDisableI2C2();
+ }
+#endif
+
+#if STM32_I2C_USE_I2C3
+ if (&I2CD3 == i2cp) {
+ rccDisableI2C3();
+ }
+#endif
+
+#if STM32_I2C_USE_I2C4
+ if (&I2CD4 == i2cp) {
+ rccDisableI2C4();
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Receives data via the I2C bus as master.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] addr slave device address
+ * @param[out] rxbuf pointer to the receive buffer
+ * @param[in] rxbytes number of bytes to be received
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a
+ * timeout the driver must be stopped and restarted
+ * because the bus is in an uncertain state.
+ *
+ * @notapi
+ */
+msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout) {
+ msg_t msg;
+ I2C_TypeDef *dp = i2cp->i2c;
+ systime_t start, end;
+
+ /* Resetting error flags for this transfer.*/
+ i2cp->errors = I2C_NO_ERROR;
+
+ /* Releases the lock from high level driver.*/
+ osalSysUnlock();
+
+ /* Sizes of transfer phases.*/
+ i2cp->txbytes = 0U;
+ i2cp->rxbytes = rxbytes;
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* RX DMA setup.*/
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ if (i2cp->is_bdma)
+#endif
+#if defined(STM32_I2C_BDMA_REQUIRED)
+ {
+ bdmaStreamSetMode(i2cp->rx.bdma, i2cp->rxdmamode);
+ bdmaStreamSetMemory(i2cp->rx.bdma, rxbuf);
+ bdmaStreamSetTransactionSize(i2cp->rx.bdma, rxbytes);
+ }
+#endif
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ else
+#endif
+#if defined(STM32_I2C_DMA_REQUIRED)
+ {
+ dmaStreamSetMode(i2cp->rx.dma, i2cp->rxdmamode);
+ dmaStreamSetMemory0(i2cp->rx.dma, rxbuf);
+ dmaStreamSetTransactionSize(i2cp->rx.dma, rxbytes);
+ }
+#endif
+#else
+ i2cp->rxptr = rxbuf;
+#endif
+
+ /* Calculating the time window for the timeout on the busy bus condition.*/
+ start = osalOsGetSystemTimeX();
+ end = osalTimeAddX(start, OSAL_MS2I(STM32_I2C_BUSY_TIMEOUT));
+
+ /* Waits until BUSY flag is reset or, alternatively, for a timeout
+ condition.*/
+ while (true) {
+ osalSysLock();
+
+ /* If the bus is not busy then the operation can continue, note, the
+ loop is exited in the locked state.*/
+ if ((dp->ISR & I2C_ISR_BUSY) == 0)
+ break;
+
+ /* If the system time went outside the allowed window then a timeout
+ condition is returned.*/
+ if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) {
+ return MSG_TIMEOUT;
+ }
+
+ osalSysUnlock();
+ }
+
+ /* Setting up the slave address.*/
+ i2c_lld_set_address(i2cp, addr);
+
+ /* Setting up the peripheral.*/
+ i2c_lld_setup_rx_transfer(i2cp);
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* Enabling RX DMA.*/
+ i2c_lld_start_rx_dma(i2cp);
+
+ /* Transfer complete interrupt enabled.*/
+ dp->CR1 |= I2C_CR1_TCIE;
+#else
+
+ /* Transfer complete and RX interrupts enabled.*/
+ dp->CR1 |= I2C_CR1_TCIE | I2C_CR1_RXIE;
+#endif
+
+ /* Starts the operation.*/
+ dp->CR2 |= I2C_CR2_START;
+
+ /* Waits for the operation completion or a timeout.*/
+ msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout);
+
+ /* In case of a software timeout a STOP is sent as an extreme attempt
+ to release the bus and DMA is forcibly disabled.*/
+ if (msg == MSG_TIMEOUT) {
+ dp->CR2 |= I2C_CR2_STOP;
+#if STM32_I2C_USE_DMA == TRUE
+ i2c_lld_stop_rx_dma(i2cp);
+#endif
+ }
+
+ return msg;
+}
+
+/**
+ * @brief Transmits data via the I2C bus as master.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] addr slave device address
+ * @param[in] txbuf pointer to the transmit buffer
+ * @param[in] txbytes number of bytes to be transmitted
+ * @param[out] rxbuf pointer to the receive buffer
+ * @param[in] rxbytes number of bytes to be received
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a
+ * timeout the driver must be stopped and restarted
+ * because the bus is in an uncertain state.
+ *
+ * @notapi
+ */
+msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ const uint8_t *txbuf, size_t txbytes,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout) {
+ msg_t msg;
+ I2C_TypeDef *dp = i2cp->i2c;
+ systime_t start, end;
+
+ /* Resetting error flags for this transfer.*/
+ i2cp->errors = I2C_NO_ERROR;
+
+ /* Releases the lock from high level driver.*/
+ osalSysUnlock();
+
+ /* Sizes of transfer phases.*/
+ i2cp->txbytes = txbytes;
+ i2cp->rxbytes = rxbytes;
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* TX and RX DMA setup.*/
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ if (i2cp->is_bdma)
+#endif
+#if defined(STM32_I2C_BDMA_REQUIRED)
+ {
+ bdmaStreamSetMode(i2cp->tx.bdma, i2cp->txdmamode);
+ bdmaStreamSetMemory(i2cp->tx.bdma, txbuf);
+ bdmaStreamSetTransactionSize(i2cp->tx.bdma, txbytes);
+
+ bdmaStreamSetMode(i2cp->rx.bdma, i2cp->rxdmamode);
+ bdmaStreamSetMemory(i2cp->rx.bdma, rxbuf);
+ bdmaStreamSetTransactionSize(i2cp->rx.bdma, rxbytes);
+ }
+#endif
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_I2C_BDMA_REQUIRED)
+ else
+#endif
+#if defined(STM32_I2C_DMA_REQUIRED)
+ {
+ dmaStreamSetMode(i2cp->tx.dma, i2cp->txdmamode);
+ dmaStreamSetMemory0(i2cp->tx.dma, txbuf);
+ dmaStreamSetTransactionSize(i2cp->tx.dma, txbytes);
+
+ dmaStreamSetMode(i2cp->rx.dma, i2cp->rxdmamode);
+ dmaStreamSetMemory0(i2cp->rx.dma, rxbuf);
+ dmaStreamSetTransactionSize(i2cp->rx.dma, rxbytes);
+ }
+#endif
+#else
+ i2cp->txptr = txbuf;
+ i2cp->rxptr = rxbuf;
+#endif
+
+ /* Calculating the time window for the timeout on the busy bus condition.*/
+ start = osalOsGetSystemTimeX();
+ end = osalTimeAddX(start, OSAL_MS2I(STM32_I2C_BUSY_TIMEOUT));
+
+ /* Waits until BUSY flag is reset or, alternatively, for a timeout
+ condition.*/
+ while (true) {
+ osalSysLock();
+
+ /* If the bus is not busy then the operation can continue, note, the
+ loop is exited in the locked state.*/
+ if ((dp->ISR & I2C_ISR_BUSY) == 0)
+ break;
+
+ /* If the system time went outside the allowed window then a timeout
+ condition is returned.*/
+ if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) {
+ return MSG_TIMEOUT;
+ }
+
+ osalSysUnlock();
+ }
+
+ /* Setting up the slave address.*/
+ i2c_lld_set_address(i2cp, addr);
+
+ /* Preparing the transfer.*/
+ i2c_lld_setup_tx_transfer(i2cp);
+
+#if STM32_I2C_USE_DMA == TRUE
+ /* Enabling TX DMA.*/
+ i2c_lld_start_tx_dma(i2cp);
+
+ /* Transfer complete interrupt enabled.*/
+ dp->CR1 |= I2C_CR1_TCIE;
+#else
+ /* Transfer complete and TX interrupts enabled.*/
+ dp->CR1 |= I2C_CR1_TCIE | I2C_CR1_TXIE;
+#endif
+
+ /* Starts the operation.*/
+ dp->CR2 |= I2C_CR2_START;
+
+ /* Waits for the operation completion or a timeout.*/
+ msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout);
+
+ /* In case of a software timeout a STOP is sent as an extreme attempt
+ to release the bus and DMA is forcibly disabled.*/
+ if (msg == MSG_TIMEOUT) {
+ dp->CR2 |= I2C_CR2_STOP;
+#if STM32_I2C_USE_DMA == TRUE
+ i2c_lld_stop_rx_dma(i2cp);
+ i2c_lld_stop_tx_dma(i2cp);
+#endif
+ }
+
+ return msg;
+}
+
+#endif /* HAL_USE_I2C */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.h
new file mode 100644
index 0000000..ee29a4e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/I2Cv3/hal_i2c_lld.h
@@ -0,0 +1,603 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file I2Cv3/hal_i2c_lld.h
+ * @brief STM32 I2C subsystem low level driver header.
+ *
+ * @addtogroup I2C
+ * @{
+ */
+
+#ifndef HAL_I2C_LLD_H
+#define HAL_I2C_LLD_H
+
+#if HAL_USE_I2C || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name TIMINGR register definitions
+ * @{
+ */
+#define STM32_TIMINGR_PRESC_MASK (15U << 28)
+#define STM32_TIMINGR_PRESC(n) ((n) << 28)
+#define STM32_TIMINGR_SCLDEL_MASK (15U << 20)
+#define STM32_TIMINGR_SCLDEL(n) ((n) << 20)
+#define STM32_TIMINGR_SDADEL_MASK (15U << 16)
+#define STM32_TIMINGR_SDADEL(n) ((n) << 16)
+#define STM32_TIMINGR_SCLH_MASK (255U << 8)
+#define STM32_TIMINGR_SCLH(n) ((n) << 8)
+#define STM32_TIMINGR_SCLL_MASK (255U << 0)
+#define STM32_TIMINGR_SCLL(n) ((n) << 0)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief I2C1 driver enable switch.
+ * @details If set to @p TRUE the support for I2C1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__)
+#define STM32_I2C_USE_I2C1 FALSE
+#endif
+
+/**
+ * @brief I2C2 driver enable switch.
+ * @details If set to @p TRUE the support for I2C2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__)
+#define STM32_I2C_USE_I2C2 FALSE
+#endif
+
+/**
+ * @brief I2C3 driver enable switch.
+ * @details If set to @p TRUE the support for I2C3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_I2C_USE_I2C3) || defined(__DOXYGEN__)
+#define STM32_I2C_USE_I2C3 FALSE
+#endif
+
+/**
+ * @brief I2C4 driver enable switch.
+ * @details If set to @p TRUE the support for I2C4 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_I2C_USE_I2C4) || defined(__DOXYGEN__)
+#define STM32_I2C_USE_I2C4 FALSE
+#endif
+
+/**
+ * @brief I2C timeout on busy condition in milliseconds.
+ */
+#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__)
+#define STM32_I2C_BUSY_TIMEOUT 50
+#endif
+
+/**
+ * @brief I2C1 interrupt priority level setting.
+ */
+#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C1_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief I2C2 interrupt priority level setting.
+ */
+#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C2_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief I2C3 interrupt priority level setting.
+ */
+#if !defined(STM32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C3_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief I2C4 interrupt priority level setting.
+ */
+#if !defined(STM32_I2C_I2C4_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C4_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief DMA use switch.
+ */
+#if !defined(STM32_I2C_USE_DMA) || defined(__DOXYGEN__)
+#define STM32_I2C_USE_DMA TRUE
+#endif
+
+/**
+ * @brief I2C1 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C1_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2C2 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C2_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2C3 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_I2C_I2C3_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C3_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2C4 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_I2C_I2C4_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2C_I2C4_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2C DMA error hook.
+ * @note The default action for DMA errors is a system halt because DMA
+ * error can only happen because programming errors.
+ */
+#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks.*/
+#if !defined(STM32_HAS_I2C1)
+#error "STM32_HAS_I2C1 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_I2C2)
+#error "STM32_HAS_I2C2 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_I2C3)
+#error "STM32_HAS_I2C3 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_I2C4)
+#error "STM32_HAS_I2C4 not defined in registry"
+#endif
+
+#if !defined(STM32_I2C4_USE_BDMA)
+#error "STM32_I2C4_USE_BDMA not defined in registry"
+#endif
+
+/** @brief error checks */
+#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1
+#error "I2C1 not present in the selected device"
+#endif
+
+#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2
+#error "I2C2 not present in the selected device"
+#endif
+
+#if STM32_I2C_USE_I2C3 && !STM32_HAS_I2C3
+#error "I2C3 not present in the selected device"
+#endif
+
+#if STM32_I2C_USE_I2C4 && !STM32_HAS_I2C4
+#error "I2C4 not present in the selected device"
+#endif
+
+#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 && !STM32_I2C_USE_I2C3 && \
+ !STM32_I2C_USE_I2C4
+#error "I2C driver activated but no I2C peripheral assigned"
+#endif
+
+#if STM32_I2C_USE_I2C1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to I2C1"
+#endif
+
+#if STM32_I2C_USE_I2C2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to I2C2"
+#endif
+
+#if STM32_I2C_USE_I2C3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to I2C3"
+#endif
+
+#if STM32_I2C_USE_I2C4 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C4_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to I2C4"
+#endif
+
+#if STM32_I2C_USE_DMA == TRUE
+
+#if STM32_I2C_USE_I2C1
+#if !defined(STM32_I2C_I2C1_RX_DMA_STREAM)
+#error "STM32_I2C_I2C1_RX_DMA_STREAM not defined"
+#endif
+
+#if !defined(STM32_I2C_I2C1_TX_DMA_STREAM)
+#error "STM32_I2C_I2C1_TX_DMA_STREAM not defined"
+#endif
+
+#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C1_RX_DMA_STREAM)
+#error "Invalid DMA stream assigned to I2C1 RX"
+#endif
+
+#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C1_TX_DMA_STREAM)
+#error "Invalid DMA stream assigned to I2C1 TX"
+#endif
+
+#if !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to I2C1"
+#endif
+#endif
+
+#if STM32_I2C_USE_I2C2
+#if !defined(STM32_I2C_I2C2_RX_DMA_STREAM)
+#error "STM32_I2C_I2C2_RX_DMA_STREAM not defined"
+#endif
+
+#if !defined(STM32_I2C_I2C2_TX_DMA_STREAM)
+#error "STM32_I2C_I2C2_TX_DMA_STREAM not defined"
+#endif
+
+#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C2_RX_DMA_STREAM)
+#error "Invalid DMA stream assigned to I2C2 RX"
+#endif
+
+#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C2_TX_DMA_STREAM)
+#error "Invalid DMA stream assigned to I2C2 TX"
+#endif
+
+#if !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to I2C2"
+#endif
+#endif
+
+#if STM32_I2C_USE_I2C3
+#if !defined(STM32_I2C_I2C3_RX_DMA_STREAM)
+#error "STM32_I2C_I2C3_RX_DMA_STREAM not defined"
+#endif
+
+#if !defined(STM32_I2C_I2C3_TX_DMA_STREAM)
+#error "STM32_I2C_I2C3_TX_DMA_STREAM not defined"
+#endif
+
+#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C3_RX_DMA_STREAM)
+#error "Invalid DMA stream assigned to I2C3 RX"
+#endif
+
+#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C3_TX_DMA_STREAM)
+#error "Invalid DMA stream assigned to I2C3 TX"
+#endif
+
+#if !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C3_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to I2C3"
+#endif
+#endif
+
+#if STM32_I2C_USE_I2C4
+#if STM32_I2C4_USE_BDMA
+
+#if !defined(STM32_I2C_I2C4_RX_BDMA_STREAM)
+#error "STM32_I2C_I2C4_RX_BDMA_STREAM not defined"
+#endif
+
+#if !defined(STM32_I2C_I2C4_TX_BDMA_STREAM)
+#error "STM32_I2C_I2C4_TX_BDMA_STREAM not defined"
+#endif
+
+#if !STM32_BDMA_IS_VALID_STREAM(STM32_I2C_I2C4_RX_BDMA_STREAM)
+#error "Invalid BDMA stream assigned to I2C4 RX"
+#endif
+
+#if !STM32_BDMA_IS_VALID_STREAM(STM32_I2C_I2C4_TX_BDMA_STREAM)
+#error "Invalid BDMA stream assigned to I2C4 TX"
+#endif
+
+#if !STM32_BDMA_IS_VALID_PRIORITY(STM32_I2C_I2C4_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to I2C4"
+#endif
+
+#else /* !STM32_I2C4_USE_BDMA */
+
+#if !defined(STM32_I2C_I2C4_RX_DMA_STREAM)
+#error "STM32_I2C_I2C4_RX_DMA_STREAM not defined"
+#endif
+
+#if !defined(STM32_I2C_I2C4_TX_DMA_STREAM)
+#error "STM32_I2C_I2C4_TX_DMA_STREAM not defined"
+#endif
+
+#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C4_RX_DMA_STREAM)
+#error "Invalid DMA stream assigned to I2C4 RX"
+#endif
+
+#if !STM32_DMA_IS_VALID_STREAM(STM32_I2C_I2C4_TX_DMA_STREAM)
+#error "Invalid DMA stream assigned to I2C4 TX"
+#endif
+
+#if !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C4_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to I2C4"
+#endif
+
+#endif /* !STM32_I2C4_USE_BDMA */
+#endif /* STM32_I2C_USE_I2C4 */
+
+#if STM32_I2C4_USE_BDMA == TRUE
+
+#if STM32_I2C_USE_I2C1 || STM32_I2C_USE_I2C2 || STM32_I2C_USE_I2C3
+#define STM32_I2C_DMA_REQUIRED
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+#endif
+
+#if STM32_I2C_USE_I2C4
+#define STM32_I2C_BDMA_REQUIRED
+#if !defined(STM32_BDMA_REQUIRED)
+#define STM32_BDMA_REQUIRED
+#endif
+#endif
+#else /* STM32_I2C4_USE_BDMA != TRUE */
+
+#if STM32_I2C_USE_I2C1 || STM32_I2C_USE_I2C2 || STM32_I2C_USE_I2C3 || STM32_I2C_USE_I2C4
+#define STM32_I2C_DMA_REQUIRED
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+#endif
+
+#endif /* STM32_I2C4_USE_BDMA != TRUE */
+
+#endif /* STM32_I2C_USE_DMA == TRUE */
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type representing an I2C address.
+ */
+typedef uint16_t i2caddr_t;
+
+/**
+ * @brief Type of I2C driver condition flags.
+ */
+typedef uint32_t i2cflags_t;
+
+/**
+ * @brief Type of I2C driver configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief TIMINGR register initialization.
+ * @note Refer to the STM32 reference manual, the values are affected
+ * by the system clock settings in mcuconf.h.
+ */
+ uint32_t timingr;
+ /**
+ * @brief CR1 register initialization.
+ * @note Leave to zero unless you know what you are doing.
+ */
+ uint32_t cr1;
+ /**
+ * @brief CR2 register initialization.
+ * @note Only the ADD10 bit can eventually be specified here.
+ */
+ uint32_t cr2;
+} I2CConfig;
+
+/**
+ * @brief Type of a structure representing an I2C driver.
+ */
+typedef struct I2CDriver I2CDriver;
+
+/**
+ * @brief Structure representing an I2C driver.
+ */
+struct I2CDriver {
+ /**
+ * @brief Driver state.
+ */
+ i2cstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const I2CConfig *config;
+ /**
+ * @brief Error flags.
+ */
+ i2cflags_t errors;
+#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
+ mutex_t mutex;
+#endif /* I2C_USE_MUTUAL_EXCLUSION */
+#if defined(I2C_DRIVER_EXT_FIELDS)
+ I2C_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Thread waiting for I/O completion.
+ */
+ thread_reference_t thread;
+ /**
+ * @brief Number of bytes in TX phase.
+ */
+ size_t txbytes;
+ /**
+ * @brief Number of bytes in RX phase.
+ */
+ size_t rxbytes;
+#if (STM32_I2C_USE_DMA == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief RX DMA mode bit mask.
+ */
+ uint32_t rxdmamode;
+ /**
+ * @brief TX DMA mode bit mask.
+ */
+ uint32_t txdmamode;
+#if defined(STM32_I2C_DMA_REQUIRED) && defined(STM32_BDMA_REQUIRED)
+ /**
+ * @brief DMA type for this instance.
+ */
+ bool is_bdma;
+#endif
+ /**
+ * @brief Union of the RX DMA streams.
+ */
+ union {
+#if defined(STM32_I2C_DMA_REQUIRED) || defined(__DOXYGEN__)
+ /**
+ * @brief Receive DMA stream.
+ */
+ const stm32_dma_stream_t *dma;
+#endif
+#if (STM32_I2C4_USE_BDMA == TRUE) || defined(__DOXYGEN__)
+#if defined(STM32_BDMA_REQUIRED) || defined(__DOXYGEN__)
+ /**
+ * @brief Receive BDMA stream.
+ */
+ const stm32_bdma_stream_t *bdma;
+#endif
+#endif
+ } rx;
+ /**
+ * @brief Union of the TX DMA streams.
+ */
+ union {
+#if defined(STM32_I2C_DMA_REQUIRED) || defined(__DOXYGEN__)
+ /**
+ * @brief Transmit DMA stream.
+ */
+ const stm32_dma_stream_t *dma;
+#endif
+#if (STM32_I2C4_USE_BDMA == TRUE) || defined(__DOXYGEN__)
+#if defined(STM32_BDMA_REQUIRED) || defined(__DOXYGEN__)
+ /**
+ * @brief Transmit DMA stream.
+ */
+ const stm32_bdma_stream_t *bdma;
+#endif
+#endif
+ } tx;
+#else /* STM32_I2C_USE_DMA == FALSE */
+ /**
+ * @brief Pointer to the next TX buffer location.
+ */
+ const uint8_t *txptr;
+ /**
+ * @brief Pointer to the next RX buffer location.
+ */
+ uint8_t *rxptr;
+#endif /* STM32_I2C_USE_DMA == FALSE */
+ /**
+ * @brief Pointer to the I2Cx registers block.
+ */
+ I2C_TypeDef *i2c;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Get errors from I2C driver.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+#define i2c_lld_get_errors(i2cp) ((i2cp)->errors)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+#if STM32_I2C_USE_I2C1
+extern I2CDriver I2CD1;
+#endif
+
+#if STM32_I2C_USE_I2C2
+extern I2CDriver I2CD2;
+#endif
+
+#if STM32_I2C_USE_I2C3
+extern I2CDriver I2CD3;
+#endif
+
+#if STM32_I2C_USE_I2C4
+extern I2CDriver I2CD4;
+#endif
+
+#endif /* !defined(__DOXYGEN__) */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void i2c_lld_init(void);
+ void i2c_lld_start(I2CDriver *i2cp);
+ void i2c_lld_stop(I2CDriver *i2cp);
+ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ const uint8_t *txbuf, size_t txbytes,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout);
+ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_I2C */
+
+#endif /* HAL_I2C_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MACv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MACv1/driver.mk
new file mode 100644
index 0000000..2964178
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MACv1/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_MAC TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MACv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.c
new file mode 100644
index 0000000..1a62533
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.c
@@ -0,0 +1,758 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file MACv1/hal_mac_lld.c
+ * @brief STM32 low level MAC driver code.
+ *
+ * @addtogroup MAC
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+
+#if HAL_USE_MAC || defined(__DOXYGEN__)
+
+#include "hal_mii.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define BUFFER_SIZE ((((STM32_MAC_BUFFERS_SIZE - 1) | 3) + 1) / 4)
+
+/* Fixing inconsistencies in ST headers.*/
+#if !defined(ETH_MACMIIAR_CR_Div102) && defined(ETH_MACMIIAR_CR_DIV102)
+#define ETH_MACMIIAR_CR_Div102 ETH_MACMIIAR_CR_DIV102
+#endif
+#if !defined(ETH_MACMIIAR_CR_Div62) && defined(ETH_MACMIIAR_CR_DIV62)
+#define ETH_MACMIIAR_CR_Div62 ETH_MACMIIAR_CR_DIV62
+#endif
+#if !defined(ETH_MACMIIAR_CR_Div42) && defined(ETH_MACMIIAR_CR_DIV42)
+#define ETH_MACMIIAR_CR_Div42 ETH_MACMIIAR_CR_DIV42
+#endif
+#if !defined(ETH_MACMIIAR_CR_Div26) && defined(ETH_MACMIIAR_CR_DIV26)
+#define ETH_MACMIIAR_CR_Div26 ETH_MACMIIAR_CR_DIV26
+#endif
+#if !defined(ETH_MACMIIAR_CR_Div16) && defined(ETH_MACMIIAR_CR_DIV16)
+#define ETH_MACMIIAR_CR_Div16 ETH_MACMIIAR_CR_DIV16
+#endif
+
+/* MII divider optimal value.*/
+#if (STM32_HCLK >= 150000000)
+#define MACMIIDR_CR ETH_MACMIIAR_CR_Div102
+#elif (STM32_HCLK >= 100000000)
+#define MACMIIDR_CR ETH_MACMIIAR_CR_Div62
+#elif (STM32_HCLK >= 60000000)
+#define MACMIIDR_CR ETH_MACMIIAR_CR_Div42
+#elif (STM32_HCLK >= 35000000)
+#define MACMIIDR_CR ETH_MACMIIAR_CR_Div26
+#elif (STM32_HCLK >= 20000000)
+#define MACMIIDR_CR ETH_MACMIIAR_CR_Div16
+#else
+#error "STM32_HCLK below minimum frequency for ETH operations (20MHz)"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief Ethernet driver 1.
+ */
+MACDriver ETHD1;
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+static const uint8_t default_mac_address[] = {0xAA, 0x55, 0x13,
+ 0x37, 0x01, 0x10};
+
+static stm32_eth_rx_descriptor_t __eth_rd[STM32_MAC_RECEIVE_BUFFERS];
+static stm32_eth_tx_descriptor_t __eth_td[STM32_MAC_TRANSMIT_BUFFERS];
+
+static uint32_t __eth_rb[STM32_MAC_RECEIVE_BUFFERS][BUFFER_SIZE];
+static uint32_t __eth_tb[STM32_MAC_TRANSMIT_BUFFERS][BUFFER_SIZE];
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Writes a PHY register.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ * @param[in] reg register number
+ * @param[in] value new register value
+ *
+ * @notapi
+ */
+void mii_write(MACDriver *macp, uint32_t reg, uint32_t value) {
+
+ ETH->MACMIIDR = value;
+ ETH->MACMIIAR = macp->phyaddr | (reg << 6) | MACMIIDR_CR |
+ ETH_MACMIIAR_MW | ETH_MACMIIAR_MB;
+ while ((ETH->MACMIIAR & ETH_MACMIIAR_MB) != 0)
+ ;
+}
+
+/**
+ * @brief Reads a PHY register.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ * @param[in] reg register number
+ *
+ * @return The PHY register content.
+ *
+ * @notapi
+ */
+uint32_t mii_read(MACDriver *macp, uint32_t reg) {
+
+ ETH->MACMIIAR = macp->phyaddr | (reg << 6) | MACMIIDR_CR | ETH_MACMIIAR_MB;
+ while ((ETH->MACMIIAR & ETH_MACMIIAR_MB) != 0)
+ ;
+ return ETH->MACMIIDR;
+}
+
+#if !defined(BOARD_PHY_ADDRESS)
+/**
+ * @brief PHY address detection.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ */
+static void mii_find_phy(MACDriver *macp) {
+ uint32_t i;
+
+#if STM32_MAC_PHY_TIMEOUT > 0
+ unsigned n = STM32_MAC_PHY_TIMEOUT;
+ do {
+#endif
+ for (i = 0U; i <= 31U; i++) {
+ macp->phyaddr = i << 11U;
+ ETH->MACMIIDR = (i << 6U) | MACMIIDR_CR;
+ if ((mii_read(macp, MII_PHYSID1) == (BOARD_PHY_ID >> 16U)) &&
+ ((mii_read(macp, MII_PHYSID2) & 0xFFF0U) == (BOARD_PHY_ID & 0xFFF0U))) {
+ return;
+ }
+ }
+#if STM32_MAC_PHY_TIMEOUT > 0
+ n--;
+ } while (n > 0U);
+#endif
+ /* Wrong or defective board.*/
+ osalSysHalt("MAC failure");
+}
+#endif
+
+/**
+ * @brief MAC address setup.
+ *
+ * @param[in] p pointer to a six bytes buffer containing the MAC
+ * address
+ */
+static void mac_lld_set_address(const uint8_t *p) {
+
+ /* MAC address configuration, only a single address comparator is used,
+ hash table not used.*/
+ ETH->MACA0HR = ((uint32_t)p[5] << 8) |
+ ((uint32_t)p[4] << 0);
+ ETH->MACA0LR = ((uint32_t)p[3] << 24) |
+ ((uint32_t)p[2] << 16) |
+ ((uint32_t)p[1] << 8) |
+ ((uint32_t)p[0] << 0);
+ ETH->MACA1HR = 0x0000FFFF;
+ ETH->MACA1LR = 0xFFFFFFFF;
+ ETH->MACA2HR = 0x0000FFFF;
+ ETH->MACA2LR = 0xFFFFFFFF;
+ ETH->MACA3HR = 0x0000FFFF;
+ ETH->MACA3LR = 0xFFFFFFFF;
+ ETH->MACHTHR = 0;
+ ETH->MACHTLR = 0;
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+OSAL_IRQ_HANDLER(STM32_ETH_HANDLER) {
+ uint32_t dmasr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ dmasr = ETH->DMASR;
+ ETH->DMASR = dmasr; /* Clear status bits.*/
+
+ if (dmasr & ETH_DMASR_RS) {
+ /* Data Received.*/
+ osalSysLockFromISR();
+ osalThreadDequeueAllI(ÐD1.rdqueue, MSG_RESET);
+#if MAC_USE_EVENTS
+ osalEventBroadcastFlagsI(ÐD1.rdevent, 0);
+#endif
+ osalSysUnlockFromISR();
+ }
+
+ if (dmasr & ETH_DMASR_TS) {
+ /* Data Transmitted.*/
+ osalSysLockFromISR();
+ osalThreadDequeueAllI(ÐD1.tdqueue, MSG_RESET);
+ osalSysUnlockFromISR();
+ }
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level MAC initialization.
+ *
+ * @notapi
+ */
+void mac_lld_init(void) {
+ unsigned i;
+
+ macObjectInit(ÐD1);
+ ETHD1.link_up = false;
+
+ /* Descriptor tables are initialized in chained mode, note that the first
+ word is not initialized here but in mac_lld_start().*/
+ for (i = 0; i < STM32_MAC_RECEIVE_BUFFERS; i++) {
+ __eth_rd[i].rdes1 = STM32_RDES1_RCH | STM32_MAC_BUFFERS_SIZE;
+ __eth_rd[i].rdes2 = (uint32_t)__eth_rb[i];
+ __eth_rd[i].rdes3 = (uint32_t)&__eth_rd[(i + 1) % STM32_MAC_RECEIVE_BUFFERS];
+ }
+ for (i = 0; i < STM32_MAC_TRANSMIT_BUFFERS; i++) {
+ __eth_td[i].tdes1 = 0;
+ __eth_td[i].tdes2 = (uint32_t)__eth_tb[i];
+ __eth_td[i].tdes3 = (uint32_t)&__eth_td[(i + 1) % STM32_MAC_TRANSMIT_BUFFERS];
+ }
+
+ /* Selection of the RMII or MII mode based on info exported by board.h.*/
+#if defined(STM32F10X_CL)
+#if defined(BOARD_PHY_RMII)
+ AFIO->MAPR |= AFIO_MAPR_MII_RMII_SEL;
+#else
+ AFIO->MAPR &= ~AFIO_MAPR_MII_RMII_SEL;
+#endif
+#elif defined(STM32F2XX) || defined(STM32F4XX) || defined(STM32F7XX)
+#if defined(BOARD_PHY_RMII)
+ SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
+#else
+ SYSCFG->PMC &= ~SYSCFG_PMC_MII_RMII_SEL;
+#endif
+#else
+#error "unsupported STM32 platform for MAC driver"
+#endif
+
+ /* Reset of the MAC core.*/
+ rccResetETH();
+
+ /* MAC clocks temporary activation.*/
+ rccEnableETH(true);
+
+ /* PHY address setup.*/
+#if defined(BOARD_PHY_ADDRESS)
+ ETHD1.phyaddr = BOARD_PHY_ADDRESS << 11;
+#else
+ mii_find_phy(ÐD1);
+#endif
+
+#if defined(BOARD_PHY_RESET)
+ /* PHY board-specific reset procedure.*/
+ BOARD_PHY_RESET();
+#else
+ /* PHY soft reset procedure.*/
+ mii_write(ÐD1, MII_BMCR, BMCR_RESET);
+#if defined(BOARD_PHY_RESET_DELAY)
+ osalSysPolledDelayX(BOARD_PHY_RESET_DELAY);
+#endif
+ while (mii_read(ÐD1, MII_BMCR) & BMCR_RESET)
+ ;
+#endif
+
+#if STM32_MAC_ETH1_CHANGE_PHY_STATE
+ /* PHY in power down mode until the driver will be started.*/
+ mii_write(ÐD1, MII_BMCR, mii_read(ÐD1, MII_BMCR) | BMCR_PDOWN);
+#endif
+
+ /* MAC clocks stopped again.*/
+ rccDisableETH();
+}
+
+/**
+ * @brief Configures and activates the MAC peripheral.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ *
+ * @notapi
+ */
+void mac_lld_start(MACDriver *macp) {
+ unsigned i;
+
+ /* Resets the state of all descriptors.*/
+ for (i = 0; i < STM32_MAC_RECEIVE_BUFFERS; i++)
+ __eth_rd[i].rdes0 = STM32_RDES0_OWN;
+ macp->rxptr = (stm32_eth_rx_descriptor_t *)__eth_rd;
+ for (i = 0; i < STM32_MAC_TRANSMIT_BUFFERS; i++)
+ __eth_td[i].tdes0 = STM32_TDES0_TCH;
+ macp->txptr = (stm32_eth_tx_descriptor_t *)__eth_td;
+
+ /* MAC clocks activation and commanded reset procedure.*/
+ rccEnableETH(true);
+#if defined(STM32_MAC_DMABMR_SR)
+ ETH->DMABMR |= ETH_DMABMR_SR;
+ while (ETH->DMABMR & ETH_DMABMR_SR)
+ ;
+#endif
+
+ /* ISR vector enabled.*/
+ nvicEnableVector(STM32_ETH_NUMBER, STM32_MAC_ETH1_IRQ_PRIORITY);
+
+#if STM32_MAC_ETH1_CHANGE_PHY_STATE
+ /* PHY in power up mode.*/
+ mii_write(macp, MII_BMCR, mii_read(macp, MII_BMCR) & ~BMCR_PDOWN);
+#endif
+
+ /* MAC configuration.*/
+ ETH->MACFFR = 0;
+ ETH->MACFCR = 0;
+ ETH->MACVLANTR = 0;
+
+ /* MAC address setup.*/
+ if (macp->config->mac_address == NULL)
+ mac_lld_set_address(default_mac_address);
+ else
+ mac_lld_set_address(macp->config->mac_address);
+
+ /* Transmitter and receiver enabled.
+ Note that the complete setup of the MAC is performed when the link
+ status is detected.*/
+#if STM32_MAC_IP_CHECKSUM_OFFLOAD
+ ETH->MACCR = ETH_MACCR_IPCO | ETH_MACCR_RE | ETH_MACCR_TE;
+#else
+ ETH->MACCR = ETH_MACCR_RE | ETH_MACCR_TE;
+#endif
+
+ /* DMA configuration:
+ Descriptor chains pointers.*/
+ ETH->DMARDLAR = (uint32_t)__eth_rd;
+ ETH->DMATDLAR = (uint32_t)__eth_td;
+
+ /* Enabling required interrupt sources.*/
+ ETH->DMASR = ETH->DMASR;
+ ETH->DMAIER = ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE;
+
+ /* DMA general settings.*/
+ ETH->DMABMR = ETH_DMABMR_AAB | ETH_DMABMR_RDP_1Beat | ETH_DMABMR_PBL_1Beat;
+
+ /* Check because errata on some devices. There should be no need to
+ disable flushing because the TXFIFO should be empty on macStart().*/
+#if !defined(STM32_MAC_DISABLE_TX_FLUSH)
+ /* Transmit FIFO flush.*/
+ ETH->DMAOMR = ETH_DMAOMR_FTF;
+ while (ETH->DMAOMR & ETH_DMAOMR_FTF)
+ ;
+#endif
+
+ /* DMA final configuration and start.*/
+ ETH->DMAOMR = ETH_DMAOMR_DTCEFD | ETH_DMAOMR_RSF | ETH_DMAOMR_TSF |
+ ETH_DMAOMR_ST | ETH_DMAOMR_SR;
+}
+
+/**
+ * @brief Deactivates the MAC peripheral.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ *
+ * @notapi
+ */
+void mac_lld_stop(MACDriver *macp) {
+
+ if (macp->state != MAC_STOP) {
+#if STM32_MAC_ETH1_CHANGE_PHY_STATE
+ /* PHY in power down mode until the driver will be restarted.*/
+ mii_write(macp, MII_BMCR, mii_read(macp, MII_BMCR) | BMCR_PDOWN);
+#endif
+
+ /* MAC and DMA stopped.*/
+ ETH->MACCR = 0;
+ ETH->DMAOMR = 0;
+ ETH->DMAIER = 0;
+ ETH->DMASR = ETH->DMASR;
+
+ /* MAC clocks stopped.*/
+ rccDisableETH();
+
+ /* ISR vector disabled.*/
+ nvicDisableVector(STM32_ETH_NUMBER);
+ }
+}
+
+/**
+ * @brief Returns a transmission descriptor.
+ * @details One of the available transmission descriptors is locked and
+ * returned.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ * @param[out] tdp pointer to a @p MACTransmitDescriptor structure
+ * @return The operation status.
+ * @retval MSG_OK the descriptor has been obtained.
+ * @retval MSG_TIMEOUT descriptor not available.
+ *
+ * @notapi
+ */
+msg_t mac_lld_get_transmit_descriptor(MACDriver *macp,
+ MACTransmitDescriptor *tdp) {
+ stm32_eth_tx_descriptor_t *tdes;
+
+ if (!macp->link_up)
+ return MSG_TIMEOUT;
+
+ /* Get Current TX descriptor.*/
+ tdes = macp->txptr;
+
+ /* Ensure that descriptor isn't owned by the Ethernet DMA or locked by
+ another thread.*/
+ if (tdes->tdes0 & (STM32_TDES0_OWN | STM32_TDES0_LOCKED)) {
+ return MSG_TIMEOUT;
+ }
+
+ /* Marks the current descriptor as locked using a reserved bit.*/
+ tdes->tdes0 |= STM32_TDES0_LOCKED;
+
+ /* Next TX descriptor to use.*/
+ macp->txptr = (stm32_eth_tx_descriptor_t *)tdes->tdes3;
+
+ /* Set the buffer size and configuration.*/
+ tdp->offset = 0;
+ tdp->size = STM32_MAC_BUFFERS_SIZE;
+ tdp->physdesc = tdes;
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Releases a transmit descriptor and starts the transmission of the
+ * enqueued data as a single frame.
+ *
+ * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure
+ *
+ * @notapi
+ */
+void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp) {
+
+ osalDbgAssert(!(tdp->physdesc->tdes0 & STM32_TDES0_OWN),
+ "attempt to release descriptor already owned by DMA");
+
+ osalSysLock();
+
+ /* Unlocks the descriptor and returns it to the DMA engine.*/
+ tdp->physdesc->tdes1 = tdp->offset;
+ tdp->physdesc->tdes0 = STM32_TDES0_CIC(STM32_MAC_IP_CHECKSUM_OFFLOAD) |
+ STM32_TDES0_IC | STM32_TDES0_LS | STM32_TDES0_FS |
+ STM32_TDES0_TCH | STM32_TDES0_OWN;
+
+ /* Wait for the write to tdes0 to go through before resuming the DMA.*/
+ __DSB();
+
+ /* If the DMA engine is stalled then a restart request is issued.*/
+ if ((ETH->DMASR & ETH_DMASR_TPS) == ETH_DMASR_TPS_Suspended) {
+ ETH->DMASR = ETH_DMASR_TBUS;
+ ETH->DMATPDR = ETH_DMASR_TBUS; /* Any value is OK.*/
+ }
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Returns a receive descriptor.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ * @param[out] rdp pointer to a @p MACReceiveDescriptor structure
+ * @return The operation status.
+ * @retval MSG_OK the descriptor has been obtained.
+ * @retval MSG_TIMEOUT descriptor not available.
+ *
+ * @notapi
+ */
+msg_t mac_lld_get_receive_descriptor(MACDriver *macp,
+ MACReceiveDescriptor *rdp) {
+ stm32_eth_rx_descriptor_t *rdes;
+
+ /* Get Current RX descriptor.*/
+ rdes = macp->rxptr;
+
+ /* Iterates through received frames until a valid one is found, invalid
+ frames are discarded.*/
+ while (!(rdes->rdes0 & STM32_RDES0_OWN)) {
+ if (!(rdes->rdes0 & (STM32_RDES0_AFM | STM32_RDES0_ES))
+#if STM32_MAC_IP_CHECKSUM_OFFLOAD
+ && (rdes->rdes0 & STM32_RDES0_FT)
+ && !(rdes->rdes0 & (STM32_RDES0_IPHCE | STM32_RDES0_PCE))
+#endif
+ && (rdes->rdes0 & STM32_RDES0_FS) && (rdes->rdes0 & STM32_RDES0_LS)) {
+ /* Found a valid one.*/
+ rdp->offset = 0;
+ rdp->size = ((rdes->rdes0 & STM32_RDES0_FL_MASK) >> 16) - 4;
+ rdp->physdesc = rdes;
+ macp->rxptr = (stm32_eth_rx_descriptor_t *)rdes->rdes3;
+
+ return MSG_OK;
+ }
+ /* Invalid frame found, purging.*/
+ rdes->rdes0 = STM32_RDES0_OWN;
+ rdes = (stm32_eth_rx_descriptor_t *)rdes->rdes3;
+ }
+
+ /* Next descriptor to check.*/
+ macp->rxptr = rdes;
+
+ return MSG_TIMEOUT;
+}
+
+/**
+ * @brief Releases a receive descriptor.
+ * @details The descriptor and its buffer are made available for more incoming
+ * frames.
+ *
+ * @param[in] rdp the pointer to the @p MACReceiveDescriptor structure
+ *
+ * @notapi
+ */
+void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp) {
+
+ osalDbgAssert(!(rdp->physdesc->rdes0 & STM32_RDES0_OWN),
+ "attempt to release descriptor already owned by DMA");
+
+ osalSysLock();
+
+ /* Give buffer back to the Ethernet DMA.*/
+ rdp->physdesc->rdes0 = STM32_RDES0_OWN;
+
+ /* Wait for the write to rdes0 to go through before resuming the DMA.*/
+ __DSB();
+
+ /* If the DMA engine is stalled then a restart request is issued.*/
+ if ((ETH->DMASR & ETH_DMASR_RPS) == ETH_DMASR_RPS_Suspended) {
+ ETH->DMASR = ETH_DMASR_RBUS;
+ ETH->DMARPDR = ETH_DMASR_RBUS; /* Any value is OK.*/
+ }
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Updates and returns the link status.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ * @return The link status.
+ * @retval true if the link is active.
+ * @retval false if the link is down.
+ *
+ * @notapi
+ */
+bool mac_lld_poll_link_status(MACDriver *macp) {
+ uint32_t maccr, bmsr, bmcr;
+
+ maccr = ETH->MACCR;
+
+ /* PHY CR and SR registers read.*/
+ (void)mii_read(macp, MII_BMSR);
+ bmsr = mii_read(macp, MII_BMSR);
+ bmcr = mii_read(macp, MII_BMCR);
+
+ /* Check on auto-negotiation mode.*/
+ if (bmcr & BMCR_ANENABLE) {
+ uint32_t lpa;
+
+ /* Auto-negotiation must be finished without faults and link established.*/
+ if ((bmsr & (BMSR_LSTATUS | BMSR_RFAULT | BMSR_ANEGCOMPLETE)) !=
+ (BMSR_LSTATUS | BMSR_ANEGCOMPLETE))
+ return macp->link_up = false;
+
+ /* Auto-negotiation enabled, checks the LPA register.*/
+ lpa = mii_read(macp, MII_LPA);
+
+ /* Check on link speed.*/
+ if (lpa & (LPA_100HALF | LPA_100FULL | LPA_100BASE4))
+ maccr |= ETH_MACCR_FES;
+ else
+ maccr &= ~ETH_MACCR_FES;
+
+ /* Check on link mode.*/
+ if (lpa & (LPA_10FULL | LPA_100FULL))
+ maccr |= ETH_MACCR_DM;
+ else
+ maccr &= ~ETH_MACCR_DM;
+ }
+ else {
+ /* Link must be established.*/
+ if (!(bmsr & BMSR_LSTATUS))
+ return macp->link_up = false;
+
+ /* Check on link speed.*/
+ if (bmcr & BMCR_SPEED100)
+ maccr |= ETH_MACCR_FES;
+ else
+ maccr &= ~ETH_MACCR_FES;
+
+ /* Check on link mode.*/
+ if (bmcr & BMCR_FULLDPLX)
+ maccr |= ETH_MACCR_DM;
+ else
+ maccr &= ~ETH_MACCR_DM;
+ }
+
+ /* Changes the mode in the MAC.*/
+ ETH->MACCR = maccr;
+
+ /* Returns the link status.*/
+ return macp->link_up = true;
+}
+
+/**
+ * @brief Writes to a transmit descriptor's stream.
+ *
+ * @param[in] tdp pointer to a @p MACTransmitDescriptor structure
+ * @param[in] buf pointer to the buffer containing the data to be
+ * written
+ * @param[in] size number of bytes to be written
+ * @return The number of bytes written into the descriptor's
+ * stream, this value can be less than the amount
+ * specified in the parameter @p size if the maximum
+ * frame size is reached.
+ *
+ * @notapi
+ */
+size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp,
+ uint8_t *buf,
+ size_t size) {
+
+ osalDbgAssert(!(tdp->physdesc->tdes0 & STM32_TDES0_OWN),
+ "attempt to write descriptor already owned by DMA");
+
+ if (size > tdp->size - tdp->offset)
+ size = tdp->size - tdp->offset;
+
+ if (size > 0) {
+ memcpy((uint8_t *)(tdp->physdesc->tdes2) + tdp->offset, buf, size);
+ tdp->offset += size;
+ }
+ return size;
+}
+
+/**
+ * @brief Reads from a receive descriptor's stream.
+ *
+ * @param[in] rdp pointer to a @p MACReceiveDescriptor structure
+ * @param[in] buf pointer to the buffer that will receive the read data
+ * @param[in] size number of bytes to be read
+ * @return The number of bytes read from the descriptor's
+ * stream, this value can be less than the amount
+ * specified in the parameter @p size if there are
+ * no more bytes to read.
+ *
+ * @notapi
+ */
+size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp,
+ uint8_t *buf,
+ size_t size) {
+
+ osalDbgAssert(!(rdp->physdesc->rdes0 & STM32_RDES0_OWN),
+ "attempt to read descriptor already owned by DMA");
+
+ if (size > rdp->size - rdp->offset)
+ size = rdp->size - rdp->offset;
+
+ if (size > 0) {
+ memcpy(buf, (uint8_t *)(rdp->physdesc->rdes2) + rdp->offset, size);
+ rdp->offset += size;
+ }
+ return size;
+}
+
+#if MAC_USE_ZERO_COPY || defined(__DOXYGEN__)
+/**
+ * @brief Returns a pointer to the next transmit buffer in the descriptor
+ * chain.
+ * @note The API guarantees that enough buffers can be requested to fill
+ * a whole frame.
+ *
+ * @param[in] tdp pointer to a @p MACTransmitDescriptor structure
+ * @param[in] size size of the requested buffer. Specify the frame size
+ * on the first call then scale the value down subtracting
+ * the amount of data already copied into the previous
+ * buffers.
+ * @param[out] sizep pointer to variable receiving the buffer size, it is
+ * zero when the last buffer has already been returned.
+ * Note that a returned size lower than the amount
+ * requested means that more buffers must be requested
+ * in order to fill the frame data entirely.
+ * @return Pointer to the returned buffer.
+ * @retval NULL if the buffer chain has been entirely scanned.
+ *
+ * @notapi
+ */
+uint8_t *mac_lld_get_next_transmit_buffer(MACTransmitDescriptor *tdp,
+ size_t size,
+ size_t *sizep) {
+
+ if (tdp->offset == 0) {
+ *sizep = tdp->size;
+ tdp->offset = size;
+ return (uint8_t *)tdp->physdesc->tdes2;
+ }
+ *sizep = 0;
+ return NULL;
+}
+
+/**
+ * @brief Returns a pointer to the next receive buffer in the descriptor
+ * chain.
+ * @note The API guarantees that the descriptor chain contains a whole
+ * frame.
+ *
+ * @param[in] rdp pointer to a @p MACReceiveDescriptor structure
+ * @param[out] sizep pointer to variable receiving the buffer size, it is
+ * zero when the last buffer has already been returned.
+ * @return Pointer to the returned buffer.
+ * @retval NULL if the buffer chain has been entirely scanned.
+ *
+ * @notapi
+ */
+const uint8_t *mac_lld_get_next_receive_buffer(MACReceiveDescriptor *rdp,
+ size_t *sizep) {
+
+ if (rdp->size > 0) {
+ *sizep = rdp->size;
+ rdp->offset = rdp->size;
+ rdp->size = 0;
+ return (uint8_t *)rdp->physdesc->rdes2;
+ }
+ *sizep = 0;
+ return NULL;
+}
+#endif /* MAC_USE_ZERO_COPY */
+
+#endif /* HAL_USE_MAC */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.h
new file mode 100644
index 0000000..31ad016
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MACv1/hal_mac_lld.h
@@ -0,0 +1,359 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file MACv1/hal_mac_lld.h
+ * @brief STM32 low level MAC driver header.
+ *
+ * @addtogroup MAC
+ * @{
+ */
+
+#ifndef HAL_MAC_LLD_H
+#define HAL_MAC_LLD_H
+
+#if HAL_USE_MAC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief This implementation supports the zero-copy mode API.
+ */
+#define MAC_SUPPORTS_ZERO_COPY TRUE
+
+/**
+ * @name RDES0 constants
+ * @{
+ */
+#define STM32_RDES0_OWN 0x80000000
+#define STM32_RDES0_AFM 0x40000000
+#define STM32_RDES0_FL_MASK 0x3FFF0000
+#define STM32_RDES0_ES 0x00008000
+#define STM32_RDES0_DESERR 0x00004000
+#define STM32_RDES0_SAF 0x00002000
+#define STM32_RDES0_LE 0x00001000
+#define STM32_RDES0_OE 0x00000800
+#define STM32_RDES0_VLAN 0x00000400
+#define STM32_RDES0_FS 0x00000200
+#define STM32_RDES0_LS 0x00000100
+#define STM32_RDES0_IPHCE 0x00000080
+#define STM32_RDES0_LCO 0x00000040
+#define STM32_RDES0_FT 0x00000020
+#define STM32_RDES0_RWT 0x00000010
+#define STM32_RDES0_RE 0x00000008
+#define STM32_RDES0_DE 0x00000004
+#define STM32_RDES0_CE 0x00000002
+#define STM32_RDES0_PCE 0x00000001
+/** @} */
+
+/**
+ * @name RDES1 constants
+ * @{
+ */
+#define STM32_RDES1_DIC 0x80000000
+#define STM32_RDES1_RBS2_MASK 0x1FFF0000
+#define STM32_RDES1_RER 0x00008000
+#define STM32_RDES1_RCH 0x00004000
+#define STM32_RDES1_RBS1_MASK 0x00001FFF
+/** @} */
+
+/**
+ * @name TDES0 constants
+ * @{
+ */
+#define STM32_TDES0_OWN 0x80000000
+#define STM32_TDES0_IC 0x40000000
+#define STM32_TDES0_LS 0x20000000
+#define STM32_TDES0_FS 0x10000000
+#define STM32_TDES0_DC 0x08000000
+#define STM32_TDES0_DP 0x04000000
+#define STM32_TDES0_TTSE 0x02000000
+#define STM32_TDES0_LOCKED 0x01000000 /* NOTE: Pseudo flag. */
+#define STM32_TDES0_CIC_MASK 0x00C00000
+#define STM32_TDES0_CIC(n) ((n) << 22)
+#define STM32_TDES0_TER 0x00200000
+#define STM32_TDES0_TCH 0x00100000
+#define STM32_TDES0_TTSS 0x00020000
+#define STM32_TDES0_IHE 0x00010000
+#define STM32_TDES0_ES 0x00008000
+#define STM32_TDES0_JT 0x00004000
+#define STM32_TDES0_FF 0x00002000
+#define STM32_TDES0_IPE 0x00001000
+#define STM32_TDES0_LCA 0x00000800
+#define STM32_TDES0_NC 0x00000400
+#define STM32_TDES0_LCO 0x00000200
+#define STM32_TDES0_EC 0x00000100
+#define STM32_TDES0_VF 0x00000080
+#define STM32_TDES0_CC_MASK 0x00000078
+#define STM32_TDES0_ED 0x00000004
+#define STM32_TDES0_UF 0x00000002
+#define STM32_TDES0_DB 0x00000001
+/** @} */
+
+/**
+ * @name TDES1 constants
+ * @{
+ */
+#define STM32_TDES1_TBS2_MASK 0x1FFF0000
+#define STM32_TDES1_TBS1_MASK 0x00001FFF
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief Number of available transmit buffers.
+ */
+#if !defined(STM32_MAC_TRANSMIT_BUFFERS) || defined(__DOXYGEN__)
+#define STM32_MAC_TRANSMIT_BUFFERS 2
+#endif
+
+/**
+ * @brief Number of available receive buffers.
+ */
+#if !defined(STM32_MAC_RECEIVE_BUFFERS) || defined(__DOXYGEN__)
+#define STM32_MAC_RECEIVE_BUFFERS 4
+#endif
+
+/**
+ * @brief Maximum supported frame size.
+ */
+#if !defined(STM32_MAC_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define STM32_MAC_BUFFERS_SIZE 1522
+#endif
+
+/**
+ * @brief PHY detection timeout.
+ * @details Timeout for PHY address detection, the scan for a PHY is performed
+ * the specified number of times before invoking the failure handler.
+ * This setting applies only if the PHY address is not explicitly
+ * set in the board header file using @p BOARD_PHY_ADDRESS. A zero
+ * value disables the timeout and a single search is performed.
+ */
+#if !defined(STM32_MAC_PHY_TIMEOUT) || defined(__DOXYGEN__)
+#define STM32_MAC_PHY_TIMEOUT 100
+#endif
+
+/**
+ * @brief Change the PHY power state inside the driver.
+ */
+#if !defined(STM32_MAC_ETH1_CHANGE_PHY_STATE) || defined(__DOXYGEN__)
+#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE
+#endif
+
+/**
+ * @brief ETHD1 interrupt priority level setting.
+ */
+#if !defined(STM32_MAC_ETH1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_MAC_ETH1_IRQ_PRIORITY 13
+#endif
+
+/**
+ * @brief IP checksum offload.
+ * @details The following modes are available:
+ * - 0 Function disabled.
+ * - 1 Only IP header checksum calculation and insertion are enabled.
+ * - 2 IP header checksum and payload checksum calculation and
+ * insertion are enabled, but pseudo-header checksum is not
+ * calculated in hardware.
+ * - 3 IP Header checksum and payload checksum calculation and
+ * insertion are enabled, and pseudo-header checksum is
+ * calculated in hardware.
+ * .
+ */
+#if !defined(STM32_MAC_IP_CHECKSUM_OFFLOAD) || defined(__DOXYGEN__)
+#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of an STM32 Ethernet receive descriptor.
+ */
+typedef struct {
+ volatile uint32_t rdes0;
+ volatile uint32_t rdes1;
+ volatile uint32_t rdes2;
+ volatile uint32_t rdes3;
+} stm32_eth_rx_descriptor_t;
+
+/**
+ * @brief Type of an STM32 Ethernet transmit descriptor.
+ */
+typedef struct {
+ volatile uint32_t tdes0;
+ volatile uint32_t tdes1;
+ volatile uint32_t tdes2;
+ volatile uint32_t tdes3;
+} stm32_eth_tx_descriptor_t;
+
+/**
+ * @brief Driver configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief MAC address.
+ */
+ uint8_t *mac_address;
+ /* End of the mandatory fields.*/
+} MACConfig;
+
+/**
+ * @brief Structure representing a MAC driver.
+ */
+struct MACDriver {
+ /**
+ * @brief Driver state.
+ */
+ macstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const MACConfig *config;
+ /**
+ * @brief Transmit semaphore.
+ */
+ threads_queue_t tdqueue;
+ /**
+ * @brief Receive semaphore.
+ */
+ threads_queue_t rdqueue;
+#if MAC_USE_EVENTS || defined(__DOXYGEN__)
+ /**
+ * @brief Receive event.
+ */
+ event_source_t rdevent;
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Link status flag.
+ */
+ bool link_up;
+ /**
+ * @brief PHY address (pre shifted).
+ */
+ uint32_t phyaddr;
+ /**
+ * @brief Receive next frame pointer.
+ */
+ stm32_eth_rx_descriptor_t *rxptr;
+ /**
+ * @brief Transmit next frame pointer.
+ */
+ stm32_eth_tx_descriptor_t *txptr;
+};
+
+/**
+ * @brief Structure representing a transmit descriptor.
+ */
+typedef struct {
+ /**
+ * @brief Current write offset.
+ */
+ size_t offset;
+ /**
+ * @brief Available space size.
+ */
+ size_t size;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Pointer to the physical descriptor.
+ */
+ stm32_eth_tx_descriptor_t *physdesc;
+} MACTransmitDescriptor;
+
+/**
+ * @brief Structure representing a receive descriptor.
+ */
+typedef struct {
+ /**
+ * @brief Current read offset.
+ */
+ size_t offset;
+ /**
+ * @brief Available data size.
+ */
+ size_t size;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Pointer to the physical descriptor.
+ */
+ stm32_eth_rx_descriptor_t *physdesc;
+} MACReceiveDescriptor;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern MACDriver ETHD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void mii_write(MACDriver *macp, uint32_t reg, uint32_t value);
+ uint32_t mii_read(MACDriver *macp, uint32_t reg);
+ void mac_lld_init(void);
+ void mac_lld_start(MACDriver *macp);
+ void mac_lld_stop(MACDriver *macp);
+ msg_t mac_lld_get_transmit_descriptor(MACDriver *macp,
+ MACTransmitDescriptor *tdp);
+ void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp);
+ msg_t mac_lld_get_receive_descriptor(MACDriver *macp,
+ MACReceiveDescriptor *rdp);
+ void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp);
+ bool mac_lld_poll_link_status(MACDriver *macp);
+ size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp,
+ uint8_t *buf,
+ size_t size);
+ size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp,
+ uint8_t *buf,
+ size_t size);
+#if MAC_USE_ZERO_COPY
+ uint8_t *mac_lld_get_next_transmit_buffer(MACTransmitDescriptor *tdp,
+ size_t size,
+ size_t *sizep);
+ const uint8_t *mac_lld_get_next_receive_buffer(MACReceiveDescriptor *rdp,
+ size_t *sizep);
+#endif /* MAC_USE_ZERO_COPY */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_MAC */
+
+#endif /* HAL_MAC_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MDMAv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MDMAv1/driver.mk
new file mode 100644
index 0000000..d10e2ad
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MDMAv1/driver.mk
@@ -0,0 +1,2 @@
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.c
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MDMAv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MDMAv1/notes.txt b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MDMAv1/notes.txt
new file mode 100644
index 0000000..a092556
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MDMAv1/notes.txt
@@ -0,0 +1,11 @@
+STM32 MDMAv1 driver.
+
+Driver capability:
+
+- The driver supports the STM32 complex MDMA controller found on H7
+ sub-family.
+
+The file registry must export:
+
+STM32_MDMA_CHn_HANDLER - Vector name for channel "n" (0..15).
+STM32_MDMA_CHn_NUMBER - Vector number for channel "n" (0..15).
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.c
new file mode 100644
index 0000000..c77bfa0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.c
@@ -0,0 +1,355 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file MDMAv1/stm32_mdma.c
+ * @brief MDMA helper driver code.
+ *
+ * @addtogroup STM32_MDMA
+ * @details MDMA sharing helper driver. In the STM32 the MDMA channels are a
+ * shared resource, this driver allows to allocate and free MDMA
+ * STM32 at runtime in order to allow all the other device
+ * drivers to coordinate the access to the resource.
+ * @note The MDMA ISR handlers are all declared into this module because
+ * sharing, the various device drivers can associate a callback to
+ * ISRs when allocating channels.
+ * @{
+ */
+
+#include "hal.h"
+
+/* The following macro is only defined if some driver requiring MDMA services
+ has been enabled.*/
+#if defined(STM32_MDMA_REQUIRED) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Global MDMA-related data structures.
+ */
+static struct {
+ /**
+ * @brief Mask of the allocated channels.
+ */
+ uint32_t allocated_mask;
+ /**
+ * @brief MDMA IRQ redirectors.
+ */
+ stm32_mdma_channel_t channels[STM32_MDMA_CHANNELS];
+} mdma;
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static void mdma_serve_interrupt(const stm32_mdma_channel_t *mdmachp) {
+ uint32_t flags;
+
+ flags = mdmachp->channel->CISR;
+ mdmachp->channel->CIFCR = flags;
+ if (mdmachp->func != NULL) {
+ mdmachp->func(mdmachp->param, flags);
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/**
+ * @brief MDMA shared interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_MDMA_HANDLER) {
+ uint32_t gisr = MDMA->GISR0;
+ OSAL_IRQ_PROLOGUE();
+
+ if ((gisr & (1U << 0)) != 0U) {
+ mdma_serve_interrupt(&mdma.channels[0]);
+ }
+
+ if ((gisr & (1U << 1)) != 0U) {
+ mdma_serve_interrupt(&mdma.channels[1]);
+ }
+
+ if ((gisr & (1U << 2)) != 0U) {
+ mdma_serve_interrupt(&mdma.channels[2]);
+ }
+
+ if ((gisr & (1U << 3)) != 0U) {
+ mdma_serve_interrupt(&mdma.channels[3]);
+ }
+
+ if ((gisr & (1U << 4)) != 0U) {
+ mdma_serve_interrupt(&mdma.channels[4]);
+ }
+
+ if ((gisr & (1U << 5)) != 0U) {
+ mdma_serve_interrupt(&mdma.channels[5]);
+ }
+
+ if ((gisr & (1U << 6)) != 0U) {
+ mdma_serve_interrupt(&mdma.channels[6]);
+ }
+
+ if ((gisr & (1U << 7)) != 0U) {
+ mdma_serve_interrupt(&mdma.channels[7]);
+ }
+
+ if ((gisr & (1U << 8)) != 0U) {
+ mdma_serve_interrupt(&mdma.channels[8]);
+ }
+
+ if ((gisr & (1U << 9)) != 0U) {
+ mdma_serve_interrupt(&mdma.channels[9]);
+ }
+
+ if ((gisr & (1U << 10)) != 0U) {
+ mdma_serve_interrupt(&mdma.channels[10]);
+ }
+
+ if ((gisr & (1U << 11)) != 0U) {
+ mdma_serve_interrupt(&mdma.channels[11]);
+ }
+
+ if ((gisr & (1U << 12)) != 0U) {
+ mdma_serve_interrupt(&mdma.channels[12]);
+ }
+
+ if ((gisr & (1U << 13)) != 0U) {
+ mdma_serve_interrupt(&mdma.channels[13]);
+ }
+
+ if ((gisr & (1U << 14)) != 0U) {
+ mdma_serve_interrupt(&mdma.channels[14]);
+ }
+
+ if ((gisr & (1U << 15)) != 0U) {
+ mdma_serve_interrupt(&mdma.channels[15]);
+ }
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 MDMA helper initialization.
+ *
+ * @init
+ */
+void mdmaInit(void) {
+ static MDMA_Channel_TypeDef * const ch[STM32_MDMA_CHANNELS] = {
+ MDMA_Channel0, MDMA_Channel1, MDMA_Channel2, MDMA_Channel3,
+ MDMA_Channel4, MDMA_Channel5, MDMA_Channel6, MDMA_Channel7,
+ MDMA_Channel8, MDMA_Channel9, MDMA_Channel10, MDMA_Channel11,
+ MDMA_Channel12, MDMA_Channel13, MDMA_Channel14, MDMA_Channel15
+ };
+ unsigned i;
+
+ mdma.allocated_mask = 0U;
+ for (i = 0U; i < STM32_MDMA_CHANNELS; i++) {
+ MDMA_Channel_TypeDef *cp = ch[i];
+ mdma.channels[i].channel = cp;
+ mdma.channels[i].func = NULL;
+ mdma.channels[i].channel->CCR = STM32_MDMA_CCR_RESET_VALUE;
+ mdma.channels[i].channel->CTCR = STM32_MDMA_CTCR_RESET_VALUE;
+ mdma.channels[i].channel->CIFCR = STM32_MDMA_CIFCR_CTEIF |
+ STM32_MDMA_CIFCR_CBRTIF |
+ STM32_MDMA_CIFCR_CBRTIF |
+ STM32_MDMA_CIFCR_CCTCIF |
+ STM32_MDMA_CIFCR_CTEIF;
+ }
+}
+
+/**
+ * @brief Allocates an MDMA channel.
+ * @details The channel is allocated and, if required, the MDMA clock enabled.
+ * The function also enables the IRQ vector associated to the channel
+ * and initializes its priority.
+ *
+ * @param[in] id numeric identifiers of a specific channel or:
+ * - @p STM32_MDMA_CHANNEL_ID_ANY for any channel.
+ * .
+ * @param[in] func handling function pointer, can be @p NULL
+ * @param[in] param a parameter to be passed to the handling function
+ * @return Pointer to the allocated @p stm32_mdma_channel_t
+ * structure.
+ * @retval NULL if a/the channel is not available.
+ *
+ * @iclass
+ */
+const stm32_mdma_channel_t *dmaChannelAllocI(uint32_t id,
+ stm32_mdmaisr_t func,
+ void *param) {
+ uint32_t i, startid, endid;
+
+ osalDbgCheckClassI();
+
+ if (id < STM32_MDMA_CHANNELS) {
+ startid = id;
+ endid = id;
+ }
+ else if (id == STM32_MDMA_CHANNEL_ID_ANY) {
+ startid = 0U;
+ endid = STM32_MDMA_CHANNELS - 1U;
+ }
+ else {
+ osalDbgCheck(false);
+ return NULL;
+ }
+
+ for (i = startid; i <= endid; i++) {
+ uint32_t mask = (1U << i);
+ if ((mdma.allocated_mask & mask) == 0U) {
+ stm32_mdma_channel_t *mdmachp = &mdma.channels[i];
+
+ /* Installs the MDMA handler.*/
+ mdma.allocated_mask |= mask;
+ mdmachp->func = func;
+ mdmachp->param = param;
+
+ /* Enabling MDMA clocks required by the current channels set.*/
+ if (mdma.allocated_mask != 0U) {
+ rccEnableMDMA(true);
+ }
+
+ return mdmachp;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * @brief Allocates a MDMA channel.
+ * @details The channel is allocated and, if required, the MDMA clock enabled.
+ * The function also enables the IRQ vector associated to the channel
+ * and initializes its priority.
+ *
+ * @param[in] id numeric identifiers of a specific channel or:
+ * - @p STM32_MDMA_CHANNEL_ID_ANY for any channel.
+ * .
+ * @param[in] func handling function pointer, can be @p NULL
+ * @param[in] param a parameter to be passed to the handling function
+ * @return Pointer to the allocated @p stm32_mdma_channel_t
+ * structure.
+ * @retval NULL if a/the channel is not available.
+ *
+ * @api
+ */
+const stm32_mdma_channel_t *dmaChannelAlloc(uint32_t id,
+ stm32_mdmaisr_t func,
+ void *param) {
+ const stm32_mdma_channel_t *mdmachp;
+
+ osalSysLock();
+ mdmachp = mdmaChannelAllocI(id, func, param);
+ osalSysUnlock();
+
+ return mdmachp;
+}
+
+/**
+ * @brief Releases a MDMA channel.
+ * @details The channel is freed and, if required, the MDMA clock disabled.
+ * Trying to release a unallocated channel is an illegal operation
+ * and is trapped if assertions are enabled.
+ *
+ * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure
+ *
+ * @iclass
+ */
+void mdmaChannelFreeI(const stm32_mdma_channel_t *mdmachp) {
+ uint32_t channel = mdmachp - mdma.channels;
+ osalDbgCheck(mdmachp != NULL);
+
+ /* Check if the channels is not taken.*/
+ osalDbgAssert((mdma.allocated_mask & (1U << channel)) != 0U,
+ "not allocated");
+
+ /* Marks the channel as not allocated.*/
+ mdma.allocated_mask &= ~(1U << channel);
+
+ /* Shutting down clocks that are no more required, if any.*/
+ if (mdma.allocated_mask == 0U) {
+ rccDisableMDMA();
+ }
+}
+
+/**
+ * @brief Releases a MDMA channel.
+ * @details The channel is freed and, if required, the MDMA clock disabled.
+ * Trying to release a unallocated channel is an illegal operation
+ * and is trapped if assertions are enabled.
+ *
+ * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure
+ *
+ * @api
+ */
+void mdmaChannelFree(const stm32_mdma_channel_t *mdmachp) {
+
+ osalSysLock();
+ mdmaChannelFreeI(mdmachp);
+ osalSysUnlock();
+}
+
+/**
+ * @brief MDMA stream disable.
+ * @details The function disables the specified stream, waits for the disable
+ * operation to complete and then clears any pending interrupt.
+ * @pre The stream must have been allocated using @p mdmaChannelAlloc().
+ * @post After use the stream can be released using @p mdmaChannelFree().
+ *
+ * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure
+ *
+ * @xclass
+ */
+void mdmaChannelDisableX(const stm32_mdma_channel_t *mdmachp) {
+ uint32_t ccr = mdmachp->channel->CCR;
+
+ /* Clearing CCR regardless of previous state.*/
+ mdmachp->channel->CCR &= ~(STM32_MDMA_CCR_TCIE | STM32_MDMA_CCR_BTIE |
+ STM32_MDMA_CCR_BRTIE | STM32_MDMA_CCR_CTCIE |
+ STM32_MDMA_CCR_TEIE | STM32_MDMA_CCR_EN);
+
+ /* If the channel was enabled then waiting for ongoing operations
+ to finish.*/
+ if ((ccr & STM32_MDMA_CCR_EN) != 0U) {
+ while (((mdmachp)->channel->CISR & STM32_MDMA_CISR_CTCIF) == 0U)
+ ;
+ }
+
+ /* Clearing IRQ sources.*/
+ mdmaChannelClearInterruptX(mdmachp);
+}
+
+#endif /* defined(STM32_MDMA_REQUIRED) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.h
new file mode 100644
index 0000000..6dfe9eb
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.h
@@ -0,0 +1,448 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file MDMAv1/stm32_mdma.h
+ * @brief MDMA helper driver header.
+ *
+ * @addtogroup STM32_MDMA
+ * @{
+ */
+
+#ifndef STM32_MDMA_H
+#define STM32_MDMA_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Total number of MDMA streams.
+ */
+#define STM32_MDMA_CHANNELS 16U
+
+/**
+ * @brief Mask of the ISR bits passed to the MDMA callback functions.
+ */
+#define STM32_MDMA_ISR_MASK 0x1FU
+
+/**
+ * @brief Checks if a MDMA priority is within the valid range.
+ * @param[in] prio MDMA priority
+ *
+ * @retval The check result.
+ * @retval false invalid MDMA priority.
+ * @retval true correct MDMA priority.
+ */
+#define STM32_MDMA_IS_VALID_PRIORITY(prio) (((prio) >= 0U) && ((prio) <= 3U))
+
+/**
+ * @brief Checks if a MDMA channel id is within the valid range.
+ *
+ * @param[in] id MDMA channel id
+ * @retval The check result.
+ * @retval false invalid MDMA channel.
+ * @retval true correct MDMA channel.
+ */
+#define STM32_MDMA_IS_VALID_CHANNEL(id) (((id) >= 0U) && \
+ ((id) <= STM32_MDMA_CHANNELS))
+
+/**
+ * @brief Special stream identifier
+ */
+#define STM32_MDMA_CHANNEL_ID_ANY STM32_MDMA_CHANNELS
+
+/**
+ * @name CISR register constants
+ * @{
+ */
+#define STM32_MDMA_CISR_TEIF (1U << 0)
+#define STM32_MDMA_CISR_CTCIF (1U << 1)
+#define STM32_MDMA_CISR_BRTIF (1U << 2)
+#define STM32_MDMA_CISR_BTIF (1U << 3)
+#define STM32_MDMA_CISR_TCIF (1U << 4)
+#define STM32_MDMA_CISR_CRQA (1U << 16)
+/** @} */
+
+/**
+ * @name CIFCR register constants
+ * @{
+ */
+#define STM32_MDMA_CIFCR_CTEIF (1U << 0)
+#define STM32_MDMA_CIFCR_CCTCIF (1U << 1)
+#define STM32_MDMA_CIFCR_CBRTIF (1U << 2)
+#define STM32_MDMA_CIFCR_CBTIF (1U << 3)
+#define STM32_MDMA_CIFCR_CTCIF (1U << 4)
+/** @} */
+
+/**
+ * @name CESR register constants
+ * @{
+ */
+#define STM32_MDMA_CESR_TEA_MASK (127U << 0)
+#define STM32_MDMA_CESR_TED (1U << 7)
+#define STM32_MDMA_CESR_TELD (1U << 8)
+#define STM32_MDMA_CESR_TEMD (1U << 9)
+#define STM32_MDMA_CESR_ASE (1U << 10)
+#define STM32_MDMA_CESR_BSE (1U << 11)
+/** @} */
+
+/**
+ * @name CCR register constants
+ * @{
+ */
+#define STM32_MDMA_CCR_RESET_VALUE 0x00000000U
+#define STM32_MDMA_CCR_EN (1U << 0)
+#define STM32_MDMA_CCR_TEIE (1U << 1)
+#define STM32_MDMA_CCR_CTCIE (1U << 2)
+#define STM32_MDMA_CCR_BRTIE (1U << 3)
+#define STM32_MDMA_CCR_BTIE (1U << 4)
+#define STM32_MDMA_CCR_TCIE (1U << 5)
+#define STM32_MDMA_CCR_PL_MASK (3U << 6)
+#define STM32_MDMA_CCR_PL(n) ((n) << 6)
+#define STM32_MDMA_CCR_BEX (1U << 12)
+#define STM32_MDMA_CCR_HEX (1U << 13)
+#define STM32_MDMA_CCR_WEX (1U << 14)
+#define STM32_MDMA_CCR_SWRQ (1U << 16)
+/** @} */
+
+/**
+ * @name CTCR register constants
+ * @{
+ */
+#define STM32_MDMA_CTCR_RESET_VALUE 0x00000000U
+
+#define STM32_MDMA_CTCR_SINC_MASK (3U << 0)
+#define STM32_MDMA_CTCR_SINC(n) ((n) << 0)
+#define STM32_MDMA_CTCR_SINC_FIXED STM32_MDMA_CTCR_SINC(0U)
+#define STM32_MDMA_CTCR_SINC_INC STM32_MDMA_CTCR_SINC(1U)
+#define STM32_MDMA_CTCR_SINC_DEC STM32_MDMA_CTCR_SINC(3U)
+
+#define STM32_MDMA_CTCR_DINC_MASK (3U << 2)
+#define STM32_MDMA_CTCR_DINC(n) ((n) << 2)
+#define STM32_MDMA_CTCR_DINC_FIXED STM32_MDMA_CTCR_DINC(0U)
+#define STM32_MDMA_CTCR_DINC_INC STM32_MDMA_CTCR_DINC(1U)
+#define STM32_MDMA_CTCR_DINC_DEC STM32_MDMA_CTCR_DINC(3U)
+
+#define STM32_MDMA_CTCR_SSIZE_MASK (3U << 4)
+#define STM32_MDMA_CTCR_SSIZE(n) ((n) << 4)
+#define STM32_MDMA_CTCR_SSIZE_BYTE STM32_MDMA_CTCR_SSIZE(0U)
+#define STM32_MDMA_CTCR_SSIZE_HALF STM32_MDMA_CTCR_SSIZE(1U)
+#define STM32_MDMA_CTCR_SSIZE_WORD STM32_MDMA_CTCR_SSIZE(2U)
+#define STM32_MDMA_CTCR_SSIZE_DWORD STM32_MDMA_CTCR_SSIZE(3U)
+
+#define STM32_MDMA_CTCR_DSIZE_MASK (3U << 6)
+#define STM32_MDMA_CTCR_DSIZE(n) ((n) << 6)
+#define STM32_MDMA_CTCR_DSIZE_BYTE STM32_MDMA_CTCR_DSIZE(0U)
+#define STM32_MDMA_CTCR_DSIZE_HALF STM32_MDMA_CTCR_DSIZE(1U)
+#define STM32_MDMA_CTCR_DSIZE_WORD STM32_MDMA_CTCR_DSIZE(2U)
+#define STM32_MDMA_CTCR_DSIZE_DWORD STM32_MDMA_CTCR_DSIZE(3U)
+
+#define STM32_MDMA_CTCR_SINCOS_MASK (3U << 8)
+#define STM32_MDMA_CTCR_SINCOS(n) ((n) << 8)
+#define STM32_MDMA_CTCR_SINCOS_BYTE STM32_MDMA_CTCR_SINCOS(0U)
+#define STM32_MDMA_CTCR_SINCOS_HALF STM32_MDMA_CTCR_SINCOS(1U)
+#define STM32_MDMA_CTCR_SINCOS_WORD STM32_MDMA_CTCR_SINCOS(2U)
+#define STM32_MDMA_CTCR_SINCOS_DWORD STM32_MDMA_CTCR_SINCOS(3U)
+
+#define STM32_MDMA_CTCR_DINCOS_MASK (3U << 10)
+#define STM32_MDMA_CTCR_DINCOS(n) ((n) << 10)
+#define STM32_MDMA_CTCR_DINCOS_BYTE STM32_MDMA_CTCR_DINCOS(0U)
+#define STM32_MDMA_CTCR_DINCOS_HALF STM32_MDMA_CTCR_DINCOS(1U)
+#define STM32_MDMA_CTCR_DINCOS_WORD STM32_MDMA_CTCR_DINCOS(2U)
+#define STM32_MDMA_CTCR_DINCOS_DWORD STM32_MDMA_CTCR_DINCOS(3U)
+
+#define STM32_MDMA_CTCR_SBURST_MASK (7U << 12)
+#define STM32_MDMA_CTCR_SBURST(n) ((n) << 12)
+#define STM32_MDMA_CTCR_SBURST_1 STM32_MDMA_CTCR_SBURST(0U)
+#define STM32_MDMA_CTCR_SBURST_2 STM32_MDMA_CTCR_SBURST(1U)
+#define STM32_MDMA_CTCR_SBURST_4 STM32_MDMA_CTCR_SBURST(2U)
+#define STM32_MDMA_CTCR_SBURST_8 STM32_MDMA_CTCR_SBURST(3U)
+#define STM32_MDMA_CTCR_SBURST_16 STM32_MDMA_CTCR_SBURST(4U)
+#define STM32_MDMA_CTCR_SBURST_32 STM32_MDMA_CTCR_SBURST(5U)
+#define STM32_MDMA_CTCR_SBURST_64 STM32_MDMA_CTCR_SBURST(6U)
+#define STM32_MDMA_CTCR_SBURST_128 STM32_MDMA_CTCR_SBURST(7U)
+
+#define STM32_MDMA_CTCR_DBURST_MASK (7U << 15)
+#define STM32_MDMA_CTCR_DBURST(n) ((n) << 15)
+#define STM32_MDMA_CTCR_DBURST_1 STM32_MDMA_CTCR_DBURST(0U)
+#define STM32_MDMA_CTCR_DBURST_2 STM32_MDMA_CTCR_DBURST(1U)
+#define STM32_MDMA_CTCR_DBURST_4 STM32_MDMA_CTCR_DBURST(2U)
+#define STM32_MDMA_CTCR_DBURST_8 STM32_MDMA_CTCR_DBURST(3U)
+#define STM32_MDMA_CTCR_DBURST_16 STM32_MDMA_CTCR_DBURST(4U)
+#define STM32_MDMA_CTCR_DBURST_32 STM32_MDMA_CTCR_DBURST(5U)
+#define STM32_MDMA_CTCR_DBURST_64 STM32_MDMA_CTCR_DBURST(6U)
+#define STM32_MDMA_CTCR_DBURST_128 STM32_MDMA_CTCR_DBURST(7U)
+
+#define STM32_MDMA_CTCR_TLEN_MASK (127U << 18)
+#define STM32_MDMA_CTCR_TLEN(n) ((n) << 18)
+
+#define STM32_MDMA_CTCR_PKE (1U << 25)
+
+#define STM32_MDMA_CTCR_PAM_MASK (3U << 26)
+#define STM32_MDMA_CTCR_PAM(n) ((n) << 26)
+#define STM32_MDMA_CTCR_PAM_RIGHT STM32_MDMA_CTCR_PAM(0U)
+#define STM32_MDMA_CTCR_PAM_RIGHT_SE STM32_MDMA_CTCR_PAM(1U)
+#define STM32_MDMA_CTCR_PAM_LEFT STM32_MDMA_CTCR_PAM(2U)
+
+#define STM32_MDMA_CTCR_TRGM_MASK (3U << 28)
+#define STM32_MDMA_CTCR_TRGM(n) ((n) << 28)
+#define STM32_MDMA_CTCR_TRGM_BUFFER STM32_MDMA_CTCR_TRGM(0U)
+#define STM32_MDMA_CTCR_TRGM_BLOCK STM32_MDMA_CTCR_TRGM(1U)
+#define STM32_MDMA_CTCR_TRGM_REP_BLOCK STM32_MDMA_CTCR_TRGM(2U)
+#define STM32_MDMA_CTCR_TRGM_WHOLE STM32_MDMA_CTCR_TRGM(3U)
+
+#define STM32_MDMA_CTCR_SWRM (1U << 30)
+
+#define STM32_MDMA_CTCR_BWM_MASK (1U << 31)
+#define STM32_MDMA_CTCR_BWM_NON_BUFF (0U << 31)
+#define STM32_MDMA_CTCR_BWM_BUFF (1U << 31)
+/** @} */
+
+/**
+ * @name BNDTR register constants
+ * @{
+ */
+#define STM32_MDMA_CBNDTR_BNDT_MASK (0x1FFFFU << 0)
+#define STM32_MDMA_CBNDTR_BNDT(n) ((n) << 0)
+#define STM32_MDMA_CBNDTR_BRSUM (1U << 18)
+#define STM32_MDMA_CBNDTR_BRDUM (1U << 19)
+#define STM32_MDMA_CBNDTR_BRC_MASK (0xFFFU << 20)
+#define STM32_MDMA_CBNDTR_BRC(n) ((n) << 20)
+/** @} */
+
+/**
+ * @name CBRUR register constants
+ * @{
+ */
+#define STM32_MDMA_CBRUR_SUV_MASK (0xFFFFU << 0)
+#define STM32_MDMA_CBRUR_SUV(n) ((n) << 0)
+#define STM32_MDMA_CBRUR_DUV_MASK (0xFFFFU << 16)
+#define STM32_MDMA_CBRUR_DUV(n) ((n) << 16)
+/** @} */
+
+/**
+ * @name CTBR register constants
+ * @{
+ */
+#define STM32_MDMA_CTBR_TSEL_MASK (0x3FU << 0)
+#define STM32_MDMA_CTBR_TSEL(n) ((n) << 0)
+#define STM32_MDMA_CTBR_TSEL_SBUS (1U << 16)
+#define STM32_MDMA_CTBR_TSEL_DBUS (1U << 17)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !defined(STM32_MDMA_HANDLER)
+#error "STM32_MDMA_HANDLER missing in registry"
+#endif
+
+#if !defined(STM32_MDMA_NUMBER)
+#error "STM32_MDMA_NUMBER missing in registry"
+#endif
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_MDMA_PRIORITY)
+#error "STM32_IRQ_MDMA_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_MDMA_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_MDMA_PRIORITY"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 MDMA ISR function type.
+ *
+ * @param[in] p parameter for the registered function
+ * @param[in] flags content of the CISR register
+ */
+typedef void (*stm32_mdmaisr_t)(void *p, uint32_t flags);
+
+/**
+ * @brief STM32 MDMA stream descriptor structure.
+ */
+typedef struct {
+ /**
+ * @brief Associated MDMA channel.
+ */
+ MDMA_Channel_TypeDef *channel;
+ /**
+ * @brief MDMA callback function.
+ */
+ stm32_mdmaisr_t func;
+ /**
+ * @brief MDMA callback parameter.
+ */
+ void *param;
+} stm32_mdma_channel_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Associates a source address to a MDMA stream.
+ * @pre The stream must have been allocated using @p mdmaChannelAlloc().
+ * @post After use the stream can be released using @p mdmaChannelFree().
+ *
+ * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure
+ * @param[in] addr value to be written in the CSAR register
+ *
+ * @xclass
+ */
+#define mdmaChannelSetSourceX(mdmachp, addr) do { \
+ (mdmachp)->channel->CSAR = (uint32_t)(addr); \
+} while (0)
+
+/**
+ * @brief Associates a memory destination to a MDMA stream.
+ * @pre The stream must have been allocated using @p mdmaChannelAlloc().
+ * @post After use the stream can be released using @p mdmaChannelFree().
+ *
+ * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure
+ * @param[in] addr value to be written in the CDAR register
+ *
+ * @xclass
+ */
+#define mdmaChannelSetDestinationX(mdmachp, addr) do { \
+ (mdmachp)->channel->CDAR = (uint32_t)(addr); \
+} while (0)
+
+/**
+ * @brief Sets parameters related to the transaction size.
+ * @pre The stream must have been allocated using @p mdmaChannelAlloc().
+ * @post After use the stream can be released using @p mdmaChannelFree().
+ *
+ * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure
+ * @param[in] size number of bytes per block
+ * @param[in] n number of blocks repetitions
+ * @param[in] opt other option bits for the CBNDTR register
+ *
+ * @xclass
+ */
+#define mdmaChannelSetTransactionSizeX(mdmachp, size, n, opt) do { \
+ (mdmachp)->channel->CBNDTR = (uint32_t)STM32_MDMA_CBNDTR_BNDT(size) | \
+ (uint32_t)STM32_MDMA_CBNDTR_BRC(n) | \
+ (uint32_t)opt; \
+} while (0)
+
+/**
+ * @brief Programs the stream mode settings.
+ * @pre The stream must have been allocated using @p mdmaChannelAlloc().
+ * @post After use the stream can be released using @p mdmaChannelFree().
+ *
+ * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure
+ * @param[in] ctcr value to be written in the CTCR register
+ * @param[in] ccr value to be written in the CCR register
+ *
+ * @xclass
+ */
+#define mdmaChannelSetModeX(mdmachp, ctcr, ccr) do { \
+ (mdmachp)->channel->CTCR = (uint32_t)(ctcr); \
+ (mdmachp)->channel->CCR = (uint32_t)(ccr); \
+} while (0)
+
+/**
+ * @brief MDMA stream enable.
+ * @pre The stream must have been allocated using @p mdmaChannelAlloc().
+ * @post After use the stream can be released using @p mdmaChannelFree().
+ *
+ * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure
+ *
+ * @xclass
+ */
+#define mdmaChannelEnableX(mdmachp) do { \
+ (mdmachp)->channel->CCR |= STM32_MDMA_CCR_EN; \
+} while (0)
+
+/**
+ * @brief Channel enable check.
+ * @pre The stream must have been allocated using @p mdmaChannelAlloc().
+ * @post After use the stream can be released using @p mdmaChannelFree().
+ *
+ * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure
+ */
+#define mdmaChannelIsEnabled(mdmachp) \
+ (((mdmachp)->channel->CCR & STM32_MDMA_CCR_EN) != 0U)
+
+/**
+ * @brief MDMA stream interrupt sources clear.
+ * @pre The stream must have been allocated using @p mdmaChannelAlloc().
+ * @post After use the stream can be released using @p mdmaChannelFree().
+ *
+ * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure
+ *
+ * @xclass
+ */
+#define mdmaChannelClearInterruptX(mdmachp) do { \
+ (mdmachp)->channel->CIFCR = (STM32_MDMA_CIFCR_CTEIF | \
+ STM32_MDMA_CIFCR_CBRTIF | \
+ STM32_MDMA_CIFCR_CBRTIF | \
+ STM32_MDMA_CIFCR_CCTCIF | \
+ STM32_MDMA_CIFCR_CTEIF); \
+} while (0)
+
+/**
+ * @brief MDMA IRQ enable.
+ */
+#define mdma_irq_init() \
+ nvicEnableVector(STM32_MDMA_NUMBER, STM32_IRQ_MDMA_PRIORITY)
+
+/**
+ * @brief MDMA IRQ disable.
+ */
+#define mdma_irq_deinit() \
+ nvicDisableVector(STM32_MDMA_NUMBER)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void mdmaInit(void);
+ const stm32_mdma_channel_t *mdmaChannelAllocI(uint32_t id,
+ stm32_mdmaisr_t func,
+ void *param);
+ const stm32_mdma_channel_t *mdmaChannelAlloc(uint32_t id,
+ stm32_mdmaisr_t func,
+ void *param);
+ void mdmaChannelFreeI(const stm32_mdma_channel_t *mdmachp);
+ void mdmaChannelFree(const stm32_mdma_channel_t *mdmachp);
+ void mdmaChannelDisableX(const stm32_mdma_channel_t *mdmachp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32_MDMA_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OCTOSPIv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OCTOSPIv1/driver.mk
new file mode 100644
index 0000000..987220b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OCTOSPIv1/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_WSPI TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/OCTOSPIv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.c
new file mode 100644
index 0000000..c71e38a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.c
@@ -0,0 +1,464 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file OCTOSPIv1/hal_wspi_lld.c
+ * @brief STM32 WSPI subsystem low level driver source.
+ *
+ * @addtogroup WSPI
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/* Workarounds for bugs in ST headers.*/
+#if !defined(OCTOSPI_FCR_CTOF) && defined(OCTOSPI_FCR_TOF)
+#define OCTOSPI_FCR_CTOF OCTOSPI_FCR_TOF
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief OCTOSPI1 driver identifier.*/
+#if STM32_WSPI_USE_OCTOSPI1 || defined(__DOXYGEN__)
+WSPIDriver WSPID1;
+#endif
+
+/** @brief OCTOSPI2 driver identifier.*/
+#if STM32_WSPI_USE_OCTOSPI2 || defined(__DOXYGEN__)
+WSPIDriver WSPID2;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Waits for completion of previous operation.
+ */
+static inline void wspi_lld_sync(WSPIDriver *wspip) {
+
+ while ((wspip->ospi->SR & OCTOSPI_SR_BUSY) != 0U) {
+ }
+}
+
+/**
+ * @brief Shared service routine.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void wspi_lld_serve_dma_interrupt(WSPIDriver *wspip, uint32_t flags) {
+
+ (void)wspip;
+ (void)flags;
+
+ /* DMA errors handling.*/
+#if defined(STM32_WSPI_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_WSPI_DMA_ERROR_HOOK(wspip);
+ }
+#endif
+}
+
+/**
+ * @brief Shared service routine.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ */
+static void wspi_lld_serve_interrupt(WSPIDriver *wspip) {
+
+ /* Portable WSPI ISR code defined in the high level driver, note, it is
+ a macro.*/
+ _wspi_isr_code(wspip);
+
+ /* Stop everything, we need to give DMA enough time to complete the ongoing
+ operation. Race condition hidden here.*/
+ while (dmaStreamGetTransactionSize(wspip->dma) > 0U)
+ ;
+ dmaStreamDisable(wspip->dma);
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_WSPI_USE_OCTOSPI1 || defined(__DOXYGEN__)
+#if !defined(STM32_OCTOSPI1_SUPPRESS_ISR)
+#if !defined(STM32_OCTOSPI1_HANDLER)
+#error "STM32_OCTOSPI1_HANDLER not defined"
+#endif
+/**
+ * @brief STM32_OCTOSPI1_HANDLER interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_OCTOSPI1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ OCTOSPI1->FCR = OCTOSPI_FCR_CTEF | OCTOSPI_FCR_CTCF |
+ OCTOSPI_FCR_CSMF | OCTOSPI_FCR_CTOF;
+
+ wspi_lld_serve_interrupt(&WSPID1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_OCTOSPI1_SUPPRESS_ISR) */
+#endif /* STM32_WSPI_USE_OCTOSPI1 */
+
+#if STM32_WSPI_USE_OCTOSPI2 || defined(__DOXYGEN__)
+#if !defined(STM32_OCTOSPI2_SUPPRESS_ISR)
+#if !defined(STM32_OCTOSPI2_HANDLER)
+#error "STM32_OCTOSPI2_HANDLER not defined"
+#endif
+/**
+ * @brief STM32_OCTOSPI2_HANDLER interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_OCTOSPI2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ OCTOSPI2->FCR = OCTOSPI_FCR_CTEF | OCTOSPI_FCR_CTCF |
+ OCTOSPI_FCR_CSMF | OCTOSPI_FCR_CTOF;
+
+ wspi_lld_serve_interrupt(&WSPID2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_OCTOSPI2_SUPPRESS_ISR) */
+#endif /* STM32_WSPI_USE_OCTOSPI2 */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level WSPI driver initialization.
+ *
+ * @notapi
+ */
+void wspi_lld_init(void) {
+
+#if STM32_WSPI_USE_OCTOSPI1
+ wspiObjectInit(&WSPID1);
+ WSPID1.ospi = OCTOSPI1;
+ WSPID1.dma = NULL;
+ WSPID1.dmamode = STM32_DMA_CR_CHSEL(OCTOSPI1_DMA_STREAM) |
+ STM32_DMA_CR_PL(STM32_WSPI_OCTOSPI1_DMA_PRIORITY) |
+ STM32_DMA_CR_PSIZE_BYTE |
+ STM32_DMA_CR_MSIZE_BYTE |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ nvicEnableVector(STM32_OCTOSPI1_NUMBER, STM32_WSPI_OCTOSPI1_IRQ_PRIORITY);
+#endif
+
+#if STM32_WSPI_USE_OCTOSPI2
+ wspiObjectInit(&WSPID2);
+ WSPID2.ospi = OCTOSPI2;
+ WSPID2.dma = NULL;
+ WSPID2.dmamode = STM32_DMA_CR_CHSEL(OCTOSPI2_DMA_STREAM) |
+ STM32_DMA_CR_PL(STM32_WSPI_OCTOSPI2_DMA_PRIORITY) |
+ STM32_DMA_CR_PSIZE_BYTE |
+ STM32_DMA_CR_MSIZE_BYTE |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ nvicEnableVector(STM32_OCTOSPI2_NUMBER, STM32_WSPI_OCTOSPI2_IRQ_PRIORITY);
+#endif
+}
+
+/**
+ * @brief Configures and activates the WSPI peripheral.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @notapi
+ */
+void wspi_lld_start(WSPIDriver *wspip) {
+
+ /* If in stopped state then full initialization.*/
+ if (wspip->state == WSPI_STOP) {
+#if STM32_WSPI_USE_OCTOSPI1
+ if (&WSPID1 == wspip) {
+ wspip->dma = dmaStreamAllocI(STM32_WSPI_OCTOSPI1_DMA_STREAM,
+ STM32_WSPI_OCTOSPI1_DMA_IRQ_PRIORITY,
+ (stm32_dmaisr_t)wspi_lld_serve_dma_interrupt,
+ (void *)wspip);
+ osalDbgAssert(wspip->dma != NULL, "unable to allocate stream");
+ rccEnableOCTOSPI1(true);
+ dmaSetRequestSource(wspip->dma, STM32_DMAMUX1_OCTOSPI1);
+ }
+#endif
+
+#if STM32_WSPI_USE_OCTOSPI2
+ if (&WSPID2 == wspip) {
+ wspip->dma = dmaStreamAllocI(STM32_WSPI_OCTOSPI2_DMA_STREAM,
+ STM32_WSPI_OCTOSPI2_DMA_IRQ_PRIORITY,
+ (stm32_dmaisr_t)wspi_lld_serve_dma_interrupt,
+ (void *)wspip);
+ osalDbgAssert(wspip->dma != NULL, "unable to allocate stream");
+ rccEnableOCTOSPI2(true);
+ dmaSetRequestSource(wspip->dma, STM32_DMAMUX1_OCTOSPI2);
+ }
+#endif
+
+ /* Common initializations.*/
+ dmaStreamSetPeripheral(wspip->dma, &wspip->ospi->DR);
+ }
+
+ /* WSPI setup and enable.*/
+ wspip->ospi->DCR1 = wspip->config->dcr1;
+ wspip->ospi->DCR2 = wspip->config->dcr2 |
+ STM32_DCR2_PRESCALER(STM32_WSPI_OCTOSPI1_PRESCALER_VALUE - 1U);
+ wspip->ospi->DCR3 = wspip->config->dcr3;
+ wspip->ospi->CR = OCTOSPI_CR_TCIE | OCTOSPI_CR_DMAEN | OCTOSPI_CR_EN;
+ wspip->ospi->FCR = OCTOSPI_FCR_CTEF | OCTOSPI_FCR_CTCF |
+ OCTOSPI_FCR_CSMF | OCTOSPI_FCR_CTOF;
+}
+
+/**
+ * @brief Deactivates the WSPI peripheral.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @notapi
+ */
+void wspi_lld_stop(WSPIDriver *wspip) {
+
+ /* Waiting for the previous operation to complete, if any.*/
+ wspi_lld_sync(wspip);
+
+ /* If in ready state then disables the OCTOSPI clock.*/
+ if (wspip->state == WSPI_READY) {
+
+ /* WSPI disable.*/
+ wspip->ospi->CR = 0U;
+
+ /* Releasing the DMA.*/
+ dmaStreamFreeI(wspip->dma);
+ wspip->dma = NULL;
+
+ /* Stopping involved clocks.*/
+#if STM32_WSPI_USE_OCTOSPI1
+ if (&WSPID1 == wspip) {
+ rccDisableOCTOSPI1();
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Sends a command without data phase.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ *
+ * @notapi
+ */
+void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp) {
+
+#if 0 //STM32_USE_STM32_D1_WORKAROUND == TRUE
+ /* If it is a command without address and alternate phases then the command
+ is sent as an alternate byte, the command phase is suppressed.*/
+ if ((cmdp->cfg & (WSPI_CFG_ADDR_MODE_MASK | WSPI_CFG_ALT_MODE_MASK)) == 0U) {
+ /* The command mode field is copied in the alternate mode field. All
+ other fields are not used in this scenario.*/
+ wspip->ospi->DLR = 0U;
+ wspip->ospi->ABR = cmdp->cmd;
+ wspip->ospi->CCR = (cmdp->cfg & WSPI_CFG_CMD_MODE_MASK) << 6U;
+ return;
+ }
+#endif
+ wspip->ospi->CR &= ~OCTOSPI_CR_FMODE;
+ wspip->ospi->DLR = 0U;
+ wspip->ospi->TCR = cmdp->dummy;
+ wspip->ospi->CCR = cmdp->cfg;
+ wspip->ospi->ABR = cmdp->alt;
+ wspip->ospi->IR = cmdp->cmd;
+ if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) {
+ wspip->ospi->AR = cmdp->addr;
+ }
+
+ /* Waiting for the previous operation to complete.*/
+ wspi_lld_sync(wspip);
+}
+
+/**
+ * @brief Sends a command with data over the WSPI bus.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note If using DTR in 8 lines mode then the following restrictions
+ * apply:
+ * - Command size must be 0, 2 or 4 bytes.
+ * - Address must be even.
+ * - Alternate bytes size must be 0, 2 or 4 bytes.
+ * - Data size must be a multiple of two.
+ * .
+ * There is no check on the above conditions in order to keep the
+ * code efficient.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[in] n number of bytes to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @notapi
+ */
+void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, const uint8_t *txbuf) {
+
+ dmaStreamSetMemory0(wspip->dma, txbuf);
+ dmaStreamSetTransactionSize(wspip->dma, n);
+ dmaStreamSetMode(wspip->dma, wspip->dmamode | STM32_DMA_CR_DIR_M2P);
+
+ wspip->ospi->CR &= ~OCTOSPI_CR_FMODE;
+ wspip->ospi->DLR = n - 1U;
+ wspip->ospi->TCR = cmdp->dummy;
+ wspip->ospi->CCR = cmdp->cfg;
+ wspip->ospi->ABR = cmdp->alt;
+ wspip->ospi->IR = cmdp->cmd;
+ if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) {
+ wspip->ospi->AR = cmdp->addr;
+ }
+
+ dmaStreamEnable(wspip->dma);
+}
+
+/**
+ * @brief Sends a command then receives data over the WSPI bus.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note If using DTR in 8 lines mode then the following restrictions
+ * apply:
+ * - Command size must be 0, 2 or 4 bytes.
+ * - Address must be even.
+ * - Alternate bytes size must be 0, 2 or 4 bytes.
+ * - Data size must be a multiple of two.
+ * .
+ * There is no check on the above conditions in order to keep the
+ * code efficient.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[in] n number of bytes to send
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, uint8_t *rxbuf) {
+
+ dmaStreamSetMemory0(wspip->dma, rxbuf);
+ dmaStreamSetTransactionSize(wspip->dma, n);
+ dmaStreamSetMode(wspip->dma, wspip->dmamode | STM32_DMA_CR_DIR_P2M);
+
+ wspip->ospi->CR = (wspip->ospi->CR & ~OCTOSPI_CR_FMODE) | OCTOSPI_CR_FMODE_0;
+ wspip->ospi->DLR = n - 1U;
+ wspip->ospi->TCR = cmdp->dummy;
+ wspip->ospi->CCR = cmdp->cfg;
+ wspip->ospi->ABR = cmdp->alt;
+ wspip->ospi->IR = cmdp->cmd;
+ if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) {
+ wspip->ospi->AR = cmdp->addr;
+ }
+
+ dmaStreamEnable(wspip->dma);
+}
+
+#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Maps in memory space a WSPI flash device.
+ * @pre The memory flash device must be initialized appropriately
+ * before mapping it in memory space.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[out] addrp pointer to the memory start address of the mapped
+ * flash or @p NULL
+ *
+ * @notapi
+ */
+void wspi_lld_map_flash(WSPIDriver *wspip,
+ const wspi_command_t *cmdp,
+ uint8_t **addrp) {
+
+ /* Starting memory mapped mode using the passed parameters.*/
+ wspip->ospi->CR = OCTOSPI_CR_FMODE_1 | OCTOSPI_CR_FMODE_0 | OCTOSPI_CR_EN;
+ wspip->ospi->TCR = cmdp->dummy;
+ wspip->ospi->CCR = cmdp->cfg;
+ wspip->ospi->IR = cmdp->cmd;
+ wspip->ospi->ABR = 0U;
+ wspip->ospi->AR = 0U;
+ wspip->ospi->WTCR = 0U;
+ wspip->ospi->WCCR = 0U;
+ wspip->ospi->WIR = 0U;
+ wspip->ospi->WABR = 0U;
+
+ /* Mapped flash absolute base address.*/
+#if STM32_WSPI_USE_OCTOSPI1
+ if (&WSPID1 == wspip) {
+ if (addrp != NULL) {
+ *addrp = (uint8_t *)0x90000000U;
+ }
+ }
+#endif
+#if STM32_WSPI_USE_OCTOSPI2
+ if (&WSPID2 == wspip) {
+ if (addrp != NULL) {
+ *addrp = (uint8_t *)0x70000000U;
+ }
+ }
+#endif
+}
+
+/**
+ * @brief Unmaps from memory space a WSPI flash device.
+ * @post The memory flash device must be re-initialized for normal
+ * commands exchange.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @notapi
+ */
+void wspi_lld_unmap_flash(WSPIDriver *wspip) {
+
+ /* Aborting memory mapped mode.*/
+ wspip->ospi->CR |= OCTOSPI_CR_ABORT;
+ while ((wspip->ospi->CR & OCTOSPI_CR_ABORT) != 0U) {
+ }
+
+ /* Disabling memory mapped mode and re-enabling DMA and IRQs.*/
+ wspip->ospi->CR = OCTOSPI_CR_TCIE | OCTOSPI_CR_DMAEN | OCTOSPI_CR_EN;
+}
+#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */
+
+#endif /* HAL_USE_WSPI */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.h
new file mode 100644
index 0000000..35e5d80
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OCTOSPIv1/hal_wspi_lld.h
@@ -0,0 +1,334 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file OCTOSPIv1/hal_wspi_lld.h
+ * @brief STM32 WSPI subsystem low level driver header.
+ *
+ * @addtogroup WSPI
+ * @{
+ */
+
+#ifndef HAL_WSPI_LLD_H
+#define HAL_WSPI_LLD_H
+
+#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name WSPI implementation capabilities
+ * @{
+ */
+#define WSPI_SUPPORTS_MEMMAP TRUE
+#define WSPI_DEFAULT_CFG_MASKS TRUE
+/** @} */
+
+/**
+ * @name DCR1 register options
+ * @{
+ */
+#define STM32_DCR1_CK_MODE (1U << 0U)
+#define STM32_DCR1_FRCK_MODE (1U << 1U)
+#define STM32_DCR1_CSHT_MASK (7U << 8U)
+#define STM32_DCR1_CSHT(n) ((n) << 8U)
+#define STM32_DCR1_DEVSIZE_MASK (31U << 16U)
+#define STM32_DCR1_DEVSIZE(n) ((n) << 16U)
+#define STM32_DCR1_MTYP_MASK (7U << 16U)
+#define STM32_DCR1_MTYP(n) ((n) << 24U)
+/** @} */
+
+/**
+ * @name DCR2 register options
+ * @{
+ */
+#define STM32_DCR2_PRESCALER_MASK (255U << 0U)
+#define STM32_DCR2_PRESCALER(n) ((n) << 0U)
+#define STM32_DCR2_WRAPSIZE_MASK (7U << 16U)
+#define STM32_DCR2_WRAPSIZE(n) ((n) << 16U)
+
+/**
+ * @name DCR3 register options
+ * @{
+ */
+#define STM32_DCR3_MAXTRAN_MASK (255U << 0U)
+#define STM32_DCR3_MAXTRAN(n) ((n) << 0U)
+#define STM32_DCR3_CSBOUND_MASK (7U << 16U)
+#define STM32_DCR3_CSBOUND(n) ((n) << 16U)
+
+/**
+ * @name DCR4 register options
+ * @{
+ */
+#define STM32_DCR4_REFRESH_MASK (255U << 0U)
+#define STM32_DCR4_REFRESH(n) ((n) << 0U)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief WSPID1 driver enable switch.
+ * @details If set to @p TRUE the support for OCTOSPI1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_WSPI_USE_OCTOSPI1) || defined(__DOXYGEN__)
+#define STM32_WSPI_USE_OCTOSPI1 FALSE
+#endif
+
+/**
+ * @brief WSPID2 driver enable switch.
+ * @details If set to @p TRUE the support for OCTOSPI2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_WSPI_USE_OCTOSPI2) || defined(__DOXYGEN__)
+#define STM32_WSPI_USE_OCTOSPI2 FALSE
+#endif
+
+/**
+ * @brief OCTOSPI1 prescaler setting.
+ * @note This is the prescaler divider value 1..256. The maximum frequency
+ * varies depending on the STM32 model and operating conditions,
+ * find the details in the data sheet.
+ */
+#if !defined(STM32_WSPI_OCTOSPI1_PRESCALER_VALUE) || defined(__DOXYGEN__)
+#define STM32_WSPI_OCTOSPI1_PRESCALER_VALUE 1
+#endif
+
+/**
+ * @brief OCTOSPI2 prescaler setting.
+ * @note This is the prescaler divider value 1..256. The maximum frequency
+ * varies depending on the STM32 model and operating conditions,
+ * find the details in the data sheet.
+ */
+#if !defined(STM32_WSPI_OCTOSPI2_PRESCALER_VALUE) || defined(__DOXYGEN__)
+#define STM32_WSPI_OCTOSPI2_PRESCALER_VALUE 1
+#endif
+
+/**
+ * @brief OCTOSPI1 interrupt priority level setting.
+ */
+#if !defined(STM32_WSPI_OCTOSPI1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_WSPI_OCTOSPI1_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief OCTOSPI2 interrupt priority level setting.
+ */
+#if !defined(STM32_WSPI_OCTOSPI2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_WSPI_OCTOSPI2_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief OCTOSPI1 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_WSPI_OCTOSPI1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_WSPI_OCTOSPI1_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief OCTOSPI2 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_WSPI_OCTOSPI2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_WSPI_OCTOSPI2_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief OCTOSPI1 DMA interrupt priority level setting.
+ */
+#if !defined(STM32_WSPI_OCTOSPI1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_WSPI_OCTOSPI1_DMA_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief OCTOSPI2 DMA interrupt priority level setting.
+ */
+#if !defined(STM32_WSPI_OCTOSPI2_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_WSPI_OCTOSPI2_DMA_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief OCTOSPI DMA error hook.
+ */
+#if !defined(STM32_WSPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define STM32_WSPI_DMA_ERROR_HOOK(qspip) osalSysHalt("DMA failure")
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !defined(STM32_HAS_OCTOSPI1)
+#define STM32_HAS_OCTOSPI1 FALSE
+#endif
+
+#if !defined(STM32_HAS_OCTOSPI2)
+#define STM32_HAS_OCTOSPI2 FALSE
+#endif
+
+#if STM32_WSPI_USE_OCTOSPI1 && !STM32_HAS_OCTOSPI1
+#error "OCTOSPI1 not present in the selected device"
+#endif
+
+#if STM32_WSPI_USE_OCTOSPI2 && !STM32_HAS_OCTOSPI2
+#error "OCTOSPI2 not present in the selected device"
+#endif
+
+#if !STM32_WSPI_USE_OCTOSPI1 && !STM32_WSPI_USE_OCTOSPI2
+#error "WSPI driver activated but no OCTOSPI peripheral assigned"
+#endif
+
+/* Check on OCTOSPI prescaler setting.*/
+#if (STM32_WSPI_OCTOSPI1_PRESCALER_VALUE < 1) || \
+ (STM32_WSPI_OCTOSPI1_PRESCALER_VALUE > 256)
+#error "STM32_WSPI_OCTOSPI1_PRESCALER_VALUE not within 1..256"
+#endif
+
+/* Check on IRQ priorities.*/
+#if STM32_WSPI_USE_OCTOSPI1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to OCTOSPI1"
+#endif
+
+#if STM32_WSPI_USE_OCTOSPI2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to OCTOSPI2"
+#endif
+
+#if STM32_WSPI_USE_OCTOSPI1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI1_DMA_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to OCTOSPI1 DMA"
+#endif
+
+#if STM32_WSPI_USE_OCTOSPI2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI2_DMA_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to OCTOSPI2 DMA"
+#endif
+
+/* Check on the presence of the DMA channels settings in mcuconf.h.*/
+#if STM32_WSPI_USE_OCTOSPI1 && !defined(STM32_WSPI_OCTOSPI1_DMA_STREAM)
+#error "OCTOSPI1 DMA stream not defined"
+#endif
+
+#if STM32_WSPI_USE_OCTOSPI2 && !defined(STM32_WSPI_OCTOSPI2_DMA_STREAM)
+#error "OCTOSPI2 DMA stream not defined"
+#endif
+
+/* Check on the validity of the assigned DMA channels.*/
+#if STM32_WSPI_USE_OCTOSPI1 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_WSPI_OCTOSPI1_DMA_STREAM)
+#error "invalid DMA stream associated to OCTOSPI1"
+#endif
+
+#if STM32_WSPI_USE_OCTOSPI2 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_WSPI_OCTOSPI2_DMA_STREAM)
+#error "invalid DMA stream associated to OCTOSPI2"
+#endif
+
+/* Check on DMA channels priority.*/
+#if STM32_WSPI_USE_OCTOSPI1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to OCTOSPI1"
+#endif
+
+#if STM32_WSPI_USE_OCTOSPI2 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_WSPI_OCTOSPI2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to OCTOSPI2"
+#endif
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the WSPI configuration structure.
+ */
+#define wspi_lld_config_fields \
+ /* DCR1 register initialization data.*/ \
+ uint32_t dcr1; \
+ /* DCR2 register initialization data. The prescaler field is internally \
+ ORed to this field, leave it to zero.*/ \
+ uint32_t dcr2; \
+ /* DCR3 register initialization data.*/ \
+ uint32_t dcr3; \
+ /* DCR4 register initialization data.*/ \
+ uint32_t dcr4
+
+/**
+ * @brief Low level fields of the WSPI driver structure.
+ */
+#define wspi_lld_driver_fields \
+ /* Pointer to the OCTOSPIx registers block.*/ \
+ OCTOSPI_TypeDef *ospi; \
+ /* OCTOSPI DMA stream.*/ \
+ const stm32_dma_stream_t *dma; \
+ /* OCTOSPI DMA mode bit mask.*/ \
+ uint32_t dmamode
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (STM32_WSPI_USE_OCTOSPI1 == TRUE) && !defined(__DOXYGEN__)
+extern WSPIDriver WSPID1;
+#endif
+
+#if (STM32_WSPI_USE_OCTOSPI2 == TRUE) && !defined(__DOXYGEN__)
+extern WSPIDriver WSPID2;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void wspi_lld_init(void);
+ void wspi_lld_start(WSPIDriver *wspip);
+ void wspi_lld_stop(WSPIDriver *wspip);
+ void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp);
+ void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, const uint8_t *txbuf);
+ void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, uint8_t *rxbuf);
+#if WSPI_SUPPORTS_MEMMAP == TRUE
+ void wspi_lld_map_flash(WSPIDriver *wspip,
+ const wspi_command_t *cmdp,
+ uint8_t **addrp);
+ void wspi_lld_unmap_flash(WSPIDriver *wspip);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_WSPI */
+
+#endif /* HAL_WSPI_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OTGv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OTGv1/driver.mk
new file mode 100644
index 0000000..197c1d2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OTGv1/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_USB TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.c
new file mode 100644
index 0000000..0f48d1f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.c
@@ -0,0 +1,1265 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file OTGv1/hal_usb_lld.c
+ * @brief STM32 USB subsystem low level driver source.
+ *
+ * @addtogroup USB
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+
+#if HAL_USE_USB || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define TRDT_VALUE_FS 5
+#define TRDT_VALUE_HS 9
+
+#define EP0_MAX_INSIZE 64
+#define EP0_MAX_OUTSIZE 64
+
+#if STM32_OTG_STEPPING == 1
+#if defined(BOARD_OTG_NOVBUSSENS)
+#define GCCFG_INIT_VALUE (GCCFG_NOVBUSSENS | GCCFG_VBUSASEN | \
+ GCCFG_VBUSBSEN | GCCFG_PWRDWN)
+#else
+#define GCCFG_INIT_VALUE (GCCFG_VBUSASEN | GCCFG_VBUSBSEN | \
+ GCCFG_PWRDWN)
+#endif
+
+#elif STM32_OTG_STEPPING == 2
+#if defined(BOARD_OTG_NOVBUSSENS)
+#define GCCFG_INIT_VALUE GCCFG_PWRDWN
+#else
+#define GCCFG_INIT_VALUE (GCCFG_VBDEN | GCCFG_PWRDWN)
+#endif
+
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief OTG_FS driver identifier.*/
+#if STM32_USB_USE_OTG1 || defined(__DOXYGEN__)
+USBDriver USBD1;
+#endif
+
+/** @brief OTG_HS driver identifier.*/
+#if STM32_USB_USE_OTG2 || defined(__DOXYGEN__)
+USBDriver USBD2;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief EP0 state.
+ * @note It is an union because IN and OUT endpoints are never used at the
+ * same time for EP0.
+ */
+static union {
+ /**
+ * @brief IN EP0 state.
+ */
+ USBInEndpointState in;
+ /**
+ * @brief OUT EP0 state.
+ */
+ USBOutEndpointState out;
+} ep0_state;
+
+/**
+ * @brief Buffer for the EP0 setup packets.
+ */
+static uint8_t ep0setup_buffer[8];
+
+/**
+ * @brief EP0 initialization structure.
+ */
+static const USBEndpointConfig ep0config = {
+ USB_EP_MODE_TYPE_CTRL,
+ _usb_ep0setup,
+ _usb_ep0in,
+ _usb_ep0out,
+ 0x40,
+ 0x40,
+ &ep0_state.in,
+ &ep0_state.out,
+ 1,
+ ep0setup_buffer
+};
+
+#if STM32_USB_USE_OTG1
+static const stm32_otg_params_t fsparams = {
+ STM32_USB_OTG1_RX_FIFO_SIZE / 4,
+ STM32_OTG1_FIFO_MEM_SIZE,
+ STM32_OTG1_ENDPOINTS
+};
+#endif
+
+#if STM32_USB_USE_OTG2
+static const stm32_otg_params_t hsparams = {
+ STM32_USB_OTG2_RX_FIFO_SIZE / 4,
+ STM32_OTG2_FIFO_MEM_SIZE,
+ STM32_OTG2_ENDPOINTS
+};
+#endif
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static void otg_core_reset(USBDriver *usbp) {
+ stm32_otg_t *otgp = usbp->otg;
+
+ /* Wait AHB idle condition.*/
+ while ((otgp->GRSTCTL & GRSTCTL_AHBIDL) == 0)
+ ;
+
+ /* Core reset and delay of at least 3 PHY cycles.*/
+ otgp->GRSTCTL = GRSTCTL_CSRST;
+ osalSysPolledDelayX(12);
+ while ((otgp->GRSTCTL & GRSTCTL_CSRST) != 0)
+ ;
+
+ osalSysPolledDelayX(18);
+
+ /* Wait AHB idle condition again.*/
+ while ((otgp->GRSTCTL & GRSTCTL_AHBIDL) == 0)
+ ;
+}
+
+static void otg_disable_ep(USBDriver *usbp) {
+ stm32_otg_t *otgp = usbp->otg;
+ unsigned i;
+
+ for (i = 0; i <= usbp->otgparams->num_endpoints; i++) {
+
+ if ((otgp->ie[i].DIEPCTL & DIEPCTL_EPENA) != 0U) {
+ otgp->ie[i].DIEPCTL |= DIEPCTL_EPDIS;
+ }
+
+ if ((otgp->oe[i].DOEPCTL & DIEPCTL_EPENA) != 0U) {
+ otgp->oe[i].DOEPCTL |= DIEPCTL_EPDIS;
+ }
+
+ otgp->ie[i].DIEPINT = 0xFFFFFFFF;
+ otgp->oe[i].DOEPINT = 0xFFFFFFFF;
+ }
+ otgp->DAINTMSK = DAINTMSK_OEPM(0) | DAINTMSK_IEPM(0);
+}
+
+static void otg_rxfifo_flush(USBDriver *usbp) {
+ stm32_otg_t *otgp = usbp->otg;
+
+ otgp->GRSTCTL = GRSTCTL_RXFFLSH;
+ while ((otgp->GRSTCTL & GRSTCTL_RXFFLSH) != 0)
+ ;
+ /* Wait for 3 PHY Clocks.*/
+ osalSysPolledDelayX(18);
+}
+
+static void otg_txfifo_flush(USBDriver *usbp, uint32_t fifo) {
+ stm32_otg_t *otgp = usbp->otg;
+
+ otgp->GRSTCTL = GRSTCTL_TXFNUM(fifo) | GRSTCTL_TXFFLSH;
+ while ((otgp->GRSTCTL & GRSTCTL_TXFFLSH) != 0)
+ ;
+ /* Wait for 3 PHY Clocks.*/
+ osalSysPolledDelayX(18);
+}
+
+/**
+ * @brief Resets the FIFO RAM memory allocator.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+static void otg_ram_reset(USBDriver *usbp) {
+
+ usbp->pmnext = usbp->otgparams->rx_fifo_size;
+}
+
+/**
+ * @brief Allocates a block from the FIFO RAM memory.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] size size of the packet buffer to allocate in words
+ *
+ * @notapi
+ */
+static uint32_t otg_ram_alloc(USBDriver *usbp, size_t size) {
+ uint32_t next;
+
+ next = usbp->pmnext;
+ usbp->pmnext += size;
+ osalDbgAssert(usbp->pmnext <= usbp->otgparams->otg_ram_size,
+ "OTG FIFO memory overflow");
+ return next;
+}
+
+/**
+ * @brief Writes to a TX FIFO.
+ *
+ * @param[in] fifop pointer to the FIFO register
+ * @param[in] buf buffer where to copy the endpoint data
+ * @param[in] n maximum number of bytes to copy
+ *
+ * @notapi
+ */
+static void otg_fifo_write_from_buffer(volatile uint32_t *fifop,
+ const uint8_t *buf,
+ size_t n) {
+
+ osalDbgAssert(n > 0, "is zero");
+
+ while (true) {
+ *fifop = *((uint32_t *)buf);
+ if (n <= 4) {
+ break;
+ }
+ n -= 4;
+ buf += 4;
+ }
+}
+
+/**
+ * @brief Reads a packet from the RXFIFO.
+ *
+ * @param[in] fifop pointer to the FIFO register
+ * @param[out] buf buffer where to copy the endpoint data
+ * @param[in] n number of bytes to pull from the FIFO
+ * @param[in] max number of bytes to copy into the buffer
+ *
+ * @notapi
+ */
+static void otg_fifo_read_to_buffer(volatile uint32_t *fifop,
+ uint8_t *buf,
+ size_t n,
+ size_t max) {
+ uint32_t w = 0;
+ size_t i = 0;
+
+ while (i < n) {
+ if ((i & 3) == 0) {
+ w = *fifop;
+ }
+ if (i < max) {
+ *buf++ = (uint8_t)w;
+ w >>= 8;
+ }
+ i++;
+ }
+}
+
+/**
+ * @brief Incoming packets handler.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+static void otg_rxfifo_handler(USBDriver *usbp) {
+ uint32_t sts, cnt, ep;
+
+ /* Popping the event word out of the RX FIFO.*/
+ sts = usbp->otg->GRXSTSP;
+
+ /* Event details.*/
+ cnt = (sts & GRXSTSP_BCNT_MASK) >> GRXSTSP_BCNT_OFF;
+ ep = (sts & GRXSTSP_EPNUM_MASK) >> GRXSTSP_EPNUM_OFF;
+
+ switch (sts & GRXSTSP_PKTSTS_MASK) {
+ case GRXSTSP_SETUP_DATA:
+ otg_fifo_read_to_buffer(usbp->otg->FIFO[0], usbp->epc[ep]->setup_buf,
+ cnt, 8);
+ break;
+ case GRXSTSP_SETUP_COMP:
+ break;
+ case GRXSTSP_OUT_DATA:
+ otg_fifo_read_to_buffer(usbp->otg->FIFO[0],
+ usbp->epc[ep]->out_state->rxbuf,
+ cnt,
+ usbp->epc[ep]->out_state->rxsize -
+ usbp->epc[ep]->out_state->rxcnt);
+ usbp->epc[ep]->out_state->rxbuf += cnt;
+ usbp->epc[ep]->out_state->rxcnt += cnt;
+ break;
+ case GRXSTSP_OUT_COMP:
+ break;
+ case GRXSTSP_OUT_GLOBAL_NAK:
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * @brief Outgoing packets handler.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+static bool otg_txfifo_handler(USBDriver *usbp, usbep_t ep) {
+
+ /* The TXFIFO is filled until there is space and data to be transmitted.*/
+ while (true) {
+ uint32_t n;
+
+ /* Transaction end condition.*/
+ if (usbp->epc[ep]->in_state->txcnt >= usbp->epc[ep]->in_state->txsize) {
+#if 1
+ usbp->otg->DIEPEMPMSK &= ~DIEPEMPMSK_INEPTXFEM(ep);
+#endif
+ return true;
+ }
+
+ /* Number of bytes remaining in current transaction.*/
+ n = usbp->epc[ep]->in_state->txsize - usbp->epc[ep]->in_state->txcnt;
+ if (n > usbp->epc[ep]->in_maxsize)
+ n = usbp->epc[ep]->in_maxsize;
+
+ /* Checks if in the TXFIFO there is enough space to accommodate the
+ next packet.*/
+ if (((usbp->otg->ie[ep].DTXFSTS & DTXFSTS_INEPTFSAV_MASK) * 4) < n)
+ return false;
+
+#if STM32_USB_OTGFIFO_FILL_BASEPRI
+ __set_BASEPRI(CORTEX_PRIO_MASK(STM32_USB_OTGFIFO_FILL_BASEPRI));
+#endif
+ otg_fifo_write_from_buffer(usbp->otg->FIFO[ep],
+ usbp->epc[ep]->in_state->txbuf,
+ n);
+ usbp->epc[ep]->in_state->txbuf += n;
+ usbp->epc[ep]->in_state->txcnt += n;
+#if STM32_USB_OTGFIFO_FILL_BASEPRI
+ __set_BASEPRI(0);
+#endif
+ }
+}
+
+/**
+ * @brief Generic endpoint IN handler.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+static void otg_epin_handler(USBDriver *usbp, usbep_t ep) {
+ stm32_otg_t *otgp = usbp->otg;
+ uint32_t epint = otgp->ie[ep].DIEPINT;
+
+ otgp->ie[ep].DIEPINT = epint;
+
+ if (epint & DIEPINT_TOC) {
+ /* Timeouts not handled yet, not sure how to handle.*/
+ }
+ if ((epint & DIEPINT_XFRC) && (otgp->DIEPMSK & DIEPMSK_XFRCM)) {
+ /* Transmit transfer complete.*/
+ USBInEndpointState *isp = usbp->epc[ep]->in_state;
+
+ if (isp->txsize < isp->totsize) {
+ /* In case the transaction covered only part of the total transfer
+ then another transaction is immediately started in order to
+ cover the remaining.*/
+ isp->txsize = isp->totsize - isp->txsize;
+ isp->txcnt = 0;
+ osalSysLockFromISR();
+ usb_lld_start_in(usbp, ep);
+ osalSysUnlockFromISR();
+ }
+ else {
+ /* End on IN transfer.*/
+ _usb_isr_invoke_in_cb(usbp, ep);
+ }
+ }
+ if ((epint & DIEPINT_TXFE) &&
+ (otgp->DIEPEMPMSK & DIEPEMPMSK_INEPTXFEM(ep))) {
+ /* TX FIFO empty or emptying.*/
+ otg_txfifo_handler(usbp, ep);
+ }
+}
+
+/**
+ * @brief Generic endpoint OUT handler.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+static void otg_epout_handler(USBDriver *usbp, usbep_t ep) {
+ stm32_otg_t *otgp = usbp->otg;
+ uint32_t epint = otgp->oe[ep].DOEPINT;
+
+ /* Resets all EP IRQ sources.*/
+ otgp->oe[ep].DOEPINT = epint;
+
+ if ((epint & DOEPINT_STUP) && (otgp->DOEPMSK & DOEPMSK_STUPM)) {
+ /* Setup packets handling, setup packets are handled using a
+ specific callback.*/
+ _usb_isr_invoke_setup_cb(usbp, ep);
+ }
+
+ if ((epint & DOEPINT_XFRC) && (otgp->DOEPMSK & DOEPMSK_XFRCM)) {
+ USBOutEndpointState *osp;
+
+ /* OUT state structure pointer for this endpoint.*/
+ osp = usbp->epc[ep]->out_state;
+
+ /* EP0 requires special handling.*/
+ if (ep == 0) {
+
+#if defined(STM32_OTG_SEQUENCE_WORKAROUND)
+ /* If an OUT transaction end interrupt is processed while the state
+ machine is not in an OUT state then it is ignored, this is caused
+ on some devices (L4) apparently injecting spurious data complete
+ words in the RX FIFO.*/
+ if ((usbp->ep0state & USB_OUT_STATE) == 0)
+ return;
+#endif
+
+ /* In case the transaction covered only part of the total transfer
+ then another transaction is immediately started in order to
+ cover the remaining.*/
+ if (((osp->rxcnt % usbp->epc[ep]->out_maxsize) == 0) &&
+ (osp->rxsize < osp->totsize)) {
+ osp->rxsize = osp->totsize - osp->rxsize;
+ osp->rxcnt = 0;
+ osalSysLockFromISR();
+ usb_lld_start_out(usbp, ep);
+ osalSysUnlockFromISR();
+ return;
+ }
+ }
+
+ /* End on OUT transfer.*/
+ _usb_isr_invoke_out_cb(usbp, ep);
+ }
+}
+
+/**
+ * @brief Isochronous IN transfer failed handler.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+static void otg_isoc_in_failed_handler(USBDriver *usbp) {
+ usbep_t ep;
+ stm32_otg_t *otgp = usbp->otg;
+
+ for (ep = 0; ep <= usbp->otgparams->num_endpoints; ep++) {
+ if (((otgp->ie[ep].DIEPCTL & DIEPCTL_EPTYP_MASK) == DIEPCTL_EPTYP_ISO) &&
+ ((otgp->ie[ep].DIEPCTL & DIEPCTL_EPENA) != 0)) {
+ /* Endpoint enabled -> ISOC IN transfer failed */
+ /* Disable endpoint */
+ otgp->ie[ep].DIEPCTL |= (DIEPCTL_EPDIS | DIEPCTL_SNAK);
+ while (otgp->ie[ep].DIEPCTL & DIEPCTL_EPENA)
+ ;
+
+ /* Flush FIFO */
+ otg_txfifo_flush(usbp, ep);
+
+ /* Prepare data for next frame */
+ _usb_isr_invoke_in_cb(usbp, ep);
+
+ /* TX FIFO empty or emptying.*/
+ otg_txfifo_handler(usbp, ep);
+ }
+ }
+}
+
+/**
+ * @brief Isochronous OUT transfer failed handler.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+static void otg_isoc_out_failed_handler(USBDriver *usbp) {
+ usbep_t ep;
+ stm32_otg_t *otgp = usbp->otg;
+
+ for (ep = 0; ep <= usbp->otgparams->num_endpoints; ep++) {
+ if (((otgp->oe[ep].DOEPCTL & DOEPCTL_EPTYP_MASK) == DOEPCTL_EPTYP_ISO) &&
+ ((otgp->oe[ep].DOEPCTL & DOEPCTL_EPENA) != 0)) {
+ /* Endpoint enabled -> ISOC OUT transfer failed */
+ /* Disable endpoint */
+ /* CHTODO:: Core stucks here */
+ /*otgp->oe[ep].DOEPCTL |= (DOEPCTL_EPDIS | DOEPCTL_SNAK);
+ while (otgp->oe[ep].DOEPCTL & DOEPCTL_EPENA)
+ ;*/
+ /* Prepare transfer for next frame.*/
+ _usb_isr_invoke_out_cb(usbp, ep);
+ }
+ }
+}
+
+/**
+ * @brief OTG shared ISR.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+static void usb_lld_serve_interrupt(USBDriver *usbp) {
+ stm32_otg_t *otgp = usbp->otg;
+ uint32_t sts, src;
+
+ sts = otgp->GINTSTS;
+ sts &= otgp->GINTMSK;
+ otgp->GINTSTS = sts;
+
+ /* Reset interrupt handling.*/
+ if (sts & GINTSTS_USBRST) {
+ /* Default reset action.*/
+ _usb_reset(usbp);
+
+ /* Preventing execution of more handlers, the core has been reset.*/
+ return;
+ }
+
+ /* Wake-up handling.*/
+ if (sts & GINTSTS_WKUPINT) {
+ /* If clocks are gated off, turn them back on (may be the case if
+ coming out of suspend mode).*/
+ if (otgp->PCGCCTL & (PCGCCTL_STPPCLK | PCGCCTL_GATEHCLK)) {
+ /* Set to zero to un-gate the USB core clocks.*/
+ otgp->PCGCCTL &= ~(PCGCCTL_STPPCLK | PCGCCTL_GATEHCLK);
+ }
+
+ /* Clear the Remote Wake-up Signaling.*/
+ otgp->DCTL &= ~DCTL_RWUSIG;
+
+ _usb_wakeup(usbp);
+ }
+
+ /* Suspend handling.*/
+ if (sts & GINTSTS_USBSUSP) {
+ /* Stopping all ongoing transfers.*/
+ otg_disable_ep(usbp);
+
+ /* Default suspend action.*/
+ _usb_suspend(usbp);
+ }
+
+ /* Enumeration done.*/
+ if (sts & GINTSTS_ENUMDNE) {
+ /* Full or High speed timing selection.*/
+ if ((otgp->DSTS & DSTS_ENUMSPD_MASK) == DSTS_ENUMSPD_HS_480) {
+ otgp->GUSBCFG = (otgp->GUSBCFG & ~(GUSBCFG_TRDT_MASK)) |
+ GUSBCFG_TRDT(TRDT_VALUE_HS);
+ }
+ else {
+ otgp->GUSBCFG = (otgp->GUSBCFG & ~(GUSBCFG_TRDT_MASK)) |
+ GUSBCFG_TRDT(TRDT_VALUE_FS);
+ }
+ }
+
+ /* SOF interrupt handling.*/
+ if (sts & GINTSTS_SOF) {
+ _usb_isr_invoke_sof_cb(usbp);
+ }
+
+ /* Isochronous IN failed handling */
+ if (sts & GINTSTS_IISOIXFR) {
+ otg_isoc_in_failed_handler(usbp);
+ }
+
+ /* Isochronous OUT failed handling */
+ if (sts & GINTSTS_IISOOXFR) {
+ otg_isoc_out_failed_handler(usbp);
+ }
+
+ /* Performing the whole FIFO emptying in the ISR, it is advised to keep
+ this IRQ at a very low priority level.*/
+ if ((sts & GINTSTS_RXFLVL) != 0U) {
+ otg_rxfifo_handler(usbp);
+ }
+
+ /* IN/OUT endpoints event handling.*/
+ src = otgp->DAINT;
+ if (sts & GINTSTS_OEPINT) {
+ if (src & (1 << 16))
+ otg_epout_handler(usbp, 0);
+ if (src & (1 << 17))
+ otg_epout_handler(usbp, 1);
+ if (src & (1 << 18))
+ otg_epout_handler(usbp, 2);
+ if (src & (1 << 19))
+ otg_epout_handler(usbp, 3);
+#if USB_MAX_ENDPOINTS >= 4
+ if (src & (1 << 20))
+ otg_epout_handler(usbp, 4);
+#endif
+#if USB_MAX_ENDPOINTS >= 5
+ if (src & (1 << 21))
+ otg_epout_handler(usbp, 5);
+#endif
+#if USB_MAX_ENDPOINTS >= 6
+ if (src & (1 << 22))
+ otg_epout_handler(usbp, 6);
+#endif
+#if USB_MAX_ENDPOINTS >= 7
+ if (src & (1 << 23))
+ otg_epout_handler(usbp, 7);
+#endif
+#if USB_MAX_ENDPOINTS >= 8
+ if (src & (1 << 24))
+ otg_epout_handler(usbp, 8);
+#endif
+ }
+ if (sts & GINTSTS_IEPINT) {
+ if (src & (1 << 0))
+ otg_epin_handler(usbp, 0);
+ if (src & (1 << 1))
+ otg_epin_handler(usbp, 1);
+ if (src & (1 << 2))
+ otg_epin_handler(usbp, 2);
+ if (src & (1 << 3))
+ otg_epin_handler(usbp, 3);
+#if USB_MAX_ENDPOINTS >= 4
+ if (src & (1 << 4))
+ otg_epin_handler(usbp, 4);
+#endif
+#if USB_MAX_ENDPOINTS >= 5
+ if (src & (1 << 5))
+ otg_epin_handler(usbp, 5);
+#endif
+#if USB_MAX_ENDPOINTS >= 6
+ if (src & (1 << 6))
+ otg_epin_handler(usbp, 6);
+#endif
+#if USB_MAX_ENDPOINTS >= 7
+ if (src & (1 << 7))
+ otg_epin_handler(usbp, 7);
+#endif
+#if USB_MAX_ENDPOINTS >= 8
+ if (src & (1 << 8))
+ otg_epin_handler(usbp, 8);
+#endif
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_USB_USE_OTG1 || defined(__DOXYGEN__)
+/**
+ * @brief OTG1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_OTG1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ usb_lld_serve_interrupt(&USBD1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if STM32_USB_USE_OTG2 || defined(__DOXYGEN__)
+/**
+ * @brief OTG2 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_OTG2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ usb_lld_serve_interrupt(&USBD2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level USB driver initialization.
+ *
+ * @notapi
+ */
+void usb_lld_init(void) {
+
+ /* Driver initialization.*/
+#if STM32_USB_USE_OTG1
+ usbObjectInit(&USBD1);
+ USBD1.otg = OTG_FS;
+ USBD1.otgparams = &fsparams;
+
+#endif
+
+#if STM32_USB_USE_OTG2
+ usbObjectInit(&USBD2);
+ USBD2.otg = OTG_HS;
+ USBD2.otgparams = &hsparams;
+#endif
+}
+
+/**
+ * @brief Configures and activates the USB peripheral.
+ * @note Starting the OTG cell can be a slow operation carried out with
+ * interrupts disabled, perform it before starting time-critical
+ * operations.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+void usb_lld_start(USBDriver *usbp) {
+ stm32_otg_t *otgp = usbp->otg;
+
+ if (usbp->state == USB_STOP) {
+ /* Clock activation.*/
+
+#if STM32_USB_USE_OTG1
+ if (&USBD1 == usbp) {
+ /* OTG FS clock enable and reset.*/
+ rccEnableOTG_FS(true);
+ rccResetOTG_FS();
+
+ /* Enables IRQ vector.*/
+ nvicEnableVector(STM32_OTG1_NUMBER, STM32_USB_OTG1_IRQ_PRIORITY);
+
+ /* - Forced device mode.
+ - USB turn-around time = TRDT_VALUE_FS.
+ - Full Speed 1.1 PHY.*/
+ otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE_FS) |
+ GUSBCFG_PHYSEL;
+
+ /* 48MHz 1.1 PHY.*/
+ otgp->DCFG = 0x02200000 | DCFG_DSPD_FS11;
+ }
+#endif
+
+#if STM32_USB_USE_OTG2
+ if (&USBD2 == usbp) {
+ /* OTG HS clock enable and reset.*/
+ rccEnableOTG_HS(true);
+ rccResetOTG_HS();
+
+ /* ULPI clock is managed depending on the presence of an external
+ PHY.*/
+#if defined(BOARD_OTG2_USES_ULPI)
+ rccEnableOTG_HSULPI(true);
+#else
+ /* Workaround for the problem described here:
+ http://forum.chibios.org/phpbb/viewtopic.php?f=16&t=1798.*/
+ rccDisableOTG_HSULPI();
+#endif
+
+ /* Enables IRQ vector.*/
+ nvicEnableVector(STM32_OTG2_NUMBER, STM32_USB_OTG2_IRQ_PRIORITY);
+
+ /* - Forced device mode.
+ - USB turn-around time = TRDT_VALUE_HS or TRDT_VALUE_FS.*/
+#if defined(BOARD_OTG2_USES_ULPI)
+ /* High speed ULPI PHY.*/
+ otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE_HS) |
+ GUSBCFG_SRPCAP | GUSBCFG_HNPCAP;
+#else
+ otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE_FS) |
+ GUSBCFG_PHYSEL;
+#endif
+
+#if defined(BOARD_OTG2_USES_ULPI)
+#if STM32_USE_USB_OTG2_HS
+ /* USB 2.0 High Speed PHY in HS mode.*/
+ otgp->DCFG = 0x02200000 | DCFG_DSPD_HS;
+#else
+ /* USB 2.0 High Speed PHY in FS mode.*/
+ otgp->DCFG = 0x02200000 | DCFG_DSPD_HS_FS;
+#endif
+#else
+ /* 48MHz 1.1 PHY.*/
+ otgp->DCFG = 0x02200000 | DCFG_DSPD_FS11;
+#endif
+ }
+#endif
+
+ /* PHY enabled.*/
+ otgp->PCGCCTL = 0;
+
+ /* VBUS sensing and transceiver enabled.*/
+ otgp->GOTGCTL = GOTGCTL_BVALOEN | GOTGCTL_BVALOVAL;
+
+#if defined(BOARD_OTG2_USES_ULPI)
+#if STM32_USB_USE_OTG1
+ if (&USBD1 == usbp) {
+ otgp->GCCFG = GCCFG_INIT_VALUE;
+ }
+#endif
+
+#if STM32_USB_USE_OTG2
+ if (&USBD2 == usbp) {
+ otgp->GCCFG = 0;
+ }
+#endif
+#else
+ otgp->GCCFG = GCCFG_INIT_VALUE;
+#endif
+
+ /* Soft core reset.*/
+ otg_core_reset(usbp);
+
+ /* Interrupts on TXFIFOs half empty.*/
+ otgp->GAHBCFG = 0;
+
+ /* Endpoints re-initialization.*/
+ otg_disable_ep(usbp);
+
+ /* Clear all pending Device Interrupts, only the USB Reset interrupt
+ is required initially.*/
+ otgp->DIEPMSK = 0;
+ otgp->DOEPMSK = 0;
+ otgp->DAINTMSK = 0;
+ if (usbp->config->sof_cb == NULL)
+ otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM | GINTMSK_USBSUSPM |
+ GINTMSK_ESUSPM | GINTMSK_SRQM | GINTMSK_WKUM |
+ GINTMSK_IISOIXFRM | GINTMSK_IISOOXFRM;
+ else
+ otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM | GINTMSK_USBSUSPM |
+ GINTMSK_ESUSPM | GINTMSK_SRQM | GINTMSK_WKUM |
+ GINTMSK_IISOIXFRM | GINTMSK_IISOOXFRM |
+ GINTMSK_SOFM;
+
+ /* Clears all pending IRQs, if any. */
+ otgp->GINTSTS = 0xFFFFFFFF;
+
+ /* Global interrupts enable.*/
+ otgp->GAHBCFG |= GAHBCFG_GINTMSK;
+ }
+}
+
+/**
+ * @brief Deactivates the USB peripheral.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+void usb_lld_stop(USBDriver *usbp) {
+ stm32_otg_t *otgp = usbp->otg;
+
+ /* If in ready state then disables the USB clock.*/
+ if (usbp->state != USB_STOP) {
+
+ /* Disabling all endpoints in case the driver has been stopped while
+ active.*/
+ otg_disable_ep(usbp);
+
+ otgp->DAINTMSK = 0;
+ otgp->GAHBCFG = 0;
+ otgp->GCCFG = 0;
+
+#if STM32_USB_USE_OTG1
+ if (&USBD1 == usbp) {
+ nvicDisableVector(STM32_OTG1_NUMBER);
+ rccDisableOTG_FS();
+ }
+#endif
+
+#if STM32_USB_USE_OTG2
+ if (&USBD2 == usbp) {
+ nvicDisableVector(STM32_OTG2_NUMBER);
+ rccDisableOTG_HS();
+#if defined(BOARD_OTG2_USES_ULPI)
+ rccDisableOTG_HSULPI()
+#endif
+ }
+#endif
+ }
+}
+
+/**
+ * @brief USB low level reset routine.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+void usb_lld_reset(USBDriver *usbp) {
+ unsigned i;
+ stm32_otg_t *otgp = usbp->otg;
+
+ /* Flush the Tx FIFO.*/
+ otg_txfifo_flush(usbp, 0);
+
+ /* Endpoint interrupts all disabled and cleared.*/
+ otgp->DIEPEMPMSK = 0;
+ otgp->DAINTMSK = DAINTMSK_OEPM(0) | DAINTMSK_IEPM(0);
+
+ /* All endpoints in NAK mode, interrupts cleared.*/
+ for (i = 0; i <= usbp->otgparams->num_endpoints; i++) {
+ otgp->ie[i].DIEPCTL = DIEPCTL_SNAK;
+ otgp->oe[i].DOEPCTL = DOEPCTL_SNAK;
+ otgp->ie[i].DIEPINT = 0xFFFFFFFF;
+ otgp->oe[i].DOEPINT = 0xFFFFFFFF;
+ }
+
+ /* Resets the FIFO memory allocator.*/
+ otg_ram_reset(usbp);
+
+ /* Receive FIFO size initialization, the address is always zero.*/
+ otgp->GRXFSIZ = usbp->otgparams->rx_fifo_size;
+ otg_rxfifo_flush(usbp);
+
+ /* Resets the device address to zero.*/
+ otgp->DCFG = (otgp->DCFG & ~DCFG_DAD_MASK) | DCFG_DAD(0);
+
+ /* Enables also EP-related interrupt sources.*/
+ otgp->GINTMSK |= GINTMSK_RXFLVLM | GINTMSK_OEPM | GINTMSK_IEPM;
+ otgp->DIEPMSK = DIEPMSK_TOCM | DIEPMSK_XFRCM;
+ otgp->DOEPMSK = DOEPMSK_STUPM | DOEPMSK_XFRCM;
+
+ /* EP0 initialization, it is a special case.*/
+ usbp->epc[0] = &ep0config;
+ otgp->oe[0].DOEPTSIZ = DOEPTSIZ_STUPCNT(3);
+ otgp->oe[0].DOEPCTL = DOEPCTL_SD0PID | DOEPCTL_USBAEP | DOEPCTL_EPTYP_CTRL |
+ DOEPCTL_MPSIZ(ep0config.out_maxsize);
+ otgp->ie[0].DIEPTSIZ = 0;
+ otgp->ie[0].DIEPCTL = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_CTRL |
+ DIEPCTL_TXFNUM(0) | DIEPCTL_MPSIZ(ep0config.in_maxsize);
+ otgp->DIEPTXF0 = DIEPTXF_INEPTXFD(ep0config.in_maxsize / 4) |
+ DIEPTXF_INEPTXSA(otg_ram_alloc(usbp,
+ ep0config.in_maxsize / 4));
+}
+
+/**
+ * @brief Sets the USB address.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+void usb_lld_set_address(USBDriver *usbp) {
+ stm32_otg_t *otgp = usbp->otg;
+
+ otgp->DCFG = (otgp->DCFG & ~DCFG_DAD_MASK) | DCFG_DAD(usbp->address);
+}
+
+/**
+ * @brief Enables an endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
+ uint32_t ctl, fsize;
+ stm32_otg_t *otgp = usbp->otg;
+
+ /* IN and OUT common parameters.*/
+ switch (usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) {
+ case USB_EP_MODE_TYPE_CTRL:
+ ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_CTRL;
+ break;
+ case USB_EP_MODE_TYPE_ISOC:
+ ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_ISO;
+ break;
+ case USB_EP_MODE_TYPE_BULK:
+ ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_BULK;
+ break;
+ case USB_EP_MODE_TYPE_INTR:
+ ctl = DIEPCTL_SD0PID | DIEPCTL_USBAEP | DIEPCTL_EPTYP_INTR;
+ break;
+ default:
+ return;
+ }
+
+ /* OUT endpoint activation or deactivation.*/
+ otgp->oe[ep].DOEPTSIZ = 0;
+ if (usbp->epc[ep]->out_state != NULL) {
+ otgp->oe[ep].DOEPCTL = ctl | DOEPCTL_MPSIZ(usbp->epc[ep]->out_maxsize);
+ otgp->DAINTMSK |= DAINTMSK_OEPM(ep);
+ }
+ else {
+ otgp->oe[ep].DOEPCTL &= ~DOEPCTL_USBAEP;
+ otgp->DAINTMSK &= ~DAINTMSK_OEPM(ep);
+ }
+
+ /* IN endpoint activation or deactivation.*/
+ otgp->ie[ep].DIEPTSIZ = 0;
+ if (usbp->epc[ep]->in_state != NULL) {
+ /* FIFO allocation for the IN endpoint.*/
+ fsize = usbp->epc[ep]->in_maxsize / 4;
+ if (usbp->epc[ep]->in_multiplier > 1)
+ fsize *= usbp->epc[ep]->in_multiplier;
+ otgp->DIEPTXF[ep - 1] = DIEPTXF_INEPTXFD(fsize) |
+ DIEPTXF_INEPTXSA(otg_ram_alloc(usbp, fsize));
+ otg_txfifo_flush(usbp, ep);
+
+ otgp->ie[ep].DIEPCTL = ctl |
+ DIEPCTL_TXFNUM(ep) |
+ DIEPCTL_MPSIZ(usbp->epc[ep]->in_maxsize);
+ otgp->DAINTMSK |= DAINTMSK_IEPM(ep);
+ }
+ else {
+ otgp->DIEPTXF[ep - 1] = 0x02000400; /* Reset value.*/
+ otg_txfifo_flush(usbp, ep);
+ otgp->ie[ep].DIEPCTL &= ~DIEPCTL_USBAEP;
+ otgp->DAINTMSK &= ~DAINTMSK_IEPM(ep);
+ }
+}
+
+/**
+ * @brief Disables all the active endpoints except the endpoint zero.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+void usb_lld_disable_endpoints(USBDriver *usbp) {
+
+ /* Resets the FIFO memory allocator.*/
+ otg_ram_reset(usbp);
+
+ /* Disabling all endpoints.*/
+ otg_disable_ep(usbp);
+}
+
+/**
+ * @brief Returns the status of an OUT endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @return The endpoint status.
+ * @retval EP_STATUS_DISABLED The endpoint is not active.
+ * @retval EP_STATUS_STALLED The endpoint is stalled.
+ * @retval EP_STATUS_ACTIVE The endpoint is active.
+ *
+ * @notapi
+ */
+usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) {
+ uint32_t ctl;
+
+ (void)usbp;
+
+ ctl = usbp->otg->oe[ep].DOEPCTL;
+ if (!(ctl & DOEPCTL_USBAEP))
+ return EP_STATUS_DISABLED;
+ if (ctl & DOEPCTL_STALL)
+ return EP_STATUS_STALLED;
+ return EP_STATUS_ACTIVE;
+}
+
+/**
+ * @brief Returns the status of an IN endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @return The endpoint status.
+ * @retval EP_STATUS_DISABLED The endpoint is not active.
+ * @retval EP_STATUS_STALLED The endpoint is stalled.
+ * @retval EP_STATUS_ACTIVE The endpoint is active.
+ *
+ * @notapi
+ */
+usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) {
+ uint32_t ctl;
+
+ (void)usbp;
+
+ ctl = usbp->otg->ie[ep].DIEPCTL;
+ if (!(ctl & DIEPCTL_USBAEP))
+ return EP_STATUS_DISABLED;
+ if (ctl & DIEPCTL_STALL)
+ return EP_STATUS_STALLED;
+ return EP_STATUS_ACTIVE;
+}
+
+/**
+ * @brief Reads a setup packet from the dedicated packet buffer.
+ * @details This function must be invoked in the context of the @p setup_cb
+ * callback in order to read the received setup packet.
+ * @pre In order to use this function the endpoint must have been
+ * initialized as a control endpoint.
+ * @post The endpoint is ready to accept another packet.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[out] buf buffer where to copy the packet data
+ *
+ * @notapi
+ */
+void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) {
+
+ memcpy(buf, usbp->epc[ep]->setup_buf, 8);
+}
+
+/**
+ * @brief Starts a receive operation on an OUT endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
+ uint32_t pcnt, rxsize;
+ USBOutEndpointState *osp = usbp->epc[ep]->out_state;
+
+ /* Transfer initialization.*/
+ osp->totsize = osp->rxsize;
+ if ((ep == 0) && (osp->rxsize > EP0_MAX_OUTSIZE))
+ osp->rxsize = EP0_MAX_OUTSIZE;
+
+ /* Transaction size is rounded to a multiple of packet size because the
+ following requirement in the RM:
+ "For OUT transfers, the transfer size field in the endpoint's transfer
+ size register must be a multiple of the maximum packet size of the
+ endpoint, adjusted to the Word boundary".*/
+ pcnt = (osp->rxsize + usbp->epc[ep]->out_maxsize - 1U) /
+ usbp->epc[ep]->out_maxsize;
+ rxsize = (pcnt * usbp->epc[ep]->out_maxsize + 3U) & 0xFFFFFFFCU;
+
+ /*Setting up transaction parameters in DOEPTSIZ.*/
+ usbp->otg->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) |
+ DOEPTSIZ_XFRSIZ(rxsize);
+
+ /* Special case of isochronous endpoint.*/
+ if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) {
+ /* Odd/even bit toggling for isochronous endpoint.*/
+ if (usbp->otg->DSTS & DSTS_FNSOF_ODD)
+ usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SEVNFRM;
+ else
+ usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SODDFRM;
+ }
+
+ /* Starting operation.*/
+ usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_EPENA | DOEPCTL_CNAK;
+}
+
+/**
+ * @brief Starts a transmit operation on an IN endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
+ USBInEndpointState *isp = usbp->epc[ep]->in_state;
+
+ /* Transfer initialization.*/
+ isp->totsize = isp->txsize;
+ if (isp->txsize == 0) {
+ /* Special case, sending zero size packet.*/
+ usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFRSIZ(0);
+ }
+ else {
+ if ((ep == 0) && (isp->txsize > EP0_MAX_INSIZE))
+ isp->txsize = EP0_MAX_INSIZE;
+
+ /* Normal case.*/
+ uint32_t pcnt = (isp->txsize + usbp->epc[ep]->in_maxsize - 1) /
+ usbp->epc[ep]->in_maxsize;
+ /* CHTODO: Support more than one packet per frame for isochronous transfers.*/
+ usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_MCNT(1) | DIEPTSIZ_PKTCNT(pcnt) |
+ DIEPTSIZ_XFRSIZ(isp->txsize);
+ }
+
+ /* Special case of isochronous endpoint.*/
+ if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) {
+ /* Odd/even bit toggling.*/
+ if (usbp->otg->DSTS & DSTS_FNSOF_ODD)
+ usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_SEVNFRM;
+ else
+ usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_SODDFRM;
+ }
+
+ /* Starting operation.*/
+ usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_EPENA | DIEPCTL_CNAK;
+ usbp->otg->DIEPEMPMSK |= DIEPEMPMSK_INEPTXFEM(ep);
+}
+
+/**
+ * @brief Brings an OUT endpoint in the stalled state.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) {
+
+ usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_STALL;
+}
+
+/**
+ * @brief Brings an IN endpoint in the stalled state.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) {
+
+ usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_STALL;
+}
+
+/**
+ * @brief Brings an OUT endpoint in the active state.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) {
+
+ usbp->otg->oe[ep].DOEPCTL &= ~DOEPCTL_STALL;
+}
+
+/**
+ * @brief Brings an IN endpoint in the active state.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) {
+
+ usbp->otg->ie[ep].DIEPCTL &= ~DIEPCTL_STALL;
+}
+
+#endif /* HAL_USE_USB */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.h
new file mode 100644
index 0000000..69a5ab6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OTGv1/hal_usb_lld.h
@@ -0,0 +1,604 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file OTGv1/hal_usb_lld.h
+ * @brief STM32 USB subsystem low level driver header.
+ *
+ * @addtogroup USB
+ * @{
+ */
+
+#ifndef HAL_USB_LLD_H
+#define HAL_USB_LLD_H
+
+#if HAL_USE_USB || defined(__DOXYGEN__)
+
+#include "stm32_otg.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Status stage handling method.
+ */
+#define USB_EP0_STATUS_STAGE USB_EP0_STATUS_STAGE_SW
+
+/**
+ * @brief The address can be changed immediately upon packet reception.
+ */
+#define USB_SET_ADDRESS_MODE USB_EARLY_SET_ADDRESS
+
+/**
+ * @brief Method for set address acknowledge.
+ */
+#define USB_SET_ADDRESS_ACK_HANDLING USB_SET_ADDRESS_ACK_SW
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief OTG1 driver enable switch.
+ * @details If set to @p TRUE the support for OTG_FS is included.
+ * @note The default is @p FALSE
+ */
+#if !defined(STM32_USB_USE_OTG1) || defined(__DOXYGEN__)
+#define STM32_USB_USE_OTG1 FALSE
+#endif
+
+/**
+ * @brief OTG2 driver enable switch.
+ * @details If set to @p TRUE the support for OTG_HS is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_USB_USE_OTG2) || defined(__DOXYGEN__)
+#define STM32_USB_USE_OTG2 FALSE
+#endif
+
+/**
+ * @brief OTG1 interrupt priority level setting.
+ */
+#if !defined(STM32_USB_OTG1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_USB_OTG1_IRQ_PRIORITY 14
+#endif
+
+/**
+ * @brief OTG2 interrupt priority level setting.
+ */
+#if !defined(STM32_USB_OTG2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_USB_OTG2_IRQ_PRIORITY 14
+#endif
+
+/**
+ * @brief OTG1 RX shared FIFO size.
+ * @note Must be a multiple of 4.
+ */
+#if !defined(STM32_USB_OTG1_RX_FIFO_SIZE) || defined(__DOXYGEN__)
+#define STM32_USB_OTG1_RX_FIFO_SIZE 512
+#endif
+
+/**
+ * @brief OTG2 RX shared FIFO size.
+ * @note Must be a multiple of 4.
+ */
+#if !defined(STM32_USB_OTG2_RX_FIFO_SIZE) || defined(__DOXYGEN__)
+#define STM32_USB_OTG2_RX_FIFO_SIZE 1024
+#endif
+
+/**
+ * @brief Enables HS mode on OTG2 else FS mode.
+ * @note The default is @p TRUE.
+ * @note Has effect only if @p BOARD_OTG2_USES_ULPI is defined.
+ */
+#if !defined(STM32_USE_USB_OTG2_HS) || defined(__DOXYGEN__)
+#define STM32_USE_USB_OTG2_HS TRUE
+#endif
+
+/**
+ * @brief Exception priority level during TXFIFOs operations.
+ * @note Because an undocumented silicon behavior the operation of
+ * copying a packet into a TXFIFO must not be interrupted by
+ * any other operation on the OTG peripheral.
+ * This parameter represents the priority mask during copy
+ * operations. The default value only allows to call USB
+ * functions from callbacks invoked from USB ISR handlers.
+ * If you need to invoke USB functions from other handlers
+ * then raise this priority mast to the same level of the
+ * handler you need to use.
+ * @note The value zero means disabled, when disabled calling USB
+ * functions is only safe from thread level or from USB
+ * callbacks.
+ */
+#if !defined(STM32_USB_OTGFIFO_FILL_BASEPRI) || defined(__DOXYGEN__)
+#define STM32_USB_OTGFIFO_FILL_BASEPRI 0
+#endif
+
+/**
+ * @brief Host wake-up procedure duration.
+ */
+#if !defined(STM32_USB_HOST_WAKEUP_DURATION) || defined(__DOXYGEN__)
+#define STM32_USB_HOST_WAKEUP_DURATION 2
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks.*/
+#if !defined(STM32_OTG_STEPPING)
+#error "STM32_OTG_STEPPING not defined in registry"
+#endif
+
+#if (STM32_OTG_STEPPING < 1) || (STM32_OTG_STEPPING > 2)
+#error "unsupported STM32_OTG_STEPPING"
+#endif
+
+#if !defined(STM32_HAS_OTG1) || !defined(STM32_HAS_OTG2)
+#error "STM32_HAS_OTGx not defined in registry"
+#endif
+
+#if STM32_HAS_OTG1 && !defined(STM32_OTG1_ENDPOINTS)
+#error "STM32_OTG1_ENDPOINTS not defined in registry"
+#endif
+
+#if STM32_HAS_OTG2 && !defined(STM32_OTG2_ENDPOINTS)
+#error "STM32_OTG2_ENDPOINTS not defined in registry"
+#endif
+
+#if STM32_HAS_OTG1 && !defined(STM32_OTG1_FIFO_MEM_SIZE)
+#error "STM32_OTG1_FIFO_MEM_SIZE not defined in registry"
+#endif
+
+#if STM32_HAS_OTG2 && !defined(STM32_OTG2_FIFO_MEM_SIZE)
+#error "STM32_OTG2_FIFO_MEM_SIZE not defined in registry"
+#endif
+
+#if (STM32_USB_USE_OTG1 && !defined(STM32_OTG1_HANDLER)) || \
+ (STM32_USB_USE_OTG2 && !defined(STM32_OTG2_HANDLER))
+#error "STM32_OTGx_HANDLER not defined in registry"
+#endif
+
+#if (STM32_USB_USE_OTG1 && !defined(STM32_OTG1_NUMBER)) || \
+ (STM32_USB_USE_OTG2 && !defined(STM32_OTG2_NUMBER))
+#error "STM32_OTGx_NUMBER not defined in registry"
+#endif
+
+/**
+ * @brief Maximum endpoint address.
+ */
+#if (STM32_HAS_OTG2 && STM32_USB_USE_OTG2) || defined(__DOXYGEN__)
+#if (STM32_OTG1_ENDPOINTS < STM32_OTG2_ENDPOINTS) || defined(__DOXYGEN__)
+#define USB_MAX_ENDPOINTS STM32_OTG2_ENDPOINTS
+#else
+#define USB_MAX_ENDPOINTS STM32_OTG1_ENDPOINTS
+#endif
+#else
+#define USB_MAX_ENDPOINTS STM32_OTG1_ENDPOINTS
+#endif
+
+#if STM32_USB_USE_OTG1 && !STM32_HAS_OTG1
+#error "OTG1 not present in the selected device"
+#endif
+
+#if STM32_USB_USE_OTG2 && !STM32_HAS_OTG2
+#error "OTG2 not present in the selected device"
+#endif
+
+#if !STM32_USB_USE_OTG1 && !STM32_USB_USE_OTG2
+#error "USB driver activated but no USB peripheral assigned"
+#endif
+
+#if STM32_USB_USE_OTG1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_USB_OTG1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to OTG1"
+#endif
+
+#if STM32_USB_USE_OTG2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_USB_OTG2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to OTG2"
+#endif
+
+#if (STM32_USB_OTG1_RX_FIFO_SIZE & 3) != 0
+#error "OTG1 RX FIFO size must be a multiple of 4"
+#endif
+
+#if (STM32_USB_OTG2_RX_FIFO_SIZE & 3) != 0
+#error "OTG2 RX FIFO size must be a multiple of 4"
+#endif
+
+#if defined(STM32F2XX) || defined(STM32F4XX) || defined(STM32F7XX)
+#define STM32_USBCLK STM32_PLL48CLK
+#elif defined(STM32F10X_CL)
+#define STM32_USBCLK STM32_OTGFSCLK
+#elif defined(STM32L4XX) || defined(STM32L4XXP)
+#define STM32_USBCLK STM32_48CLK
+#elif defined(STM32H7XX)
+/* Defines directly STM32_USBCLK.*/
+#define rccEnableOTG_FS rccEnableUSB2_OTG_HS
+#define rccDisableOTG_FS rccDisableUSB2_OTG_HS
+#define rccResetOTG_FS rccResetUSB2_OTG_HS
+#define rccEnableOTG_HS rccEnableUSB1_OTG_HS
+#define rccDisableOTG_HS rccDisableUSB1_OTG_HS
+#define rccResetOTG_HS rccResetUSB1_OTG_HS
+#define rccEnableOTG_HSULPI rccEnableUSB1_HSULPI
+#define rccDisableOTG_HSULPI rccDisableUSB1_HSULPI
+#else
+#error "unsupported STM32 platform for OTG functionality"
+#endif
+
+/* Allowing for a small tolerance.*/
+#if STM32_USBCLK < 47880000 || STM32_USBCLK > 48120000
+#error "the USB OTG driver requires a 48MHz clock"
+#endif
+
+#if (STM32_USB_HOST_WAKEUP_DURATION < 2) || (STM32_USB_HOST_WAKEUP_DURATION > 15)
+#error "invalid STM32_USB_HOST_WAKEUP_DURATION setting, it must be between 2 and 15"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Peripheral-specific parameters block.
+ */
+typedef struct {
+ uint32_t rx_fifo_size;
+ uint32_t otg_ram_size;
+ uint32_t num_endpoints;
+} stm32_otg_params_t;
+
+/**
+ * @brief Type of an IN endpoint state structure.
+ */
+typedef struct {
+ /**
+ * @brief Requested transmit transfer size.
+ */
+ size_t txsize;
+ /**
+ * @brief Transmitted bytes so far.
+ */
+ size_t txcnt;
+ /**
+ * @brief Pointer to the transmission linear buffer.
+ */
+ const uint8_t *txbuf;
+#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Waiting thread.
+ */
+ thread_reference_t thread;
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Total transmit transfer size.
+ */
+ size_t totsize;
+} USBInEndpointState;
+
+/**
+ * @brief Type of an OUT endpoint state structure.
+ */
+typedef struct {
+ /**
+ * @brief Requested receive transfer size.
+ */
+ size_t rxsize;
+ /**
+ * @brief Received bytes so far.
+ */
+ size_t rxcnt;
+ /**
+ * @brief Pointer to the receive linear buffer.
+ */
+ uint8_t *rxbuf;
+#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Waiting thread.
+ */
+ thread_reference_t thread;
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Total receive transfer size.
+ */
+ size_t totsize;
+} USBOutEndpointState;
+
+/**
+ * @brief Type of an USB endpoint configuration structure.
+ * @note Platform specific restrictions may apply to endpoints.
+ */
+typedef struct {
+ /**
+ * @brief Type and mode of the endpoint.
+ */
+ uint32_t ep_mode;
+ /**
+ * @brief Setup packet notification callback.
+ * @details This callback is invoked when a setup packet has been
+ * received.
+ * @post The application must immediately call @p usbReadPacket() in
+ * order to access the received packet.
+ * @note This field is only valid for @p USB_EP_MODE_TYPE_CTRL
+ * endpoints, it should be set to @p NULL for other endpoint
+ * types.
+ */
+ usbepcallback_t setup_cb;
+ /**
+ * @brief IN endpoint notification callback.
+ * @details This field must be set to @p NULL if callback is not required.
+ */
+ usbepcallback_t in_cb;
+ /**
+ * @brief OUT endpoint notification callback.
+ * @details This field must be set to @p NULL if callback is not required.
+ */
+ usbepcallback_t out_cb;
+ /**
+ * @brief IN endpoint maximum packet size.
+ * @details This field must be set to zero if the IN endpoint is not used.
+ */
+ uint16_t in_maxsize;
+ /**
+ * @brief OUT endpoint maximum packet size.
+ * @details This field must be set to zero if the OUT endpoint is not used.
+ */
+ uint16_t out_maxsize;
+ /**
+ * @brief @p USBEndpointState associated to the IN endpoint.
+ * @details This field must be set to @p NULL if the IN endpoint is not
+ * used.
+ */
+ USBInEndpointState *in_state;
+ /**
+ * @brief @p USBEndpointState associated to the OUT endpoint.
+ * @details This field must be set to @p NULL if the OUT endpoint is not
+ * used.
+ */
+ USBOutEndpointState *out_state;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Determines the space allocated for the TXFIFO as multiples of
+ * the packet size (@p in_maxsize). Note that zero is interpreted
+ * as one for simplicity and robustness.
+ */
+ uint16_t in_multiplier;
+ /**
+ * @brief Pointer to a buffer for setup packets.
+ * @details Setup packets require a dedicated 8-bytes buffer, set this
+ * field to @p NULL for non-control endpoints.
+ */
+ uint8_t *setup_buf;
+} USBEndpointConfig;
+
+/**
+ * @brief Type of an USB driver configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief USB events callback.
+ * @details This callback is invoked when an USB driver event is registered.
+ */
+ usbeventcb_t event_cb;
+ /**
+ * @brief Device GET_DESCRIPTOR request callback.
+ * @note This callback is mandatory and cannot be set to @p NULL.
+ */
+ usbgetdescriptor_t get_descriptor_cb;
+ /**
+ * @brief Requests hook callback.
+ * @details This hook allows to be notified of standard requests or to
+ * handle non standard requests.
+ */
+ usbreqhandler_t requests_hook_cb;
+ /**
+ * @brief Start Of Frame callback.
+ */
+ usbcallback_t sof_cb;
+ /* End of the mandatory fields.*/
+} USBConfig;
+
+/**
+ * @brief Structure representing an USB driver.
+ */
+struct USBDriver {
+ /**
+ * @brief Driver state.
+ */
+ usbstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const USBConfig *config;
+ /**
+ * @brief Bit map of the transmitting IN endpoints.
+ */
+ uint16_t transmitting;
+ /**
+ * @brief Bit map of the receiving OUT endpoints.
+ */
+ uint16_t receiving;
+ /**
+ * @brief Active endpoints configurations.
+ */
+ const USBEndpointConfig *epc[USB_MAX_ENDPOINTS + 1];
+ /**
+ * @brief Fields available to user, it can be used to associate an
+ * application-defined handler to an IN endpoint.
+ * @note The base index is one, the endpoint zero does not have a
+ * reserved element in this array.
+ */
+ void *in_params[USB_MAX_ENDPOINTS];
+ /**
+ * @brief Fields available to user, it can be used to associate an
+ * application-defined handler to an OUT endpoint.
+ * @note The base index is one, the endpoint zero does not have a
+ * reserved element in this array.
+ */
+ void *out_params[USB_MAX_ENDPOINTS];
+ /**
+ * @brief Endpoint 0 state.
+ */
+ usbep0state_t ep0state;
+ /**
+ * @brief Next position in the buffer to be transferred through endpoint 0.
+ */
+ uint8_t *ep0next;
+ /**
+ * @brief Number of bytes yet to be transferred through endpoint 0.
+ */
+ size_t ep0n;
+ /**
+ * @brief Endpoint 0 end transaction callback.
+ */
+ usbcallback_t ep0endcb;
+ /**
+ * @brief Setup packet buffer.
+ */
+ uint8_t setup[8];
+ /**
+ * @brief Current USB device status.
+ */
+ uint16_t status;
+ /**
+ * @brief Assigned USB address.
+ */
+ uint8_t address;
+ /**
+ * @brief Current USB device configuration.
+ */
+ uint8_t configuration;
+ /**
+ * @brief State of the driver when a suspend happened.
+ */
+ usbstate_t saved_state;
+#if defined(USB_DRIVER_EXT_FIELDS)
+ USB_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Pointer to the OTG peripheral associated to this driver.
+ */
+ stm32_otg_t *otg;
+ /**
+ * @brief Peripheral-specific parameters.
+ */
+ const stm32_otg_params_t *otgparams;
+ /**
+ * @brief Pointer to the next address in the packet memory.
+ */
+ uint32_t pmnext;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Returns the exact size of a receive transaction.
+ * @details The received size can be different from the size specified in
+ * @p usbStartReceiveI() because the last packet could have a size
+ * different from the expected one.
+ * @pre The OUT endpoint must have been configured in transaction mode
+ * in order to use this function.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @return Received data size.
+ *
+ * @notapi
+ */
+#define usb_lld_get_transaction_size(usbp, ep) \
+ ((usbp)->epc[ep]->out_state->rxcnt)
+
+/**
+ * @brief Connects the USB device.
+ *
+ * @notapi
+ */
+#if (STM32_OTG_STEPPING == 1) || defined(__DOXYGEN__)
+#define usb_lld_connect_bus(usbp) ((usbp)->otg->GCCFG |= GCCFG_VBUSBSEN)
+#else
+#define usb_lld_connect_bus(usbp) ((usbp)->otg->DCTL &= ~DCTL_SDIS)
+#endif
+
+/**
+ * @brief Disconnect the USB device.
+ *
+ * @notapi
+ */
+#if (STM32_OTG_STEPPING == 1) || defined(__DOXYGEN__)
+#define usb_lld_disconnect_bus(usbp) ((usbp)->otg->GCCFG &= ~GCCFG_VBUSBSEN)
+#else
+#define usb_lld_disconnect_bus(usbp) ((usbp)->otg->DCTL |= DCTL_SDIS)
+#endif
+
+/**
+ * @brief Start of host wake-up procedure.
+ *
+ * @notapi
+ */
+#define usb_lld_wakeup_host(usbp) \
+ do { \
+ (usbp)->otg->DCTL |= DCTL_RWUSIG; \
+ osalThreadSleepMilliseconds(STM32_USB_HOST_WAKEUP_DURATION); \
+ (usbp)->otg->DCTL &= ~DCTL_RWUSIG; \
+ } while (false)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_USB_USE_OTG1 && !defined(__DOXYGEN__)
+extern USBDriver USBD1;
+#endif
+
+#if STM32_USB_USE_OTG2 && !defined(__DOXYGEN__)
+extern USBDriver USBD2;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void usb_lld_init(void);
+ void usb_lld_start(USBDriver *usbp);
+ void usb_lld_stop(USBDriver *usbp);
+ void usb_lld_reset(USBDriver *usbp);
+ void usb_lld_set_address(USBDriver *usbp);
+ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep);
+ void usb_lld_disable_endpoints(USBDriver *usbp);
+ usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep);
+ usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep);
+ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf);
+ void usb_lld_start_out(USBDriver *usbp, usbep_t ep);
+ void usb_lld_start_in(USBDriver *usbp, usbep_t ep);
+ void usb_lld_stall_out(USBDriver *usbp, usbep_t ep);
+ void usb_lld_stall_in(USBDriver *usbp, usbep_t ep);
+ void usb_lld_clear_out(USBDriver *usbp, usbep_t ep);
+ void usb_lld_clear_in(USBDriver *usbp, usbep_t ep);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_USB */
+
+#endif /* HAL_USB_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OTGv1/stm32_otg.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OTGv1/stm32_otg.h
new file mode 100644
index 0000000..0ea7314
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/OTGv1/stm32_otg.h
@@ -0,0 +1,927 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file OTGv1/stm32_otg.h
+ * @brief STM32 OTG registers layout header.
+ *
+ * @addtogroup USB
+ * @{
+ */
+
+#ifndef STM32_OTG_H
+#define STM32_OTG_H
+
+/**
+ * @brief OTG_FS FIFO memory size in words.
+ */
+#define STM32_OTG1_FIFO_MEM_SIZE 320
+
+/**
+ * @brief OTG_HS FIFO memory size in words.
+ */
+#define STM32_OTG2_FIFO_MEM_SIZE 1024
+
+/**
+ * @brief Host channel registers group.
+ */
+typedef struct {
+ volatile uint32_t HCCHAR; /**< @brief Host channel characteristics
+ register. */
+ volatile uint32_t resvd8;
+ volatile uint32_t HCINT; /**< @brief Host channel interrupt register.*/
+ volatile uint32_t HCINTMSK; /**< @brief Host channel interrupt mask
+ register. */
+ volatile uint32_t HCTSIZ; /**< @brief Host channel transfer size
+ register. */
+ volatile uint32_t resvd14;
+ volatile uint32_t resvd18;
+ volatile uint32_t resvd1c;
+} stm32_otg_host_chn_t;
+
+/**
+ * @brief Device input endpoint registers group.
+ */
+typedef struct {
+ volatile uint32_t DIEPCTL; /**< @brief Device control IN endpoint
+ control register. */
+ volatile uint32_t resvd4;
+ volatile uint32_t DIEPINT; /**< @brief Device IN endpoint interrupt
+ register. */
+ volatile uint32_t resvdC;
+ volatile uint32_t DIEPTSIZ; /**< @brief Device IN endpoint transfer size
+ register. */
+ volatile uint32_t resvd14;
+ volatile uint32_t DTXFSTS; /**< @brief Device IN endpoint transmit FIFO
+ status register. */
+ volatile uint32_t resvd1C;
+} stm32_otg_in_ep_t;
+
+/**
+ * @brief Device output endpoint registers group.
+ */
+typedef struct {
+ volatile uint32_t DOEPCTL; /**< @brief Device control OUT endpoint
+ control register. */
+ volatile uint32_t resvd4;
+ volatile uint32_t DOEPINT; /**< @brief Device OUT endpoint interrupt
+ register. */
+ volatile uint32_t resvdC;
+ volatile uint32_t DOEPTSIZ; /**< @brief Device OUT endpoint transfer
+ size register. */
+ volatile uint32_t resvd14;
+ volatile uint32_t resvd18;
+ volatile uint32_t resvd1C;
+} stm32_otg_out_ep_t;
+
+/**
+ * @brief USB registers memory map.
+ */
+typedef struct {
+ volatile uint32_t GOTGCTL; /**< @brief OTG control and status register.*/
+ volatile uint32_t GOTGINT; /**< @brief OTG interrupt register. */
+ volatile uint32_t GAHBCFG; /**< @brief AHB configuration register. */
+ volatile uint32_t GUSBCFG; /**< @brief USB configuration register. */
+ volatile uint32_t GRSTCTL; /**< @brief Reset register size. */
+ volatile uint32_t GINTSTS; /**< @brief Interrupt register. */
+ volatile uint32_t GINTMSK; /**< @brief Interrupt mask register. */
+ volatile uint32_t GRXSTSR; /**< @brief Receive status debug read
+ register. */
+ volatile uint32_t GRXSTSP; /**< @brief Receive status read/pop
+ register. */
+ volatile uint32_t GRXFSIZ; /**< @brief Receive FIFO size register. */
+ volatile uint32_t DIEPTXF0; /**< @brief Endpoint 0 transmit FIFO size
+ register. */
+ volatile uint32_t HNPTXSTS; /**< @brief Non-periodic transmit FIFO/queue
+ status register. */
+ volatile uint32_t resvd30;
+ volatile uint32_t resvd34;
+ volatile uint32_t GCCFG; /**< @brief General core configuration. */
+ volatile uint32_t CID; /**< @brief Core ID register. */
+ volatile uint32_t resvd58[48];
+ volatile uint32_t HPTXFSIZ; /**< @brief Host periodic transmit FIFO size
+ register. */
+ volatile uint32_t DIEPTXF[15];/**< @brief Device IN endpoint transmit FIFO
+ size registers. */
+ volatile uint32_t resvd140[176];
+ volatile uint32_t HCFG; /**< @brief Host configuration register. */
+ volatile uint32_t HFIR; /**< @brief Host frame interval register. */
+ volatile uint32_t HFNUM; /**< @brief Host frame number/frame time
+ Remaining register. */
+ volatile uint32_t resvd40C;
+ volatile uint32_t HPTXSTS; /**< @brief Host periodic transmit FIFO/queue
+ status register. */
+ volatile uint32_t HAINT; /**< @brief Host all channels interrupt
+ register. */
+ volatile uint32_t HAINTMSK; /**< @brief Host all channels interrupt mask
+ register. */
+ volatile uint32_t resvd41C[9];
+ volatile uint32_t HPRT; /**< @brief Host port control and status
+ register. */
+ volatile uint32_t resvd444[47];
+ stm32_otg_host_chn_t hc[16]; /**< @brief Host channels array. */
+ volatile uint32_t resvd700[64];
+ volatile uint32_t DCFG; /**< @brief Device configuration register. */
+ volatile uint32_t DCTL; /**< @brief Device control register. */
+ volatile uint32_t DSTS; /**< @brief Device status register. */
+ volatile uint32_t resvd80C;
+ volatile uint32_t DIEPMSK; /**< @brief Device IN endpoint common
+ interrupt mask register. */
+ volatile uint32_t DOEPMSK; /**< @brief Device OUT endpoint common
+ interrupt mask register. */
+ volatile uint32_t DAINT; /**< @brief Device all endpoints interrupt
+ register. */
+ volatile uint32_t DAINTMSK; /**< @brief Device all endpoints interrupt
+ mask register. */
+ volatile uint32_t resvd820;
+ volatile uint32_t resvd824;
+ volatile uint32_t DVBUSDIS; /**< @brief Device VBUS discharge time
+ register. */
+ volatile uint32_t DVBUSPULSE; /**< @brief Device VBUS pulsing time
+ register. */
+ volatile uint32_t resvd830;
+ volatile uint32_t DIEPEMPMSK; /**< @brief Device IN endpoint FIFO empty
+ interrupt mask register. */
+ volatile uint32_t resvd838;
+ volatile uint32_t resvd83C;
+ volatile uint32_t resvd840[16];
+ volatile uint32_t resvd880[16];
+ volatile uint32_t resvd8C0[16];
+ stm32_otg_in_ep_t ie[16]; /**< @brief Input endpoints. */
+ stm32_otg_out_ep_t oe[16]; /**< @brief Output endpoints. */
+ volatile uint32_t resvdD00[64];
+ volatile uint32_t PCGCCTL; /**< @brief Power and clock gating control
+ register. */
+ volatile uint32_t resvdE04[127];
+ volatile uint32_t FIFO[16][1024];
+} stm32_otg_t;
+
+/**
+ * @name GOTGCTL register bit definitions
+ * @{
+ */
+#define GOTGCTL_BSVLD (1U<<19) /**< B-Session Valid. */
+#define GOTGCTL_ASVLD (1U<<18) /**< A-Session Valid. */
+#define GOTGCTL_DBCT (1U<<17) /**< Long/Short debounce time. */
+#define GOTGCTL_CIDSTS (1U<<16) /**< Connector ID status. */
+#define GOTGCTL_EHEN (1U<<12)
+#define GOTGCTL_DHNPEN (1U<<11) /**< Device HNP enabled. */
+#define GOTGCTL_HSHNPEN (1U<<10) /**< Host Set HNP enable. */
+#define GOTGCTL_HNPRQ (1U<<9) /**< HNP request. */
+#define GOTGCTL_HNGSCS (1U<<8) /**< Host negotiation success. */
+#define GOTGCTL_BVALOVAL (1U<<7)
+#define GOTGCTL_BVALOEN (1U<<6)
+#define GOTGCTL_AVALOVAL (1U<<5)
+#define GOTGCTL_AVALOEN (1U<<4)
+#define GOTGCTL_VBVALOVAL (1U<<3)
+#define GOTGCTL_VBVALOEN (1U<<2)
+#define GOTGCTL_SRQ (1U<<1) /**< Session request. */
+#define GOTGCTL_SRQSCS (1U<<0) /**< Session request success. */
+/** @} */
+
+/**
+ * @name GOTGINT register bit definitions
+ * @{
+ */
+#define GOTGINT_DBCDNE (1U<<19) /**< Debounce done. */
+#define GOTGINT_ADTOCHG (1U<<18) /**< A-Device timeout change. */
+#define GOTGINT_HNGDET (1U<<17) /**< Host negotiation detected. */
+#define GOTGINT_HNSSCHG (1U<<9) /**< Host negotiation success
+ status change. */
+#define GOTGINT_SRSSCHG (1U<<8) /**< Session request success
+ status change. */
+#define GOTGINT_SEDET (1U<<2) /**< Session end detected. */
+/** @} */
+
+/**
+ * @name GAHBCFG register bit definitions
+ * @{
+ */
+#define GAHBCFG_PTXFELVL (1U<<8) /**< Periodic TxFIFO empty
+ level. */
+#define GAHBCFG_TXFELVL (1U<<7) /**< Non-periodic TxFIFO empty
+ level. */
+#define GAHBCFG_DMAEN (1U<<5) /**< DMA enable (HS only). */
+#define GAHBCFG_HBSTLEN_MASK (15U<<1) /**< Burst length/type mask (HS
+ only). */
+#define GAHBCFG_HBSTLEN(n) ((n)<<1) /**< Burst length/type (HS
+ only). */
+#define GAHBCFG_GINTMSK (1U<<0) /**< Global interrupt mask. */
+/** @} */
+
+/**
+ * @name GUSBCFG register bit definitions
+ * @{
+ */
+#define GUSBCFG_CTXPKT (1U<<31) /**< Corrupt Tx packet. */
+#define GUSBCFG_FDMOD (1U<<30) /**< Force Device Mode. */
+#define GUSBCFG_FHMOD (1U<<29) /**< Force Host Mode. */
+#define GUSBCFG_TRDT_MASK (15U<<10) /**< USB Turnaround time field
+ mask. */
+#define GUSBCFG_TRDT(n) ((n)<<10) /**< USB Turnaround time field
+ value. */
+#define GUSBCFG_HNPCAP (1U<<9) /**< HNP-Capable. */
+#define GUSBCFG_SRPCAP (1U<<8) /**< SRP-Capable. */
+#define GUSBCFG_PHYSEL (1U<<6) /**< USB 2.0 High-Speed PHY or
+ USB 1.1 Full-Speed serial
+ transceiver Select. */
+#define GUSBCFG_TOCAL_MASK (7U<<0) /**< HS/FS timeout calibration
+ field mask. */
+#define GUSBCFG_TOCAL(n) ((n)<<0) /**< HS/FS timeout calibration
+ field value. */
+/** @} */
+
+/**
+ * @name GRSTCTL register bit definitions
+ * @{
+ */
+#define GRSTCTL_AHBIDL (1U<<31) /**< AHB Master Idle. */
+#define GRSTCTL_TXFNUM_MASK (31U<<6) /**< TxFIFO number field mask. */
+#define GRSTCTL_TXFNUM(n) ((n)<<6) /**< TxFIFO number field value. */
+#define GRSTCTL_TXFFLSH (1U<<5) /**< TxFIFO flush. */
+#define GRSTCTL_RXFFLSH (1U<<4) /**< RxFIFO flush. */
+#define GRSTCTL_FCRST (1U<<2) /**< Host frame counter reset. */
+#define GRSTCTL_HSRST (1U<<1) /**< HClk soft reset. */
+#define GRSTCTL_CSRST (1U<<0) /**< Core soft reset. */
+/** @} */
+
+/**
+ * @name GINTSTS register bit definitions
+ * @{
+ */
+#define GINTSTS_WKUPINT (1U<<31) /**< Resume/Remote wakeup
+ detected interrupt. */
+#define GINTSTS_SRQINT (1U<<30) /**< Session request/New session
+ detected interrupt. */
+#define GINTSTS_DISCINT (1U<<29) /**< Disconnect detected
+ interrupt. */
+#define GINTSTS_CIDSCHG (1U<<28) /**< Connector ID status change.*/
+#define GINTSTS_PTXFE (1U<<26) /**< Periodic TxFIFO empty. */
+#define GINTSTS_HCINT (1U<<25) /**< Host channels interrupt. */
+#define GINTSTS_HPRTINT (1U<<24) /**< Host port interrupt. */
+#define GINTSTS_IPXFR (1U<<21) /**< Incomplete periodic
+ transfer. */
+#define GINTSTS_IISOOXFR (1U<<21) /**< Incomplete isochronous OUT
+ transfer. */
+#define GINTSTS_IISOIXFR (1U<<20) /**< Incomplete isochronous IN
+ transfer. */
+#define GINTSTS_OEPINT (1U<<19) /**< OUT endpoints interrupt. */
+#define GINTSTS_IEPINT (1U<<18) /**< IN endpoints interrupt. */
+#define GINTSTS_EOPF (1U<<15) /**< End of periodic frame
+ interrupt. */
+#define GINTSTS_ISOODRP (1U<<14) /**< Isochronous OUT packet
+ dropped interrupt. */
+#define GINTSTS_ENUMDNE (1U<<13) /**< Enumeration done. */
+#define GINTSTS_USBRST (1U<<12) /**< USB reset. */
+#define GINTSTS_USBSUSP (1U<<11) /**< USB suspend. */
+#define GINTSTS_ESUSP (1U<<10) /**< Early suspend. */
+#define GINTSTS_GONAKEFF (1U<<7) /**< Global OUT NAK effective. */
+#define GINTSTS_GINAKEFF (1U<<6) /**< Global IN non-periodic NAK
+ effective. */
+#define GINTSTS_NPTXFE (1U<<5) /**< Non-periodic TxFIFO empty. */
+#define GINTSTS_RXFLVL (1U<<4) /**< RxFIFO non-empty. */
+#define GINTSTS_SOF (1U<<3) /**< Start of frame. */
+#define GINTSTS_OTGINT (1U<<2) /**< OTG interrupt. */
+#define GINTSTS_MMIS (1U<<1) /**< Mode Mismatch interrupt. */
+#define GINTSTS_CMOD (1U<<0) /**< Current mode of operation. */
+/** @} */
+
+/**
+ * @name GINTMSK register bit definitions
+ * @{
+ */
+#define GINTMSK_WKUM (1U<<31) /**< Resume/remote wakeup
+ detected interrupt mask. */
+#define GINTMSK_SRQM (1U<<30) /**< Session request/New session
+ detected interrupt mask. */
+#define GINTMSK_DISCM (1U<<29) /**< Disconnect detected
+ interrupt mask. */
+#define GINTMSK_CIDSCHGM (1U<<28) /**< Connector ID status change
+ mask. */
+#define GINTMSK_PTXFEM (1U<<26) /**< Periodic TxFIFO empty mask.*/
+#define GINTMSK_HCM (1U<<25) /**< Host channels interrupt
+ mask. */
+#define GINTMSK_HPRTM (1U<<24) /**< Host port interrupt mask. */
+#define GINTMSK_IPXFRM (1U<<21) /**< Incomplete periodic
+ transfer mask. */
+#define GINTMSK_IISOOXFRM (1U<<21) /**< Incomplete isochronous OUT
+ transfer mask. */
+#define GINTMSK_IISOIXFRM (1U<<20) /**< Incomplete isochronous IN
+ transfer mask. */
+#define GINTMSK_OEPM (1U<<19) /**< OUT endpoints interrupt
+ mask. */
+#define GINTMSK_IEPM (1U<<18) /**< IN endpoints interrupt
+ mask. */
+#define GINTMSK_EOPFM (1U<<15) /**< End of periodic frame
+ interrupt mask. */
+#define GINTMSK_ISOODRPM (1U<<14) /**< Isochronous OUT packet
+ dropped interrupt mask. */
+#define GINTMSK_ENUMDNEM (1U<<13) /**< Enumeration done mask. */
+#define GINTMSK_USBRSTM (1U<<12) /**< USB reset mask. */
+#define GINTMSK_USBSUSPM (1U<<11) /**< USB suspend mask. */
+#define GINTMSK_ESUSPM (1U<<10) /**< Early suspend mask. */
+#define GINTMSK_GONAKEFFM (1U<<7) /**< Global OUT NAK effective
+ mask. */
+#define GINTMSK_GINAKEFFM (1U<<6) /**< Global non-periodic IN NAK
+ effective mask. */
+#define GINTMSK_NPTXFEM (1U<<5) /**< Non-periodic TxFIFO empty
+ mask. */
+#define GINTMSK_RXFLVLM (1U<<4) /**< Receive FIFO non-empty
+ mask. */
+#define GINTMSK_SOFM (1U<<3) /**< Start of (micro)frame mask.*/
+#define GINTMSK_OTGM (1U<<2) /**< OTG interrupt mask. */
+#define GINTMSK_MMISM (1U<<1) /**< Mode Mismatch interrupt
+ mask. */
+/** @} */
+
+/**
+ * @name GRXSTSR register bit definitions
+ * @{
+ */
+#define GRXSTSR_PKTSTS_MASK (15U<<17) /**< Packet status mask. */
+#define GRXSTSR_PKTSTS(n) ((n)<<17) /**< Packet status value. */
+#define GRXSTSR_OUT_GLOBAL_NAK GRXSTSR_PKTSTS(1)
+#define GRXSTSR_OUT_DATA GRXSTSR_PKTSTS(2)
+#define GRXSTSR_OUT_COMP GRXSTSR_PKTSTS(3)
+#define GRXSTSR_SETUP_COMP GRXSTSR_PKTSTS(4)
+#define GRXSTSR_SETUP_DATA GRXSTSR_PKTSTS(6)
+#define GRXSTSR_DPID_MASK (3U<<15) /**< Data PID mask. */
+#define GRXSTSR_DPID(n) ((n)<<15) /**< Data PID value. */
+#define GRXSTSR_BCNT_MASK (0x7FF<<4) /**< Byte count mask. */
+#define GRXSTSR_BCNT(n) ((n)<<4) /**< Byte count value. */
+#define GRXSTSR_CHNUM_MASK (15U<<0) /**< Channel number mask. */
+#define GRXSTSR_CHNUM(n) ((n)<<0) /**< Channel number value. */
+#define GRXSTSR_EPNUM_MASK (15U<<0) /**< Endpoint number mask. */
+#define GRXSTSR_EPNUM(n) ((n)<<0) /**< Endpoint number value. */
+/** @} */
+
+/**
+ * @name GRXSTSP register bit definitions
+ * @{
+ */
+#define GRXSTSP_PKTSTS_MASK (15<<17) /**< Packet status mask. */
+#define GRXSTSP_PKTSTS(n) ((n)<<17) /**< Packet status value. */
+#define GRXSTSP_OUT_GLOBAL_NAK GRXSTSP_PKTSTS(1)
+#define GRXSTSP_OUT_DATA GRXSTSP_PKTSTS(2)
+#define GRXSTSP_OUT_COMP GRXSTSP_PKTSTS(3)
+#define GRXSTSP_SETUP_COMP GRXSTSP_PKTSTS(4)
+#define GRXSTSP_SETUP_DATA GRXSTSP_PKTSTS(6)
+#define GRXSTSP_DPID_MASK (3U<<15) /**< Data PID mask. */
+#define GRXSTSP_DPID(n) ((n)<<15) /**< Data PID value. */
+#define GRXSTSP_BCNT_MASK (0x7FF<<4) /**< Byte count mask. */
+#define GRXSTSP_BCNT_OFF 4 /**< Byte count offset. */
+#define GRXSTSP_BCNT(n) ((n)<<4) /**< Byte count value. */
+#define GRXSTSP_CHNUM_MASK (15U<<0) /**< Channel number mask. */
+#define GRXSTSP_CHNUM(n) ((n)<<0) /**< Channel number value. */
+#define GRXSTSP_EPNUM_MASK (15U<<0) /**< Endpoint number mask. */
+#define GRXSTSP_EPNUM_OFF 0 /**< Endpoint number offset. */
+#define GRXSTSP_EPNUM(n) ((n)<<0) /**< Endpoint number value. */
+/** @} */
+
+/**
+ * @name GRXFSIZ register bit definitions
+ * @{
+ */
+#define GRXFSIZ_RXFD_MASK (0xFFFF<<0) /**< RxFIFO depth mask. */
+#define GRXFSIZ_RXFD(n) ((n)<<0) /**< RxFIFO depth value. */
+/** @} */
+
+/**
+ * @name DIEPTXFx register bit definitions
+ * @{
+ */
+#define DIEPTXF_INEPTXFD_MASK (0xFFFFU<<16)/**< IN endpoint TxFIFO depth
+ mask. */
+#define DIEPTXF_INEPTXFD(n) ((n)<<16) /**< IN endpoint TxFIFO depth
+ value. */
+#define DIEPTXF_INEPTXSA_MASK (0xFFFF<<0) /**< IN endpoint FIFOx transmit
+ RAM start address mask. */
+#define DIEPTXF_INEPTXSA(n) ((n)<<0) /**< IN endpoint FIFOx transmit
+ RAM start address value. */
+/** @} */
+
+/**
+ * @name GCCFG register bit definitions
+ * @{
+ */
+/* Definitions for stepping 1.*/
+#define GCCFG_NOVBUSSENS (1U<<21) /**< VBUS sensing disable. */
+#define GCCFG_SOFOUTEN (1U<<20) /**< SOF output enable. */
+#define GCCFG_VBUSBSEN (1U<<19) /**< Enable the VBUS sensing "B"
+ device. */
+#define GCCFG_VBUSASEN (1U<<18) /**< Enable the VBUS sensing "A"
+ device. */
+
+/* Definitions for stepping 2.*/
+#define GCCFG_VBDEN (1U<<21) /**< VBUS sensing enable. */
+#define GCCFG_PWRDWN (1U<<16) /**< Power down. */
+/** @} */
+
+/**
+ * @name HPTXFSIZ register bit definitions
+ * @{
+ */
+#define HPTXFSIZ_PTXFD_MASK (0xFFFFU<<16)/**< Host periodic TxFIFO
+ depth mask. */
+#define HPTXFSIZ_PTXFD(n) ((n)<<16) /**< Host periodic TxFIFO
+ depth value. */
+#define HPTXFSIZ_PTXSA_MASK (0xFFFFU<<0)/**< Host periodic TxFIFO
+ Start address mask. */
+#define HPTXFSIZ_PTXSA(n) ((n)<<0) /**< Host periodic TxFIFO
+ start address value. */
+/** @} */
+
+/**
+ * @name HCFG register bit definitions
+ * @{
+ */
+#define HCFG_FSLSS (1U<<2) /**< FS- and LS-only support. */
+#define HCFG_FSLSPCS_MASK (3U<<0) /**< FS/LS PHY clock select
+ mask. */
+#define HCFG_FSLSPCS_48 (1U<<0) /**< PHY clock is running at
+ 48 MHz. */
+#define HCFG_FSLSPCS_6 (2U<<0) /**< PHY clock is running at
+ 6 MHz. */
+/** @} */
+
+/**
+ * @name HFIR register bit definitions
+ * @{
+ */
+#define HFIR_FRIVL_MASK (0xFFFFU<<0)/**< Frame interval mask. */
+#define HFIR_FRIVL(n) ((n)<<0) /**< Frame interval value. */
+/** @} */
+
+/**
+ * @name HFNUM register bit definitions
+ * @{
+ */
+#define HFNUM_FTREM_MASK (0xFFFFU<<16)/**< Frame time Remaining mask.*/
+#define HFNUM_FTREM(n) ((n)<<16) /**< Frame time Remaining value.*/
+#define HFNUM_FRNUM_MASK (0xFFFFU<<0)/**< Frame number mask. */
+#define HFNUM_FRNUM(n) ((n)<<0) /**< Frame number value. */
+/** @} */
+
+/**
+ * @name HPTXSTS register bit definitions
+ * @{
+ */
+#define HPTXSTS_PTXQTOP_MASK (0xFFU<<24) /**< Top of the periodic
+ transmit request queue
+ mask. */
+#define HPTXSTS_PTXQTOP(n) ((n)<<24) /**< Top of the periodic
+ transmit request queue
+ value. */
+#define HPTXSTS_PTXQSAV_MASK (0xFF<<16) /**< Periodic transmit request
+ queue Space Available
+ mask. */
+#define HPTXSTS_PTXQSAV(n) ((n)<<16) /**< Periodic transmit request
+ queue Space Available
+ value. */
+#define HPTXSTS_PTXFSAVL_MASK (0xFFFF<<0) /**< Periodic transmit Data
+ FIFO Space Available
+ mask. */
+#define HPTXSTS_PTXFSAVL(n) ((n)<<0) /**< Periodic transmit Data
+ FIFO Space Available
+ value. */
+/** @} */
+
+/**
+ * @name HAINT register bit definitions
+ * @{
+ */
+#define HAINT_HAINT_MASK (0xFFFFU<<0)/**< Channel interrupts mask. */
+#define HAINT_HAINT(n) ((n)<<0) /**< Channel interrupts value. */
+/** @} */
+
+/**
+ * @name HAINTMSK register bit definitions
+ * @{
+ */
+#define HAINTMSK_HAINTM_MASK (0xFFFFU<<0)/**< Channel interrupt mask
+ mask. */
+#define HAINTMSK_HAINTM(n) ((n)<<0) /**< Channel interrupt mask
+ value. */
+/** @} */
+
+/**
+ * @name HPRT register bit definitions
+ * @{
+ */
+#define HPRT_PSPD_MASK (3U<<17) /**< Port speed mask. */
+#define HPRT_PSPD_FS (1U<<17) /**< Full speed value. */
+#define HPRT_PSPD_LS (2U<<17) /**< Low speed value. */
+#define HPRT_PTCTL_MASK (15<<13) /**< Port Test control mask. */
+#define HPRT_PTCTL(n) ((n)<<13) /**< Port Test control value. */
+#define HPRT_PPWR (1U<<12) /**< Port power. */
+#define HPRT_PLSTS_MASK (3U<<11) /**< Port Line status mask. */
+#define HPRT_PLSTS_DM (1U<<11) /**< Logic level of D-. */
+#define HPRT_PLSTS_DP (1U<<10) /**< Logic level of D+. */
+#define HPRT_PRST (1U<<8) /**< Port reset. */
+#define HPRT_PSUSP (1U<<7) /**< Port suspend. */
+#define HPRT_PRES (1U<<6) /**< Port Resume. */
+#define HPRT_POCCHNG (1U<<5) /**< Port overcurrent change. */
+#define HPRT_POCA (1U<<4) /**< Port overcurrent active. */
+#define HPRT_PENCHNG (1U<<3) /**< Port enable/disable change.*/
+#define HPRT_PENA (1U<<2) /**< Port enable. */
+#define HPRT_PCDET (1U<<1) /**< Port Connect detected. */
+#define HPRT_PCSTS (1U<<0) /**< Port connect status. */
+/** @} */
+
+/**
+ * @name HCCHAR register bit definitions
+ * @{
+ */
+#define HCCHAR_CHENA (1U<<31) /**< Channel enable. */
+#define HCCHAR_CHDIS (1U<<30) /**< Channel Disable. */
+#define HCCHAR_ODDFRM (1U<<29) /**< Odd frame. */
+#define HCCHAR_DAD_MASK (0x7FU<<22) /**< Device Address mask. */
+#define HCCHAR_DAD(n) ((n)<<22) /**< Device Address value. */
+#define HCCHAR_MCNT_MASK (3U<<20) /**< Multicount mask. */
+#define HCCHAR_MCNT(n) ((n)<<20) /**< Multicount value. */
+#define HCCHAR_EPTYP_MASK (3U<<18) /**< Endpoint type mask. */
+#define HCCHAR_EPTYP(n) ((n)<<18) /**< Endpoint type value. */
+#define HCCHAR_EPTYP_CTL (0U<<18) /**< Control endpoint value. */
+#define HCCHAR_EPTYP_ISO (1U<<18) /**< Isochronous endpoint value.*/
+#define HCCHAR_EPTYP_BULK (2U<<18) /**< Bulk endpoint value. */
+#define HCCHAR_EPTYP_INTR (3U<<18) /**< Interrupt endpoint value. */
+#define HCCHAR_LSDEV (1U<<17) /**< Low-Speed device. */
+#define HCCHAR_EPDIR (1U<<15) /**< Endpoint direction. */
+#define HCCHAR_EPNUM_MASK (15U<<11) /**< Endpoint number mask. */
+#define HCCHAR_EPNUM(n) ((n)<<11) /**< Endpoint number value. */
+#define HCCHAR_MPS_MASK (0x7FFU<<0) /**< Maximum packet size mask. */
+#define HCCHAR_MPS(n) ((n)<<0) /**< Maximum packet size value. */
+/** @} */
+
+/**
+ * @name HCINT register bit definitions
+ * @{
+ */
+#define HCINT_DTERR (1U<<10) /**< Data toggle error. */
+#define HCINT_FRMOR (1U<<9) /**< Frame overrun. */
+#define HCINT_BBERR (1U<<8) /**< Babble error. */
+#define HCINT_TRERR (1U<<7) /**< Transaction Error. */
+#define HCINT_ACK (1U<<5) /**< ACK response
+ received/transmitted
+ interrupt. */
+#define HCINT_NAK (1U<<4) /**< NAK response received
+ interrupt. */
+#define HCINT_STALL (1U<<3) /**< STALL response received
+ interrupt. */
+#define HCINT_AHBERR (1U<<2) /**< AHB error interrupt. */
+#define HCINT_CHH (1U<<1) /**< Channel halted. */
+#define HCINT_XFRC (1U<<0) /**< Transfer completed. */
+/** @} */
+
+/**
+ * @name HCINTMSK register bit definitions
+ * @{
+ */
+#define HCINTMSK_DTERRM (1U<<10) /**< Data toggle error mask. */
+#define HCINTMSK_FRMORM (1U<<9) /**< Frame overrun mask. */
+#define HCINTMSK_BBERRM (1U<<8) /**< Babble error mask. */
+#define HCINTMSK_TRERRM (1U<<7) /**< Transaction error mask. */
+#define HCINTMSK_NYET (1U<<6) /**< NYET response received
+ interrupt mask. */
+#define HCINTMSK_ACKM (1U<<5) /**< ACK Response
+ received/transmitted
+ interrupt mask. */
+#define HCINTMSK_NAKM (1U<<4) /**< NAK response received
+ interrupt mask. */
+#define HCINTMSK_STALLM (1U<<3) /**< STALL response received
+ interrupt mask. */
+#define HCINTMSK_AHBERRM (1U<<2) /**< AHB error interrupt mask. */
+#define HCINTMSK_CHHM (1U<<1) /**< Channel halted mask. */
+#define HCINTMSK_XFRCM (1U<<0) /**< Transfer completed mask. */
+/** @} */
+
+/**
+ * @name HCTSIZ register bit definitions
+ * @{
+ */
+#define HCTSIZ_DPID_MASK (3U<<29) /**< PID mask. */
+#define HCTSIZ_DPID_DATA0 (0U<<29) /**< DATA0. */
+#define HCTSIZ_DPID_DATA2 (1U<<29) /**< DATA2. */
+#define HCTSIZ_DPID_DATA1 (2U<<29) /**< DATA1. */
+#define HCTSIZ_DPID_MDATA (3U<<29) /**< MDATA. */
+#define HCTSIZ_DPID_SETUP (3U<<29) /**< SETUP. */
+#define HCTSIZ_PKTCNT_MASK (0x3FFU<<19)/**< Packet count mask. */
+#define HCTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */
+#define HCTSIZ_XFRSIZ_MASK (0x7FFFF<<0)/**< Transfer size mask. */
+#define HCTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */
+/** @} */
+
+/**
+ * @name DCFG register bit definitions
+ * @{
+ */
+#define DCFG_PFIVL_MASK (3U<<11) /**< Periodic frame interval
+ mask. */
+#define DCFG_PFIVL(n) ((n)<<11) /**< Periodic frame interval
+ value. */
+#define DCFG_DAD_MASK (0x7FU<<4) /**< Device address mask. */
+#define DCFG_DAD(n) ((n)<<4) /**< Device address value. */
+#define DCFG_NZLSOHSK (1U<<2) /**< Non-Zero-Length status
+ OUT handshake. */
+#define DCFG_DSPD_MASK (3U<<0) /**< Device speed mask. */
+#define DCFG_DSPD_HS (0U<<0) /**< High speed (USB 2.0). */
+#define DCFG_DSPD_HS_FS (1U<<0) /**< High speed (USB 2.0) in FS
+ mode. */
+#define DCFG_DSPD_FS11 (3U<<0) /**< Full speed (USB 1.1
+ transceiver clock is 48
+ MHz). */
+/** @} */
+
+/**
+ * @name DCTL register bit definitions
+ * @{
+ */
+#define DCTL_POPRGDNE (1U<<11) /**< Power-on programming done. */
+#define DCTL_CGONAK (1U<<10) /**< Clear global OUT NAK. */
+#define DCTL_SGONAK (1U<<9) /**< Set global OUT NAK. */
+#define DCTL_CGINAK (1U<<8) /**< Clear global non-periodic
+ IN NAK. */
+#define DCTL_SGINAK (1U<<7) /**< Set global non-periodic
+ IN NAK. */
+#define DCTL_TCTL_MASK (7U<<4) /**< Test control mask. */
+#define DCTL_TCTL(n) ((n)<<4 /**< Test control value. */
+#define DCTL_GONSTS (1U<<3) /**< Global OUT NAK status. */
+#define DCTL_GINSTS (1U<<2) /**< Global non-periodic IN
+ NAK status. */
+#define DCTL_SDIS (1U<<1) /**< Soft disconnect. */
+#define DCTL_RWUSIG (1U<<0) /**< Remote wakeup signaling. */
+/** @} */
+
+/**
+ * @name DSTS register bit definitions
+ * @{
+ */
+#define DSTS_FNSOF_MASK (0x3FFU<<8) /**< Frame number of the received
+ SOF mask. */
+#define DSTS_FNSOF(n) ((n)<<8) /**< Frame number of the received
+ SOF value. */
+#define DSTS_FNSOF_ODD (1U<<8) /**< Frame parity of the received
+ SOF value. */
+#define DSTS_EERR (1U<<3) /**< Erratic error. */
+#define DSTS_ENUMSPD_MASK (3U<<1) /**< Enumerated speed mask. */
+#define DSTS_ENUMSPD_FS_48 (3U<<1) /**< Full speed (PHY clock is
+ running at 48 MHz). */
+#define DSTS_ENUMSPD_HS_480 (0U<<1) /**< High speed. */
+#define DSTS_SUSPSTS (1U<<0) /**< Suspend status. */
+/** @} */
+
+/**
+ * @name DIEPMSK register bit definitions
+ * @{
+ */
+#define DIEPMSK_TXFEM (1U<<6) /**< Transmit FIFO empty mask. */
+#define DIEPMSK_INEPNEM (1U<<6) /**< IN endpoint NAK effective
+ mask. */
+#define DIEPMSK_ITTXFEMSK (1U<<4) /**< IN token received when
+ TxFIFO empty mask. */
+#define DIEPMSK_TOCM (1U<<3) /**< Timeout condition mask. */
+#define DIEPMSK_EPDM (1U<<1) /**< Endpoint disabled
+ interrupt mask. */
+#define DIEPMSK_XFRCM (1U<<0) /**< Transfer completed
+ interrupt mask. */
+/** @} */
+
+/**
+ * @name DOEPMSK register bit definitions
+ * @{
+ */
+#define DOEPMSK_OTEPDM (1U<<4) /**< OUT token received when
+ endpoint disabled mask. */
+#define DOEPMSK_STUPM (1U<<3) /**< SETUP phase done mask. */
+#define DOEPMSK_EPDM (1U<<1) /**< Endpoint disabled
+ interrupt mask. */
+#define DOEPMSK_XFRCM (1U<<0) /**< Transfer completed
+ interrupt mask. */
+/** @} */
+
+/**
+ * @name DAINT register bit definitions
+ * @{
+ */
+#define DAINT_OEPINT_MASK (0xFFFFU<<16)/**< OUT endpoint interrupt
+ bits mask. */
+#define DAINT_OEPINT(n) ((n)<<16) /**< OUT endpoint interrupt
+ bits value. */
+#define DAINT_IEPINT_MASK (0xFFFFU<<0)/**< IN endpoint interrupt
+ bits mask. */
+#define DAINT_IEPINT(n) ((n)<<0) /**< IN endpoint interrupt
+ bits value. */
+/** @} */
+
+/**
+ * @name DAINTMSK register bit definitions
+ * @{
+ */
+#define DAINTMSK_OEPM_MASK (0xFFFFU<<16)/**< OUT EP interrupt mask
+ bits mask. */
+#define DAINTMSK_OEPM(n) (1U<<(16+(n)))/**< OUT EP interrupt mask
+ bits value. */
+#define DAINTMSK_IEPM_MASK (0xFFFFU<<0)/**< IN EP interrupt mask
+ bits mask. */
+#define DAINTMSK_IEPM(n) (1U<<(n)) /**< IN EP interrupt mask
+ bits value. */
+/** @} */
+
+/**
+ * @name DVBUSDIS register bit definitions
+ * @{
+ */
+#define DVBUSDIS_VBUSDT_MASK (0xFFFFU<<0)/**< Device VBUS discharge
+ time mask. */
+#define DVBUSDIS_VBUSDT(n) ((n)<<0) /**< Device VBUS discharge
+ time value. */
+/** @} */
+
+/**
+ * @name DVBUSPULSE register bit definitions
+ * @{
+ */
+#define DVBUSPULSE_DVBUSP_MASK (0xFFFU<<0) /**< Device VBUSpulsing time
+ mask. */
+#define DVBUSPULSE_DVBUSP(n) ((n)<<0) /**< Device VBUS pulsing time
+ value. */
+/** @} */
+
+/**
+ * @name DIEPEMPMSK register bit definitions
+ * @{
+ */
+#define DIEPEMPMSK_INEPTXFEM(n) (1U<<(n)) /**< IN EP Tx FIFO empty
+ interrupt mask bit. */
+/** @} */
+
+/**
+ * @name DIEPCTL register bit definitions
+ * @{
+ */
+#define DIEPCTL_EPENA (1U<<31) /**< Endpoint enable. */
+#define DIEPCTL_EPDIS (1U<<30) /**< Endpoint disable. */
+#define DIEPCTL_SD1PID (1U<<29) /**< Set DATA1 PID. */
+#define DIEPCTL_SODDFRM (1U<<29) /**< Set odd frame. */
+#define DIEPCTL_SD0PID (1U<<28) /**< Set DATA0 PID. */
+#define DIEPCTL_SEVNFRM (1U<<28) /**< Set even frame. */
+#define DIEPCTL_SNAK (1U<<27) /**< Set NAK. */
+#define DIEPCTL_CNAK (1U<<26) /**< Clear NAK. */
+#define DIEPCTL_TXFNUM_MASK (15U<<22) /**< TxFIFO number mask. */
+#define DIEPCTL_TXFNUM(n) ((n)<<22) /**< TxFIFO number value. */
+#define DIEPCTL_STALL (1U<<21) /**< STALL handshake. */
+#define DIEPCTL_SNPM (1U<<20) /**< Snoop mode. */
+#define DIEPCTL_EPTYP_MASK (3<<18) /**< Endpoint type mask. */
+#define DIEPCTL_EPTYP_CTRL (0U<<18) /**< Control. */
+#define DIEPCTL_EPTYP_ISO (1U<<18) /**< Isochronous. */
+#define DIEPCTL_EPTYP_BULK (2U<<18) /**< Bulk. */
+#define DIEPCTL_EPTYP_INTR (3U<<18) /**< Interrupt. */
+#define DIEPCTL_NAKSTS (1U<<17) /**< NAK status. */
+#define DIEPCTL_EONUM (1U<<16) /**< Even/odd frame. */
+#define DIEPCTL_DPID (1U<<16) /**< Endpoint data PID. */
+#define DIEPCTL_USBAEP (1U<<15) /**< USB active endpoint. */
+#define DIEPCTL_MPSIZ_MASK (0x3FFU<<0) /**< Maximum Packet size mask. */
+#define DIEPCTL_MPSIZ(n) ((n)<<0) /**< Maximum Packet size value. */
+/** @} */
+
+/**
+ * @name DIEPINT register bit definitions
+ * @{
+ */
+#define DIEPINT_TXFE (1U<<7) /**< Transmit FIFO empty. */
+#define DIEPINT_INEPNE (1U<<6) /**< IN endpoint NAK effective. */
+#define DIEPINT_ITTXFE (1U<<4) /**< IN Token received when
+ TxFIFO is empty. */
+#define DIEPINT_TOC (1U<<3) /**< Timeout condition. */
+#define DIEPINT_EPDISD (1U<<1) /**< Endpoint disabled
+ interrupt. */
+#define DIEPINT_XFRC (1U<<0) /**< Transfer completed. */
+/** @} */
+
+/**
+ * @name DIEPTSIZ register bit definitions
+ * @{
+ */
+#define DIEPTSIZ_MCNT_MASK (3U<<29) /**< Multi count mask. */
+#define DIEPTSIZ_MCNT(n) ((n)<<29) /**< Multi count value. */
+#define DIEPTSIZ_PKTCNT_MASK (0x3FF<<19) /**< Packet count mask. */
+#define DIEPTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */
+#define DIEPTSIZ_XFRSIZ_MASK (0x7FFFFU<<0)/**< Transfer size mask. */
+#define DIEPTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */
+/** @} */
+
+/**
+ * @name DTXFSTS register bit definitions.
+ * @{
+ */
+#define DTXFSTS_INEPTFSAV_MASK (0xFFFF<<0) /**< IN endpoint TxFIFO space
+ available. */
+/** @} */
+
+/**
+ * @name DOEPCTL register bit definitions.
+ * @{
+ */
+#define DOEPCTL_EPENA (1U<<31) /**< Endpoint enable. */
+#define DOEPCTL_EPDIS (1U<<30) /**< Endpoint disable. */
+#define DOEPCTL_SD1PID (1U<<29) /**< Set DATA1 PID. */
+#define DOEPCTL_SODDFRM (1U<<29) /**< Set odd frame. */
+#define DOEPCTL_SD0PID (1U<<28) /**< Set DATA0 PID. */
+#define DOEPCTL_SEVNFRM (1U<<28) /**< Set even frame. */
+#define DOEPCTL_SNAK (1U<<27) /**< Set NAK. */
+#define DOEPCTL_CNAK (1U<<26) /**< Clear NAK. */
+#define DOEPCTL_STALL (1U<<21) /**< STALL handshake. */
+#define DOEPCTL_SNPM (1U<<20) /**< Snoop mode. */
+#define DOEPCTL_EPTYP_MASK (3U<<18) /**< Endpoint type mask. */
+#define DOEPCTL_EPTYP_CTRL (0U<<18) /**< Control. */
+#define DOEPCTL_EPTYP_ISO (1U<<18) /**< Isochronous. */
+#define DOEPCTL_EPTYP_BULK (2U<<18) /**< Bulk. */
+#define DOEPCTL_EPTYP_INTR (3U<<18) /**< Interrupt. */
+#define DOEPCTL_NAKSTS (1U<<17) /**< NAK status. */
+#define DOEPCTL_EONUM (1U<<16) /**< Even/odd frame. */
+#define DOEPCTL_DPID (1U<<16) /**< Endpoint data PID. */
+#define DOEPCTL_USBAEP (1U<<15) /**< USB active endpoint. */
+#define DOEPCTL_MPSIZ_MASK (0x3FFU<<0) /**< Maximum Packet size mask. */
+#define DOEPCTL_MPSIZ(n) ((n)<<0) /**< Maximum Packet size value. */
+/** @} */
+
+/**
+ * @name DOEPINT register bit definitions
+ * @{
+ */
+#define DOEPINT_SETUP_RCVD (1U<<15) /**< SETUP packet received. */
+#define DOEPINT_B2BSTUP (1U<<6) /**< Back-to-back SETUP packets
+ received. */
+#define DOEPINT_OTEPDIS (1U<<4) /**< OUT token received when
+ endpoint disabled. */
+#define DOEPINT_STUP (1U<<3) /**< SETUP phase done. */
+#define DOEPINT_EPDISD (1U<<1) /**< Endpoint disabled
+ interrupt. */
+#define DOEPINT_XFRC (1U<<0) /**< Transfer completed
+ interrupt. */
+/** @} */
+
+/**
+ * @name DOEPTSIZ register bit definitions
+ * @{
+ */
+#define DOEPTSIZ_RXDPID_MASK (3U<<29) /**< Received data PID mask. */
+#define DOEPTSIZ_RXDPID(n) ((n)<<29) /**< Received data PID value. */
+#define DOEPTSIZ_STUPCNT_MASK (3U<<29) /**< SETUP packet count mask. */
+#define DOEPTSIZ_STUPCNT(n) ((n)<<29) /**< SETUP packet count value. */
+#define DOEPTSIZ_PKTCNT_MASK (0x3FFU<<19)/**< Packet count mask. */
+#define DOEPTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */
+#define DOEPTSIZ_XFRSIZ_MASK (0x7FFFFU<<0)/**< Transfer size mask. */
+#define DOEPTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */
+/** @} */
+
+/**
+ * @name PCGCCTL register bit definitions
+ * @{
+ */
+#define PCGCCTL_PHYSUSP (1U<<4) /**< PHY Suspended. */
+#define PCGCCTL_GATEHCLK (1U<<1) /**< Gate HCLK. */
+#define PCGCCTL_STPPCLK (1U<<0) /**< Stop PCLK. */
+/** @} */
+
+#if defined(STM32H7XX) || defined(__DOXYGEN__)
+/**
+ * @brief OTG_FS registers block memory address.
+ */
+#define OTG_FS_ADDR 0x40080000
+
+/**
+ * @brief OTG_HS registers block memory address.
+ */
+#define OTG_HS_ADDR 0x40040000
+#else
+#define OTG_FS_ADDR 0x50000000
+#define OTG_HS_ADDR 0x40040000
+#endif
+
+/**
+ * @brief Accesses to the OTG_FS registers block.
+ */
+#define OTG_FS ((stm32_otg_t *)OTG_FS_ADDR)
+
+/**
+ * @brief Accesses to the OTG_HS registers block.
+ */
+#define OTG_HS ((stm32_otg_t *)OTG_HS_ADDR)
+
+#endif /* STM32_OTG_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk
new file mode 100644
index 0000000..e59aec0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_WSPI TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.c
new file mode 100644
index 0000000..678339a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.c
@@ -0,0 +1,375 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file QUADSPIv1//hal_wspi_lld.c
+ * @brief STM32 WSPI subsystem low level driver source.
+ *
+ * @addtogroup WSPI
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define QUADSPI1_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_WSPI_QUADSPI1_DMA_STREAM, \
+ STM32_QUADSPI1_DMA_CHN)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief QUADSPI1 driver identifier.*/
+#if STM32_WSPI_USE_QUADSPI1 || defined(__DOXYGEN__)
+WSPIDriver WSPID1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Waits for completion of previous operation.
+ */
+static inline void wspi_lld_sync(WSPIDriver *wspip) {
+
+ while ((wspip->qspi->SR & QUADSPI_SR_BUSY) != 0U) {
+ }
+}
+
+/**
+ * @brief Shared service routine.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void wspi_lld_serve_dma_interrupt(WSPIDriver *wspip, uint32_t flags) {
+
+ (void)wspip;
+ (void)flags;
+
+ /* DMA errors handling.*/
+#if defined(STM32_WSPI_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_WSPI_DMA_ERROR_HOOK(wspip);
+ }
+#endif
+}
+
+/**
+ * @brief Shared service routine.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ */
+static void wspi_lld_serve_interrupt(WSPIDriver *wspip) {
+
+ /* Portable WSPI ISR code defined in the high level driver, note, it is
+ a macro.*/
+ _wspi_isr_code(wspip);
+
+ /* Stop everything, we need to give DMA enough time to complete the ongoing
+ operation. Race condition hidden here.*/
+ while (dmaStreamGetTransactionSize(wspip->dma) > 0U)
+ ;
+
+ /* Handling of errata: Extra data written in the FIFO at the end of a
+ read transfer.*/
+ if (wspip->state == WSPI_RECEIVE) {
+ while ((wspip->qspi->SR & QUADSPI_SR_BUSY) != 0U) {
+ (void) wspip->qspi->DR;
+ }
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_WSPI_USE_QUADSPI1 || defined(__DOXYGEN__)
+#if !defined(STM32_QUADSPI1_SUPPRESS_ISR)
+#if !defined(STM32_QUADSPI1_HANDLER)
+#error "STM32_QUADSPI1_HANDLER not defined"
+#endif
+/**
+ * @brief STM32_QUADSPI1_HANDLER interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_QUADSPI1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ QUADSPI->FCR = QUADSPI_FCR_CTEF | QUADSPI_FCR_CTCF |
+ QUADSPI_FCR_CSMF | QUADSPI_FCR_CTOF;
+
+ wspi_lld_serve_interrupt(&WSPID1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_QUADSPI1_SUPPRESS_ISR) */
+#endif /* STM32_WSPI_USE_QUADSPI1 */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level WSPI driver initialization.
+ *
+ * @notapi
+ */
+void wspi_lld_init(void) {
+
+#if STM32_WSPI_USE_QUADSPI1
+ wspiObjectInit(&WSPID1);
+ WSPID1.qspi = QUADSPI;
+ WSPID1.dma = NULL;
+ WSPID1.dmamode = STM32_DMA_CR_CHSEL(QUADSPI1_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_WSPI_QUADSPI1_DMA_PRIORITY) |
+ STM32_DMA_CR_PSIZE_BYTE |
+ STM32_DMA_CR_MSIZE_BYTE |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ nvicEnableVector(STM32_QUADSPI1_NUMBER, STM32_WSPI_QUADSPI1_IRQ_PRIORITY);
+#endif
+}
+
+/**
+ * @brief Configures and activates the WSPI peripheral.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @notapi
+ */
+void wspi_lld_start(WSPIDriver *wspip) {
+
+ /* If in stopped state then full initialization.*/
+ if (wspip->state == WSPI_STOP) {
+#if STM32_WSPI_USE_QUADSPI1
+ if (&WSPID1 == wspip) {
+ wspip->dma = dmaStreamAllocI(STM32_WSPI_QUADSPI1_DMA_STREAM,
+ STM32_WSPI_QUADSPI1_DMA_IRQ_PRIORITY,
+ (stm32_dmaisr_t)wspi_lld_serve_dma_interrupt,
+ (void *)wspip);
+ osalDbgAssert(wspip->dma != NULL, "unable to allocate stream");
+ rccEnableQUADSPI1(true);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(wspip->dma, STM32_DMAMUX1_QUADSPI);
+#endif
+ }
+#endif
+
+ /* Common initializations.*/
+ dmaStreamSetPeripheral(wspip->dma, &wspip->qspi->DR);
+ }
+
+ /* WSPI setup and enable.*/
+ wspip->qspi->DCR = wspip->config->dcr;
+ wspip->qspi->CR = ((STM32_WSPI_QUADSPI1_PRESCALER_VALUE - 1U) << 24U) |
+ QUADSPI_CR_TCIE | QUADSPI_CR_DMAEN | QUADSPI_CR_EN;
+ wspip->qspi->FCR = QUADSPI_FCR_CTEF | QUADSPI_FCR_CTCF |
+ QUADSPI_FCR_CSMF | QUADSPI_FCR_CTOF;
+}
+
+/**
+ * @brief Deactivates the WSPI peripheral.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @notapi
+ */
+void wspi_lld_stop(WSPIDriver *wspip) {
+
+ /* If in ready state then disables the QUADSPI clock.*/
+ if (wspip->state == WSPI_READY) {
+
+ /* WSPI disable.*/
+ wspip->qspi->CR = 0U;
+
+ /* Releasing the DMA.*/
+ dmaStreamFreeI(wspip->dma);
+ wspip->dma = NULL;
+
+ /* Stopping involved clocks.*/
+#if STM32_WSPI_USE_QUADSPI1
+ if (&WSPID1 == wspip) {
+ rccDisableQUADSPI1();
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Sends a command without data phase.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ *
+ * @notapi
+ */
+void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp) {
+
+#if STM32_USE_STM32_D1_WORKAROUND == TRUE
+ /* If it is a command without address and alternate phases then the command
+ is sent as an alternate byte, the command phase is suppressed.*/
+ if ((cmdp->cfg & (WSPI_CFG_ADDR_MODE_MASK | WSPI_CFG_ALT_MODE_MASK)) == 0U) {
+ /* The command mode field is copied in the alternate mode field. All
+ other fields are not used in this scenario.*/
+ wspip->qspi->DLR = 0U;
+ wspip->qspi->ABR = cmdp->cmd;
+ wspip->qspi->CCR = (cmdp->cfg & WSPI_CFG_CMD_MODE_MASK) << 6U;
+ return;
+ }
+#endif
+ wspip->qspi->DLR = 0U;
+ wspip->qspi->ABR = cmdp->alt;
+ wspip->qspi->CCR = cmdp->cmd | cmdp->cfg;
+ if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) {
+ wspip->qspi->AR = cmdp->addr;
+ }
+
+ /* Waiting for the previous operation to complete.*/
+ wspi_lld_sync(wspip);
+}
+
+/**
+ * @brief Sends a command with data over the WSPI bus.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[in] n number of bytes to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @notapi
+ */
+void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, const uint8_t *txbuf) {
+
+ dmaStreamSetMemory0(wspip->dma, txbuf);
+ dmaStreamSetTransactionSize(wspip->dma, n);
+ dmaStreamSetMode(wspip->dma, wspip->dmamode | STM32_DMA_CR_DIR_M2P);
+
+ wspip->qspi->DLR = n - 1;
+ wspip->qspi->ABR = cmdp->alt;
+ wspip->qspi->CCR = cmdp->cmd | cmdp->cfg;
+ if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) {
+ wspip->qspi->AR = cmdp->addr;
+ }
+
+ dmaStreamEnable(wspip->dma);
+}
+
+/**
+ * @brief Sends a command then receives data over the WSPI bus.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[in] n number of bytes to send
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, uint8_t *rxbuf) {
+
+ dmaStreamSetMemory0(wspip->dma, rxbuf);
+ dmaStreamSetTransactionSize(wspip->dma, n);
+ dmaStreamSetMode(wspip->dma, wspip->dmamode | STM32_DMA_CR_DIR_P2M);
+
+ wspip->qspi->DLR = n - 1;
+ wspip->qspi->ABR = cmdp->alt;
+ wspip->qspi->CCR = cmdp->cmd | cmdp->cfg |
+ QUADSPI_CCR_DUMMY_CYCLES(cmdp->dummy) |
+ QUADSPI_CCR_FMODE_0;
+ if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) {
+ wspip->qspi->AR = cmdp->addr;
+ }
+
+ dmaStreamEnable(wspip->dma);
+}
+
+#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Maps in memory space a WSPI flash device.
+ * @pre The memory flash device must be initialized appropriately
+ * before mapping it in memory space.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[out] addrp pointer to the memory start address of the mapped
+ * flash or @p NULL
+ *
+ * @notapi
+ */
+void wspi_lld_map_flash(WSPIDriver *wspip,
+ const wspi_command_t *cmdp,
+ uint8_t **addrp) {
+
+ /* Disabling the DMA request while in memory mapped mode.*/
+ wspip->qspi->CR &= ~QUADSPI_CR_DMAEN;
+
+ /* Starting memory mapped mode using the passed parameters.*/
+ wspip->qspi->DLR = 0;
+ wspip->qspi->ABR = 0;
+ wspip->qspi->AR = 0;
+ wspip->qspi->CCR = cmdp->cmd | cmdp->cfg |
+ QUADSPI_CCR_DUMMY_CYCLES(cmdp->dummy) |
+ QUADSPI_CCR_FMODE_1 | QUADSPI_CCR_FMODE_0;
+
+ /* Mapped flash absolute base address.*/
+ if (addrp != NULL) {
+ *addrp = (uint8_t *)0x90000000;
+ }
+}
+
+/**
+ * @brief Unmaps from memory space a WSPI flash device.
+ * @post The memory flash device must be re-initialized for normal
+ * commands exchange.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @notapi
+ */
+void wspi_lld_unmap_flash(WSPIDriver *wspip) {
+
+ /* Aborting memory mapped mode.*/
+ wspip->qspi->CR |= QUADSPI_CR_ABORT;
+ while ((wspip->qspi->CR & QUADSPI_CR_ABORT) != 0U) {
+ }
+
+ /* Re-enabling DMA request, we are going back to indirect mode.*/
+ wspip->qspi->CR |= QUADSPI_CR_DMAEN;
+}
+#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */
+
+#endif /* HAL_USE_WSPI */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.h
new file mode 100644
index 0000000..5ebbd06
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv1/hal_wspi_lld.h
@@ -0,0 +1,313 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file QUADSPIv1/hal_wspi_lld.h
+ * @brief STM32 WSPI subsystem low level driver header.
+ *
+ * @addtogroup WSPI
+ * @{
+ */
+
+#ifndef HAL_WSPI_LLD_H
+#define HAL_WSPI_LLD_H
+
+#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name WSPI implementation capabilities
+ * @{
+ */
+#define WSPI_SUPPORTS_MEMMAP TRUE
+#define WSPI_DEFAULT_CFG_MASKS FALSE
+/** @} */
+
+/**
+ * @name Transfer options
+ * @note The low level driver has the option to override the following
+ * definitions and use its own ones. In must take care to use
+ * the same name for the same function or compatibility is not
+ * ensured.
+ * @note There are the following limitations in this implementation:
+ * - Eight lines are not supported.
+ * - DDR mode is only supported for the whole command, separate
+ * masks are defined but all define the same bit.
+ * - Only 8 bits instructions are supported.
+ * .
+ * @{
+ */
+#define WSPI_CFG_CMD_MODE_MASK (3LU << 8LU)
+#define WSPI_CFG_CMD_MODE_NONE (0LU << 8LU)
+#define WSPI_CFG_CMD_MODE_ONE_LINE (1LU << 8LU)
+#define WSPI_CFG_CMD_MODE_TWO_LINES (2LU << 8LU)
+#define WSPI_CFG_CMD_MODE_FOUR_LINES (3LU << 8LU)
+
+#define WSPI_CFG_CMD_DDR (1LU << 31LU)
+
+#define WSPI_CFG_CMD_SIZE_MASK 0LU
+#define WSPI_CFG_CMD_SIZE_8 0LU
+
+#define WSPI_CFG_ADDR_MODE_MASK (3LU << 10LU)
+#define WSPI_CFG_ADDR_MODE_NONE (0LU << 10LU)
+#define WSPI_CFG_ADDR_MODE_ONE_LINE (1LU << 10LU)
+#define WSPI_CFG_ADDR_MODE_TWO_LINES (2LU << 10LU)
+#define WSPI_CFG_ADDR_MODE_FOUR_LINES (3LU << 10LU)
+
+#define WSPI_CFG_ADDR_DDR (1LU << 31LU)
+
+#define WSPI_CFG_ADDR_SIZE_MASK (3LU << 12LU)
+#define WSPI_CFG_ADDR_SIZE_8 (0LU << 12LU)
+#define WSPI_CFG_ADDR_SIZE_16 (1LU << 12LU)
+#define WSPI_CFG_ADDR_SIZE_24 (2LU << 12LU)
+#define WSPI_CFG_ADDR_SIZE_32 (3LU << 12LU)
+
+#define WSPI_CFG_ALT_MODE_MASK (3LU << 14LU)
+#define WSPI_CFG_ALT_MODE_NONE (0LU << 14LU)
+#define WSPI_CFG_ALT_MODE_ONE_LINE (1LU << 14LU)
+#define WSPI_CFG_ALT_MODE_TWO_LINES (2LU << 14LU)
+#define WSPI_CFG_ALT_MODE_FOUR_LINES (3LU << 14LU)
+
+#define WSPI_CFG_ALT_DDR (1LU << 31LU)
+
+#define WSPI_CFG_ALT_SIZE_MASK (3LU << 16LU)
+#define WSPI_CFG_ALT_SIZE_8 (0LU << 16LU)
+#define WSPI_CFG_ALT_SIZE_16 (1LU << 16LU)
+#define WSPI_CFG_ALT_SIZE_24 (2LU << 16LU)
+#define WSPI_CFG_ALT_SIZE_32 (3LU << 16LU)
+
+#define WSPI_CFG_DATA_MODE_MASK (3LU << 24LU)
+#define WSPI_CFG_DATA_MODE_NONE (0LU << 24LU)
+#define WSPI_CFG_DATA_MODE_ONE_LINE (1LU << 24LU)
+#define WSPI_CFG_DATA_MODE_TWO_LINES (2LU << 24LU)
+#define WSPI_CFG_DATA_MODE_FOUR_LINES (3LU << 24LU)
+
+#define WSPI_CFG_DATA_DDR (1LU << 31LU)
+
+#define WSPI_CFG_SIOO (1LU << 28LU)
+/** @} */
+
+/**
+ * @name Helpers for CCR register.
+ * @{
+ */
+#define QUADSPI_CCR_DUMMY_CYCLES_MASK (0x1FLU << 18LU)
+#define QUADSPI_CCR_DUMMY_CYCLES(n) ((n) << 18LU)
+/** @} */
+
+/**
+ * @name DCR register options
+ * @{
+ */
+#define STM32_DCR_CK_MODE (1U << 0U)
+#define STM32_DCR_CSHT_MASK (7U << 8U)
+#define STM32_DCR_CSHT(n) ((n) << 8U)
+#define STM32_DCR_FSIZE_MASK (31U << 16U)
+#define STM32_DCR_FSIZE(n) ((n) << 16U)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief WSPID1 driver enable switch.
+ * @details If set to @p TRUE the support for QUADSPI1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_WSPI_USE_QUADSPI1) || defined(__DOXYGEN__)
+#define STM32_WSPI_USE_QUADSPI1 FALSE
+#endif
+
+/**
+ * @brief QUADSPI1 prescaler setting.
+ * @note This is the prescaler divider value 1..256. The maximum frequency
+ * varies depending on the STM32 model and operating conditions,
+ * find the details in the data sheet.
+ */
+#if !defined(STM32_WSPI_QUADSPI1_PRESCALER_VALUE) || defined(__DOXYGEN__)
+#define STM32_WSPI_QUADSPI1_PRESCALER_VALUE 1
+#endif
+
+/**
+ * @brief QUADSPI1 interrupt priority level setting.
+ */
+#if !defined(STM32_WSPI_QUADSPI1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_WSPI_QUADSPI1_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief QUADSPI1 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_WSPI_QUADSPI1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_WSPI_QUADSPI1_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief QUADSPI1 DMA interrupt priority level setting.
+ */
+#if !defined(STM32_WSPI_QUADSPI1_DMA_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_WSPI_QUADSPI1_DMA_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief QUADSPI DMA error hook.
+ */
+#if !defined(STM32_WSPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define STM32_WSPI_DMA_ERROR_HOOK(qspip) osalSysHalt("DMA failure")
+#endif
+
+/**
+ * @brief Enables a workaround for a STM32L476 QUADSPI errata.
+ * @details The document DM00111498 states: "QUADSPI_BK1_IO1 is always an
+ * input when the command is sent in dual or quad SPI mode".
+ * This workaround makes commands without address or data phases
+ * to be sent as alternate bytes.
+ */
+#if !defined(STM32_USE_STM32_D1_WORKAROUND) || defined(__DOXYGEN__)
+#define STM32_USE_STM32_D1_WORKAROUND TRUE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !defined(STM32_HAS_QUADSPI1)
+#define STM32_HAS_QUADSPI1 FALSE
+#endif
+
+#if STM32_WSPI_USE_QUADSPI1 && !STM32_HAS_QUADSPI1
+#error "QUADSPI1 not present in the selected device"
+#endif
+
+#if !STM32_WSPI_USE_QUADSPI1
+#error "WSPI driver activated but no QUADSPI peripheral assigned"
+#endif
+
+#if STM32_WSPI_USE_QUADSPI1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_QUADSPI1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to QUADSPI1"
+#endif
+
+#if STM32_WSPI_USE_QUADSPI1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_WSPI_QUADSPI1_DMA_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to QUADSPI1 DMA"
+#endif
+
+#if STM32_WSPI_USE_QUADSPI1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_WSPI_QUADSPI1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to QUADSPI1"
+#endif
+
+#if (STM32_WSPI_QUADSPI1_PRESCALER_VALUE < 1) || \
+ (STM32_WSPI_QUADSPI1_PRESCALER_VALUE > 256)
+#error "STM32_WSPI_QUADSPI1_PRESCALER_VALUE not within 1..256"
+#endif
+
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if STM32_WSPI_USE_QUADSPI1 && !defined(STM32_WSPI_QUADSPI1_DMA_STREAM)
+#error "QUADSPI1 DMA stream not defined"
+#endif
+
+/* Check on the validity of the assigned DMA channels.*/
+#if STM32_WSPI_USE_QUADSPI1 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_WSPI_QUADSPI1_DMA_STREAM)
+#error "invalid DMA stream associated to QUADSPI1"
+#endif
+
+/* Devices without DMAMUX require an additional check.*/
+#if !STM32_DMA_SUPPORTS_DMAMUX
+
+/* Check on the validity of the assigned DMA channels.*/
+#if STM32_WSPI_USE_QUADSPI1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_WSPI_QUADSPI1_DMA_STREAM, STM32_QUADSPI1_DMA_MSK)
+#error "invalid DMA stream associated to QUADSPI1"
+#endif
+
+#endif /* !STM32_DMA_SUPPORTS_DMAMUX */
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the WSPI configuration structure.
+ */
+#define wspi_lld_config_fields \
+ /* DCR register initialization data.*/ \
+ uint32_t dcr
+
+/**
+ * @brief Low level fields of the WSPI driver structure.
+ */
+#define wspi_lld_driver_fields \
+ /* Pointer to the QUADSPIx registers block.*/ \
+ QUADSPI_TypeDef *qspi; \
+ /* QUADSPI DMA stream.*/ \
+ const stm32_dma_stream_t *dma; \
+ /* QUADSPI DMA mode bit mask.*/ \
+ uint32_t dmamode
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (STM32_WSPI_USE_QUADSPI1 == TRUE) && !defined(__DOXYGEN__)
+extern WSPIDriver WSPID1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void wspi_lld_init(void);
+ void wspi_lld_start(WSPIDriver *wspip);
+ void wspi_lld_stop(WSPIDriver *wspip);
+ void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp);
+ void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, const uint8_t *txbuf);
+ void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, uint8_t *rxbuf);
+#if WSPI_SUPPORTS_MEMMAP == TRUE
+ void wspi_lld_map_flash(WSPIDriver *wspip,
+ const wspi_command_t *cmdp,
+ uint8_t **addrp);
+ void wspi_lld_unmap_flash(WSPIDriver *wspip);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_WSPI */
+
+#endif /* HAL_WSPI_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv2/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv2/driver.mk
new file mode 100644
index 0000000..0a9e099
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv2/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_WSPI TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv2
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.c
new file mode 100644
index 0000000..118556b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.c
@@ -0,0 +1,356 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file QUADSPIv2//hal_wspi_lld.c
+ * @brief STM32 WSPI subsystem low level driver source.
+ *
+ * @addtogroup WSPI
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief QUADSPI1 driver identifier.*/
+#if STM32_WSPI_USE_QUADSPI1 || defined(__DOXYGEN__)
+WSPIDriver WSPID1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Waits for completion of previous operation.
+ */
+static inline void wspi_lld_sync(WSPIDriver *wspip) {
+
+ while ((wspip->qspi->SR & QUADSPI_SR_BUSY) != 0U) {
+ }
+}
+
+/**
+ * @brief Shared service routine.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] flags content of the CISR register
+ */
+static void wspi_lld_serve_mdma_interrupt(WSPIDriver *wspip, uint32_t flags) {
+
+ (void)wspip;
+ (void)flags;
+
+ /* DMA errors handling.*/
+#if defined(STM32_WSPI_MDMA_ERROR_HOOK)
+ if ((flags & STM32_MDMA_CISR_TEIF) != 0) {
+ STM32_WSPI_MDMA_ERROR_HOOK(wspip);
+ }
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level WSPI driver initialization.
+ *
+ * @notapi
+ */
+void wspi_lld_init(void) {
+
+#if STM32_WSPI_USE_QUADSPI1
+ wspiObjectInit(&WSPID1);
+ WSPID1.qspi = QUADSPI;
+ WSPID1.mdma = NULL;
+#endif
+}
+
+/**
+ * @brief Configures and activates the WSPI peripheral.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @notapi
+ */
+void wspi_lld_start(WSPIDriver *wspip) {
+
+ /* If in stopped state then full initialization.*/
+ if (wspip->state == WSPI_STOP) {
+#if STM32_WSPI_USE_QUADSPI1
+ if (&WSPID1 == wspip) {
+ wspip->mdma = mdmaChannelAllocI(STM32_WSPI_QUADSPI1_MDMA_CHANNEL,
+ (stm32_mdmaisr_t)wspi_lld_serve_mdma_interrupt,
+ (void *)wspip);
+ osalDbgAssert(wspip->mdma != NULL, "unable to allocate MDMA channel");
+ rccEnableQUADSPI1(true);
+ }
+#endif
+ }
+
+ /* WSPI setup and enable.*/
+ wspip->qspi->DCR = wspip->config->dcr;
+ wspip->qspi->CR = ((STM32_WSPI_QUADSPI1_PRESCALER_VALUE - 1U) << 24U) |
+ QUADSPI_CR_TCIE | QUADSPI_CR_DMAEN | QUADSPI_CR_EN;
+ wspip->qspi->FCR = QUADSPI_FCR_CTEF | QUADSPI_FCR_CTCF |
+ QUADSPI_FCR_CSMF | QUADSPI_FCR_CTOF;
+}
+
+/**
+ * @brief Deactivates the WSPI peripheral.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @notapi
+ */
+void wspi_lld_stop(WSPIDriver *wspip) {
+
+ /* If in ready state then disables the QUADSPI clock.*/
+ if (wspip->state == WSPI_READY) {
+
+ /* WSPI disable.*/
+ wspip->qspi->CR = 0U;
+
+ /* Releasing the DMA.*/
+ mdmaChannelFreeI(wspip->mdma);
+ wspip->mdma = NULL;
+
+ /* Stopping involved clocks.*/
+#if STM32_WSPI_USE_QUADSPI1
+ if (&WSPID1 == wspip) {
+ rccDisableQUADSPI1();
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Sends a command without data phase.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ *
+ * @notapi
+ */
+void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp) {
+
+#if STM32_USE_STM32_D1_WORKAROUND == TRUE
+ /* If it is a command without address and alternate phases then the command
+ is sent as an alternate byte, the command phase is suppressed.*/
+ if ((cmdp->cfg & (WSPI_CFG_ADDR_MODE_MASK | WSPI_CFG_ALT_MODE_MASK)) == 0U) {
+ /* The command mode field is copied in the alternate mode field. All
+ other fields are not used in this scenario.*/
+ wspip->qspi->DLR = 0U;
+ wspip->qspi->ABR = cmdp->cmd;
+ wspip->qspi->CCR = (cmdp->cfg & WSPI_CFG_CMD_MODE_MASK) << 6U;
+ return;
+ }
+#endif
+ wspip->qspi->DLR = 0U;
+ wspip->qspi->ABR = cmdp->alt;
+ wspip->qspi->CCR = cmdp->cmd | cmdp->cfg;
+ if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) {
+ wspip->qspi->AR = cmdp->addr;
+ }
+
+ /* Waiting for the previous operation to complete.*/
+ wspi_lld_sync(wspip);
+}
+
+/**
+ * @brief Sends a command with data over the WSPI bus.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[in] n number of bytes to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @notapi
+ */
+void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, const uint8_t *txbuf) {
+ uint32_t ctcr = STM32_MDMA_CTCR_BWM_NON_BUFF | /* Dest. non-cacheable. */
+ STM32_MDMA_CTCR_TRGM_BUFFER | /* Trigger on buffer. */
+ STM32_MDMA_CTCR_TLEN(0U) | /* One byte buffer. */
+ STM32_MDMA_CTCR_DBURST_16 | /* Assuming AXI bus. */
+ STM32_MDMA_CTCR_SBURST_16 | /* Assuming AXI bus. */
+ STM32_MDMA_CTCR_DINCOS_BYTE | /* Byte increment. */
+ STM32_MDMA_CTCR_SINCOS_BYTE | /* Byte increment. */
+ STM32_MDMA_CTCR_DSIZE_BYTE | /* Destination size. */
+ STM32_MDMA_CTCR_SSIZE_BYTE | /* Source size. */
+ STM32_MDMA_CTCR_DINC_FIXED | /* Destination fixed. */
+ STM32_MDMA_CTCR_SINC_INC; /* Source incremented. */
+ uint32_t ccr = STM32_MDMA_CCR_PL(STM32_WSPI_QUADSPI1_MDMA_PRIORITY) |
+ STM32_MDMA_CCR_CTCIE | /* On transfer complete.*/
+ STM32_MDMA_CCR_TCIE; /* On transfer error. */
+
+ /* MDMA initializations.*/
+ mdmaChannelSetSourceX(wspip->mdma, &wspip->qspi->DR);
+ mdmaChannelSetDestinationX(wspip->mdma, txbuf);
+ mdmaChannelSetTransactionSizeX(wspip->mdma, n, 0, 0);
+ mdmaChannelSetModeX(wspip->mdma, ctcr, ccr);
+
+ wspip->qspi->DLR = n - 1;
+ wspip->qspi->ABR = cmdp->alt;
+ wspip->qspi->CCR = cmdp->cmd | cmdp->cfg;
+ if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) {
+ wspip->qspi->AR = cmdp->addr;
+ }
+
+ mdmaChannelEnableX(wspip->mdma);
+}
+
+/**
+ * @brief Sends a command then receives data over the WSPI bus.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[in] n number of bytes to send
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, uint8_t *rxbuf) {
+ uint32_t ctcr = STM32_MDMA_CTCR_BWM_NON_BUFF | /* Dest. non-cacheable. */
+ STM32_MDMA_CTCR_TRGM_BUFFER | /* Trigger on buffer. */
+ STM32_MDMA_CTCR_TLEN(0U) | /* One byte buffer. */
+ STM32_MDMA_CTCR_DBURST_16 | /* Assuming AXI bus. */
+ STM32_MDMA_CTCR_SBURST_16 | /* Assuming AXI bus. */
+ STM32_MDMA_CTCR_DINCOS_BYTE | /* Byte increment. */
+ STM32_MDMA_CTCR_SINCOS_BYTE | /* Byte increment. */
+ STM32_MDMA_CTCR_DSIZE_BYTE | /* Destination size. */
+ STM32_MDMA_CTCR_SSIZE_BYTE | /* Source size. */
+ STM32_MDMA_CTCR_DINC_INC | /* Destination incr. */
+ STM32_MDMA_CTCR_SINC_FIXED; /* Source fixed. */
+ uint32_t ccr = STM32_MDMA_CCR_PL(STM32_WSPI_QUADSPI1_MDMA_PRIORITY) |
+ STM32_MDMA_CCR_CTCIE | /* On transfer complete.*/
+ STM32_MDMA_CCR_TCIE; /* On transfer error. */
+
+ /* MDMA initializations.*/
+ mdmaChannelSetSourceX(wspip->mdma, rxbuf);
+ mdmaChannelSetDestinationX(wspip->mdma, &wspip->qspi->DR);
+ mdmaChannelSetTransactionSizeX(wspip->mdma, n, 0, 0);
+ mdmaChannelSetModeX(wspip->mdma, ctcr, ccr);
+
+ wspip->qspi->DLR = n - 1;
+ wspip->qspi->ABR = cmdp->alt;
+ wspip->qspi->CCR = cmdp->cmd | cmdp->cfg |
+ QUADSPI_CCR_DUMMY_CYCLES(cmdp->dummy) |
+ QUADSPI_CCR_FMODE_0;
+ if ((cmdp->cfg & WSPI_CFG_ADDR_MODE_MASK) != WSPI_CFG_ADDR_MODE_NONE) {
+ wspip->qspi->AR = cmdp->addr;
+ }
+
+ mdmaChannelEnableX(wspip->mdma);
+}
+
+#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Maps in memory space a WSPI flash device.
+ * @pre The memory flash device must be initialized appropriately
+ * before mapping it in memory space.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[out] addrp pointer to the memory start address of the mapped
+ * flash or @p NULL
+ *
+ * @notapi
+ */
+void wspi_lld_map_flash(WSPIDriver *wspip,
+ const wspi_command_t *cmdp,
+ uint8_t **addrp) {
+
+ /* Disabling the DMA request while in memory mapped mode.*/
+ wspip->qspi->CR &= ~QUADSPI_CR_DMAEN;
+
+ /* Starting memory mapped mode using the passed parameters.*/
+ wspip->qspi->DLR = 0;
+ wspip->qspi->ABR = 0;
+ wspip->qspi->AR = 0;
+ wspip->qspi->CCR = cmdp->cmd | cmdp->cfg |
+ QUADSPI_CCR_DUMMY_CYCLES(cmdp->dummy) |
+ QUADSPI_CCR_FMODE_1 | QUADSPI_CCR_FMODE_0;
+
+ /* Mapped flash absolute base address.*/
+ if (addrp != NULL) {
+ *addrp = (uint8_t *)0x90000000;
+ }
+}
+
+/**
+ * @brief Unmaps from memory space a WSPI flash device.
+ * @post The memory flash device must be re-initialized for normal
+ * commands exchange.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @notapi
+ */
+void wspi_lld_unmap_flash(WSPIDriver *wspip) {
+
+ /* Aborting memory mapped mode.*/
+ wspip->qspi->CR |= QUADSPI_CR_ABORT;
+ while ((wspip->qspi->CR & QUADSPI_CR_ABORT) != 0U) {
+ }
+
+ /* Re-enabling DMA request, we are going back to indirect mode.*/
+ wspip->qspi->CR |= QUADSPI_CR_DMAEN;
+}
+#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */
+
+/**
+ * @brief Shared service routine.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ */
+void wspi_lld_serve_interrupt(WSPIDriver *wspip) {
+
+ wspip->qspi->FCR = QUADSPI_FCR_CTEF | QUADSPI_FCR_CTCF |
+ QUADSPI_FCR_CSMF | QUADSPI_FCR_CTOF;
+
+ /* Portable WSPI ISR code defined in the high level driver, note, it is
+ a macro.*/
+ _wspi_isr_code(wspip);
+
+ mdmaChannelDisableX(wspip->mdma);
+}
+
+#endif /* HAL_USE_WSPI */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.h
new file mode 100644
index 0000000..cf97200
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv2/hal_wspi_lld.h
@@ -0,0 +1,279 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file QUADSPIv2/hal_wspi_lld.h
+ * @brief STM32 WSPI subsystem low level driver header.
+ *
+ * @addtogroup WSPI
+ * @{
+ */
+
+#ifndef HAL_WSPI_LLD_H
+#define HAL_WSPI_LLD_H
+
+#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name WSPI implementation capabilities
+ * @{
+ */
+#define WSPI_SUPPORTS_MEMMAP TRUE
+#define WSPI_DEFAULT_CFG_MASKS FALSE
+/** @} */
+
+/**
+ * @name Transfer options
+ * @note The low level driver has the option to override the following
+ * definitions and use its own ones. In must take care to use
+ * the same name for the same function or compatibility is not
+ * ensured.
+ * @note There are the following limitations in this implementation:
+ * - Eight lines are not supported.
+ * - DDR mode is only supported for the whole command, separate
+ * masks are defined but all define the same bit.
+ * - Only 8 bits instructions are supported.
+ * .
+ * @{
+ */
+#define WSPI_CFG_CMD_MODE_MASK (3LU << 8LU)
+#define WSPI_CFG_CMD_MODE_NONE (0LU << 8LU)
+#define WSPI_CFG_CMD_MODE_ONE_LINE (1LU << 8LU)
+#define WSPI_CFG_CMD_MODE_TWO_LINES (2LU << 8LU)
+#define WSPI_CFG_CMD_MODE_FOUR_LINES (3LU << 8LU)
+
+#define WSPI_CFG_CMD_DDR (1LU << 31LU)
+
+#define WSPI_CFG_CMD_SIZE_MASK 0LU
+#define WSPI_CFG_CMD_SIZE_8 0LU
+
+#define WSPI_CFG_ADDR_MODE_MASK (3LU << 10LU)
+#define WSPI_CFG_ADDR_MODE_NONE (0LU << 10LU)
+#define WSPI_CFG_ADDR_MODE_ONE_LINE (1LU << 10LU)
+#define WSPI_CFG_ADDR_MODE_TWO_LINES (2LU << 10LU)
+#define WSPI_CFG_ADDR_MODE_FOUR_LINES (3LU << 10LU)
+
+#define WSPI_CFG_ADDR_DDR (1LU << 31LU)
+
+#define WSPI_CFG_ADDR_SIZE_MASK (3LU << 12LU)
+#define WSPI_CFG_ADDR_SIZE_8 (0LU << 12LU)
+#define WSPI_CFG_ADDR_SIZE_16 (1LU << 12LU)
+#define WSPI_CFG_ADDR_SIZE_24 (2LU << 12LU)
+#define WSPI_CFG_ADDR_SIZE_32 (3LU << 12LU)
+
+#define WSPI_CFG_ALT_MODE_MASK (3LU << 14LU)
+#define WSPI_CFG_ALT_MODE_NONE (0LU << 14LU)
+#define WSPI_CFG_ALT_MODE_ONE_LINE (1LU << 14LU)
+#define WSPI_CFG_ALT_MODE_TWO_LINES (2LU << 14LU)
+#define WSPI_CFG_ALT_MODE_FOUR_LINES (3LU << 14LU)
+
+#define WSPI_CFG_ALT_DDR (1LU << 31LU)
+
+#define WSPI_CFG_ALT_SIZE_MASK (3LU << 16LU)
+#define WSPI_CFG_ALT_SIZE_8 (0LU << 16LU)
+#define WSPI_CFG_ALT_SIZE_16 (1LU << 16LU)
+#define WSPI_CFG_ALT_SIZE_24 (2LU << 16LU)
+#define WSPI_CFG_ALT_SIZE_32 (3LU << 16LU)
+
+#define WSPI_CFG_DATA_MODE_MASK (3LU << 24LU)
+#define WSPI_CFG_DATA_MODE_NONE (0LU << 24LU)
+#define WSPI_CFG_DATA_MODE_ONE_LINE (1LU << 24LU)
+#define WSPI_CFG_DATA_MODE_TWO_LINES (2LU << 24LU)
+#define WSPI_CFG_DATA_MODE_FOUR_LINES (3LU << 24LU)
+
+#define WSPI_CFG_DATA_DDR (1LU << 31LU)
+
+#define WSPI_CFG_SIOO (1LU << 28LU)
+/** @} */
+
+/**
+ * @name Helpers for CCR register.
+ * @{
+ */
+#define QUADSPI_CCR_DUMMY_CYCLES_MASK (0x1FLU << 18LU)
+#define QUADSPI_CCR_DUMMY_CYCLES(n) ((n) << 18LU)
+/** @} */
+
+/**
+ * @name DCR register options
+ * @{
+ */
+#define STM32_DCR_CK_MODE (1U << 0U)
+#define STM32_DCR_CSHT_MASK (7U << 8U)
+#define STM32_DCR_CSHT(n) ((n) << 8U)
+#define STM32_DCR_FSIZE_MASK (31U << 16U)
+#define STM32_DCR_FSIZE(n) ((n) << 16U)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief WSPID1 driver enable switch.
+ * @details If set to @p TRUE the support for QUADSPI1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_WSPI_USE_QUADSPI1) || defined(__DOXYGEN__)
+#define STM32_WSPI_USE_QUADSPI1 FALSE
+#endif
+
+/**
+ * @brief QUADSPI1 prescaler setting.
+ * @note This is the prescaler divider value 1..256. The maximum frequency
+ * varies depending on the STM32 model and operating conditions,
+ * find the details in the data sheet.
+ */
+#if !defined(STM32_WSPI_QUADSPI1_PRESCALER_VALUE) || defined(__DOXYGEN__)
+#define STM32_WSPI_QUADSPI1_PRESCALER_VALUE 1
+#endif
+
+/**
+ * @brief QUADSPI1 MDMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_WSPI_QUADSPI1_MDMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_WSPI_QUADSPI1_MDMA_PRIORITY 1
+#endif
+
+/**
+ * @brief QUADSPI MDMA error hook.
+ */
+#if !defined(STM32_WSPI_MDMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define STM32_WSPI_MDMA_ERROR_HOOK(qspip) osalSysHalt("MDMA failure")
+#endif
+
+/**
+ * @brief Enables a workaround for a STM32L476 QUADSPI errata.
+ * @details The document DM00111498 states: "QUADSPI_BK1_IO1 is always an
+ * input when the command is sent in dual or quad SPI mode".
+ * This workaround makes commands without address or data phases
+ * to be sent as alternate bytes.
+ */
+#if !defined(STM32_USE_STM32_D1_WORKAROUND) || defined(__DOXYGEN__)
+#define STM32_USE_STM32_D1_WORKAROUND TRUE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !defined(STM32_HAS_QUADSPI1)
+#define STM32_HAS_QUADSPI1 FALSE
+#endif
+
+#if STM32_WSPI_USE_QUADSPI1 && !STM32_HAS_QUADSPI1
+#error "QUADSPI1 not present in the selected device"
+#endif
+
+#if !STM32_WSPI_USE_QUADSPI1
+#error "WSPI driver activated but no QUADSPI peripheral assigned"
+#endif
+
+/* MDMA-related checks.*/
+#if STM32_WSPI_USE_QUADSPI1 && \
+ !STM32_MDMA_IS_VALID_PRIORITY(STM32_WSPI_QUADSPI1_MDMA_PRIORITY)
+#error "Invalid MDMA priority assigned to QUADSPI1"
+#endif
+
+/* Checks on prescaler setting.*/
+#if (STM32_WSPI_QUADSPI1_PRESCALER_VALUE < 1) || \
+ (STM32_WSPI_QUADSPI1_PRESCALER_VALUE > 256)
+#error "STM32_WSPI_QUADSPI1_PRESCALER_VALUE not within 1..256"
+#endif
+
+/* Check on the presence of the DMA channels settings in mcuconf.h.*/
+#if STM32_WSPI_USE_QUADSPI1 && !defined(STM32_WSPI_QUADSPI1_MDMA_CHANNEL)
+#error "QUADSPI1 MDMA channel not defined"
+#endif
+
+/* Check on the validity of the assigned DMA channels.*/
+#if STM32_WSPI_USE_QUADSPI1 && \
+ !STM32_MDMA_IS_VALID_CHANNEL(STM32_WSPI_QUADSPI1_MDMA_CHANNEL)
+#error "invalid MDMA channel associated to QUADSPI1"
+#endif
+
+#if !defined(STM32_MDMA_REQUIRED)
+#define STM32_MDMA_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the WSPI configuration structure.
+ */
+#define wspi_lld_config_fields \
+ /* DCR register initialization data.*/ \
+ uint32_t dcr
+
+/**
+ * @brief Low level fields of the WSPI driver structure.
+ */
+#define wspi_lld_driver_fields \
+ /* Pointer to the QUADSPIx registers block.*/ \
+ QUADSPI_TypeDef *qspi; \
+ /* QUADSPI MDMA channel.*/ \
+ const stm32_mdma_channel_t *mdma
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (STM32_WSPI_USE_QUADSPI1 == TRUE) && !defined(__DOXYGEN__)
+extern WSPIDriver WSPID1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void wspi_lld_init(void);
+ void wspi_lld_start(WSPIDriver *wspip);
+ void wspi_lld_stop(WSPIDriver *wspip);
+ void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp);
+ void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, const uint8_t *txbuf);
+ void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, uint8_t *rxbuf);
+#if WSPI_SUPPORTS_MEMMAP == TRUE
+ void wspi_lld_map_flash(WSPIDriver *wspip,
+ const wspi_command_t *cmdp,
+ uint8_t **addrp);
+ void wspi_lld_unmap_flash(WSPIDriver *wspip);
+#endif
+ void wspi_lld_serve_interrupt(WSPIDriver *wspip);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_WSPI */
+
+#endif /* HAL_WSPI_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv2/stm32_quadspi1.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv2/stm32_quadspi1.inc
new file mode 100644
index 0000000..371bf77
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/QUADSPIv2/stm32_quadspi1.inc
@@ -0,0 +1,110 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file QUADSPIv2/stm32_quadspi1.inc
+ * @brief Shared QUADSPI1 handler.
+ *
+ * @addtogroup STM32_QUADSPI1_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_QUADSPI1)
+#error "STM32_HAS_QUADSPI1 not defined in registry"
+#endif
+
+#if STM32_HAS_QUADSPI1
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_QUADSPI1_PRIORITY)
+#error "STM32_IRQ_QUADSPI1_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_QUADSPI1_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_QUADSPI1_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_QUADSPI1 */
+
+/* Other checks.*/
+#if (HAL_USE_WSPI && STM32_WSPI_USE_QUADSPI1)
+#define STM32_QUADSPI1_IS_USED TRUE
+#else
+#define STM32_QUADSPI1_IS_USED FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void quadspi1_irq_init(void) {
+#if STM32_QUADSPI1_IS_USED
+ nvicEnableVector(STM32_QUADSPI1_NUMBER, STM32_IRQ_QUADSPI1_PRIORITY);
+#endif
+}
+
+static inline void quadspi1_irq_deinit(void) {
+#if STM32_QUADSPI1_IS_USED
+ nvicDisableVector(STM32_QUADSPI1_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_QUADSPI1_IS_USED|| defined(__DOXYGEN__)
+/**
+ * @brief QUADSPI1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_QUADSPI1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_WSPI
+#if STM32_WSPI_USE_QUADSPI1
+ wspi_lld_serve_interrupt(&WSPID1);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RNGv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RNGv1/driver.mk
new file mode 100644
index 0000000..3c90500
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RNGv1/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_TRNG TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.c
new file mode 100644
index 0000000..c81e433
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.c
@@ -0,0 +1,179 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_trng_lld.c
+ * @brief STM32 TRNG subsystem low level driver source.
+ *
+ * @addtogroup TRNG
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_TRNG == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief TRNGD1 driver identifier.
+ */
+#if (STM32_TRNG_USE_RNG1 == TRUE) || defined(__DOXYGEN__)
+TRNGDriver TRNGD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+static const TRNGConfig default_cfg = {.cr = 0};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level TRNG driver initialization.
+ *
+ * @notapi
+ */
+void trng_lld_init(void) {
+
+#if STM32_TRNG_USE_RNG1 == TRUE
+ /* Driver initialization.*/
+ trngObjectInit(&TRNGD1);
+ TRNGD1.rng = RNG;
+#endif
+}
+
+/**
+ * @brief Configures and activates the TRNG peripheral.
+ *
+ * @param[in] trngp pointer to the @p TRNGDriver object
+ *
+ * @notapi
+ */
+void trng_lld_start(TRNGDriver *trngp) {
+
+ /* There is no real configuration but setting up a valid pointer anyway.*/
+ if (trngp->config == NULL) {
+ trngp->config = &default_cfg;
+ }
+
+ if (trngp->state == TRNG_STOP) {
+ /* Enables the peripheral.*/
+#if STM32_TRNG_USE_RNG1 == TRUE
+ if (&TRNGD1 == trngp) {
+ rccEnableRNG(false);
+ }
+#endif
+ }
+ /* Configures the peripheral.*/
+ trngp->rng->CR |= RNG_CR_RNGEN;
+}
+
+/**
+ * @brief Deactivates the TRNG peripheral.
+ *
+ * @param[in] trngp pointer to the @p TRNGDriver object
+ *
+ * @notapi
+ */
+void trng_lld_stop(TRNGDriver *trngp) {
+
+ if (trngp->state == TRNG_READY) {
+ /* Resets the peripheral.*/
+ trngp->rng->CR &= ~RNG_CR_RNGEN;
+
+ /* Disables the peripheral.*/
+#if STM32_TRNG_USE_RNG1 == TRUE
+ if (&TRNGD1 == trngp) {
+ rccDisableRNG();
+ }
+#endif
+ }
+}
+
+/**
+ * @brief True random numbers generator.
+ * @note The function is blocking and likely performs polled waiting
+ * inside the low level implementation.
+ *
+ * @param[in] trngp pointer to the @p TRNGDriver object
+ * @param[in] size size of output buffer
+ * @param[out] out output buffer
+ * @return The operation status.
+ * @retval false if a random number has been generated.
+ * @retval true if an HW error occurred.
+ *
+ * @api
+ */
+bool trng_lld_generate(TRNGDriver *trngp, size_t size, uint8_t *out) {
+
+ while (true) {
+ uint32_t r, tmo;
+ size_t i;
+
+ /* Waiting for error conditions to be cleared.*/
+ tmo = STM32_TRNG_ERROR_CLEAR_ATTEMPTS;
+ while ((tmo > 0) && ((trngp->rng->SR & (RNG_SR_CECS | RNG_SR_SECS)) != 0)) {
+ tmo--;
+ if (tmo == 0) {
+ return true;
+ }
+ }
+
+ /* Waiting for a random number in data register.*/
+ tmo = STM32_DATA_FETCH_ATTEMPTS;
+ while ((tmo > 0) && ((trngp->rng->SR & RNG_SR_DRDY) == 0)) {
+ tmo--;
+ if (tmo == 0) {
+ return true;
+ }
+ }
+
+ /* Getting the generated random number.*/
+ r = trngp->rng->DR;
+
+ /* Writing in the output buffer.*/
+ for (i = 0; i < sizeof (uint32_t) / sizeof (uint8_t); i++) {
+ *out++ = (uint8_t)r;
+ r = r >> 8;
+ size--;
+ if (size == 0) {
+ return false;
+ }
+ }
+ }
+}
+
+#endif /* HAL_USE_TRNG == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.h
new file mode 100644
index 0000000..2a1e9ba
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RNGv1/hal_trng_lld.h
@@ -0,0 +1,141 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_trng_lld.h
+ * @brief STM32 TRNG subsystem low level driver header.
+ *
+ * @addtogroup TRNG
+ * @{
+ */
+
+#ifndef HAL_TRNG_LLD_H
+#define HAL_TRNG_LLD_H
+
+#if (HAL_USE_TRNG == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name STM32 configuration options
+ * @{
+ */
+/**
+ * @brief TRNGD1 driver enable switch.
+ * @details If set to @p TRUE the support for TRNGD1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_TRNG_USE_RNG1) || defined(__DOXYGEN__)
+#define STM32_TRNG_USE_RNG1 FALSE
+#endif
+
+/**
+ * @brief TRNGD1 error clear timeout counter.
+ * @details Number of status register fetches before failing.
+ */
+#if !defined(STM32_TRNG_ERROR_CLEAR_ATTEMPTS) || defined(__DOXYGEN__)
+#define STM32_TRNG_ERROR_CLEAR_ATTEMPTS 1000
+#endif
+
+/**
+ * @brief TRNGD1 data available timeout counter.
+ * @details Number of status register fetches before failing.
+ */
+#if !defined(STM32_DATA_FETCH_ATTEMPTS) || defined(__DOXYGEN__)
+#define STM32_DATA_FETCH_ATTEMPTS 1000
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !defined(STM32_HAS_RNG1)
+#define STM32_HAS_RNG1 FALSE
+#endif
+
+#if STM32_TRNG_USE_RNG1 && !STM32_HAS_RNG1
+#error "RNG1 not present in the selected device"
+#endif
+
+#if !STM32_TRNG_USE_RNG1
+#error "TRNG driver activated but no RNG peripheral assigned"
+#endif
+
+#if !defined(STM32_RNGCLK)
+#error "STM32_RNGCLK not defined in this HAL"
+#endif
+
+#if ((STM32_RNGCLK < 47000000) || (STM32_RNGCLK > 49000000)) && \
+ ((STM32_RNGCLK < 3500000) || (STM32_RNGCLK > 4500000))
+#if !defined(STM32_DISABLE_RNG_CLOCK_CHECK)
+#error "STM32_RNGCLK is not within a tested clock range"
+#error "define STM32_DISABLE_RNG_CLOCK_CHECK to override this check"
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the TRNG configuration structure.
+ */
+#define trng_lld_config_fields \
+ /* CR register initialization value.*/ \
+ uint32_t cr
+
+/**
+ * @brief Low level fields of the TRNG driver structure.
+ */
+#define trng_lld_driver_fields \
+ /* Pointer to the RNG registers block.*/ \
+ RNG_TypeDef *rng
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (STM32_TRNG_USE_RNG1 == TRUE) && !defined(__DOXYGEN__)
+extern TRNGDriver TRNGD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void trng_lld_init(void);
+ void trng_lld_start(TRNGDriver *trngp);
+ void trng_lld_stop(TRNGDriver *trngp);
+ bool trng_lld_generate(TRNGDriver *trngp, size_t size, uint8_t *out);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_TRNG == TRUE */
+
+#endif /* HAL_TRNG_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RNGv1/notes.txt b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RNGv1/notes.txt
new file mode 100644
index 0000000..8e0c8e5
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RNGv1/notes.txt
@@ -0,0 +1,10 @@
+STM32 RNGv1 driver.
+
+Driver capability:
+
+- Supports the STM32 TRNGv1 found on STM32L4 and STM32L4+ families.
+
+The file registry must export:
+
+STM32_HAS_RNG1 - RNG presence flag.
+
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv1/driver.mk
new file mode 100644
index 0000000..972b475
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv1/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_RTC TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.c
new file mode 100644
index 0000000..248a9c3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.c
@@ -0,0 +1,447 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file RTCv1/hal_rtc_lld.c
+ * @brief STM32 RTC subsystem low level driver header.
+ *
+ * @addtogroup RTC
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_RTC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief RTC driver identifier.
+ */
+RTCDriver RTCD1;
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Wait for synchronization of RTC registers with APB1 bus.
+ * @details This function must be invoked before trying to read RTC registers
+ * in the backup domain: DIV, CNT, ALR. CR registers can always
+ * be read.
+ *
+ * @notapi
+ */
+static void rtc_apb1_sync(void) {
+
+ while ((RTC->CRL & RTC_CRL_RSF) == 0)
+ ;
+}
+
+/**
+ * @brief Wait for for previous write operation complete.
+ * @details This function must be invoked before writing to any RTC registers
+ *
+ * @notapi
+ */
+static void rtc_wait_write_completed(void) {
+
+ while ((RTC->CRL & RTC_CRL_RTOFF) == 0)
+ ;
+}
+
+/**
+ * @brief Acquires write access to RTC registers.
+ * @details Before writing to the backup domain RTC registers the previous
+ * write operation must be completed. Use this function before
+ * writing to PRL, CNT, ALR registers.
+ *
+ * @notapi
+ */
+static void rtc_acquire_access(void) {
+
+ rtc_wait_write_completed();
+ RTC->CRL |= RTC_CRL_CNF;
+}
+
+/**
+ * @brief Releases write access to RTC registers.
+ *
+ * @notapi
+ */
+static void rtc_release_access(void) {
+
+ RTC->CRL &= ~RTC_CRL_CNF;
+}
+
+/**
+ * @brief Converts time from timespec to seconds counter.
+ *
+ * @param[in] timespec pointer to a @p RTCDateTime structure
+ * @return the TR register encoding.
+ *
+ * @notapi
+ */
+static time_t rtc_encode(const RTCDateTime *timespec) {
+ struct tm tim;
+
+ rtcConvertDateTimeToStructTm(timespec, &tim, NULL);
+ return mktime(&tim);
+}
+
+/**
+ * @brief Converts time from seconds/milliseconds to timespec.
+ *
+ * @param[in] tv_sec seconds value
+ * @param[in] tv_msec milliseconds value
+ * @param[out] timespec pointer to a @p RTCDateTime structure
+ *
+ * @notapi
+ */
+static void rtc_decode(uint32_t tv_sec,
+ uint32_t tv_msec,
+ RTCDateTime *timespec) {
+ struct tm tim;
+ struct tm *t;
+ const time_t time = (const time_t)tv_sec; /* Could be 64 bits.*/
+
+ /* If the conversion is successful the function returns a pointer
+ to the object the result was written into.*/
+#if defined(__GNUC__) || defined(__CC_ARM)
+ t = localtime_r(&time, &tim);
+ osalDbgAssert(t != NULL, "conversion failed");
+#else
+ t = localtime(&time);
+ memcpy(&tim, t, sizeof(struct tm));
+#endif
+
+ rtcConvertStructTmToDateTime(&tim, tv_msec, timespec);
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/**
+ * @brief RTC interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_RTC1_HANDLER) {
+ uint16_t flags;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Code hits this wait only when AHB1 bus was previously powered off by any
+ reason (standby, reset, etc). In other cases there is no waiting.*/
+ rtc_apb1_sync();
+
+ /* Mask of all enabled and pending sources.*/
+ flags = RTCD1.rtc->CRH & RTCD1.rtc->CRL;
+ RTCD1.rtc->CRL &= ~(RTC_CRL_SECF | RTC_CRL_ALRF | RTC_CRL_OWF);
+
+ if (flags & RTC_CRL_SECF)
+ RTCD1.callback(&RTCD1, RTC_EVENT_SECOND);
+
+ if (flags & RTC_CRL_ALRF)
+ RTCD1.callback(&RTCD1, RTC_EVENT_ALARM);
+
+ if (flags & RTC_CRL_OWF)
+ RTCD1.callback(&RTCD1, RTC_EVENT_OVERFLOW);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Load value of RTCCLK to prescaler registers.
+ * @note The pre-scaler must not be set on every reset as RTC clock
+ * counts are lost when it is set.
+ * @note This function designed to be called from
+ * hal_lld_backup_domain_init(). Because there is only place
+ * where possible to detect BKP domain reset event reliably.
+ *
+ * @notapi
+ */
+void rtc_lld_set_prescaler(void) {
+ syssts_t sts;
+
+ /* Entering a reentrant critical zone.*/
+ sts = osalSysGetStatusAndLockX();
+
+ rtc_acquire_access();
+ RTC->PRLH = (uint16_t)((STM32_RTCCLK - 1) >> 16) & 0x000F;
+ RTC->PRLL = (uint16_t)(((STM32_RTCCLK - 1)) & 0xFFFF);
+ rtc_release_access();
+
+ /* Leaving a reentrant critical zone.*/
+ osalSysRestoreStatusX(sts);
+}
+
+/**
+ * @brief Initialize RTC.
+ *
+ * @notapi
+ */
+void rtc_lld_init(void) {
+
+ /* RTC object initialization.*/
+ rtcObjectInit(&RTCD1);
+
+ /* RTC pointer initialization.*/
+ RTCD1.rtc = RTC;
+
+ /* RSF bit must be cleared by software after an APB1 reset or an APB1 clock
+ stop. Otherwise its value will not be actual. */
+ RTCD1.rtc->CRL &= ~RTC_CRL_RSF;
+
+ /* Required because access to PRL.*/
+ rtc_apb1_sync();
+
+ /* All interrupts initially disabled.*/
+ rtc_wait_write_completed();
+ RTCD1.rtc->CRH = 0;
+
+ /* Callback initially disabled.*/
+ RTCD1.callback = NULL;
+
+ /* IRQ vector permanently assigned to this driver.*/
+ nvicEnableVector(STM32_RTC1_NUMBER, STM32_RTC_IRQ_PRIORITY);
+}
+
+/**
+ * @brief Set current time.
+ * @note Fractional part will be silently ignored. There is no possibility
+ * to change it on STM32F1xx platform.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] timespec pointer to a @p RTCDateTime structure
+ *
+ * @notapi
+ */
+void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec) {
+ time_t tv_sec = rtc_encode(timespec);
+
+ rtcSTM32SetSec(rtcp, tv_sec);
+}
+
+/**
+ * @brief Get current time.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] timespec pointer to a @p RTCDateTime structure
+ *
+ * @notapi
+ */
+void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec) {
+ uint32_t tv_sec, tv_msec;
+
+ rtcSTM32GetSecMsec(rtcp, &tv_sec, &tv_msec);
+ rtc_decode(tv_sec, tv_msec, timespec);
+}
+
+/**
+ * @brief Set alarm time.
+ *
+ * @note Default value after BKP domain reset is 0xFFFFFFFF
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] alarm alarm identifier
+ * @param[in] alarmspec pointer to a @p RTCAlarm structure
+ *
+ * @notapi
+ */
+void rtc_lld_set_alarm(RTCDriver *rtcp,
+ rtcalarm_t alarm_number,
+ const RTCAlarm *alarmspec) {
+ syssts_t sts;
+ (void)alarm_number;
+
+ /* Entering a reentrant critical zone.*/
+ sts = osalSysGetStatusAndLockX();
+
+ rtc_acquire_access();
+ if (alarmspec != NULL) {
+ rtcp->rtc->ALRH = (uint16_t)(alarmspec->tv_sec >> 16);
+ rtcp->rtc->ALRL = (uint16_t)(alarmspec->tv_sec & 0xFFFF);
+ }
+ else {
+ rtcp->rtc->ALRH = 0;
+ rtcp->rtc->ALRL = 0;
+ }
+ rtc_release_access();
+
+ /* Leaving a reentrant critical zone.*/
+ osalSysRestoreStatusX(sts);
+}
+
+/**
+ * @brief Get current alarm.
+ * @note If an alarm has not been set then the returned alarm specification
+ * is not meaningful.
+ * @note The function can be called from any context.
+ * @note Default value after BKP domain reset is 0xFFFFFFFF.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] alarm alarm identifier
+ * @param[out] alarmspec pointer to a @p RTCAlarm structure
+ *
+ * @notapi
+ */
+void rtc_lld_get_alarm(RTCDriver *rtcp,
+ rtcalarm_t alarm_number,
+ RTCAlarm *alarmspec) {
+ syssts_t sts;
+ (void)alarm_number;
+
+ /* Entering a reentrant critical zone.*/
+ sts = osalSysGetStatusAndLockX();
+
+ /* Required because access to ALR.*/
+ rtc_apb1_sync();
+
+ alarmspec->tv_sec = ((rtcp->rtc->ALRH << 16) + rtcp->rtc->ALRL);
+
+ /* Leaving a reentrant critical zone.*/
+ osalSysRestoreStatusX(sts);
+}
+
+/**
+ * @brief Enables or disables RTC callbacks.
+ * @details This function enables or disables callbacks, use a @p NULL pointer
+ * in order to disable a callback.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] callback callback function pointer or @p NULL
+ *
+ * @notapi
+ */
+void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) {
+ syssts_t sts;
+
+ /* Entering a reentrant critical zone.*/
+ sts = osalSysGetStatusAndLockX();
+
+ if (callback != NULL) {
+
+ /* IRQ sources enabled only after setting up the callback.*/
+ rtcp->callback = callback;
+
+ rtc_wait_write_completed();
+ rtcp->rtc->CRL &= ~(RTC_CRL_OWF | RTC_CRL_ALRF | RTC_CRL_SECF);
+ rtcp->rtc->CRH = RTC_CRH_OWIE | RTC_CRH_ALRIE | RTC_CRH_SECIE;
+ }
+ else {
+ rtc_wait_write_completed();
+ rtcp->rtc->CRH = 0;
+
+ /* Callback set to NULL only after disabling the IRQ sources.*/
+ rtcp->callback = NULL;
+ }
+
+ /* Leaving a reentrant critical zone.*/
+ osalSysRestoreStatusX(sts);
+}
+
+/**
+ * @brief Get seconds and (optionally) milliseconds from RTC.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[out] tv_sec pointer to seconds value
+ * @param[out] tv_msec pointer to milliseconds value, set it
+ * to @p NULL if not needed
+ *
+ * @api
+ */
+void rtcSTM32GetSecMsec(RTCDriver *rtcp, uint32_t *tv_sec, uint32_t *tv_msec) {
+ uint32_t time_frac;
+ syssts_t sts;
+
+ osalDbgCheck((NULL != tv_sec) && (NULL != rtcp));
+
+ /* Entering a reentrant critical zone.*/
+ sts = osalSysGetStatusAndLockX();
+
+ /* Required because access to CNT and DIV.*/
+ rtc_apb1_sync();
+
+ /* wait for previous write accesses to complete.*/
+ rtc_wait_write_completed();
+
+ /* Loops until two consecutive read returning the same value.*/
+ do {
+ *tv_sec = ((uint32_t)(rtcp->rtc->CNTH) << 16) + rtcp->rtc->CNTL;
+ time_frac = (((uint32_t)rtcp->rtc->DIVH) << 16) + (uint32_t)rtcp->rtc->DIVL;
+ } while ((*tv_sec) != (((uint32_t)(rtcp->rtc->CNTH) << 16) + rtcp->rtc->CNTL));
+
+ /* Leaving a reentrant critical zone.*/
+ osalSysRestoreStatusX(sts);
+
+ if (NULL != tv_msec)
+ *tv_msec = (((uint32_t)STM32_RTCCLK - 1 - time_frac) * 1000) / STM32_RTCCLK;
+}
+
+/**
+ * @brief Set seconds in RTC.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] tv_sec seconds value
+ *
+ * @api
+ */
+void rtcSTM32SetSec(RTCDriver *rtcp, uint32_t tv_sec) {
+ syssts_t sts;
+
+ osalDbgCheck(NULL != rtcp);
+
+ /* Entering a reentrant critical zone.*/
+ sts = osalSysGetStatusAndLockX();
+
+ rtc_acquire_access();
+ rtcp->rtc->CNTH = (uint16_t)(tv_sec >> 16);
+ rtcp->rtc->CNTL = (uint16_t)(tv_sec & 0xFFFF);
+ rtc_release_access();
+
+ /* Leaving a reentrant critical zone.*/
+ osalSysRestoreStatusX(sts);
+}
+
+#endif /* HAL_USE_RTC */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.h
new file mode 100644
index 0000000..0926315
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv1/hal_rtc_lld.h
@@ -0,0 +1,152 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file RTCv1/hal_rtc_lld.h
+ * @brief STM32 RTC subsystem low level driver header.
+ *
+ * @addtogroup RTC
+ * @{
+ */
+
+#ifndef HAL_RTC_LLD_H
+#define HAL_RTC_LLD_H
+
+#if HAL_USE_RTC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Implementation capabilities
+ */
+/**
+ * @brief This RTC implementation supports callbacks.
+ */
+#define RTC_SUPPORTS_CALLBACKS TRUE
+
+/**
+ * @brief One alarm comparator available.
+ */
+#define RTC_ALARMS 1
+
+/**
+ * @brief Presence of a local persistent storage.
+ */
+#define RTC_HAS_STORAGE FALSE
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/*
+ * RTC driver system settings.
+ */
+#define STM32_RTC_IRQ_PRIORITY 15
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if HAL_USE_RTC && !STM32_HAS_RTC
+#error "RTC not present in the selected device"
+#endif
+
+#if STM32_RTCCLK == 0
+#error "RTC clock not enabled"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of an RTC event.
+ */
+typedef enum {
+ RTC_EVENT_SECOND = 0, /** Triggered every second. */
+ RTC_EVENT_ALARM = 1, /** Triggered on alarm. */
+ RTC_EVENT_OVERFLOW = 2 /** Triggered on counter overflow. */
+} rtcevent_t;
+
+/**
+ * @brief Type of a generic RTC callback.
+ */
+typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event);
+
+/**
+ * @brief Type of a structure representing an RTC alarm time stamp.
+ */
+typedef struct hal_rtc_alarm {
+ /**
+ * @brief Seconds since UNIX epoch.
+ */
+ uint32_t tv_sec;
+} RTCAlarm;
+
+/**
+ * @brief Implementation-specific @p RTCDriver fields.
+ */
+#define rtc_lld_driver_fields \
+ /* Pointer to the RTC registers block.*/ \
+ RTC_TypeDef *rtc; \
+ /* Callback pointer.*/ \
+ rtccb_t callback
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void rtc_lld_set_prescaler(void);
+ void rtc_lld_init(void);
+ void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec);
+ void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec);
+ void rtc_lld_set_alarm(RTCDriver *rtcp,
+ rtcalarm_t alarm_number,
+ const RTCAlarm *alarmspec);
+ void rtc_lld_get_alarm(RTCDriver *rtcp,
+ rtcalarm_t alarm_number,
+ RTCAlarm *alarmspec);
+ void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback);
+ void rtcSTM32GetSecMsec(RTCDriver *rtcp, uint32_t *tv_sec, uint32_t *tv_msec);
+ void rtcSTM32SetSec(RTCDriver *rtcp, uint32_t tv_sec);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_RTC */
+
+#endif /* HAL_RTC_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv2/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv2/driver.mk
new file mode 100644
index 0000000..25ef11d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv2/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_RTC TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c
new file mode 100644
index 0000000..aa8bb5e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.c
@@ -0,0 +1,843 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file RTCv2/hal_rtc_lld.c
+ * @brief STM32 RTC low level driver.
+ *
+ * @addtogroup RTC
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_RTC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define RTC_TR_PM_OFFSET 22
+#define RTC_TR_HT_OFFSET 20
+#define RTC_TR_HU_OFFSET 16
+#define RTC_TR_MNT_OFFSET 12
+#define RTC_TR_MNU_OFFSET 8
+#define RTC_TR_ST_OFFSET 4
+#define RTC_TR_SU_OFFSET 0
+
+#define RTC_DR_YT_OFFSET 20
+#define RTC_DR_YU_OFFSET 16
+#define RTC_DR_WDU_OFFSET 13
+#define RTC_DR_MT_OFFSET 12
+#define RTC_DR_MU_OFFSET 8
+#define RTC_DR_DT_OFFSET 4
+#define RTC_DR_DU_OFFSET 0
+
+#define RTC_CR_BKP_OFFSET 18
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief RTC driver identifier.
+ */
+RTCDriver RTCD1;
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Beginning of configuration procedure.
+ *
+ * @notapi
+ */
+static void rtc_enter_init(void) {
+
+ RTCD1.rtc->ISR |= RTC_ISR_INIT;
+ while ((RTCD1.rtc->ISR & RTC_ISR_INITF) == 0)
+ ;
+}
+
+/**
+ * @brief Finalizing of configuration procedure.
+ *
+ * @notapi
+ */
+static inline void rtc_exit_init(void) {
+
+ RTCD1.rtc->ISR &= ~RTC_ISR_INIT;
+}
+
+/**
+ * @brief Converts time from TR register encoding to timespec.
+ *
+ * @param[in] tr TR register value
+ * @param[out] timespec pointer to a @p RTCDateTime structure
+ *
+ * @notapi
+ */
+static void rtc_decode_time(uint32_t tr, RTCDateTime *timespec) {
+ uint32_t n;
+
+ n = ((tr >> RTC_TR_HT_OFFSET) & 3) * 36000000;
+ n += ((tr >> RTC_TR_HU_OFFSET) & 15) * 3600000;
+ n += ((tr >> RTC_TR_MNT_OFFSET) & 7) * 600000;
+ n += ((tr >> RTC_TR_MNU_OFFSET) & 15) * 60000;
+ n += ((tr >> RTC_TR_ST_OFFSET) & 7) * 10000;
+ n += ((tr >> RTC_TR_SU_OFFSET) & 15) * 1000;
+ timespec->millisecond = n;
+}
+
+/**
+ * @brief Converts date from DR register encoding to timespec.
+ *
+ * @param[in] dr DR register value
+ * @param[out] timespec pointer to a @p RTCDateTime structure
+ *
+ * @notapi
+ */
+static void rtc_decode_date(uint32_t dr, RTCDateTime *timespec) {
+
+ timespec->year = (((dr >> RTC_DR_YT_OFFSET) & 15) * 10) +
+ ((dr >> RTC_DR_YU_OFFSET) & 15);
+ timespec->month = (((dr >> RTC_TR_MNT_OFFSET) & 1) * 10) +
+ ((dr >> RTC_TR_MNU_OFFSET) & 15);
+ timespec->day = (((dr >> RTC_DR_DT_OFFSET) & 3) * 10) +
+ ((dr >> RTC_DR_DU_OFFSET) & 15);
+ timespec->dayofweek = (dr >> RTC_DR_WDU_OFFSET) & 7;
+}
+
+/**
+ * @brief Converts time from timespec to TR register encoding.
+ *
+ * @param[in] timespec pointer to a @p RTCDateTime structure
+ * @return the TR register encoding.
+ *
+ * @notapi
+ */
+static uint32_t rtc_encode_time(const RTCDateTime *timespec) {
+ uint32_t n, tr = 0;
+
+ /* Subseconds cannot be set.*/
+ n = timespec->millisecond / 1000;
+
+ /* Seconds conversion.*/
+ tr = tr | ((n % 10) << RTC_TR_SU_OFFSET);
+ n /= 10;
+ tr = tr | ((n % 6) << RTC_TR_ST_OFFSET);
+ n /= 6;
+
+ /* Minutes conversion.*/
+ tr = tr | ((n % 10) << RTC_TR_MNU_OFFSET);
+ n /= 10;
+ tr = tr | ((n % 6) << RTC_TR_MNT_OFFSET);
+ n /= 6;
+
+ /* Hours conversion.*/
+ tr = tr | ((n % 10) << RTC_TR_HU_OFFSET);
+ n /= 10;
+ tr = tr | (n << RTC_TR_HT_OFFSET);
+
+ return tr;
+}
+
+/**
+ * @brief Converts a date from timespec to DR register encoding.
+ *
+ * @param[in] timespec pointer to a @p RTCDateTime structure
+ * @return the DR register encoding.
+ *
+ * @notapi
+ */
+static uint32_t rtc_encode_date(const RTCDateTime *timespec) {
+ uint32_t n, dr = 0;
+
+ /* Year conversion. Note, only years last two digits are considered.*/
+ n = timespec->year;
+ dr = dr | ((n % 10) << RTC_DR_YU_OFFSET);
+ n /= 10;
+ dr = dr | ((n % 10) << RTC_DR_YT_OFFSET);
+
+ /* Months conversion.*/
+ n = timespec->month;
+ dr = dr | ((n % 10) << RTC_DR_MU_OFFSET);
+ n /= 10;
+ dr = dr | ((n % 10) << RTC_DR_MT_OFFSET);
+
+ /* Days conversion.*/
+ n = timespec->day;
+ dr = dr | ((n % 10) << RTC_DR_DU_OFFSET);
+ n /= 10;
+ dr = dr | ((n % 10) << RTC_DR_DT_OFFSET);
+
+ /* Days of week conversion.*/
+ dr = dr | (timespec->dayofweek << RTC_DR_WDU_OFFSET);
+
+ return dr;
+}
+
+#if RTC_HAS_STORAGE == TRUE
+static size_t _getsize(void *instance) {
+
+ (void)instance;
+
+ return (size_t)STM32_RTC_STORAGE_SIZE;
+}
+
+static ps_error_t _read(void *instance, ps_offset_t offset,
+ size_t n, uint8_t *rp) {
+ volatile uint32_t *bkpr = &((RTCDriver *)instance)->rtc->BKP0R;
+ unsigned i;
+
+ chDbgCheck((instance != NULL) && (rp != NULL));
+ chDbgCheck((n > 0U) && (n <= STM32_RTC_STORAGE_SIZE));
+ chDbgCheck((offset < STM32_RTC_STORAGE_SIZE) &&
+ (offset + n <= STM32_RTC_STORAGE_SIZE));
+
+ for (i = 0; i < (unsigned)n; i++) {
+ unsigned index = ((unsigned)offset + i) / sizeof (uint32_t);
+ unsigned shift = ((unsigned)offset + i) % sizeof (uint32_t);
+ *rp++ = (uint8_t)(bkpr[index] >> (shift * 8U));
+ }
+
+ return PS_NO_ERROR;
+}
+
+static ps_error_t _write(void *instance, ps_offset_t offset,
+ size_t n, const uint8_t *wp) {
+ volatile uint32_t *bkpr = &((RTCDriver *)instance)->rtc->BKP0R;
+ unsigned i;
+
+ chDbgCheck((instance != NULL) && (wp != NULL));
+ chDbgCheck((n > 0U) && (n <= STM32_RTC_STORAGE_SIZE));
+ chDbgCheck((offset < STM32_RTC_STORAGE_SIZE) &&
+ (offset + n <= STM32_RTC_STORAGE_SIZE));
+
+ for (i = 0; i < (unsigned)n; i++) {
+ unsigned index = ((unsigned)offset + i) / sizeof (uint32_t);
+ unsigned shift = ((unsigned)offset + i) % sizeof (uint32_t);
+ uint32_t regval = bkpr[index];
+ regval &= ~(0xFFU << (shift * 8U));
+ regval |= (uint32_t)*wp++ << (shift * 8U);
+ bkpr[index] = regval;
+ }
+
+ return PS_NO_ERROR;
+}
+
+/**
+ * @brief VMT for the RTC storage file interface.
+ */
+struct RTCDriverVMT _rtc_lld_vmt = {
+ (size_t)0,
+ _getsize, _read, _write
+};
+#endif /* RTC_HAS_STORAGE == TRUE */
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_RTC_COMMON_HANDLER)
+#if !defined(STM32_RTC_SUPPRESS_COMMON_ISR)
+/**
+ * @brief RTC common interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_RTC_COMMON_HANDLER) {
+ uint32_t isr, clear;
+
+ OSAL_IRQ_PROLOGUE();
+
+ clear = (0U
+ | RTC_ISR_TSF
+ | RTC_ISR_TSOVF
+#if defined(RTC_ISR_TAMP1F)
+ | RTC_ISR_TAMP1F
+#endif
+#if defined(RTC_ISR_TAMP2F)
+ | RTC_ISR_TAMP2F
+#endif
+#if defined(RTC_ISR_TAMP3F)
+ | RTC_ISR_TAMP3F
+#endif
+#if defined(RTC_ISR_WUTF)
+ | RTC_ISR_WUTF
+#endif
+#if defined(RTC_ISR_ALRAF)
+ | RTC_ISR_ALRAF
+#endif
+#if defined(RTC_ISR_ALRBF)
+ | RTC_ISR_ALRBF
+#endif
+ );
+
+ isr = RTCD1.rtc->ISR;
+ RTCD1.rtc->ISR = isr & ~clear;
+
+ extiClearGroup1(EXTI_MASK1(STM32_RTC_ALARM_EXTI) |
+ EXTI_MASK1(STM32_RTC_TAMP_STAMP_EXTI) |
+ EXTI_MASK1(STM32_RTC_WKUP_EXTI));
+
+ if (RTCD1.callback != NULL) {
+ uint32_t cr = RTCD1.rtc->CR;
+ uint32_t tcr;
+
+#if defined(RTC_ISR_WUTF)
+ if (((cr & RTC_CR_WUTIE) != 0U) && ((isr & RTC_ISR_WUTF) != 0U)) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_WAKEUP);
+ }
+#endif
+
+#if defined(RTC_ISR_ALRAF)
+ if (((cr & RTC_CR_ALRAIE) != 0U) && ((isr & RTC_ISR_ALRAF) != 0U)) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_ALARM_A);
+ }
+#endif
+#if defined(RTC_ISR_ALRBF)
+ if (((cr & RTC_CR_ALRBIE) != 0U) && ((isr & RTC_ISR_ALRBF) != 0U)) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_ALARM_B);
+ }
+#endif
+
+ if ((cr & RTC_CR_TSIE) != 0U) {
+ if ((isr & RTC_ISR_TSF) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TS);
+ }
+ if ((isr & RTC_ISR_TSOVF) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TS_OVF);
+ }
+ }
+
+ /* This part is different depending on if the RTC has a TAMPCR or TAFCR
+ register.*/
+#if defined(RTC_TAFCR_TAMP1E)
+ tcr = RTCD1.rtc->TAFCR;
+ if ((tcr & RTC_TAFCR_TAMPIE) != 0U) {
+#if defined(RTC_ISR_TAMP1F)
+ if ((isr & RTC_ISR_TAMP1F) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TAMP1);
+ }
+#endif
+#if defined(RTC_ISR_TAMP2F)
+ if ((isr & RTC_ISR_TAMP2F) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TAMP2);
+ }
+#endif
+ }
+
+#else /* !defined(RTC_TAFCR_TAMP1E) */
+ tcr = RTCD1.rtc->TAMPCR;
+#if defined(RTC_ISR_TAMP1F)
+ if (((tcr & RTC_TAMPCR_TAMP1IE) != 0U) &&
+ ((isr & RTC_ISR_TAMP1F) != 0U)) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TAMP1);
+ }
+#endif
+#if defined(RTC_ISR_TAMP2F)
+ if (((tcr & RTC_TAMPCR_TAMP2IE) != 0U) &&
+ ((isr & RTC_ISR_TAMP2F) != 0U)) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TAMP2);
+ }
+#endif
+#if defined(RTC_ISR_TAMP3F)
+ if (((tcr & RTC_TAMPCR_TAMP3IE) != 0U) &&
+ ((isr & RTC_ISR_TAMP3F) != 0U)) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TAMP3);
+ }
+#endif
+#endif /* !defined(RTC_TAFCR_TAMP1E) */
+ }
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_RTC_SUPPRESS_COMMON_ISR) */
+
+#elif defined(STM32_RTC_TAMP_STAMP_HANDLER) && \
+ defined(STM32_RTC_WKUP_HANDLER) && \
+ defined(STM32_RTC_ALARM_HANDLER)
+/**
+ * @brief RTC TAMP/STAMP interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_RTC_TAMP_STAMP_HANDLER) {
+ uint32_t isr, clear;
+
+ OSAL_IRQ_PROLOGUE();
+
+ clear = (0U
+ | RTC_ISR_TSF
+ | RTC_ISR_TSOVF
+#if defined(RTC_ISR_TAMP1F)
+ | RTC_ISR_TAMP1F
+#endif
+#if defined(RTC_ISR_TAMP2F)
+ | RTC_ISR_TAMP2F
+#endif
+#if defined(RTC_ISR_TAMP3F)
+ | RTC_ISR_TAMP3F
+#endif
+ );
+
+ isr = RTCD1.rtc->ISR;
+ RTCD1.rtc->ISR = isr & ~clear;
+
+ extiClearGroup1(EXTI_MASK1(STM32_RTC_TAMP_STAMP_EXTI));
+
+ if (RTCD1.callback != NULL) {
+ uint32_t cr, tcr;
+
+ cr = RTCD1.rtc->CR;
+ if ((cr & RTC_CR_TSIE) != 0U) {
+ if ((isr & RTC_ISR_TSF) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TS);
+ }
+ if ((isr & RTC_ISR_TSOVF) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TS_OVF);
+ }
+ }
+
+ /* This part is different depending on if the RTC has a TAMPCR or TAFCR
+ register.*/
+#if defined(RTC_TAFCR_TAMP1E)
+ tcr = RTCD1.rtc->TAFCR;
+ if ((tcr & RTC_TAFCR_TAMPIE) != 0U) {
+#if defined(RTC_ISR_TAMP1F)
+ if ((isr & RTC_ISR_TAMP1F) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TAMP1);
+ }
+#endif
+#if defined(RTC_ISR_TAMP2F)
+ if ((isr & RTC_ISR_TAMP2F) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TAMP2);
+ }
+#endif
+ }
+
+#else /* !defined(RTC_TAFCR_TAMP1E) */
+ tcr = RTCD1.rtc->TAMPCR;
+#if defined(RTC_ISR_TAMP1F)
+ if (((tcr & RTC_TAMPCR_TAMP1IE) != 0U) &&
+ ((isr & RTC_ISR_TAMP1F) != 0U)) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TAMP1);
+ }
+#endif
+#if defined(RTC_ISR_TAMP2F)
+ if (((tcr & RTC_TAMPCR_TAMP2IE) != 0U) &&
+ ((isr & RTC_ISR_TAMP2F) != 0U)) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TAMP2);
+ }
+#endif
+#if defined(RTC_ISR_TAMP3F)
+ if (((tcr & RTC_TAMPCR_TAMP3IE) != 0U) &&
+ ((isr & RTC_ISR_TAMP3F) != 0U)) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TAMP3);
+ }
+#endif
+#endif /* !defined(RTC_TAFCR_TAMP1E) */
+ }
+
+ OSAL_IRQ_EPILOGUE();
+}
+/**
+ * @brief RTC wakeup interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_RTC_WKUP_HANDLER) {
+ uint32_t isr;
+
+ OSAL_IRQ_PROLOGUE();
+
+ isr = RTCD1.rtc->ISR;
+ RTCD1.rtc->ISR = isr & ~RTC_ISR_WUTF;
+
+ extiClearGroup1(EXTI_MASK1(STM32_RTC_WKUP_EXTI));
+
+ if (RTCD1.callback != NULL) {
+ uint32_t cr = RTCD1.rtc->CR;
+
+ if (((cr & RTC_CR_WUTIE) != 0U) && ((isr & RTC_ISR_WUTF) != 0U)) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_WAKEUP);
+ }
+ }
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief RTC alarm interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_RTC_ALARM_HANDLER) {
+ uint32_t isr, clear;
+
+ OSAL_IRQ_PROLOGUE();
+
+ clear = (0U
+#if defined(RTC_ISR_ALRAF)
+ | RTC_ISR_ALRAF
+#endif
+#if defined(RTC_ISR_ALRBF)
+ | RTC_ISR_ALRBF
+#endif
+ );
+
+ isr = RTCD1.rtc->ISR;
+ RTCD1.rtc->ISR = isr & ~clear;
+
+ extiClearGroup1(EXTI_MASK1(STM32_RTC_ALARM_EXTI));
+
+ if (RTCD1.callback != NULL) {
+ uint32_t cr = RTCD1.rtc->CR;
+#if defined(RTC_ISR_ALRAF)
+ if (((cr & RTC_CR_ALRAIE) != 0U) && ((isr & RTC_ISR_ALRAF) != 0U)) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_ALARM_A);
+ }
+#endif
+#if defined(RTC_ISR_ALRBF)
+ if (((cr & RTC_CR_ALRBIE) != 0U) && ((isr & RTC_ISR_ALRBF) != 0U)) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_ALARM_B);
+ }
+#endif
+ }
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#else
+#error "missing required RTC handlers definitions in registry"
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Enable access to registers.
+ *
+ * @notapi
+ */
+void rtc_lld_init(void) {
+
+ /* RTC object initialization.*/
+ rtcObjectInit(&RTCD1);
+
+ /* RTC pointer initialization.*/
+ RTCD1.rtc = RTC;
+
+ /* Disable write protection. */
+ RTCD1.rtc->WPR = 0xCA;
+ RTCD1.rtc->WPR = 0x53;
+
+ /* If calendar has not been initialized yet then proceed with the
+ initial setup.*/
+ if (!(RTCD1.rtc->ISR & RTC_ISR_INITS)) {
+
+ rtc_enter_init();
+
+ RTCD1.rtc->CR = STM32_RTC_CR_INIT;
+#if defined(RTC_TAFCR_TAMP1E)
+ RTCD1.rtc->TAFCR = STM32_RTC_TAMPCR_INIT;
+#else
+ RTCD1.rtc->TAMPCR = STM32_RTC_TAMPCR_INIT;
+#endif
+ RTCD1.rtc->ISR = RTC_ISR_INIT; /* Clearing all but RTC_ISR_INIT. */
+ RTCD1.rtc->PRER = STM32_RTC_PRER_BITS;
+ RTCD1.rtc->PRER = STM32_RTC_PRER_BITS;
+
+ rtc_exit_init();
+ }
+ else {
+ RTCD1.rtc->ISR &= ~RTC_ISR_RSF;
+ }
+
+ /* Callback initially disabled.*/
+ RTCD1.callback = NULL;
+
+ /* Enabling RTC-related EXTI lines.*/
+ extiEnableGroup1(EXTI_MASK1(STM32_RTC_ALARM_EXTI) |
+ EXTI_MASK1(STM32_RTC_TAMP_STAMP_EXTI) |
+ EXTI_MASK1(STM32_RTC_WKUP_EXTI),
+ EXTI_MODE_RISING_EDGE | EXTI_MODE_ACTION_INTERRUPT);
+
+ /* IRQ vectors permanently assigned to this driver.*/
+ STM32_RTC_IRQ_ENABLE();
+}
+
+/**
+ * @brief Set current time.
+ * @note Fractional part will be silently ignored. There is no possibility
+ * to set it on STM32 platform.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] timespec pointer to a @p RTCDateTime structure
+ *
+ * @notapi
+ */
+void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec) {
+ uint32_t dr, tr;
+ syssts_t sts;
+
+ tr = rtc_encode_time(timespec);
+ dr = rtc_encode_date(timespec);
+
+ /* Entering a reentrant critical zone.*/
+ sts = osalSysGetStatusAndLockX();
+
+ /* Writing the registers.*/
+ rtc_enter_init();
+ rtcp->rtc->TR = tr;
+ rtcp->rtc->DR = dr;
+ rtcp->rtc->CR = (rtcp->rtc->CR & ~(1U << RTC_CR_BKP_OFFSET)) |
+ (timespec->dstflag << RTC_CR_BKP_OFFSET);
+ rtc_exit_init();
+
+ /* Leaving a reentrant critical zone.*/
+ osalSysRestoreStatusX(sts);
+}
+
+/**
+ * @brief Get current time.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[out] timespec pointer to a @p RTCDateTime structure
+ *
+ * @notapi
+ */
+void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec) {
+ uint32_t dr, tr, cr;
+ uint32_t subs;
+#if STM32_RTC_HAS_SUBSECONDS
+ uint32_t ssr;
+#endif /* STM32_RTC_HAS_SUBSECONDS */
+ syssts_t sts;
+
+ /* Entering a reentrant critical zone.*/
+ sts = osalSysGetStatusAndLockX();
+
+ /* Synchronization with the RTC and reading the registers, note
+ DR must be read last.*/
+ while ((rtcp->rtc->ISR & RTC_ISR_RSF) == 0)
+ ;
+#if STM32_RTC_HAS_SUBSECONDS
+ ssr = rtcp->rtc->SSR;
+#endif /* STM32_RTC_HAS_SUBSECONDS */
+ tr = rtcp->rtc->TR;
+ dr = rtcp->rtc->DR;
+ cr = rtcp->rtc->CR;
+ rtcp->rtc->ISR &= ~RTC_ISR_RSF;
+
+ /* Leaving a reentrant critical zone.*/
+ osalSysRestoreStatusX(sts);
+
+ /* Decoding day time, this starts the atomic read sequence, see "Reading
+ the calendar" in the RTC documentation.*/
+ rtc_decode_time(tr, timespec);
+
+ /* If the RTC is capable of sub-second counting then the value is
+ normalized in milliseconds and added to the time.*/
+#if STM32_RTC_HAS_SUBSECONDS
+ subs = (((STM32_RTC_PRESS_VALUE - 1U) - ssr) * 1000U) / STM32_RTC_PRESS_VALUE;
+#else
+ subs = 0;
+#endif /* STM32_RTC_HAS_SUBSECONDS */
+ timespec->millisecond += subs;
+
+ /* Decoding date, this concludes the atomic read sequence.*/
+ rtc_decode_date(dr, timespec);
+
+ /* Retrieving the DST bit.*/
+ timespec->dstflag = (cr >> RTC_CR_BKP_OFFSET) & 1;
+}
+
+#if (RTC_ALARMS > 0) || defined(__DOXYGEN__)
+/**
+ * @brief Set alarm time.
+ * @note Default value after BKP domain reset for both comparators is 0.
+ * @note Function does not performs any checks of alarm time validity.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure.
+ * @param[in] alarm alarm identifier. Can be 0 or 1.
+ * @param[in] alarmspec pointer to a @p RTCAlarm structure.
+ *
+ * @notapi
+ */
+void rtc_lld_set_alarm(RTCDriver *rtcp,
+ rtcalarm_t alarm,
+ const RTCAlarm *alarmspec) {
+ syssts_t sts;
+
+ /* Entering a reentrant critical zone.*/
+ sts = osalSysGetStatusAndLockX();
+
+ if (alarm == 0) {
+ if (alarmspec != NULL) {
+ rtcp->rtc->CR &= ~RTC_CR_ALRAE;
+ while (!(rtcp->rtc->ISR & RTC_ISR_ALRAWF))
+ ;
+ rtcp->rtc->ALRMAR = alarmspec->alrmr;
+ rtcp->rtc->CR |= RTC_CR_ALRAE;
+ rtcp->rtc->CR |= RTC_CR_ALRAIE;
+ }
+ else {
+ rtcp->rtc->CR &= ~RTC_CR_ALRAIE;
+ rtcp->rtc->CR &= ~RTC_CR_ALRAE;
+ }
+ }
+#if RTC_ALARMS > 1
+ else {
+ if (alarmspec != NULL) {
+ rtcp->rtc->CR &= ~RTC_CR_ALRBE;
+ while (!(rtcp->rtc->ISR & RTC_ISR_ALRBWF))
+ ;
+ rtcp->rtc->ALRMBR = alarmspec->alrmr;
+ rtcp->rtc->CR |= RTC_CR_ALRBE;
+ rtcp->rtc->CR |= RTC_CR_ALRBIE;
+ }
+ else {
+ rtcp->rtc->CR &= ~RTC_CR_ALRBIE;
+ rtcp->rtc->CR &= ~RTC_CR_ALRBE;
+ }
+ }
+#endif /* RTC_ALARMS > 1 */
+
+ /* Leaving a reentrant critical zone.*/
+ osalSysRestoreStatusX(sts);
+}
+
+/**
+ * @brief Get alarm time.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] alarm alarm identifier. Can be 0 or 1.
+ * @param[out] alarmspec pointer to a @p RTCAlarm structure
+ *
+ * @notapi
+ */
+void rtc_lld_get_alarm(RTCDriver *rtcp,
+ rtcalarm_t alarm,
+ RTCAlarm *alarmspec) {
+
+ if (alarm == 0)
+ alarmspec->alrmr = rtcp->rtc->ALRMAR;
+#if RTC_ALARMS > 1
+ else
+ alarmspec->alrmr = rtcp->rtc->ALRMBR;
+#endif /* RTC_ALARMS > 1 */
+}
+#endif /* RTC_ALARMS > 0 */
+
+/**
+ * @brief Enables or disables RTC callbacks.
+ * @details This function enables or disables callbacks, use a @p NULL pointer
+ * in order to disable a callback.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] callback callback function pointer or @p NULL
+ *
+ * @notapi
+ */
+void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) {
+
+ rtcp->callback = callback;
+}
+
+#if STM32_RTC_HAS_PERIODIC_WAKEUPS || defined(__DOXYGEN__)
+/**
+ * @brief Sets time of periodic wakeup.
+ * @note Default value after BKP domain reset is 0x0000FFFF
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] wakeupspec pointer to a @p RTCWakeup structure
+ *
+ * @api
+ */
+void rtcSTM32SetPeriodicWakeup(RTCDriver *rtcp, const RTCWakeup *wakeupspec) {
+ syssts_t sts;
+
+ /* Entering a reentrant critical zone.*/
+ sts = osalSysGetStatusAndLockX();
+
+ if (wakeupspec != NULL) {
+ osalDbgCheck(wakeupspec->wutr != 0x30000);
+
+ rtcp->rtc->CR &= ~RTC_CR_WUTE;
+ rtcp->rtc->CR &= ~RTC_CR_WUTIE;
+ while (!(rtcp->rtc->ISR & RTC_ISR_WUTWF))
+ ;
+ rtcp->rtc->WUTR = wakeupspec->wutr & 0xFFFF;
+ rtcp->rtc->CR &= ~RTC_CR_WUCKSEL;
+ rtcp->rtc->CR |= (wakeupspec->wutr >> 16) & RTC_CR_WUCKSEL;
+ rtcp->rtc->CR |= RTC_CR_WUTIE;
+ rtcp->rtc->CR |= RTC_CR_WUTE;
+ }
+ else {
+ rtcp->rtc->CR &= ~RTC_CR_WUTE;
+ rtcp->rtc->CR &= ~RTC_CR_WUTIE;
+ }
+
+ /* Leaving a reentrant critical zone.*/
+ osalSysRestoreStatusX(sts);
+}
+
+/**
+ * @brief Gets time of periodic wakeup.
+ * @note Default value after BKP domain reset is 0x0000FFFF
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[out] wakeupspec pointer to a @p RTCWakeup structure
+ *
+ * @api
+ */
+void rtcSTM32GetPeriodicWakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec) {
+ syssts_t sts;
+
+ /* Entering a reentrant critical zone.*/
+ sts = osalSysGetStatusAndLockX();
+
+ wakeupspec->wutr = 0;
+ wakeupspec->wutr |= rtcp->rtc->WUTR;
+ wakeupspec->wutr |= (((uint32_t)rtcp->rtc->CR) & 0x7) << 16;
+
+ /* Leaving a reentrant critical zone.*/
+ osalSysRestoreStatusX(sts);
+}
+#endif /* STM32_RTC_HAS_PERIODIC_WAKEUPS */
+
+#endif /* HAL_USE_RTC */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.h
new file mode 100644
index 0000000..f60e798
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv2/hal_rtc_lld.h
@@ -0,0 +1,249 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file RTCv2/hal_rtc_lld.h
+ * @brief STM32 RTC low level driver header.
+ *
+ * @addtogroup RTC
+ * @{
+ */
+
+#ifndef HAL_RTC_LLD_H
+#define HAL_RTC_LLD_H
+
+#if HAL_USE_RTC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Implementation capabilities
+ */
+/**
+ * @brief Callback support int the driver.
+ */
+#define RTC_SUPPORTS_CALLBACKS TRUE
+
+/**
+ * @brief Number of alarms available.
+ */
+#define RTC_ALARMS STM32_RTC_NUM_ALARMS
+
+/**
+ * @brief Presence of a local persistent storage.
+ */
+#define RTC_HAS_STORAGE (STM32_RTC_STORAGE_SIZE > 0)
+/** @} */
+
+/**
+ * @brief RTC PRER register initializer.
+ */
+#define RTC_PRER(a, s) ((((a) - 1) << 16) | ((s) - 1))
+
+/**
+ * @name Alarm helper macros
+ * @{
+ */
+#define RTC_ALRM_MSK4 (1U << 31)
+#define RTC_ALRM_WDSEL (1U << 30)
+#define RTC_ALRM_DT(n) ((n) << 28)
+#define RTC_ALRM_DU(n) ((n) << 24)
+#define RTC_ALRM_MSK3 (1U << 23)
+#define RTC_ALRM_HT(n) ((n) << 20)
+#define RTC_ALRM_HU(n) ((n) << 16)
+#define RTC_ALRM_MSK2 (1U << 15)
+#define RTC_ALRM_MNT(n) ((n) << 12)
+#define RTC_ALRM_MNU(n) ((n) << 8)
+#define RTC_ALRM_MSK1 (1U << 7)
+#define RTC_ALRM_ST(n) ((n) << 4)
+#define RTC_ALRM_SU(n) ((n) << 0)
+/** @} */
+
+/* Requires services from the EXTI driver.*/
+#if !defined(STM32_EXTI_REQUIRED)
+#define STM32_EXTI_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief RTC PRES register initialization.
+ * @note The default is calculated for a 32768Hz clock.
+ */
+#if !defined(STM32_RTC_PRESA_VALUE) || defined(__DOXYGEN__)
+#define STM32_RTC_PRESA_VALUE 32
+#endif
+
+/**
+ * @brief RTC PRESS divider initialization.
+ * @note The default is calculated for a 32768Hz clock.
+ */
+#if !defined(STM32_RTC_PRESS_VALUE) || defined(__DOXYGEN__)
+#define STM32_RTC_PRESS_VALUE 1024
+#endif
+
+/**
+ * @brief RTC CR register initialization value.
+ * @note Use this value to initialize features not directly handled by
+ * the RTC driver.
+ */
+#if !defined(STM32_RTC_CR_INIT) || defined(__DOXYGEN__)
+#define STM32_RTC_CR_INIT 0
+#endif
+
+/**
+ * @brief RTC TAMPCR register initialization value.
+ * @note Use this value to initialize features not directly handled by
+ * the RTC driver.
+ * @note On some devices this values goes in the similar TAFCR register.
+ */
+#if !defined(STM32_RTC_TAMPCR_INIT) || defined(__DOXYGEN__)
+#define STM32_RTC_TAMPCR_INIT 0
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if HAL_USE_RTC && !STM32_HAS_RTC
+#error "RTC not present in the selected device"
+#endif
+
+#if defined(STM32_RTC_CK) && !defined(STM32_RTCCLK)
+#define STM32_RTCCLK STM32_RTC_CK
+#endif
+
+#if !defined(STM32_RTCCLK)
+#error "RTC clock not exported by HAL layer"
+#endif
+
+#if STM32_PCLK1 < (STM32_RTCCLK * 7)
+#error "STM32_PCLK1 frequency is too low"
+#endif
+
+/**
+ * @brief Initialization for the RTC_PRER register.
+ */
+#define STM32_RTC_PRER_BITS RTC_PRER(STM32_RTC_PRESA_VALUE, \
+ STM32_RTC_PRESS_VALUE)
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of an RTC event.
+ */
+typedef enum {
+ RTC_EVENT_ALARM_A = 0, /** Alarm A. */
+ RTC_EVENT_ALARM_B = 1, /** Alarm B. */
+ RTC_EVENT_TS = 2, /** Time stamp. */
+ RTC_EVENT_TS_OVF = 3, /** Time stamp overflow. */
+ RTC_EVENT_TAMP1 = 4, /** Tamper 1. */
+ RTC_EVENT_TAMP2 = 5, /** Tamper 2- */
+ RTC_EVENT_TAMP3 = 6, /** Tamper 3. */
+ RTC_EVENT_WAKEUP = 7 /** Wakeup. */
+ } rtcevent_t;
+
+/**
+ * @brief Type of a generic RTC callback.
+ */
+typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event);
+
+/**
+ * @brief Type of a structure representing an RTC alarm time stamp.
+ */
+typedef struct hal_rtc_alarm {
+ /**
+ * @brief Type of an alarm as encoded in RTC ALRMxR registers.
+ */
+ uint32_t alrmr;
+} RTCAlarm;
+
+#if STM32_RTC_HAS_PERIODIC_WAKEUPS
+/**
+ * @brief Type of a wakeup as encoded in RTC WUTR register.
+ */
+typedef struct hal_rtc_wakeup {
+ /**
+ * @brief Wakeup as encoded in RTC WUTR register.
+ * @note ((WUTR == 0) || (WUCKSEL == 3)) are a forbidden combination.
+ * @note Bits 16..18 are copied in the CR bits 0..2 (WUCKSEL).
+ */
+ uint32_t wutr;
+} RTCWakeup;
+#endif
+
+/**
+ * @brief Implementation-specific @p RTCDriver fields.
+ */
+#define rtc_lld_driver_fields \
+ /* Pointer to the RTC registers block.*/ \
+ RTC_TypeDef *rtc; \
+ /* Callback pointer.*/ \
+ rtccb_t callback
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void rtc_lld_init(void);
+ void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec);
+ void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec);
+#if RTC_SUPPORTS_CALLBACKS == TRUE
+ void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback);
+#endif
+#if RTC_ALARMS > 0
+ void rtc_lld_set_alarm(RTCDriver *rtcp,
+ rtcalarm_t alarm,
+ const RTCAlarm *alarmspec);
+ void rtc_lld_get_alarm(RTCDriver *rtcp,
+ rtcalarm_t alarm,
+ RTCAlarm *alarmspec);
+#endif
+#if STM32_RTC_HAS_PERIODIC_WAKEUPS
+ void rtcSTM32SetPeriodicWakeup(RTCDriver *rtcp, const RTCWakeup *wakeupspec);
+ void rtcSTM32GetPeriodicWakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec);
+#endif /* STM32_RTC_HAS_PERIODIC_WAKEUPS */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_RTC */
+
+#endif /* HAL_RTC_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv3/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv3/driver.mk
new file mode 100644
index 0000000..be3a5ad
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv3/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_RTC TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv3
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.c
new file mode 100644
index 0000000..6f776f3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.c
@@ -0,0 +1,717 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file RTCv3/hal_rtc_lld.c
+ * @brief STM32 RTC low level driver.
+ *
+ * @addtogroup RTC
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_RTC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define RTC_TR_PM_OFFSET RTC_TR_PM_Pos
+#define RTC_TR_HT_OFFSET RTC_TR_HT_Pos
+#define RTC_TR_HU_OFFSET RTC_TR_HU_Pos
+#define RTC_TR_MNT_OFFSET RTC_TR_MNT_Pos
+#define RTC_TR_MNU_OFFSET RTC_TR_MNU_Pos
+#define RTC_TR_ST_OFFSET RTC_TR_ST_Pos
+#define RTC_TR_SU_OFFSET RTC_TR_SU_Pos
+
+#define RTC_DR_YT_OFFSET RTC_DR_YT_Pos
+#define RTC_DR_YU_OFFSET RTC_DR_YU_Pos
+#define RTC_DR_WDU_OFFSET RTC_DR_WDU_Pos
+#define RTC_DR_MT_OFFSET RTC_DR_MT_Pos
+#define RTC_DR_MU_OFFSET RTC_DR_MU_Pos
+#define RTC_DR_DT_OFFSET RTC_DR_DT_Pos
+#define RTC_DR_DU_OFFSET RTC_DR_DU_Pos
+
+#define RTC_CR_BKP_OFFSET RTC_CR_BKP_Pos
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief RTC driver identifier.
+ */
+RTCDriver RTCD1;
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Beginning of configuration procedure.
+ *
+ * @notapi
+ */
+static void rtc_enter_init(void) {
+
+ RTCD1.rtc->ICSR |= RTC_ICSR_INIT;
+ while ((RTCD1.rtc->ICSR & RTC_ICSR_INITF) == 0)
+ ;
+}
+
+/**
+ * @brief Finalizing of configuration procedure.
+ *
+ * @notapi
+ */
+static inline void rtc_exit_init(void) {
+
+ RTCD1.rtc->ICSR &= ~RTC_ICSR_INIT;
+}
+
+/**
+ * @brief Converts time from TR register encoding to timespec.
+ *
+ * @param[in] tr TR register value
+ * @param[out] timespec pointer to a @p RTCDateTime structure
+ *
+ * @notapi
+ */
+static void rtc_decode_time(uint32_t tr, RTCDateTime *timespec) {
+ uint32_t n;
+
+ n = ((tr >> RTC_TR_HT_OFFSET) & 3) * 36000000;
+ n += ((tr >> RTC_TR_HU_OFFSET) & 15) * 3600000;
+ n += ((tr >> RTC_TR_MNT_OFFSET) & 7) * 600000;
+ n += ((tr >> RTC_TR_MNU_OFFSET) & 15) * 60000;
+ n += ((tr >> RTC_TR_ST_OFFSET) & 7) * 10000;
+ n += ((tr >> RTC_TR_SU_OFFSET) & 15) * 1000;
+ timespec->millisecond = n;
+}
+
+/**
+ * @brief Converts date from DR register encoding to timespec.
+ *
+ * @param[in] dr DR register value
+ * @param[out] timespec pointer to a @p RTCDateTime structure
+ *
+ * @notapi
+ */
+static void rtc_decode_date(uint32_t dr, RTCDateTime *timespec) {
+
+ timespec->year = (((dr >> RTC_DR_YT_OFFSET) & 15) * 10) +
+ ((dr >> RTC_DR_YU_OFFSET) & 15);
+ timespec->month = (((dr >> RTC_TR_MNT_OFFSET) & 1) * 10) +
+ ((dr >> RTC_TR_MNU_OFFSET) & 15);
+ timespec->day = (((dr >> RTC_DR_DT_OFFSET) & 3) * 10) +
+ ((dr >> RTC_DR_DU_OFFSET) & 15);
+ timespec->dayofweek = ((dr >> RTC_DR_WDU_OFFSET) & 7) + 1;
+}
+
+/**
+ * @brief Converts time from timespec to TR register encoding.
+ *
+ * @param[in] timespec pointer to a @p RTCDateTime structure
+ * @return the TR register encoding.
+ *
+ * @notapi
+ */
+static uint32_t rtc_encode_time(const RTCDateTime *timespec) {
+ uint32_t n, tr = 0;
+
+ /* Subseconds cannot be set.*/
+ n = timespec->millisecond / 1000;
+
+ /* Seconds conversion.*/
+ tr = tr | ((n % 10) << RTC_TR_SU_OFFSET);
+ n /= 10;
+ tr = tr | ((n % 6) << RTC_TR_ST_OFFSET);
+ n /= 6;
+
+ /* Minutes conversion.*/
+ tr = tr | ((n % 10) << RTC_TR_MNU_OFFSET);
+ n /= 10;
+ tr = tr | ((n % 6) << RTC_TR_MNT_OFFSET);
+ n /= 6;
+
+ /* Hours conversion.*/
+ tr = tr | ((n % 10) << RTC_TR_HU_OFFSET);
+ n /= 10;
+ tr = tr | (n << RTC_TR_HT_OFFSET);
+
+ return tr;
+}
+
+/**
+ * @brief Converts a date from timespec to DR register encoding.
+ *
+ * @param[in] timespec pointer to a @p RTCDateTime structure
+ * @return the DR register encoding.
+ *
+ * @notapi
+ */
+static uint32_t rtc_encode_date(const RTCDateTime *timespec) {
+ uint32_t n, dr = 0;
+
+ /* Year conversion. Note, only years last two digits are considered.*/
+ n = timespec->year;
+ dr = dr | ((n % 10) << RTC_DR_YU_OFFSET);
+ n /= 10;
+ dr = dr | ((n % 10) << RTC_DR_YT_OFFSET);
+
+ /* Months conversion.*/
+ n = timespec->month;
+ dr = dr | ((n % 10) << RTC_DR_MU_OFFSET);
+ n /= 10;
+ dr = dr | ((n % 10) << RTC_DR_MT_OFFSET);
+
+ /* Days conversion.*/
+ n = timespec->day;
+ dr = dr | ((n % 10) << RTC_DR_DU_OFFSET);
+ n /= 10;
+ dr = dr | ((n % 10) << RTC_DR_DT_OFFSET);
+
+ /* Days of week conversion.*/
+ dr = dr | ((timespec->dayofweek) << RTC_DR_WDU_OFFSET);
+
+ return dr;
+}
+
+#if RTC_HAS_STORAGE == TRUE
+static size_t _getsize(void *instance) {
+
+ (void)instance;
+
+ return (size_t)STM32_RTC_STORAGE_SIZE;
+}
+
+static ps_error_t _read(void *instance, ps_offset_t offset,
+ size_t n, uint8_t *rp) {
+ volatile uint32_t *bkpr = &((RTCDriver *)instance)->tamp->BKP0R;
+ unsigned i;
+
+ chDbgCheck((instance != NULL) && (rp != NULL));
+ chDbgCheck((n > 0U) && (n <= STM32_RTC_STORAGE_SIZE));
+ chDbgCheck((offset < STM32_RTC_STORAGE_SIZE) &&
+ (offset + n <= STM32_RTC_STORAGE_SIZE));
+
+ for (i = 0; i < (unsigned)n; i++) {
+ unsigned index = ((unsigned)offset + i) / sizeof (uint32_t);
+ unsigned shift = ((unsigned)offset + i) % sizeof (uint32_t);
+ *rp++ = (uint8_t)(bkpr[index] >> (shift * 8U));
+ }
+
+ return PS_NO_ERROR;
+}
+
+static ps_error_t _write(void *instance, ps_offset_t offset,
+ size_t n, const uint8_t *wp) {
+ volatile uint32_t *bkpr = &((RTCDriver *)instance)->tamp->BKP0R;
+ unsigned i;
+
+ chDbgCheck((instance != NULL) && (wp != NULL));
+ chDbgCheck((n > 0U) && (n <= STM32_RTC_STORAGE_SIZE));
+ chDbgCheck((offset < STM32_RTC_STORAGE_SIZE) &&
+ (offset + n <= STM32_RTC_STORAGE_SIZE));
+
+ for (i = 0; i < (unsigned)n; i++) {
+ unsigned index = ((unsigned)offset + i) / sizeof (uint32_t);
+ unsigned shift = ((unsigned)offset + i) % sizeof (uint32_t);
+ uint32_t regval = bkpr[index];
+ regval &= ~(0xFFU << (shift * 8U));
+ regval |= (uint32_t)*wp++ << (shift * 8U);
+ bkpr[index] = regval;
+ }
+
+ return PS_NO_ERROR;
+}
+
+/**
+ * @brief VMT for the RTC storage file interface.
+ */
+struct RTCDriverVMT _rtc_lld_vmt = {
+ (size_t)0,
+ _getsize, _read, _write
+};
+#endif /* RTC_HAS_STORAGE == TRUE */
+
+/**
+ * @brief RTC ISR service routine.
+ *
+ */
+static void rtc_lld_serve_interrupt(void) {
+
+ uint32_t isr;
+
+ /* Get and clear the RTC interrupts. */
+ isr = RTCD1.rtc->MISR;
+ RTCD1.rtc->SCR = isr;
+
+ /* Clear EXTI events. */
+ STM32_RTC_CLEAR_ALL_EXTI();
+
+ /* Process call backs if enabled. */
+ if (RTCD1.callback != NULL) {
+
+#if defined(RTC_MISR_WUTMF)
+ if ((isr & RTC_MISR_WUTMF) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_WAKEUP);
+ }
+#endif
+
+#if defined(RTC_MISR_ALRAMF)
+ if ((isr & RTC_MISR_ALRAMF) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_ALARM_A);
+ }
+#endif
+#if defined(RTC_MISR_ALRBMF)
+ if ((isr & RTC_MISR_ALRBMF) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_ALARM_B);
+ }
+#endif
+#if defined(RTC_MISR_ITSMF)
+ if ((isr & RTC_MISR_ITSMF) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TS);
+ }
+#endif
+#if defined(RTC_MISR_TSOVMF)
+ if ((isr & RTC_MISR_TSOVMF) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TS_OVF);
+ }
+#endif
+
+ /* Get and clear the TAMP interrupts. */
+ isr = RTCD1.tamp->MISR;
+ RTCD1.tamp->SCR = isr;
+#if defined(TAMP_MISR_TAMP1MF)
+ if ((isr & TAMP_MISR_TAMP1MF) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TAMP1);
+ }
+#endif
+#if defined(TAMP_MISR_TAMP2MF)
+ if ((isr & TAMP_MISR_TAMP2MF) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TAMP2);
+ }
+#endif
+#if defined(TAMP_MISR_ITAMP3MF)
+ if ((isr & TAMP_MISR_ITAMP3MF) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TAMP3);
+ }
+#endif
+#if defined(TAMP_MISR_ITAMP4MF)
+ if ((isr & TAMP_MISR_ITAMP4MF) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TAMP4);
+ }
+#endif
+#if defined(TAMP_MISR_ITAMP5MF)
+ if ((isr & TAMP_MISR_ITAMP5MF) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TAMP5);
+ }
+#endif
+#if defined(TAMP_MISR_ITAMP6MF)
+ if ((isr & TAMP_MISR_ITAMP6MF) != 0U) {
+ RTCD1.callback(&RTCD1, RTC_EVENT_TAMP6);
+ }
+#endif
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_RTC_COMMON_HANDLER)
+#if !defined(STM32_RTC_SUPPRESS_COMMON_ISR)
+/**
+ * @brief RTC common interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_RTC_COMMON_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ rtc_lld_serve_interrupt();
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_RTC_SUPPRESS_COMMON_ISR) */
+
+#elif defined(STM32_RTC_TAMP_STAMP_HANDLER) && \
+ defined(STM32_RTC_WKUP_HANDLER) && \
+ defined(STM32_RTC_ALARM_HANDLER)
+/**
+ * @brief RTC TAMP/STAMP interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_RTC_TAMP_STAMP_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ rtc_lld_serve_interrupt();
+
+ OSAL_IRQ_EPILOGUE();
+}
+/**
+ * @brief RTC wakeup interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_RTC_WKUP_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ rtc_lld_serve_interrupt();
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief RTC alarm interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_RTC_ALARM_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ rtc_lld_serve_interrupt();
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#else
+#error "missing required RTC handler definitions in registry"
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Enable access to registers.
+ *
+ * @notapi
+ */
+void rtc_lld_init(void) {
+
+ /* RTC object initialization.*/
+ rtcObjectInit(&RTCD1);
+
+ /* RTC pointer initialization.*/
+ RTCD1.rtc = RTC;
+
+ /* Disable write protection. */
+ RTCD1.rtc->WPR = 0xCA;
+ RTCD1.rtc->WPR = 0x53;
+
+ /* If calendar has not been initialized yet then proceed with the
+ initial setup.*/
+ if (!(RTCD1.rtc->ICSR & RTC_ICSR_INITS)) {
+
+ rtc_enter_init();
+
+ RTCD1.rtc->CR |= (STM32_RTC_CR_INIT & STM32_RTC_CR_MASK);
+ /* Setting PRER has to be done as two writes. Write Sync part first
+ then Sync + Async. */
+ RTCD1.rtc->PRER = STM32_RTC_PRER_BITS & 0x7FFF;
+ RTCD1.rtc->PRER = STM32_RTC_PRER_BITS;
+
+ rtc_exit_init();
+ }
+ else {
+ RTCD1.rtc->ICSR &= ~RTC_ICSR_RSF;
+ }
+
+ /* TAMP pointer initialization. */
+ RTCD1.tamp = TAMP;
+
+ /* Initialise TAMP registers. */
+ RTCD1.tamp->CR1 |= (STM32_TAMP_CR1_INIT & STM32_TAMP_CR1_MASK);
+ RTCD1.tamp->CR2 |= (STM32_TAMP_CR2_INIT & STM32_TAMP_CR2_MASK);
+ RTCD1.tamp->FLTCR |= (STM32_TAMP_FLTCR_INIT & STM32_TAMP_FLTCR_MASK);
+ RTCD1.tamp->IER |= (STM32_TAMP_IER_INIT & STM32_TAMP_IER_MASK);
+
+ /* Callback initially disabled.*/
+ RTCD1.callback = NULL;
+
+ /* Enabling RTC-related EXTI lines.*/
+ STM32_RTC_ENABLE_ALL_EXTI();
+
+ /* IRQ vectors permanently assigned to this driver.*/
+ STM32_RTC_IRQ_ENABLE();
+}
+
+/**
+ * @brief Set current time.
+ * @note Fractional part will be silently ignored. There is no possibility
+ * to set it on STM32 platform.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] timespec pointer to a @p RTCDateTime structure
+ *
+ * @notapi
+ */
+void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec) {
+ uint32_t dr, tr;
+ syssts_t sts;
+
+ tr = rtc_encode_time(timespec);
+ dr = rtc_encode_date(timespec);
+
+ /* Entering a reentrant critical zone.*/
+ sts = osalSysGetStatusAndLockX();
+
+ /* Writing the registers.*/
+ rtc_enter_init();
+ rtcp->rtc->TR = tr;
+ rtcp->rtc->DR = dr;
+ rtcp->rtc->CR = (rtcp->rtc->CR & ~(1U << RTC_CR_BKP_OFFSET)) |
+ (timespec->dstflag << RTC_CR_BKP_OFFSET);
+ rtc_exit_init();
+
+ /* Leaving a reentrant critical zone.*/
+ osalSysRestoreStatusX(sts);
+}
+
+/**
+ * @brief Get current time.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[out] timespec pointer to a @p RTCDateTime structure
+ *
+ * @notapi
+ */
+void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec) {
+ uint32_t dr, tr, cr;
+ uint32_t subs;
+#if STM32_RTC_HAS_SUBSECONDS
+ uint32_t ssr;
+#endif /* STM32_RTC_HAS_SUBSECONDS */
+ syssts_t sts;
+
+ /* Entering a reentrant critical zone.*/
+ sts = osalSysGetStatusAndLockX();
+
+ /* Synchronization with the RTC and reading the registers, note
+ DR must be read last.*/
+ while ((rtcp->rtc->ICSR & RTC_ICSR_RSF) == 0)
+ ;
+#if STM32_RTC_HAS_SUBSECONDS
+ ssr = rtcp->rtc->SSR;
+#endif /* STM32_RTC_HAS_SUBSECONDS */
+ tr = rtcp->rtc->TR;
+ dr = rtcp->rtc->DR;
+ cr = rtcp->rtc->CR;
+ rtcp->rtc->ICSR &= ~RTC_ICSR_RSF;
+
+ /* Leaving a reentrant critical zone.*/
+ osalSysRestoreStatusX(sts);
+
+ /* Decoding day time, this starts the atomic read sequence, see "Reading
+ the calendar" in the RTC documentation.*/
+ rtc_decode_time(tr, timespec);
+
+ /* If the RTC is capable of sub-second counting then the value is
+ normalized in milliseconds and added to the time.*/
+#if STM32_RTC_HAS_SUBSECONDS
+ subs = (((STM32_RTC_PRESS_VALUE - 1U) - ssr) * 1000U) / STM32_RTC_PRESS_VALUE;
+#else
+ subs = 0;
+#endif /* STM32_RTC_HAS_SUBSECONDS */
+ timespec->millisecond += subs;
+
+ /* Decoding date, this concludes the atomic read sequence.*/
+ rtc_decode_date(dr, timespec);
+
+ /* Retrieving the DST bit.*/
+ timespec->dstflag = (cr >> RTC_CR_BKP_OFFSET) & 1;
+}
+
+#if (RTC_ALARMS > 0) || defined(__DOXYGEN__)
+/**
+ * @brief Set alarm time.
+ * @note Default value after BKP domain reset for both comparators is 0.
+ * @note Function does not performs any checks of alarm time validity.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure.
+ * @param[in] alarm alarm identifier. Can be 0 or 1.
+ * @param[in] alarmspec pointer to a @p RTCAlarm structure.
+ *
+ * @notapi
+ */
+void rtc_lld_set_alarm(RTCDriver *rtcp,
+ rtcalarm_t alarm,
+ const RTCAlarm *alarmspec) {
+ syssts_t sts;
+
+ /* Entering a reentrant critical zone.*/
+ sts = osalSysGetStatusAndLockX();
+
+ if (alarm == 0) {
+ if (alarmspec != NULL) {
+ rtcp->rtc->CR &= ~RTC_CR_ALRAE;
+ while (!(rtcp->rtc->ICSR & RTC_ICSR_ALRAWF))
+ ;
+ rtcp->rtc->ALRMAR = alarmspec->alrmr;
+ rtcp->rtc->CR |= RTC_CR_ALRAE;
+ rtcp->rtc->CR |= RTC_CR_ALRAIE;
+ }
+ else {
+ rtcp->rtc->CR &= ~RTC_CR_ALRAIE;
+ rtcp->rtc->CR &= ~RTC_CR_ALRAE;
+ }
+ }
+#if RTC_ALARMS > 1
+ else {
+ if (alarmspec != NULL) {
+ rtcp->rtc->CR &= ~RTC_CR_ALRBE;
+ while (!(rtcp->rtc->ICSR & RTC_ICSR_ALRBWF))
+ ;
+ rtcp->rtc->ALRMBR = alarmspec->alrmr;
+ rtcp->rtc->CR |= RTC_CR_ALRBE;
+ rtcp->rtc->CR |= RTC_CR_ALRBIE;
+ }
+ else {
+ rtcp->rtc->CR &= ~RTC_CR_ALRBIE;
+ rtcp->rtc->CR &= ~RTC_CR_ALRBE;
+ }
+ }
+#endif /* RTC_ALARMS > 1 */
+
+ /* Leaving a reentrant critical zone.*/
+ osalSysRestoreStatusX(sts);
+}
+
+/**
+ * @brief Get alarm time.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] alarm alarm identifier. Can be 0 or 1.
+ * @param[out] alarmspec pointer to a @p RTCAlarm structure
+ *
+ * @notapi
+ */
+void rtc_lld_get_alarm(RTCDriver *rtcp,
+ rtcalarm_t alarm,
+ RTCAlarm *alarmspec) {
+
+ if (alarm == 0)
+ alarmspec->alrmr = rtcp->rtc->ALRMAR;
+#if RTC_ALARMS > 1
+ else
+ alarmspec->alrmr = rtcp->rtc->ALRMBR;
+#endif /* RTC_ALARMS > 1 */
+}
+#endif /* RTC_ALARMS > 0 */
+
+/**
+ * @brief Enables or disables RTC callbacks.
+ * @details This function enables or disables callbacks, use a @p NULL pointer
+ * in order to disable a callback.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] callback callback function pointer or @p NULL
+ *
+ * @notapi
+ */
+void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback) {
+
+ rtcp->callback = callback;
+}
+
+#if STM32_RTC_HAS_PERIODIC_WAKEUPS || defined(__DOXYGEN__)
+/**
+ * @brief Sets time of periodic wakeup.
+ * @note Default value after BKP domain reset is 0x0000FFFF
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] wakeupspec pointer to a @p RTCWakeup structure
+ *
+ * @api
+ */
+void rtcSTM32SetPeriodicWakeup(RTCDriver *rtcp, const RTCWakeup *wakeupspec) {
+ syssts_t sts;
+
+ /* Entering a reentrant critical zone.*/
+ sts = osalSysGetStatusAndLockX();
+
+ if (wakeupspec != NULL) {
+ osalDbgCheck(wakeupspec->wutr != 0x30000);
+
+ rtcp->rtc->CR &= ~RTC_CR_WUTE;
+ rtcp->rtc->CR &= ~RTC_CR_WUTIE;
+ while (!(rtcp->rtc->ICSR & RTC_ICSR_WUTWF))
+ ;
+ rtcp->rtc->WUTR = wakeupspec->wutr & 0xFFFF;
+ rtcp->rtc->CR &= ~RTC_CR_WUCKSEL;
+ rtcp->rtc->CR |= (wakeupspec->wutr >> 16) & RTC_CR_WUCKSEL;
+ rtcp->rtc->CR |= RTC_CR_WUTIE;
+ rtcp->rtc->CR |= RTC_CR_WUTE;
+ }
+ else {
+ rtcp->rtc->CR &= ~RTC_CR_WUTE;
+ rtcp->rtc->CR &= ~RTC_CR_WUTIE;
+ }
+
+ /* Leaving a reentrant critical zone.*/
+ osalSysRestoreStatusX(sts);
+}
+
+/**
+ * @brief Gets time of periodic wakeup.
+ * @note Default value after BKP domain reset is 0x0000FFFF
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[out] wakeupspec pointer to a @p RTCWakeup structure
+ *
+ * @api
+ */
+void rtcSTM32GetPeriodicWakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec) {
+ syssts_t sts;
+
+ /* Entering a reentrant critical zone.*/
+ sts = osalSysGetStatusAndLockX();
+
+ wakeupspec->wutr = 0;
+ wakeupspec->wutr |= rtcp->rtc->WUTR;
+ wakeupspec->wutr |= (((uint32_t)rtcp->rtc->CR) & 0x7) << 16;
+
+ /* Leaving a reentrant critical zone.*/
+ osalSysRestoreStatusX(sts);
+}
+#endif /* STM32_RTC_HAS_PERIODIC_WAKEUPS */
+
+#endif /* HAL_USE_RTC */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.h
new file mode 100644
index 0000000..4097a62
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/RTCv3/hal_rtc_lld.h
@@ -0,0 +1,289 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file RTCv3/hal_rtc_lld.h
+ * @brief STM32 RTC low level driver header.
+ *
+ * @addtogroup RTC
+ * @{
+ */
+
+#ifndef HAL_RTC_LLD_H
+#define HAL_RTC_LLD_H
+
+#if HAL_USE_RTC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Implementation capabilities
+ */
+/**
+ * @brief Callback support int the driver.
+ */
+#define RTC_SUPPORTS_CALLBACKS TRUE
+
+/**
+ * @brief Number of alarms available.
+ */
+#define RTC_ALARMS STM32_RTC_NUM_ALARMS
+
+/**
+ * @brief Presence of a local persistent storage.
+ */
+#define RTC_HAS_STORAGE (STM32_RTC_STORAGE_SIZE > 0)
+/** @} */
+
+/**
+ * @brief RTC PRER register initializer.
+ */
+#define RTC_PRER(a, s) ((((a) - 1) << 16) | ((s) - 1))
+
+/**
+ * @name Alarm helper macros
+ * @{
+ */
+#define RTC_ALRM_MSK4 (1U << 31)
+#define RTC_ALRM_WDSEL (1U << 30)
+#define RTC_ALRM_DT(n) ((n) << 28)
+#define RTC_ALRM_DU(n) ((n) << 24)
+#define RTC_ALRM_MSK3 (1U << 23)
+#define RTC_ALRM_HT(n) ((n) << 20)
+#define RTC_ALRM_HU(n) ((n) << 16)
+#define RTC_ALRM_MSK2 (1U << 15)
+#define RTC_ALRM_MNT(n) ((n) << 12)
+#define RTC_ALRM_MNU(n) ((n) << 8)
+#define RTC_ALRM_MSK1 (1U << 7)
+#define RTC_ALRM_ST(n) ((n) << 4)
+#define RTC_ALRM_SU(n) ((n) << 0)
+/** @} */
+
+/* Requires services from the EXTI driver.*/
+#if !defined(STM32_EXTI_REQUIRED)
+#define STM32_EXTI_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief RTC PRESA register initialization.
+ * @note The default is calculated for a 32768Hz clock.
+ */
+#if !defined(STM32_RTC_PRESA_VALUE) || defined(__DOXYGEN__)
+#define STM32_RTC_PRESA_VALUE 32
+#endif
+
+/**
+ * @brief RTC PRESS divider initialization.
+ * @note The default is calculated for a 32768Hz clock.
+ */
+#if !defined(STM32_RTC_PRESS_VALUE) || defined(__DOXYGEN__)
+#define STM32_RTC_PRESS_VALUE 1024
+#endif
+
+/**
+ * @brief RTC CR register initialization value.
+ * @note Use this value to initialize features not directly handled by
+ * the RTC driver.
+ */
+#if !defined(STM32_RTC_CR_INIT) || defined(__DOXYGEN__)
+#define STM32_RTC_CR_INIT 0
+#endif
+
+/**
+ * @brief TAMP register initialization value.
+ * @note Use this value to initialize features not directly handled by
+ * the RTC driver.
+ * @note On some devices this values goes in the similar TAFCR register.
+ */
+#if !defined(STM32_TAMP_CR1_INIT) || defined(__DOXYGEN__)
+#define STM32_TAMP_CR1_INIT 0
+#endif
+
+/**
+ * @brief TAMP register initialization value.
+ * @note Use this value to initialize features not directly handled by
+ * the RTC driver.
+ * @note On some devices this values goes in the similar TAFCR register.
+ */
+#if !defined(STM32_TAMP_CR2_INIT) || defined(__DOXYGEN__)
+#define STM32_TAMP_CR2_INIT 0
+#endif
+
+/**
+ * @brief TAMP register initialization value.
+ * @note Use this value to initialize features not directly handled by
+ * the RTC driver.
+ * @note On some devices this values goes in the similar TAFCR register.
+ */
+#if !defined(STM32_TAMP_FLTCR_INIT) || defined(__DOXYGEN__)
+#define STM32_TAMP_FLTCR_INIT 0
+#endif
+
+/**
+ * @brief TAMP register initialization value.
+ * @note Use this value to initialize features not directly handled by
+ * the RTC driver.
+ * @note On some devices this values goes in the similar TAFCR register.
+ */
+#if !defined(STM32_TAMP_IER_INIT) || defined(__DOXYGEN__)
+#define STM32_TAMP_IER_INIT 0
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if HAL_USE_RTC && !STM32_HAS_RTC
+#error "RTC not present in the selected device"
+#endif
+
+#if defined(STM32_RTC_CK) && !defined(STM32_RTCCLK)
+#define STM32_RTCCLK STM32_RTC_CK
+#endif
+
+#if !defined(STM32_RTCCLK)
+#error "RTC clock not exported by HAL layer"
+#endif
+
+#if STM32_RTCCLK == 0
+#error "RTC has no clock source selected"
+#endif
+
+#if STM32_PCLK1 < (STM32_RTCCLK * 7)
+#error "STM32_PCLK1 frequency is too low for RTC"
+#endif
+
+/**
+ * @brief Initialization for the RTC_PRER register.
+ */
+#define STM32_RTC_PRER_BITS RTC_PRER(STM32_RTC_PRESA_VALUE, \
+ STM32_RTC_PRESS_VALUE)
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of an RTC event.
+ */
+typedef enum {
+ RTC_EVENT_ALARM_A = 0, /** Alarm A. */
+ RTC_EVENT_ALARM_B = 1, /** Alarm B. */
+ RTC_EVENT_TS = 2, /** Time stamp. */
+ RTC_EVENT_TS_OVF = 3, /** Time stamp overflow. */
+ RTC_EVENT_TAMP1 = 4, /** Tamper 1. */
+ RTC_EVENT_TAMP2 = 5, /** Tamper 2- */
+ RTC_EVENT_TAMP3 = 6, /** Tamper 3. */
+ RTC_EVENT_TAMP4 = 7, /** Tamper 4. */
+ RTC_EVENT_TAMP5 = 8, /** Tamper 5. */
+ RTC_EVENT_TAMP6 = 9, /** Tamper 6. */
+ RTC_EVENT_WAKEUP = 10, /** Wakeup. */
+ } rtcevent_t;
+
+/**
+ * @brief Type of a generic RTC callback.
+ */
+typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event);
+
+/**
+ * @brief Type of a structure representing an RTC alarm time stamp.
+ */
+typedef struct hal_rtc_alarm {
+ /**
+ * @brief Type of an alarm as encoded in RTC ALRMxR registers.
+ */
+ uint32_t alrmr;
+} RTCAlarm;
+
+#if STM32_RTC_HAS_PERIODIC_WAKEUPS
+/**
+ * @brief Type of a wakeup as encoded in RTC WUTR register.
+ */
+typedef struct hal_rtc_wakeup {
+ /**
+ * @brief Wakeup as encoded in RTC WUTR register.
+ * @note ((WUTR == 0) || (WUCKSEL == 3)) are a forbidden combination.
+ * @note Bits 16..18 are copied in the CR bits 0..2 (WUCKSEL).
+ */
+ uint32_t wutr;
+} RTCWakeup;
+#endif
+
+/**
+ * @brief Implementation-specific @p RTCDriver fields.
+ */
+#define rtc_lld_driver_fields \
+ /* Pointer to the RTC registers block.*/ \
+ RTC_TypeDef *rtc; \
+ /* RTC event callback pointer.*/ \
+ rtccb_t callback; \
+ /* Pointer to TAMPER registers block. */ \
+ TAMP_TypeDef *tamp
+
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void rtc_lld_init(void);
+ void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec);
+ void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec);
+#if RTC_SUPPORTS_CALLBACKS == TRUE
+ void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback);
+#endif
+#if RTC_ALARMS > 0
+ void rtc_lld_set_alarm(RTCDriver *rtcp,
+ rtcalarm_t alarm,
+ const RTCAlarm *alarmspec);
+ void rtc_lld_get_alarm(RTCDriver *rtcp,
+ rtcalarm_t alarm,
+ RTCAlarm *alarmspec);
+#endif
+#if STM32_RTC_HAS_PERIODIC_WAKEUPS
+ void rtcSTM32SetPeriodicWakeup(RTCDriver *rtcp, const RTCWakeup *wakeupspec);
+ void rtcSTM32GetPeriodicWakeup(RTCDriver *rtcp, RTCWakeup *wakeupspec);
+#endif /* STM32_RTC_HAS_PERIODIC_WAKEUPS */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_RTC */
+
+#endif /* HAL_RTC_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDIOv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDIOv1/driver.mk
new file mode 100644
index 0000000..a1ce6d4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDIOv1/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_SDC TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDIOv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.c
new file mode 100644
index 0000000..37d4989
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.c
@@ -0,0 +1,876 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SDIOv1/hal_sdc_lld.c
+ * @brief STM32 SDC subsystem low level driver source.
+ *
+ * @addtogroup SDC
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+
+#if HAL_USE_SDC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_SDC_SDIO_DMA_STREAM, \
+ STM32_SDC_SDIO_DMA_CHN)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief SDCD1 driver identifier.*/
+SDCDriver SDCD1;
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+#if STM32_SDC_SDIO_UNALIGNED_SUPPORT
+/**
+ * @brief Buffer for temporary storage during unaligned transfers.
+ */
+static union {
+ uint32_t alignment;
+ uint8_t buf[MMCSD_BLOCK_SIZE];
+} u;
+#endif /* STM32_SDC_SDIO_UNALIGNED_SUPPORT */
+
+/**
+ * @brief SDIO default configuration.
+ */
+static const SDCConfig sdc_default_cfg = {
+ SDC_MODE_4BIT
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Prepares to handle read transaction.
+ * @details Designed for read special registers from card.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[out] buf pointer to the read buffer
+ * @param[in] bytes number of bytes to read
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+static bool sdc_lld_prepare_read_bytes(SDCDriver *sdcp,
+ uint8_t *buf, uint32_t bytes) {
+ osalDbgCheck(bytes < 0x1000000);
+
+ sdcp->sdio->DTIMER = STM32_SDC_READ_TIMEOUT;
+
+ /* Checks for errors and waits for the card to be ready for reading.*/
+ if (_sdc_wait_for_transfer_state(sdcp))
+ return HAL_FAILED;
+
+ /* Prepares the DMA channel for writing.*/
+ dmaStreamSetMemory0(sdcp->dma, buf);
+ dmaStreamSetTransactionSize(sdcp->dma, bytes / sizeof (uint32_t));
+ dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_P2M);
+ dmaStreamEnable(sdcp->dma);
+
+ /* Setting up data transfer.*/
+ sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS;
+ sdcp->sdio->MASK = SDIO_MASK_DCRCFAILIE |
+ SDIO_MASK_DTIMEOUTIE |
+ SDIO_MASK_STBITERRIE |
+ SDIO_MASK_RXOVERRIE |
+ SDIO_MASK_DATAENDIE;
+ sdcp->sdio->DLEN = bytes;
+
+ /* Transaction starts just after DTEN bit setting.*/
+ sdcp->sdio->DCTRL = SDIO_DCTRL_DTDIR |
+ SDIO_DCTRL_DTMODE | /* Multibyte data transfer.*/
+ SDIO_DCTRL_DMAEN |
+ SDIO_DCTRL_DTEN;
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Prepares card to handle read transaction.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to read
+ * @param[in] n number of blocks to read
+ * @param[in] resp pointer to the response buffer
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+static bool sdc_lld_prepare_read(SDCDriver *sdcp, uint32_t startblk,
+ uint32_t n, uint32_t *resp) {
+
+ /* Driver handles data in 512 bytes blocks (just like HC cards). But if we
+ have not HC card than we must convert address from blocks to bytes.*/
+ if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY))
+ startblk *= MMCSD_BLOCK_SIZE;
+
+ if (n > 1) {
+ /* Send read multiple blocks command to card.*/
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_READ_MULTIPLE_BLOCK,
+ startblk, resp) || MMCSD_R1_ERROR(resp[0]))
+ return HAL_FAILED;
+ }
+ else {
+ /* Send read single block command.*/
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_READ_SINGLE_BLOCK,
+ startblk, resp) || MMCSD_R1_ERROR(resp[0]))
+ return HAL_FAILED;
+ }
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Prepares card to handle write transaction.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to read
+ * @param[in] n number of blocks to write
+ * @param[in] resp pointer to the response buffer
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+static bool sdc_lld_prepare_write(SDCDriver *sdcp, uint32_t startblk,
+ uint32_t n, uint32_t *resp) {
+
+ /* Driver handles data in 512 bytes blocks (just like HC cards). But if we
+ have not HC card than we must convert address from blocks to bytes.*/
+ if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY))
+ startblk *= MMCSD_BLOCK_SIZE;
+
+ if (n > 1) {
+ /* Write multiple blocks command.*/
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK,
+ startblk, resp) || MMCSD_R1_ERROR(resp[0]))
+ return HAL_FAILED;
+ }
+ else {
+ /* Write single block command.*/
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_WRITE_BLOCK,
+ startblk, resp) || MMCSD_R1_ERROR(resp[0]))
+ return HAL_FAILED;
+ }
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Wait end of data transaction and performs finalizations.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] n number of blocks in transaction
+ * @param[in] resp pointer to the response buffer
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ */
+static bool sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n,
+ uint32_t *resp) {
+
+ /* Note the mask is checked before going to sleep because the interrupt
+ may have occurred before reaching the critical zone.*/
+ osalSysLock();
+ if (sdcp->sdio->MASK != 0)
+ osalThreadSuspendS(&sdcp->thread);
+ if ((sdcp->sdio->STA & SDIO_STA_DATAEND) == 0) {
+ osalSysUnlock();
+ return HAL_FAILED;
+ }
+
+#if (defined(STM32F4XX) || defined(STM32F2XX))
+ /* Wait until DMA channel enabled to be sure that all data transferred.*/
+ while (sdcp->dma->stream->CR & STM32_DMA_CR_EN)
+ ;
+
+ /* DMA event flags must be manually cleared.*/
+ dmaStreamClearInterrupt(sdcp->dma);
+
+ sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS;
+ sdcp->sdio->DCTRL = 0;
+ osalSysUnlock();
+#else
+ /* Waits for transfer completion at DMA level, then the stream is
+ disabled and cleared.*/
+ dmaWaitCompletion(sdcp->dma);
+
+ sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS;
+ sdcp->sdio->DCTRL = 0;
+ osalSysUnlock();
+#endif
+
+ /* Finalize transaction.*/
+ if (n > 1)
+ return sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp);
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Gets SDC errors.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] sta value of the STA register
+ *
+ * @notapi
+ */
+static void sdc_lld_collect_errors(SDCDriver *sdcp, uint32_t sta) {
+ uint32_t errors = SDC_NO_ERROR;
+
+ if (sta & SDIO_STA_CCRCFAIL)
+ errors |= SDC_CMD_CRC_ERROR;
+ if (sta & SDIO_STA_DCRCFAIL)
+ errors |= SDC_DATA_CRC_ERROR;
+ if (sta & SDIO_STA_CTIMEOUT)
+ errors |= SDC_COMMAND_TIMEOUT;
+ if (sta & SDIO_STA_DTIMEOUT)
+ errors |= SDC_DATA_TIMEOUT;
+ if (sta & SDIO_STA_TXUNDERR)
+ errors |= SDC_TX_UNDERRUN;
+ if (sta & SDIO_STA_RXOVERR)
+ errors |= SDC_RX_OVERRUN;
+ if (sta & SDIO_STA_STBITERR)
+ errors |= SDC_STARTBIT_ERROR;
+
+ sdcp->errors |= errors;
+}
+
+/**
+ * @brief Performs clean transaction stopping in case of errors.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] n number of blocks in transaction
+ * @param[in] resp pointer to the response buffer
+ *
+ * @notapi
+ */
+static void sdc_lld_error_cleanup(SDCDriver *sdcp,
+ uint32_t n,
+ uint32_t *resp) {
+ uint32_t sta = sdcp->sdio->STA;
+
+ dmaStreamClearInterrupt(sdcp->dma);
+ dmaStreamDisable(sdcp->dma);
+ sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS;
+ sdcp->sdio->MASK = 0;
+ sdcp->sdio->DCTRL = 0;
+ sdc_lld_collect_errors(sdcp, sta);
+ if (n > 1)
+ sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp);
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if !defined(STM32_SDIO_HANDLER)
+#error "STM32_SDIO_HANDLER not defined"
+#endif
+/**
+ * @brief SDIO IRQ handler.
+ * @details It just wakes transaction thread. All error handling performs in
+ * that thread.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_SDIO_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ osalSysLockFromISR();
+
+ /* Disables the source but the status flags are not reset because the
+ read/write functions needs to check them.*/
+ SDIO->MASK = 0;
+
+ osalThreadResumeI(&SDCD1.thread, MSG_OK);
+
+ osalSysUnlockFromISR();
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level SDC driver initialization.
+ *
+ * @notapi
+ */
+void sdc_lld_init(void) {
+
+ sdcObjectInit(&SDCD1);
+ SDCD1.thread = NULL;
+ SDCD1.dma = NULL;
+ SDCD1.sdio = SDIO;
+ nvicEnableVector(STM32_SDIO_NUMBER, STM32_SDC_SDIO_IRQ_PRIORITY);
+}
+
+/**
+ * @brief Configures and activates the SDC peripheral.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_start(SDCDriver *sdcp) {
+
+ /* Checking configuration, using a default if NULL has been passed.*/
+ if (sdcp->config == NULL) {
+ sdcp->config = &sdc_default_cfg;
+ }
+
+ sdcp->dmamode = STM32_DMA_CR_CHSEL(DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_SDC_SDIO_DMA_PRIORITY) |
+ STM32_DMA_CR_PSIZE_WORD |
+ STM32_DMA_CR_MSIZE_WORD |
+ STM32_DMA_CR_MINC;
+
+#if (defined(STM32F4XX) || defined(STM32F2XX))
+ sdcp->dmamode |= STM32_DMA_CR_PFCTRL |
+ STM32_DMA_CR_PBURST_INCR4 |
+ STM32_DMA_CR_MBURST_INCR4;
+#endif
+
+ if (sdcp->state == BLK_STOP) {
+ sdcp->dma = dmaStreamAllocI(STM32_SDC_SDIO_DMA_STREAM,
+ STM32_SDC_SDIO_IRQ_PRIORITY,
+ NULL,
+ NULL);
+ osalDbgAssert(sdcp->dma != NULL, "unable to allocate stream");
+
+ dmaStreamSetPeripheral(sdcp->dma, &sdcp->sdio->FIFO);
+#if (defined(STM32F4XX) || defined(STM32F2XX))
+ dmaStreamSetFIFO(sdcp->dma, STM32_DMA_FCR_DMDIS | STM32_DMA_FCR_FTH_FULL);
+#endif
+ rccEnableSDIO(true);
+ }
+
+ /* Configuration, card clock is initially stopped.*/
+ sdcp->sdio->POWER = 0;
+ sdcp->sdio->CLKCR = 0;
+ sdcp->sdio->DCTRL = 0;
+ sdcp->sdio->DTIMER = 0;
+}
+
+/**
+ * @brief Deactivates the SDC peripheral.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_stop(SDCDriver *sdcp) {
+
+ if (sdcp->state != BLK_STOP) {
+
+ /* SDIO deactivation.*/
+ sdcp->sdio->POWER = 0;
+ sdcp->sdio->CLKCR = 0;
+ sdcp->sdio->DCTRL = 0;
+ sdcp->sdio->DTIMER = 0;
+
+ /* DMA stream released.*/
+ dmaStreamFreeI(sdcp->dma);
+ sdcp->dma = NULL;
+
+ /* Clock deactivation.*/
+ rccDisableSDIO();
+ }
+}
+
+/**
+ * @brief Starts the SDIO clock and sets it to init mode (400kHz or less).
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_start_clk(SDCDriver *sdcp) {
+
+ /* Initial clock setting: 400kHz, 1bit mode.*/
+ sdcp->sdio->CLKCR = STM32_SDIO_DIV_LS;
+ sdcp->sdio->POWER |= SDIO_POWER_PWRCTRL_0 | SDIO_POWER_PWRCTRL_1;
+ sdcp->sdio->CLKCR |= SDIO_CLKCR_CLKEN;
+
+ /* Clock activation delay.*/
+ osalThreadSleep(OSAL_MS2I(STM32_SDC_CLOCK_ACTIVATION_DELAY));
+}
+
+/**
+ * @brief Sets the SDIO clock to data mode (25MHz or less).
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] clk the clock mode
+ *
+ * @notapi
+ */
+void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk) {
+
+#if STM32_SDC_SDIO_50MHZ
+ if (SDC_CLK_50MHz == clk) {
+ sdcp->sdio->CLKCR = (sdcp->sdio->CLKCR & 0xFFFFFF00U) | STM32_SDIO_DIV_HS
+ | SDIO_CLKCR_BYPASS;
+ }
+ else
+ sdcp->sdio->CLKCR = (sdcp->sdio->CLKCR & 0xFFFFFF00U) | STM32_SDIO_DIV_HS;
+#else
+ (void)clk;
+
+ sdcp->sdio->CLKCR = (sdcp->sdio->CLKCR & 0xFFFFFF00U) | STM32_SDIO_DIV_HS;
+#endif
+}
+
+/**
+ * @brief Stops the SDIO clock.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_stop_clk(SDCDriver *sdcp) {
+
+ sdcp->sdio->CLKCR = 0;
+ sdcp->sdio->POWER = 0;
+}
+
+/**
+ * @brief Switches the bus to 4 bits mode.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] mode bus mode
+ *
+ * @notapi
+ */
+void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) {
+ uint32_t clk = sdcp->sdio->CLKCR & ~SDIO_CLKCR_WIDBUS;
+
+ switch (mode) {
+ case SDC_MODE_1BIT:
+ sdcp->sdio->CLKCR = clk;
+ break;
+ case SDC_MODE_4BIT:
+ sdcp->sdio->CLKCR = clk | SDIO_CLKCR_WIDBUS_0;
+ break;
+ case SDC_MODE_8BIT:
+ sdcp->sdio->CLKCR = clk | SDIO_CLKCR_WIDBUS_1;
+ break;
+ }
+}
+
+/**
+ * @brief Sends an SDIO command with no response expected.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] cmd card command
+ * @param[in] arg command argument
+ *
+ * @notapi
+ */
+void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg) {
+
+ sdcp->sdio->ARG = arg;
+ sdcp->sdio->CMD = (uint32_t)cmd | SDIO_CMD_CPSMEN;
+ while ((sdcp->sdio->STA & SDIO_STA_CMDSENT) == 0)
+ ;
+ sdcp->sdio->ICR = SDIO_ICR_CMDSENTC;
+}
+
+/**
+ * @brief Sends an SDIO command with a short response expected.
+ * @note The CRC is not verified.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] cmd card command
+ * @param[in] arg command argument
+ * @param[out] resp pointer to the response buffer (one word)
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp) {
+ uint32_t sta;
+
+ sdcp->sdio->ARG = arg;
+ sdcp->sdio->CMD = (uint32_t)cmd | SDIO_CMD_WAITRESP_0 | SDIO_CMD_CPSMEN;
+ while (((sta = sdcp->sdio->STA) & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT |
+ SDIO_STA_CCRCFAIL)) == 0)
+ ;
+ sdcp->sdio->ICR = sta & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT |
+ SDIO_STA_CCRCFAIL);
+ if ((sta & (SDIO_STA_CTIMEOUT)) != 0) {
+ sdc_lld_collect_errors(sdcp, sta);
+ return HAL_FAILED;
+ }
+ *resp = sdcp->sdio->RESP1;
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Sends an SDIO command with a short response expected and CRC.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] cmd card command
+ * @param[in] arg command argument
+ * @param[out] resp pointer to the response buffer (one word)
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp) {
+ uint32_t sta;
+
+ sdcp->sdio->ARG = arg;
+ sdcp->sdio->CMD = (uint32_t)cmd | SDIO_CMD_WAITRESP_0 | SDIO_CMD_CPSMEN;
+ while (((sta = sdcp->sdio->STA) & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT |
+ SDIO_STA_CCRCFAIL)) == 0)
+ ;
+ sdcp->sdio->ICR = sta & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT | SDIO_STA_CCRCFAIL);
+ if ((sta & (SDIO_STA_CTIMEOUT | SDIO_STA_CCRCFAIL)) != 0) {
+ sdc_lld_collect_errors(sdcp, sta);
+ return HAL_FAILED;
+ }
+ *resp = sdcp->sdio->RESP1;
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Sends an SDIO command with a long response expected and CRC.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] cmd card command
+ * @param[in] arg command argument
+ * @param[out] resp pointer to the response buffer (four words)
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp) {
+ uint32_t sta;
+
+ (void)sdcp;
+
+ sdcp->sdio->ARG = arg;
+ sdcp->sdio->CMD = (uint32_t)cmd | SDIO_CMD_WAITRESP_0 | SDIO_CMD_WAITRESP_1 |
+ SDIO_CMD_CPSMEN;
+ while (((sta = sdcp->sdio->STA) & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT |
+ SDIO_STA_CCRCFAIL)) == 0)
+ ;
+ sdcp->sdio->ICR = sta & (SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT |
+ SDIO_STA_CCRCFAIL);
+ if ((sta & (STM32_SDIO_STA_ERROR_MASK)) != 0) {
+ sdc_lld_collect_errors(sdcp, sta);
+ return HAL_FAILED;
+ }
+ /* Save bytes in reverse order because MSB in response comes first.*/
+ *resp++ = sdcp->sdio->RESP4;
+ *resp++ = sdcp->sdio->RESP3;
+ *resp++ = sdcp->sdio->RESP2;
+ *resp = sdcp->sdio->RESP1;
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Reads special registers using data bus.
+ * @details Needs only during card detection procedure.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[out] buf pointer to the read buffer
+ * @param[in] bytes number of bytes to read
+ * @param[in] cmd card command
+ * @param[in] arg argument for command
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes,
+ uint8_t cmd, uint32_t arg) {
+ uint32_t resp[1];
+
+ if (sdc_lld_prepare_read_bytes(sdcp, buf, bytes))
+ goto error;
+
+ if (sdc_lld_send_cmd_short_crc(sdcp, cmd, arg, resp)
+ || MMCSD_R1_ERROR(resp[0]))
+ goto error;
+
+ if (sdc_lld_wait_transaction_end(sdcp, 1, resp))
+ goto error;
+
+ return HAL_SUCCESS;
+
+error:
+ sdc_lld_error_cleanup(sdcp, 1, resp);
+ return HAL_FAILED;
+}
+
+/**
+ * @brief Reads one or more blocks.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to read
+ * @param[out] buf pointer to the read buffer
+ * @param[in] blocks number of blocks to read
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_read_aligned(SDCDriver *sdcp, uint32_t startblk,
+ uint8_t *buf, uint32_t blocks) {
+ uint32_t resp[1];
+
+ osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE);
+
+ sdcp->sdio->DTIMER = STM32_SDC_READ_TIMEOUT;
+
+ /* Checks for errors and waits for the card to be ready for reading.*/
+ if (_sdc_wait_for_transfer_state(sdcp))
+ return HAL_FAILED;
+
+ /* Prepares the DMA channel for writing.*/
+ dmaStreamSetMemory0(sdcp->dma, buf);
+ dmaStreamSetTransactionSize(sdcp->dma,
+ (blocks * MMCSD_BLOCK_SIZE) / sizeof (uint32_t));
+ dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_P2M);
+ dmaStreamEnable(sdcp->dma);
+
+ /* Setting up data transfer.*/
+ sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS;
+ sdcp->sdio->MASK = SDIO_MASK_DCRCFAILIE |
+ SDIO_MASK_DTIMEOUTIE |
+ SDIO_MASK_STBITERRIE |
+ SDIO_MASK_RXOVERRIE |
+ SDIO_MASK_DATAENDIE;
+ sdcp->sdio->DLEN = blocks * MMCSD_BLOCK_SIZE;
+
+ /* Transaction starts just after DTEN bit setting.*/
+ sdcp->sdio->DCTRL = SDIO_DCTRL_DTDIR |
+ SDIO_DCTRL_DBLOCKSIZE_3 |
+ SDIO_DCTRL_DBLOCKSIZE_0 |
+ SDIO_DCTRL_DMAEN |
+ SDIO_DCTRL_DTEN;
+
+ if (sdc_lld_prepare_read(sdcp, startblk, blocks, resp) == true)
+ goto error;
+
+ if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == true)
+ goto error;
+
+ return HAL_SUCCESS;
+
+error:
+ sdc_lld_error_cleanup(sdcp, blocks, resp);
+ return HAL_FAILED;
+}
+
+/**
+ * @brief Writes one or more blocks.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to write
+ * @param[out] buf pointer to the write buffer
+ * @param[in] n number of blocks to write
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_write_aligned(SDCDriver *sdcp, uint32_t startblk,
+ const uint8_t *buf, uint32_t blocks) {
+ uint32_t resp[1];
+
+ osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE);
+
+ sdcp->sdio->DTIMER = STM32_SDC_WRITE_TIMEOUT;
+
+ /* Checks for errors and waits for the card to be ready for writing.*/
+ if (_sdc_wait_for_transfer_state(sdcp))
+ return HAL_FAILED;
+
+ /* Prepares the DMA channel for writing.*/
+ dmaStreamSetMemory0(sdcp->dma, buf);
+ dmaStreamSetTransactionSize(sdcp->dma,
+ (blocks * MMCSD_BLOCK_SIZE) / sizeof (uint32_t));
+ dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_M2P);
+ dmaStreamEnable(sdcp->dma);
+
+ /* Setting up data transfer.*/
+ sdcp->sdio->ICR = STM32_SDIO_ICR_ALL_FLAGS;
+ sdcp->sdio->MASK = SDIO_MASK_DCRCFAILIE |
+ SDIO_MASK_DTIMEOUTIE |
+ SDIO_MASK_STBITERRIE |
+ SDIO_MASK_TXUNDERRIE |
+ SDIO_MASK_DATAENDIE;
+ sdcp->sdio->DLEN = blocks * MMCSD_BLOCK_SIZE;
+
+ /* Talk to card what we want from it.*/
+ if (sdc_lld_prepare_write(sdcp, startblk, blocks, resp) == true)
+ goto error;
+
+ /* Transaction starts just after DTEN bit setting.*/
+ sdcp->sdio->DCTRL = SDIO_DCTRL_DBLOCKSIZE_3 |
+ SDIO_DCTRL_DBLOCKSIZE_0 |
+ SDIO_DCTRL_DMAEN |
+ SDIO_DCTRL_DTEN;
+
+ if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == true)
+ goto error;
+
+ return HAL_SUCCESS;
+
+error:
+ sdc_lld_error_cleanup(sdcp, blocks, resp);
+ return HAL_FAILED;
+}
+
+/**
+ * @brief Reads one or more blocks.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to read
+ * @param[out] buf pointer to the read buffer
+ * @param[in] blocks number of blocks to read
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk,
+ uint8_t *buf, uint32_t blocks) {
+
+#if STM32_SDC_SDIO_UNALIGNED_SUPPORT
+ if (((unsigned)buf & 3) != 0) {
+ uint32_t i;
+ for (i = 0; i < blocks; i++) {
+ if (sdc_lld_read_aligned(sdcp, startblk, u.buf, 1))
+ return HAL_FAILED;
+ memcpy(buf, u.buf, MMCSD_BLOCK_SIZE);
+ buf += MMCSD_BLOCK_SIZE;
+ startblk++;
+ }
+ return HAL_SUCCESS;
+ }
+#else /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */
+ osalDbgAssert((((unsigned)buf & 3) == 0), "unaligned buffer");
+#endif /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */
+ return sdc_lld_read_aligned(sdcp, startblk, buf, blocks);
+}
+
+/**
+ * @brief Writes one or more blocks.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to write
+ * @param[out] buf pointer to the write buffer
+ * @param[in] blocks number of blocks to write
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk,
+ const uint8_t *buf, uint32_t blocks) {
+
+#if STM32_SDC_SDIO_UNALIGNED_SUPPORT
+ if (((unsigned)buf & 3) != 0) {
+ uint32_t i;
+ for (i = 0; i < blocks; i++) {
+ memcpy(u.buf, buf, MMCSD_BLOCK_SIZE);
+ buf += MMCSD_BLOCK_SIZE;
+ if (sdc_lld_write_aligned(sdcp, startblk, u.buf, 1))
+ return HAL_FAILED;
+ startblk++;
+ }
+ return HAL_SUCCESS;
+ }
+#else /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */
+ osalDbgAssert((((unsigned)buf & 3) == 0), "unaligned buffer");
+#endif /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */
+ return sdc_lld_write_aligned(sdcp, startblk, buf, blocks);
+}
+
+/**
+ * @brief Waits for card idle condition.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS the operation succeeded.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @api
+ */
+bool sdc_lld_sync(SDCDriver *sdcp) {
+
+ /* CHTODO: Implement.*/
+ (void)sdcp;
+ return HAL_SUCCESS;
+}
+
+#endif /* HAL_USE_SDC */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.h
new file mode 100644
index 0000000..4f0a430
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDIOv1/hal_sdc_lld.h
@@ -0,0 +1,353 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SDIOv1/hal_sdc_lld.h
+ * @brief STM32 SDC subsystem low level driver header.
+ *
+ * @addtogroup SDC
+ * @{
+ */
+
+#ifndef HAL_SDC_LLD_H
+#define HAL_SDC_LLD_H
+
+#if HAL_USE_SDC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*
+ * The following definitions are missing from some implementations, fixing
+ * as zeroed masks.
+ */
+#if !defined(SDIO_STA_STBITERR)
+#define SDIO_STA_STBITERR 0
+#endif
+
+#if !defined(SDIO_ICR_STBITERRC)
+#define SDIO_ICR_STBITERRC 0
+#endif
+
+#if !defined(SDIO_ICR_CEATAENDC)
+#define SDIO_ICR_CEATAENDC 0
+#endif
+
+#if !defined(SDIO_MASK_STBITERRIE)
+#define SDIO_MASK_STBITERRIE 0
+#endif
+
+/**
+ * @brief Value to clear all interrupts flag at once.
+ */
+#define STM32_SDIO_ICR_ALL_FLAGS (SDIO_ICR_CCRCFAILC | SDIO_ICR_DCRCFAILC | \
+ SDIO_ICR_CTIMEOUTC | SDIO_ICR_DTIMEOUTC | \
+ SDIO_ICR_TXUNDERRC | SDIO_ICR_RXOVERRC | \
+ SDIO_ICR_CMDRENDC | SDIO_ICR_CMDSENTC | \
+ SDIO_ICR_DATAENDC | SDIO_ICR_STBITERRC | \
+ SDIO_ICR_DBCKENDC | SDIO_ICR_SDIOITC | \
+ SDIO_ICR_CEATAENDC)
+
+/**
+ * @brief Mask of error flags in STA register.
+ */
+#define STM32_SDIO_STA_ERROR_MASK (SDIO_STA_CCRCFAIL | SDIO_STA_DCRCFAIL | \
+ SDIO_STA_CTIMEOUT | SDIO_STA_DTIMEOUT | \
+ SDIO_STA_TXUNDERR | SDIO_STA_RXOVERR)
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief SDIO DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_SDC_SDIO_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SDC_SDIO_DMA_PRIORITY 3
+#endif
+
+/**
+ * @brief SDIO interrupt priority level setting.
+ */
+#if !defined(STM32_SDC_SDIO_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SDC_SDIO_IRQ_PRIORITY 9
+#endif
+
+/**
+ * @brief Enable clock bypass.
+ * @note Allow clock speed up to 50 Mhz.
+ */
+#if !defined(STM32_SDC_SDIO_50MHZ) || defined(__DOXYGEN__)
+#define STM32_SDC_SDIO_50MHZ FALSE
+#endif
+
+/**
+ * @brief Write timeout in milliseconds.
+ */
+#if !defined(STM32_SDC_WRITE_TIMEOUT_MS) || defined(__DOXYGEN__)
+#define STM32_SDC_WRITE_TIMEOUT_MS 1000
+#endif
+
+/**
+ * @brief Read timeout in milliseconds.
+ */
+#if !defined(STM32_SDC_READ_TIMEOUT_MS) || defined(__DOXYGEN__)
+#define STM32_SDC_READ_TIMEOUT_MS 1000
+#endif
+
+/**
+ * @brief Card clock activation delay in milliseconds.
+ */
+#if !defined(STM32_SDC_CLOCK_ACTIVATION_DELAY) || defined(__DOXYGEN__)
+#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10
+#endif
+
+/**
+ * @brief Support for unaligned transfers.
+ * @note Unaligned transfers are much slower.
+ */
+#if !defined(STM32_SDC_SDIO_UNALIGNED_SUPPORT) || defined(__DOXYGEN__)
+#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !STM32_HAS_SDIO
+#error "SDIO not present in the selected device"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SDC_SDIO_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SDIO"
+#endif
+
+#if !STM32_DMA_IS_VALID_PRIORITY(STM32_SDC_SDIO_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SDIO"
+#endif
+
+/* The following checks are only required when there is a DMA able to
+ reassign streams to different channels.*/
+#if STM32_ADVANCED_DMA
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if !defined(STM32_SDC_SDIO_DMA_STREAM)
+#error "SDIO DMA streams not defined"
+#endif
+
+/* Check on the validity of the assigned DMA channels.*/
+#if !STM32_DMA_IS_VALID_ID(STM32_SDC_SDIO_DMA_STREAM, STM32_SDC_SDIO_DMA_MSK)
+#error "invalid DMA stream associated to SDIO"
+#endif
+#endif /* STM32_ADVANCED_DMA */
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+/*
+ * SDIO clock divider.
+ */
+#if (defined(STM32F4XX) || defined(STM32F2XX))
+#define STM32_SDIO_DIV_HS 0
+#define STM32_SDIO_DIV_LS 120
+
+#elif STM32_HCLK > 48000000
+#define STM32_SDIO_DIV_HS 1
+#define STM32_SDIO_DIV_LS 178
+#else
+
+#define STM32_SDIO_DIV_HS 0
+#define STM32_SDIO_DIV_LS 118
+#endif
+
+/**
+ * @brief SDIO data timeouts in SDIO clock cycles.
+ */
+#if (defined(STM32F4XX) || defined(STM32F2XX))
+#if !STM32_CLOCK48_REQUIRED
+#error "SDIO requires STM32_CLOCK48_REQUIRED to be enabled"
+#endif
+
+#if STM32_PLL48CLK != 48000000
+#error "invalid STM32_PLL48CLK clock value"
+#endif
+
+#define STM32_SDC_WRITE_TIMEOUT \
+ (((STM32_PLL48CLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * \
+ STM32_SDC_WRITE_TIMEOUT_MS)
+#define STM32_SDC_READ_TIMEOUT \
+ (((STM32_PLL48CLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * \
+ STM32_SDC_READ_TIMEOUT_MS)
+
+#else /* !(defined(STM32F4XX) || defined(STM32F2XX)) */
+
+#define STM32_SDC_WRITE_TIMEOUT \
+ (((STM32_HCLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * \
+ STM32_SDC_WRITE_TIMEOUT_MS)
+#define STM32_SDC_READ_TIMEOUT \
+ (((STM32_HCLK / (STM32_SDIO_DIV_HS + 2)) / 1000) * \
+ STM32_SDC_READ_TIMEOUT_MS)
+
+#endif /* !(defined(STM32F4XX) || defined(STM32F2XX)) */
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of card flags.
+ */
+typedef uint32_t sdcmode_t;
+
+/**
+ * @brief SDC Driver condition flags type.
+ */
+typedef uint32_t sdcflags_t;
+
+/**
+ * @brief Type of a structure representing an SDC driver.
+ */
+typedef struct SDCDriver SDCDriver;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+ /**
+ * @brief Bus width.
+ */
+ sdcbusmode_t bus_width;
+ /* End of the mandatory fields.*/
+} SDCConfig;
+
+/**
+ * @brief @p SDCDriver specific methods.
+ */
+#define _sdc_driver_methods \
+ _mmcsd_block_device_methods
+
+/**
+ * @extends MMCSDBlockDeviceVMT
+ *
+ * @brief @p SDCDriver virtual methods table.
+ */
+struct SDCDriverVMT {
+ _sdc_driver_methods
+};
+
+/**
+ * @brief Structure representing an SDC driver.
+ */
+struct SDCDriver {
+ /**
+ * @brief Virtual Methods Table.
+ */
+ const struct SDCDriverVMT *vmt;
+ _mmcsd_block_device_data
+ /**
+ * @brief Current configuration data.
+ */
+ const SDCConfig *config;
+ /**
+ * @brief Various flags regarding the mounted card.
+ */
+ sdcmode_t cardmode;
+ /**
+ * @brief Errors flags.
+ */
+ sdcflags_t errors;
+ /**
+ * @brief Card RCA.
+ */
+ uint32_t rca;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Thread waiting for I/O completion IRQ.
+ */
+ thread_reference_t thread;
+ /**
+ * @brief DMA mode bit mask.
+ */
+ uint32_t dmamode;
+ /**
+ * @brief Transmit DMA channel.
+ */
+ const stm32_dma_stream_t *dma;
+ /**
+ * @brief Pointer to the SDIO registers block.
+ * @note Needed for debugging aid.
+ */
+ SDIO_TypeDef *sdio;
+ /**
+ * @brief Buffer for internal operations.
+ */
+ uint8_t buf[MMCSD_BLOCK_SIZE];
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern SDCDriver SDCD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void sdc_lld_init(void);
+ void sdc_lld_start(SDCDriver *sdcp);
+ void sdc_lld_stop(SDCDriver *sdcp);
+ void sdc_lld_start_clk(SDCDriver *sdcp);
+ void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk);
+ void sdc_lld_stop_clk(SDCDriver *sdcp);
+ void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode);
+ void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg);
+ bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp);
+ bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp);
+ bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp);
+ bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes,
+ uint8_t cmd, uint32_t argument);
+ bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk,
+ uint8_t *buf, uint32_t blocks);
+ bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk,
+ const uint8_t *buf, uint32_t blocks);
+ bool sdc_lld_sync(SDCDriver *sdcp);
+ bool sdc_lld_is_card_inserted(SDCDriver *sdcp);
+ bool sdc_lld_is_write_protected(SDCDriver *sdcp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SDC */
+
+#endif /* HAL_SDC_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv1/driver.mk
new file mode 100644
index 0000000..7edbc24
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv1/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_SDC TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.c
new file mode 100644
index 0000000..1544981
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.c
@@ -0,0 +1,981 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SDMMCv1/hal_sdc_lld.c
+ * @brief STM32 SDC subsystem low level driver source.
+ *
+ * @addtogroup SDC
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+
+#if HAL_USE_SDC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define SDMMC_ICR_ALL_FLAGS \
+ (SDMMC_ICR_CCRCFAILC | SDMMC_ICR_DCRCFAILC | \
+ SDMMC_ICR_CTIMEOUTC | SDMMC_ICR_DTIMEOUTC | \
+ SDMMC_ICR_TXUNDERRC | SDMMC_ICR_RXOVERRC | \
+ SDMMC_ICR_CMDRENDC | SDMMC_ICR_CMDSENTC | \
+ SDMMC_ICR_DATAENDC | SDMMC_ICR_DBCKENDC | \
+ SDMMC_ICR_SDIOITC)
+
+#define SDMMC_STA_ERROR_MASK \
+ (SDMMC_STA_CCRCFAIL | SDMMC_STA_DCRCFAIL | \
+ SDMMC_STA_CTIMEOUT | SDMMC_STA_DTIMEOUT | \
+ SDMMC_STA_TXUNDERR | SDMMC_STA_RXOVERR)
+
+#define SDMMC_CLKDIV_HS (2 - 2)
+#define SDMMC_CLKDIV_LS (120 - 2)
+
+#define SDMMC1_WRITE_TIMEOUT \
+ (((STM32_SDMMC1CLK / (SDMMC_CLKDIV_HS + 2)) / 1000) * \
+ STM32_SDC_SDMMC_WRITE_TIMEOUT)
+#define SDMMC1_READ_TIMEOUT \
+ (((STM32_SDMMC1CLK / (SDMMC_CLKDIV_HS + 2)) / 1000) * \
+ STM32_SDC_SDMMC_READ_TIMEOUT)
+
+#define SDMMC2_WRITE_TIMEOUT \
+ (((STM32_SDMMC2CLK / (SDMMC_CLKDIV_HS + 2)) / 1000) * \
+ STM32_SDC_SDMMC_WRITE_TIMEOUT)
+#define SDMMC2_READ_TIMEOUT \
+ (((STM32_SDMMC2CLK / (SDMMC_CLKDIV_HS + 2)) / 1000) * \
+ STM32_SDC_SDMMC_READ_TIMEOUT)
+
+#define SDMMC1_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_SDC_SDMMC1_DMA_STREAM, \
+ STM32_SDC_SDMMC1_DMA_CHN)
+
+#define SDMMC2_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_SDC_SDMMC2_DMA_STREAM, \
+ STM32_SDC_SDMMC2_DMA_CHN)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief SDCD1 driver identifier.*/
+#if STM32_SDC_USE_SDMMC1 || defined(__DOXYGEN__)
+SDCDriver SDCD1;
+#endif
+
+/** @brief SDCD2 driver identifier.*/
+#if STM32_SDC_USE_SDMMC2 || defined(__DOXYGEN__)
+SDCDriver SDCD2;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief SDIO default configuration.
+ */
+static const SDCConfig sdc_default_cfg = {
+ SDC_MODE_4BIT
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Prepares to handle read transaction.
+ * @details Designed for read special registers from card.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[out] buf pointer to the read buffer
+ * @param[in] bytes number of bytes to read
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+static bool sdc_lld_prepare_read_bytes(SDCDriver *sdcp,
+ uint8_t *buf, uint32_t bytes) {
+ osalDbgCheck(bytes < 0x1000000);
+
+ sdcp->sdmmc->DTIMER = sdcp->rtmo;
+
+ /* Checks for errors and waits for the card to be ready for reading.*/
+ if (_sdc_wait_for_transfer_state(sdcp))
+ return HAL_FAILED;
+
+ /* Prepares the DMA channel for writing.*/
+ dmaStreamSetMemory0(sdcp->dma, buf);
+ dmaStreamSetTransactionSize(sdcp->dma, bytes / sizeof (uint32_t));
+ dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_P2M);
+ dmaStreamEnable(sdcp->dma);
+
+ /* Setting up data transfer.*/
+ sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS;
+ sdcp->sdmmc->MASK = SDMMC_MASK_DCRCFAILIE |
+ SDMMC_MASK_DTIMEOUTIE |
+ SDMMC_MASK_RXOVERRIE |
+ SDMMC_MASK_DATAENDIE;
+ sdcp->sdmmc->DLEN = bytes;
+
+ /* Transaction starts just after DTEN bit setting.*/
+ sdcp->sdmmc->DCTRL = SDMMC_DCTRL_DTDIR |
+ SDMMC_DCTRL_DTMODE | /* Multibyte data transfer.*/
+ SDMMC_DCTRL_DMAEN |
+ SDMMC_DCTRL_DTEN;
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Prepares card to handle read transaction.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to read
+ * @param[in] n number of blocks to read
+ * @param[in] resp pointer to the response buffer
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+static bool sdc_lld_prepare_read(SDCDriver *sdcp, uint32_t startblk,
+ uint32_t n, uint32_t *resp) {
+
+ /* Driver handles data in 512 bytes blocks (just like HC cards). But if we
+ have not HC card than we must convert address from blocks to bytes.*/
+ if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY))
+ startblk *= MMCSD_BLOCK_SIZE;
+
+ if (n > 1) {
+ /* Send read multiple blocks command to card.*/
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_READ_MULTIPLE_BLOCK,
+ startblk, resp) || MMCSD_R1_ERROR(resp[0]))
+ return HAL_FAILED;
+ }
+ else {
+ /* Send read single block command.*/
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_READ_SINGLE_BLOCK,
+ startblk, resp) || MMCSD_R1_ERROR(resp[0]))
+ return HAL_FAILED;
+ }
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Prepares card to handle write transaction.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to read
+ * @param[in] n number of blocks to write
+ * @param[in] resp pointer to the response buffer
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+static bool sdc_lld_prepare_write(SDCDriver *sdcp, uint32_t startblk,
+ uint32_t n, uint32_t *resp) {
+
+ /* Driver handles data in 512 bytes blocks (just like HC cards). But if we
+ have not HC card than we must convert address from blocks to bytes.*/
+ if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY))
+ startblk *= MMCSD_BLOCK_SIZE;
+
+ if (n > 1) {
+ /* Write multiple blocks command.*/
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK,
+ startblk, resp) || MMCSD_R1_ERROR(resp[0]))
+ return HAL_FAILED;
+ }
+ else {
+ /* Write single block command.*/
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_WRITE_BLOCK,
+ startblk, resp) || MMCSD_R1_ERROR(resp[0]))
+ return HAL_FAILED;
+ }
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Wait end of data transaction and performs finalizations.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] n number of blocks in transaction
+ * @param[in] resp pointer to the response buffer
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ */
+static bool sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n,
+ uint32_t *resp) {
+
+ /* Note the mask is checked before going to sleep because the interrupt
+ may have occurred before reaching the critical zone.*/
+ osalSysLock();
+ if (sdcp->sdmmc->MASK != 0)
+ osalThreadSuspendS(&sdcp->thread);
+ if ((sdcp->sdmmc->STA & SDMMC_STA_DATAEND) == 0) {
+ osalSysUnlock();
+ return HAL_FAILED;
+ }
+
+ /* Waits for transfer completion at DMA level, then the stream is
+ disabled and cleared.*/
+ dmaWaitCompletion(sdcp->dma);
+
+ sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS;
+ sdcp->sdmmc->DCTRL = 0;
+ osalSysUnlock();
+
+ /* Finalize transaction.*/
+ if (n > 1)
+ return sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp);
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Gets SDC errors.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] sta value of the STA register
+ *
+ * @notapi
+ */
+static void sdc_lld_collect_errors(SDCDriver *sdcp, uint32_t sta) {
+ uint32_t errors = SDC_NO_ERROR;
+
+ if (sta & SDMMC_STA_CCRCFAIL)
+ errors |= SDC_CMD_CRC_ERROR;
+ if (sta & SDMMC_STA_DCRCFAIL)
+ errors |= SDC_DATA_CRC_ERROR;
+ if (sta & SDMMC_STA_CTIMEOUT)
+ errors |= SDC_COMMAND_TIMEOUT;
+ if (sta & SDMMC_STA_DTIMEOUT)
+ errors |= SDC_DATA_TIMEOUT;
+ if (sta & SDMMC_STA_TXUNDERR)
+ errors |= SDC_TX_UNDERRUN;
+ if (sta & SDMMC_STA_RXOVERR)
+ errors |= SDC_RX_OVERRUN;
+/* if (sta & SDMMC_STA_STBITERR)
+ errors |= SDC_STARTBIT_ERROR;*/
+
+ sdcp->errors |= errors;
+}
+
+/**
+ * @brief Performs clean transaction stopping in case of errors.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] n number of blocks in transaction
+ * @param[in] resp pointer to the response buffer
+ *
+ * @notapi
+ */
+static void sdc_lld_error_cleanup(SDCDriver *sdcp,
+ uint32_t n,
+ uint32_t *resp) {
+ uint32_t sta = sdcp->sdmmc->STA;
+
+ dmaStreamDisable(sdcp->dma);
+ sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS;
+ sdcp->sdmmc->MASK = 0;
+ sdcp->sdmmc->DCTRL = 0;
+ sdc_lld_collect_errors(sdcp, sta);
+
+ if (n > 1)
+ sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp);
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/**
+ * @brief SDMMC1 IRQ handler.
+ * @details It just wakes transaction thread, errors handling is performed in
+ * there.
+ *
+ * @isr
+ */
+#if STM32_SDC_USE_SDMMC1 || defined(__DOXYGEN__)
+OSAL_IRQ_HANDLER(STM32_SDMMC1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ osalSysLockFromISR();
+
+ /* Disables the source but the status flags are not reset because the
+ read/write functions needs to check them.*/
+ SDMMC1->MASK = 0;
+
+ osalThreadResumeI(&SDCD1.thread, MSG_OK);
+
+ osalSysUnlockFromISR();
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/**
+ * @brief SDMMC2 IRQ handler.
+ * @details It just wakes transaction thread, errors handling is performed in
+ * there.
+ *
+ * @isr
+ */
+#if STM32_SDC_USE_SDMMC2 || defined(__DOXYGEN__)
+OSAL_IRQ_HANDLER(STM32_SDMMC2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ osalSysLockFromISR();
+
+ /* Disables the source but the status flags are not reset because the
+ read/write functions needs to check them.*/
+ SDMMC2->MASK = 0;
+
+ osalThreadResumeI(&SDCD2.thread, MSG_OK);
+
+ osalSysUnlockFromISR();
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level SDC driver initialization.
+ *
+ * @notapi
+ */
+void sdc_lld_init(void) {
+
+#if STM32_SDC_USE_SDMMC1
+ sdcObjectInit(&SDCD1);
+ SDCD1.thread = NULL;
+ SDCD1.rtmo = SDMMC1_READ_TIMEOUT;
+ SDCD1.wtmo = SDMMC1_WRITE_TIMEOUT;
+ SDCD1.dma = NULL;
+ SDCD1.sdmmc = SDMMC1;
+ nvicEnableVector(STM32_SDMMC1_NUMBER, STM32_SDC_SDMMC1_IRQ_PRIORITY);
+#endif
+
+#if STM32_SDC_USE_SDMMC2
+ sdcObjectInit(&SDCD2);
+ SDCD2.thread = NULL;
+ SDCD2.rtmo = SDMMC2_READ_TIMEOUT;
+ SDCD2.wtmo = SDMMC2_WRITE_TIMEOUT;
+ SDCD2.dma = NULL;
+ SDCD2.sdmmc = SDMMC2;
+ nvicEnableVector(STM32_SDMMC2_NUMBER, STM32_SDC_SDMMC2_IRQ_PRIORITY);
+#endif
+}
+
+/**
+ * @brief Configures and activates the SDC peripheral.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_start(SDCDriver *sdcp) {
+
+ /* Checking configuration, using a default if NULL has been passed.*/
+ if (sdcp->config == NULL) {
+ sdcp->config = &sdc_default_cfg;
+ }
+
+ sdcp->dmamode = STM32_DMA_CR_PSIZE_WORD |
+ STM32_DMA_CR_MSIZE_WORD |
+ STM32_DMA_CR_MINC;
+
+#if STM32_DMA_ADVANCED
+ sdcp->dmamode |= STM32_DMA_CR_PFCTRL |
+ STM32_DMA_CR_PBURST_INCR4 |
+ STM32_DMA_CR_MBURST_INCR4;
+#endif
+
+ /* If in stopped state then clocks are enabled and DMA initialized.*/
+ if (sdcp->state == BLK_STOP) {
+#if STM32_SDC_USE_SDMMC1
+ if (&SDCD1 == sdcp) {
+ sdcp->dma = dmaStreamAllocI(STM32_SDC_SDMMC1_DMA_STREAM,
+ STM32_SDC_SDMMC1_IRQ_PRIORITY,
+ NULL,
+ NULL);
+ osalDbgAssert(sdcp->dma != NULL, "unable to allocate stream");
+
+ sdcp->dmamode |= STM32_DMA_CR_CHSEL(SDMMC1_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_SDC_SDMMC1_DMA_PRIORITY);
+ dmaStreamSetPeripheral(sdcp->dma, &sdcp->sdmmc->FIFO);
+#if STM32_DMA_ADVANCED
+ dmaStreamSetFIFO(sdcp->dma, STM32_DMA_FCR_DMDIS |
+ STM32_DMA_FCR_FTH_FULL);
+#endif
+ rccEnableSDMMC1(true);
+ }
+#endif /* STM32_SDC_USE_SDMMC1 */
+
+#if STM32_SDC_USE_SDMMC2
+ if (&SDCD2 == sdcp) {
+ sdcp->dma = dmaStreamAllocI(STM32_SDC_SDMMC2_DMA_STREAM,
+ STM32_SDC_SDMMC2_IRQ_PRIORITY,
+ NULL,
+ NULL);
+ osalDbgAssert(sdcp->dma != NULL, "unable to allocate stream");
+
+ sdcp->dmamode |= STM32_DMA_CR_CHSEL(SDMMC2_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_SDC_SDMMC2_DMA_PRIORITY);
+ dmaStreamSetPeripheral(sdcp->dma, &sdcp->sdmmc->FIFO);
+#if STM32_DMA_ADVANCED
+ dmaStreamSetFIFO(sdcp->dma, STM32_DMA_FCR_DMDIS |
+ STM32_DMA_FCR_FTH_FULL);
+#endif
+ rccEnableSDMMC2(true);
+ }
+#endif /* STM32_SDC_USE_SDMMC2 */
+ }
+
+ /* Configuration, card clock is initially stopped.*/
+ sdcp->sdmmc->POWER = 0;
+ sdcp->sdmmc->CLKCR = 0;
+ sdcp->sdmmc->DCTRL = 0;
+ sdcp->sdmmc->DTIMER = 0;
+}
+
+/**
+ * @brief Deactivates the SDC peripheral.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_stop(SDCDriver *sdcp) {
+
+ if (sdcp->state != BLK_STOP) {
+
+ /* SDIO deactivation.*/
+ sdcp->sdmmc->POWER = 0;
+ sdcp->sdmmc->CLKCR = 0;
+ sdcp->sdmmc->DCTRL = 0;
+ sdcp->sdmmc->DTIMER = 0;
+
+ /* DMA stream released.*/
+ dmaStreamFreeI(sdcp->dma);
+ sdcp->dma = NULL;
+
+ /* Clock deactivation.*/
+#if STM32_SDC_USE_SDMMC1
+ if (&SDCD1 == sdcp) {
+ rccDisableSDMMC1();
+ }
+#endif
+
+#if STM32_SDC_USE_SDMMC2
+ if (&SDCD2 == sdcp) {
+ rccDisableSDMMC2();
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Starts the SDIO clock and sets it to init mode (400kHz or less).
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_start_clk(SDCDriver *sdcp) {
+
+ /* Initial clock setting: 400kHz, 1bit mode.*/
+ sdcp->sdmmc->CLKCR = SDMMC_CLKDIV_LS;
+ sdcp->sdmmc->POWER |= SDMMC_POWER_PWRCTRL_0 | SDMMC_POWER_PWRCTRL_1;
+ sdcp->sdmmc->CLKCR |= SDMMC_CLKCR_CLKEN;
+
+ /* Clock activation delay.*/
+ osalThreadSleep(OSAL_MS2I(STM32_SDC_SDMMC_CLOCK_DELAY));
+}
+
+/**
+ * @brief Sets the SDIO clock to data mode (25/50 MHz or less).
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] clk the clock mode
+ *
+ * @notapi
+ */
+void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk) {
+
+#if STM32_SDC_SDMMC_50MHZ
+ if (SDC_CLK_50MHz == clk) {
+ sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) |
+#if STM32_SDC_SDMMC_PWRSAV
+ SDMMC_CLKDIV_HS | SDMMC_CLKCR_BYPASS |
+ SDMMC_CLKCR_PWRSAV;
+#else
+ SDMMC_CLKDIV_HS | SDMMC_CLKCR_BYPASS;
+#endif
+ }
+ else {
+#if STM32_SDC_SDMMC_PWRSAV
+ sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | SDMMC_CLKDIV_HS |
+ SDMMC_CLKCR_PWRSAV;
+#else
+ sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | SDMMC_CLKDIV_HS;
+#endif
+ }
+#else
+ (void)clk;
+
+#if STM32_SDC_SDMMC_PWRSAV
+ sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | SDMMC_CLKDIV_HS |
+ SDMMC_CLKCR_PWRSAV;
+#else
+ sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) | SDMMC_CLKDIV_HS;
+#endif
+#endif
+}
+
+/**
+ * @brief Stops the SDIO clock.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_stop_clk(SDCDriver *sdcp) {
+
+ sdcp->sdmmc->CLKCR = 0;
+ sdcp->sdmmc->POWER = 0;
+}
+
+/**
+ * @brief Switches the bus to 1, 4 or 8 bits mode.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] mode bus mode
+ *
+ * @notapi
+ */
+void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) {
+ uint32_t clk = sdcp->sdmmc->CLKCR & ~SDMMC_CLKCR_WIDBUS;
+
+ switch (mode) {
+ case SDC_MODE_1BIT:
+ sdcp->sdmmc->CLKCR = clk;
+ break;
+ case SDC_MODE_4BIT:
+ sdcp->sdmmc->CLKCR = clk | SDMMC_CLKCR_WIDBUS_0;
+ break;
+ case SDC_MODE_8BIT:
+ sdcp->sdmmc->CLKCR = clk | SDMMC_CLKCR_WIDBUS_1;
+ break;
+ }
+}
+
+/**
+ * @brief Sends an SDIO command with no response expected.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] cmd card command
+ * @param[in] arg command argument
+ *
+ * @notapi
+ */
+void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg) {
+
+ sdcp->sdmmc->ARG = arg;
+ sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_CPSMEN;
+ while ((sdcp->sdmmc->STA & SDMMC_STA_CMDSENT) == 0)
+ ;
+ sdcp->sdmmc->ICR = SDMMC_ICR_CMDSENTC;
+}
+
+/**
+ * @brief Sends an SDIO command with a short response expected.
+ * @note The CRC is not verified.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] cmd card command
+ * @param[in] arg command argument
+ * @param[out] resp pointer to the response buffer (one word)
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp) {
+ uint32_t sta;
+
+ sdcp->sdmmc->ARG = arg;
+ sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_CPSMEN;
+ while (((sta = sdcp->sdmmc->STA) & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT |
+ SDMMC_STA_CCRCFAIL)) == 0)
+ ;
+ sdcp->sdmmc->ICR = sta & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT |
+ SDMMC_STA_CCRCFAIL);
+ if ((sta & (SDMMC_STA_CTIMEOUT)) != 0) {
+ sdc_lld_collect_errors(sdcp, sta);
+ return HAL_FAILED;
+ }
+ *resp = sdcp->sdmmc->RESP1;
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Sends an SDIO command with a short response expected and CRC.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] cmd card command
+ * @param[in] arg command argument
+ * @param[out] resp pointer to the response buffer (one word)
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp) {
+ uint32_t sta;
+
+ sdcp->sdmmc->ARG = arg;
+ sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_CPSMEN;
+ while (((sta = sdcp->sdmmc->STA) & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT |
+ SDMMC_STA_CCRCFAIL)) == 0)
+ ;
+ sdcp->sdmmc->ICR = sta & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT | SDMMC_STA_CCRCFAIL);
+ if ((sta & (SDMMC_STA_CTIMEOUT | SDMMC_STA_CCRCFAIL)) != 0) {
+ sdc_lld_collect_errors(sdcp, sta);
+ return HAL_FAILED;
+ }
+ *resp = sdcp->sdmmc->RESP1;
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Sends an SDIO command with a long response expected and CRC.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] cmd card command
+ * @param[in] arg command argument
+ * @param[out] resp pointer to the response buffer (four words)
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp) {
+ uint32_t sta;
+
+ (void)sdcp;
+
+ sdcp->sdmmc->ARG = arg;
+ sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_WAITRESP_1 |
+ SDMMC_CMD_CPSMEN;
+ while (((sta = sdcp->sdmmc->STA) & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT |
+ SDMMC_STA_CCRCFAIL)) == 0)
+ ;
+ sdcp->sdmmc->ICR = sta & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT |
+ SDMMC_STA_CCRCFAIL);
+ if ((sta & (SDMMC_STA_ERROR_MASK)) != 0) {
+ sdc_lld_collect_errors(sdcp, sta);
+ return HAL_FAILED;
+ }
+ /* Save bytes in reverse order because MSB in response comes first.*/
+ *resp++ = sdcp->sdmmc->RESP4;
+ *resp++ = sdcp->sdmmc->RESP3;
+ *resp++ = sdcp->sdmmc->RESP2;
+ *resp = sdcp->sdmmc->RESP1;
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Reads special registers using data bus.
+ * @details Needs only during card detection procedure.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[out] buf pointer to the read buffer
+ * @param[in] bytes number of bytes to read
+ * @param[in] cmd card command
+ * @param[in] arg argument for command
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes,
+ uint8_t cmd, uint32_t arg) {
+ uint32_t resp[1];
+
+ if (sdc_lld_prepare_read_bytes(sdcp, buf, bytes))
+ goto error;
+
+ if (sdc_lld_send_cmd_short_crc(sdcp, cmd, arg, resp)
+ || MMCSD_R1_ERROR(resp[0]))
+ goto error;
+
+ if (sdc_lld_wait_transaction_end(sdcp, 1, resp))
+ goto error;
+
+ return HAL_SUCCESS;
+
+error:
+ sdc_lld_error_cleanup(sdcp, 1, resp);
+ return HAL_FAILED;
+}
+
+/**
+ * @brief Reads one or more blocks.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to read
+ * @param[out] buf pointer to the read buffer
+ * @param[in] blocks number of blocks to read
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_read_aligned(SDCDriver *sdcp, uint32_t startblk,
+ uint8_t *buf, uint32_t blocks) {
+ uint32_t resp[1];
+
+ osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE);
+
+ sdcp->sdmmc->DTIMER = sdcp->rtmo;
+
+ /* Checks for errors and waits for the card to be ready for reading.*/
+ if (_sdc_wait_for_transfer_state(sdcp))
+ return HAL_FAILED;
+
+ /* Prepares the DMA channel for writing.*/
+ dmaStreamSetMemory0(sdcp->dma, buf);
+ dmaStreamSetTransactionSize(sdcp->dma,
+ (blocks * MMCSD_BLOCK_SIZE) / sizeof (uint32_t));
+ dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_P2M);
+ dmaStreamEnable(sdcp->dma);
+
+ /* Setting up data transfer.*/
+ sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS;
+ sdcp->sdmmc->MASK = SDMMC_MASK_DCRCFAILIE |
+ SDMMC_MASK_DTIMEOUTIE |
+ SDMMC_MASK_RXOVERRIE |
+ SDMMC_MASK_DATAENDIE;
+ sdcp->sdmmc->DLEN = blocks * MMCSD_BLOCK_SIZE;
+
+ /* Transaction starts just after DTEN bit setting.*/
+ sdcp->sdmmc->DCTRL = SDMMC_DCTRL_DTDIR |
+ SDMMC_DCTRL_DBLOCKSIZE_3 |
+ SDMMC_DCTRL_DBLOCKSIZE_0 |
+ SDMMC_DCTRL_DMAEN |
+ SDMMC_DCTRL_DTEN;
+
+ if (sdc_lld_prepare_read(sdcp, startblk, blocks, resp) == true)
+ goto error;
+
+ if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == true)
+ goto error;
+
+ return HAL_SUCCESS;
+
+error:
+ sdc_lld_error_cleanup(sdcp, blocks, resp);
+ return HAL_FAILED;
+}
+
+/**
+ * @brief Writes one or more blocks.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to write
+ * @param[out] buf pointer to the write buffer
+ * @param[in] n number of blocks to write
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_write_aligned(SDCDriver *sdcp, uint32_t startblk,
+ const uint8_t *buf, uint32_t blocks) {
+ uint32_t resp[1];
+
+ osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE);
+
+ sdcp->sdmmc->DTIMER = sdcp->wtmo;
+
+ /* Checks for errors and waits for the card to be ready for writing.*/
+ if (_sdc_wait_for_transfer_state(sdcp))
+ return HAL_FAILED;
+
+ /* Prepares the DMA channel for writing.*/
+ dmaStreamSetMemory0(sdcp->dma, buf);
+ dmaStreamSetTransactionSize(sdcp->dma,
+ (blocks * MMCSD_BLOCK_SIZE) / sizeof (uint32_t));
+ dmaStreamSetMode(sdcp->dma, sdcp->dmamode | STM32_DMA_CR_DIR_M2P);
+ dmaStreamEnable(sdcp->dma);
+
+ /* Setting up data transfer.*/
+ sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS;
+ sdcp->sdmmc->MASK = SDMMC_MASK_DCRCFAILIE |
+ SDMMC_MASK_DTIMEOUTIE |
+ SDMMC_MASK_TXUNDERRIE |
+ SDMMC_MASK_DATAENDIE;
+ sdcp->sdmmc->DLEN = blocks * MMCSD_BLOCK_SIZE;
+
+ /* Talk to card what we want from it.*/
+ if (sdc_lld_prepare_write(sdcp, startblk, blocks, resp) == true)
+ goto error;
+
+ /* Transaction starts just after DTEN bit setting.*/
+ sdcp->sdmmc->DCTRL = SDMMC_DCTRL_DBLOCKSIZE_3 |
+ SDMMC_DCTRL_DBLOCKSIZE_0 |
+ SDMMC_DCTRL_DMAEN |
+ SDMMC_DCTRL_DTEN;
+
+ if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == true)
+ goto error;
+
+ return HAL_SUCCESS;
+
+error:
+ sdc_lld_error_cleanup(sdcp, blocks, resp);
+ return HAL_FAILED;
+}
+
+/**
+ * @brief Reads one or more blocks.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to read
+ * @param[out] buf pointer to the read buffer
+ * @param[in] blocks number of blocks to read
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk,
+ uint8_t *buf, uint32_t blocks) {
+
+#if STM32_SDC_SDMMC_UNALIGNED_SUPPORT
+ if (((unsigned)buf & 3) != 0) {
+ uint32_t i;
+ for (i = 0; i < blocks; i++) {
+ if (sdc_lld_read_aligned(sdcp, startblk, sdcp->buf, 1))
+ return HAL_FAILED;
+ memcpy(buf, sdcp->buf, MMCSD_BLOCK_SIZE);
+ buf += MMCSD_BLOCK_SIZE;
+ startblk++;
+ }
+ return HAL_SUCCESS;
+ }
+#else /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */
+ osalDbgAssert((((unsigned)buf & 3) == 0), "unaligned buffer");
+#endif /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */
+ return sdc_lld_read_aligned(sdcp, startblk, buf, blocks);
+}
+
+/**
+ * @brief Writes one or more blocks.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to write
+ * @param[out] buf pointer to the write buffer
+ * @param[in] blocks number of blocks to write
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk,
+ const uint8_t *buf, uint32_t blocks) {
+
+#if STM32_SDC_SDMMC_UNALIGNED_SUPPORT
+ if (((unsigned)buf & 3) != 0) {
+ uint32_t i;
+ for (i = 0; i < blocks; i++) {
+ memcpy(sdcp->buf, buf, MMCSD_BLOCK_SIZE);
+ buf += MMCSD_BLOCK_SIZE;
+ if (sdc_lld_write_aligned(sdcp, startblk, sdcp->buf, 1))
+ return HAL_FAILED;
+ startblk++;
+ }
+ return HAL_SUCCESS;
+ }
+#else /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */
+ osalDbgAssert((((unsigned)buf & 3) == 0), "unaligned buffer");
+#endif /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */
+ return sdc_lld_write_aligned(sdcp, startblk, buf, blocks);
+}
+
+/**
+ * @brief Waits for card idle condition.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS the operation succeeded.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @api
+ */
+bool sdc_lld_sync(SDCDriver *sdcp) {
+
+ /* CHTODO: Implement.*/
+ (void)sdcp;
+ return HAL_SUCCESS;
+}
+
+#endif /* HAL_USE_SDC */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.h
new file mode 100644
index 0000000..b9ad69c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv1/hal_sdc_lld.h
@@ -0,0 +1,400 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SDMMCv1/hal_sdc_lld.h
+ * @brief STM32 SDC subsystem low level driver header.
+ *
+ * @addtogroup SDC
+ * @{
+ */
+
+#ifndef HAL_SDC_LLD_H
+#define HAL_SDC_LLD_H
+
+#if HAL_USE_SDC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief SDMMC1 driver enable switch.
+ * @details If set to @p TRUE the support for SDMMC1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SDC_USE_SDMMC1) || defined(__DOXYGEN__)
+#define STM32_SDC_USE_SDMMC1 FALSE
+#endif
+
+/**
+ * @brief SDMMC2 driver enable switch.
+ * @details If set to @p TRUE the support for SDMMC2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SDC_USE_SDMMC2) || defined(__DOXYGEN__)
+#define STM32_SDC_USE_SDMMC2 FALSE
+#endif
+
+/**
+ * @brief Support for unaligned transfers.
+ * @note Unaligned transfers are much slower.
+ */
+#if !defined(STM32_SDC_SDMMC_UNALIGNED_SUPPORT) || defined(__DOXYGEN__)
+#define STM32_SDC_SDMMC_UNALIGNED_SUPPORT TRUE
+#endif
+
+/**
+ * @brief Enable clock bypass.
+ * @note Allow clock speed up to 50 Mhz.
+ */
+#if !defined(STM32_SDC_SDMMC_50MHZ) || defined(__DOXYGEN__)
+#define STM32_SDC_SDMMC_50MHZ FALSE
+#endif
+
+/**
+ * @brief Write timeout in milliseconds.
+ */
+#if !defined(STM32_SDC_SDMMC_WRITE_TIMEOUT) || defined(__DOXYGEN__)
+#define STM32_SDC_SDMMC_WRITE_TIMEOUT 1000
+#endif
+
+/**
+ * @brief Read timeout in milliseconds.
+ */
+#if !defined(STM32_SDC_SDMMC_READ_TIMEOUT) || defined(__DOXYGEN__)
+#define STM32_SDC_SDMMC_READ_TIMEOUT 1000
+#endif
+
+/**
+ * @brief Card clock activation delay in milliseconds.
+ */
+#if !defined(STM32_SDC_SDMMC_CLOCK_DELAY) || defined(__DOXYGEN__)
+#define STM32_SDC_SDMMC_CLOCK_DELAY 10
+#endif
+
+/**
+ * @brief Card clock power saving enable.
+ */
+#if !defined(STM32_SDC_SDMMC_PWRSAV) || defined(__DOXYGEN__)
+#define STM32_SDC_SDMMC_PWRSAV TRUE
+#endif
+
+/**
+ * @brief SDMMC1 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_SDC_SDMMC1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SDC_SDMMC1_DMA_PRIORITY 3
+#endif
+
+/**
+ * @brief SDMMC2 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_SDC_SDMMC2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SDC_SDMMC2_DMA_PRIORITY 3
+#endif
+
+/**
+ * @brief SDMMC1 interrupt priority level setting.
+ */
+#if !defined(STM32_SDC_SDMMC1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SDC_SDMMC1_IRQ_PRIORITY 9
+#endif
+
+/**
+ * @brief SDMMC2 interrupt priority level setting.
+ */
+#if !defined(STM32_SDC_SDMMC2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SDC_SDMMC2_IRQ_PRIORITY 9
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks.*/
+#if (STM32_SDC_USE_SDMMC1 && !defined(STM32_SDMMC1_HANDLER)) || \
+ (STM32_SDC_USE_SDMMC2 && !defined(STM32_SDMMC2_HANDLER))
+#error "STM32_SDMMCx_HANDLER not defined in registry"
+#endif
+
+#if (STM32_SDC_USE_SDMMC1 && !defined(STM32_SDMMC1_NUMBER)) || \
+ (STM32_SDC_USE_SDMMC2 && !defined(STM32_SDMMC2_NUMBER))
+#error "STM32_SDMMCx_NUMBER not defined in registry"
+#endif
+
+#if (STM32_SDC_USE_SDMMC1 && !defined(STM32_SDC_SDMMC1_DMA_MSK)) || \
+ (STM32_SDC_USE_SDMMC2 && !defined(STM32_SDC_SDMMC2_DMA_MSK))
+#error "STM32_SDC_SDMMCx_DMA_MSK not defined in registry"
+#endif
+
+#if (STM32_SDC_USE_SDMMC1 && !defined(STM32_SDC_SDMMC1_DMA_CHN)) || \
+ (STM32_SDC_USE_SDMMC2 && !defined(STM32_SDC_SDMMC2_DMA_CHN))
+#error "STM32_SDC_SDMMCx_DMA_CHN not defined in registry"
+#endif
+
+/* Units checks.*/
+#if STM32_SDC_USE_SDMMC1 && !STM32_HAS_SDMMC1
+#error "SDMMC1 not present in the selected device"
+#endif
+
+#if STM32_SDC_USE_SDMMC2 && !STM32_HAS_SDMMC2
+#error "SDMMC2 not present in the selected device"
+#endif
+
+#if !STM32_SDC_USE_SDMMC1 && !STM32_SDC_USE_SDMMC2
+#error "SDC driver activated but no SDMMC peripheral assigned"
+#endif
+
+/* Clock related tests.*/
+#if STM32_HAS_SDMMC1 && !defined(STM32_SDMMC1CLK)
+#error "STM32_SDMMC1CLK not defined"
+#endif
+
+/* Clock related tests.*/
+#if STM32_HAS_SDMMC2 && !defined(STM32_SDMMC2CLK)
+#error "STM32_SDMMC2CLK not defined"
+#endif
+
+#if !defined(STM32_HCLK)
+#error "STM32_HCLK not defined"
+#endif
+
+#if STM32_HAS_SDMMC1 && (STM32_SDMMC1CLK * 10 > STM32_HCLK * 7)
+#error "STM32_SDMMC1CLK must not exceed STM32_HCLK * 0.7"
+#endif
+
+#if STM32_HAS_SDMMC2 && (STM32_SDMMC2CLK * 10 > STM32_HCLK * 7)
+#error "STM32_SDMMC2CLK must not exceed STM32_HCLK * 0.7"
+#endif
+
+#if STM32_HAS_SDMMC1 && (STM32_SDMMC1CLK > 48000000)
+#error "STM32_SDMMC1CLK must not exceed 48MHz"
+#endif
+
+#if STM32_HAS_SDMMC2 && (STM32_SDMMC2CLK > 48000000)
+#error "STM32_SDMMC2CLK must not exceed 48MHz"
+#endif
+
+#if defined(STM32_SDC_SDMMC_50MHZ) && STM32_SDC_SDMMC_50MHZ && !defined(STM32F7XX)
+#error "50 Mhz clock only works for STM32F7XX"
+#endif
+
+/* SDMMC IRQ priority tests.*/
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SDC_SDMMC1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SDMMC1"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SDC_SDMMC2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SDMMC2"
+#endif
+
+/* DMA priority tests.*/
+#if !STM32_DMA_IS_VALID_PRIORITY(STM32_SDC_SDMMC1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SDMMC1"
+#endif
+
+#if !STM32_DMA_IS_VALID_PRIORITY(STM32_SDC_SDMMC2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SDMMC2"
+#endif
+
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if STM32_SDC_USE_SDMMC1 && !defined(STM32_SDC_SDMMC1_DMA_STREAM)
+#error "SDMMC1 DMA streams not defined"
+#endif
+
+#if STM32_SDC_USE_SDMMC2 && !defined(STM32_SDC_SDMMC2_DMA_STREAM)
+#error "SDMMC2 DMA streams not defined"
+#endif
+
+/* Check on the validity of the assigned DMA channels.*/
+#if STM32_SDC_USE_SDMMC1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SDC_SDMMC1_DMA_STREAM, STM32_SDC_SDMMC1_DMA_MSK)
+#error "invalid DMA stream associated to SDMMC1"
+#endif
+
+#if STM32_SDC_USE_SDMMC2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SDC_SDMMC2_DMA_STREAM, STM32_SDC_SDMMC2_DMA_MSK)
+#error "invalid DMA stream associated to SDMMC2"
+#endif
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of card flags.
+ */
+typedef uint32_t sdcmode_t;
+
+/**
+ * @brief SDC Driver condition flags type.
+ */
+typedef uint32_t sdcflags_t;
+
+/**
+ * @brief Type of a structure representing an SDC driver.
+ */
+typedef struct SDCDriver SDCDriver;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+ /**
+ * @brief Bus width.
+ */
+ sdcbusmode_t bus_width;
+ /* End of the mandatory fields.*/
+} SDCConfig;
+
+/**
+ * @brief @p SDCDriver specific methods.
+ */
+#define _sdc_driver_methods \
+ _mmcsd_block_device_methods
+
+/**
+ * @extends MMCSDBlockDeviceVMT
+ *
+ * @brief @p SDCDriver virtual methods table.
+ */
+struct SDCDriverVMT {
+ _sdc_driver_methods
+};
+
+/**
+ * @brief Structure representing an SDC driver.
+ */
+struct SDCDriver {
+ /**
+ * @brief Virtual Methods Table.
+ */
+ const struct SDCDriverVMT *vmt;
+ _mmcsd_block_device_data
+ /**
+ * @brief Current configuration data.
+ */
+ const SDCConfig *config;
+ /**
+ * @brief Various flags regarding the mounted card.
+ */
+ sdcmode_t cardmode;
+ /**
+ * @brief Errors flags.
+ */
+ sdcflags_t errors;
+ /**
+ * @brief Card RCA.
+ */
+ uint32_t rca;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Thread waiting for I/O completion IRQ.
+ */
+ thread_reference_t thread;
+ /**
+ * @brief DTIMER register value for read operations.
+ */
+ uint32_t rtmo;
+ /**
+ * @brief DTIMER register value for write operations.
+ */
+ uint32_t wtmo;
+ /**
+ * @brief DMA mode bit mask.
+ */
+ uint32_t dmamode;
+ /**
+ * @brief Transmit DMA channel.
+ */
+ const stm32_dma_stream_t *dma;
+ /**
+ * @brief Pointer to the SDMMC registers block.
+ * @note Needed for debugging aid.
+ */
+ SDMMC_TypeDef *sdmmc;
+ /**
+ * @brief Buffer for internal operations.
+ */
+ uint8_t buf[MMCSD_BLOCK_SIZE];
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_SDC_USE_SDMMC1 && !defined(__DOXYGEN__)
+extern SDCDriver SDCD1;
+#endif
+
+#if STM32_SDC_USE_SDMMC2 && !defined(__DOXYGEN__)
+extern SDCDriver SDCD2;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void sdc_lld_init(void);
+ void sdc_lld_start(SDCDriver *sdcp);
+ void sdc_lld_stop(SDCDriver *sdcp);
+ void sdc_lld_start_clk(SDCDriver *sdcp);
+ void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk);
+ void sdc_lld_stop_clk(SDCDriver *sdcp);
+ void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode);
+ void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg);
+ bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp);
+ bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp);
+ bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp);
+ bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes,
+ uint8_t cmd, uint32_t argument);
+ bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk,
+ uint8_t *buf, uint32_t blocks);
+ bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk,
+ const uint8_t *buf, uint32_t blocks);
+ bool sdc_lld_sync(SDCDriver *sdcp);
+ bool sdc_lld_is_card_inserted(SDCDriver *sdcp);
+ bool sdc_lld_is_write_protected(SDCDriver *sdcp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SDC */
+
+#endif /* HAL_SDC_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv2/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv2/driver.mk
new file mode 100644
index 0000000..cf8b9d2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv2/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_SDC TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv2
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.c
new file mode 100644
index 0000000..9740df2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.c
@@ -0,0 +1,865 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SDMMCv2/hal_sdc_lld.c
+ * @brief STM32 SDC subsystem low level driver source.
+ *
+ * @addtogroup SDC
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+
+#if HAL_USE_SDC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define SDMMC_ICR_ALL_FLAGS 0xFFFFFFFFU
+
+#define SDMMC_STA_ERROR_MASK \
+ (SDMMC_STA_CCRCFAIL | SDMMC_STA_DCRCFAIL | \
+ SDMMC_STA_CTIMEOUT | SDMMC_STA_DTIMEOUT | \
+ SDMMC_STA_TXUNDERR | SDMMC_STA_RXOVERR)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief SDCD1 driver identifier.*/
+#if STM32_SDC_USE_SDMMC1 || defined(__DOXYGEN__)
+SDCDriver SDCD1;
+#endif
+
+/** @brief SDCD2 driver identifier.*/
+#if STM32_SDC_USE_SDMMC2 || defined(__DOXYGEN__)
+SDCDriver SDCD2;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief SDIO default configuration.
+ */
+static const SDCConfig sdc_default_cfg = {
+ SDC_MODE_4BIT
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Calculates a clock divider for the specified frequency.
+ * @note The divider is calculated to not exceed the required frequency
+ * in case of non-integer division.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] f required frequency
+ */
+static uint32_t sdc_lld_clkdiv(SDCDriver *sdcp, uint32_t f) {
+
+ if (f >= sdcp->clkfreq) {
+ return 0;
+ }
+
+ return (sdcp->clkfreq + (f * 2) - 1) / (f * 2);
+}
+
+/**
+ * @brief Prepares to handle read transaction.
+ * @details Designed for read special registers from card.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[out] buf pointer to the read buffer
+ * @param[in] bytes number of bytes to read
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+static bool sdc_lld_prepare_read_bytes(SDCDriver *sdcp,
+ uint8_t *buf, uint32_t bytes) {
+ osalDbgCheck(bytes < 0x1000000);
+
+ sdcp->sdmmc->DTIMER = STM32_SDC_SDMMC_READ_TIMEOUT;
+
+ /* Checks for errors and waits for the card to be ready for reading.*/
+ if (_sdc_wait_for_transfer_state(sdcp))
+ return HAL_FAILED;
+
+ /* Setting up data transfer.*/
+ sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS;
+ sdcp->sdmmc->MASK = SDMMC_MASK_DCRCFAILIE |
+ SDMMC_MASK_DTIMEOUTIE |
+ SDMMC_MASK_RXOVERRIE |
+ SDMMC_MASK_DATAENDIE;
+ sdcp->sdmmc->DLEN = bytes;
+
+ /* Transfer modes.*/
+ sdcp->sdmmc->DCTRL = SDMMC_DCTRL_DTDIR |
+ SDMMC_DCTRL_DTMODE_0; /* Multibyte data transfer.*/
+
+ /* Prepares IDMA.*/
+ sdcp->sdmmc->IDMABASE0 = (uint32_t)buf;
+ sdcp->sdmmc->IDMACTRL = SDMMC_IDMA_IDMAEN;
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Prepares card to handle read transaction.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to read
+ * @param[in] n number of blocks to read
+ * @param[in] resp pointer to the response buffer
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+static bool sdc_lld_prepare_read(SDCDriver *sdcp, uint32_t startblk,
+ uint32_t n, uint32_t *resp) {
+
+ /* Driver handles data in 512 bytes blocks (just like HC cards). But if we
+ have not HC card than we must convert address from blocks to bytes.*/
+ if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY))
+ startblk *= MMCSD_BLOCK_SIZE;
+
+ if (n > 1) {
+ /* Send read multiple blocks command to card.*/
+ if (sdc_lld_send_cmd_short_crc(sdcp, SDMMC_CMD_CMDTRANS | MMCSD_CMD_READ_MULTIPLE_BLOCK,
+ startblk, resp) || MMCSD_R1_ERROR(resp[0]))
+ return HAL_FAILED;
+ }
+ else {
+ /* Send read single block command.*/
+ if (sdc_lld_send_cmd_short_crc(sdcp, SDMMC_CMD_CMDTRANS | MMCSD_CMD_READ_SINGLE_BLOCK,
+ startblk, resp) || MMCSD_R1_ERROR(resp[0]))
+ return HAL_FAILED;
+ }
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Prepares card to handle write transaction.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to read
+ * @param[in] n number of blocks to write
+ * @param[in] resp pointer to the response buffer
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+static bool sdc_lld_prepare_write(SDCDriver *sdcp, uint32_t startblk,
+ uint32_t n, uint32_t *resp) {
+
+ /* Driver handles data in 512 bytes blocks (just like HC cards). But if we
+ have not HC card than we must convert address from blocks to bytes.*/
+ if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY))
+ startblk *= MMCSD_BLOCK_SIZE;
+
+ if (n > 1) {
+ /* Write multiple blocks command.*/
+ if (sdc_lld_send_cmd_short_crc(sdcp, SDMMC_CMD_CMDTRANS | MMCSD_CMD_WRITE_MULTIPLE_BLOCK,
+ startblk, resp) || MMCSD_R1_ERROR(resp[0]))
+ return HAL_FAILED;
+ }
+ else {
+ /* Write single block command.*/
+ if (sdc_lld_send_cmd_short_crc(sdcp, SDMMC_CMD_CMDTRANS | MMCSD_CMD_WRITE_BLOCK,
+ startblk, resp) || MMCSD_R1_ERROR(resp[0]))
+ return HAL_FAILED;
+ }
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Wait end of data transaction and performs finalizations.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] n number of blocks in transaction
+ * @param[in] resp pointer to the response buffer
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ */
+static bool sdc_lld_wait_transaction_end(SDCDriver *sdcp, uint32_t n,
+ uint32_t *resp) {
+
+ /* Note the mask is checked before going to sleep because the interrupt
+ may have occurred before reaching the critical zone.*/
+ osalSysLock();
+ if (sdcp->sdmmc->MASK != 0)
+ osalThreadSuspendS(&sdcp->thread);
+
+ /* Stopping operations.*/
+ sdcp->sdmmc->IDMACTRL = 0;
+ sdcp->sdmmc->MASK = 0;
+ sdcp->sdmmc->DCTRL = 0;
+
+ if ((sdcp->sdmmc->STA & SDMMC_STA_DATAEND) == 0) {
+ osalSysUnlock();
+ return HAL_FAILED;
+ }
+
+ /* Clearing status.*/
+ sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS;
+ osalSysUnlock();
+
+ /* Finalize transaction.*/
+ if (n > 1)
+ return sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp);
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Gets SDC errors.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] sta value of the STA register
+ *
+ * @notapi
+ */
+static void sdc_lld_collect_errors(SDCDriver *sdcp, uint32_t sta) {
+ uint32_t errors = SDC_NO_ERROR;
+
+ if (sta & SDMMC_STA_CCRCFAIL)
+ errors |= SDC_CMD_CRC_ERROR;
+ if (sta & SDMMC_STA_DCRCFAIL)
+ errors |= SDC_DATA_CRC_ERROR;
+ if (sta & SDMMC_STA_CTIMEOUT)
+ errors |= SDC_COMMAND_TIMEOUT;
+ if (sta & SDMMC_STA_DTIMEOUT)
+ errors |= SDC_DATA_TIMEOUT;
+ if (sta & SDMMC_STA_TXUNDERR)
+ errors |= SDC_TX_UNDERRUN;
+ if (sta & SDMMC_STA_RXOVERR)
+ errors |= SDC_RX_OVERRUN;
+/* if (sta & SDMMC_STA_STBITERR)
+ errors |= SDC_STARTBIT_ERROR;*/
+
+ sdcp->errors |= errors;
+}
+
+/**
+ * @brief Performs clean transaction stopping in case of errors.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] n number of blocks in transaction
+ * @param[in] resp pointer to the response buffer
+ *
+ * @notapi
+ */
+static void sdc_lld_error_cleanup(SDCDriver *sdcp,
+ uint32_t n,
+ uint32_t *resp) {
+ uint32_t sta = sdcp->sdmmc->STA;
+
+ /* Clearing status.*/
+ sta = sdcp->sdmmc->STA;
+ sdcp->sdmmc->ICR = sta;
+ sdc_lld_collect_errors(sdcp, sta);
+
+ if (n > 1)
+ sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_STOP_TRANSMISSION, 0, resp);
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level SDC driver initialization.
+ *
+ * @notapi
+ */
+void sdc_lld_init(void) {
+
+#if STM32_SDC_USE_SDMMC1
+ sdcObjectInit(&SDCD1);
+ SDCD1.thread = NULL;
+ SDCD1.sdmmc = SDMMC1;
+ SDCD1.clkfreq = STM32_SDMMC1CLK;
+#endif
+
+#if STM32_SDC_USE_SDMMC2
+ sdcObjectInit(&SDCD2);
+ SDCD2.thread = NULL;
+ SDCD2.sdmmc = SDMMC2;
+ SDCD2.clkfreq = STM32_SDMMC2CLK;
+#endif
+}
+
+/**
+ * @brief Configures and activates the SDC peripheral.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_start(SDCDriver *sdcp) {
+
+ /* Checking configuration, using a default if NULL has been passed.*/
+ if (sdcp->config == NULL) {
+ sdcp->config = &sdc_default_cfg;
+ }
+
+ /* If in stopped state then clocks are enabled and DMA initialized.*/
+ if (sdcp->state == BLK_STOP) {
+#if STM32_SDC_USE_SDMMC1
+ if (&SDCD1 == sdcp) {
+ rccEnableSDMMC1(true);
+ }
+#endif /* STM32_SDC_USE_SDMMC1 */
+
+#if STM32_SDC_USE_SDMMC2
+ if (&SDCD2 == sdcp) {
+ rccEnableSDMMC2(true);
+ }
+#endif /* STM32_SDC_USE_SDMMC2 */
+ }
+
+ /* Configuration, card clock is initially stopped.*/
+ sdcp->sdmmc->IDMACTRL = 0;
+ sdcp->sdmmc->DCTRL = 0;
+ sdcp->sdmmc->POWER = 0;
+ sdcp->sdmmc->CLKCR = 0;
+ sdcp->sdmmc->DTIMER = 0;
+ sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS;
+}
+
+/**
+ * @brief Deactivates the SDC peripheral.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_stop(SDCDriver *sdcp) {
+
+ if (sdcp->state != BLK_STOP) {
+
+ /* SDIO deactivation.*/
+ sdcp->sdmmc->IDMACTRL = 0;
+ sdcp->sdmmc->DCTRL = 0;
+ sdcp->sdmmc->POWER = 0;
+ sdcp->sdmmc->CLKCR = 0;
+ sdcp->sdmmc->DTIMER = 0;
+ sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS;
+
+ /* Clock deactivation.*/
+#if STM32_SDC_USE_SDMMC1
+ if (&SDCD1 == sdcp) {
+ rccDisableSDMMC1();
+ }
+#endif
+
+#if STM32_SDC_USE_SDMMC2
+ if (&SDCD2 == sdcp) {
+ rccDisableSDMMC2();
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Starts the SDIO clock and sets it to init mode (400kHz or less).
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_start_clk(SDCDriver *sdcp) {
+
+ /* Initial clock setting: 400kHz, 1bit mode.*/
+ sdcp->sdmmc->CLKCR = sdc_lld_clkdiv(sdcp, 4000000);
+ sdcp->sdmmc->POWER |= SDMMC_POWER_PWRCTRL_0 | SDMMC_POWER_PWRCTRL_1;
+/* TODO sdcp->sdmmc->CLKCR |= SDMMC_CLKCR_CLKEN;*/
+
+ /* Clock activation delay.*/
+ osalThreadSleep(OSAL_MS2I(STM32_SDC_SDMMC_CLOCK_DELAY));
+}
+
+/**
+ * @brief Sets the SDIO clock to data mode (25/50 MHz or less).
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] clk the clock mode
+ *
+ * @notapi
+ */
+void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk) {
+
+ if (SDC_CLK_50MHz == clk) {
+ sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) |
+#if STM32_SDC_SDMMC_PWRSAV
+ sdc_lld_clkdiv(sdcp, 50000000) | SDMMC_CLKCR_PWRSAV;
+#else
+ sdc_lld_clkdiv(sdcp, 50000000);
+#endif
+ }
+ else {
+#if STM32_SDC_SDMMC_PWRSAV
+ sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) |
+ sdc_lld_clkdiv(sdcp, 25000000) | SDMMC_CLKCR_PWRSAV;
+#else
+ sdcp->sdmmc->CLKCR = (sdcp->sdmmc->CLKCR & 0xFFFFFF00U) |
+ sdc_lld_clkdiv(sdcp, 25000000);
+#endif
+ }
+}
+
+/**
+ * @brief Stops the SDIO clock.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_stop_clk(SDCDriver *sdcp) {
+
+ sdcp->sdmmc->CLKCR = 0;
+ sdcp->sdmmc->POWER = 0;
+}
+
+/**
+ * @brief Switches the bus to 1, 4 or 8 bits mode.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] mode bus mode
+ *
+ * @notapi
+ */
+void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) {
+ uint32_t clk = sdcp->sdmmc->CLKCR & ~SDMMC_CLKCR_WIDBUS;
+
+ switch (mode) {
+ case SDC_MODE_1BIT:
+ sdcp->sdmmc->CLKCR = clk;
+ break;
+ case SDC_MODE_4BIT:
+ sdcp->sdmmc->CLKCR = clk | SDMMC_CLKCR_WIDBUS_0;
+ break;
+ case SDC_MODE_8BIT:
+ sdcp->sdmmc->CLKCR = clk | SDMMC_CLKCR_WIDBUS_1;
+ break;
+ }
+}
+
+/**
+ * @brief Sends an SDIO command with no response expected.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] cmd card command
+ * @param[in] arg command argument
+ *
+ * @notapi
+ */
+void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg) {
+
+ sdcp->sdmmc->ARG = arg;
+ sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_CPSMEN;
+ while ((sdcp->sdmmc->STA & SDMMC_STA_CMDSENT) == 0)
+ ;
+ sdcp->sdmmc->ICR = SDMMC_ICR_CMDSENTC;
+}
+
+/**
+ * @brief Sends an SDIO command with a short response expected.
+ * @note The CRC is not verified.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] cmd card command
+ * @param[in] arg command argument
+ * @param[out] resp pointer to the response buffer (one word)
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp) {
+ uint32_t sta;
+
+ sdcp->sdmmc->ARG = arg;
+ sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_CPSMEN;
+ while (((sta = sdcp->sdmmc->STA) & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT |
+ SDMMC_STA_CCRCFAIL)) == 0)
+ ;
+ sdcp->sdmmc->ICR = sta & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT |
+ SDMMC_STA_CCRCFAIL);
+ if ((sta & (SDMMC_STA_CTIMEOUT)) != 0) {
+ sdc_lld_collect_errors(sdcp, sta);
+ return HAL_FAILED;
+ }
+ *resp = sdcp->sdmmc->RESP1;
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Sends an SDIO command with a short response expected and CRC.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] cmd card command
+ * @param[in] arg command argument
+ * @param[out] resp pointer to the response buffer (one word)
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp) {
+ uint32_t sta;
+
+ sdcp->sdmmc->ARG = arg;
+ sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_CPSMEN;
+ while (((sta = sdcp->sdmmc->STA) & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT |
+ SDMMC_STA_CCRCFAIL)) == 0)
+ ;
+ sdcp->sdmmc->ICR = sta & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT |
+ SDMMC_STA_CCRCFAIL);
+ if ((sta & (SDMMC_STA_CTIMEOUT | SDMMC_STA_CCRCFAIL)) != 0) {
+ sdc_lld_collect_errors(sdcp, sta);
+ return HAL_FAILED;
+ }
+ *resp = sdcp->sdmmc->RESP1;
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Sends an SDIO command with a long response expected and CRC.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] cmd card command
+ * @param[in] arg command argument
+ * @param[out] resp pointer to the response buffer (four words)
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp) {
+ uint32_t sta;
+
+ (void)sdcp;
+
+ sdcp->sdmmc->ARG = arg;
+ sdcp->sdmmc->CMD = (uint32_t)cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_WAITRESP_1 |
+ SDMMC_CMD_CPSMEN;
+ while (((sta = sdcp->sdmmc->STA) & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT |
+ SDMMC_STA_CCRCFAIL)) == 0)
+ ;
+ sdcp->sdmmc->ICR = sta & (SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT |
+ SDMMC_STA_CCRCFAIL);
+ if ((sta & (SDMMC_STA_ERROR_MASK)) != 0) {
+ sdc_lld_collect_errors(sdcp, sta);
+ return HAL_FAILED;
+ }
+ /* Save bytes in reverse order because MSB in response comes first.*/
+ *resp++ = sdcp->sdmmc->RESP4;
+ *resp++ = sdcp->sdmmc->RESP3;
+ *resp++ = sdcp->sdmmc->RESP2;
+ *resp = sdcp->sdmmc->RESP1;
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Reads special registers using data bus.
+ * @details Needs only during card detection procedure.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[out] buf pointer to the read buffer
+ * @param[in] bytes number of bytes to read
+ * @param[in] cmd card command
+ * @param[in] arg argument for command
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes,
+ uint8_t cmd, uint32_t arg) {
+ uint32_t resp[1];
+
+ if (sdc_lld_prepare_read_bytes(sdcp, buf, bytes))
+ goto error;
+
+ if (sdc_lld_send_cmd_short_crc(sdcp, SDMMC_CMD_CMDTRANS | cmd, arg, resp) ||
+ MMCSD_R1_ERROR(resp[0]))
+ goto error;
+
+ if (sdc_lld_wait_transaction_end(sdcp, 1, resp))
+ goto error;
+
+ return HAL_SUCCESS;
+
+error:
+ sdc_lld_error_cleanup(sdcp, 1, resp);
+ return HAL_FAILED;
+}
+
+/**
+ * @brief Reads one or more blocks.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to read
+ * @param[out] buf pointer to the read buffer
+ * @param[in] blocks number of blocks to read
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_read_aligned(SDCDriver *sdcp, uint32_t startblk,
+ uint8_t *buf, uint32_t blocks) {
+ uint32_t resp[1];
+
+ osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE);
+
+ sdcp->sdmmc->DTIMER = STM32_SDC_SDMMC_READ_TIMEOUT;
+
+ /* Checks for errors and waits for the card to be ready for reading.*/
+ if (_sdc_wait_for_transfer_state(sdcp))
+ return HAL_FAILED;
+
+ /* Setting up data transfer.*/
+ sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS;
+ sdcp->sdmmc->MASK = SDMMC_MASK_DCRCFAILIE |
+ SDMMC_MASK_DTIMEOUTIE |
+ SDMMC_MASK_RXOVERRIE |
+ SDMMC_MASK_DATAENDIE;
+ sdcp->sdmmc->DLEN = blocks * MMCSD_BLOCK_SIZE;
+
+ /* Transfer modes.*/
+ sdcp->sdmmc->DCTRL = SDMMC_DCTRL_DTDIR |
+ SDMMC_DCTRL_DBLOCKSIZE_3 |
+ SDMMC_DCTRL_DBLOCKSIZE_0;
+
+ /* Prepares IDMA.*/
+ sdcp->sdmmc->IDMABASE0 = (uint32_t)buf;
+ sdcp->sdmmc->IDMACTRL = SDMMC_IDMA_IDMAEN;
+
+ if (sdc_lld_prepare_read(sdcp, startblk, blocks, resp) == true)
+ goto error;
+
+ if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == true)
+ goto error;
+
+ return HAL_SUCCESS;
+
+error:
+ sdc_lld_error_cleanup(sdcp, blocks, resp);
+ return HAL_FAILED;
+}
+
+/**
+ * @brief Writes one or more blocks.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to write
+ * @param[out] buf pointer to the write buffer
+ * @param[in] n number of blocks to write
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_write_aligned(SDCDriver *sdcp, uint32_t startblk,
+ const uint8_t *buf, uint32_t blocks) {
+ uint32_t resp[1];
+
+ osalDbgCheck(blocks < 0x1000000 / MMCSD_BLOCK_SIZE);
+
+ sdcp->sdmmc->DTIMER = STM32_SDC_SDMMC_WRITE_TIMEOUT;
+
+ /* Checks for errors and waits for the card to be ready for writing.*/
+ if (_sdc_wait_for_transfer_state(sdcp))
+ return HAL_FAILED;
+
+ /* Setting up data transfer.*/
+ sdcp->sdmmc->ICR = SDMMC_ICR_ALL_FLAGS;
+ sdcp->sdmmc->MASK = SDMMC_MASK_DCRCFAILIE |
+ SDMMC_MASK_DTIMEOUTIE |
+ SDMMC_MASK_TXUNDERRIE |
+ SDMMC_MASK_DATAENDIE;
+ sdcp->sdmmc->DLEN = blocks * MMCSD_BLOCK_SIZE;
+
+ /* Transfer modes.*/
+ sdcp->sdmmc->DCTRL = SDMMC_DCTRL_DBLOCKSIZE_3 |
+ SDMMC_DCTRL_DBLOCKSIZE_0;
+
+ /* Prepares IDMA.*/
+ sdcp->sdmmc->IDMABASE0 = (uint32_t)buf;
+ sdcp->sdmmc->IDMACTRL = SDMMC_IDMA_IDMAEN;
+
+ if (sdc_lld_prepare_write(sdcp, startblk, blocks, resp) == true)
+ goto error;
+
+ if (sdc_lld_wait_transaction_end(sdcp, blocks, resp) == true)
+ goto error;
+
+ return HAL_SUCCESS;
+
+error:
+ sdc_lld_error_cleanup(sdcp, blocks, resp);
+ return HAL_FAILED;
+}
+
+/**
+ * @brief Reads one or more blocks.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to read
+ * @param[out] buf pointer to the read buffer
+ * @param[in] blocks number of blocks to read
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk,
+ uint8_t *buf, uint32_t blocks) {
+
+#if STM32_SDC_SDMMC_UNALIGNED_SUPPORT
+ if (((unsigned)buf & 3) != 0) {
+ uint32_t i;
+ for (i = 0; i < blocks; i++) {
+ if (sdc_lld_read_aligned(sdcp, startblk, sdcp->buf, 1))
+ return HAL_FAILED;
+ memcpy(buf, sdcp->buf, MMCSD_BLOCK_SIZE);
+ buf += MMCSD_BLOCK_SIZE;
+ startblk++;
+ }
+ return HAL_SUCCESS;
+ }
+#else /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */
+ osalDbgAssert((((unsigned)buf & 3) == 0), "unaligned buffer");
+#endif /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */
+ return sdc_lld_read_aligned(sdcp, startblk, buf, blocks);
+}
+
+/**
+ * @brief Writes one or more blocks.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to write
+ * @param[out] buf pointer to the write buffer
+ * @param[in] blocks number of blocks to write
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk,
+ const uint8_t *buf, uint32_t blocks) {
+
+#if STM32_SDC_SDMMC_UNALIGNED_SUPPORT
+ if (((unsigned)buf & 3) != 0) {
+ uint32_t i;
+ for (i = 0; i < blocks; i++) {
+ memcpy(sdcp->buf, buf, MMCSD_BLOCK_SIZE);
+ buf += MMCSD_BLOCK_SIZE;
+ if (sdc_lld_write_aligned(sdcp, startblk, sdcp->buf, 1))
+ return HAL_FAILED;
+ startblk++;
+ }
+ return HAL_SUCCESS;
+ }
+#else /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */
+ osalDbgAssert((((unsigned)buf & 3) == 0), "unaligned buffer");
+#endif /* !STM32_SDC_SDIO_UNALIGNED_SUPPORT */
+ return sdc_lld_write_aligned(sdcp, startblk, buf, blocks);
+}
+
+/**
+ * @brief Waits for card idle condition.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS the operation succeeded.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @api
+ */
+bool sdc_lld_sync(SDCDriver *sdcp) {
+
+ /* CHTODO: Implement.*/
+ (void)sdcp;
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Shared service routine.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ */
+void sdc_lld_serve_interrupt(SDCDriver *sdcp) {
+
+ /* Disables the source but the status flags are not reset because the
+ read/write functions needs to check them.*/
+ sdcp->sdmmc->MASK = 0;
+
+ osalSysLockFromISR();
+ osalThreadResumeI(&sdcp->thread, MSG_OK);
+ osalSysUnlockFromISR();
+}
+
+#endif /* HAL_USE_SDC */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.h
new file mode 100644
index 0000000..334bf7a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv2/hal_sdc_lld.h
@@ -0,0 +1,301 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SDMMCv2/hal_sdc_lld.h
+ * @brief STM32 SDC subsystem low level driver header.
+ *
+ * @addtogroup SDC
+ * @{
+ */
+
+#ifndef HAL_SDC_LLD_H
+#define HAL_SDC_LLD_H
+
+#if HAL_USE_SDC || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief SDMMC1 driver enable switch.
+ * @details If set to @p TRUE the support for SDMMC1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SDC_USE_SDMMC1) || defined(__DOXYGEN__)
+#define STM32_SDC_USE_SDMMC1 FALSE
+#endif
+
+/**
+ * @brief SDMMC2 driver enable switch.
+ * @details If set to @p TRUE the support for SDMMC2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SDC_USE_SDMMC2) || defined(__DOXYGEN__)
+#define STM32_SDC_USE_SDMMC2 FALSE
+#endif
+
+/**
+ * @brief Support for unaligned transfers.
+ * @note Unaligned transfers are much slower.
+ */
+#if !defined(STM32_SDC_SDMMC_UNALIGNED_SUPPORT) || defined(__DOXYGEN__)
+#define STM32_SDC_SDMMC_UNALIGNED_SUPPORT TRUE
+#endif
+
+/**
+ * @brief Write timeout in card clock cycles.
+ */
+#if !defined(STM32_SDC_SDMMC_WRITE_TIMEOUT) || defined(__DOXYGEN__)
+#define STM32_SDC_SDMMC_WRITE_TIMEOUT 1000000
+#endif
+
+/**
+ * @brief Read timeout in card clock cycles.
+ */
+#if !defined(STM32_SDC_SDMMC_READ_TIMEOUT) || defined(__DOXYGEN__)
+#define STM32_SDC_SDMMC_READ_TIMEOUT 1000000
+#endif
+
+/**
+ * @brief Card clock activation delay in milliseconds.
+ */
+#if !defined(STM32_SDC_SDMMC_CLOCK_DELAY) || defined(__DOXYGEN__)
+#define STM32_SDC_SDMMC_CLOCK_DELAY 10
+#endif
+
+/**
+ * @brief Card clock power saving enable.
+ */
+#if !defined(STM32_SDC_SDMMC_PWRSAV) || defined(__DOXYGEN__)
+#define STM32_SDC_SDMMC_PWRSAV TRUE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks.*/
+#if (STM32_SDC_USE_SDMMC1 && !defined(STM32_SDMMC1_HANDLER)) || \
+ (STM32_SDC_USE_SDMMC2 && !defined(STM32_SDMMC2_HANDLER))
+#error "STM32_SDMMCx_HANDLER not defined in registry"
+#endif
+
+#if (STM32_SDC_USE_SDMMC1 && !defined(STM32_SDMMC1_NUMBER)) || \
+ (STM32_SDC_USE_SDMMC2 && !defined(STM32_SDMMC2_NUMBER))
+#error "STM32_SDMMCx_NUMBER not defined in registry"
+#endif
+
+/* Units checks.*/
+#if STM32_SDC_USE_SDMMC1 && !STM32_HAS_SDMMC1
+#error "SDMMC1 not present in the selected device"
+#endif
+
+#if STM32_SDC_USE_SDMMC2 && !STM32_HAS_SDMMC2
+#error "SDMMC2 not present in the selected device"
+#endif
+
+#if !STM32_SDC_USE_SDMMC1 && !STM32_SDC_USE_SDMMC2
+#error "SDC driver activated but no SDMMC peripheral assigned"
+#endif
+
+/* Clock related tests.*/
+#if STM32_HAS_SDMMC1 && !defined(STM32_SDMMC1CLK)
+#error "STM32_SDMMC1CLK not defined"
+#endif
+
+/* Clock related tests.*/
+#if STM32_HAS_SDMMC2 && !defined(STM32_SDMMC2CLK)
+#error "STM32_SDMMC2CLK not defined"
+#endif
+
+#if !defined(STM32_HCLK)
+#error "STM32_HCLK not defined"
+#endif
+
+#if STM32_HAS_SDMMC1 && (STM32_SDMMC1CLK * 10 > STM32_HCLK * 7)
+#error "STM32_SDMMC1CLK must not exceed STM32_HCLK * 0.7"
+#endif
+
+#if STM32_HAS_SDMMC2 && (STM32_SDMMC2CLK * 10 > STM32_HCLK * 7)
+#error "STM32_SDMMC2CLK must not exceed STM32_HCLK * 0.7"
+#endif
+
+#if !defined(STM32_SDMMC_MAXCLK)
+#define STM32_SDMMC_MAXCLK 50000000
+#endif
+
+#if STM32_HAS_SDMMC1 && (STM32_SDMMC1CLK > STM32_SDMMC_MAXCLK)
+#error "STM32_SDMMC1CLK must not exceed STM32_SDMMC_MAXCLK"
+#endif
+
+#if STM32_HAS_SDMMC2 && (STM32_SDMMC2CLK > STM32_SDMMC_MAXCLK)
+#error "STM32_SDMMC2CLK must not exceed STM32_SDMMC_MAXCLK"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of card flags.
+ */
+typedef uint32_t sdcmode_t;
+
+/**
+ * @brief SDC Driver condition flags type.
+ */
+typedef uint32_t sdcflags_t;
+
+/**
+ * @brief Type of a structure representing an SDC driver.
+ */
+typedef struct SDCDriver SDCDriver;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+ /**
+ * @brief Bus width.
+ */
+ sdcbusmode_t bus_width;
+ /* End of the mandatory fields.*/
+} SDCConfig;
+
+/**
+ * @brief @p SDCDriver specific methods.
+ */
+#define _sdc_driver_methods \
+ _mmcsd_block_device_methods
+
+/**
+ * @extends MMCSDBlockDeviceVMT
+ *
+ * @brief @p SDCDriver virtual methods table.
+ */
+struct SDCDriverVMT {
+ _sdc_driver_methods
+};
+
+/**
+ * @brief Structure representing an SDC driver.
+ */
+struct SDCDriver {
+ /**
+ * @brief Virtual Methods Table.
+ */
+ const struct SDCDriverVMT *vmt;
+ _mmcsd_block_device_data
+ /**
+ * @brief Current configuration data.
+ */
+ const SDCConfig *config;
+ /**
+ * @brief Various flags regarding the mounted card.
+ */
+ sdcmode_t cardmode;
+ /**
+ * @brief Errors flags.
+ */
+ sdcflags_t errors;
+ /**
+ * @brief Card RCA.
+ */
+ uint32_t rca;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Thread waiting for I/O completion IRQ.
+ */
+ thread_reference_t thread;
+ /**
+ * @brief Pointer to the SDMMC registers block.
+ * @note Needed for debugging aid.
+ */
+ SDMMC_TypeDef *sdmmc;
+ /**
+ * @brief Input clock frequency.
+ */
+ uint32_t clkfreq;
+ /**
+ * @brief Buffer for internal operations.
+ */
+ uint8_t buf[MMCSD_BLOCK_SIZE];
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_SDC_USE_SDMMC1 && !defined(__DOXYGEN__)
+extern SDCDriver SDCD1;
+#endif
+
+#if STM32_SDC_USE_SDMMC2 && !defined(__DOXYGEN__)
+extern SDCDriver SDCD2;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void sdc_lld_init(void);
+ void sdc_lld_start(SDCDriver *sdcp);
+ void sdc_lld_stop(SDCDriver *sdcp);
+ void sdc_lld_start_clk(SDCDriver *sdcp);
+ void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk);
+ void sdc_lld_stop_clk(SDCDriver *sdcp);
+ void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode);
+ void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg);
+ bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp);
+ bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp);
+ bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp);
+ bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes,
+ uint8_t cmd, uint32_t argument);
+ bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk,
+ uint8_t *buf, uint32_t blocks);
+ bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk,
+ const uint8_t *buf, uint32_t blocks);
+ bool sdc_lld_sync(SDCDriver *sdcp);
+ bool sdc_lld_is_card_inserted(SDCDriver *sdcp);
+ bool sdc_lld_is_write_protected(SDCDriver *sdcp);
+ void sdc_lld_serve_interrupt(SDCDriver *sdcp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SDC */
+
+#endif /* HAL_SDC_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv2/stm32_sdmmc1.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv2/stm32_sdmmc1.inc
new file mode 100644
index 0000000..ae7b38e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv2/stm32_sdmmc1.inc
@@ -0,0 +1,110 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SDMMCv2/stm32_sdmmc1.inc
+ * @brief Shared SDMMC1 handler.
+ *
+ * @addtogroup STM32_SDMMC1_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_SDMMC1)
+#error "STM32_HAS_SDMMC1 not defined in registry"
+#endif
+
+#if STM32_HAS_SDMMC1
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_SDMMC1_PRIORITY)
+#error "STM32_IRQ_SDMMC1_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_SDMMC1_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_SDMMC1_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_SDMMC1 */
+
+/* Other checks.*/
+#if (HAL_USE_SDC && STM32_SDC_USE_SDMMC1)
+#define STM32_SDMMC1_IS_USED TRUE
+#else
+#define STM32_SDMMC1_IS_USED FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void sdmmc1_irq_init(void) {
+#if STM32_SDMMC1_IS_USED
+ nvicEnableVector(STM32_SDMMC1_NUMBER, STM32_IRQ_SDMMC1_PRIORITY);
+#endif
+}
+
+static inline void sdmmc1_irq_deinit(void) {
+#if STM32_SDMMC1_IS_USED
+ nvicDisableVector(STM32_SDMMC1_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_SDMMC1_IS_USED|| defined(__DOXYGEN__)
+/**
+ * @brief SDMMC1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_SDMMC1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SDC
+#if STM32_SDC_USE_SDMMC1
+ sdc_lld_serve_interrupt(&SDCD1);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv2/stm32_sdmmc2.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv2/stm32_sdmmc2.inc
new file mode 100644
index 0000000..75c614c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SDMMCv2/stm32_sdmmc2.inc
@@ -0,0 +1,110 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SDMMCv2/stm32_sdmmc2.inc
+ * @brief Shared SDMMC2 handler.
+ *
+ * @addtogroup STM32_SDMMC2_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_SDMMC2)
+#error "STM32_HAS_SDMMC2 not defined in registry"
+#endif
+
+#if STM32_HAS_SDMMC2
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_SDMMC2_PRIORITY)
+#error "STM32_IRQ_SDMMC2_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_SDMMC2_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_SDMMC2_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_SDMMC2 */
+
+/* Other checks.*/
+#if (HAL_USE_SDC && STM32_SDC_USE_SDMMC2)
+#define STM32_SDMMC2_IS_USED TRUE
+#else
+#define STM32_SDMMC2_IS_USED FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void sdmmc2_irq_init(void) {
+#if STM32_SDMMC2_IS_USED
+ nvicEnableVector(STM32_SDMMC2_NUMBER, STM32_IRQ_SDMMC2_PRIORITY);
+#endif
+}
+
+static inline void sdmmc2_irq_deinit(void) {
+#if STM32_SDMMC2_IS_USED
+ nvicDisableVector(STM32_SDMMC2_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_SDMMC2_IS_USED|| defined(__DOXYGEN__)
+/**
+ * @brief SDMMC2 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_SDMMC2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SDC
+#if STM32_SDC_USE_SDMMC2
+ sdc_lld_serve_interrupt(&SDCD2);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv1/driver.mk
new file mode 100644
index 0000000..1af9692
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv1/driver.mk
@@ -0,0 +1,13 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_I2S TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.c
+endif
+ifneq ($(findstring HAL_USE_SPI TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.c
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.c
new file mode 100644
index 0000000..235d2b8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.c
@@ -0,0 +1,584 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SPIv1/hal_i2s_lld.c
+ * @brief STM32 I2S subsystem low level driver source.
+ *
+ * @addtogroup I2S
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_I2S || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define I2S1_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2S_SPI1_RX_DMA_STREAM, \
+ STM32_SPI1_RX_DMA_CHN)
+
+#define I2S1_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2S_SPI1_TX_DMA_STREAM, \
+ STM32_SPI1_TX_DMA_CHN)
+
+#define I2S2_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2S_SPI2_RX_DMA_STREAM, \
+ STM32_SPI2_RX_DMA_CHN)
+
+#define I2S2_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2S_SPI2_TX_DMA_STREAM, \
+ STM32_SPI2_TX_DMA_CHN)
+
+#define I2S3_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2S_SPI3_RX_DMA_STREAM, \
+ STM32_SPI3_RX_DMA_CHN)
+
+#define I2S3_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2S_SPI3_TX_DMA_STREAM, \
+ STM32_SPI3_TX_DMA_CHN)
+
+/*
+ * Static I2S settings for I2S1.
+ */
+#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI1_MODE)
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE)
+#define STM32_I2S1_CFGR_CFG 0
+#endif
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE)
+#define STM32_I2S1_CFGR_CFG SPI_I2SCFGR_I2SCFG_0
+#endif
+#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI1_MODE) */
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE)
+#define STM32_I2S1_CFGR_CFG SPI_I2SCFGR_I2SCFG_1
+#endif
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE)
+#define STM32_I2S1_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \
+ SPI_I2SCFGR_I2SCFG_0)
+#endif
+#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI1_MODE) */
+
+/*
+ * Static I2S settings for I2S2.
+ */
+#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE)
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE)
+#define STM32_I2S2_CFGR_CFG 0
+#endif
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE)
+#define STM32_I2S2_CFGR_CFG SPI_I2SCFGR_I2SCFG_0
+#endif
+#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE) */
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE)
+#define STM32_I2S2_CFGR_CFG SPI_I2SCFGR_I2SCFG_1
+#endif
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE)
+#define STM32_I2S2_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \
+ SPI_I2SCFGR_I2SCFG_0)
+#endif
+#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE) */
+
+/*
+ * Static I2S settings for I2S3.
+ */
+#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE)
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE)
+#define STM32_I2S3_CFGR_CFG 0
+#endif
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE)
+#define STM32_I2S3_CFGR_CFG SPI_I2SCFGR_I2SCFG_0
+#endif
+#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE) */
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE)
+#define STM32_I2S3_CFGR_CFG SPI_I2SCFGR_I2SCFG_1
+#endif
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE)
+#define STM32_I2S3_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \
+ SPI_I2SCFGR_I2SCFG_0)
+#endif
+#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE) */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief I2S1 driver identifier.*/
+#if STM32_I2S_USE_SPI1 || defined(__DOXYGEN__)
+I2SDriver I2SD1;
+#endif
+
+/** @brief I2S2 driver identifier.*/
+#if STM32_I2S_USE_SPI2 || defined(__DOXYGEN__)
+I2SDriver I2SD2;
+#endif
+
+/** @brief I2S3 driver identifier.*/
+#if STM32_I2S_USE_SPI3 || defined(__DOXYGEN__)
+I2SDriver I2SD3;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) || \
+ STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) || \
+ STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__)
+/**
+ * @brief Shared end-of-rx service routine.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void i2s_lld_serve_rx_interrupt(I2SDriver *i2sp, uint32_t flags) {
+
+ (void)i2sp;
+
+ /* DMA errors handling.*/
+#if defined(STM32_I2S_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_I2S_DMA_ERROR_HOOK(i2sp);
+ }
+#endif
+
+ /* Callbacks handling, note it is portable code defined in the high
+ level driver.*/
+ if ((flags & STM32_DMA_ISR_TCIF) != 0) {
+ /* Transfer complete processing.*/
+ _i2s_isr_full_code(i2sp);
+ }
+ else if ((flags & STM32_DMA_ISR_HTIF) != 0) {
+ /* Half transfer processing.*/
+ _i2s_isr_half_code(i2sp);
+ }
+}
+#endif
+
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) || \
+ STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) || \
+ STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__)
+/**
+ * @brief Shared end-of-tx service routine.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void i2s_lld_serve_tx_interrupt(I2SDriver *i2sp, uint32_t flags) {
+
+ (void)i2sp;
+
+ /* DMA errors handling.*/
+#if defined(STM32_I2S_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_I2S_DMA_ERROR_HOOK(i2sp);
+ }
+#endif
+
+ /* Callbacks handling, note it is portable code defined in the high
+ level driver.*/
+ if ((flags & STM32_DMA_ISR_TCIF) != 0) {
+ /* Transfer complete processing.*/
+ _i2s_isr_full_code(i2sp);
+ }
+ else if ((flags & STM32_DMA_ISR_HTIF) != 0) {
+ /* Half transfer processing.*/
+ _i2s_isr_half_code(i2sp);
+ }
+}
+#endif
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level I2S driver initialization.
+ *
+ * @notapi
+ */
+void i2s_lld_init(void) {
+
+#if STM32_I2S_USE_SPI1
+ i2sObjectInit(&I2SD1);
+ I2SD1.spi = SPI1;
+ I2SD1.cfg = STM32_I2S1_CFGR_CFG;
+ I2SD1.dmarx = NULL;
+ I2SD1.dmatx = NULL;
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE)
+ I2SD1.rxdmamode = STM32_DMA_CR_CHSEL(I2S1_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2S_SPI1_DMA_PRIORITY) |
+ STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MSIZE_HWORD |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_CIRC |
+ STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#else
+ I2SD1.rxdmamode = 0;
+#endif
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE)
+ I2SD1.txdmamode = STM32_DMA_CR_CHSEL(I2S1_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2S_SPI1_DMA_PRIORITY) |
+ STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MSIZE_HWORD |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_CIRC |
+ STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#else
+ I2SD1.txdmamode = 0;
+#endif
+#endif
+
+#if STM32_I2S_USE_SPI2
+ i2sObjectInit(&I2SD2);
+ I2SD2.spi = SPI2;
+ I2SD2.cfg = STM32_I2S2_CFGR_CFG;
+ I2SD2.dmarx = NULL;
+ I2SD2.dmatx = NULL;
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE)
+ I2SD2.rxdmamode = STM32_DMA_CR_CHSEL(I2S2_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2S_SPI2_DMA_PRIORITY) |
+ STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MSIZE_HWORD |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_CIRC |
+ STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#else
+ I2SD2.rxdmamode = 0;
+#endif
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE)
+ I2SD2.txdmamode = STM32_DMA_CR_CHSEL(I2S2_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2S_SPI2_DMA_PRIORITY) |
+ STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MSIZE_HWORD |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_CIRC |
+ STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#else
+ I2SD2.txdmamode = 0;
+#endif
+#endif
+
+#if STM32_I2S_USE_SPI3
+ i2sObjectInit(&I2SD3);
+ I2SD3.spi = SPI3;
+ I2SD3.cfg = STM32_I2S3_CFGR_CFG;
+ I2SD3.dmarx = NULL;
+ I2SD3.dmatx = NULL;
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE)
+ I2SD3.rxdmamode = STM32_DMA_CR_CHSEL(I2S3_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2S_SPI3_DMA_PRIORITY) |
+ STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MSIZE_HWORD |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_CIRC |
+ STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#else
+ I2SD3.rxdmamode = 0;
+#endif
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE)
+ I2SD3.txdmamode = STM32_DMA_CR_CHSEL(I2S3_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2S_SPI3_DMA_PRIORITY) |
+ STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MSIZE_HWORD |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_CIRC |
+ STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#else
+ I2SD3.txdmamode = 0;
+#endif
+#endif
+}
+
+/**
+ * @brief Configures and activates the I2S peripheral.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @notapi
+ */
+void i2s_lld_start(I2SDriver *i2sp) {
+
+ /* If in stopped state then enables the SPI and DMA clocks.*/
+ if (i2sp->state == I2S_STOP) {
+
+#if STM32_I2S_USE_SPI1
+ if (&I2SD1 == i2sp) {
+
+ /* Enabling I2S unit clock.*/
+ rccEnableSPI1(true);
+
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE)
+ i2sp->dmarx = dmaStreamAllocI(STM32_I2S_SPI1_RX_DMA_STREAM,
+ STM32_I2S_SPI1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt,
+ (void *)i2sp);
+ osalDbgAssert(i2sp->dmarx != NULL, "unable to allocate stream");
+
+ /* CRs settings are done here because those never changes until
+ the driver is stopped.*/
+ i2sp->spi->CR1 = 0;
+ i2sp->spi->CR2 = SPI_CR2_RXDMAEN;
+#endif
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE)
+ i2sp->dmatx = dmaStreamAllocI(STM32_I2S_SPI1_TX_DMA_STREAM,
+ STM32_I2S_SPI1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt,
+ (void *)i2sp);
+ osalDbgAssert(i2sp->dmatx != NULL, "unable to allocate stream");
+
+ /* CRs settings are done here because those never changes until
+ the driver is stopped.*/
+ i2sp->spi->CR1 = 0;
+ i2sp->spi->CR2 = SPI_CR2_TXDMAEN;
+#endif
+ }
+#endif
+
+#if STM32_I2S_USE_SPI2
+ if (&I2SD2 == i2sp) {
+
+ /* Enabling I2S unit clock.*/
+ rccEnableSPI2(true);
+
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE)
+ i2sp->dmarx = dmaStreamAllocI(STM32_I2S_SPI2_RX_DMA_STREAM,
+ STM32_I2S_SPI2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt,
+ (void *)i2sp);
+ osalDbgAssert(i2sp->dmarx != NULL, "unable to allocate stream");
+
+ /* CRs settings are done here because those never changes until
+ the driver is stopped.*/
+ i2sp->spi->CR1 = 0;
+ i2sp->spi->CR2 = SPI_CR2_RXDMAEN;
+#endif
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE)
+ i2sp->dmatx = dmaStreamAllocI(STM32_I2S_SPI2_TX_DMA_STREAM,
+ STM32_I2S_SPI2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt,
+ (void *)i2sp);
+ osalDbgAssert(i2sp->dmatx != NULL, "unable to allocate stream");
+
+ /* CRs settings are done here because those never changes until
+ the driver is stopped.*/
+ i2sp->spi->CR1 = 0;
+ i2sp->spi->CR2 = SPI_CR2_TXDMAEN;
+#endif
+ }
+#endif
+
+#if STM32_I2S_USE_SPI3
+ if (&I2SD3 == i2sp) {
+
+ /* Enabling I2S unit clock.*/
+ rccEnableSPI3(true);
+
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE)
+ i2sp->dmarx = dmaStreamAllocI(STM32_I2S_SPI3_RX_DMA_STREAM,
+ STM32_I2S_SPI3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt,
+ (void *)i2sp);
+ osalDbgAssert(i2sp->dmarx != NULL, "unable to allocate stream");
+
+ /* CRs settings are done here because those never changes until
+ the driver is stopped.*/
+ i2sp->spi->CR1 = 0;
+ i2sp->spi->CR2 = SPI_CR2_RXDMAEN;
+#endif
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE)
+ i2sp->dmatx = dmaStreamAllocI(STM32_I2S_SPI3_TX_DMA_STREAM,
+ STM32_I2S_SPI3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt,
+ (void *)i2sp);
+ osalDbgAssert(i2sp->dmatx != NULL, "unable to allocate stream");
+
+ /* CRs settings are done here because those never changes until
+ the driver is stopped.*/
+ i2sp->spi->CR1 = 0;
+ i2sp->spi->CR2 = SPI_CR2_TXDMAEN;
+#endif
+ }
+#endif
+ }
+
+ /* I2S (re)configuration.*/
+ i2sp->spi->I2SPR = i2sp->config->i2spr;
+ i2sp->spi->I2SCFGR = i2sp->config->i2scfgr | i2sp->cfg | SPI_I2SCFGR_I2SMOD;
+}
+
+/**
+ * @brief Deactivates the I2S peripheral.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @notapi
+ */
+void i2s_lld_stop(I2SDriver *i2sp) {
+
+ /* If in ready state then disables the SPI clock.*/
+ if (i2sp->state == I2S_READY) {
+
+ /* SPI disable.*/
+ i2sp->spi->CR2 = 0;
+ if (NULL != i2sp->dmarx) {
+ dmaStreamFreeI(i2sp->dmarx);
+ i2sp->dmarx = NULL;
+ }
+ if (NULL != i2sp->dmatx) {
+ dmaStreamFreeI(i2sp->dmatx);
+ i2sp->dmatx = NULL;
+ }
+
+#if STM32_I2S_USE_SPI1
+ if (&I2SD1 == i2sp)
+ rccDisableSPI1();
+#endif
+
+#if STM32_I2S_USE_SPI2
+ if (&I2SD2 == i2sp)
+ rccDisableSPI2();
+#endif
+
+#if STM32_I2S_USE_SPI3
+ if (&I2SD3 == i2sp)
+ rccDisableSPI3();
+#endif
+ }
+}
+
+/**
+ * @brief Starts a I2S data exchange.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @notapi
+ */
+void i2s_lld_start_exchange(I2SDriver *i2sp) {
+ size_t size = i2sp->config->size;
+
+ /* In 32 bit modes the DMA has to perform double operations because fetches
+ are always performed using 16 bit accesses.
+ DATLEN CHLEN SIZE
+ 00 (16) 0 (16) 16
+ 00 (16) 1 (32) 16
+ 01 (24) X 32
+ 10 (32) X 32
+ 11 (NA) X NA
+ */
+ if ((i2sp->config->i2scfgr & SPI_I2SCFGR_DATLEN) != 0)
+ size *= 2;
+
+ /* RX DMA setup.*/
+ if (NULL != i2sp->dmarx) {
+ dmaStreamSetMode(i2sp->dmarx, i2sp->rxdmamode);
+ dmaStreamSetPeripheral(i2sp->dmarx, &i2sp->spi->DR);
+ dmaStreamSetMemory0(i2sp->dmarx, i2sp->config->rx_buffer);
+ dmaStreamSetTransactionSize(i2sp->dmarx, size);
+ dmaStreamEnable(i2sp->dmarx);
+ }
+
+ /* TX DMA setup.*/
+ if (NULL != i2sp->dmatx) {
+ dmaStreamSetMode(i2sp->dmatx, i2sp->txdmamode);
+ dmaStreamSetPeripheral(i2sp->dmatx, &i2sp->spi->DR);
+ dmaStreamSetMemory0(i2sp->dmatx, i2sp->config->tx_buffer);
+ dmaStreamSetTransactionSize(i2sp->dmatx, size);
+ dmaStreamEnable(i2sp->dmatx);
+ }
+
+ /* Starting transfer.*/
+ i2sp->spi->I2SCFGR |= SPI_I2SCFGR_I2SE;
+}
+
+/**
+ * @brief Stops the ongoing data exchange.
+ * @details The ongoing data exchange, if any, is stopped, if the driver
+ * was not active the function does nothing.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @notapi
+ */
+void i2s_lld_stop_exchange(I2SDriver *i2sp) {
+
+ /* Stop TX DMA, if enabled.*/
+ if (NULL != i2sp->dmatx) {
+ dmaStreamDisable(i2sp->dmatx);
+
+ /* From the RM: To switch off the I2S, by clearing I2SE, it is mandatory
+ to wait for TXE = 1 and BSY = 0.*/
+ while ((i2sp->spi->SR & (SPI_SR_TXE | SPI_SR_BSY)) != SPI_SR_TXE)
+ ;
+
+ /* Stop SPI/I2S peripheral.*/
+ i2sp->spi->I2SCFGR &= ~SPI_I2SCFGR_I2SE;
+ }
+
+ /* Stop RX DMA, if enabled then draining the RX DR.*/
+ if (NULL != i2sp->dmarx) {
+ dmaStreamDisable(i2sp->dmarx);
+
+ /* Waiting for some data to be present in RX DR.*/
+ while ((i2sp->spi->SR & SPI_SR_RXNE) != SPI_SR_RXNE)
+ ;
+
+ /* Stop SPI/I2S peripheral.*/
+ i2sp->spi->I2SCFGR &= ~SPI_I2SCFGR_I2SE;
+
+ /* Purging data in DR.*/
+ while ((i2sp->spi->SR & SPI_SR_RXNE) != 0)
+ (void) i2sp->spi->DR;
+ }
+}
+
+#endif /* HAL_USE_I2S */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.h
new file mode 100644
index 0000000..37b3f2a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv1/hal_i2s_lld.h
@@ -0,0 +1,371 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SPIv1/hal_i2s_lld.h
+ * @brief STM32 I2S subsystem low level driver header.
+ *
+ * @addtogroup I2S
+ * @{
+ */
+
+#ifndef HAL_I2S_LLD_H
+#define HAL_I2S_LLD_H
+
+#if HAL_USE_I2S || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Static I2S modes
+ * @{
+ */
+#define STM32_I2S_MODE_SLAVE 0
+#define STM32_I2S_MODE_MASTER 1
+#define STM32_I2S_MODE_RX 2
+#define STM32_I2S_MODE_TX 4
+#define STM32_I2S_MODE_RXTX (STM32_I2S_MODE_RX | \
+ STM32_I2S_MODE_TX)
+/** @} */
+
+/**
+ * @name Mode checks
+ * @{
+ */
+#define STM32_I2S_IS_MASTER(mode) ((mode) & STM32_I2S_MODE_MASTER)
+#define STM32_I2S_RX_ENABLED(mode) ((mode) & STM32_I2S_MODE_RX)
+#define STM32_I2S_TX_ENABLED(mode) ((mode) & STM32_I2S_MODE_TX)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief I2S1 driver enable switch.
+ * @details If set to @p TRUE the support for I2S1 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_I2S_USE_SPI1) || defined(__DOXYGEN__)
+#define STM32_I2S_USE_SPI1 FALSE
+#endif
+
+/**
+ * @brief I2S2 driver enable switch.
+ * @details If set to @p TRUE the support for I2S2 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_I2S_USE_SPI2) || defined(__DOXYGEN__)
+#define STM32_I2S_USE_SPI2 FALSE
+#endif
+
+/**
+ * @brief I2S3 driver enable switch.
+ * @details If set to @p TRUE the support for I2S3 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_I2S_USE_SPI3) || defined(__DOXYGEN__)
+#define STM32_I2S_USE_SPI3 FALSE
+#endif
+
+/**
+ * @brief I2S1 mode.
+ */
+#if !defined(STM32_I2S_SPI1_MODE) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI1_MODE (STM32_I2S_MODE_MASTER | \
+ STM32_I2S_MODE_RX)
+#endif
+
+/**
+ * @brief I2S2 mode.
+ */
+#if !defined(STM32_I2S_SPI2_MODE) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI2_MODE (STM32_I2S_MODE_MASTER | \
+ STM32_I2S_MODE_RX)
+#endif
+
+/**
+ * @brief I2S3 mode.
+ */
+#if !defined(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI3_MODE (STM32_I2S_MODE_MASTER | \
+ STM32_I2S_MODE_RX)
+#endif
+
+/**
+ * @brief I2S1 interrupt priority level setting.
+ */
+#if !defined(STM32_I2S_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI1_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief I2S2 interrupt priority level setting.
+ */
+#if !defined(STM32_I2S_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI2_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief I2S3 interrupt priority level setting.
+ */
+#if !defined(STM32_I2S_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI3_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief I2S1 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_I2S_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI1_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2S2 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_I2S_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI2_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2S3 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_I2S_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI3_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2S DMA error hook.
+ */
+#if !defined(STM32_I2S_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure")
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if STM32_I2S_USE_SPI1 && !STM32_SPI1_SUPPORTS_I2S
+#error "SPI1 does not support I2S mode"
+#endif
+
+#if STM32_I2S_USE_SPI2 && !STM32_SPI2_SUPPORTS_I2S
+#error "SPI2 does not support I2S mode"
+#endif
+
+#if STM32_I2S_USE_SPI3 && !STM32_SPI3_SUPPORTS_I2S
+#error "SPI3 does not support I2S mode"
+#endif
+
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) && \
+ STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE)
+#error "I2S1 RX and TX mode not supported in this driver implementation"
+#endif
+
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) && \
+ STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE)
+#error "I2S2 RX and TX mode not supported in this driver implementation"
+#endif
+
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) && \
+ STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE)
+#error "I2S3 RX and TX mode not supported in this driver implementation"
+#endif
+
+#if STM32_I2S_USE_SPI1 && !STM32_HAS_SPI1
+#error "SPI1 not present in the selected device"
+#endif
+
+#if STM32_I2S_USE_SPI2 && !STM32_HAS_SPI2
+#error "SPI2 not present in the selected device"
+#endif
+
+#if STM32_I2S_USE_SPI3 && !STM32_HAS_SPI3
+#error "SPI3 not present in the selected device"
+#endif
+
+#if !STM32_I2S_USE_SPI1 && !STM32_I2S_USE_SPI2 && !STM32_I2S_USE_SPI3
+#error "I2S driver activated but no SPI peripheral assigned"
+#endif
+
+#if STM32_I2S_USE_SPI1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2S_SPI1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI1"
+#endif
+
+#if STM32_I2S_USE_SPI2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2S_SPI2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI2"
+#endif
+
+#if STM32_I2S_USE_SPI3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2S_SPI3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI3"
+#endif
+
+#if STM32_I2S_USE_SPI1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI1"
+#endif
+
+#if STM32_I2S_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI2"
+#endif
+
+#if STM32_I2S_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI3_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI3"
+#endif
+
+/* The following checks are only required when there is a DMA able to
+ reassign streams to different channels.*/
+#if STM32_ADVANCED_DMA
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if STM32_I2S_USE_SPI1 && (!defined(STM32_I2S_SPI1_RX_DMA_STREAM) || \
+ !defined(STM32_I2S_SPI1_TX_DMA_STREAM))
+#error "SPI1 DMA streams not defined"
+#endif
+
+#if STM32_I2S_USE_SPI2 && (!defined(STM32_I2S_SPI2_RX_DMA_STREAM) || \
+ !defined(STM32_I2S_SPI2_TX_DMA_STREAM))
+#error "SPI2 DMA streams not defined"
+#endif
+
+#if STM32_I2S_USE_SPI3 && (!defined(STM32_I2S_SPI3_RX_DMA_STREAM) || \
+ !defined(STM32_I2S_SPI3_TX_DMA_STREAM))
+#error "SPI3 DMA streams not defined"
+#endif
+
+/* Check on the validity of the assigned DMA channels.*/
+#if STM32_I2S_USE_SPI1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI1_RX_DMA_STREAM, STM32_SPI1_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI1 RX"
+#endif
+
+#if STM32_I2S_USE_SPI1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI1_TX_DMA_STREAM, STM32_SPI1_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI1 TX"
+#endif
+
+#if STM32_I2S_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI2 RX"
+#endif
+
+#if STM32_I2S_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI2 TX"
+#endif
+
+#if STM32_I2S_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI3 RX"
+#endif
+
+#if STM32_I2S_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI3 TX"
+#endif
+#endif /* STM32_ADVANCED_DMA */
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the I2S driver structure.
+ */
+#define i2s_lld_driver_fields \
+ /* Pointer to the SPIx registers block.*/ \
+ SPI_TypeDef *spi; \
+ /* Calculated part of the I2SCFGR register.*/ \
+ uint16_t cfg; \
+ /* Receive DMA stream or @p NULL.*/ \
+ const stm32_dma_stream_t *dmarx; \
+ /* Transmit DMA stream or @p NULL.*/ \
+ const stm32_dma_stream_t *dmatx; \
+ /* RX DMA mode bit mask.*/ \
+ uint32_t rxdmamode; \
+ /* TX DMA mode bit mask.*/ \
+ uint32_t txdmamode
+
+/**
+ * @brief Low level fields of the I2S configuration structure.
+ */
+#define i2s_lld_config_fields \
+ /* Configuration of the I2SCFGR register. \
+ NOTE: See the STM32 reference manual, this register is used for \
+ the I2S configuration, the following bits must not be \
+ specified because handled directly by the driver: \
+ - I2SMOD \
+ - I2SE \
+ - I2SCFG \
+ */ \
+ int16_t i2scfgr; \
+ /* Configuration of the I2SPR register. \
+ NOTE: See the STM32 reference manual, this register is used for \
+ the I2S clock setup.*/ \
+ int16_t i2spr
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_I2S_USE_SPI1 && !defined(__DOXYGEN__)
+extern I2SDriver I2SD1;
+#endif
+
+#if STM32_I2S_USE_SPI2 && !defined(__DOXYGEN__)
+extern I2SDriver I2SD2;
+#endif
+
+#if STM32_I2S_USE_SPI3 && !defined(__DOXYGEN__)
+extern I2SDriver I2SD3;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void i2s_lld_init(void);
+ void i2s_lld_start(I2SDriver *i2sp);
+ void i2s_lld_stop(I2SDriver *i2sp);
+ void i2s_lld_start_exchange(I2SDriver *i2sp);
+ void i2s_lld_stop_exchange(I2SDriver *i2sp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_I2S */
+
+#endif /* HAL_I2S_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.c
new file mode 100644
index 0000000..459e6b9
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.c
@@ -0,0 +1,679 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SPIv1/hal_spi_lld.c
+ * @brief STM32 SPI subsystem low level driver source.
+ *
+ * @addtogroup SPI
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_SPI || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define SPI1_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_RX_DMA_STREAM, \
+ STM32_SPI1_RX_DMA_CHN)
+
+#define SPI1_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_TX_DMA_STREAM, \
+ STM32_SPI1_TX_DMA_CHN)
+
+#define SPI2_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_RX_DMA_STREAM, \
+ STM32_SPI2_RX_DMA_CHN)
+
+#define SPI2_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_TX_DMA_STREAM, \
+ STM32_SPI2_TX_DMA_CHN)
+
+#define SPI3_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_RX_DMA_STREAM, \
+ STM32_SPI3_RX_DMA_CHN)
+
+#define SPI3_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_TX_DMA_STREAM, \
+ STM32_SPI3_TX_DMA_CHN)
+
+#define SPI4_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI4_RX_DMA_STREAM, \
+ STM32_SPI4_RX_DMA_CHN)
+
+#define SPI4_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI4_TX_DMA_STREAM, \
+ STM32_SPI4_TX_DMA_CHN)
+
+#define SPI5_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI5_RX_DMA_STREAM, \
+ STM32_SPI5_RX_DMA_CHN)
+
+#define SPI5_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI5_TX_DMA_STREAM, \
+ STM32_SPI5_TX_DMA_CHN)
+
+#define SPI6_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI6_RX_DMA_STREAM, \
+ STM32_SPI6_RX_DMA_CHN)
+
+#define SPI6_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI6_TX_DMA_STREAM, \
+ STM32_SPI6_TX_DMA_CHN)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief SPI1 driver identifier.*/
+#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__)
+SPIDriver SPID1;
+#endif
+
+/** @brief SPI2 driver identifier.*/
+#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__)
+SPIDriver SPID2;
+#endif
+
+/** @brief SPI3 driver identifier.*/
+#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__)
+SPIDriver SPID3;
+#endif
+
+/** @brief SPI4 driver identifier.*/
+#if STM32_SPI_USE_SPI4 || defined(__DOXYGEN__)
+SPIDriver SPID4;
+#endif
+
+/** @brief SPI5 driver identifier.*/
+#if STM32_SPI_USE_SPI5 || defined(__DOXYGEN__)
+SPIDriver SPID5;
+#endif
+
+/** @brief SPI6 driver identifier.*/
+#if STM32_SPI_USE_SPI6 || defined(__DOXYGEN__)
+SPIDriver SPID6;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+static const uint16_t dummytx = 0xFFFFU;
+static uint16_t dummyrx;
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Shared end-of-rx service routine.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(STM32_SPI_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_SPI_DMA_ERROR_HOOK(spip);
+ }
+#else
+ (void)flags;
+#endif
+
+ if (spip->config->circular) {
+ if ((flags & STM32_DMA_ISR_HTIF) != 0U) {
+ /* Half buffer interrupt.*/
+ _spi_isr_half_code(spip);
+ }
+ if ((flags & STM32_DMA_ISR_TCIF) != 0U) {
+ /* End buffer interrupt.*/
+ _spi_isr_full_code(spip);
+ }
+ }
+ else {
+ /* Stopping DMAs.*/
+ dmaStreamDisable(spip->dmatx);
+ dmaStreamDisable(spip->dmarx);
+
+ /* Portable SPI ISR code defined in the high level driver, note, it is
+ a macro.*/
+ _spi_isr_code(spip);
+ }
+}
+
+/**
+ * @brief Shared end-of-tx service routine.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(STM32_SPI_DMA_ERROR_HOOK)
+ (void)spip;
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_SPI_DMA_ERROR_HOOK(spip);
+ }
+#else
+ (void)spip;
+ (void)flags;
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level SPI driver initialization.
+ *
+ * @notapi
+ */
+void spi_lld_init(void) {
+
+#if STM32_SPI_USE_SPI1
+ spiObjectInit(&SPID1);
+ SPID1.spi = SPI1;
+ SPID1.dmarx = NULL;
+ SPID1.dmatx = NULL;
+ SPID1.rxdmamode = STM32_DMA_CR_CHSEL(SPI1_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ SPID1.txdmamode = STM32_DMA_CR_CHSEL(SPI1_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#endif
+
+#if STM32_SPI_USE_SPI2
+ spiObjectInit(&SPID2);
+ SPID2.spi = SPI2;
+ SPID2.dmarx = NULL;
+ SPID2.dmatx = NULL;
+ SPID2.rxdmamode = STM32_DMA_CR_CHSEL(SPI2_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ SPID2.txdmamode = STM32_DMA_CR_CHSEL(SPI2_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#endif
+
+#if STM32_SPI_USE_SPI3
+ spiObjectInit(&SPID3);
+ SPID3.spi = SPI3;
+ SPID3.dmarx = NULL;
+ SPID3.dmatx = NULL;
+ SPID3.rxdmamode = STM32_DMA_CR_CHSEL(SPI3_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ SPID3.txdmamode = STM32_DMA_CR_CHSEL(SPI3_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#endif
+
+#if STM32_SPI_USE_SPI4
+ spiObjectInit(&SPID4);
+ SPID4.spi = SPI4;
+ SPID4.dmarx = NULL;
+ SPID4.dmatx = NULL;
+ SPID4.rxdmamode = STM32_DMA_CR_CHSEL(SPI4_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI4_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ SPID4.txdmamode = STM32_DMA_CR_CHSEL(SPI4_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI4_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#endif
+
+#if STM32_SPI_USE_SPI5
+ spiObjectInit(&SPID5);
+ SPID5.spi = SPI5;
+ SPID5.dmarx = NULL;
+ SPID5.dmatx = NULL;
+ SPID5.rxdmamode = STM32_DMA_CR_CHSEL(SPI5_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI5_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ SPID5.txdmamode = STM32_DMA_CR_CHSEL(SPI5_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI5_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#endif
+
+#if STM32_SPI_USE_SPI6
+ spiObjectInit(&SPID6);
+ SPID6.spi = SPI6;
+ SPID6.dmarx = NULL;
+ SPID6.dmatx = NULL;
+ SPID6.rxdmamode = STM32_DMA_CR_CHSEL(SPI6_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI6_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ SPID6.txdmamode = STM32_DMA_CR_CHSEL(SPI6_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI6_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#endif
+}
+
+/**
+ * @brief Configures and activates the SPI peripheral.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_start(SPIDriver *spip) {
+
+ /* If in stopped state then enables the SPI and DMA clocks.*/
+ if (spip->state == SPI_STOP) {
+#if STM32_SPI_USE_SPI1
+ if (&SPID1 == spip) {
+ spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI1_RX_DMA_STREAM,
+ STM32_SPI_SPI1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream");
+ spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI1_TX_DMA_STREAM,
+ STM32_SPI_SPI1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream");
+ rccEnableSPI1(true);
+ }
+#endif
+#if STM32_SPI_USE_SPI2
+ if (&SPID2 == spip) {
+ spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI2_RX_DMA_STREAM,
+ STM32_SPI_SPI2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream");
+ spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI2_TX_DMA_STREAM,
+ STM32_SPI_SPI2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream");
+ rccEnableSPI2(true);
+ }
+#endif
+#if STM32_SPI_USE_SPI3
+ if (&SPID3 == spip) {
+ spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI3_RX_DMA_STREAM,
+ STM32_SPI_SPI3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream");
+ spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI3_TX_DMA_STREAM,
+ STM32_SPI_SPI3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream");
+ rccEnableSPI3(true);
+ }
+#endif
+#if STM32_SPI_USE_SPI4
+ if (&SPID4 == spip) {
+ spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI4_RX_DMA_STREAM,
+ STM32_SPI_SPI4_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream");
+ spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI4_TX_DMA_STREAM,
+ STM32_SPI_SPI4_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream");
+ rccEnableSPI4(true);
+ }
+#endif
+#if STM32_SPI_USE_SPI5
+ if (&SPID5 == spip) {
+ spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI5_RX_DMA_STREAM,
+ STM32_SPI_SPI5_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream");
+ spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI5_TX_DMA_STREAM,
+ STM32_SPI_SPI5_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream");
+ rccEnableSPI5(true);
+ }
+#endif
+#if STM32_SPI_USE_SPI6
+ if (&SPID6 == spip) {
+ spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI6_RX_DMA_STREAM,
+ STM32_SPI_SPI6_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream");
+ spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI6_TX_DMA_STREAM,
+ STM32_SPI_SPI6_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream");
+ rccEnableSPI6(true);
+ }
+#endif
+
+ /* DMA setup.*/
+ dmaStreamSetPeripheral(spip->dmarx, &spip->spi->DR);
+ dmaStreamSetPeripheral(spip->dmatx, &spip->spi->DR);
+ }
+
+ /* Configuration-specific DMA setup.*/
+ if ((spip->config->cr1 & SPI_CR1_DFF) == 0) {
+ /* Frame width is 8 bits or smaller.*/
+ spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) |
+ STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE;
+ spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) |
+ STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE;
+ }
+ else {
+ /* Frame width is larger than 8 bits.*/
+ spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) |
+ STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
+ spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) |
+ STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
+ }
+
+ if (spip->config->circular) {
+ spip->rxdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE);
+ spip->txdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE);
+ }
+ else {
+ spip->rxdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE);
+ spip->txdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE);
+ }
+
+ /* SPI setup and enable.*/
+ spip->spi->CR1 &= ~SPI_CR1_SPE;
+ spip->spi->CR1 = spip->config->cr1 | SPI_CR1_MSTR | SPI_CR1_SSM |
+ SPI_CR1_SSI;
+ spip->spi->CR2 = spip->config->cr2 | SPI_CR2_SSOE | SPI_CR2_RXDMAEN |
+ SPI_CR2_TXDMAEN;
+ spip->spi->CR1 |= SPI_CR1_SPE;
+}
+
+/**
+ * @brief Deactivates the SPI peripheral.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_stop(SPIDriver *spip) {
+
+ /* If in ready state then disables the SPI clock.*/
+ if (spip->state == SPI_READY) {
+
+ /* SPI disable.*/
+ spip->spi->CR1 &= ~SPI_CR1_SPE;
+ spip->spi->CR1 = 0;
+ spip->spi->CR2 = 0;
+ dmaStreamFreeI(spip->dmarx);
+ dmaStreamFreeI(spip->dmatx);
+ spip->dmarx = NULL;
+ spip->dmatx = NULL;
+
+#if STM32_SPI_USE_SPI1
+ if (&SPID1 == spip)
+ rccDisableSPI1();
+#endif
+#if STM32_SPI_USE_SPI2
+ if (&SPID2 == spip)
+ rccDisableSPI2();
+#endif
+#if STM32_SPI_USE_SPI3
+ if (&SPID3 == spip)
+ rccDisableSPI3();
+#endif
+#if STM32_SPI_USE_SPI4
+ if (&SPID4 == spip)
+ rccDisableSPI4();
+#endif
+#if STM32_SPI_USE_SPI5
+ if (&SPID5 == spip)
+ rccDisableSPI5();
+#endif
+#if STM32_SPI_USE_SPI6
+ if (&SPID6 == spip)
+ rccDisableSPI6();
+#endif
+ }
+}
+
+#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__)
+/**
+ * @brief Asserts the slave select signal and prepares for transfers.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_select(SPIDriver *spip) {
+
+ /* No implementation on STM32.*/
+}
+
+/**
+ * @brief Deasserts the slave select signal.
+ * @details The previously selected peripheral is unselected.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_unselect(SPIDriver *spip) {
+
+ /* No implementation on STM32.*/
+}
+#endif
+
+/**
+ * @brief Ignores data on the SPI bus.
+ * @details This asynchronous function starts the transmission of a series of
+ * idle words on the SPI bus and ignores the received data.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be ignored
+ *
+ * @notapi
+ */
+void spi_lld_ignore(SPIDriver *spip, size_t n) {
+
+ osalDbgAssert(n < 65536, "unsupported DMA transfer size");
+
+ dmaStreamSetMemory0(spip->dmarx, &dummyrx);
+ dmaStreamSetTransactionSize(spip->dmarx, n);
+ dmaStreamSetMode(spip->dmarx, spip->rxdmamode);
+
+ dmaStreamSetMemory0(spip->dmatx, &dummytx);
+ dmaStreamSetTransactionSize(spip->dmatx, n);
+ dmaStreamSetMode(spip->dmatx, spip->txdmamode);
+
+ dmaStreamEnable(spip->dmarx);
+ dmaStreamEnable(spip->dmatx);
+}
+
+/**
+ * @brief Exchanges data on the SPI bus.
+ * @details This asynchronous function starts a simultaneous transmit/receive
+ * operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be exchanged
+ * @param[in] txbuf the pointer to the transmit buffer
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void spi_lld_exchange(SPIDriver *spip, size_t n,
+ const void *txbuf, void *rxbuf) {
+
+ osalDbgAssert(n < 65536, "unsupported DMA transfer size");
+
+ dmaStreamSetMemory0(spip->dmarx, rxbuf);
+ dmaStreamSetTransactionSize(spip->dmarx, n);
+ dmaStreamSetMode(spip->dmarx, spip->rxdmamode| STM32_DMA_CR_MINC);
+
+ dmaStreamSetMemory0(spip->dmatx, txbuf);
+ dmaStreamSetTransactionSize(spip->dmatx, n);
+ dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC);
+
+ dmaStreamEnable(spip->dmarx);
+ dmaStreamEnable(spip->dmatx);
+}
+
+/**
+ * @brief Sends data over the SPI bus.
+ * @details This asynchronous function starts a transmit operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @notapi
+ */
+void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
+
+ osalDbgAssert(n < 65536, "unsupported DMA transfer size");
+
+ dmaStreamSetMemory0(spip->dmarx, &dummyrx);
+ dmaStreamSetTransactionSize(spip->dmarx, n);
+ dmaStreamSetMode(spip->dmarx, spip->rxdmamode);
+
+ dmaStreamSetMemory0(spip->dmatx, txbuf);
+ dmaStreamSetTransactionSize(spip->dmatx, n);
+ dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC);
+
+ dmaStreamEnable(spip->dmarx);
+ dmaStreamEnable(spip->dmatx);
+}
+
+/**
+ * @brief Receives data from the SPI bus.
+ * @details This asynchronous function starts a receive operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to receive
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
+
+ osalDbgAssert(n < 65536, "unsupported DMA transfer size");
+
+ dmaStreamSetMemory0(spip->dmarx, rxbuf);
+ dmaStreamSetTransactionSize(spip->dmarx, n);
+ dmaStreamSetMode(spip->dmarx, spip->rxdmamode | STM32_DMA_CR_MINC);
+
+ dmaStreamSetMemory0(spip->dmatx, &dummytx);
+ dmaStreamSetTransactionSize(spip->dmatx, n);
+ dmaStreamSetMode(spip->dmatx, spip->txdmamode);
+
+ dmaStreamEnable(spip->dmarx);
+ dmaStreamEnable(spip->dmatx);
+}
+
+#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Aborts the ongoing SPI operation, if any.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_abort(SPIDriver *spip) {
+
+ /* Stopping DMAs.*/
+ dmaStreamDisable(spip->dmatx);
+ dmaStreamDisable(spip->dmarx);
+}
+#endif /* SPI_SUPPORTS_CIRCULAR == TRUE */
+
+/**
+ * @brief Exchanges one frame using a polled wait.
+ * @details This synchronous function exchanges one frame using a polled
+ * synchronization method. This function is useful when exchanging
+ * small amount of data on high speed channels, usually in this
+ * situation is much more efficient just wait for completion using
+ * polling than suspending the thread waiting for an interrupt.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] frame the data frame to send over the SPI bus
+ * @return The received data frame from the SPI bus.
+ */
+uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) {
+
+ spip->spi->DR = frame;
+ while ((spip->spi->SR & SPI_SR_RXNE) == 0)
+ ;
+ return spip->spi->DR;
+}
+
+#endif /* HAL_USE_SPI */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.h
new file mode 100644
index 0000000..09a6eec
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv1/hal_spi_lld.h
@@ -0,0 +1,495 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SPIv1/hal_spi_lld.h
+ * @brief STM32 SPI subsystem low level driver header.
+ *
+ * @addtogroup SPI
+ * @{
+ */
+
+#ifndef HAL_SPI_LLD_H
+#define HAL_SPI_LLD_H
+
+#if HAL_USE_SPI || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Circular mode support flag.
+ */
+#define SPI_SUPPORTS_CIRCULAR TRUE
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief SPI1 driver enable switch.
+ * @details If set to @p TRUE the support for SPI1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SPI_USE_SPI1) || defined(__DOXYGEN__)
+#define STM32_SPI_USE_SPI1 FALSE
+#endif
+
+/**
+ * @brief SPI2 driver enable switch.
+ * @details If set to @p TRUE the support for SPI2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SPI_USE_SPI2) || defined(__DOXYGEN__)
+#define STM32_SPI_USE_SPI2 FALSE
+#endif
+
+/**
+ * @brief SPI3 driver enable switch.
+ * @details If set to @p TRUE the support for SPI3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SPI_USE_SPI3) || defined(__DOXYGEN__)
+#define STM32_SPI_USE_SPI3 FALSE
+#endif
+
+/**
+ * @brief SPI4 driver enable switch.
+ * @details If set to @p TRUE the support for SPI4 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SPI_USE_SPI4) || defined(__DOXYGEN__)
+#define STM32_SPI_USE_SPI4 FALSE
+#endif
+
+/**
+ * @brief SPI5 driver enable switch.
+ * @details If set to @p TRUE the support for SPI5 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SPI_USE_SPI5) || defined(__DOXYGEN__)
+#define STM32_SPI_USE_SPI5 FALSE
+#endif
+
+/**
+ * @brief SPI6 driver enable switch.
+ * @details If set to @p TRUE the support for SPI6 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SPI_USE_SPI6) || defined(__DOXYGEN__)
+#define STM32_SPI_USE_SPI6 FALSE
+#endif
+
+/**
+ * @brief SPI1 interrupt priority level setting.
+ */
+#if !defined(STM32_SPI_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI1_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI2 interrupt priority level setting.
+ */
+#if !defined(STM32_SPI_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI2_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI3 interrupt priority level setting.
+ */
+#if !defined(STM32_SPI_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI3_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI4 interrupt priority level setting.
+ */
+#if !defined(STM32_SPI_SPI4_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI4_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI5 interrupt priority level setting.
+ */
+#if !defined(STM32_SPI_SPI5_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI5_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI6 interrupt priority level setting.
+ */
+#if !defined(STM32_SPI_SPI6_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI6_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI1 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_SPI_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI1_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI2 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_SPI_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI2_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI3 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_SPI_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI3_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI4 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_SPI_SPI4_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI4_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI5 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_SPI_SPI5_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI5_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI6 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_SPI_SPI6_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI6_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI DMA error hook.
+ */
+#if !defined(STM32_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if STM32_SPI_USE_SPI1 && !STM32_HAS_SPI1
+#error "SPI1 not present in the selected device"
+#endif
+
+#if STM32_SPI_USE_SPI2 && !STM32_HAS_SPI2
+#error "SPI2 not present in the selected device"
+#endif
+
+#if STM32_SPI_USE_SPI3 && !STM32_HAS_SPI3
+#error "SPI3 not present in the selected device"
+#endif
+
+#if STM32_SPI_USE_SPI4 && !STM32_HAS_SPI4
+#error "SPI4 not present in the selected device"
+#endif
+
+#if STM32_SPI_USE_SPI5 && !STM32_HAS_SPI5
+#error "SPI5 not present in the selected device"
+#endif
+
+#if STM32_SPI_USE_SPI6 && !STM32_HAS_SPI6
+#error "SPI6 not present in the selected device"
+#endif
+
+#if !STM32_SPI_USE_SPI1 && !STM32_SPI_USE_SPI2 && !STM32_SPI_USE_SPI3 && \
+ !STM32_SPI_USE_SPI4 && !STM32_SPI_USE_SPI5 && !STM32_SPI_USE_SPI6
+#error "SPI driver activated but no SPI peripheral assigned"
+#endif
+
+#if STM32_SPI_USE_SPI1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI1"
+#endif
+
+#if STM32_SPI_USE_SPI2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI2"
+#endif
+
+#if STM32_SPI_USE_SPI3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI3"
+#endif
+
+#if STM32_SPI_USE_SPI4 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI4_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI4"
+#endif
+
+#if STM32_SPI_USE_SPI5 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI5_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI5"
+#endif
+
+#if STM32_SPI_USE_SPI6 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI6_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI6"
+#endif
+
+#if STM32_SPI_USE_SPI1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI1"
+#endif
+
+#if STM32_SPI_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI2"
+#endif
+
+#if STM32_SPI_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI3_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI3"
+#endif
+
+#if STM32_SPI_USE_SPI4 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI4_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI4"
+#endif
+
+#if STM32_SPI_USE_SPI5 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI5_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI5"
+#endif
+
+#if STM32_SPI_USE_SPI6 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI6_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI6"
+#endif
+
+/* The following checks are only required when there is a DMA able to
+ reassign streams to different channels.*/
+#if STM32_ADVANCED_DMA
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if STM32_SPI_USE_SPI1 && (!defined(STM32_SPI_SPI1_RX_DMA_STREAM) || \
+ !defined(STM32_SPI_SPI1_TX_DMA_STREAM))
+#error "SPI1 DMA streams not defined"
+#endif
+
+#if STM32_SPI_USE_SPI2 && (!defined(STM32_SPI_SPI2_RX_DMA_STREAM) || \
+ !defined(STM32_SPI_SPI2_TX_DMA_STREAM))
+#error "SPI2 DMA streams not defined"
+#endif
+
+#if STM32_SPI_USE_SPI3 && (!defined(STM32_SPI_SPI3_RX_DMA_STREAM) || \
+ !defined(STM32_SPI_SPI3_TX_DMA_STREAM))
+#error "SPI3 DMA streams not defined"
+#endif
+
+#if STM32_SPI_USE_SPI4 && (!defined(STM32_SPI_SPI4_RX_DMA_STREAM) || \
+ !defined(STM32_SPI_SPI4_TX_DMA_STREAM))
+#error "SPI4 DMA streams not defined"
+#endif
+
+#if STM32_SPI_USE_SPI5 && (!defined(STM32_SPI_SPI5_RX_DMA_STREAM) || \
+ !defined(STM32_SPI_SPI5_TX_DMA_STREAM))
+#error "SPI5 DMA streams not defined"
+#endif
+
+#if STM32_SPI_USE_SPI6 && (!defined(STM32_SPI_SPI6_RX_DMA_STREAM) || \
+ !defined(STM32_SPI_SPI6_TX_DMA_STREAM))
+#error "SPI6 DMA streams not defined"
+#endif
+
+/* Check on the validity of the assigned DMA channels.*/
+#if STM32_SPI_USE_SPI1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_RX_DMA_STREAM, STM32_SPI1_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI1 RX"
+#endif
+
+#if STM32_SPI_USE_SPI1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_TX_DMA_STREAM, STM32_SPI1_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI1 TX"
+#endif
+
+#if STM32_SPI_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI2 RX"
+#endif
+
+#if STM32_SPI_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI2 TX"
+#endif
+
+#if STM32_SPI_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI3 RX"
+#endif
+
+#if STM32_SPI_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI3 TX"
+#endif
+
+#if STM32_SPI_USE_SPI4 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI4_RX_DMA_STREAM, STM32_SPI4_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI4 RX"
+#endif
+
+#if STM32_SPI_USE_SPI4 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI4_TX_DMA_STREAM, STM32_SPI4_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI4 TX"
+#endif
+
+#if STM32_SPI_USE_SPI5 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI5_RX_DMA_STREAM, STM32_SPI5_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI5 RX"
+#endif
+
+#if STM32_SPI_USE_SPI5 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI5_TX_DMA_STREAM, STM32_SPI5_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI5 TX"
+#endif
+
+#if STM32_SPI_USE_SPI6 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI6_RX_DMA_STREAM, STM32_SPI6_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI6 RX"
+#endif
+
+#if STM32_SPI_USE_SPI6 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI6_TX_DMA_STREAM, STM32_SPI6_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI6 TX"
+#endif
+#endif /* STM32_ADVANCED_DMA */
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+#if SPI_SELECT_MODE == SPI_SELECT_MODE_LLD
+#error "SPI_SELECT_MODE_LLD not supported by this driver"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the SPI driver structure.
+ */
+#define spi_lld_driver_fields \
+ /* Pointer to the SPIx registers block.*/ \
+ SPI_TypeDef *spi; \
+ /* Receive DMA stream.*/ \
+ const stm32_dma_stream_t *dmarx; \
+ /* Transmit DMA stream.*/ \
+ const stm32_dma_stream_t *dmatx; \
+ /* RX DMA mode bit mask.*/ \
+ uint32_t rxdmamode; \
+ /* TX DMA mode bit mask.*/ \
+ uint32_t txdmamode
+
+/**
+ * @brief Low level fields of the SPI configuration structure.
+ */
+#define spi_lld_config_fields \
+ /* SPI CR1 register initialization data.*/ \
+ uint16_t cr1; \
+ /* SPI CR2 register initialization data.*/ \
+ uint16_t cr2
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_SPI_USE_SPI1 && !defined(__DOXYGEN__)
+extern SPIDriver SPID1;
+#endif
+
+#if STM32_SPI_USE_SPI2 && !defined(__DOXYGEN__)
+extern SPIDriver SPID2;
+#endif
+
+#if STM32_SPI_USE_SPI3 && !defined(__DOXYGEN__)
+extern SPIDriver SPID3;
+#endif
+
+#if STM32_SPI_USE_SPI4 && !defined(__DOXYGEN__)
+extern SPIDriver SPID4;
+#endif
+
+#if STM32_SPI_USE_SPI5 && !defined(__DOXYGEN__)
+extern SPIDriver SPID5;
+#endif
+
+#if STM32_SPI_USE_SPI6 && !defined(__DOXYGEN__)
+extern SPIDriver SPID6;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void spi_lld_init(void);
+ void spi_lld_start(SPIDriver *spip);
+ void spi_lld_stop(SPIDriver *spip);
+#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__)
+ void spi_lld_select(SPIDriver *spip);
+ void spi_lld_unselect(SPIDriver *spip);
+#endif
+ void spi_lld_ignore(SPIDriver *spip, size_t n);
+ void spi_lld_exchange(SPIDriver *spip, size_t n,
+ const void *txbuf, void *rxbuf);
+ void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
+ void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
+#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__)
+ void spi_lld_abort(SPIDriver *spip);
+#endif
+ uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SPI */
+
+#endif /* HAL_SPI_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv2/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv2/driver.mk
new file mode 100644
index 0000000..2e1bae4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv2/driver.mk
@@ -0,0 +1,13 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_I2S TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.c
+endif
+ifneq ($(findstring HAL_USE_SPI TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.c
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.c
new file mode 100644
index 0000000..aa437da
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.c
@@ -0,0 +1,572 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SPIv2/hal_i2s_lld.c
+ * @brief STM32 I2S subsystem low level driver source.
+ *
+ * @addtogroup I2S
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_I2S || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define I2S1_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2S_SPI1_RX_DMA_STREAM, \
+ STM32_SPI1_RX_DMA_CHN)
+
+#define I2S1_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2S_SPI1_TX_DMA_STREAM, \
+ STM32_SPI1_TX_DMA_CHN)
+
+#define I2S2_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2S_SPI2_RX_DMA_STREAM, \
+ STM32_SPI2_RX_DMA_CHN)
+
+#define I2S2_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2S_SPI2_TX_DMA_STREAM, \
+ STM32_SPI2_TX_DMA_CHN)
+
+#define I2S3_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2S_SPI3_RX_DMA_STREAM, \
+ STM32_SPI3_RX_DMA_CHN)
+
+#define I2S3_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_I2S_SPI3_TX_DMA_STREAM, \
+ STM32_SPI3_TX_DMA_CHN)
+
+/*
+ * Static I2S settings for I2S1.
+ */
+#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI1_MODE)
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE)
+#define STM32_I2S1_CFGR_CFG 0
+#endif
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE)
+#define STM32_I2S1_CFGR_CFG SPI_I2SCFGR_I2SCFG_0
+#endif
+#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI1_MODE) */
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE)
+#define STM32_I2S1_CFGR_CFG SPI_I2SCFGR_I2SCFG_1
+#endif
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE)
+#define STM32_I2S1_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \
+ SPI_I2SCFGR_I2SCFG_0)
+#endif
+#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI1_MODE) */
+
+/*
+ * Static I2S settings for I2S2.
+ */
+#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE)
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE)
+#define STM32_I2S2_CFGR_CFG 0
+#endif
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE)
+#define STM32_I2S2_CFGR_CFG SPI_I2SCFGR_I2SCFG_0
+#endif
+#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE) */
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE)
+#define STM32_I2S2_CFGR_CFG SPI_I2SCFGR_I2SCFG_1
+#endif
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE)
+#define STM32_I2S2_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \
+ SPI_I2SCFGR_I2SCFG_0)
+#endif
+#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI2_MODE) */
+
+/*
+ * Static I2S settings for I2S3.
+ */
+#if !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE)
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE)
+#define STM32_I2S3_CFGR_CFG 0
+#endif
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE)
+#define STM32_I2S3_CFGR_CFG SPI_I2SCFGR_I2SCFG_0
+#endif
+#else /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE) */
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE)
+#define STM32_I2S3_CFGR_CFG SPI_I2SCFGR_I2SCFG_1
+#endif
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE)
+#define STM32_I2S3_CFGR_CFG (SPI_I2SCFGR_I2SCFG_1 | \
+ SPI_I2SCFGR_I2SCFG_0)
+#endif
+#endif /* !STM32_I2S_IS_MASTER(STM32_I2S_SPI3_MODE) */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief I2S1 driver identifier.*/
+#if STM32_I2S_USE_SPI1 || defined(__DOXYGEN__)
+I2SDriver I2SD1;
+#endif
+
+/** @brief I2S2 driver identifier.*/
+#if STM32_I2S_USE_SPI2 || defined(__DOXYGEN__)
+I2SDriver I2SD2;
+#endif
+
+/** @brief I2S3 driver identifier.*/
+#if STM32_I2S_USE_SPI3 || defined(__DOXYGEN__)
+I2SDriver I2SD3;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) || \
+ STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) || \
+ STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__)
+/**
+ * @brief Shared end-of-rx service routine.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void i2s_lld_serve_rx_interrupt(I2SDriver *i2sp, uint32_t flags) {
+
+ (void)i2sp;
+
+ /* DMA errors handling.*/
+#if defined(STM32_I2S_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_I2S_DMA_ERROR_HOOK(i2sp);
+ }
+#endif
+
+ /* Callbacks handling, note it is portable code defined in the high
+ level driver.*/
+ if ((flags & STM32_DMA_ISR_TCIF) != 0) {
+ /* Transfer complete processing.*/
+ _i2s_isr_full_code(i2sp);
+ }
+ else if ((flags & STM32_DMA_ISR_HTIF) != 0) {
+ /* Half transfer processing.*/
+ _i2s_isr_half_code(i2sp);
+ }
+}
+#endif
+
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE) || \
+ STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE) || \
+ STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__)
+/**
+ * @brief Shared end-of-tx service routine.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void i2s_lld_serve_tx_interrupt(I2SDriver *i2sp, uint32_t flags) {
+
+ (void)i2sp;
+
+ /* DMA errors handling.*/
+#if defined(STM32_I2S_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_I2S_DMA_ERROR_HOOK(i2sp);
+ }
+#endif
+
+ /* Callbacks handling, note it is portable code defined in the high
+ level driver.*/
+ if ((flags & STM32_DMA_ISR_TCIF) != 0) {
+ /* Transfer complete processing.*/
+ _i2s_isr_full_code(i2sp);
+ }
+ else if ((flags & STM32_DMA_ISR_HTIF) != 0) {
+ /* Half transfer processing.*/
+ _i2s_isr_half_code(i2sp);
+ }
+}
+#endif
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level I2S driver initialization.
+ *
+ * @notapi
+ */
+void i2s_lld_init(void) {
+
+#if STM32_I2S_USE_SPI1
+ i2sObjectInit(&I2SD1);
+ I2SD1.spi = SPI1;
+ I2SD1.cfg = STM32_I2S1_CFGR_CFG;
+ I2SD1.dmarx = NULL;
+ I2SD1.dmatx = NULL;
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE)
+ I2SD1.rxdmamode = STM32_DMA_CR_CHSEL(I2S1_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2S_SPI1_DMA_PRIORITY) |
+ STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MSIZE_HWORD |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_CIRC |
+ STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#else
+ I2SD1.rxdmamode = 0;
+#endif
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE)
+ I2SD1.txdmamode = STM32_DMA_CR_CHSEL(I2S1_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2S_SPI1_DMA_PRIORITY) |
+ STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MSIZE_HWORD |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_CIRC |
+ STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#else
+ I2SD1.txdmamode = 0;
+#endif
+#endif
+
+#if STM32_I2S_USE_SPI2
+ i2sObjectInit(&I2SD2);
+ I2SD2.spi = SPI2;
+ I2SD2.cfg = STM32_I2S2_CFGR_CFG;
+ I2SD2.dmarx = NULL;
+ I2SD2.dmatx = NULL;
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE)
+ I2SD2.rxdmamode = STM32_DMA_CR_CHSEL(I2S2_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2S_SPI2_DMA_PRIORITY) |
+ STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MSIZE_HWORD |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_CIRC |
+ STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#else
+ I2SD2.rxdmamode = 0;
+#endif
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE)
+ I2SD2.txdmamode = STM32_DMA_CR_CHSEL(I2S2_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2S_SPI2_DMA_PRIORITY) |
+ STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MSIZE_HWORD |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_CIRC |
+ STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#else
+ I2SD2.txdmamode = 0;
+#endif
+#endif
+
+#if STM32_I2S_USE_SPI3
+ i2sObjectInit(&I2SD3);
+ I2SD3.spi = SPI3;
+ I2SD3.cfg = STM32_I2S3_CFGR_CFG;
+ I2SD3.dmarx = NULL;
+ I2SD3.dmatx = NULL;
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE)
+ I2SD3.rxdmamode = STM32_DMA_CR_CHSEL(I2S3_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2S_SPI3_DMA_PRIORITY) |
+ STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MSIZE_HWORD |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_CIRC |
+ STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#else
+ I2SD3.rxdmamode = 0;
+#endif
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE)
+ I2SD3.txdmamode = STM32_DMA_CR_CHSEL(I2S3_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_I2S_SPI3_DMA_PRIORITY) |
+ STM32_DMA_CR_PSIZE_HWORD |
+ STM32_DMA_CR_MSIZE_HWORD |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_MINC |
+ STM32_DMA_CR_CIRC |
+ STM32_DMA_CR_HTIE |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#else
+ I2SD3.txdmamode = 0;
+#endif
+#endif
+}
+
+/**
+ * @brief Configures and activates the I2S peripheral.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @notapi
+ */
+void i2s_lld_start(I2SDriver *i2sp) {
+
+ /* If in stopped state then enables the SPI and DMA clocks.*/
+ if (i2sp->state == I2S_STOP) {
+
+#if STM32_I2S_USE_SPI1
+ if (&I2SD1 == i2sp) {
+
+ /* Enabling I2S unit clock.*/
+ rccEnableSPI1(true);
+
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE)
+ i2sp->dmarx = dmaStreamAllocI(STM32_I2S_SPI1_RX_DMA_STREAM,
+ STM32_I2S_SPI1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt,
+ (void *)i2sp);
+ osalDbgAssert(i2sp->dmarx != NULL, "unable to allocate stream");
+
+ /* CRs settings are done here because those never changes until
+ the driver is stopped.*/
+ i2sp->spi->CR1 = 0;
+ i2sp->spi->CR2 = SPI_CR2_RXDMAEN;
+#endif
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE)
+ i2sp->dmatx = dmaStreamAllocI(STM32_I2S_SPI1_TX_DMA_STREAM,
+ STM32_I2S_SPI1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt,
+ (void *)i2sp);
+ osalDbgAssert(i2sp->dmatx != NULL, "unable to allocate stream");
+
+ /* CRs settings are done here because those never changes until
+ the driver is stopped.*/
+ i2sp->spi->CR1 = 0;
+ i2sp->spi->CR2 = SPI_CR2_TXDMAEN;
+#endif
+ }
+#endif
+
+#if STM32_I2S_USE_SPI2
+ if (&I2SD2 == i2sp) {
+
+ /* Enabling I2S unit clock.*/
+ rccEnableSPI2(true);
+
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE)
+ i2sp->dmarx = dmaStreamAllocI(STM32_I2S_SPI2_RX_DMA_STREAM,
+ STM32_I2S_SPI2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt,
+ (void *)i2sp);
+ osalDbgAssert(i2sp->dmarx != NULL, "unable to allocate stream");
+
+ /* CRs settings are done here because those never changes until
+ the driver is stopped.*/
+ i2sp->spi->CR1 = 0;
+ i2sp->spi->CR2 = SPI_CR2_RXDMAEN;
+#endif
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE)
+ i2sp->dmatx = dmaStreamAllocI(STM32_I2S_SPI2_TX_DMA_STREAM,
+ STM32_I2S_SPI2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt,
+ (void *)i2sp);
+ osalDbgAssert(i2sp->dmatx != NULL, "unable to allocate stream");
+
+ /* CRs settings are done here because those never changes until
+ the driver is stopped.*/
+ i2sp->spi->CR1 = 0;
+ i2sp->spi->CR2 = SPI_CR2_TXDMAEN;
+#endif
+ }
+#endif
+
+#if STM32_I2S_USE_SPI3
+ if (&I2SD3 == i2sp) {
+
+ /* Enabling I2S unit clock.*/
+ rccEnableSPI3(true);
+
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE)
+ i2sp->dmarx = dmaStreamAllocI(STM32_I2S_SPI3_RX_DMA_STREAM,
+ STM32_I2S_SPI3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2s_lld_serve_rx_interrupt,
+ (void *)i2sp);
+ osalDbgAssert(i2sp->dmarx != NULL, "unable to allocate stream");
+
+ /* CRs settings are done here because those never changes until
+ the driver is stopped.*/
+ i2sp->spi->CR1 = 0;
+ i2sp->spi->CR2 = SPI_CR2_RXDMAEN;
+#endif
+#if STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE)
+ i2sp->dmatx = dmaStreamAllocI(STM32_I2S_SPI3_TX_DMA_STREAM,
+ STM32_I2S_SPI3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)i2s_lld_serve_tx_interrupt,
+ (void *)i2sp);
+ osalDbgAssert(i2sp->dmatx != NULL, "unable to allocate stream");
+
+ /* CRs settings are done here because those never changes until
+ the driver is stopped.*/
+ i2sp->spi->CR1 = 0;
+ i2sp->spi->CR2 = SPI_CR2_TXDMAEN;
+#endif
+ }
+#endif
+ }
+
+ /* I2S (re)configuration.*/
+ i2sp->spi->I2SPR = i2sp->config->i2spr;
+ i2sp->spi->I2SCFGR = i2sp->config->i2scfgr | i2sp->cfg | SPI_I2SCFGR_I2SMOD;
+}
+
+/**
+ * @brief Deactivates the I2S peripheral.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @notapi
+ */
+void i2s_lld_stop(I2SDriver *i2sp) {
+
+ /* If in ready state then disables the SPI clock.*/
+ if (i2sp->state == I2S_READY) {
+
+ /* SPI disable.*/
+ i2sp->spi->CR2 = 0;
+ if (NULL != i2sp->dmarx) {
+ dmaStreamFreeI(i2sp->dmarx);
+ i2sp->dmarx = NULL;
+ }
+ if (NULL != i2sp->dmatx) {
+ dmaStreamFreeI(i2sp->dmatx);
+ i2sp->dmatx = NULL;
+ }
+
+#if STM32_I2S_USE_SPI1
+ if (&I2SD1 == i2sp)
+ rccDisableSPI1();
+#endif
+
+#if STM32_I2S_USE_SPI2
+ if (&I2SD2 == i2sp)
+ rccDisableSPI2();
+#endif
+
+#if STM32_I2S_USE_SPI3
+ if (&I2SD3 == i2sp)
+ rccDisableSPI3();
+#endif
+ }
+}
+
+/**
+ * @brief Starts a I2S data exchange.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @notapi
+ */
+void i2s_lld_start_exchange(I2SDriver *i2sp) {
+ size_t size = i2sp->config->size;
+
+ /* In 32 bit modes the DMA has to perform double operations because fetches
+ are always performed using 16 bit accesses.
+ DATLEN CHLEN SIZE
+ 00 (16) 0 (16) 16
+ 00 (16) 1 (32) 16
+ 01 (24) X 32
+ 10 (32) X 32
+ 11 (NA) X NA
+ */
+ if ((i2sp->config->i2scfgr & SPI_I2SCFGR_DATLEN) != 0)
+ size *= 2;
+
+ /* RX DMA setup.*/
+ if (NULL != i2sp->dmarx) {
+ dmaStreamSetMode(i2sp->dmarx, i2sp->rxdmamode);
+ dmaStreamSetPeripheral(i2sp->dmarx, &i2sp->spi->DR);
+ dmaStreamSetMemory0(i2sp->dmarx, i2sp->config->rx_buffer);
+ dmaStreamSetTransactionSize(i2sp->dmarx, size);
+ dmaStreamEnable(i2sp->dmarx);
+ }
+
+ /* TX DMA setup.*/
+ if (NULL != i2sp->dmatx) {
+ dmaStreamSetMode(i2sp->dmatx, i2sp->txdmamode);
+ dmaStreamSetPeripheral(i2sp->dmatx, &i2sp->spi->DR);
+ dmaStreamSetMemory0(i2sp->dmatx, i2sp->config->tx_buffer);
+ dmaStreamSetTransactionSize(i2sp->dmatx, size);
+ dmaStreamEnable(i2sp->dmatx);
+ }
+
+ /* Starting transfer.*/
+ i2sp->spi->I2SCFGR |= SPI_I2SCFGR_I2SE;
+}
+
+/**
+ * @brief Stops the ongoing data exchange.
+ * @details The ongoing data exchange, if any, is stopped, if the driver
+ * was not active the function does nothing.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @notapi
+ */
+void i2s_lld_stop_exchange(I2SDriver *i2sp) {
+
+ /* Stop TX DMA, if enabled.*/
+ if (NULL != i2sp->dmatx) {
+ dmaStreamDisable(i2sp->dmatx);
+
+ /* From the RM: To switch off the I2S, by clearing I2SE, it is mandatory
+ to wait for TXE = 1 and BSY = 0.*/
+ while ((i2sp->spi->SR & (SPI_SR_TXE | SPI_SR_BSY)) != SPI_SR_TXE)
+ ;
+ }
+
+ /* Stop SPI/I2S peripheral.*/
+ i2sp->spi->I2SCFGR &= ~SPI_I2SCFGR_I2SE;
+
+ /* Stop RX DMA, if enabled.*/
+ if (NULL != i2sp->dmarx)
+ dmaStreamDisable(i2sp->dmarx);
+}
+
+#endif /* HAL_USE_I2S */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.h
new file mode 100644
index 0000000..acf92e1
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.h
@@ -0,0 +1,371 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SPIv2/hal_i2s_lld.h
+ * @brief STM32 I2S subsystem low level driver header.
+ *
+ * @addtogroup I2S
+ * @{
+ */
+
+#ifndef HAL_I2S_LLD_H
+#define HAL_I2S_LLD_H
+
+#if HAL_USE_I2S || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Static I2S modes
+ * @{
+ */
+#define STM32_I2S_MODE_SLAVE 0
+#define STM32_I2S_MODE_MASTER 1
+#define STM32_I2S_MODE_RX 2
+#define STM32_I2S_MODE_TX 4
+#define STM32_I2S_MODE_RXTX (STM32_I2S_MODE_RX | \
+ STM32_I2S_MODE_TX)
+/** @} */
+
+/**
+ * @name Mode checks
+ * @{
+ */
+#define STM32_I2S_IS_MASTER(mode) ((mode) & STM32_I2S_MODE_MASTER)
+#define STM32_I2S_RX_ENABLED(mode) ((mode) & STM32_I2S_MODE_RX)
+#define STM32_I2S_TX_ENABLED(mode) ((mode) & STM32_I2S_MODE_TX)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief I2S1 driver enable switch.
+ * @details If set to @p TRUE the support for I2S1 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_I2S_USE_SPI1) || defined(__DOXYGEN__)
+#define STM32_I2S_USE_SPI1 FALSE
+#endif
+
+/**
+ * @brief I2S2 driver enable switch.
+ * @details If set to @p TRUE the support for I2S2 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_I2S_USE_SPI2) || defined(__DOXYGEN__)
+#define STM32_I2S_USE_SPI2 FALSE
+#endif
+
+/**
+ * @brief I2S3 driver enable switch.
+ * @details If set to @p TRUE the support for I2S3 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_I2S_USE_SPI3) || defined(__DOXYGEN__)
+#define STM32_I2S_USE_SPI3 FALSE
+#endif
+
+/**
+ * @brief I2S1 mode.
+ */
+#if !defined(STM32_I2S_SPI1_MODE) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI1_MODE (STM32_I2S_MODE_MASTER | \
+ STM32_I2S_MODE_RX)
+#endif
+
+/**
+ * @brief I2S2 mode.
+ */
+#if !defined(STM32_I2S_SPI2_MODE) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI2_MODE (STM32_I2S_MODE_MASTER | \
+ STM32_I2S_MODE_RX)
+#endif
+
+/**
+ * @brief I2S3 mode.
+ */
+#if !defined(STM32_I2S_SPI3_MODE) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI3_MODE (STM32_I2S_MODE_MASTER | \
+ STM32_I2S_MODE_RX)
+#endif
+
+/**
+ * @brief I2S1 interrupt priority level setting.
+ */
+#if !defined(STM32_I2S_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI1_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief I2S2 interrupt priority level setting.
+ */
+#if !defined(STM32_I2S_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI2_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief I2S3 interrupt priority level setting.
+ */
+#if !defined(STM32_I2S_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI3_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief I2S1 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_I2S_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI1_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2S2 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_I2S_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI2_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2S3 DMA priority (0..3|lowest..highest).
+ */
+#if !defined(STM32_I2S_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_I2S_SPI3_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief I2S DMA error hook.
+ */
+#if !defined(STM32_I2S_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure")
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if STM32_I2S_USE_SPI1 && !STM32_SPI1_SUPPORTS_I2S
+#error "SPI1 does not support I2S mode"
+#endif
+
+#if STM32_I2S_USE_SPI2 && !STM32_SPI2_SUPPORTS_I2S
+#error "SPI2 does not support I2S mode"
+#endif
+
+#if STM32_I2S_USE_SPI3 && !STM32_SPI3_SUPPORTS_I2S
+#error "SPI3 does not support I2S mode"
+#endif
+
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI1_MODE) && \
+ STM32_I2S_TX_ENABLED(STM32_I2S_SPI1_MODE)
+#error "I2S1 RX and TX mode not supported in this driver implementation"
+#endif
+
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI2_MODE) && \
+ STM32_I2S_TX_ENABLED(STM32_I2S_SPI2_MODE)
+#error "I2S2 RX and TX mode not supported in this driver implementation"
+#endif
+
+#if STM32_I2S_RX_ENABLED(STM32_I2S_SPI3_MODE) && \
+ STM32_I2S_TX_ENABLED(STM32_I2S_SPI3_MODE)
+#error "I2S3 RX and TX mode not supported in this driver implementation"
+#endif
+
+#if STM32_I2S_USE_SPI1 && !STM32_HAS_SPI1
+#error "SPI1 not present in the selected device"
+#endif
+
+#if STM32_I2S_USE_SPI2 && !STM32_HAS_SPI2
+#error "SPI2 not present in the selected device"
+#endif
+
+#if STM32_I2S_USE_SPI3 && !STM32_HAS_SPI3
+#error "SPI3 not present in the selected device"
+#endif
+
+#if !STM32_I2S_USE_SPI1 && !STM32_I2S_USE_SPI2 && !STM32_I2S_USE_SPI3
+#error "I2S driver activated but no SPI peripheral assigned"
+#endif
+
+#if STM32_I2S_USE_SPI1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2S_SPI1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI1"
+#endif
+
+#if STM32_I2S_USE_SPI2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2S_SPI2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI2"
+#endif
+
+#if STM32_I2S_USE_SPI3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2S_SPI3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI3"
+#endif
+
+#if STM32_I2S_USE_SPI1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI1"
+#endif
+
+#if STM32_I2S_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI2"
+#endif
+
+#if STM32_I2S_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_I2S_SPI3_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI3"
+#endif
+
+/* The following checks are only required when there is a DMA able to
+ reassign streams to different channels.*/
+#if STM32_ADVANCED_DMA
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if STM32_I2S_USE_SPI1 && (!defined(STM32_I2S_SPI1_RX_DMA_STREAM) || \
+ !defined(STM32_I2S_SPI1_TX_DMA_STREAM))
+#error "SPI1 DMA streams not defined"
+#endif
+
+#if STM32_I2S_USE_SPI2 && (!defined(STM32_I2S_SPI2_RX_DMA_STREAM) || \
+ !defined(STM32_I2S_SPI2_TX_DMA_STREAM))
+#error "SPI2 DMA streams not defined"
+#endif
+
+#if STM32_I2S_USE_SPI3 && (!defined(STM32_I2S_SPI3_RX_DMA_STREAM) || \
+ !defined(STM32_I2S_SPI3_TX_DMA_STREAM))
+#error "SPI3 DMA streams not defined"
+#endif
+
+/* Check on the validity of the assigned DMA channels.*/
+#if STM32_I2S_USE_SPI1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI1_RX_DMA_STREAM, STM32_SPI1_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI1 RX"
+#endif
+
+#if STM32_I2S_USE_SPI1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI1_TX_DMA_STREAM, STM32_SPI1_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI1 TX"
+#endif
+
+#if STM32_I2S_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI2 RX"
+#endif
+
+#if STM32_I2S_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI2 TX"
+#endif
+
+#if STM32_I2S_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI3 RX"
+#endif
+
+#if STM32_I2S_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_I2S_SPI3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI3 TX"
+#endif
+#endif /* STM32_ADVANCED_DMA */
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the I2S driver structure.
+ */
+#define i2s_lld_driver_fields \
+ /* Pointer to the SPIx registers block.*/ \
+ SPI_TypeDef *spi; \
+ /* Calculated part of the I2SCFGR register.*/ \
+ uint16_t cfg; \
+ /* Receive DMA stream or @p NULL.*/ \
+ const stm32_dma_stream_t *dmarx; \
+ /* Transmit DMA stream or @p NULL.*/ \
+ const stm32_dma_stream_t *dmatx; \
+ /* RX DMA mode bit mask.*/ \
+ uint32_t rxdmamode; \
+ /* TX DMA mode bit mask.*/ \
+ uint32_t txdmamode
+
+/**
+ * @brief Low level fields of the I2S configuration structure.
+ */
+#define i2s_lld_config_fields \
+ /* Configuration of the I2SCFGR register. \
+ NOTE: See the STM32 reference manual, this register is used for \
+ the I2S configuration, the following bits must not be \
+ specified because handled directly by the driver: \
+ - I2SMOD \
+ - I2SE \
+ - I2SCFG \
+ */ \
+ int16_t i2scfgr; \
+ /* Configuration of the I2SPR register. \
+ NOTE: See the STM32 reference manual, this register is used for \
+ the I2S clock setup.*/ \
+ int16_t i2spr
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_I2S_USE_SPI1 && !defined(__DOXYGEN__)
+extern I2SDriver I2SD1;
+#endif
+
+#if STM32_I2S_USE_SPI2 && !defined(__DOXYGEN__)
+extern I2SDriver I2SD2;
+#endif
+
+#if STM32_I2S_USE_SPI3 && !defined(__DOXYGEN__)
+extern I2SDriver I2SD3;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void i2s_lld_init(void);
+ void i2s_lld_start(I2SDriver *i2sp);
+ void i2s_lld_stop(I2SDriver *i2sp);
+ void i2s_lld_start_exchange(I2SDriver *i2sp);
+ void i2s_lld_stop_exchange(I2SDriver *i2sp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_I2S */
+
+#endif /* HAL_I2S_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.c
new file mode 100644
index 0000000..02bc9a0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.c
@@ -0,0 +1,720 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SPIv2/hal_spi_lld.c
+ * @brief STM32 SPI subsystem low level driver source.
+ *
+ * @addtogroup SPI
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_SPI || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define SPI1_RX_DMA_STREAM \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_RX_DMA_STREAM, \
+ STM32_SPI1_RX_DMA_CHN)
+
+#define SPI1_TX_DMA_STREAM \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI1_TX_DMA_STREAM, \
+ STM32_SPI1_TX_DMA_CHN)
+
+#define SPI2_RX_DMA_STREAM \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_RX_DMA_STREAM, \
+ STM32_SPI2_RX_DMA_CHN)
+
+#define SPI2_TX_DMA_STREAM \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI2_TX_DMA_STREAM, \
+ STM32_SPI2_TX_DMA_CHN)
+
+#define SPI3_RX_DMA_STREAM \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_RX_DMA_STREAM, \
+ STM32_SPI3_RX_DMA_CHN)
+
+#define SPI3_TX_DMA_STREAM \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI3_TX_DMA_STREAM, \
+ STM32_SPI3_TX_DMA_CHN)
+
+#define SPI4_RX_DMA_STREAM \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI4_RX_DMA_STREAM, \
+ STM32_SPI4_RX_DMA_CHN)
+
+#define SPI4_TX_DMA_STREAM \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI4_TX_DMA_STREAM, \
+ STM32_SPI4_TX_DMA_CHN)
+
+#define SPI5_RX_DMA_STREAM \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI5_RX_DMA_STREAM, \
+ STM32_SPI5_RX_DMA_CHN)
+
+#define SPI5_TX_DMA_STREAM \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI5_TX_DMA_STREAM, \
+ STM32_SPI5_TX_DMA_CHN)
+
+#define SPI6_RX_DMA_STREAM \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI6_RX_DMA_STREAM, \
+ STM32_SPI6_RX_DMA_CHN)
+
+#define SPI6_TX_DMA_STREAM \
+ STM32_DMA_GETCHANNEL(STM32_SPI_SPI6_TX_DMA_STREAM, \
+ STM32_SPI6_TX_DMA_CHN)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief SPI1 driver identifier.*/
+#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__)
+SPIDriver SPID1;
+#endif
+
+/** @brief SPI2 driver identifier.*/
+#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__)
+SPIDriver SPID2;
+#endif
+
+/** @brief SPI3 driver identifier.*/
+#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__)
+SPIDriver SPID3;
+#endif
+
+/** @brief SPI4 driver identifier.*/
+#if STM32_SPI_USE_SPI4 || defined(__DOXYGEN__)
+SPIDriver SPID4;
+#endif
+
+/** @brief SPI5 driver identifier.*/
+#if STM32_SPI_USE_SPI5 || defined(__DOXYGEN__)
+SPIDriver SPID5;
+#endif
+
+/** @brief SPI6 driver identifier.*/
+#if STM32_SPI_USE_SPI6 || defined(__DOXYGEN__)
+SPIDriver SPID6;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+static const uint16_t dummytx = 0xFFFFU;
+static uint16_t dummyrx;
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Shared end-of-rx service routine.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(STM32_SPI_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_SPI_DMA_ERROR_HOOK(spip);
+ }
+#else
+ (void)flags;
+#endif
+
+ if (spip->config->circular) {
+ if ((flags & STM32_DMA_ISR_HTIF) != 0U) {
+ /* Half buffer interrupt.*/
+ _spi_isr_half_code(spip);
+ }
+ if ((flags & STM32_DMA_ISR_TCIF) != 0U) {
+ /* End buffer interrupt.*/
+ _spi_isr_full_code(spip);
+ }
+ }
+ else {
+ /* Stopping DMAs.*/
+ dmaStreamDisable(spip->dmatx);
+ dmaStreamDisable(spip->dmarx);
+
+ /* Portable SPI ISR code defined in the high level driver, note, it is
+ a macro.*/
+ _spi_isr_code(spip);
+ }
+}
+
+/**
+ * @brief Shared end-of-tx service routine.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(STM32_SPI_DMA_ERROR_HOOK)
+ (void)spip;
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_SPI_DMA_ERROR_HOOK(spip);
+ }
+#else
+ (void)spip;
+ (void)flags;
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level SPI driver initialization.
+ *
+ * @notapi
+ */
+void spi_lld_init(void) {
+
+#if STM32_SPI_USE_SPI1
+ spiObjectInit(&SPID1);
+ SPID1.spi = SPI1;
+ SPID1.dmarx = NULL;
+ SPID1.dmatx = NULL;
+ SPID1.rxdmamode = STM32_DMA_CR_CHSEL(SPI1_RX_DMA_STREAM) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ SPID1.txdmamode = STM32_DMA_CR_CHSEL(SPI1_TX_DMA_STREAM) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#endif
+
+#if STM32_SPI_USE_SPI2
+ spiObjectInit(&SPID2);
+ SPID2.spi = SPI2;
+ SPID2.dmarx = NULL;
+ SPID2.dmatx = NULL;
+ SPID2.rxdmamode = STM32_DMA_CR_CHSEL(SPI2_RX_DMA_STREAM) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ SPID2.txdmamode = STM32_DMA_CR_CHSEL(SPI2_TX_DMA_STREAM) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#endif
+
+#if STM32_SPI_USE_SPI3
+ spiObjectInit(&SPID3);
+ SPID3.spi = SPI3;
+ SPID3.dmarx = NULL;
+ SPID3.dmatx = NULL;
+ SPID3.rxdmamode = STM32_DMA_CR_CHSEL(SPI3_RX_DMA_STREAM) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ SPID3.txdmamode = STM32_DMA_CR_CHSEL(SPI3_TX_DMA_STREAM) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#endif
+
+#if STM32_SPI_USE_SPI4
+ spiObjectInit(&SPID4);
+ SPID4.spi = SPI4;
+ SPID4.dmarx = NULL;
+ SPID4.dmatx = NULL;
+ SPID4.rxdmamode = STM32_DMA_CR_CHSEL(SPI4_RX_DMA_STREAM) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI4_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ SPID4.txdmamode = STM32_DMA_CR_CHSEL(SPI4_TX_DMA_STREAM) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI4_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#endif
+
+#if STM32_SPI_USE_SPI5
+ spiObjectInit(&SPID5);
+ SPID5.spi = SPI5;
+ SPID5.dmarx = NULL;
+ SPID5.dmatx = NULL;
+ SPID5.rxdmamode = STM32_DMA_CR_CHSEL(SPI5_RX_DMA_STREAM) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI5_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ SPID5.txdmamode = STM32_DMA_CR_CHSEL(SPI5_TX_DMA_STREAM) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI5_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#endif
+
+#if STM32_SPI_USE_SPI6
+ spiObjectInit(&SPID6);
+ SPID6.spi = SPI6;
+ SPID6.dmarx = NULL;
+ SPID6.dmatx = NULL;
+ SPID6.rxdmamode = STM32_DMA_CR_CHSEL(SPI6_RX_DMA_STREAM) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI6_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ SPID6.txdmamode = STM32_DMA_CR_CHSEL(SPI6_TX_DMA_STREAM) |
+ STM32_DMA_CR_PL(STM32_SPI_SPI6_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#endif
+}
+
+/**
+ * @brief Configures and activates the SPI peripheral.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_start(SPIDriver *spip) {
+ uint32_t ds;
+
+ /* If in stopped state then enables the SPI and DMA clocks.*/
+ if (spip->state == SPI_STOP) {
+#if STM32_SPI_USE_SPI1
+ if (&SPID1 == spip) {
+ spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI1_RX_DMA_STREAM,
+ STM32_SPI_SPI1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream");
+ spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI1_TX_DMA_STREAM,
+ STM32_SPI_SPI1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream");
+ rccEnableSPI1(true);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI1_RX);
+ dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI1_TX);
+#endif
+ }
+#endif
+#if STM32_SPI_USE_SPI2
+ if (&SPID2 == spip) {
+ spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI2_RX_DMA_STREAM,
+ STM32_SPI_SPI2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream");
+ spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI2_TX_DMA_STREAM,
+ STM32_SPI_SPI2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream");
+ rccEnableSPI2(true);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI2_RX);
+ dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI2_TX);
+#endif
+ }
+#endif
+#if STM32_SPI_USE_SPI3
+ if (&SPID3 == spip) {
+ spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI3_RX_DMA_STREAM,
+ STM32_SPI_SPI3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream");
+ spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI3_TX_DMA_STREAM,
+ STM32_SPI_SPI3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream");
+ rccEnableSPI3(true);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI3_RX);
+ dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI3_TX);
+#endif
+ }
+#endif
+#if STM32_SPI_USE_SPI4
+ if (&SPID4 == spip) {
+ spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI4_RX_DMA_STREAM,
+ STM32_SPI_SPI4_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream");
+ spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI4_TX_DMA_STREAM,
+ STM32_SPI_SPI4_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream");
+ rccEnableSPI4(true);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI4_RX);
+ dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI4_TX);
+#endif
+ }
+#endif
+#if STM32_SPI_USE_SPI5
+ if (&SPID5 == spip) {
+ spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI5_RX_DMA_STREAM,
+ STM32_SPI_SPI5_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream");
+ spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI5_TX_DMA_STREAM,
+ STM32_SPI_SPI5_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream");
+ rccEnableSPI5(true);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI5_RX);
+ dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI5_TX);
+#endif
+ }
+#endif
+#if STM32_SPI_USE_SPI6
+ if (&SPID6 == spip) {
+ spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI6_RX_DMA_STREAM,
+ STM32_SPI_SPI6_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream");
+ spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI6_TX_DMA_STREAM,
+ STM32_SPI_SPI6_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream");
+ rccEnableSPI6(true);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI6_RX);
+ dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI6_TX);
+#endif
+ }
+#endif
+
+ /* DMA setup.*/
+ dmaStreamSetPeripheral(spip->dmarx, &spip->spi->DR);
+ dmaStreamSetPeripheral(spip->dmatx, &spip->spi->DR);
+ }
+
+ /* Configuration-specific DMA setup.*/
+ ds = spip->config->cr2 & SPI_CR2_DS;
+ if (!ds || (ds <= (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0))) {
+ /* Frame width is 8 bits or smaller.*/
+ spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) |
+ STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE;
+ spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) |
+ STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE;
+ }
+ else {
+ /* Frame width is larger than 8 bits.*/
+ spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) |
+ STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
+ spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) |
+ STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
+ }
+
+ if (spip->config->circular) {
+ spip->rxdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE);
+ spip->txdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE);
+ }
+ else {
+ spip->rxdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE);
+ spip->txdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE);
+ }
+
+ /* SPI setup and enable.*/
+ spip->spi->CR1 &= ~SPI_CR1_SPE;
+ spip->spi->CR1 = spip->config->cr1 | SPI_CR1_MSTR;
+ spip->spi->CR2 = spip->config->cr2 | SPI_CR2_FRXTH | SPI_CR2_SSOE |
+ SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN;
+ spip->spi->CR1 |= SPI_CR1_SPE;
+}
+
+/**
+ * @brief Deactivates the SPI peripheral.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_stop(SPIDriver *spip) {
+
+ /* If in ready state then disables the SPI clock.*/
+ if (spip->state == SPI_READY) {
+
+ /* SPI disable.*/
+ spip->spi->CR1 &= ~SPI_CR1_SPE;
+ spip->spi->CR1 = 0;
+ spip->spi->CR2 = 0;
+ dmaStreamFreeI(spip->dmarx);
+ dmaStreamFreeI(spip->dmatx);
+ spip->dmarx = NULL;
+ spip->dmatx = NULL;
+
+#if STM32_SPI_USE_SPI1
+ if (&SPID1 == spip)
+ rccDisableSPI1();
+#endif
+#if STM32_SPI_USE_SPI2
+ if (&SPID2 == spip)
+ rccDisableSPI2();
+#endif
+#if STM32_SPI_USE_SPI3
+ if (&SPID3 == spip)
+ rccDisableSPI3();
+#endif
+#if STM32_SPI_USE_SPI4
+ if (&SPID4 == spip)
+ rccDisableSPI4();
+#endif
+#if STM32_SPI_USE_SPI5
+ if (&SPID5 == spip)
+ rccDisableSPI5();
+#endif
+#if STM32_SPI_USE_SPI6
+ if (&SPID6 == spip)
+ rccDisableSPI6();
+#endif
+ }
+}
+
+#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__)
+/**
+ * @brief Asserts the slave select signal and prepares for transfers.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_select(SPIDriver *spip) {
+
+ /* No implementation on STM32.*/
+}
+
+/**
+ * @brief Deasserts the slave select signal.
+ * @details The previously selected peripheral is unselected.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_unselect(SPIDriver *spip) {
+
+ /* No implementation on STM32.*/
+}
+#endif
+
+/**
+ * @brief Ignores data on the SPI bus.
+ * @details This asynchronous function starts the transmission of a series of
+ * idle words on the SPI bus and ignores the received data.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be ignored
+ *
+ * @notapi
+ */
+void spi_lld_ignore(SPIDriver *spip, size_t n) {
+
+ osalDbgAssert(n < 65536, "unsupported DMA transfer size");
+
+ dmaStreamSetMemory0(spip->dmarx, &dummyrx);
+ dmaStreamSetTransactionSize(spip->dmarx, n);
+ dmaStreamSetMode(spip->dmarx, spip->rxdmamode);
+
+ dmaStreamSetMemory0(spip->dmatx, &dummytx);
+ dmaStreamSetTransactionSize(spip->dmatx, n);
+ dmaStreamSetMode(spip->dmatx, spip->txdmamode);
+
+ dmaStreamEnable(spip->dmarx);
+ dmaStreamEnable(spip->dmatx);
+}
+
+/**
+ * @brief Exchanges data on the SPI bus.
+ * @details This asynchronous function starts a simultaneous transmit/receive
+ * operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be exchanged
+ * @param[in] txbuf the pointer to the transmit buffer
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void spi_lld_exchange(SPIDriver *spip, size_t n,
+ const void *txbuf, void *rxbuf) {
+
+ osalDbgAssert(n < 65536, "unsupported DMA transfer size");
+
+ dmaStreamSetMemory0(spip->dmarx, rxbuf);
+ dmaStreamSetTransactionSize(spip->dmarx, n);
+ dmaStreamSetMode(spip->dmarx, spip->rxdmamode | STM32_DMA_CR_MINC);
+
+ dmaStreamSetMemory0(spip->dmatx, txbuf);
+ dmaStreamSetTransactionSize(spip->dmatx, n);
+ dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC);
+
+ dmaStreamEnable(spip->dmarx);
+ dmaStreamEnable(spip->dmatx);
+}
+
+/**
+ * @brief Sends data over the SPI bus.
+ * @details This asynchronous function starts a transmit operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @notapi
+ */
+void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
+
+ osalDbgAssert(n < 65536, "unsupported DMA transfer size");
+
+ dmaStreamSetMemory0(spip->dmarx, &dummyrx);
+ dmaStreamSetTransactionSize(spip->dmarx, n);
+ dmaStreamSetMode(spip->dmarx, spip->rxdmamode);
+
+ dmaStreamSetMemory0(spip->dmatx, txbuf);
+ dmaStreamSetTransactionSize(spip->dmatx, n);
+ dmaStreamSetMode(spip->dmatx, spip->txdmamode | STM32_DMA_CR_MINC);
+
+ dmaStreamEnable(spip->dmarx);
+ dmaStreamEnable(spip->dmatx);
+}
+
+/**
+ * @brief Receives data from the SPI bus.
+ * @details This asynchronous function starts a receive operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to receive
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
+
+ osalDbgAssert(n < 65536, "unsupported DMA transfer size");
+
+ dmaStreamSetMemory0(spip->dmarx, rxbuf);
+ dmaStreamSetTransactionSize(spip->dmarx, n);
+ dmaStreamSetMode(spip->dmarx, spip->rxdmamode | STM32_DMA_CR_MINC);
+
+ dmaStreamSetMemory0(spip->dmatx, &dummytx);
+ dmaStreamSetTransactionSize(spip->dmatx, n);
+ dmaStreamSetMode(spip->dmatx, spip->txdmamode);
+
+ dmaStreamEnable(spip->dmarx);
+ dmaStreamEnable(spip->dmatx);
+}
+
+#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Aborts the ongoing SPI operation, if any.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_abort(SPIDriver *spip) {
+
+ /* Stopping DMAs.*/
+ dmaStreamDisable(spip->dmatx);
+ dmaStreamDisable(spip->dmarx);
+}
+#endif /* SPI_SUPPORTS_CIRCULAR == TRUE */
+
+/**
+ * @brief Exchanges one frame using a polled wait.
+ * @details This synchronous function exchanges one frame using a polled
+ * synchronization method. This function is useful when exchanging
+ * small amount of data on high speed channels, usually in this
+ * situation is much more efficient just wait for completion using
+ * polling than suspending the thread waiting for an interrupt.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] frame the data frame to send over the SPI bus
+ * @return The received data frame from the SPI bus.
+ */
+uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) {
+
+ /*
+ * Data register must be accessed with the appropriate data size.
+ * Byte size access (uint8_t *) for transactions that are <= 8-bit.
+ * Halfword size access (uint16_t) for transactions that are <= 8-bit.
+ */
+ if ((spip->config->cr2 & SPI_CR2_DS) <= (SPI_CR2_DS_2 |
+ SPI_CR2_DS_1 |
+ SPI_CR2_DS_0)) {
+ volatile uint8_t *spidr = (volatile uint8_t *)&spip->spi->DR;
+ *spidr = (uint8_t)frame;
+ while ((spip->spi->SR & SPI_SR_RXNE) == 0)
+ ;
+ return (uint16_t)*spidr;
+ }
+ else {
+ spip->spi->DR = frame;
+ while ((spip->spi->SR & SPI_SR_RXNE) == 0)
+ ;
+ return spip->spi->DR;
+ }
+}
+
+#endif /* HAL_USE_SPI */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.h
new file mode 100644
index 0000000..3ded6ed
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv2/hal_spi_lld.h
@@ -0,0 +1,552 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SPIv2/hal_spi_lld.h
+ * @brief STM32 SPI subsystem low level driver header.
+ *
+ * @addtogroup SPI
+ * @{
+ */
+
+#ifndef HAL_SPI_LLD_H
+#define HAL_SPI_LLD_H
+
+#if HAL_USE_SPI || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Circular mode support flag.
+ */
+#define SPI_SUPPORTS_CIRCULAR TRUE
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief SPI1 driver enable switch.
+ * @details If set to @p TRUE the support for SPI1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SPI_USE_SPI1) || defined(__DOXYGEN__)
+#define STM32_SPI_USE_SPI1 FALSE
+#endif
+
+/**
+ * @brief SPI2 driver enable switch.
+ * @details If set to @p TRUE the support for SPI2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SPI_USE_SPI2) || defined(__DOXYGEN__)
+#define STM32_SPI_USE_SPI2 FALSE
+#endif
+
+/**
+ * @brief SPI3 driver enable switch.
+ * @details If set to @p TRUE the support for SPI3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SPI_USE_SPI3) || defined(__DOXYGEN__)
+#define STM32_SPI_USE_SPI3 FALSE
+#endif
+
+/**
+ * @brief SPI4 driver enable switch.
+ * @details If set to @p TRUE the support for SPI4 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SPI_USE_SPI4) || defined(__DOXYGEN__)
+#define STM32_SPI_USE_SPI4 FALSE
+#endif
+
+/**
+ * @brief SPI5 driver enable switch.
+ * @details If set to @p TRUE the support for SPI5 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SPI_USE_SPI5) || defined(__DOXYGEN__)
+#define STM32_SPI_USE_SPI5 FALSE
+#endif
+
+/**
+ * @brief SPI6 driver enable switch.
+ * @details If set to @p TRUE the support for SPI6 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SPI_USE_SPI6) || defined(__DOXYGEN__)
+#define STM32_SPI_USE_SPI6 FALSE
+#endif
+
+/**
+ * @brief SPI1 interrupt priority level setting.
+ */
+#if !defined(STM32_SPI_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI1_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI2 interrupt priority level setting.
+ */
+#if !defined(STM32_SPI_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI2_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI3 interrupt priority level setting.
+ */
+#if !defined(STM32_SPI_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI3_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI4 interrupt priority level setting.
+ */
+#if !defined(STM32_SPI_SPI4_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI4_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI5 interrupt priority level setting.
+ */
+#if !defined(STM32_SPI_SPI5_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI5_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI6 interrupt priority level setting.
+ */
+#if !defined(STM32_SPI_SPI6_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI6_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI1 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_SPI_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI1_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI2 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_SPI_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI2_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI3 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_SPI_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI3_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI4 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_SPI_SPI4_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI4_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI5 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_SPI_SPI5_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI5_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI6 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_SPI_SPI6_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI6_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI DMA error hook.
+ */
+#if !defined(STM32_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if STM32_SPI_USE_SPI1 && !STM32_HAS_SPI1
+#error "SPI1 not present in the selected device"
+#endif
+
+#if STM32_SPI_USE_SPI2 && !STM32_HAS_SPI2
+#error "SPI2 not present in the selected device"
+#endif
+
+#if STM32_SPI_USE_SPI3 && !STM32_HAS_SPI3
+#error "SPI3 not present in the selected device"
+#endif
+
+#if STM32_SPI_USE_SPI4 && !STM32_HAS_SPI4
+#error "SPI4 not present in the selected device"
+#endif
+
+#if STM32_SPI_USE_SPI5 && !STM32_HAS_SPI5
+#error "SPI5 not present in the selected device"
+#endif
+
+#if STM32_SPI_USE_SPI6 && !STM32_HAS_SPI6
+#error "SPI6 not present in the selected device"
+#endif
+
+#if !STM32_SPI_USE_SPI1 && !STM32_SPI_USE_SPI2 && !STM32_SPI_USE_SPI3 && \
+ !STM32_SPI_USE_SPI4 && !STM32_SPI_USE_SPI5 && !STM32_SPI_USE_SPI6
+#error "SPI driver activated but no SPI peripheral assigned"
+#endif
+
+#if STM32_SPI_USE_SPI1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI1"
+#endif
+
+#if STM32_SPI_USE_SPI2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI2"
+#endif
+
+#if STM32_SPI_USE_SPI3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI3"
+#endif
+
+#if STM32_SPI_USE_SPI4 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI4_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI4"
+#endif
+
+#if STM32_SPI_USE_SPI5 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI5_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI5"
+#endif
+
+#if STM32_SPI_USE_SPI6 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI6_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI6"
+#endif
+
+#if STM32_SPI_USE_SPI1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI1"
+#endif
+
+#if STM32_SPI_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI2"
+#endif
+
+#if STM32_SPI_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI3_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI3"
+#endif
+
+#if STM32_SPI_USE_SPI4 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI4_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI4"
+#endif
+
+#if STM32_SPI_USE_SPI5 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI5_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI5"
+#endif
+
+#if STM32_SPI_USE_SPI6 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI6_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI6"
+#endif
+
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if STM32_SPI_USE_SPI1 && (!defined(STM32_SPI_SPI1_RX_DMA_STREAM) || \
+ !defined(STM32_SPI_SPI1_TX_DMA_STREAM))
+#error "SPI1 DMA streams not defined"
+#endif
+
+#if STM32_SPI_USE_SPI2 && (!defined(STM32_SPI_SPI2_RX_DMA_STREAM) || \
+ !defined(STM32_SPI_SPI2_TX_DMA_STREAM))
+#error "SPI2 DMA streams not defined"
+#endif
+
+#if STM32_SPI_USE_SPI3 && (!defined(STM32_SPI_SPI3_RX_DMA_STREAM) || \
+ !defined(STM32_SPI_SPI3_TX_DMA_STREAM))
+#error "SPI3 DMA streams not defined"
+#endif
+
+#if STM32_SPI_USE_SPI4 && (!defined(STM32_SPI_SPI4_RX_DMA_STREAM) || \
+ !defined(STM32_SPI_SPI4_TX_DMA_STREAM))
+#error "SPI4 DMA streams not defined"
+#endif
+
+#if STM32_SPI_USE_SPI5 && (!defined(STM32_SPI_SPI5_RX_DMA_STREAM) || \
+ !defined(STM32_SPI_SPI5_TX_DMA_STREAM))
+#error "SPI5 DMA streams not defined"
+#endif
+
+#if STM32_SPI_USE_SPI6 && (!defined(STM32_SPI_SPI6_RX_DMA_STREAM) || \
+ !defined(STM32_SPI_SPI6_TX_DMA_STREAM))
+#error "SPI6 DMA streams not defined"
+#endif
+
+/* Check on the validity of the assigned DMA channels.*/
+#if STM32_SPI_USE_SPI1 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM)
+#error "Invalid DMA channel assigned to SPI1 TX"
+#endif
+
+#if STM32_SPI_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI2_RX_DMA_STREAM)
+#error "Invalid DMA channel assigned to SPI2 RX"
+#endif
+
+#if STM32_SPI_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI2_TX_DMA_STREAM)
+#error "Invalid DMA channel assigned to SPI2 TX"
+#endif
+
+#if STM32_SPI_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI3_RX_DMA_STREAM)
+#error "Invalid DMA channel assigned to SPI3 RX"
+#endif
+
+#if STM32_SPI_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI3_TX_DMA_STREAM)
+#error "Invalid DMA channel assigned to SPI3 TX"
+#endif
+
+#if STM32_SPI_USE_SPI4 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI4_RX_DMA_STREAM)
+#error "Invalid DMA channel assigned to SPI4 RX"
+#endif
+
+#if STM32_SPI_USE_SPI4 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI4_TX_DMA_STREAM)
+#error "Invalid DMA channel assigned to SPI4 TX"
+#endif
+
+#if STM32_SPI_USE_SPI5 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI5_RX_DMA_STREAM)
+#error "Invalid DMA channel assigned to SPI5 RX"
+#endif
+
+#if STM32_SPI_USE_SPI5 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI5_TX_DMA_STREAM)
+#error "Invalid DMA channel assigned to SPI5 TX"
+#endif
+
+#if STM32_SPI_USE_SPI6 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI6_RX_DMA_STREAM)
+#error "Invalid DMA channel assigned to SPI6 RX"
+#endif
+
+#if STM32_SPI_USE_SPI6 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI6_TX_DMA_STREAM)
+#error "Invalid DMA channel assigned to SPI6 TX"
+#endif
+
+/* Devices without DMAMUX require an additional check.*/
+#if STM32_ADVANCED_DMA && !STM32_DMA_SUPPORTS_DMAMUX
+
+/* Check on the validity of the assigned DMA channels.*/
+#if STM32_SPI_USE_SPI1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_RX_DMA_STREAM, STM32_SPI1_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI1 RX"
+#endif
+
+#if STM32_SPI_USE_SPI1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_TX_DMA_STREAM, STM32_SPI1_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI1 TX"
+#endif
+
+#if STM32_SPI_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI2 RX"
+#endif
+
+#if STM32_SPI_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI2 TX"
+#endif
+
+#if STM32_SPI_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI3 RX"
+#endif
+
+#if STM32_SPI_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI3 TX"
+#endif
+
+#if STM32_SPI_USE_SPI4 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI4_RX_DMA_STREAM, STM32_SPI4_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI4 RX"
+#endif
+
+#if STM32_SPI_USE_SPI4 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI4_TX_DMA_STREAM, STM32_SPI4_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI4 TX"
+#endif
+
+#if STM32_SPI_USE_SPI5 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI5_RX_DMA_STREAM, STM32_SPI5_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI5 RX"
+#endif
+
+#if STM32_SPI_USE_SPI5 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI5_TX_DMA_STREAM, STM32_SPI5_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI5 TX"
+#endif
+
+#if STM32_SPI_USE_SPI6 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI6_RX_DMA_STREAM, STM32_SPI6_RX_DMA_MSK)
+#error "invalid DMA stream associated to SPI6 RX"
+#endif
+
+#if STM32_SPI_USE_SPI6 && \
+ !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI6_TX_DMA_STREAM, STM32_SPI6_TX_DMA_MSK)
+#error "invalid DMA stream associated to SPI6 TX"
+#endif
+
+#endif /* STM32_ADVANCED_DMA && !STM32_DMA_SUPPORTS_DMAMUX */
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+#if SPI_SELECT_MODE == SPI_SELECT_MODE_LLD
+#error "SPI_SELECT_MODE_LLD not supported by this driver"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the SPI driver structure.
+ */
+#define spi_lld_driver_fields \
+ /* Pointer to the SPIx registers block.*/ \
+ SPI_TypeDef *spi; \
+ /* Receive DMA stream.*/ \
+ const stm32_dma_stream_t *dmarx; \
+ /* Transmit DMA stream.*/ \
+ const stm32_dma_stream_t *dmatx; \
+ /* RX DMA mode bit mask.*/ \
+ uint32_t rxdmamode; \
+ /* TX DMA mode bit mask.*/ \
+ uint32_t txdmamode
+
+/**
+ * @brief Low level fields of the SPI configuration structure.
+ */
+#define spi_lld_config_fields \
+ /* SPI CR1 register initialization data.*/ \
+ uint16_t cr1; \
+ /* SPI CR2 register initialization data.*/ \
+ uint16_t cr2
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_SPI_USE_SPI1 && !defined(__DOXYGEN__)
+extern SPIDriver SPID1;
+#endif
+
+#if STM32_SPI_USE_SPI2 && !defined(__DOXYGEN__)
+extern SPIDriver SPID2;
+#endif
+
+#if STM32_SPI_USE_SPI3 && !defined(__DOXYGEN__)
+extern SPIDriver SPID3;
+#endif
+
+#if STM32_SPI_USE_SPI4 && !defined(__DOXYGEN__)
+extern SPIDriver SPID4;
+#endif
+
+#if STM32_SPI_USE_SPI5 && !defined(__DOXYGEN__)
+extern SPIDriver SPID5;
+#endif
+
+#if STM32_SPI_USE_SPI6 && !defined(__DOXYGEN__)
+extern SPIDriver SPID6;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void spi_lld_init(void);
+ void spi_lld_start(SPIDriver *spip);
+ void spi_lld_stop(SPIDriver *spip);
+#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__)
+ void spi_lld_select(SPIDriver *spip);
+ void spi_lld_unselect(SPIDriver *spip);
+#endif
+ void spi_lld_ignore(SPIDriver *spip, size_t n);
+ void spi_lld_exchange(SPIDriver *spip, size_t n,
+ const void *txbuf, void *rxbuf);
+ void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
+ void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
+#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__)
+ void spi_lld_abort(SPIDriver *spip);
+#endif
+ uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SPI */
+
+#endif /* HAL_SPI_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv3/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv3/driver.mk
new file mode 100644
index 0000000..b29942c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv3/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_SPI TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv3
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c
new file mode 100644
index 0000000..4a67c87
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c
@@ -0,0 +1,1140 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SPIv3/hal_spi_lld.c
+ * @brief STM32 SPI subsystem low level driver source.
+ *
+ * @addtogroup SPI
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_SPI || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief SPI1 driver identifier.*/
+#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__)
+SPIDriver SPID1;
+#endif
+
+/** @brief SPI2 driver identifier.*/
+#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__)
+SPIDriver SPID2;
+#endif
+
+/** @brief SPI3 driver identifier.*/
+#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__)
+SPIDriver SPID3;
+#endif
+
+/** @brief SPI4 driver identifier.*/
+#if STM32_SPI_USE_SPI4 || defined(__DOXYGEN__)
+SPIDriver SPID4;
+#endif
+
+/** @brief SPI5 driver identifier.*/
+#if STM32_SPI_USE_SPI5 || defined(__DOXYGEN__)
+SPIDriver SPID5;
+#endif
+
+/** @brief SPI6 driver identifier.*/
+#if STM32_SPI_USE_SPI6 || defined(__DOXYGEN__)
+SPIDriver SPID6;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+static const uint32_t dummytx = STM32_SPI_FILLER_PATTERN;
+static uint32_t dummyrx;
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static void spi_lld_wait_complete(SPIDriver *spip) {
+
+ while ((spip->spi->CR1 & SPI_CR1_CSTART) != 0) {
+ }
+ spip->spi->IFCR = 0xFFFFFFFF;
+}
+
+#if defined(STM32_SPI_BDMA_REQUIRED)
+/**
+ * @brief Shared DMA end-of-rx service routine.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void spi_lld_serve_bdma_rx_interrupt(SPIDriver *spip, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(STM32_SPI_DMA_ERROR_HOOK)
+ if ((flags & STM32_BDMA_ISR_TEIF) != 0U) {
+ STM32_SPI_DMA_ERROR_HOOK(spip);
+ }
+#else
+ (void)flags;
+#endif
+
+ if (spip->config->circular) {
+ if ((flags & STM32_BDMA_ISR_HTIF) != 0U) {
+ /* Half buffer interrupt.*/
+ _spi_isr_half_code(spip);
+ }
+ if ((flags & STM32_BDMA_ISR_TCIF) != 0U) {
+ /* End buffer interrupt.*/
+ _spi_isr_full_code(spip);
+ }
+ }
+ else {
+ /* Stopping SPI.*/
+ spip->spi->CR1 |= SPI_CR1_CSUSP;
+
+ /* Stopping DMAs.*/
+ bdmaStreamDisable(spip->tx.bdma);
+ bdmaStreamDisable(spip->rx.bdma);
+
+ /* Portable SPI ISR code defined in the high level driver, note, it is
+ a macro.*/
+ _spi_isr_code(spip);
+ }
+}
+
+/**
+ * @brief Shared BDMA end-of-tx service routine.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void spi_lld_serve_bdma_tx_interrupt(SPIDriver *spip, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(STM32_SPI_DMA_ERROR_HOOK)
+ (void)spip;
+ if ((flags & STM32_BDMA_ISR_TEIF) != 0) {
+ STM32_SPI_DMA_ERROR_HOOK(spip);
+ }
+#else
+ (void)spip;
+ (void)flags;
+#endif
+}
+#endif /* defined(STM32_SPI_BDMA_REQUIRED) */
+
+#if defined(STM32_SPI_DMA_REQUIRED)
+/**
+ * @brief Shared DMA end-of-rx service routine.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void spi_lld_serve_dma_rx_interrupt(SPIDriver *spip, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(STM32_SPI_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0U) {
+ STM32_SPI_DMA_ERROR_HOOK(spip);
+ }
+#else
+ (void)flags;
+#endif
+
+ if (spip->config->circular) {
+ if ((flags & STM32_DMA_ISR_HTIF) != 0U) {
+ /* Half buffer interrupt.*/
+ _spi_isr_half_code(spip);
+ }
+ if ((flags & STM32_DMA_ISR_TCIF) != 0U) {
+ /* End buffer interrupt.*/
+ _spi_isr_full_code(spip);
+ }
+ }
+ else {
+ /* Stopping SPI.*/
+ spip->spi->CR1 |= SPI_CR1_CSUSP;
+
+ /* Stopping DMAs.*/
+ dmaStreamDisable(spip->tx.dma);
+ dmaStreamDisable(spip->rx.dma);
+
+ /* Portable SPI ISR code defined in the high level driver, note, it is
+ a macro.*/
+ _spi_isr_code(spip);
+ }
+}
+
+/**
+ * @brief Shared DMA end-of-tx service routine.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void spi_lld_serve_dma_tx_interrupt(SPIDriver *spip, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(STM32_SPI_DMA_ERROR_HOOK)
+ (void)spip;
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_SPI_DMA_ERROR_HOOK(spip);
+ }
+#else
+ (void)spip;
+ (void)flags;
+#endif
+}
+#endif /* defined(STM32_SPI_DMA_REQUIRED) */
+
+/**
+ * @brief Shared SPI service routine.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ */
+static void spi_lld_serve_interrupt(SPIDriver *spip) {
+ uint32_t sr;
+
+ sr = spip->spi->SR & spip->spi->IER;
+ spip->spi->IFCR = sr;
+
+ if ((sr & SPI_SR_OVR) != 0U) {
+ /* CHTODO: fault notification.*/
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__)
+#if !defined(STM32_SPI1_SUPPRESS_ISR)
+#if !defined(STM32_SPI1_HANDLER)
+#error "STM32_SPI1_HANDLER not defined"
+#endif
+/**
+ * @brief SPI1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_SPI1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ spi_lld_serve_interrupt(&SPID1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_SPI1_SUPPRESS_ISR) */
+#endif /* STM32_SPI_USE_SPI1 */
+
+#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__)
+#if !defined(STM32_SPI2_SUPPRESS_ISR)
+#if !defined(STM32_SPI2_HANDLER)
+#error "STM32_SPI2_HANDLER not defined"
+#endif
+/**
+ * @brief SPI2 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_SPI2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ spi_lld_serve_interrupt(&SPID2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_SPI2_SUPPRESS_ISR) */
+#endif /* STM32_SPI_USE_SPI2 */
+
+#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__)
+#if !defined(STM32_SPI3_SUPPRESS_ISR)
+#if !defined(STM32_SPI3_HANDLER)
+#error "STM32_SPI3_HANDLER not defined"
+#endif
+/**
+ * @brief SPI3 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_SPI3_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ spi_lld_serve_interrupt(&SPID3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_SPI3_SUPPRESS_ISR) */
+#endif /* STM32_SPI_USE_SPI3 */
+
+#if STM32_SPI_USE_SPI4 || defined(__DOXYGEN__)
+#if !defined(STM32_SPI4_SUPPRESS_ISR)
+#if !defined(STM32_SPI4_HANDLER)
+#error "STM32_SPI4_HANDLER not defined"
+#endif
+/**
+ * @brief SPI4 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_SPI4_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ spi_lld_serve_interrupt(&SPID4);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_SPI4_SUPPRESS_ISR) */
+#endif /* STM32_SPI_USE_SPI4 */
+
+#if STM32_SPI_USE_SPI5 || defined(__DOXYGEN__)
+#if !defined(STM32_SPI5_SUPPRESS_ISR)
+#if !defined(STM32_SPI5_HANDLER)
+#error "STM32_SPI5_HANDLER not defined"
+#endif
+/**
+ * @brief SPI5 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_SPI5_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ spi_lld_serve_interrupt(&SPID5);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_SPI5_SUPPRESS_ISR) */
+#endif /* STM32_SPI_USE_SPI5 */
+
+#if STM32_SPI_USE_SPI6 || defined(__DOXYGEN__)
+#if !defined(STM32_SPI6_SUPPRESS_ISR)
+#if !defined(STM32_SPI6_HANDLER)
+#error "STM32_SPI6_HANDLER not defined"
+#endif
+/**
+ * @brief SPI6 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_SPI6_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ spi_lld_serve_interrupt(&SPID6);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_SPI6_SUPPRESS_ISR) */
+#endif /* STM32_SPI_USE_SPI6 */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level SPI driver initialization.
+ *
+ * @notapi
+ */
+void spi_lld_init(void) {
+
+#if STM32_SPI_USE_SPI1
+ spiObjectInit(&SPID1);
+ SPID1.spi = SPI1;
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ SPID1.is_bdma = false;
+#endif
+ SPID1.rx.dma = NULL;
+ SPID1.tx.dma = NULL;
+ SPID1.rxdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ SPID1.txdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#if !defined(STM32_SPI1_SUPPRESS_ISR)
+ nvicEnableVector(STM32_SPI1_NUMBER, STM32_SPI_SPI1_IRQ_PRIORITY);
+#endif
+#endif
+
+#if STM32_SPI_USE_SPI2
+ spiObjectInit(&SPID2);
+ SPID2.spi = SPI2;
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ SPID2.is_bdma = false;
+#endif
+ SPID2.rx.dma = NULL;
+ SPID2.tx.dma = NULL;
+ SPID2.rxdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ SPID2.txdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI2_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#if !defined(STM32_SPI2_SUPPRESS_ISR)
+ nvicEnableVector(STM32_SPI2_NUMBER, STM32_SPI_SPI2_IRQ_PRIORITY);
+#endif
+#endif
+
+#if STM32_SPI_USE_SPI3
+ spiObjectInit(&SPID3);
+ SPID3.spi = SPI3;
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ SPID3.is_bdma = false;
+#endif
+ SPID3.rx.dma = NULL;
+ SPID3.tx.dma = NULL;
+ SPID3.rxdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ SPID3.txdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI3_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#if !defined(STM32_SPI3_SUPPRESS_ISR)
+ nvicEnableVector(STM32_SPI3_NUMBER, STM32_SPI_SPI3_IRQ_PRIORITY);
+#endif
+#endif
+
+#if STM32_SPI_USE_SPI4
+ spiObjectInit(&SPID4);
+ SPID4.spi = SPI4;
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ SPID4.is_bdma = false;
+#endif
+ SPID4.rx.dma = NULL;
+ SPID4.tx.dma = NULL;
+ SPID4.rxdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI4_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ SPID4.txdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI4_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#if !defined(STM32_SPI4_SUPPRESS_ISR)
+ nvicEnableVector(STM32_SPI4_NUMBER, STM32_SPI_SPI4_IRQ_PRIORITY);
+#endif
+#endif
+
+#if STM32_SPI_USE_SPI5
+ spiObjectInit(&SPID5);
+ SPID5.spi = SPI5;
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ SPID5.is_bdma = false;
+#endif
+ SPID5.rx.dma = NULL;
+ SPID5.tx.dma = NULL;
+ SPID5.rxdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI5_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_TCIE |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+ SPID5.txdmamode = STM32_DMA_CR_PL(STM32_SPI_SPI5_DMA_PRIORITY) |
+ STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_DMEIE |
+ STM32_DMA_CR_TEIE;
+#if !defined(STM32_SPI5_SUPPRESS_ISR)
+ nvicEnableVector(STM32_SPI5_NUMBER, STM32_SPI_SPI5_IRQ_PRIORITY);
+#endif
+#endif
+
+#if STM32_SPI_USE_SPI6
+ spiObjectInit(&SPID6);
+ SPID6.spi = SPI6;
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ SPID6.is_bdma = true;
+#endif
+ SPID6.rx.bdma = NULL;
+ SPID6.tx.bdma = NULL;
+ SPID6.rxdmamode = STM32_BDMA_CR_PL(STM32_SPI_SPI6_DMA_PRIORITY) |
+ STM32_BDMA_CR_DIR_P2M |
+ STM32_BDMA_CR_TCIE |
+ STM32_BDMA_CR_TEIE;
+ SPID6.txdmamode = STM32_BDMA_CR_PL(STM32_SPI_SPI6_DMA_PRIORITY) |
+ STM32_BDMA_CR_DIR_M2P |
+ STM32_BDMA_CR_TEIE;
+#if !defined(STM32_SPI6_SUPPRESS_ISR)
+ nvicEnableVector(STM32_SPI6_NUMBER, STM32_SPI_SPI6_IRQ_PRIORITY);
+#endif
+#endif
+}
+
+/**
+ * @brief Configures and activates the SPI peripheral.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_start(SPIDriver *spip) {
+ uint32_t dsize;
+
+ /* If in stopped state then enables the SPI and DMA clocks.*/
+ if (spip->state == SPI_STOP) {
+#if STM32_SPI_USE_SPI1
+ if (&SPID1 == spip) {
+ spip->rx.dma = dmaStreamAllocI(STM32_SPI_SPI1_RX_DMA_STREAM,
+ STM32_SPI_SPI1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->rx.dma != NULL, "unable to allocate stream");
+ spip->tx.dma = dmaStreamAllocI(STM32_SPI_SPI1_TX_DMA_STREAM,
+ STM32_SPI_SPI1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->tx.dma != NULL, "unable to allocate stream");
+ rccEnableSPI1(true);
+ dmaSetRequestSource(spip->rx.dma, STM32_DMAMUX1_SPI1_RX);
+ dmaSetRequestSource(spip->tx.dma, STM32_DMAMUX1_SPI1_TX);
+ }
+#endif
+#if STM32_SPI_USE_SPI2
+ if (&SPID2 == spip) {
+ spip->rx.dma = dmaStreamAllocI(STM32_SPI_SPI2_RX_DMA_STREAM,
+ STM32_SPI_SPI2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->rx.dma != NULL, "unable to allocate stream");
+ spip->tx.dma = dmaStreamAllocI(STM32_SPI_SPI2_TX_DMA_STREAM,
+ STM32_SPI_SPI2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->tx.dma != NULL, "unable to allocate stream");
+ rccEnableSPI2(true);
+ dmaSetRequestSource(spip->rx.dma, STM32_DMAMUX1_SPI2_RX);
+ dmaSetRequestSource(spip->tx.dma, STM32_DMAMUX1_SPI2_TX);
+ }
+#endif
+#if STM32_SPI_USE_SPI3
+ if (&SPID3 == spip) {
+ spip->rx.dma = dmaStreamAllocI(STM32_SPI_SPI3_RX_DMA_STREAM,
+ STM32_SPI_SPI3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->rx.dma != NULL, "unable to allocate stream");
+ spip->tx.dma = dmaStreamAllocI(STM32_SPI_SPI3_TX_DMA_STREAM,
+ STM32_SPI_SPI3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->tx.dma != NULL, "unable to allocate stream");
+ rccEnableSPI3(true);
+ dmaSetRequestSource(spip->rx.dma, STM32_DMAMUX1_SPI3_RX);
+ dmaSetRequestSource(spip->tx.dma, STM32_DMAMUX1_SPI3_TX);
+ }
+#endif
+#if STM32_SPI_USE_SPI4
+ if (&SPID4 == spip) {
+ spip->rx.dma = dmaStreamAllocI(STM32_SPI_SPI4_RX_DMA_STREAM,
+ STM32_SPI_SPI4_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->rx.dma != NULL, "unable to allocate stream");
+ spip->tx.dma = dmaStreamAllocI(STM32_SPI_SPI4_TX_DMA_STREAM,
+ STM32_SPI_SPI4_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->tx.dma != NULL, "unable to allocate stream");
+ rccEnableSPI4(true);
+ dmaSetRequestSource(spip->rx.dma, STM32_DMAMUX1_SPI4_RX);
+ dmaSetRequestSource(spip->tx.dma, STM32_DMAMUX1_SPI4_TX);
+ }
+#endif
+#if STM32_SPI_USE_SPI5
+ if (&SPID5 == spip) {
+ spip->rx.dma = dmaStreamAllocI(STM32_SPI_SPI5_RX_DMA_STREAM,
+ STM32_SPI_SPI5_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->rx.dma != NULL, "unable to allocate stream");
+ spip->tx.dma = dmaStreamAllocI(STM32_SPI_SPI5_TX_DMA_STREAM,
+ STM32_SPI_SPI5_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->tx.dma != NULL, "unable to allocate stream");
+ rccEnableSPI5(true);
+ dmaSetRequestSource(spip->rx.dma, STM32_DMAMUX1_SPI5_RX);
+ dmaSetRequestSource(spip->tx.dma, STM32_DMAMUX1_SPI5_TX);
+ }
+#endif
+#if STM32_SPI_USE_SPI6
+ if (&SPID6 == spip) {
+ spip->rx.bdma = bdmaStreamAllocI(STM32_SPI_SPI6_RX_BDMA_STREAM,
+ STM32_SPI_SPI6_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_bdma_rx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->rx.dma != NULL, "unable to allocate stream");
+ spip->tx.bdma = bdmaStreamAllocI(STM32_SPI_SPI6_TX_BDMA_STREAM,
+ STM32_SPI_SPI6_IRQ_PRIORITY,
+ (stm32_dmaisr_t)spi_lld_serve_bdma_tx_interrupt,
+ (void *)spip);
+ osalDbgAssert(spip->tx.dma != NULL, "unable to allocate stream");
+ rccEnableSPI6(true);
+ bdmaSetRequestSource(spip->rx.bdma, STM32_DMAMUX2_SPI6_RX);
+ bdmaSetRequestSource(spip->tx.bdma, STM32_DMAMUX2_SPI6_TX);
+ }
+#endif
+
+ /* DMA setup.*/
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ if (spip->is_bdma)
+#endif
+#if defined(STM32_SPI_BDMA_REQUIRED)
+ {
+ bdmaStreamSetPeripheral(spip->rx.bdma, &spip->spi->RXDR);
+ bdmaStreamSetPeripheral(spip->tx.bdma, &spip->spi->TXDR);
+ }
+#endif
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ else
+#endif
+#if defined(STM32_SPI_DMA_REQUIRED)
+ {
+ dmaStreamSetPeripheral(spip->rx.dma, &spip->spi->RXDR);
+ dmaStreamSetPeripheral(spip->tx.dma, &spip->spi->TXDR);
+ }
+#endif
+ }
+
+ /* Configuration-specific DMA setup.*/
+ dsize = (spip->config->cfg1 & SPI_CFG1_DSIZE_Msk) + 1U;
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ if (spip->is_bdma)
+#endif
+#if defined(STM32_SPI_BDMA_REQUIRED)
+ {
+ if (dsize <= 8U) {
+ /* Frame width is between 4 and 8 bits.*/
+ spip->rxdmamode = (spip->rxdmamode & ~STM32_BDMA_CR_SIZE_MASK) |
+ STM32_BDMA_CR_PSIZE_BYTE | STM32_BDMA_CR_MSIZE_BYTE;
+ spip->txdmamode = (spip->txdmamode & ~STM32_BDMA_CR_SIZE_MASK) |
+ STM32_BDMA_CR_PSIZE_BYTE | STM32_BDMA_CR_MSIZE_BYTE;
+ }
+ else if (dsize <= 16U) {
+ /* Frame width is between 9 and 16 bits.*/
+ spip->rxdmamode = (spip->rxdmamode & ~STM32_BDMA_CR_SIZE_MASK) |
+ STM32_BDMA_CR_PSIZE_HWORD | STM32_BDMA_CR_MSIZE_HWORD;
+ spip->txdmamode = (spip->txdmamode & ~STM32_BDMA_CR_SIZE_MASK) |
+ STM32_BDMA_CR_PSIZE_HWORD | STM32_BDMA_CR_MSIZE_HWORD;
+ }
+ else {
+ /* Frame width is between 16 and 32 bits.*/
+ spip->rxdmamode = (spip->rxdmamode & ~STM32_BDMA_CR_SIZE_MASK) |
+ STM32_BDMA_CR_PSIZE_WORD | STM32_BDMA_CR_MSIZE_WORD;
+ spip->txdmamode = (spip->txdmamode & ~STM32_BDMA_CR_SIZE_MASK) |
+ STM32_BDMA_CR_PSIZE_WORD | STM32_BDMA_CR_MSIZE_WORD;
+ }
+ if (spip->config->circular) {
+ spip->rxdmamode |= (STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE);
+ spip->txdmamode |= (STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE);
+ }
+ else {
+ spip->rxdmamode &= ~(STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE);
+ spip->txdmamode &= ~(STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE);
+ }
+ }
+#endif
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ else
+#endif
+#if defined(STM32_SPI_DMA_REQUIRED)
+ {
+ if (dsize <= 8U) {
+ /* Frame width is between 4 and 8 bits.*/
+ spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) |
+ STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE;
+ spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) |
+ STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE;
+ }
+ else if (dsize <= 16U) {
+ /* Frame width is between 9 and 16 bits.*/
+ spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) |
+ STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
+ spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) |
+ STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
+ }
+ else {
+ /* Frame width is between 16 and 32 bits.*/
+ spip->rxdmamode = (spip->rxdmamode & ~STM32_DMA_CR_SIZE_MASK) |
+ STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD;
+ spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) |
+ STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD;
+ }
+ if (spip->config->circular) {
+ spip->rxdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE);
+ spip->txdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE);
+ }
+ else {
+ spip->rxdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE);
+ spip->txdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE);
+ }
+ }
+#endif
+
+ /* SPI setup and enable.*/
+ spip->spi->CR1 &= ~SPI_CR1_SPE;
+ spip->spi->CR1 = SPI_CR1_MASRX;
+ spip->spi->CR2 = 0U;
+ spip->spi->CFG1 = (spip->config->cfg1 & ~SPI_CFG1_FTHLV_Msk) |
+ SPI_CFG1_RXDMAEN | SPI_CFG1_TXDMAEN;
+ spip->spi->CFG2 = (spip->config->cfg2 | SPI_CFG2_MASTER | SPI_CFG2_SSOE) &
+ ~SPI_CFG2_COMM_Msk;
+ spip->spi->IER = SPI_IER_OVRIE;
+ spip->spi->IFCR = 0xFFFFFFFFU;
+ spip->spi->CR1 |= SPI_CR1_SPE;
+}
+
+/**
+ * @brief Deactivates the SPI peripheral.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_stop(SPIDriver *spip) {
+
+ /* If in ready state then disables the SPI clock.*/
+ if (spip->state == SPI_READY) {
+
+ /* SPI disable.*/
+ spip->spi->CR1 &= ~SPI_CR1_SPE;
+ spip->spi->CR1 = 0U;
+ spip->spi->CR2 = 0U;
+ spip->spi->CFG1 = 0U;
+ spip->spi->CFG2 = 0U;
+ spip->spi->IER = 0U;
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ if (spip->is_bdma)
+#endif
+#if defined(STM32_SPI_BDMA_REQUIRED)
+ {
+ bdmaStreamFreeI(spip->rx.bdma);
+ bdmaStreamFreeI(spip->tx.bdma);
+ }
+#endif
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ else
+#endif
+#if defined(STM32_SPI_DMA_REQUIRED)
+ {
+ dmaStreamFreeI(spip->rx.dma);
+ dmaStreamFreeI(spip->tx.dma);
+ }
+#endif
+
+#if STM32_SPI_USE_SPI1
+ if (&SPID1 == spip)
+ rccDisableSPI1();
+#endif
+#if STM32_SPI_USE_SPI2
+ if (&SPID2 == spip)
+ rccDisableSPI2();
+#endif
+#if STM32_SPI_USE_SPI3
+ if (&SPID3 == spip)
+ rccDisableSPI3();
+#endif
+#if STM32_SPI_USE_SPI4
+ if (&SPID4 == spip)
+ rccDisableSPI4();
+#endif
+#if STM32_SPI_USE_SPI5
+ if (&SPID5 == spip)
+ rccDisableSPI5();
+#endif
+#if STM32_SPI_USE_SPI6
+ if (&SPID6 == spip)
+ rccDisableSPI6();
+#endif
+ }
+}
+
+#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__)
+/**
+ * @brief Asserts the slave select signal and prepares for transfers.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_select(SPIDriver *spip) {
+
+ /* No implementation on STM32.*/
+}
+
+/**
+ * @brief Deasserts the slave select signal.
+ * @details The previously selected peripheral is unselected.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_unselect(SPIDriver *spip) {
+
+ /* No implementation on STM32.*/
+}
+#endif
+
+/**
+ * @brief Ignores data on the SPI bus.
+ * @details This asynchronous function starts the transmission of a series of
+ * idle words on the SPI bus and ignores the received data.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be ignored
+ *
+ * @notapi
+ */
+void spi_lld_ignore(SPIDriver *spip, size_t n) {
+
+ osalDbgAssert(n < 65536, "unsupported DMA transfer size");
+
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ if (spip->is_bdma)
+#endif
+#if defined(STM32_SPI_BDMA_REQUIRED)
+ {
+ bdmaStreamSetMemory(spip->rx.bdma, &dummyrx);
+ bdmaStreamSetTransactionSize(spip->rx.bdma, n);
+ bdmaStreamSetMode(spip->rx.bdma, spip->rxdmamode);
+
+ bdmaStreamSetMemory(spip->tx.bdma, &dummytx);
+ bdmaStreamSetTransactionSize(spip->tx.bdma, n);
+ bdmaStreamSetMode(spip->tx.bdma, spip->txdmamode);
+
+ bdmaStreamEnable(spip->rx.bdma);
+ bdmaStreamEnable(spip->tx.bdma);
+ }
+#endif
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ else
+#endif
+#if defined(STM32_SPI_DMA_REQUIRED)
+ {
+ dmaStreamSetMemory0(spip->rx.dma, &dummyrx);
+ dmaStreamSetTransactionSize(spip->rx.dma, n);
+ dmaStreamSetMode(spip->rx.dma, spip->rxdmamode);
+
+ dmaStreamSetMemory0(spip->tx.dma, &dummytx);
+ dmaStreamSetTransactionSize(spip->tx.dma, n);
+ dmaStreamSetMode(spip->tx.dma, spip->txdmamode);
+
+ dmaStreamEnable(spip->rx.dma);
+ dmaStreamEnable(spip->tx.dma);
+ }
+#endif
+
+ spip->spi->CR1 |= SPI_CR1_CSTART;
+}
+
+/**
+ * @brief Exchanges data on the SPI bus.
+ * @details This asynchronous function starts a simultaneous transmit/receive
+ * operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be exchanged
+ * @param[in] txbuf the pointer to the transmit buffer
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void spi_lld_exchange(SPIDriver *spip, size_t n,
+ const void *txbuf, void *rxbuf) {
+
+ osalDbgAssert(n < 65536, "unsupported DMA transfer size");
+
+ spi_lld_wait_complete(spip);
+
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ if (spip->is_bdma)
+#endif
+#if defined(STM32_SPI_BDMA_REQUIRED)
+ {
+ bdmaStreamSetMemory(spip->rx.bdma, rxbuf);
+ bdmaStreamSetTransactionSize(spip->rx.bdma, n);
+ bdmaStreamSetMode(spip->rx.bdma, spip->rxdmamode | STM32_BDMA_CR_MINC);
+
+ bdmaStreamSetMemory(spip->tx.bdma, txbuf);
+ bdmaStreamSetTransactionSize(spip->tx.bdma, n);
+ bdmaStreamSetMode(spip->tx.bdma, spip->txdmamode | STM32_BDMA_CR_MINC);
+
+ bdmaStreamEnable(spip->rx.bdma);
+ bdmaStreamEnable(spip->tx.bdma);
+ }
+#endif
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ else
+#endif
+#if defined(STM32_SPI_DMA_REQUIRED)
+ {
+ dmaStreamSetMemory0(spip->rx.dma, rxbuf);
+ dmaStreamSetTransactionSize(spip->rx.dma, n);
+ dmaStreamSetMode(spip->rx.dma, spip->rxdmamode | STM32_DMA_CR_MINC);
+
+ dmaStreamSetMemory0(spip->tx.dma, txbuf);
+ dmaStreamSetTransactionSize(spip->tx.dma, n);
+ dmaStreamSetMode(spip->tx.dma, spip->txdmamode | STM32_DMA_CR_MINC);
+
+ dmaStreamEnable(spip->rx.dma);
+ dmaStreamEnable(spip->tx.dma);
+ }
+#endif
+
+ spip->spi->CR1 |= SPI_CR1_CSTART;
+}
+
+/**
+ * @brief Sends data over the SPI bus.
+ * @details This asynchronous function starts a transmit operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @notapi
+ */
+void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
+
+ osalDbgAssert(n < 65536, "unsupported DMA transfer size");
+
+ spi_lld_wait_complete(spip);
+
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ if (spip->is_bdma)
+#endif
+#if defined(STM32_SPI_BDMA_REQUIRED)
+ {
+ bdmaStreamSetMemory(spip->rx.bdma, &dummyrx);
+ bdmaStreamSetTransactionSize(spip->rx.bdma, n);
+ bdmaStreamSetMode(spip->rx.bdma, spip->rxdmamode);
+
+ bdmaStreamSetMemory(spip->tx.bdma, txbuf);
+ bdmaStreamSetTransactionSize(spip->tx.bdma, n);
+ bdmaStreamSetMode(spip->tx.bdma, spip->txdmamode | STM32_BDMA_CR_MINC);
+
+ bdmaStreamEnable(spip->rx.bdma);
+ bdmaStreamEnable(spip->tx.bdma);
+ }
+#endif
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ else
+#endif
+#if defined(STM32_SPI_DMA_REQUIRED)
+ {
+ dmaStreamSetMemory0(spip->rx.dma, &dummyrx);
+ dmaStreamSetTransactionSize(spip->rx.dma, n);
+ dmaStreamSetMode(spip->rx.dma, spip->rxdmamode);
+
+ dmaStreamSetMemory0(spip->tx.dma, txbuf);
+ dmaStreamSetTransactionSize(spip->tx.dma, n);
+ dmaStreamSetMode(spip->tx.dma, spip->txdmamode | STM32_DMA_CR_MINC);
+
+ dmaStreamEnable(spip->rx.dma);
+ dmaStreamEnable(spip->tx.dma);
+ }
+#endif
+
+ spip->spi->CR1 |= SPI_CR1_CSTART;
+}
+
+/**
+ * @brief Receives data from the SPI bus.
+ * @details This asynchronous function starts a receive operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to receive
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
+
+ osalDbgAssert(n < 65536, "unsupported DMA transfer size");
+
+ spi_lld_wait_complete(spip);
+
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ if (spip->is_bdma)
+#endif
+#if defined(STM32_SPI_BDMA_REQUIRED)
+ {
+ bdmaStreamSetMemory(spip->rx.bdma, rxbuf);
+ bdmaStreamSetTransactionSize(spip->rx.bdma, n);
+ bdmaStreamSetMode(spip->rx.bdma, spip->rxdmamode | STM32_BDMA_CR_MINC);
+
+ bdmaStreamSetMemory(spip->tx.bdma, &dummytx);
+ bdmaStreamSetTransactionSize(spip->tx.bdma, n);
+ bdmaStreamSetMode(spip->tx.bdma, spip->txdmamode);
+
+ bdmaStreamEnable(spip->rx.bdma);
+ bdmaStreamEnable(spip->tx.bdma);
+ }
+#endif
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ else
+#endif
+#if defined(STM32_SPI_DMA_REQUIRED)
+ {
+ dmaStreamSetMemory0(spip->rx.dma, rxbuf);
+ dmaStreamSetTransactionSize(spip->rx.dma, n);
+ dmaStreamSetMode(spip->rx.dma, spip->rxdmamode | STM32_DMA_CR_MINC);
+
+ dmaStreamSetMemory0(spip->tx.dma, &dummytx);
+ dmaStreamSetTransactionSize(spip->tx.dma, n);
+ dmaStreamSetMode(spip->tx.dma, spip->txdmamode);
+
+ dmaStreamEnable(spip->rx.dma);
+ dmaStreamEnable(spip->tx.dma);
+ }
+#endif
+
+ spip->spi->CR1 |= SPI_CR1_CSTART;
+}
+
+#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Aborts the ongoing SPI operation, if any.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_abort(SPIDriver *spip) {
+
+ /* Stopping SPI.*/
+ spip->spi->CR1 |= SPI_CR1_CSUSP;
+
+ spi_lld_wait_complete(spip);
+
+ /* Stopping DMAs.*/
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ if (spip->is_bdma)
+#endif
+#if defined(STM32_SPI_BDMA_REQUIRED)
+ {
+ bdmaStreamDisable(spip->tx.bdma);
+ bdmaStreamDisable(spip->rx.bdma);
+ }
+#endif
+#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+ else
+#endif
+#if defined(STM32_SPI_DMA_REQUIRED)
+ {
+ dmaStreamDisable(spip->tx.dma);
+ dmaStreamDisable(spip->rx.dma);
+ }
+#endif
+}
+#endif /* SPI_SUPPORTS_CIRCULAR == TRUE */
+
+/**
+ * @brief Exchanges one frame using a polled wait.
+ * @details This synchronous function exchanges one frame using a polled
+ * synchronization method. This function is useful when exchanging
+ * small amount of data on high speed channels, usually in this
+ * situation is much more efficient just wait for completion using
+ * polling than suspending the thread waiting for an interrupt.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] frame the data frame to send over the SPI bus
+ * @return The received data frame from the SPI bus.
+ *
+ * @notapi
+ */
+uint32_t spi_lld_polled_exchange(SPIDriver *spip, uint32_t frame) {
+ uint32_t dsize = (spip->spi->CFG1 & SPI_CFG1_DSIZE_Msk) + 1U;
+ uint32_t rxframe;
+
+ spi_lld_wait_complete(spip);
+
+ spip->spi->CR1 |= SPI_CR1_CSTART;
+
+ /* wait for room in TX FIFO.*/
+ while ((spip->spi->SR & SPI_SR_TXP) == 0U)
+ ;
+
+ /* Data register must be accessed with the appropriate data size.
+ Byte size access (uint8_t *) for transactions that are <= 8-bit etc.*/
+ if (dsize <= 8U) {
+ /* Frame width is between 4 and 8 bits.*/
+ volatile uint8_t *txdrp8 = (volatile uint8_t *)&spip->spi->TXDR;
+ volatile uint8_t *rxdrp8 = (volatile uint8_t *)&spip->spi->RXDR;
+ *txdrp8 = (uint8_t)frame;
+ while ((spip->spi->SR & SPI_SR_RXP) == 0U)
+ ;
+ rxframe = (uint32_t)*rxdrp8;
+ }
+ else if (dsize <= 16U) {
+ /* Frame width is between 9 and 16 bits.*/
+ volatile uint16_t *txdrp16 = (volatile uint16_t *)&spip->spi->TXDR;
+ volatile uint16_t *rxdrp16 = (volatile uint16_t *)&spip->spi->RXDR;
+ *txdrp16 = (uint16_t)frame;
+ while ((spip->spi->SR & SPI_SR_RXP) == 0U)
+ ;
+ rxframe = (uint32_t)*rxdrp16;
+ }
+ else {
+ /* Frame width is between 16 and 32 bits.*/
+ spip->spi->TXDR = frame;
+ while ((spip->spi->SR & SPI_SR_RXP) == 0U)
+ ;
+ rxframe = spip->spi->RXDR;
+ }
+
+ spip->spi->CR1 |= SPI_CR1_CSUSP;
+
+ return rxframe;
+}
+
+#endif /* HAL_USE_SPI */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.h
new file mode 100644
index 0000000..c906524
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.h
@@ -0,0 +1,590 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SPIv3/hal_spi_lld.h
+ * @brief STM32 SPI subsystem low level driver header.
+ *
+ * @addtogroup SPI
+ * @{
+ */
+
+#ifndef HAL_SPI_LLD_H
+#define HAL_SPI_LLD_H
+
+#if HAL_USE_SPI || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Circular mode support flag.
+ */
+#define SPI_SUPPORTS_CIRCULAR TRUE
+
+/**
+ * @name Register helpers not found in ST headers
+ * @{
+ */
+#define SPI_CFG1_MBR_VALUE(n) ((n) << SPI_CFG1_MBR_Pos)
+#define SPI_CFG1_MBR_DIV2 SPI_CFG1_MBR_VALUE(0)
+#define SPI_CFG1_MBR_DIV4 SPI_CFG1_MBR_VALUE(1)
+#define SPI_CFG1_MBR_DIV8 SPI_CFG1_MBR_VALUE(2)
+#define SPI_CFG1_MBR_DIV16 SPI_CFG1_MBR_VALUE(3)
+#define SPI_CFG1_MBR_DIV32 SPI_CFG1_MBR_VALUE(4)
+#define SPI_CFG1_MBR_DIV64 SPI_CFG1_MBR_VALUE(5)
+#define SPI_CFG1_MBR_DIV128 SPI_CFG1_MBR_VALUE(6)
+#define SPI_CFG1_MBR_DIV256 SPI_CFG1_MBR_VALUE(7)
+#define SPI_CFG1_CRCSIZE_VALUE(n) ((n) << SPI_CFG1_CRCSIZE_Pos)
+#define SPI_CFG1_UDRDET_VALUE(n) ((n) << SPI_CFG1_UDRDET_Pos)
+#define SPI_CFG1_UDRCFG_VALUE(n) ((n) << SPI_CFG1_UDRCFG_Pos)
+#define SPI_CFG1_FTHLV_VALUE(n) ((n) << SPI_CFG1_FTHLV_Pos)
+#define SPI_CFG1_DSIZE_VALUE(n) ((n) << SPI_CFG1_DSIZE_Pos)
+
+#define SPI_CFG2_SP_VALUE(n) ((n) << SPI_CFG2_SP_Pos)
+#define SPI_CFG2_COMM_VALUE(n) ((n) << SPI_CFG2_COMM_Pos)
+#define SPI_CFG2_COMM_FULL_DUPLEX SPI_CFG2_COMM_VALUE(0)
+#define SPI_CFG2_COMM_TRANSMITTER SPI_CFG2_COMM_VALUE(1)
+#define SPI_CFG2_COMM_RECEIVER SPI_CFG2_COMM_VALUE(2)
+#define SPI_CFG2_COMM_HALF_DUPLEX SPI_CFG2_COMM_VALUE(3)
+#define SPI_CFG2_MIDI_VALUE(n) ((n) << SPI_CFG2_MIDI_Pos)
+#define SPI_CFG2_MSSI_VALUE(n) ((n) << SPI_CFG2_MSSI_Pos)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief SPI1 driver enable switch.
+ * @details If set to @p TRUE the support for SPI1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SPI_USE_SPI1) || defined(__DOXYGEN__)
+#define STM32_SPI_USE_SPI1 FALSE
+#endif
+
+/**
+ * @brief SPI2 driver enable switch.
+ * @details If set to @p TRUE the support for SPI2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SPI_USE_SPI2) || defined(__DOXYGEN__)
+#define STM32_SPI_USE_SPI2 FALSE
+#endif
+
+/**
+ * @brief SPI3 driver enable switch.
+ * @details If set to @p TRUE the support for SPI3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SPI_USE_SPI3) || defined(__DOXYGEN__)
+#define STM32_SPI_USE_SPI3 FALSE
+#endif
+
+/**
+ * @brief SPI4 driver enable switch.
+ * @details If set to @p TRUE the support for SPI4 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SPI_USE_SPI4) || defined(__DOXYGEN__)
+#define STM32_SPI_USE_SPI4 FALSE
+#endif
+
+/**
+ * @brief SPI5 driver enable switch.
+ * @details If set to @p TRUE the support for SPI5 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SPI_USE_SPI5) || defined(__DOXYGEN__)
+#define STM32_SPI_USE_SPI5 FALSE
+#endif
+
+/**
+ * @brief SPI6 driver enable switch.
+ * @details If set to @p TRUE the support for SPI6 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SPI_USE_SPI6) || defined(__DOXYGEN__)
+#define STM32_SPI_USE_SPI6 FALSE
+#endif
+
+/**
+ * @brief Filler pattern used when there is nothing to transmit.
+ */
+#if !defined(STM32_SPI_FILLER_PATTERN) || defined(__DOXYGEN__)
+#define STM32_SPI_FILLER_PATTERN 0xFFFFFFFFU
+#endif
+
+/**
+ * @brief SPI1 interrupt priority level setting.
+ */
+#if !defined(STM32_SPI_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI1_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI2 interrupt priority level setting.
+ */
+#if !defined(STM32_SPI_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI2_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI3 interrupt priority level setting.
+ */
+#if !defined(STM32_SPI_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI3_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI4 interrupt priority level setting.
+ */
+#if !defined(STM32_SPI_SPI4_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI4_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI5 interrupt priority level setting.
+ */
+#if !defined(STM32_SPI_SPI5_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI5_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI6 interrupt priority level setting.
+ */
+#if !defined(STM32_SPI_SPI6_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI6_IRQ_PRIORITY 10
+#endif
+
+/**
+ * @brief SPI1 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_SPI_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI1_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI2 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_SPI_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI2_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI3 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_SPI_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI3_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI4 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_SPI_SPI4_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI4_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI5 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_SPI_SPI5_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI5_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI6 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA streams but
+ * because of the streams ordering the RX stream has always priority
+ * over the TX stream.
+ */
+#if !defined(STM32_SPI_SPI6_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SPI_SPI6_DMA_PRIORITY 1
+#endif
+
+/**
+ * @brief SPI DMA error hook.
+ */
+#if !defined(STM32_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if STM32_SPI_USE_SPI1 && !STM32_HAS_SPI1
+#error "SPI1 not present in the selected device"
+#endif
+
+#if STM32_SPI_USE_SPI2 && !STM32_HAS_SPI2
+#error "SPI2 not present in the selected device"
+#endif
+
+#if STM32_SPI_USE_SPI3 && !STM32_HAS_SPI3
+#error "SPI3 not present in the selected device"
+#endif
+
+#if STM32_SPI_USE_SPI4 && !STM32_HAS_SPI4
+#error "SPI4 not present in the selected device"
+#endif
+
+#if STM32_SPI_USE_SPI5 && !STM32_HAS_SPI5
+#error "SPI5 not present in the selected device"
+#endif
+
+#if STM32_SPI_USE_SPI6 && !STM32_HAS_SPI6
+#error "SPI6 not present in the selected device"
+#endif
+
+#if !STM32_SPI_USE_SPI1 && !STM32_SPI_USE_SPI2 && !STM32_SPI_USE_SPI3 && \
+ !STM32_SPI_USE_SPI4 && !STM32_SPI_USE_SPI5 && !STM32_SPI_USE_SPI6
+#error "SPI driver activated but no SPI peripheral assigned"
+#endif
+
+#if STM32_SPI_USE_SPI1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI1"
+#endif
+
+#if STM32_SPI_USE_SPI2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI2"
+#endif
+
+#if STM32_SPI_USE_SPI3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI3"
+#endif
+
+#if STM32_SPI_USE_SPI4 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI4_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI4"
+#endif
+
+#if STM32_SPI_USE_SPI5 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI5_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI5"
+#endif
+
+#if STM32_SPI_USE_SPI6 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI6_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to SPI6"
+#endif
+
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if STM32_SPI_USE_SPI1 && (!defined(STM32_SPI_SPI1_RX_DMA_STREAM) || \
+ !defined(STM32_SPI_SPI1_TX_DMA_STREAM))
+#error "SPI1 DMA streams not defined"
+#endif
+
+#if STM32_SPI_USE_SPI2 && (!defined(STM32_SPI_SPI2_RX_DMA_STREAM) || \
+ !defined(STM32_SPI_SPI2_TX_DMA_STREAM))
+#error "SPI2 DMA streams not defined"
+#endif
+
+#if STM32_SPI_USE_SPI3 && (!defined(STM32_SPI_SPI3_RX_DMA_STREAM) || \
+ !defined(STM32_SPI_SPI3_TX_DMA_STREAM))
+#error "SPI3 DMA streams not defined"
+#endif
+
+#if STM32_SPI_USE_SPI4 && (!defined(STM32_SPI_SPI4_RX_DMA_STREAM) || \
+ !defined(STM32_SPI_SPI4_TX_DMA_STREAM))
+#error "SPI4 DMA streams not defined"
+#endif
+
+#if STM32_SPI_USE_SPI5 && (!defined(STM32_SPI_SPI5_RX_DMA_STREAM) || \
+ !defined(STM32_SPI_SPI5_TX_DMA_STREAM))
+#error "SPI5 DMA streams not defined"
+#endif
+
+#if STM32_SPI_USE_SPI6 && (!defined(STM32_SPI_SPI6_RX_BDMA_STREAM) || \
+ !defined(STM32_SPI_SPI6_TX_BDMA_STREAM))
+#error "SPI6 BDMA streams not defined"
+#endif
+
+/* Check on the validity of the assigned DMA streams.*/
+#if STM32_SPI_USE_SPI1 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI1_RX_DMA_STREAM)
+#error "Invalid DMA stream assigned to SPI1 RX"
+#endif
+
+#if STM32_SPI_USE_SPI1 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM)
+#error "Invalid DMA stream assigned to SPI1 TX"
+#endif
+
+#if STM32_SPI_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI2_RX_DMA_STREAM)
+#error "Invalid DMA stream assigned to SPI2 RX"
+#endif
+
+#if STM32_SPI_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI2_TX_DMA_STREAM)
+#error "Invalid DMA stream assigned to SPI2 TX"
+#endif
+
+#if STM32_SPI_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI3_RX_DMA_STREAM)
+#error "Invalid DMA stream assigned to SPI3 RX"
+#endif
+
+#if STM32_SPI_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI3_TX_DMA_STREAM)
+#error "Invalid DMA stream assigned to SPI3 TX"
+#endif
+
+#if STM32_SPI_USE_SPI4 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI4_RX_DMA_STREAM)
+#error "Invalid DMA stream assigned to SPI4 RX"
+#endif
+
+#if STM32_SPI_USE_SPI4 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI4_TX_DMA_STREAM)
+#error "Invalid DMA stream assigned to SPI4 TX"
+#endif
+
+#if STM32_SPI_USE_SPI5 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI5_RX_DMA_STREAM)
+#error "Invalid DMA stream assigned to SPI5 RX"
+#endif
+
+#if STM32_SPI_USE_SPI5 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI5_TX_DMA_STREAM)
+#error "Invalid DMA stream assigned to SPI5 TX"
+#endif
+
+#if STM32_SPI_USE_SPI6 && \
+ !STM32_BDMA_IS_VALID_STREAM(STM32_SPI_SPI6_RX_BDMA_STREAM)
+#error "Invalid BDMA stream assigned to SPI6 RX"
+#endif
+
+#if STM32_SPI_USE_SPI6 && \
+ !STM32_BDMA_IS_VALID_STREAM(STM32_SPI_SPI6_TX_BDMA_STREAM)
+#error "Invalid BDMA stream assigned to SPI6 TX"
+#endif
+
+#if STM32_SPI_USE_SPI1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI1"
+#endif
+
+#if STM32_SPI_USE_SPI2 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI2"
+#endif
+
+#if STM32_SPI_USE_SPI3 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI3_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI3"
+#endif
+
+#if STM32_SPI_USE_SPI4 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI4_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI4"
+#endif
+
+#if STM32_SPI_USE_SPI5 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI5_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI5"
+#endif
+
+#if STM32_SPI_USE_SPI6 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI6_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to SPI6"
+#endif
+
+#if STM32_SPI_USE_SPI1 || STM32_SPI_USE_SPI2 || STM32_SPI_USE_SPI1 || \
+ STM32_SPI_USE_SPI4 || STM32_SPI_USE_SPI5
+#define STM32_SPI_DMA_REQUIRED
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+#endif
+
+#if STM32_SPI_USE_SPI6
+#define STM32_SPI_BDMA_REQUIRED
+#if !defined(STM32_BDMA_REQUIRED)
+#define STM32_BDMA_REQUIRED
+#endif
+#endif
+
+#if SPI_SELECT_MODE == SPI_SELECT_MODE_LLD
+#error "SPI_SELECT_MODE_LLD not supported by this driver"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+#if (defined(STM32_SPI_DMA_REQUIRED) && \
+ defined(STM32_SPI_BDMA_REQUIRED)) || defined(__DOXYGEN__)
+#define spi_lld_driver_fields \
+ /* Pointer to the SPIx registers block.*/ \
+ SPI_TypeDef *spi; \
+ /** DMA type for this instance.*/ \
+ bool is_bdma; \
+ /** Union of the RX DMA streams.*/ \
+ union { \
+ /* Receive DMA stream.*/ \
+ const stm32_dma_stream_t *dma; \
+ /* Receive BDMA stream.*/ \
+ const stm32_bdma_stream_t *bdma; \
+ } rx; \
+ /* Union of the TX DMA streams.*/ \
+ union { \
+ /* Transmit DMA stream.*/ \
+ const stm32_dma_stream_t *dma; \
+ /* Transmit DMA stream.*/ \
+ const stm32_bdma_stream_t *bdma; \
+ } tx; \
+ /* RX DMA mode bit mask.*/ \
+ uint32_t rxdmamode; \
+ /* TX DMA mode bit mask.*/ \
+ uint32_t txdmamode
+#endif
+
+#if defined(STM32_SPI_DMA_REQUIRED) && !defined(STM32_SPI_BDMA_REQUIRED)
+#define spi_lld_driver_fields \
+ /* Pointer to the SPIx registers block.*/ \
+ SPI_TypeDef *spi; \
+ /** Union of the RX DMA streams.*/ \
+ union { \
+ /* Receive DMA stream.*/ \
+ const stm32_dma_stream_t *dma; \
+ } rx; \
+ /* Union of the TX DMA streams.*/ \
+ union { \
+ /* Transmit DMA stream.*/ \
+ const stm32_dma_stream_t *dma; \
+ } tx; \
+ /* RX DMA mode bit mask.*/ \
+ uint32_t rxdmamode; \
+ /* TX DMA mode bit mask.*/ \
+ uint32_t txdmamode
+#endif
+
+#if !defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED)
+#define spi_lld_driver_fields \
+ /* Pointer to the SPIx registers block.*/ \
+ SPI_TypeDef *spi; \
+ /** Union of the RX DMA streams.*/ \
+ union { \
+ /* Receive BDMA stream.*/ \
+ const stm32_bdma_stream_t *bdma; \
+ } rx; \
+ /* Union of the TX DMA streams.*/ \
+ union { \
+ /* Transmit DMA stream.*/ \
+ const stm32_bdma_stream_t *bdma; \
+ } tx; \
+ /* RX DMA mode bit mask.*/ \
+ uint32_t rxdmamode; \
+ /* TX DMA mode bit mask.*/ \
+ uint32_t txdmamode
+#endif
+
+/**
+ * @brief Low level fields of the SPI configuration structure.
+ */
+#define spi_lld_config_fields \
+ /* SPI CFG1 register initialization data.*/ \
+ uint32_t cfg1; \
+ /* SPI CFG2 register initialization data.*/ \
+ uint32_t cfg2
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_SPI_USE_SPI1 && !defined(__DOXYGEN__)
+extern SPIDriver SPID1;
+#endif
+
+#if STM32_SPI_USE_SPI2 && !defined(__DOXYGEN__)
+extern SPIDriver SPID2;
+#endif
+
+#if STM32_SPI_USE_SPI3 && !defined(__DOXYGEN__)
+extern SPIDriver SPID3;
+#endif
+
+#if STM32_SPI_USE_SPI4 && !defined(__DOXYGEN__)
+extern SPIDriver SPID4;
+#endif
+
+#if STM32_SPI_USE_SPI5 && !defined(__DOXYGEN__)
+extern SPIDriver SPID5;
+#endif
+
+#if STM32_SPI_USE_SPI6 && !defined(__DOXYGEN__)
+extern SPIDriver SPID6;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void spi_lld_init(void);
+ void spi_lld_start(SPIDriver *spip);
+ void spi_lld_stop(SPIDriver *spip);
+#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__)
+ void spi_lld_select(SPIDriver *spip);
+ void spi_lld_unselect(SPIDriver *spip);
+#endif
+ void spi_lld_ignore(SPIDriver *spip, size_t n);
+ void spi_lld_exchange(SPIDriver *spip, size_t n,
+ const void *txbuf, void *rxbuf);
+ void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
+ void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
+#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__)
+ void spi_lld_abort(SPIDriver *spip);
+#endif
+ uint32_t spi_lld_polled_exchange(SPIDriver *spip, uint32_t frame);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SPI */
+
+#endif /* HAL_SPI_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/driver.mk
new file mode 100644
index 0000000..032d75a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/driver.mk
@@ -0,0 +1,19 @@
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c
+
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_GPT TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c
+endif
+ifneq ($(findstring HAL_USE_ICU TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c
+endif
+ifneq ($(findstring HAL_USE_PWM TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c
new file mode 100644
index 0000000..f7c449e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c
@@ -0,0 +1,1153 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/hal_gpt_lld.c
+ * @brief STM32 GPT subsystem low level driver source.
+ *
+ * @addtogroup GPT
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_GPT || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief GPTD1 driver identifier.
+ * @note The driver GPTD1 allocates the complex timer TIM1 when enabled.
+ */
+#if STM32_GPT_USE_TIM1 || defined(__DOXYGEN__)
+GPTDriver GPTD1;
+#endif
+
+/**
+ * @brief GPTD2 driver identifier.
+ * @note The driver GPTD2 allocates the timer TIM2 when enabled.
+ */
+#if STM32_GPT_USE_TIM2 || defined(__DOXYGEN__)
+GPTDriver GPTD2;
+#endif
+
+/**
+ * @brief GPTD3 driver identifier.
+ * @note The driver GPTD3 allocates the timer TIM3 when enabled.
+ */
+#if STM32_GPT_USE_TIM3 || defined(__DOXYGEN__)
+GPTDriver GPTD3;
+#endif
+
+/**
+ * @brief GPTD4 driver identifier.
+ * @note The driver GPTD4 allocates the timer TIM4 when enabled.
+ */
+#if STM32_GPT_USE_TIM4 || defined(__DOXYGEN__)
+GPTDriver GPTD4;
+#endif
+
+/**
+ * @brief GPTD5 driver identifier.
+ * @note The driver GPTD5 allocates the timer TIM5 when enabled.
+ */
+#if STM32_GPT_USE_TIM5 || defined(__DOXYGEN__)
+GPTDriver GPTD5;
+#endif
+
+/**
+ * @brief GPTD6 driver identifier.
+ * @note The driver GPTD6 allocates the timer TIM6 when enabled.
+ */
+#if STM32_GPT_USE_TIM6 || defined(__DOXYGEN__)
+GPTDriver GPTD6;
+#endif
+
+/**
+ * @brief GPTD7 driver identifier.
+ * @note The driver GPTD7 allocates the timer TIM7 when enabled.
+ */
+#if STM32_GPT_USE_TIM7 || defined(__DOXYGEN__)
+GPTDriver GPTD7;
+#endif
+
+/**
+ * @brief GPTD8 driver identifier.
+ * @note The driver GPTD8 allocates the timer TIM8 when enabled.
+ */
+#if STM32_GPT_USE_TIM8 || defined(__DOXYGEN__)
+GPTDriver GPTD8;
+#endif
+
+/**
+ * @brief GPTD9 driver identifier.
+ * @note The driver GPTD9 allocates the timer TIM9 when enabled.
+ */
+#if STM32_GPT_USE_TIM9 || defined(__DOXYGEN__)
+GPTDriver GPTD9;
+#endif
+
+/**
+ * @brief GPTD10 driver identifier.
+ * @note The driver GPTD10 allocates the timer TIM10 when enabled.
+ */
+#if STM32_GPT_USE_TIM10 || defined(__DOXYGEN__)
+GPTDriver GPTD10;
+#endif
+
+/**
+ * @brief GPTD11 driver identifier.
+ * @note The driver GPTD11 allocates the timer TIM11 when enabled.
+ */
+#if STM32_GPT_USE_TIM11 || defined(__DOXYGEN__)
+GPTDriver GPTD11;
+#endif
+
+/**
+ * @brief GPTD12 driver identifier.
+ * @note The driver GPTD12 allocates the timer TIM12 when enabled.
+ */
+#if STM32_GPT_USE_TIM12 || defined(__DOXYGEN__)
+GPTDriver GPTD12;
+#endif
+
+/**
+ * @brief GPTD13 driver identifier.
+ * @note The driver GPTD13 allocates the timer TIM13 when enabled.
+ */
+#if STM32_GPT_USE_TIM13 || defined(__DOXYGEN__)
+GPTDriver GPTD13;
+#endif
+
+/**
+ * @brief GPTD14 driver identifier.
+ * @note The driver GPTD14 allocates the timer TIM14 when enabled.
+ */
+#if STM32_GPT_USE_TIM14 || defined(__DOXYGEN__)
+GPTDriver GPTD14;
+#endif
+
+/**
+ * @brief GPTD15 driver identifier.
+ * @note The driver GPTD14 allocates the timer TIM14 when enabled.
+ */
+#if STM32_GPT_USE_TIM15 || defined(__DOXYGEN__)
+GPTDriver GPTD15;
+#endif
+
+/**
+ * @brief GPTD16 driver identifier.
+ * @note The driver GPTD14 allocates the timer TIM14 when enabled.
+ */
+#if STM32_GPT_USE_TIM16 || defined(__DOXYGEN__)
+GPTDriver GPTD16;
+#endif
+
+/**
+ * @brief GPTD17 driver identifier.
+ * @note The driver GPTD14 allocates the timer TIM14 when enabled.
+ */
+#if STM32_GPT_USE_TIM17 || defined(__DOXYGEN__)
+GPTDriver GPTD17;
+#endif
+
+/**
+ * @brief GPTD21 driver identifier.
+ * @note The driver GPTD21 allocates the timer TIM21 when enabled.
+ */
+#if STM32_GPT_USE_TIM21 || defined(__DOXYGEN__)
+GPTDriver GPTD21;
+#endif
+
+/**
+ * @brief GPTD22 driver identifier.
+ * @note The driver GPTD22 allocates the timer TIM22 when enabled.
+ */
+#if STM32_GPT_USE_TIM22 || defined(__DOXYGEN__)
+GPTDriver GPTD22;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_GPT_USE_TIM1 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM1_SUPPRESS_ISR)
+#if !defined(STM32_TIM1_UP_HANDLER)
+#error "STM32_TIM1_UP_HANDLER not defined"
+#endif
+/**
+ * @brief TIM1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ gpt_lld_serve_interrupt(&GPTD1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM1_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM1 */
+
+#if STM32_GPT_USE_TIM2 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM2_SUPPRESS_ISR)
+#if !defined(STM32_TIM2_HANDLER)
+#error "STM32_TIM2_HANDLER not defined"
+#endif
+/**
+ * @brief TIM2 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ gpt_lld_serve_interrupt(&GPTD2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM2_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM2 */
+
+#if STM32_GPT_USE_TIM3 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM3_SUPPRESS_ISR)
+#if !defined(STM32_TIM3_HANDLER)
+#error "STM32_TIM3_HANDLER not defined"
+#endif
+/**
+ * @brief TIM3 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ gpt_lld_serve_interrupt(&GPTD3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM3_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM3 */
+
+#if STM32_GPT_USE_TIM4 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM4_SUPPRESS_ISR)
+#if !defined(STM32_TIM4_HANDLER)
+#error "STM32_TIM4_HANDLER not defined"
+#endif
+/**
+ * @brief TIM4 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ gpt_lld_serve_interrupt(&GPTD4);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM4_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM4 */
+
+#if STM32_GPT_USE_TIM5 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM5_SUPPRESS_ISR)
+#if !defined(STM32_TIM5_HANDLER)
+#error "STM32_TIM5_HANDLER not defined"
+#endif
+/**
+ * @brief TIM5 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ gpt_lld_serve_interrupt(&GPTD5);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM5_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM5 */
+
+#if STM32_GPT_USE_TIM6 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM6_SUPPRESS_ISR)
+#if !defined(STM32_TIM6_HANDLER)
+#error "STM32_TIM6_HANDLER not defined"
+#endif
+/**
+ * @brief TIM6 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM6_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ gpt_lld_serve_interrupt(&GPTD6);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM6_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM6 */
+
+#if STM32_GPT_USE_TIM7 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM7_SUPPRESS_ISR)
+#if !defined(STM32_TIM7_HANDLER)
+#error "STM32_TIM7_HANDLER not defined"
+#endif
+/**
+ * @brief TIM7 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM7_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ gpt_lld_serve_interrupt(&GPTD7);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM7_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM7 */
+
+#if STM32_GPT_USE_TIM8 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM8_SUPPRESS_ISR)
+#if !defined(STM32_TIM8_UP_HANDLER)
+#error "STM32_TIM8_UP_HANDLER not defined"
+#endif
+/**
+ * @brief TIM8 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ gpt_lld_serve_interrupt(&GPTD8);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM8_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM8 */
+
+#if STM32_GPT_USE_TIM9 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM9_SUPPRESS_ISR)
+#error "TIM9 ISR not defined by platform"
+#endif /* !defined(STM32_TIM9_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM9 */
+
+#if STM32_GPT_USE_TIM10 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM10_SUPPRESS_ISR)
+#error "TIM10 ISR not defined by platform"
+#endif /* !defined(STM32_TIM10_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM10 */
+
+#if STM32_GPT_USE_TIM11 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM11_SUPPRESS_ISR)
+#error "TIM11 ISR not defined by platform"
+#endif /* !defined(STM32_TIM11_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM11 */
+
+#if STM32_GPT_USE_TIM12 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM12_SUPPRESS_ISR)
+#error "TIM12 ISR not defined by platform"
+#endif /* !defined(STM32_TIM12_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM12 */
+
+#if STM32_GPT_USE_TIM13 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM13_SUPPRESS_ISR)
+#error "TIM13 ISR not defined by platform"
+#endif /* !defined(STM32_TIM13_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM13 */
+
+#if STM32_GPT_USE_TIM14 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM14_SUPPRESS_ISR)
+#error "TIM14 ISR not defined by platform"
+#endif /* !defined(STM32_TIM14_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM14 */
+
+#if STM32_GPT_USE_TIM15 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM15_SUPPRESS_ISR)
+#error "TIM15 ISR not defined by platform"
+#endif /* !defined(STM32_TIM15_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM15 */
+
+#if STM32_GPT_USE_TIM16 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM16_SUPPRESS_ISR)
+#error "TIM16 ISR not defined by platform"
+#endif /* !defined(STM32_TIM16_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM16 */
+
+#if STM32_GPT_USE_TIM17 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM17_SUPPRESS_ISR)
+#error "TIM17 ISR not defined by platform"
+#endif /* !defined(STM32_TIM17_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM17 */
+
+#if STM32_GPT_USE_TIM21 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM21_SUPPRESS_ISR)
+#if !defined(STM32_TIM21_HANDLER)
+#error "STM32_TIM21_HANDLER not defined"
+#endif
+/**
+ * @brief TIM21 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM21_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ gpt_lld_serve_interrupt(&GPTD21);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM21_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM21 */
+
+#if STM32_GPT_USE_TIM22 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM22_SUPPRESS_ISR)
+#if !defined(STM32_TIM22_HANDLER)
+#error "STM32_TIM22_HANDLER not defined"
+#endif
+/**
+ * @brief TIM22 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM22_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ gpt_lld_serve_interrupt(&GPTD22);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM22_SUPPRESS_ISR) */
+#endif /* STM32_GPT_USE_TIM22 */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level GPT driver initialization.
+ *
+ * @notapi
+ */
+void gpt_lld_init(void) {
+
+#if STM32_GPT_USE_TIM1
+ /* Driver initialization.*/
+ GPTD1.tim = STM32_TIM1;
+ gptObjectInit(&GPTD1);
+#endif
+
+#if STM32_GPT_USE_TIM2
+ /* Driver initialization.*/
+ GPTD2.tim = STM32_TIM2;
+ gptObjectInit(&GPTD2);
+#endif
+
+#if STM32_GPT_USE_TIM3
+ /* Driver initialization.*/
+ GPTD3.tim = STM32_TIM3;
+ gptObjectInit(&GPTD3);
+#endif
+
+#if STM32_GPT_USE_TIM4
+ /* Driver initialization.*/
+ GPTD4.tim = STM32_TIM4;
+ gptObjectInit(&GPTD4);
+#endif
+
+#if STM32_GPT_USE_TIM5
+ /* Driver initialization.*/
+ GPTD5.tim = STM32_TIM5;
+ gptObjectInit(&GPTD5);
+#endif
+
+#if STM32_GPT_USE_TIM6
+ /* Driver initialization.*/
+ GPTD6.tim = STM32_TIM6;
+ gptObjectInit(&GPTD6);
+#endif
+
+#if STM32_GPT_USE_TIM7
+ /* Driver initialization.*/
+ GPTD7.tim = STM32_TIM7;
+ gptObjectInit(&GPTD7);
+#endif
+
+#if STM32_GPT_USE_TIM8
+ /* Driver initialization.*/
+ GPTD8.tim = STM32_TIM8;
+ gptObjectInit(&GPTD8);
+#endif
+
+#if STM32_GPT_USE_TIM9
+ /* Driver initialization.*/
+ GPTD9.tim = STM32_TIM9;
+ gptObjectInit(&GPTD9);
+#endif
+
+#if STM32_GPT_USE_TIM10
+ /* Driver initialization.*/
+ GPTD10.tim = STM32_TIM10;
+ gptObjectInit(&GPTD10);
+#endif
+
+#if STM32_GPT_USE_TIM11
+ /* Driver initialization.*/
+ GPTD11.tim = STM32_TIM11;
+ gptObjectInit(&GPTD11);
+#endif
+
+#if STM32_GPT_USE_TIM12
+ /* Driver initialization.*/
+ GPTD12.tim = STM32_TIM12;
+ gptObjectInit(&GPTD12);
+#endif
+
+#if STM32_GPT_USE_TIM13
+ /* Driver initialization.*/
+ GPTD13.tim = STM32_TIM13;
+ gptObjectInit(&GPTD13);
+#endif
+
+#if STM32_GPT_USE_TIM14
+ /* Driver initialization.*/
+ GPTD14.tim = STM32_TIM14;
+ gptObjectInit(&GPTD14);
+#endif
+
+#if STM32_GPT_USE_TIM15
+ /* Driver initialization.*/
+ GPTD15.tim = STM32_TIM15;
+ gptObjectInit(&GPTD15);
+#endif
+
+#if STM32_GPT_USE_TIM16
+ /* Driver initialization.*/
+ GPTD16.tim = STM32_TIM16;
+ gptObjectInit(&GPTD16);
+#endif
+
+#if STM32_GPT_USE_TIM17
+ /* Driver initialization.*/
+ GPTD17.tim = STM32_TIM17;
+ gptObjectInit(&GPTD17);
+#endif
+
+#if STM32_GPT_USE_TIM21
+ /* Driver initialization.*/
+ GPTD21.tim = STM32_TIM21;
+ gptObjectInit(&GPTD21);
+#endif
+
+#if STM32_GPT_USE_TIM22
+ /* Driver initialization.*/
+ GPTD22.tim = STM32_TIM22;
+ gptObjectInit(&GPTD22);
+#endif
+}
+
+/**
+ * @brief Configures and activates the GPT peripheral.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ *
+ * @notapi
+ */
+void gpt_lld_start(GPTDriver *gptp) {
+ uint16_t psc;
+
+ if (gptp->state == GPT_STOP) {
+ /* Clock activation.*/
+#if STM32_GPT_USE_TIM1
+ if (&GPTD1 == gptp) {
+ rccEnableTIM1(true);
+ rccResetTIM1();
+#if !defined(STM32_TIM1_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_GPT_TIM1_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM1CLK)
+ gptp->clock = STM32_TIM1CLK;
+#else
+ gptp->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_GPT_USE_TIM2
+ if (&GPTD2 == gptp) {
+ rccEnableTIM2(true);
+ rccResetTIM2();
+#if !defined(STM32_TIM2_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM2_NUMBER, STM32_GPT_TIM2_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM2CLK)
+ gptp->clock = STM32_TIM2CLK;
+#else
+ gptp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_GPT_USE_TIM3
+ if (&GPTD3 == gptp) {
+ rccEnableTIM3(true);
+ rccResetTIM3();
+#if !defined(STM32_TIM3_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM3_NUMBER, STM32_GPT_TIM3_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM3CLK)
+ gptp->clock = STM32_TIM3CLK;
+#else
+ gptp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_GPT_USE_TIM4
+ if (&GPTD4 == gptp) {
+ rccEnableTIM4(true);
+ rccResetTIM4();
+#if !defined(STM32_TIM4_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM4_NUMBER, STM32_GPT_TIM4_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM4CLK)
+ gptp->clock = STM32_TIM4CLK;
+#else
+ gptp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_GPT_USE_TIM5
+ if (&GPTD5 == gptp) {
+ rccEnableTIM5(true);
+ rccResetTIM5();
+#if !defined(STM32_TIM5_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM5_NUMBER, STM32_GPT_TIM5_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM5CLK)
+ gptp->clock = STM32_TIM5CLK;
+#else
+ gptp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_GPT_USE_TIM6
+ if (&GPTD6 == gptp) {
+ rccEnableTIM6(true);
+ rccResetTIM6();
+#if !defined(STM32_TIM6_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM6_NUMBER, STM32_GPT_TIM6_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM6CLK)
+ gptp->clock = STM32_TIM6CLK;
+#else
+ gptp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_GPT_USE_TIM7
+ if (&GPTD7 == gptp) {
+ rccEnableTIM7(true);
+ rccResetTIM7();
+#if !defined(STM32_TIM7_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM7_NUMBER, STM32_GPT_TIM7_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM7CLK)
+ gptp->clock = STM32_TIM7CLK;
+#else
+ gptp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_GPT_USE_TIM8
+ if (&GPTD8 == gptp) {
+ rccEnableTIM8(true);
+ rccResetTIM8();
+#if !defined(STM32_TIM8_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_GPT_TIM8_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM8CLK)
+ gptp->clock = STM32_TIM8CLK;
+#else
+ gptp->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_GPT_USE_TIM9
+ if (&GPTD9 == gptp) {
+ rccEnableTIM9(true);
+ rccResetTIM9();
+#if !defined(STM32_TIM9_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM9_NUMBER, STM32_GPT_TIM9_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM9CLK)
+ gptp->clock = STM32_TIM9CLK;
+#else
+ gptp->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_GPT_USE_TIM10
+ if (&GPTD10 == gptp) {
+ rccEnableTIM10(true);
+ rccResetTIM10();
+#if !defined(STM32_TIM10_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM10_NUMBER, STM32_GPT_TIM10_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM10CLK)
+ gptp->clock = STM32_TIM10CLK;
+#else
+ gptp->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_GPT_USE_TIM11
+ if (&GPTD11 == gptp) {
+ rccEnableTIM11(true);
+ rccResetTIM11();
+#if !defined(STM32_TIM11_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM11_NUMBER, STM32_GPT_TIM11_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM11CLK)
+ gptp->clock = STM32_TIM11CLK;
+#else
+ gptp->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_GPT_USE_TIM12
+ if (&GPTD12 == gptp) {
+ rccEnableTIM12(true);
+ rccResetTIM12();
+#if !defined(STM32_TIM12_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM12_NUMBER, STM32_GPT_TIM12_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM12CLK)
+ gptp->clock = STM32_TIM12CLK;
+#else
+ gptp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_GPT_USE_TIM13
+ if (&GPTD13 == gptp) {
+ rccEnableTIM13(true);
+ rccResetTIM13();
+#if !defined(STM32_TIM13_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM13_NUMBER, STM32_GPT_TIM13_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM13CLK)
+ gptp->clock = STM32_TIM13CLK;
+#else
+ gptp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_GPT_USE_TIM14
+ if (&GPTD14 == gptp) {
+ rccEnableTIM14(true);
+ rccResetTIM14();
+#if !defined(STM32_TIM14_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM14_NUMBER, STM32_GPT_TIM14_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM14CLK)
+ gptp->clock = STM32_TIM14CLK;
+#else
+ gptp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_GPT_USE_TIM15
+ if (&GPTD15 == gptp) {
+ rccEnableTIM15(true);
+ rccResetTIM15();
+#if defined(STM32_TIM15CLK)
+ gptp->clock = STM32_TIM15CLK;
+#else
+ gptp->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_GPT_USE_TIM16
+ if (&GPTD16 == gptp) {
+ rccEnableTIM16(true);
+ rccResetTIM16();
+#if defined(STM32_TIM16CLK)
+ gptp->clock = STM32_TIM16CLK;
+#else
+ gptp->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_GPT_USE_TIM17
+ if (&GPTD17 == gptp) {
+ rccEnableTIM17(true);
+ rccResetTIM17();
+#if defined(STM32_TIM17CLK)
+ gptp->clock = STM32_TIM17CLK;
+#else
+ gptp->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_GPT_USE_TIM21
+ if (&GPTD21 == gptp) {
+ rccEnableTIM21(true);
+ rccResetTIM21();
+#if !defined(STM32_TIM21_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM21_NUMBER, STM32_GPT_TIM21_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM21CLK)
+ gptp->clock = STM32_TIM21CLK;
+#else
+ gptp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_GPT_USE_TIM22
+ if (&GPTD22 == gptp) {
+ rccEnableTIM22(true);
+ rccResetTIM22();
+#if !defined(STM32_TIM22_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM22_NUMBER, STM32_GPT_TIM22_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM22CLK)
+ gptp->clock = STM32_TIM22CLK;
+#else
+ gptp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+ }
+
+ /* Prescaler value calculation.*/
+ psc = (uint16_t)((gptp->clock / gptp->config->frequency) - 1);
+ osalDbgAssert(((uint32_t)(psc + 1) * gptp->config->frequency) == gptp->clock,
+ "invalid frequency");
+
+ /* Timer configuration.*/
+ gptp->tim->CR1 = 0; /* Initially stopped. */
+ gptp->tim->CR2 = gptp->config->cr2;
+ gptp->tim->PSC = psc; /* Prescaler value. */
+ gptp->tim->SR = 0; /* Clear pending IRQs. */
+ gptp->tim->DIER = gptp->config->dier & /* DMA-related DIER bits. */
+ ~STM32_TIM_DIER_IRQ_MASK;
+}
+
+/**
+ * @brief Deactivates the GPT peripheral.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ *
+ * @notapi
+ */
+void gpt_lld_stop(GPTDriver *gptp) {
+
+ if (gptp->state == GPT_READY) {
+ gptp->tim->CR1 = 0; /* Timer disabled. */
+ gptp->tim->DIER = 0; /* All IRQs disabled. */
+ gptp->tim->SR = 0; /* Clear pending IRQs. */
+
+#if STM32_GPT_USE_TIM1
+ if (&GPTD1 == gptp) {
+#if !defined(STM32_TIM1_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM1_UP_NUMBER);
+#endif
+ rccDisableTIM1();
+ }
+#endif
+
+#if STM32_GPT_USE_TIM2
+ if (&GPTD2 == gptp) {
+#if !defined(STM32_TIM2_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM2_NUMBER);
+#endif
+ rccDisableTIM2();
+ }
+#endif
+
+#if STM32_GPT_USE_TIM3
+ if (&GPTD3 == gptp) {
+#if !defined(STM32_TIM3_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM3_NUMBER);
+#endif
+ rccDisableTIM3();
+ }
+#endif
+
+#if STM32_GPT_USE_TIM4
+ if (&GPTD4 == gptp) {
+#if !defined(STM32_TIM4_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM4_NUMBER);
+#endif
+ rccDisableTIM4();
+ }
+#endif
+
+#if STM32_GPT_USE_TIM5
+ if (&GPTD5 == gptp) {
+#if !defined(STM32_TIM5_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM5_NUMBER);
+#endif
+ rccDisableTIM5();
+ }
+#endif
+
+#if STM32_GPT_USE_TIM6
+ if (&GPTD6 == gptp) {
+#if !defined(STM32_TIM6_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM6_NUMBER);
+#endif
+ rccDisableTIM6();
+ }
+#endif
+
+#if STM32_GPT_USE_TIM7
+ if (&GPTD7 == gptp) {
+#if !defined(STM32_TIM7_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM7_NUMBER);
+#endif
+ rccDisableTIM7();
+ }
+#endif
+
+#if STM32_GPT_USE_TIM8
+ if (&GPTD8 == gptp) {
+#if !defined(STM32_TIM8_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM8_UP_NUMBER);
+#endif
+ rccDisableTIM8();
+ }
+#endif
+
+#if STM32_GPT_USE_TIM9
+ if (&GPTD9 == gptp) {
+#if !defined(STM32_TIM9_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM9_NUMBER);
+#endif
+ rccDisableTIM9();
+ }
+#endif
+
+#if STM32_GPT_USE_TIM10
+ if (&GPTD10 == gptp) {
+#if !defined(STM32_TIM10_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM10_NUMBER);
+#endif
+ rccDisableTIM10();
+ }
+#endif
+
+#if STM32_GPT_USE_TIM11
+ if (&GPTD11 == gptp) {
+#if !defined(STM32_TIM11_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM11_NUMBER);
+#endif
+ rccDisableTIM11();
+ }
+#endif
+
+#if STM32_GPT_USE_TIM12
+ if (&GPTD12 == gptp) {
+#if !defined(STM32_TIM12_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM12_NUMBER);
+#endif
+ rccDisableTIM12();
+ }
+#endif
+
+#if STM32_GPT_USE_TIM13
+ if (&GPTD13 == gptp) {
+#if !defined(STM32_TIM13_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM13_NUMBER);
+#endif
+ rccDisableTIM13();
+ }
+#endif
+
+#if STM32_GPT_USE_TIM14
+ if (&GPTD14 == gptp) {
+#if !defined(STM32_TIM14_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM14_NUMBER);
+#endif
+ rccDisableTIM14();
+ }
+#endif
+
+#if STM32_GPT_USE_TIM15
+ if (&GPTD15 == gptp) {
+ rccDisableTIM15();
+ }
+#endif
+
+#if STM32_GPT_USE_TIM16
+ if (&GPTD16 == gptp) {
+ rccDisableTIM16();
+ }
+#endif
+
+#if STM32_GPT_USE_TIM17
+ if (&GPTD17 == gptp) {
+ rccDisableTIM17();
+ }
+#endif
+
+#if STM32_GPT_USE_TIM21
+ if (&GPTD21 == gptp) {
+#if !defined(STM32_TIM21_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM21_NUMBER);
+#endif
+ rccDisableTIM21();
+ }
+#endif
+
+#if STM32_GPT_USE_TIM22
+ if (&GPTD22 == gptp) {
+#if !defined(STM32_TIM22_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM22_NUMBER);
+#endif
+ rccDisableTIM22();
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Starts the timer in continuous mode.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ * @param[in] interval period in ticks
+ *
+ * @notapi
+ */
+void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval) {
+
+ gptp->tim->ARR = (uint32_t)(interval - 1U); /* Time constant. */
+ gptp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */
+ gptp->tim->CNT = 0; /* Reset counter. */
+
+ /* NOTE: After generating the UG event it takes several clock cycles before
+ SR bit 0 goes to 1. This is why the clearing of CNT has been inserted
+ before the clearing of SR, to give it some time.*/
+ gptp->tim->SR = 0; /* Clear pending IRQs. */
+ if (NULL != gptp->config->callback)
+ gptp->tim->DIER |= STM32_TIM_DIER_UIE; /* Update Event IRQ enabled.*/
+ gptp->tim->CR1 = STM32_TIM_CR1_ARPE | STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN;
+}
+
+/**
+ * @brief Stops the timer.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ *
+ * @notapi
+ */
+void gpt_lld_stop_timer(GPTDriver *gptp) {
+
+ gptp->tim->CR1 = 0; /* Initially stopped. */
+ gptp->tim->SR = 0; /* Clear pending IRQs. */
+
+ /* All interrupts disabled.*/
+ gptp->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK;
+}
+
+/**
+ * @brief Starts the timer in one shot mode and waits for completion.
+ * @details This function specifically polls the timer waiting for completion
+ * in order to not have extra delays caused by interrupt servicing,
+ * this function is only recommended for short delays.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ * @param[in] interval time interval in ticks
+ *
+ * @notapi
+ */
+void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval) {
+
+ gptp->tim->ARR = (uint32_t)(interval - 1U); /* Time constant. */
+ gptp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */
+ gptp->tim->SR = 0; /* Clear pending IRQs. */
+ gptp->tim->CR1 = STM32_TIM_CR1_OPM | STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN;
+ while (!(gptp->tim->SR & STM32_TIM_SR_UIF))
+ ;
+ gptp->tim->SR = 0; /* Clear pending IRQs. */
+}
+
+/**
+ * @brief Shared IRQ handler.
+ *
+ * @param[in] gptp pointer to a @p GPTDriver object
+ *
+ * @notapi
+ */
+void gpt_lld_serve_interrupt(GPTDriver *gptp) {
+ uint32_t sr;
+
+ sr = gptp->tim->SR;
+ sr &= gptp->tim->DIER & STM32_TIM_DIER_IRQ_MASK;
+ gptp->tim->SR = ~sr;
+ if ((sr & STM32_TIM_SR_UIF) != 0) {
+ _gpt_isr_invoke_cb(gptp);
+ }
+}
+
+#endif /* HAL_USE_GPT */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.h
new file mode 100644
index 0000000..1fbdea3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.h
@@ -0,0 +1,980 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/hal_gpt_lld.h
+ * @brief STM32 GPT subsystem low level driver header.
+ *
+ * @addtogroup GPT
+ * @{
+ */
+
+#ifndef HAL_GPT_LLD_H
+#define HAL_GPT_LLD_H
+
+#include "stm32_tim.h"
+
+#if HAL_USE_GPT || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief GPTD1 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM1) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM1 FALSE
+#endif
+
+/**
+ * @brief GPTD2 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM2) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM2 FALSE
+#endif
+
+/**
+ * @brief GPTD3 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM3) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM3 FALSE
+#endif
+
+/**
+ * @brief GPTD4 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD4 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM4) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM4 FALSE
+#endif
+
+/**
+ * @brief GPTD5 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD5 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM5) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM5 FALSE
+#endif
+
+/**
+ * @brief GPTD6 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD6 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM6) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM6 FALSE
+#endif
+
+/**
+ * @brief GPTD7 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD7 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM7) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM7 FALSE
+#endif
+
+/**
+ * @brief GPTD8 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD8 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM8) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM8 FALSE
+#endif
+
+/**
+ * @brief GPTD9 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD9 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM9) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM9 FALSE
+#endif
+
+/**
+ * @brief GPTD10 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD10 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM10) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM10 FALSE
+#endif
+
+/**
+ * @brief GPTD11 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD11 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM11) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM11 FALSE
+#endif
+
+/**
+ * @brief GPTD12 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD12 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM12) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM12 FALSE
+#endif
+
+/**
+ * @brief GPTD13 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD13 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM13) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM13 FALSE
+#endif
+
+/**
+ * @brief GPTD14 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD14 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM14) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM14 FALSE
+#endif
+
+/**
+ * @brief GPTD14 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD15 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM15) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM15 FALSE
+#endif
+
+/**
+ * @brief GPTD14 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD16 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM16) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM16 FALSE
+#endif
+
+/**
+ * @brief GPTD14 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD17 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM17) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM17 FALSE
+#endif
+
+/**
+ * @brief GPTD21 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD21 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM21) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM21 FALSE
+#endif
+
+/**
+ * @brief GPTD22 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD22 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_GPT_USE_TIM22) || defined(__DOXYGEN__)
+#define STM32_GPT_USE_TIM22 FALSE
+#endif
+
+/**
+ * @brief GPTD1 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM1_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief GPTD2 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM2_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief GPTD3 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM3_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief GPTD4 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM4_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief GPTD5 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM5_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief GPTD6 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM6_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM6_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief GPTD7 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM7_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM7_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief GPTD8 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM8_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief GPTD9 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM9_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief GPTD10 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM10_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM10_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief GPTD11 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM11_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM11_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief GPTD12 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM12_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM12_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief GPTD13 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM13_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM13_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief GPTD14 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM14_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM14_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief GPTD15 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM15_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM15_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief GPTD16 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM16_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM16_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief GPTD17 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM17_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM17_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief GPTD21 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM21_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM21_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief GPTD22 interrupt priority level setting.
+ */
+#if !defined(STM32_GPT_TIM22_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_GPT_TIM22_IRQ_PRIORITY 7
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !defined(STM32_HAS_TIM1)
+#define STM32_HAS_TIM1 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM2)
+#define STM32_HAS_TIM2 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM3)
+#define STM32_HAS_TIM3 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM4)
+#define STM32_HAS_TIM4 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM5)
+#define STM32_HAS_TIM5 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM6)
+#define STM32_HAS_TIM6 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM7)
+#define STM32_HAS_TIM7 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM8)
+#define STM32_HAS_TIM8 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM9)
+#define STM32_HAS_TIM9 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM10)
+#define STM32_HAS_TIM10 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM11)
+#define STM32_HAS_TIM11 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM12)
+#define STM32_HAS_TIM12 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM13)
+#define STM32_HAS_TIM13 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM14)
+#define STM32_HAS_TIM14 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM15)
+#define STM32_HAS_TIM15 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM16)
+#define STM32_HAS_TIM16 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM17)
+#define STM32_HAS_TIM17 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM21)
+#define STM32_HAS_TIM21 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM22)
+#define STM32_HAS_TIM22 FALSE
+#endif
+
+#if STM32_GPT_USE_TIM1 && !STM32_HAS_TIM1
+#error "TIM1 not present in the selected device"
+#endif
+
+#if STM32_GPT_USE_TIM2 && !STM32_HAS_TIM2
+#error "TIM2 not present in the selected device"
+#endif
+
+#if STM32_GPT_USE_TIM3 && !STM32_HAS_TIM3
+#error "TIM3 not present in the selected device"
+#endif
+
+#if STM32_GPT_USE_TIM4 && !STM32_HAS_TIM4
+#error "TIM4 not present in the selected device"
+#endif
+
+#if STM32_GPT_USE_TIM5 && !STM32_HAS_TIM5
+#error "TIM5 not present in the selected device"
+#endif
+
+#if STM32_GPT_USE_TIM6 && !STM32_HAS_TIM6
+#error "TIM6 not present in the selected device"
+#endif
+
+#if STM32_GPT_USE_TIM7 && !STM32_HAS_TIM7
+#error "TIM7 not present in the selected device"
+#endif
+
+#if STM32_GPT_USE_TIM8 && !STM32_HAS_TIM8
+#error "TIM8 not present in the selected device"
+#endif
+
+#if STM32_GPT_USE_TIM9 && !STM32_HAS_TIM9
+#error "TIM9 not present in the selected device"
+#endif
+
+#if STM32_GPT_USE_TIM10 && !STM32_HAS_TIM10
+#error "TIM10 not present in the selected device"
+#endif
+
+#if STM32_GPT_USE_TIM11 && !STM32_HAS_TIM11
+#error "TIM11 not present in the selected device"
+#endif
+
+#if STM32_GPT_USE_TIM12 && !STM32_HAS_TIM12
+#error "TIM12 not present in the selected device"
+#endif
+
+#if STM32_GPT_USE_TIM13 && !STM32_HAS_TIM13
+#error "TIM13 not present in the selected device"
+#endif
+
+#if STM32_GPT_USE_TIM14 && !STM32_HAS_TIM14
+#error "TIM14 not present in the selected device"
+#endif
+
+#if STM32_GPT_USE_TIM15 && !STM32_HAS_TIM15
+#error "TIM15 not present in the selected device"
+#endif
+
+#if STM32_GPT_USE_TIM16 && !STM32_HAS_TIM16
+#error "TIM16 not present in the selected device"
+#endif
+
+#if STM32_GPT_USE_TIM17 && !STM32_HAS_TIM17
+#error "TIM17 not present in the selected device"
+#endif
+
+#if STM32_GPT_USE_TIM21 && !STM32_HAS_TIM21
+#error "TIM21 not present in the selected device"
+#endif
+
+#if STM32_GPT_USE_TIM22 && !STM32_HAS_TIM22
+#error "TIM22 not present in the selected device"
+#endif
+
+#if !STM32_GPT_USE_TIM1 && !STM32_GPT_USE_TIM2 && \
+ !STM32_GPT_USE_TIM3 && !STM32_GPT_USE_TIM4 && \
+ !STM32_GPT_USE_TIM5 && !STM32_GPT_USE_TIM6 && \
+ !STM32_GPT_USE_TIM7 && !STM32_GPT_USE_TIM8 && \
+ !STM32_GPT_USE_TIM9 && !STM32_GPT_USE_TIM10 && \
+ !STM32_GPT_USE_TIM11 && !STM32_GPT_USE_TIM12 && \
+ !STM32_GPT_USE_TIM13 && !STM32_GPT_USE_TIM14 && \
+ !STM32_GPT_USE_TIM15 && !STM32_GPT_USE_TIM16 && \
+ !STM32_GPT_USE_TIM17 && \
+ !STM32_GPT_USE_TIM21 && !STM32_GPT_USE_TIM22
+#error "GPT driver activated but no TIM peripheral assigned"
+#endif
+
+/* Checks on allocation of TIMx units.*/
+#if STM32_GPT_USE_TIM1
+#if defined(STM32_TIM1_IS_USED)
+#error "GPTD1 requires TIM1 but the timer is already used"
+#else
+#define STM32_TIM1_IS_USED
+#endif
+#endif
+
+#if STM32_GPT_USE_TIM2
+#if defined(STM32_TIM2_IS_USED)
+#error "GPTD2 requires TIM2 but the timer is already used"
+#else
+#define STM32_TIM2_IS_USED
+#endif
+#endif
+
+#if STM32_GPT_USE_TIM3
+#if defined(STM32_TIM3_IS_USED)
+#error "GPTD3 requires TIM3 but the timer is already used"
+#else
+#define STM32_TIM3_IS_USED
+#endif
+#endif
+
+#if STM32_GPT_USE_TIM4
+#if defined(STM32_TIM4_IS_USED)
+#error "GPTD4 requires TIM4 but the timer is already used"
+#else
+#define STM32_TIM4_IS_USED
+#endif
+#endif
+
+#if STM32_GPT_USE_TIM5
+#if defined(STM32_TIM5_IS_USED)
+#error "GPTD5 requires TIM5 but the timer is already used"
+#else
+#define STM32_TIM5_IS_USED
+#endif
+#endif
+
+#if STM32_GPT_USE_TIM6
+#if defined(STM32_TIM6_IS_USED)
+#error "GPTD6 requires TIM6 but the timer is already used"
+#else
+#define STM32_TIM6_IS_USED
+#endif
+#endif
+
+#if STM32_GPT_USE_TIM7
+#if defined(STM32_TIM7_IS_USED)
+#error "GPTD7 requires TIM7 but the timer is already used"
+#else
+#define STM32_TIM7_IS_USED
+#endif
+#endif
+
+#if STM32_GPT_USE_TIM8
+#if defined(STM32_TIM8_IS_USED)
+#error "GPTD8 requires TIM8 but the timer is already used"
+#else
+#define STM32_TIM8_IS_USED
+#endif
+#endif
+
+#if STM32_GPT_USE_TIM9
+#if defined(STM32_TIM9_IS_USED)
+#error "GPTD9 requires TIM9 but the timer is already used"
+#else
+#define STM32_TIM9_IS_USED
+#endif
+#endif
+
+#if STM32_GPT_USE_TIM10
+#if defined(STM32_TIM10_IS_USED)
+#error "GPTD10 requires TIM10 but the timer is already used"
+#else
+#define STM32_TIM10_IS_USED
+#endif
+#endif
+
+#if STM32_GPT_USE_TIM11
+#if defined(STM32_TIM11_IS_USED)
+#error "GPTD11 requires TIM11 but the timer is already used"
+#else
+#define STM32_TIM11_IS_USED
+#endif
+#endif
+
+#if STM32_GPT_USE_TIM12
+#if defined(STM32_TIM12_IS_USED)
+#error "GPTD12 requires TIM12 but the timer is already used"
+#else
+#define STM32_TIM12_IS_USED
+#endif
+#endif
+
+#if STM32_GPT_USE_TIM13
+#if defined(STM32_TIM13_IS_USED)
+#error "GPTD13 requires TIM13 but the timer is already used"
+#else
+#define STM32_TIM13_IS_USED
+#endif
+#endif
+
+#if STM32_GPT_USE_TIM14
+#if defined(STM32_TIM14_IS_USED)
+#error "GPTD14 requires TIM14 but the timer is already used"
+#else
+#define STM32_TIM14_IS_USED
+#endif
+#endif
+
+#if STM32_GPT_USE_TIM15
+#if defined(STM32_TIM15_IS_USED)
+#error "GPTD14 requires TIM15 but the timer is already used"
+#else
+#define STM32_TIM15_IS_USED
+#endif
+#endif
+
+#if STM32_GPT_USE_TIM16
+#if defined(STM32_TIM16_IS_USED)
+#error "GPTD14 requires TIM16 but the timer is already used"
+#else
+#define STM32_TIM16_IS_USED
+#endif
+#endif
+
+#if STM32_GPT_USE_TIM17
+#if defined(STM32_TIM17_IS_USED)
+#error "GPTD14 requires TIM17 but the timer is already used"
+#else
+#define STM32_TIM17_IS_USED
+#endif
+#endif
+
+#if STM32_GPT_USE_TIM21
+#if defined(STM32_TIM21_IS_USED)
+#error "GPTD21 requires TIM21 but the timer is already used"
+#else
+#define STM32_TIM21_IS_USED
+#endif
+#endif
+
+#if STM32_GPT_USE_TIM22
+#if defined(STM32_TIM22_IS_USED)
+#error "GPTD22 requires TIM22 but the timer is already used"
+#else
+#define STM32_TIM22_IS_USED
+#endif
+#endif
+
+/* IRQ priority checks.*/
+#if STM32_GPT_USE_TIM1 && !defined(STM32_TIM1_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM1"
+#endif
+
+#if STM32_GPT_USE_TIM2 && !defined(STM32_TIM2_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM2"
+#endif
+
+#if STM32_GPT_USE_TIM3 && !defined(STM32_TIM3_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM3"
+#endif
+
+#if STM32_GPT_USE_TIM4 && !defined(STM32_TIM_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM4_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM4"
+#endif
+
+#if STM32_GPT_USE_TIM5 && !defined(STM32_TIM5_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM5_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM5"
+#endif
+
+#if STM32_GPT_USE_TIM6 && !defined(STM32_TIM6_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM6_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM6"
+#endif
+
+#if STM32_GPT_USE_TIM7 && !defined(STM32_TIM7_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM7_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM7"
+#endif
+
+#if STM32_GPT_USE_TIM8 && !defined(STM32_TIM8_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM8_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM8"
+#endif
+
+#if STM32_GPT_USE_TIM9 && !defined(STM32_TIM9_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM9_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM9"
+#endif
+
+#if STM32_GPT_USE_TIM10 && !defined(STM32_TIM10_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM10_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM10"
+#endif
+
+#if STM32_GPT_USE_TIM11 && !defined(STM32_TIM11_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM11_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM11"
+#endif
+
+#if STM32_GPT_USE_TIM12 && !defined(STM32_TIM12_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM12_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM12"
+#endif
+
+#if STM32_GPT_USE_TIM13 && !defined(STM32_TIM13_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM13_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM13"
+#endif
+
+#if STM32_GPT_USE_TIM14 && !defined(STM32_TIM14_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM14_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM14"
+#endif
+
+#if STM32_GPT_USE_TIM15 && !defined(STM32_TIM15_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM15_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM15"
+#endif
+
+#if STM32_GPT_USE_TIM16 && !defined(STM32_TIM16_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM16_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM16"
+#endif
+
+#if STM32_GPT_USE_TIM17 && !defined(STM32_TIM17_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM17_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM17"
+#endif
+
+#if STM32_GPT_USE_TIM21 && !defined(STM32_TIM21_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM21_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM21"
+#endif
+
+#if STM32_GPT_USE_TIM22 && !defined(STM32_TIM22_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_GPT_TIM22_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM22"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief GPT frequency type.
+ */
+typedef uint32_t gptfreq_t;
+
+/**
+ * @brief GPT counter type.
+ */
+typedef uint32_t gptcnt_t;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+ /**
+ * @brief Timer clock in Hz.
+ * @note The low level can use assertions in order to catch invalid
+ * frequency specifications.
+ */
+ gptfreq_t frequency;
+ /**
+ * @brief Timer callback pointer.
+ * @note This callback is invoked on GPT counter events.
+ * @note This callback can be set to @p NULL but in that case the
+ * one-shot mode cannot be used.
+ */
+ gptcallback_t callback;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief TIM CR2 register initialization data.
+ * @note The value of this field should normally be equal to zero.
+ */
+ uint32_t cr2;
+ /**
+ * @brief TIM DIER register initialization data.
+ * @note The value of this field should normally be equal to zero.
+ * @note Only the DMA-related bits can be specified in this field.
+ */
+ uint32_t dier;
+} GPTConfig;
+
+/**
+ * @brief Structure representing a GPT driver.
+ */
+struct GPTDriver {
+ /**
+ * @brief Driver state.
+ */
+ gptstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const GPTConfig *config;
+#if defined(GPT_DRIVER_EXT_FIELDS)
+ GPT_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Timer base clock.
+ */
+ uint32_t clock;
+ /**
+ * @brief Pointer to the TIMx registers block.
+ */
+ stm32_tim_t *tim;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Changes the interval of GPT peripheral.
+ * @details This function changes the interval of a running GPT unit.
+ * @pre The GPT unit must be running in continuous mode.
+ * @post The GPT unit interval is changed to the new value.
+ * @note The function has effect at the next cycle start.
+ *
+ * @param[in] gptp pointer to a @p GPTDriver object
+ * @param[in] interval new cycle time in timer ticks
+ *
+ * @notapi
+ */
+#define gpt_lld_change_interval(gptp, interval) \
+ ((gptp)->tim->ARR = (uint32_t)((interval) - 1U))
+
+/**
+ * @brief Returns the interval of GPT peripheral.
+ * @pre The GPT unit must be running in continuous mode.
+ *
+ * @param[in] gptp pointer to a @p GPTDriver object
+ * @return The current interval.
+ *
+ * @notapi
+ */
+#define gpt_lld_get_interval(gptp) ((gptcnt_t)((gptp)->tim->ARR + 1U))
+
+/**
+ * @brief Returns the counter value of GPT peripheral.
+ * @pre The GPT unit must be running in continuous mode.
+ * @note The nature of the counter is not defined, it may count upward
+ * or downward, it could be continuously running or not.
+ *
+ * @param[in] gptp pointer to a @p GPTDriver object
+ * @return The current counter value.
+ *
+ * @notapi
+ */
+#define gpt_lld_get_counter(gptp) ((gptcnt_t)(gptp)->tim->CNT)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_GPT_USE_TIM1 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD1;
+#endif
+
+#if STM32_GPT_USE_TIM2 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD2;
+#endif
+
+#if STM32_GPT_USE_TIM3 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD3;
+#endif
+
+#if STM32_GPT_USE_TIM4 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD4;
+#endif
+
+#if STM32_GPT_USE_TIM5 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD5;
+#endif
+
+#if STM32_GPT_USE_TIM6 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD6;
+#endif
+
+#if STM32_GPT_USE_TIM7 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD7;
+#endif
+
+#if STM32_GPT_USE_TIM8 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD8;
+#endif
+
+#if STM32_GPT_USE_TIM9 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD9;
+#endif
+
+#if STM32_GPT_USE_TIM10 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD10;
+#endif
+
+#if STM32_GPT_USE_TIM11 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD11;
+#endif
+
+#if STM32_GPT_USE_TIM12 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD12;
+#endif
+
+#if STM32_GPT_USE_TIM13 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD13;
+#endif
+
+#if STM32_GPT_USE_TIM14 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD14;
+#endif
+
+#if STM32_GPT_USE_TIM15 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD15;
+#endif
+
+#if STM32_GPT_USE_TIM16 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD16;
+#endif
+
+#if STM32_GPT_USE_TIM17 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD17;
+#endif
+
+#if STM32_GPT_USE_TIM21 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD21;
+#endif
+
+#if STM32_GPT_USE_TIM22 && !defined(__DOXYGEN__)
+extern GPTDriver GPTD22;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void gpt_lld_init(void);
+ void gpt_lld_start(GPTDriver *gptp);
+ void gpt_lld_stop(GPTDriver *gptp);
+ void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t period);
+ void gpt_lld_stop_timer(GPTDriver *gptp);
+ void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval);
+ void gpt_lld_serve_interrupt(GPTDriver *gptp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_GPT */
+
+#endif /* HAL_GPT_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c
new file mode 100644
index 0000000..e9a669d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c
@@ -0,0 +1,1135 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Fabio Utzig and
+ Xo Wang.
+ */
+
+/**
+ * @file TIMv1/hal_icu_lld.c
+ * @brief STM32 ICU subsystem low level driver header.
+ *
+ * @addtogroup ICU
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_ICU || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief ICUD1 driver identifier.
+ * @note The driver ICUD1 allocates the complex timer TIM1 when enabled.
+ */
+#if STM32_ICU_USE_TIM1 || defined(__DOXYGEN__)
+ICUDriver ICUD1;
+#endif
+
+/**
+ * @brief ICUD2 driver identifier.
+ * @note The driver ICUD1 allocates the timer TIM2 when enabled.
+ */
+#if STM32_ICU_USE_TIM2 || defined(__DOXYGEN__)
+ICUDriver ICUD2;
+#endif
+
+/**
+ * @brief ICUD3 driver identifier.
+ * @note The driver ICUD1 allocates the timer TIM3 when enabled.
+ */
+#if STM32_ICU_USE_TIM3 || defined(__DOXYGEN__)
+ICUDriver ICUD3;
+#endif
+
+/**
+ * @brief ICUD4 driver identifier.
+ * @note The driver ICUD4 allocates the timer TIM4 when enabled.
+ */
+#if STM32_ICU_USE_TIM4 || defined(__DOXYGEN__)
+ICUDriver ICUD4;
+#endif
+
+/**
+ * @brief ICUD5 driver identifier.
+ * @note The driver ICUD5 allocates the timer TIM5 when enabled.
+ */
+#if STM32_ICU_USE_TIM5 || defined(__DOXYGEN__)
+ICUDriver ICUD5;
+#endif
+
+/**
+ * @brief ICUD8 driver identifier.
+ * @note The driver ICUD8 allocates the timer TIM8 when enabled.
+ */
+#if STM32_ICU_USE_TIM8 || defined(__DOXYGEN__)
+ICUDriver ICUD8;
+#endif
+
+/**
+ * @brief ICUD9 driver identifier.
+ * @note The driver ICUD9 allocates the timer TIM9 when enabled.
+ */
+#if STM32_ICU_USE_TIM9 || defined(__DOXYGEN__)
+ICUDriver ICUD9;
+#endif
+
+/**
+ * @brief ICUD10 driver identifier.
+ * @note The driver ICUD10 allocates the timer TIM10 when enabled.
+ */
+#if STM32_ICU_USE_TIM10 || defined(__DOXYGEN__)
+ICUDriver ICUD10;
+#endif
+
+/**
+ * @brief ICUD11 driver identifier.
+ * @note The driver ICUD11 allocates the timer TIM11 when enabled.
+ */
+#if STM32_ICU_USE_TIM11 || defined(__DOXYGEN__)
+ICUDriver ICUD11;
+#endif
+
+/**
+ * @brief ICUD12 driver identifier.
+ * @note The driver ICUD12 allocates the timer TIM12 when enabled.
+ */
+#if STM32_ICU_USE_TIM12 || defined(__DOXYGEN__)
+ICUDriver ICUD12;
+#endif
+
+/**
+ * @brief ICUD13 driver identifier.
+ * @note The driver ICUD13 allocates the timer TIM13 when enabled.
+ */
+#if STM32_ICU_USE_TIM13 || defined(__DOXYGEN__)
+ICUDriver ICUD13;
+#endif
+
+/**
+ * @brief ICUD14 driver identifier.
+ * @note The driver ICUD14 allocates the timer TIM14 when enabled.
+ */
+#if STM32_ICU_USE_TIM14 || defined(__DOXYGEN__)
+ICUDriver ICUD14;
+#endif
+
+/**
+ * @brief ICUD15 driver identifier.
+ * @note The driver ICUD15 allocates the timer TIM15 when enabled.
+ */
+#if STM32_ICU_USE_TIM15 || defined(__DOXYGEN__)
+ICUDriver ICUD15;
+#endif
+
+/**
+ * @brief ICUD20 driver identifier.
+ * @note The driver ICUD20 allocates the timer TIM20 when enabled.
+ */
+#if STM32_ICU_USE_TIM20 || defined(__DOXYGEN__)
+ICUDriver ICUD20;
+#endif
+
+/**
+ * @brief ICUD21 driver identifier.
+ * @note The driver ICUD21 allocates the timer TIM21 when enabled.
+ */
+#if STM32_ICU_USE_TIM21 || defined(__DOXYGEN__)
+ICUDriver ICUD21;
+#endif
+
+/**
+ * @brief ICUD22 driver identifier.
+ * @note The driver ICUD22 allocates the timer TIM22 when enabled.
+ */
+#if STM32_ICU_USE_TIM22 || defined(__DOXYGEN__)
+ICUDriver ICUD22;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static bool icu_lld_wait_edge(ICUDriver *icup) {
+ uint32_t sr;
+ bool result;
+
+ /* Polled mode so re-enabling the interrupts while the operation is
+ performed.*/
+ osalSysUnlock();
+
+ /* Polling the right bit depending on the input channel.*/
+ if (icup->config->channel == ICU_CHANNEL_1) {
+ /* Waiting for an edge.*/
+ while (((sr = icup->tim->SR) &
+ (STM32_TIM_SR_CC1IF | STM32_TIM_SR_UIF)) == 0)
+ ;
+ }
+ else {
+ /* Waiting for an edge.*/
+ while (((sr = icup->tim->SR) &
+ (STM32_TIM_SR_CC2IF | STM32_TIM_SR_UIF)) == 0)
+ ;
+ }
+
+ /* Edge or overflow?*/
+ result = (sr & STM32_TIM_SR_UIF) != 0 ? true : false;
+
+ /* Done, disabling interrupts again.*/
+ osalSysLock();
+
+ /* Resetting all flags.*/
+ icup->tim->SR &= ~(STM32_TIM_SR_CC1IF |
+ STM32_TIM_SR_CC2IF |
+ STM32_TIM_SR_UIF);
+
+ return result;
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_ICU_USE_TIM1 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM1_SUPPRESS_ISR)
+#if !defined(STM32_TIM1_UP_HANDLER)
+#error "STM32_TIM1_UP_HANDLER not defined"
+#endif
+/**
+ * @brief TIM1 compare interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#if !defined(STM32_TIM1_CC_HANDLER)
+#error "STM32_TIM1_CC_HANDLER not defined"
+#endif
+/**
+ * @brief TIM1 compare interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM1_SUPPRESS_ISR) */
+#endif /* STM32_ICU_USE_TIM1 */
+
+#if STM32_ICU_USE_TIM2 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM2_SUPPRESS_ISR)
+#if !defined(STM32_TIM2_HANDLER)
+#error "STM32_TIM2_HANDLER not defined"
+#endif
+/**
+ * @brief TIM2 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM2_SUPPRESS_ISR) */
+#endif /* STM32_ICU_USE_TIM2 */
+
+#if STM32_ICU_USE_TIM3 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM3_SUPPRESS_ISR)
+#if !defined(STM32_TIM3_HANDLER)
+#error "STM32_TIM3_HANDLER not defined"
+#endif
+/**
+ * @brief TIM3 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM3_SUPPRESS_ISR) */
+#endif /* STM32_ICU_USE_TIM3 */
+
+#if STM32_ICU_USE_TIM4 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM4_SUPPRESS_ISR)
+#if !defined(STM32_TIM4_HANDLER)
+#error "STM32_TIM4_HANDLER not defined"
+#endif
+/**
+ * @brief TIM4 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD4);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM4_SUPPRESS_ISR) */
+#endif /* STM32_ICU_USE_TIM4 */
+
+#if STM32_ICU_USE_TIM5 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM5_SUPPRESS_ISR)
+#if !defined(STM32_TIM5_HANDLER)
+#error "STM32_TIM5_HANDLER not defined"
+#endif
+/**
+ * @brief TIM5 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD5);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM5_SUPPRESS_ISR) */
+#endif /* STM32_ICU_USE_TIM5 */
+
+#if STM32_ICU_USE_TIM8 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM8_SUPPRESS_ISR)
+#if !defined(STM32_TIM8_UP_HANDLER)
+#error "STM32_TIM8_UP_HANDLER not defined"
+#endif
+/**
+ * @brief TIM8 compare interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD8);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#if !defined(STM32_TIM8_CC_HANDLER)
+#error "STM32_TIM8_CC_HANDLER not defined"
+#endif
+/**
+ * @brief TIM8 compare interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ icu_lld_serve_interrupt(&ICUD8);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM8_SUPPRESS_ISR) */
+#endif /* STM32_ICU_USE_TIM8 */
+
+#if STM32_ICU_USE_TIM9 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM9_SUPPRESS_ISR)
+#error "TIM9 ISR not defined by platform"
+#endif /* !defined(STM32_TIM9_SUPPRESS_ISR) */
+#endif /* STM32_ICU_USE_TIM9 */
+
+#if STM32_ICU_USE_TIM10 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM10_SUPPRESS_ISR)
+#error "TIM10 ISR not defined by platform"
+#endif /* !defined(STM32_TIM10_SUPPRESS_ISR) */
+#endif /* STM32_ICU_USE_TIM10 */
+
+#if STM32_ICU_USE_TIM11 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM11_SUPPRESS_ISR)
+#error "TIM11 ISR not defined by platform"
+#endif /* !defined(STM32_TIM11_SUPPRESS_ISR) */
+#endif /* STM32_ICU_USE_TIM11 */
+
+#if STM32_ICU_USE_TIM12 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM12_SUPPRESS_ISR)
+#error "TIM12 ISR not defined by platform"
+#endif /* !defined(STM32_TIM12_SUPPRESS_ISR) */
+#endif /* STM32_ICU_USE_TIM12 */
+
+#if STM32_ICU_USE_TIM13 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM13_SUPPRESS_ISR)
+#error "TIM13 ISR not defined by platform"
+#endif /* !defined(STM32_TIM13_SUPPRESS_ISR) */
+#endif /* STM32_ICU_USE_TIM13 */
+
+#if STM32_ICU_USE_TIM14 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM14_SUPPRESS_ISR)
+#error "TIM14 ISR not defined by platform"
+#endif /* !defined(STM32_TIM14_SUPPRESS_ISR) */
+#endif /* STM32_ICU_USE_TIM14 */
+
+#if STM32_ICU_USE_TIM15 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM15_SUPPRESS_ISR)
+#error "TIM15 ISR not defined by platform"
+#endif /* !defined(STM32_TIM15_SUPPRESS_ISR) */
+#endif /* STM32_ICU_USE_TIM15 */
+
+#if STM32_ICU_USE_TIM20 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM20_SUPPRESS_ISR)
+#error "TIM20 ISR not defined by platform"
+#endif /* !defined(STM32_TIM20_SUPPRESS_ISR) */
+#endif /* STM32_ICU_USE_TIM20 */
+
+#if STM32_ICU_USE_TIM21 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM21_SUPPRESS_ISR)
+#error "TIM21 ISR not defined by platform"
+#endif /* !defined(STM32_TIM21_SUPPRESS_ISR) */
+#endif /* STM32_ICU_USE_TIM21 */
+
+#if STM32_ICU_USE_TIM22 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM22_SUPPRESS_ISR)
+#error "TIM22 ISR not defined by platform"
+#endif /* !defined(STM32_TIM22_SUPPRESS_ISR) */
+#endif /* STM32_ICU_USE_TIM22 */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level ICU driver initialization.
+ *
+ * @notapi
+ */
+void icu_lld_init(void) {
+
+#if STM32_ICU_USE_TIM1
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD1);
+ ICUD1.tim = STM32_TIM1;
+#endif
+
+#if STM32_ICU_USE_TIM2
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD2);
+ ICUD2.tim = STM32_TIM2;
+#endif
+
+#if STM32_ICU_USE_TIM3
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD3);
+ ICUD3.tim = STM32_TIM3;
+#endif
+
+#if STM32_ICU_USE_TIM4
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD4);
+ ICUD4.tim = STM32_TIM4;
+#endif
+
+#if STM32_ICU_USE_TIM5
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD5);
+ ICUD5.tim = STM32_TIM5;
+#endif
+
+#if STM32_ICU_USE_TIM8
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD8);
+ ICUD8.tim = STM32_TIM8;
+#endif
+
+#if STM32_ICU_USE_TIM9
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD9);
+ ICUD9.tim = STM32_TIM9;
+#endif
+
+#if STM32_ICU_USE_TIM10
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD10);
+ ICUD10.tim = STM32_TIM10;
+#endif
+
+#if STM32_ICU_USE_TIM11
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD11);
+ ICUD11.tim = STM32_TIM11;
+#endif
+
+#if STM32_ICU_USE_TIM12
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD12);
+ ICUD12.tim = STM32_TIM12;
+#endif
+
+#if STM32_ICU_USE_TIM13
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD13);
+ ICUD13.tim = STM32_TIM13;
+#endif
+
+#if STM32_ICU_USE_TIM14
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD14);
+ ICUD14.tim = STM32_TIM14;
+#endif
+
+#if STM32_ICU_USE_TIM15
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD15);
+ ICUD15.tim = STM32_TIM15;
+#endif
+
+#if STM32_ICU_USE_TIM20
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD20);
+ ICUD20.tim = STM32_TIM20;
+#endif
+
+#if STM32_ICU_USE_TIM21
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD21);
+ ICUD21.tim = STM32_TIM21;
+#endif
+
+#if STM32_ICU_USE_TIM22
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD22);
+ ICUD22.tim = STM32_TIM22;
+#endif
+}
+
+/**
+ * @brief Configures and activates the ICU peripheral.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @notapi
+ */
+void icu_lld_start(ICUDriver *icup) {
+ uint32_t psc;
+
+ osalDbgAssert((icup->config->channel == ICU_CHANNEL_1) ||
+ (icup->config->channel == ICU_CHANNEL_2),
+ "invalid input");
+
+ if (icup->state == ICU_STOP) {
+ /* Clock activation and timer reset.*/
+#if STM32_ICU_USE_TIM1
+ if (&ICUD1 == icup) {
+ rccEnableTIM1(true);
+ rccResetTIM1();
+#if !defined(STM32_TIM1_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_ICU_TIM1_IRQ_PRIORITY);
+ nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_ICU_TIM1_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM1CLK)
+ icup->clock = STM32_TIM1CLK;
+#else
+ icup->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_ICU_USE_TIM2
+ if (&ICUD2 == icup) {
+ rccEnableTIM2(true);
+ rccResetTIM2();
+#if !defined(STM32_TIM2_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM2_NUMBER, STM32_ICU_TIM2_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM2CLK)
+ icup->clock = STM32_TIM2CLK;
+#else
+ icup->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_ICU_USE_TIM3
+ if (&ICUD3 == icup) {
+ rccEnableTIM3(true);
+ rccResetTIM3();
+#if !defined(STM32_TIM3_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM3_NUMBER, STM32_ICU_TIM3_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM3CLK)
+ icup->clock = STM32_TIM3CLK;
+#else
+ icup->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_ICU_USE_TIM4
+ if (&ICUD4 == icup) {
+ rccEnableTIM4(true);
+ rccResetTIM4();
+#if !defined(STM32_TIM4_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM4_NUMBER, STM32_ICU_TIM4_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM4CLK)
+ icup->clock = STM32_TIM4CLK;
+#else
+ icup->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_ICU_USE_TIM5
+ if (&ICUD5 == icup) {
+ rccEnableTIM5(true);
+ rccResetTIM5();
+#if !defined(STM32_TIM5_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM5_NUMBER, STM32_ICU_TIM5_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM5CLK)
+ icup->clock = STM32_TIM5CLK;
+#else
+ icup->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_ICU_USE_TIM8
+ if (&ICUD8 == icup) {
+ rccEnableTIM8(true);
+ rccResetTIM8();
+#if !defined(STM32_TIM8_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_ICU_TIM8_IRQ_PRIORITY);
+ nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_ICU_TIM8_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM8CLK)
+ icup->clock = STM32_TIM8CLK;
+#else
+ icup->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_ICU_USE_TIM9
+ if (&ICUD9 == icup) {
+ rccEnableTIM9(true);
+ rccResetTIM9();
+#if defined(STM32_TIM9CLK)
+ icup->clock = STM32_TIM9CLK;
+#else
+ icup->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_ICU_USE_TIM10
+ if (&ICUD10 == icup) {
+ rccEnableTIM10(true);
+ rccResetTIM10();
+#if defined(STM32_TIM10CLK)
+ icup->clock = STM32_TIM10CLK;
+#else
+ icup->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_ICU_USE_TIM11
+ if (&ICUD11 == icup) {
+ rccEnableTIM11(true);
+ rccResetTIM11();
+#if defined(STM32_TIM11CLK)
+ icup->clock = STM32_TIM11CLK;
+#else
+ icup->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_ICU_USE_TIM12
+ if (&ICUD12 == icup) {
+ rccEnableTIM12(true);
+ rccResetTIM12();
+#if defined(STM32_TIM12CLK)
+ icup->clock = STM32_TIM12CLK;
+#else
+ icup->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_ICU_USE_TIM13
+ if (&ICUD13 == icup) {
+ rccEnableTIM13(true);
+ rccResetTIM13();
+#if defined(STM32_TIM13CLK)
+ icup->clock = STM32_TIM13CLK;
+#else
+ icup->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_ICU_USE_TIM14
+ if (&ICUD14 == icup) {
+ rccEnableTIM14(true);
+ rccResetTIM14();
+#if defined(STM32_TIM14CLK)
+ icup->clock = STM32_TIM14CLK;
+#else
+ icup->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_ICU_USE_TIM15
+ if (&ICUD15 == icup) {
+ rccEnableTIM15(true);
+ rccResetTIM15();
+#if defined(STM32_TIM15CLK)
+ icup->clock = STM32_TIM15CLK;
+#else
+ icup->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_ICU_USE_TIM20
+ if (&ICUD20 == icup) {
+ rccEnableTIM20(true);
+ rccResetTIM20();
+#if defined(STM32_TIM20CLK)
+ icup->clock = STM32_TIM20CLK;
+#else
+ icup->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_ICU_USE_TIM21
+ if (&ICUD21 == icup) {
+ rccEnableTIM21(true);
+ rccResetTIM21();
+#if defined(STM32_TIM21CLK)
+ icup->clock = STM32_TIM21CLK;
+#else
+ icup->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_ICU_USE_TIM22
+ if (&ICUD22 == icup) {
+ rccEnableTIM22(true);
+ rccResetTIM22();
+#if defined(STM32_TIM22CLK)
+ icup->clock = STM32_TIM22CLK;
+#else
+ icup->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+ }
+ else {
+ /* Driver re-configuration scenario, it must be stopped first.*/
+ icup->tim->CR1 = 0; /* Timer disabled. */
+ icup->tim->CCR[0] = 0; /* Comparator 1 disabled. */
+ icup->tim->CCR[1] = 0; /* Comparator 2 disabled. */
+ icup->tim->CNT = 0; /* Counter reset to zero. */
+ }
+
+ /* Timer configuration.*/
+ icup->tim->SR = 0; /* Clear eventual pending IRQs. */
+ icup->tim->DIER = icup->config->dier & /* DMA-related DIER settings. */
+ ~STM32_TIM_DIER_IRQ_MASK;
+ psc = (icup->clock / icup->config->frequency) - 1;
+ osalDbgAssert((psc <= 0xFFFF) &&
+ ((psc + 1) * icup->config->frequency) == icup->clock,
+ "invalid frequency");
+ icup->tim->PSC = psc;
+ if (icup->config->arr == 0U) {
+ /* Zero is an invalid value and is turned in maximum value, also for
+ legacy configurations compatibility.*/
+ icup->tim->ARR = 0xFFFFFFFFU;
+ }
+ else {
+ icup->tim->ARR = icup->config->arr;
+ }
+
+ if (icup->config->channel == ICU_CHANNEL_1) {
+ /* Selected input 1.
+ CCMR1_CC1S = 01 = CH1 Input on TI1.
+ CCMR1_CC2S = 10 = CH2 Input on TI1.*/
+ icup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(1) | STM32_TIM_CCMR1_CC2S(2);
+
+ /* SMCR_TS = 101, input is TI1FP1.
+ SMCR_SMS = 100, reset on rising edge.*/
+ icup->tim->SMCR = STM32_TIM_SMCR_TS(5) | STM32_TIM_SMCR_SMS(4);
+
+ /* The CCER settings depend on the selected trigger mode.
+ ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge.
+ ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/
+ if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH)
+ icup->tim->CCER = STM32_TIM_CCER_CC1E |
+ STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P;
+ else
+ icup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P |
+ STM32_TIM_CCER_CC2E;
+
+ /* Direct pointers to the capture registers in order to make reading
+ data faster from within callbacks.*/
+ icup->wccrp = &icup->tim->CCR[1];
+ icup->pccrp = &icup->tim->CCR[0];
+ }
+ else {
+ /* Selected input 2.
+ CCMR1_CC1S = 10 = CH1 Input on TI2.
+ CCMR1_CC2S = 01 = CH2 Input on TI2.*/
+ icup->tim->CCMR1 = STM32_TIM_CCMR1_CC1S(2) | STM32_TIM_CCMR1_CC2S(1);
+
+ /* SMCR_TS = 110, input is TI2FP2.
+ SMCR_SMS = 100, reset on rising edge.*/
+ icup->tim->SMCR = STM32_TIM_SMCR_TS(6) | STM32_TIM_SMCR_SMS(4);
+
+ /* The CCER settings depend on the selected trigger mode.
+ ICU_INPUT_ACTIVE_HIGH: Active on rising edge, idle on falling edge.
+ ICU_INPUT_ACTIVE_LOW: Active on falling edge, idle on rising edge.*/
+ if (icup->config->mode == ICU_INPUT_ACTIVE_HIGH)
+ icup->tim->CCER = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P |
+ STM32_TIM_CCER_CC2E;
+ else
+ icup->tim->CCER = STM32_TIM_CCER_CC1E |
+ STM32_TIM_CCER_CC2E | STM32_TIM_CCER_CC2P;
+
+ /* Direct pointers to the capture registers in order to make reading
+ data faster from within callbacks.*/
+ icup->wccrp = &icup->tim->CCR[0];
+ icup->pccrp = &icup->tim->CCR[1];
+ }
+}
+
+/**
+ * @brief Deactivates the ICU peripheral.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @notapi
+ */
+void icu_lld_stop(ICUDriver *icup) {
+
+ if (icup->state == ICU_READY) {
+ /* Clock deactivation.*/
+ icup->tim->CR1 = 0; /* Timer disabled. */
+ icup->tim->DIER = 0; /* All IRQs disabled. */
+ icup->tim->SR = 0; /* Clear eventual pending IRQs. */
+
+#if STM32_ICU_USE_TIM1
+ if (&ICUD1 == icup) {
+#if !defined(STM32_TIM1_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM1_UP_NUMBER);
+ nvicDisableVector(STM32_TIM1_CC_NUMBER);
+#endif
+ rccDisableTIM1();
+ }
+#endif
+
+#if STM32_ICU_USE_TIM2
+ if (&ICUD2 == icup) {
+#if !defined(STM32_TIM2_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM2_NUMBER);
+#endif
+ rccDisableTIM2();
+ }
+#endif
+
+#if STM32_ICU_USE_TIM3
+ if (&ICUD3 == icup) {
+#if !defined(STM32_TIM3_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM3_NUMBER);
+#endif
+ rccDisableTIM3();
+ }
+#endif
+
+#if STM32_ICU_USE_TIM4
+ if (&ICUD4 == icup) {
+#if !defined(STM32_TIM4_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM4_NUMBER);
+#endif
+ rccDisableTIM4();
+ }
+#endif
+
+#if STM32_ICU_USE_TIM5
+ if (&ICUD5 == icup) {
+#if !defined(STM32_TIM5_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM5_NUMBER);
+#endif
+ rccDisableTIM5();
+ }
+#endif
+
+#if STM32_ICU_USE_TIM8
+ if (&ICUD8 == icup) {
+#if !defined(STM32_TIM8_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM8_UP_NUMBER);
+ nvicDisableVector(STM32_TIM8_CC_NUMBER);
+#endif
+ rccDisableTIM8();
+ }
+#endif
+
+#if STM32_ICU_USE_TIM9
+ if (&ICUD9 == icup) {
+ rccDisableTIM9();
+ }
+#endif
+
+#if STM32_ICU_USE_TIM10
+ if (&ICUD10 == icup) {
+ rccDisableTIM10();
+ }
+#endif
+
+#if STM32_ICU_USE_TIM11
+ if (&ICUD11 == icup) {
+ rccDisableTIM11();
+ }
+#endif
+
+#if STM32_ICU_USE_TIM12
+ if (&ICUD12 == icup) {
+ rccDisableTIM12();
+ }
+#endif
+
+#if STM32_ICU_USE_TIM13
+ if (&ICUD13 == icup) {
+ rccDisableTIM13();
+ }
+#endif
+
+#if STM32_ICU_USE_TIM14
+ if (&ICUD14 == icup) {
+ rccDisableTIM14();
+ }
+#endif
+
+#if STM32_ICU_USE_TIM15
+ if (&ICUD15 == icup) {
+ rccDisableTIM15();
+ }
+#endif
+
+#if STM32_ICU_USE_TIM20
+ if (&ICUD20 == icup) {
+ rccDisableTIM20();
+ }
+#endif
+
+#if STM32_ICU_USE_TIM21
+ if (&ICUD21 == icup) {
+ rccDisableTIM21();
+ }
+#endif
+
+#if STM32_ICU_USE_TIM22
+ if (&ICUD22 == icup) {
+ rccDisableTIM22();
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Starts the input capture.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @notapi
+ */
+void icu_lld_start_capture(ICUDriver *icup) {
+
+ /* Triggering an UG and clearing the IRQ status.*/
+ icup->tim->EGR |= STM32_TIM_EGR_UG;
+ icup->tim->SR = 0;
+
+ /* Timer is started.*/
+ icup->tim->CR1 = STM32_TIM_CR1_URS | STM32_TIM_CR1_CEN;
+}
+
+/**
+ * @brief Waits for a completed capture.
+ * @note The operation is performed in polled mode.
+ * @note In order to use this function notifications must be disabled.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @return The capture status.
+ * @retval false if the capture is successful.
+ * @retval true if a timer overflow occurred.
+ *
+ * @notapi
+ */
+bool icu_lld_wait_capture(ICUDriver *icup) {
+
+ /* If the driver is still in the ICU_WAITING state then we need to wait
+ for the first activation edge.*/
+ if (icup->state == ICU_WAITING)
+ if (icu_lld_wait_edge(icup))
+ return true;
+
+ /* This edge marks the availability of a capture result.*/
+ return icu_lld_wait_edge(icup);
+}
+
+/**
+ * @brief Stops the input capture.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @notapi
+ */
+void icu_lld_stop_capture(ICUDriver *icup) {
+
+ /* Timer stopped.*/
+ icup->tim->CR1 = 0;
+
+ /* All interrupts disabled.*/
+ icup->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK;
+}
+
+/**
+ * @brief Enables notifications.
+ * @pre The ICU unit must have been activated using @p icuStart() and the
+ * capture started using @p icuStartCapture().
+ * @note If the notification is already enabled then the call has no effect.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @notapi
+ */
+void icu_lld_enable_notifications(ICUDriver *icup) {
+ uint32_t dier = icup->tim->DIER;
+
+ /* If interrupts were already enabled then the operation is skipped.
+ This is done in order to avoid clearing the SR and risk losing
+ pending interrupts.*/
+ if ((dier & STM32_TIM_DIER_IRQ_MASK) == 0) {
+ /* Previously triggered IRQs are ignored, status cleared.*/
+ icup->tim->SR = 0;
+
+ if (icup->config->channel == ICU_CHANNEL_1) {
+ /* Enabling periodic callback on CC1.*/
+ dier |= STM32_TIM_DIER_CC1IE;
+
+ /* Optionally enabling width callback on CC2.*/
+ if (icup->config->width_cb != NULL)
+ dier |= STM32_TIM_DIER_CC2IE;
+ }
+ else {
+ /* Enabling periodic callback on CC2.*/
+ dier |= STM32_TIM_DIER_CC2IE;
+
+ /* Optionally enabling width callback on CC1.*/
+ if (icup->config->width_cb != NULL)
+ dier |= STM32_TIM_DIER_CC1IE;
+ }
+
+ /* If an overflow callback is defined then also the overflow callback
+ is enabled.*/
+ if (icup->config->overflow_cb != NULL)
+ dier |= STM32_TIM_DIER_UIE;
+
+ /* One single atomic write.*/
+ icup->tim->DIER = dier;
+ }
+}
+
+/**
+ * @brief Disables notifications.
+ * @pre The ICU unit must have been activated using @p icuStart() and the
+ * capture started using @p icuStartCapture().
+ * @note If the notification is already disabled then the call has no effect.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @notapi
+ */
+void icu_lld_disable_notifications(ICUDriver *icup) {
+
+ /* All interrupts disabled.*/
+ icup->tim->DIER &= ~STM32_TIM_DIER_IRQ_MASK;
+}
+
+/**
+ * @brief Shared IRQ handler.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @notapi
+ */
+void icu_lld_serve_interrupt(ICUDriver *icup) {
+ uint32_t sr;
+
+ sr = icup->tim->SR;
+ sr &= icup->tim->DIER & STM32_TIM_DIER_IRQ_MASK;
+ icup->tim->SR = ~sr;
+ if (icup->config->channel == ICU_CHANNEL_1) {
+ if ((sr & STM32_TIM_SR_CC2IF) != 0)
+ _icu_isr_invoke_width_cb(icup);
+ if ((sr & STM32_TIM_SR_CC1IF) != 0)
+ _icu_isr_invoke_period_cb(icup);
+ }
+ else {
+ if ((sr & STM32_TIM_SR_CC1IF) != 0)
+ _icu_isr_invoke_width_cb(icup);
+ if ((sr & STM32_TIM_SR_CC2IF) != 0)
+ _icu_isr_invoke_period_cb(icup);
+ }
+ if ((sr & STM32_TIM_SR_UIF) != 0)
+ _icu_isr_invoke_overflow_cb(icup);
+}
+
+#endif /* HAL_USE_ICU */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.h
new file mode 100644
index 0000000..38c1907
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.h
@@ -0,0 +1,893 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/hal_icu_lld.h
+ * @brief STM32 ICU subsystem low level driver header.
+ *
+ * @addtogroup ICU
+ * @{
+ */
+
+#ifndef HAL_ICU_LLD_H
+#define HAL_ICU_LLD_H
+
+#if HAL_USE_ICU || defined(__DOXYGEN__)
+
+#include "stm32_tim.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief ICUD1 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ICU_USE_TIM1) || defined(__DOXYGEN__)
+#define STM32_ICU_USE_TIM1 FALSE
+#endif
+
+/**
+ * @brief ICUD2 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ICU_USE_TIM2) || defined(__DOXYGEN__)
+#define STM32_ICU_USE_TIM2 FALSE
+#endif
+
+/**
+ * @brief ICUD3 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ICU_USE_TIM3) || defined(__DOXYGEN__)
+#define STM32_ICU_USE_TIM3 FALSE
+#endif
+
+/**
+ * @brief ICUD4 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD4 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ICU_USE_TIM4) || defined(__DOXYGEN__)
+#define STM32_ICU_USE_TIM4 FALSE
+#endif
+
+/**
+ * @brief ICUD5 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD5 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ICU_USE_TIM5) || defined(__DOXYGEN__)
+#define STM32_ICU_USE_TIM5 FALSE
+#endif
+
+/**
+ * @brief ICUD8 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD8 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ICU_USE_TIM8) || defined(__DOXYGEN__)
+#define STM32_ICU_USE_TIM8 FALSE
+#endif
+
+/**
+ * @brief ICUD9 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD9 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ICU_USE_TIM9) || defined(__DOXYGEN__)
+#define STM32_ICU_USE_TIM9 FALSE
+#endif
+
+/**
+ * @brief ICUD10 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD10 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ICU_USE_TIM10) || defined(__DOXYGEN__)
+#define STM32_ICU_USE_TIM10 FALSE
+#endif
+
+/**
+ * @brief ICUD11 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD11 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ICU_USE_TIM11) || defined(__DOXYGEN__)
+#define STM32_ICU_USE_TIM11 FALSE
+#endif
+
+/**
+ * @brief ICUD12 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD12 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ICU_USE_TIM12) || defined(__DOXYGEN__)
+#define STM32_ICU_USE_TIM12 FALSE
+#endif
+
+/**
+ * @brief ICUD13 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD13 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ICU_USE_TIM13) || defined(__DOXYGEN__)
+#define STM32_ICU_USE_TIM13 FALSE
+#endif
+
+/**
+ * @brief ICUD14 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD14 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ICU_USE_TIM14) || defined(__DOXYGEN__)
+#define STM32_ICU_USE_TIM14 FALSE
+#endif
+
+/**
+ * @brief ICUD15 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD15 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ICU_USE_TIM15) || defined(__DOXYGEN__)
+#define STM32_ICU_USE_TIM15 FALSE
+#endif
+
+/**
+ * @brief ICUD20 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD20 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ICU_USE_TIM20) || defined(__DOXYGEN__)
+#define STM32_ICU_USE_TIM20 FALSE
+#endif
+
+/**
+ * @brief ICUD21 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD21 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ICU_USE_TIM21) || defined(__DOXYGEN__)
+#define STM32_ICU_USE_TIM21 FALSE
+#endif
+
+/**
+ * @brief ICUD22 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD22 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_ICU_USE_TIM22) || defined(__DOXYGEN__)
+#define STM32_ICU_USE_TIM22 FALSE
+#endif
+
+/**
+ * @brief ICUD1 interrupt priority level setting.
+ */
+#if !defined(STM32_ICU_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ICU_TIM1_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD2 interrupt priority level setting.
+ */
+#if !defined(STM32_ICU_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ICU_TIM2_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD3 interrupt priority level setting.
+ */
+#if !defined(STM32_ICU_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ICU_TIM3_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD4 interrupt priority level setting.
+ */
+#if !defined(STM32_ICU_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ICU_TIM4_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD5 interrupt priority level setting.
+ */
+#if !defined(STM32_ICU_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ICU_TIM5_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD8 interrupt priority level setting.
+ */
+#if !defined(STM32_ICU_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ICU_TIM8_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD9 interrupt priority level setting.
+ */
+#if !defined(STM32_ICU_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ICU_TIM9_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD10 interrupt priority level setting.
+ */
+#if !defined(STM32_ICU_TIM10_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ICU_TIM10_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD11 interrupt priority level setting.
+ */
+#if !defined(STM32_ICU_TIM11_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ICU_TIM11_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD12 interrupt priority level setting.
+ */
+#if !defined(STM32_ICU_TIM12_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ICU_TIM12_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD13 interrupt priority level setting.
+ */
+#if !defined(STM32_ICU_TIM13_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ICU_TIM13_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD14 interrupt priority level setting.
+ */
+#if !defined(STM32_ICU_TIM14_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ICU_TIM14_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD15 interrupt priority level setting.
+ */
+#if !defined(STM32_ICU_TIM15_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ICU_TIM15_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD20 interrupt priority level setting.
+ */
+#if !defined(STM32_ICU_TIM20_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ICU_TIM20_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD21 interrupt priority level setting.
+ */
+#if !defined(STM32_ICU_TIM21_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ICU_TIM21_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief ICUD22 interrupt priority level setting.
+ */
+#if !defined(STM32_ICU_TIM22_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ICU_TIM22_IRQ_PRIORITY 7
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !defined(STM32_HAS_TIM1)
+#define STM32_HAS_TIM1 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM2)
+#define STM32_HAS_TIM2 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM3)
+#define STM32_HAS_TIM3 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM4)
+#define STM32_HAS_TIM4 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM5)
+#define STM32_HAS_TIM5 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM8)
+#define STM32_HAS_TIM8 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM9)
+#define STM32_HAS_TIM9 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM10)
+#define STM32_HAS_TIM10 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM11)
+#define STM32_HAS_TIM11 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM12)
+#define STM32_HAS_TIM12 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM13)
+#define STM32_HAS_TIM13 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM14)
+#define STM32_HAS_TIM14 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM15)
+#define STM32_HAS_TIM15 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM20)
+#define STM32_HAS_TIM20 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM21)
+#define STM32_HAS_TIM21 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM22)
+#define STM32_HAS_TIM22 FALSE
+#endif
+
+#if STM32_ICU_USE_TIM1 && !STM32_HAS_TIM1
+#error "TIM1 not present in the selected device"
+#endif
+
+#if STM32_ICU_USE_TIM2 && !STM32_HAS_TIM2
+#error "TIM2 not present in the selected device"
+#endif
+
+#if STM32_ICU_USE_TIM3 && !STM32_HAS_TIM3
+#error "TIM3 not present in the selected device"
+#endif
+
+#if STM32_ICU_USE_TIM4 && !STM32_HAS_TIM4
+#error "TIM4 not present in the selected device"
+#endif
+
+#if STM32_ICU_USE_TIM5 && !STM32_HAS_TIM5
+#error "TIM5 not present in the selected device"
+#endif
+
+#if STM32_ICU_USE_TIM8 && !STM32_HAS_TIM8
+#error "TIM8 not present in the selected device"
+#endif
+
+#if STM32_ICU_USE_TIM9 && !STM32_HAS_TIM9
+#error "TIM9 not present in the selected device"
+#endif
+
+#if STM32_ICU_USE_TIM10 && !STM32_HAS_TIM10
+#error "TIM10 not present in the selected device"
+#endif
+
+#if STM32_ICU_USE_TIM11 && !STM32_HAS_TIM11
+#error "TIM11 not present in the selected device"
+#endif
+
+#if STM32_ICU_USE_TIM12 && !STM32_HAS_TIM12
+#error "TIM12 not present in the selected device"
+#endif
+
+#if STM32_ICU_USE_TIM13 && !STM32_HAS_TIM13
+#error "TIM13 not present in the selected device"
+#endif
+
+#if STM32_ICU_USE_TIM14 && !STM32_HAS_TIM14
+#error "TIM14 not present in the selected device"
+#endif
+
+#if STM32_ICU_USE_TIM15 && !STM32_HAS_TIM15
+#error "TIM15 not present in the selected device"
+#endif
+
+#if STM32_ICU_USE_TIM20 && !STM32_HAS_TIM20
+#error "TIM20 not present in the selected device"
+#endif
+
+#if STM32_ICU_USE_TIM21 && !STM32_HAS_TIM21
+#error "TIM21 not present in the selected device"
+#endif
+
+#if STM32_ICU_USE_TIM22 && !STM32_HAS_TIM22
+#error "TIM22 not present in the selected device"
+#endif
+
+#if !STM32_ICU_USE_TIM1 && !STM32_ICU_USE_TIM2 && \
+ !STM32_ICU_USE_TIM3 && !STM32_ICU_USE_TIM4 && \
+ !STM32_ICU_USE_TIM5 && !STM32_ICU_USE_TIM8 && \
+ !STM32_ICU_USE_TIM9 && !STM32_ICU_USE_TIM10 && \
+ !STM32_ICU_USE_TIM11 && !STM32_ICU_USE_TIM12 && \
+ !STM32_ICU_USE_TIM13 && !STM32_ICU_USE_TIM14 && \
+ !STM32_ICU_USE_TIM15 && !STM32_ICU_USE_TIM20 && \
+ !STM32_ICU_USE_TIM21 && !STM32_ICU_USE_TIM22
+#error "ICU driver activated but no TIM peripheral assigned"
+#endif
+
+/* Checks on allocation of TIMx units.*/
+#if STM32_ICU_USE_TIM1
+#if defined(STM32_TIM1_IS_USED)
+#error "ICUD1 requires TIM1 but the timer is already used"
+#else
+#define STM32_TIM1_IS_USED
+#endif
+#endif
+
+#if STM32_ICU_USE_TIM2
+#if defined(STM32_TIM2_IS_USED)
+#error "ICUD2 requires TIM2 but the timer is already used"
+#else
+#define STM32_TIM2_IS_USED
+#endif
+#endif
+
+#if STM32_ICU_USE_TIM3
+#if defined(STM32_TIM3_IS_USED)
+#error "ICUD3 requires TIM3 but the timer is already used"
+#else
+#define STM32_TIM3_IS_USED
+#endif
+#endif
+
+#if STM32_ICU_USE_TIM4
+#if defined(STM32_TIM4_IS_USED)
+#error "ICUD4 requires TIM4 but the timer is already used"
+#else
+#define STM32_TIM4_IS_USED
+#endif
+#endif
+
+#if STM32_ICU_USE_TIM5
+#if defined(STM32_TIM5_IS_USED)
+#error "ICUD5 requires TIM5 but the timer is already used"
+#else
+#define STM32_TIM5_IS_USED
+#endif
+#endif
+
+#if STM32_ICU_USE_TIM8
+#if defined(STM32_TIM8_IS_USED)
+#error "ICUD8 requires TIM8 but the timer is already used"
+#else
+#define STM32_TIM8_IS_USED
+#endif
+#endif
+
+#if STM32_ICU_USE_TIM9
+#if defined(STM32_TIM9_IS_USED)
+#error "ICUD9 requires TIM9 but the timer is already used"
+#else
+#define STM32_TIM9_IS_USED
+#endif
+#endif
+
+#if STM32_ICU_USE_TIM10
+#if defined(STM32_TIM10_IS_USED)
+#error "ICUD10 requires TIM10 but the timer is already used"
+#else
+#define STM32_TIM10_IS_USED
+#endif
+#endif
+
+#if STM32_ICU_USE_TIM11
+#if defined(STM32_TIM11_IS_USED)
+#error "ICUD11 requires TIM11 but the timer is already used"
+#else
+#define STM32_TIM11_IS_USED
+#endif
+#endif
+
+#if STM32_ICU_USE_TIM12
+#if defined(STM32_TIM12_IS_USED)
+#error "ICUD12 requires TIM12 but the timer is already used"
+#else
+#define STM32_TIM12_IS_USED
+#endif
+#endif
+
+#if STM32_ICU_USE_TIM13
+#if defined(STM32_TIM13_IS_USED)
+#error "ICUD13 requires TIM13 but the timer is already used"
+#else
+#define STM32_TIM13_IS_USED
+#endif
+#endif
+
+#if STM32_ICU_USE_TIM14
+#if defined(STM32_TIM14_IS_USED)
+#error "ICUD14 requires TIM14 but the timer is already used"
+#else
+#define STM32_TIM14_IS_USED
+#endif
+#endif
+
+#if STM32_ICU_USE_TIM15
+#if defined(STM32_TIM15_IS_USED)
+#error "ICUD15 requires TIM15 but the timer is already used"
+#else
+#define STM32_TIM15_IS_USED
+#endif
+#endif
+
+#if STM32_ICU_USE_TIM20
+#if defined(STM32_TIM20_IS_USED)
+#error "ICUD20 requires TIM20 but the timer is already used"
+#else
+#define STM32_TIM20_IS_USED
+#endif
+#endif
+
+#if STM32_ICU_USE_TIM21
+#if defined(STM32_TIM21_IS_USED)
+#error "ICUD21 requires TIM21 but the timer is already used"
+#else
+#define STM32_TIM21_IS_USED
+#endif
+#endif
+
+#if STM32_ICU_USE_TIM22
+#if defined(STM32_TIM22_IS_USED)
+#error "ICUD22 requires TIM22 but the timer is already used"
+#else
+#define STM32_TIM22_IS_USED
+#endif
+#endif
+
+/* IRQ priority checks.*/
+#if STM32_ICU_USE_TIM1 && !defined(STM32_TIM1_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM1"
+#endif
+
+#if STM32_ICU_USE_TIM2 && !defined(STM32_TIM2_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM2"
+#endif
+
+#if STM32_ICU_USE_TIM3 && !defined(STM32_TIM3_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM3"
+#endif
+
+#if STM32_ICU_USE_TIM4 && !defined(STM32_TIM4_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM4_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM4"
+#endif
+
+#if STM32_ICU_USE_TIM5 && !defined(STM32_TIM5_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM5_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM5"
+#endif
+
+#if STM32_ICU_USE_TIM8 && !defined(STM32_TIM8_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM8_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM8"
+#endif
+
+#if STM32_ICU_USE_TIM9 && !defined(STM32_TIM9_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM9_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM9"
+#endif
+
+#if STM32_ICU_USE_TIM10 && !defined(STM32_TIM10_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM10_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM10"
+#endif
+
+#if STM32_ICU_USE_TIM11 && !defined(STM32_TIM11_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM11_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM11"
+#endif
+
+#if STM32_ICU_USE_TIM12 && !defined(STM32_TIM12_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM12_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM12"
+#endif
+
+#if STM32_ICU_USE_TIM13 && !defined(STM32_TIM13_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM13_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM13"
+#endif
+
+#if STM32_ICU_USE_TIM14 && !defined(STM32_TIM14_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM14_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM14"
+#endif
+
+#if STM32_ICU_USE_TIM15 && !defined(STM32_TIM15_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM15_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM15"
+#endif
+
+#if STM32_ICU_USE_TIM20 && !defined(STM32_TIM20_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM20_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM20"
+#endif
+
+#if STM32_ICU_USE_TIM21 && !defined(STM32_TIM21_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM21_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM21"
+#endif
+
+#if STM32_ICU_USE_TIM22 && !defined(STM32_TIM22_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_ICU_TIM22_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM22"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief ICU driver mode.
+ */
+typedef enum {
+ ICU_INPUT_ACTIVE_HIGH = 0, /**< Trigger on rising edge. */
+ ICU_INPUT_ACTIVE_LOW = 1, /**< Trigger on falling edge. */
+} icumode_t;
+
+/**
+ * @brief ICU frequency type.
+ */
+typedef uint32_t icufreq_t;
+
+/**
+ * @brief ICU channel type.
+ */
+typedef enum {
+ ICU_CHANNEL_1 = 0, /**< Use TIMxCH1. */
+ ICU_CHANNEL_2 = 1, /**< Use TIMxCH2. */
+} icuchannel_t;
+
+/**
+ * @brief ICU counter type.
+ */
+typedef uint32_t icucnt_t;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+ /**
+ * @brief Driver mode.
+ */
+ icumode_t mode;
+ /**
+ * @brief Timer clock in Hz.
+ * @note The low level can use assertions in order to catch invalid
+ * frequency specifications.
+ */
+ icufreq_t frequency;
+ /**
+ * @brief Callback for pulse width measurement.
+ */
+ icucallback_t width_cb;
+ /**
+ * @brief Callback for cycle period measurement.
+ */
+ icucallback_t period_cb;
+ /**
+ * @brief Callback for timer overflow.
+ */
+ icucallback_t overflow_cb;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Timer input channel to be used.
+ * @note Only inputs TIMx 1 and 2 are supported.
+ */
+ icuchannel_t channel;
+ /**
+ * @brief TIM DIER register initialization data.
+ * @note The value of this field should normally be equal to zero.
+ * @note Only the DMA-related bits can be specified in this field.
+ */
+ uint32_t dier;
+ /**
+ * @brief TIM ARR register initialization data.
+ * @note The value of this field should normally be equal to 0xFFFFFFFFU.
+ */
+ uint32_t arr;
+} ICUConfig;
+
+/**
+ * @brief Structure representing an ICU driver.
+ */
+struct ICUDriver {
+ /**
+ * @brief Driver state.
+ */
+ icustate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const ICUConfig *config;
+#if defined(ICU_DRIVER_EXT_FIELDS)
+ ICU_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Timer base clock.
+ */
+ uint32_t clock;
+ /**
+ * @brief Pointer to the TIMx registers block.
+ */
+ stm32_tim_t *tim;
+ /**
+ * @brief CCR register used for width capture.
+ */
+ volatile uint32_t *wccrp;
+ /**
+ * @brief CCR register used for period capture.
+ */
+ volatile uint32_t *pccrp;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Returns the width of the latest pulse.
+ * @details The pulse width is defined as number of ticks between the start
+ * edge and the stop edge.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @return The number of ticks.
+ *
+ * @notapi
+ */
+#define icu_lld_get_width(icup) (*((icup)->wccrp) + 1)
+
+/**
+ * @brief Returns the width of the latest cycle.
+ * @details The cycle width is defined as number of ticks between a start
+ * edge and the next start edge.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @return The number of ticks.
+ *
+ * @notapi
+ */
+#define icu_lld_get_period(icup) (*((icup)->pccrp) + 1)
+
+/**
+ * @brief Check on notifications status.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @return The notifications status.
+ * @retval false if notifications are not enabled.
+ * @retval true if notifications are enabled.
+ *
+ * @notapi
+ */
+#define icu_lld_are_notifications_enabled(icup) \
+ (bool)(((icup)->tim->DIER & STM32_TIM_DIER_IRQ_MASK) != 0)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_ICU_USE_TIM1 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD1;
+#endif
+
+#if STM32_ICU_USE_TIM2 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD2;
+#endif
+
+#if STM32_ICU_USE_TIM3 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD3;
+#endif
+
+#if STM32_ICU_USE_TIM4 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD4;
+#endif
+
+#if STM32_ICU_USE_TIM5 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD5;
+#endif
+
+#if STM32_ICU_USE_TIM8 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD8;
+#endif
+
+#if STM32_ICU_USE_TIM9 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD9;
+#endif
+
+#if STM32_ICU_USE_TIM10 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD10;
+#endif
+
+#if STM32_ICU_USE_TIM11 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD11;
+#endif
+
+#if STM32_ICU_USE_TIM12 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD12;
+#endif
+
+#if STM32_ICU_USE_TIM13 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD13;
+#endif
+
+#if STM32_ICU_USE_TIM14 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD14;
+#endif
+
+#if STM32_ICU_USE_TIM15 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD15;
+#endif
+
+#if STM32_ICU_USE_TIM20 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD20;
+#endif
+
+#if STM32_ICU_USE_TIM21 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD21;
+#endif
+
+#if STM32_ICU_USE_TIM22 && !defined(__DOXYGEN__)
+extern ICUDriver ICUD22;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void icu_lld_init(void);
+ void icu_lld_start(ICUDriver *icup);
+ void icu_lld_stop(ICUDriver *icup);
+ void icu_lld_start_capture(ICUDriver *icup);
+ bool icu_lld_wait_capture(ICUDriver *icup);
+ void icu_lld_stop_capture(ICUDriver *icup);
+ void icu_lld_enable_notifications(ICUDriver *icup);
+ void icu_lld_disable_notifications(ICUDriver *icup);
+ void icu_lld_serve_interrupt(ICUDriver *icup);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_ICU */
+
+#endif /* HAL_ICU_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c
new file mode 100644
index 0000000..eb6bebc
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c
@@ -0,0 +1,1302 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/hal_pwm_lld.c
+ * @brief STM32 PWM subsystem low level driver header.
+ *
+ * @addtogroup PWM
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_PWM || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief PWMD1 driver identifier.
+ * @note The driver PWMD1 allocates the complex timer TIM1 when enabled.
+ */
+#if STM32_PWM_USE_TIM1 || defined(__DOXYGEN__)
+PWMDriver PWMD1;
+#endif
+
+/**
+ * @brief PWMD2 driver identifier.
+ * @note The driver PWMD2 allocates the timer TIM2 when enabled.
+ */
+#if STM32_PWM_USE_TIM2 || defined(__DOXYGEN__)
+PWMDriver PWMD2;
+#endif
+
+/**
+ * @brief PWMD3 driver identifier.
+ * @note The driver PWMD3 allocates the timer TIM3 when enabled.
+ */
+#if STM32_PWM_USE_TIM3 || defined(__DOXYGEN__)
+PWMDriver PWMD3;
+#endif
+
+/**
+ * @brief PWMD4 driver identifier.
+ * @note The driver PWMD4 allocates the timer TIM4 when enabled.
+ */
+#if STM32_PWM_USE_TIM4 || defined(__DOXYGEN__)
+PWMDriver PWMD4;
+#endif
+
+/**
+ * @brief PWMD5 driver identifier.
+ * @note The driver PWMD5 allocates the timer TIM5 when enabled.
+ */
+#if STM32_PWM_USE_TIM5 || defined(__DOXYGEN__)
+PWMDriver PWMD5;
+#endif
+
+/**
+ * @brief PWMD8 driver identifier.
+ * @note The driver PWMD8 allocates the timer TIM8 when enabled.
+ */
+#if STM32_PWM_USE_TIM8 || defined(__DOXYGEN__)
+PWMDriver PWMD8;
+#endif
+
+/**
+ * @brief PWMD9 driver identifier.
+ * @note The driver PWMD9 allocates the timer TIM9 when enabled.
+ */
+#if STM32_PWM_USE_TIM9 || defined(__DOXYGEN__)
+PWMDriver PWMD9;
+#endif
+
+/**
+ * @brief PWMD10 driver identifier.
+ * @note The driver PWMD10 allocates the timer TIM10 when enabled.
+ */
+#if STM32_PWM_USE_TIM10 || defined(__DOXYGEN__)
+PWMDriver PWMD10;
+#endif
+
+/**
+ * @brief PWMD11 driver identifier.
+ * @note The driver PWMD11 allocates the timer TIM11 when enabled.
+ */
+#if STM32_PWM_USE_TIM11 || defined(__DOXYGEN__)
+PWMDriver PWMD11;
+#endif
+
+/**
+ * @brief PWMD12 driver identifier.
+ * @note The driver PWMD12 allocates the timer TIM12 when enabled.
+ */
+#if STM32_PWM_USE_TIM12 || defined(__DOXYGEN__)
+PWMDriver PWMD12;
+#endif
+
+/**
+ * @brief PWMD13 driver identifier.
+ * @note The driver PWMD13 allocates the timer TIM13 when enabled.
+ */
+#if STM32_PWM_USE_TIM13 || defined(__DOXYGEN__)
+PWMDriver PWMD13;
+#endif
+
+/**
+ * @brief PWMD14 driver identifier.
+ * @note The driver PWMD14 allocates the timer TIM14 when enabled.
+ */
+#if STM32_PWM_USE_TIM14 || defined(__DOXYGEN__)
+PWMDriver PWMD14;
+#endif
+
+/**
+ * @brief PWMD15 driver identifier.
+ * @note The driver PWMD15 allocates the timer TIM15 when enabled.
+ */
+#if STM32_PWM_USE_TIM15 || defined(__DOXYGEN__)
+PWMDriver PWMD15;
+#endif
+
+/**
+ * @brief PWMD16 driver identifier.
+ * @note The driver PWMD16 allocates the timer TIM16 when enabled.
+ */
+#if STM32_PWM_USE_TIM16 || defined(__DOXYGEN__)
+PWMDriver PWMD16;
+#endif
+
+/**
+ * @brief PWMD17 driver identifier.
+ * @note The driver PWMD17 allocates the timer TIM17 when enabled.
+ */
+#if STM32_PWM_USE_TIM17 || defined(__DOXYGEN__)
+PWMDriver PWMD17;
+#endif
+
+/**
+ * @brief PWMD20 driver identifier.
+ * @note The driver PWMD20 allocates the timer TIM20 when enabled.
+ */
+#if STM32_PWM_USE_TIM20 || defined(__DOXYGEN__)
+PWMDriver PWMD20;
+#endif
+
+/**
+ * @brief PWMD21 driver identifier.
+ * @note The driver PWMD21 allocates the timer TIM21 when enabled.
+ */
+#if STM32_PWM_USE_TIM21 || defined(__DOXYGEN__)
+PWMDriver PWMD21;
+#endif
+
+/**
+ * @brief PWMD22 driver identifier.
+ * @note The driver PWMD22 allocates the timer TIM22 when enabled.
+ */
+#if STM32_PWM_USE_TIM22 || defined(__DOXYGEN__)
+PWMDriver PWMD22;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_PWM_USE_TIM1 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM1_SUPPRESS_ISR)
+#if !defined(STM32_TIM1_UP_HANDLER)
+#error "STM32_TIM1_UP_HANDLER not defined"
+#endif
+/**
+ * @brief TIM1 update interrupt handler.
+ * @note It is assumed that this interrupt is only activated if the callback
+ * pointer is not equal to @p NULL in order to not perform an extra
+ * check in a potentially critical interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ pwm_lld_serve_interrupt(&PWMD1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#if !defined(STM32_TIM1_CC_HANDLER)
+#error "STM32_TIM1_CC_HANDLER not defined"
+#endif
+/**
+ * @brief TIM1 compare interrupt handler.
+ * @note It is assumed that the various sources are only activated if the
+ * associated callback pointer is not equal to @p NULL in order to not
+ * perform an extra check in a potentially critical interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ pwm_lld_serve_interrupt(&PWMD1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM1_SUPPRESS_ISR) */
+#endif /* STM32_PWM_USE_TIM1 */
+
+#if STM32_PWM_USE_TIM2 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM2_SUPPRESS_ISR)
+#if !defined(STM32_TIM2_HANDLER)
+#error "STM32_TIM2_HANDLER not defined"
+#endif
+/**
+ * @brief TIM2 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ pwm_lld_serve_interrupt(&PWMD2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM2_SUPPRESS_ISR) */
+#endif /* STM32_PWM_USE_TIM2 */
+
+#if STM32_PWM_USE_TIM3 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM3_SUPPRESS_ISR)
+#if !defined(STM32_TIM3_HANDLER)
+#error "STM32_TIM3_HANDLER not defined"
+#endif
+/**
+ * @brief TIM3 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ pwm_lld_serve_interrupt(&PWMD3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM3_SUPPRESS_ISR) */
+#endif /* STM32_PWM_USE_TIM3 */
+
+#if STM32_PWM_USE_TIM4 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM4_SUPPRESS_ISR)
+#if !defined(STM32_TIM4_HANDLER)
+#error "STM32_TIM4_HANDLER not defined"
+#endif
+/**
+ * @brief TIM4 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ pwm_lld_serve_interrupt(&PWMD4);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM4_SUPPRESS_ISR) */
+#endif /* STM32_PWM_USE_TIM4 */
+
+#if STM32_PWM_USE_TIM5 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM5_SUPPRESS_ISR)
+#if !defined(STM32_TIM5_HANDLER)
+#error "STM32_TIM5_HANDLER not defined"
+#endif
+/**
+ * @brief TIM5 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ pwm_lld_serve_interrupt(&PWMD5);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM5_SUPPRESS_ISR) */
+#endif /* STM32_PWM_USE_TIM5 */
+
+#if STM32_PWM_USE_TIM8 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM8_SUPPRESS_ISR)
+#if !defined(STM32_TIM8_UP_HANDLER)
+#error "STM32_TIM8_UP_HANDLER not defined"
+#endif
+/**
+ * @brief TIM8 update interrupt handler.
+ * @note It is assumed that this interrupt is only activated if the callback
+ * pointer is not equal to @p NULL in order to not perform an extra
+ * check in a potentially critical interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ pwm_lld_serve_interrupt(&PWMD8);
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#if !defined(STM32_TIM8_CC_HANDLER)
+#error "STM32_TIM8_CC_HANDLER not defined"
+#endif
+/**
+ * @brief TIM8 compare interrupt handler.
+ * @note It is assumed that the various sources are only activated if the
+ * associated callback pointer is not equal to @p NULL in order to not
+ * perform an extra check in a potentially critical interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ pwm_lld_serve_interrupt(&PWMD8);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* !defined(STM32_TIM8_SUPPRESS_ISR) */
+#endif /* STM32_PWM_USE_TIM8 */
+
+#if STM32_PWM_USE_TIM9 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM9_SUPPRESS_ISR)
+#error "TIM9 ISR not defined by platform"
+#endif /* !defined(STM32_TIM9_SUPPRESS_ISR) */
+#endif /* STM32_PWM_USE_TIM9 */
+
+#if STM32_PWM_USE_TIM10 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM10_SUPPRESS_ISR)
+#error "TIM10 ISR not defined by platform"
+#endif /* !defined(STM32_TIM10_SUPPRESS_ISR) */
+#endif /* STM32_PWM_USE_TIM10 */
+
+#if STM32_PWM_USE_TIM11 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM11_SUPPRESS_ISR)
+#error "TIM11 ISR not defined by platform"
+#endif /* !defined(STM32_TIM11_SUPPRESS_ISR) */
+#endif /* STM32_PWM_USE_TIM11 */
+
+#if STM32_PWM_USE_TIM12 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM12_SUPPRESS_ISR)
+#error "TIM12 ISR not defined by platform"
+#endif /* !defined(STM32_TIM12_SUPPRESS_ISR) */
+#endif /* STM32_PWM_USE_TIM12 */
+
+#if STM32_PWM_USE_TIM13 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM13_SUPPRESS_ISR)
+#error "TIM13 ISR not defined by platform"
+#endif /* !defined(STM32_TIM13_SUPPRESS_ISR) */
+#endif /* STM32_PWM_USE_TIM13 */
+
+#if STM32_PWM_USE_TIM14 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM14_SUPPRESS_ISR)
+#error "TIM14 ISR not defined by platform"
+#endif /* !defined(STM32_TIM14_SUPPRESS_ISR) */
+#endif /* STM32_PWM_USE_TIM14 */
+
+#if STM32_PWM_USE_TIM15 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM15_SUPPRESS_ISR)
+#error "TIM15 ISR not defined by platform"
+#endif /* !defined(STM32_TIM15_SUPPRESS_ISR) */
+#endif /* STM32_PWM_USE_TIM15 */
+
+#if STM32_PWM_USE_TIM16 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM16_SUPPRESS_ISR)
+#error "TIM16 ISR not defined by platform"
+#endif /* !defined(STM32_TIM16_SUPPRESS_ISR) */
+#endif /* STM32_PWM_USE_TIM16 */
+
+#if STM32_PWM_USE_TIM17 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM17_SUPPRESS_ISR)
+#error "TIM17 ISR not defined by platform"
+#endif /* !defined(STM32_TIM17_SUPPRESS_ISR) */
+#endif /* STM32_PWM_USE_TIM17 */
+
+#if STM32_PWM_USE_TIM20 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM20_SUPPRESS_ISR)
+#error "TIM20 ISR not defined by platform"
+#endif /* !defined(STM32_TIM20_SUPPRESS_ISR) */
+#endif /* STM32_PWM_USE_TIM20 */
+
+#if STM32_PWM_USE_TIM21 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM21_SUPPRESS_ISR)
+#error "TIM21 ISR not defined by platform"
+#endif /* !defined(STM32_TIM21_SUPPRESS_ISR) */
+#endif /* STM32_PWM_USE_TIM21 */
+
+#if STM32_PWM_USE_TIM22 || defined(__DOXYGEN__)
+#if !defined(STM32_TIM22_SUPPRESS_ISR)
+#error "TIM22 ISR not defined by platform"
+#endif /* !defined(STM32_TIM22_SUPPRESS_ISR) */
+#endif /* STM32_PWM_USE_TIM22 */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level PWM driver initialization.
+ *
+ * @notapi
+ */
+void pwm_lld_init(void) {
+
+#if STM32_PWM_USE_TIM1
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD1);
+ PWMD1.channels = STM32_TIM1_CHANNELS;
+ PWMD1.tim = STM32_TIM1;
+#endif
+
+#if STM32_PWM_USE_TIM2
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD2);
+ PWMD2.channels = STM32_TIM2_CHANNELS;
+ PWMD2.tim = STM32_TIM2;
+#endif
+
+#if STM32_PWM_USE_TIM3
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD3);
+ PWMD3.channels = STM32_TIM3_CHANNELS;
+ PWMD3.tim = STM32_TIM3;
+#endif
+
+#if STM32_PWM_USE_TIM4
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD4);
+ PWMD4.channels = STM32_TIM4_CHANNELS;
+ PWMD4.tim = STM32_TIM4;
+#endif
+
+#if STM32_PWM_USE_TIM5
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD5);
+ PWMD5.channels = STM32_TIM5_CHANNELS;
+ PWMD5.tim = STM32_TIM5;
+#endif
+
+#if STM32_PWM_USE_TIM8
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD8);
+ PWMD8.channels = STM32_TIM8_CHANNELS;
+ PWMD8.tim = STM32_TIM8;
+#endif
+
+#if STM32_PWM_USE_TIM9
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD9);
+ PWMD9.channels = STM32_TIM9_CHANNELS;
+ PWMD9.tim = STM32_TIM9;
+#endif
+
+#if STM32_PWM_USE_TIM10
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD10);
+ PWMD10.channels = STM32_TIM10_CHANNELS;
+ PWMD10.tim = STM32_TIM10;
+#endif
+
+#if STM32_PWM_USE_TIM11
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD11);
+ PWMD11.channels = STM32_TIM11_CHANNELS;
+ PWMD11.tim = STM32_TIM11;
+#endif
+
+#if STM32_PWM_USE_TIM12
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD12);
+ PWMD12.channels = STM32_TIM12_CHANNELS;
+ PWMD12.tim = STM32_TIM12;
+#endif
+
+#if STM32_PWM_USE_TIM13
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD13);
+ PWMD13.channels = STM32_TIM13_CHANNELS;
+ PWMD13.tim = STM32_TIM13;
+#endif
+
+#if STM32_PWM_USE_TIM14
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD14);
+ PWMD14.channels = STM32_TIM14_CHANNELS;
+ PWMD14.tim = STM32_TIM14;
+#endif
+
+#if STM32_PWM_USE_TIM15
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD15);
+ PWMD15.channels = STM32_TIM15_CHANNELS;
+ PWMD15.tim = STM32_TIM15;
+#endif
+
+#if STM32_PWM_USE_TIM16
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD16);
+ PWMD16.channels = STM32_TIM16_CHANNELS;
+ PWMD16.tim = STM32_TIM16;
+#endif
+
+#if STM32_PWM_USE_TIM17
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD17);
+ PWMD17.channels = STM32_TIM17_CHANNELS;
+ PWMD17.tim = STM32_TIM17;
+#endif
+
+#if STM32_PWM_USE_TIM20
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD20);
+ PWMD20.channels = STM32_TIM20_CHANNELS;
+ PWMD20.tim = STM32_TIM20;
+#endif
+
+#if STM32_PWM_USE_TIM21
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD21);
+ PWMD21.channels = STM32_TIM21_CHANNELS;
+ PWMD21.tim = STM32_TIM21;
+#endif
+
+#if STM32_PWM_USE_TIM22
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD22);
+ PWMD22.channels = STM32_TIM22_CHANNELS;
+ PWMD22.tim = STM32_TIM22;
+#endif
+}
+
+/**
+ * @brief Configures and activates the PWM peripheral.
+ * @note Starting a driver that is already in the @p PWM_READY state
+ * disables all the active channels.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ *
+ * @notapi
+ */
+void pwm_lld_start(PWMDriver *pwmp) {
+ uint32_t psc;
+ uint32_t ccer;
+
+ if (pwmp->state == PWM_STOP) {
+ /* Clock activation and timer reset.*/
+#if STM32_PWM_USE_TIM1
+ if (&PWMD1 == pwmp) {
+ rccEnableTIM1(true);
+ rccResetTIM1();
+#if !defined(STM32_TIM1_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_PWM_TIM1_IRQ_PRIORITY);
+ nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_PWM_TIM1_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM1CLK)
+ pwmp->clock = STM32_TIM1CLK;
+#else
+ pwmp->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_PWM_USE_TIM2
+ if (&PWMD2 == pwmp) {
+ rccEnableTIM2(true);
+ rccResetTIM2();
+#if !defined(STM32_TIM2_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM2_NUMBER, STM32_PWM_TIM2_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM2CLK)
+ pwmp->clock = STM32_TIM2CLK;
+#else
+ pwmp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_PWM_USE_TIM3
+ if (&PWMD3 == pwmp) {
+ rccEnableTIM3(true);
+ rccResetTIM3();
+#if !defined(STM32_TIM3_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM3_NUMBER, STM32_PWM_TIM3_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM3CLK)
+ pwmp->clock = STM32_TIM3CLK;
+#else
+ pwmp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_PWM_USE_TIM4
+ if (&PWMD4 == pwmp) {
+ rccEnableTIM4(true);
+ rccResetTIM4();
+#if !defined(STM32_TIM4_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM4_NUMBER, STM32_PWM_TIM4_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM4CLK)
+ pwmp->clock = STM32_TIM4CLK;
+#else
+ pwmp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_PWM_USE_TIM5
+ if (&PWMD5 == pwmp) {
+ rccEnableTIM5(true);
+ rccResetTIM5();
+#if !defined(STM32_TIM5_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM5_NUMBER, STM32_PWM_TIM5_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM5CLK)
+ pwmp->clock = STM32_TIM5CLK;
+#else
+ pwmp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_PWM_USE_TIM8
+ if (&PWMD8 == pwmp) {
+ rccEnableTIM8(true);
+ rccResetTIM8();
+#if !defined(STM32_TIM8_SUPPRESS_ISR)
+ nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_PWM_TIM8_IRQ_PRIORITY);
+ nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_PWM_TIM8_IRQ_PRIORITY);
+#endif
+#if defined(STM32_TIM8CLK)
+ pwmp->clock = STM32_TIM8CLK;
+#else
+ pwmp->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_PWM_USE_TIM9
+ if (&PWMD9 == pwmp) {
+ rccEnableTIM9(true);
+ rccResetTIM9();
+#if defined(STM32_TIM9CLK)
+ pwmp->clock = STM32_TIM9CLK;
+#else
+ pwmp->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_PWM_USE_TIM10
+ if (&PWMD10 == pwmp) {
+ rccEnableTIM10(true);
+ rccResetTIM10();
+#if defined(STM32_TIM10CLK)
+ pwmp->clock = STM32_TIM10CLK;
+#else
+ pwmp->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_PWM_USE_TIM11
+ if (&PWMD11 == pwmp) {
+ rccEnableTIM11(true);
+ rccResetTIM11();
+#if defined(STM32_TIM11CLK)
+ pwmp->clock = STM32_TIM11CLK;
+#else
+ pwmp->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_PWM_USE_TIM12
+ if (&PWMD12 == pwmp) {
+ rccEnableTIM12(true);
+ rccResetTIM12();
+#if defined(STM32_TIM12CLK)
+ pwmp->clock = STM32_TIM12CLK;
+#else
+ pwmp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_PWM_USE_TIM13
+ if (&PWMD13 == pwmp) {
+ rccEnableTIM13(true);
+ rccResetTIM13();
+#if defined(STM32_TIM13CLK)
+ pwmp->clock = STM32_TIM13CLK;
+#else
+ pwmp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_PWM_USE_TIM14
+ if (&PWMD14 == pwmp) {
+ rccEnableTIM14(true);
+ rccResetTIM14();
+#if defined(STM32_TIM14CLK)
+ pwmp->clock = STM32_TIM14CLK;
+#else
+ pwmp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_PWM_USE_TIM15
+ if (&PWMD15 == pwmp) {
+ rccEnableTIM15(true);
+ rccResetTIM15();
+#if defined(STM32_TIM15CLK)
+ pwmp->clock = STM32_TIM15CLK;
+#else
+ pwmp->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_PWM_USE_TIM16
+ if (&PWMD16 == pwmp) {
+ rccEnableTIM16(true);
+ rccResetTIM16();
+#if defined(STM32_TIM16CLK)
+ pwmp->clock = STM32_TIM16CLK;
+#else
+ pwmp->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_PWM_USE_TIM17
+ if (&PWMD17 == pwmp) {
+ rccEnableTIM17(true);
+ rccResetTIM17();
+#if defined(STM32_TIM17CLK)
+ pwmp->clock = STM32_TIM17CLK;
+#else
+ pwmp->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_PWM_USE_TIM20
+ if (&PWMD20 == pwmp) {
+ rccEnableTIM20(true);
+ rccResetTIM20();
+#if defined(STM32_TIM20CLK)
+ pwmp->clock = STM32_TIM20CLK;
+#else
+ pwmp->clock = STM32_TIMCLK2;
+#endif
+ }
+#endif
+
+#if STM32_PWM_USE_TIM21
+ if (&PWMD21 == pwmp) {
+ rccEnableTIM21(true);
+ rccResetTIM21();
+#if defined(STM32_TIM21CLK)
+ pwmp->clock = STM32_TIM21CLK;
+#else
+ pwmp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+#if STM32_PWM_USE_TIM22
+ if (&PWMD22 == pwmp) {
+ rccEnableTIM22(true);
+ rccResetTIM22();
+#if defined(STM32_TIM22CLK)
+ pwmp->clock = STM32_TIM22CLK;
+#else
+ pwmp->clock = STM32_TIMCLK1;
+#endif
+ }
+#endif
+
+ /* All channels configured in PWM1 mode with preload enabled and will
+ stay that way until the driver is stopped.*/
+ pwmp->tim->CCMR1 = STM32_TIM_CCMR1_OC1M(6) | STM32_TIM_CCMR1_OC1PE |
+ STM32_TIM_CCMR1_OC2M(6) | STM32_TIM_CCMR1_OC2PE;
+ pwmp->tim->CCMR2 = STM32_TIM_CCMR2_OC3M(6) | STM32_TIM_CCMR2_OC3PE |
+ STM32_TIM_CCMR2_OC4M(6) | STM32_TIM_CCMR2_OC4PE;
+#if STM32_TIM_MAX_CHANNELS > 4
+ pwmp->tim->CCMR3 = STM32_TIM_CCMR3_OC5M(6) | STM32_TIM_CCMR3_OC5PE |
+ STM32_TIM_CCMR3_OC6M(6) | STM32_TIM_CCMR3_OC6PE;
+#endif
+ }
+ else {
+ /* Driver re-configuration scenario, it must be stopped first.*/
+ pwmp->tim->CR1 = 0; /* Timer disabled. */
+ pwmp->tim->CCR[0] = 0; /* Comparator 1 disabled. */
+ pwmp->tim->CCR[1] = 0; /* Comparator 2 disabled. */
+ pwmp->tim->CCR[2] = 0; /* Comparator 3 disabled. */
+ pwmp->tim->CCR[3] = 0; /* Comparator 4 disabled. */
+#if STM32_TIM_MAX_CHANNELS > 4
+ if (pwmp->channels > 4) {
+ pwmp->tim->CCXR[0] = 0; /* Comparator 5 disabled. */
+ pwmp->tim->CCXR[1] = 0; /* Comparator 6 disabled. */
+ }
+#endif
+ pwmp->tim->CNT = 0; /* Counter reset to zero. */
+ }
+
+ /* Timer configuration.*/
+ psc = (pwmp->clock / pwmp->config->frequency) - 1;
+ osalDbgAssert((psc <= 0xFFFF) &&
+ ((psc + 1) * pwmp->config->frequency) == pwmp->clock,
+ "invalid frequency");
+ pwmp->tim->PSC = psc;
+ pwmp->tim->ARR = pwmp->period - 1;
+ pwmp->tim->CR2 = pwmp->config->cr2;
+
+ /* Output enables and polarities setup.*/
+ ccer = 0;
+ switch (pwmp->config->channels[0].mode & PWM_OUTPUT_MASK) {
+ case PWM_OUTPUT_ACTIVE_LOW:
+ ccer |= STM32_TIM_CCER_CC1P;
+ /* Falls through.*/
+ case PWM_OUTPUT_ACTIVE_HIGH:
+ ccer |= STM32_TIM_CCER_CC1E;
+ /* Falls through.*/
+ default:
+ ;
+ }
+ switch (pwmp->config->channels[1].mode & PWM_OUTPUT_MASK) {
+ case PWM_OUTPUT_ACTIVE_LOW:
+ ccer |= STM32_TIM_CCER_CC2P;
+ /* Falls through.*/
+ case PWM_OUTPUT_ACTIVE_HIGH:
+ ccer |= STM32_TIM_CCER_CC2E;
+ /* Falls through.*/
+ default:
+ ;
+ }
+ switch (pwmp->config->channels[2].mode & PWM_OUTPUT_MASK) {
+ case PWM_OUTPUT_ACTIVE_LOW:
+ ccer |= STM32_TIM_CCER_CC3P;
+ /* Falls through.*/
+ case PWM_OUTPUT_ACTIVE_HIGH:
+ ccer |= STM32_TIM_CCER_CC3E;
+ /* Falls through.*/
+ default:
+ ;
+ }
+ switch (pwmp->config->channels[3].mode & PWM_OUTPUT_MASK) {
+ case PWM_OUTPUT_ACTIVE_LOW:
+ ccer |= STM32_TIM_CCER_CC4P;
+ /* Falls through.*/
+ case PWM_OUTPUT_ACTIVE_HIGH:
+ ccer |= STM32_TIM_CCER_CC4E;
+ /* Falls through.*/
+ default:
+ ;
+ }
+#if STM32_PWM_USE_ADVANCED
+#if STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 && !STM32_PWM_USE_TIM20
+ if (&PWMD1 == pwmp) {
+#endif
+#if !STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 && !STM32_PWM_USE_TIM20
+ if (&PWMD8 == pwmp) {
+#endif
+#if STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 && !STM32_PWM_USE_TIM20
+ if ((&PWMD1 == pwmp) || (&PWMD8 == pwmp)) {
+#endif
+#if !STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 && STM32_PWM_USE_TIM20
+ if (&PWMD20 == pwmp) {
+#endif
+#if STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 && STM32_PWM_USE_TIM20
+ if ((&PWMD1 == pwmp) || (&PWMD20 == pwmp)) {
+#endif
+#if !STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 && STM32_PWM_USE_TIM20
+ if ((&PWMD8 == pwmp) || (&PWMD20 == pwmp)) {
+#endif
+#if STM32_PWM_USE_TIM1 && STM32_PWM_USE_TIM8 && STM32_PWM_USE_TIM20
+ if ((&PWMD1 == pwmp) || (&PWMD8 == pwmp) || (&PWMD20 == pwmp)) {
+#endif
+ switch (pwmp->config->channels[0].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) {
+ case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW:
+ ccer |= STM32_TIM_CCER_CC1NP;
+ /* Falls through.*/
+ case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH:
+ ccer |= STM32_TIM_CCER_CC1NE;
+ /* Falls through.*/
+ default:
+ ;
+ }
+ switch (pwmp->config->channels[1].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) {
+ case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW:
+ ccer |= STM32_TIM_CCER_CC2NP;
+ /* Falls through.*/
+ case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH:
+ ccer |= STM32_TIM_CCER_CC2NE;
+ /* Falls through.*/
+ default:
+ ;
+ }
+ switch (pwmp->config->channels[2].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) {
+ case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW:
+ ccer |= STM32_TIM_CCER_CC3NP;
+ /* Falls through.*/
+ case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH:
+ ccer |= STM32_TIM_CCER_CC3NE;
+ /* Falls through.*/
+ default:
+ ;
+ }
+ switch (pwmp->config->channels[3].mode & PWM_COMPLEMENTARY_OUTPUT_MASK) {
+ case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW:
+ ccer |= STM32_TIM_CCER_CC4NP;
+ /* Falls through.*/
+ case PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH:
+ ccer |= STM32_TIM_CCER_CC4NE;
+ /* Falls through.*/
+ default:
+ ;
+ }
+ }
+#endif /* STM32_PWM_USE_ADVANCED*/
+
+ pwmp->tim->CCER = ccer;
+ pwmp->tim->EGR = STM32_TIM_EGR_UG; /* Update event. */
+ pwmp->tim->SR = 0; /* Clear pending IRQs. */
+ pwmp->tim->DIER = pwmp->config->dier & /* DMA-related DIER settings. */
+ ~STM32_TIM_DIER_IRQ_MASK;
+#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8 || STM32_PWM_USE_TIM20
+#if STM32_PWM_USE_ADVANCED
+ pwmp->tim->BDTR = pwmp->config->bdtr | STM32_TIM_BDTR_MOE;
+#else
+ pwmp->tim->BDTR = STM32_TIM_BDTR_MOE;
+#endif
+#endif
+ /* Timer configured and started.*/
+ pwmp->tim->CR1 = STM32_TIM_CR1_ARPE | STM32_TIM_CR1_URS |
+ STM32_TIM_CR1_CEN;
+}
+
+/**
+ * @brief Deactivates the PWM peripheral.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ *
+ * @notapi
+ */
+void pwm_lld_stop(PWMDriver *pwmp) {
+
+ /* If in ready state then disables the PWM clock.*/
+ if (pwmp->state == PWM_READY) {
+ pwmp->tim->CR1 = 0; /* Timer disabled. */
+ pwmp->tim->DIER = 0; /* All IRQs disabled. */
+ pwmp->tim->SR = 0; /* Clear eventual pending IRQs. */
+#if STM32_PWM_USE_TIM1 || STM32_PWM_USE_TIM8 || STM32_PWM_USE_TIM20
+ pwmp->tim->BDTR = 0;
+#endif
+
+#if STM32_PWM_USE_TIM1
+ if (&PWMD1 == pwmp) {
+#if !defined(STM32_TIM1_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM1_UP_NUMBER);
+ nvicDisableVector(STM32_TIM1_CC_NUMBER);
+#endif
+ rccDisableTIM1();
+ }
+#endif
+
+#if STM32_PWM_USE_TIM2
+ if (&PWMD2 == pwmp) {
+#if !defined(STM32_TIM2_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM2_NUMBER);
+#endif
+ rccDisableTIM2();
+ }
+#endif
+
+#if STM32_PWM_USE_TIM3
+ if (&PWMD3 == pwmp) {
+#if !defined(STM32_TIM3_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM3_NUMBER);
+#endif
+ rccDisableTIM3();
+ }
+#endif
+
+#if STM32_PWM_USE_TIM4
+ if (&PWMD4 == pwmp) {
+#if !defined(STM32_TIM4_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM4_NUMBER);
+#endif
+ rccDisableTIM4();
+ }
+#endif
+
+#if STM32_PWM_USE_TIM5
+ if (&PWMD5 == pwmp) {
+#if !defined(STM32_TIM5_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM5_NUMBER);
+#endif
+ rccDisableTIM5();
+ }
+#endif
+
+#if STM32_PWM_USE_TIM8
+ if (&PWMD8 == pwmp) {
+#if !defined(STM32_TIM8_SUPPRESS_ISR)
+ nvicDisableVector(STM32_TIM8_UP_NUMBER);
+ nvicDisableVector(STM32_TIM8_CC_NUMBER);
+#endif
+ rccDisableTIM8();
+ }
+#endif
+
+#if STM32_PWM_USE_TIM9
+ if (&PWMD9 == pwmp) {
+ rccDisableTIM9();
+ }
+#endif
+
+#if STM32_PWM_USE_TIM10
+ if (&PWMD10 == pwmp) {
+ rccDisableTIM10();
+ }
+#endif
+
+#if STM32_PWM_USE_TIM11
+ if (&PWMD11 == pwmp) {
+ rccDisableTIM11();
+ }
+#endif
+
+#if STM32_PWM_USE_TIM12
+ if (&PWMD12 == pwmp) {
+ rccDisableTIM12();
+ }
+#endif
+
+#if STM32_PWM_USE_TIM13
+ if (&PWMD13 == pwmp) {
+ rccDisableTIM13();
+ }
+#endif
+
+#if STM32_PWM_USE_TIM14
+ if (&PWMD14 == pwmp) {
+ rccDisableTIM14();
+ }
+#endif
+
+#if STM32_PWM_USE_TIM15
+ if (&PWMD15 == pwmp) {
+ rccDisableTIM15();
+ }
+#endif
+
+#if STM32_PWM_USE_TIM16
+ if (&PWMD16 == pwmp) {
+ rccDisableTIM16();
+ }
+#endif
+
+#if STM32_PWM_USE_TIM17
+ if (&PWMD17 == pwmp) {
+ rccDisableTIM17();
+ }
+#endif
+
+#if STM32_PWM_USE_TIM20
+ if (&PWMD20 == pwmp) {
+ rccDisableTIM20();
+ }
+#endif
+
+#if STM32_PWM_USE_TIM21
+ if (&PWMD21 == pwmp) {
+ rccDisableTIM21();
+ }
+#endif
+
+#if STM32_PWM_USE_TIM22
+ if (&PWMD22 == pwmp) {
+ rccDisableTIM22();
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Enables a PWM channel.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @post The channel is active using the specified configuration.
+ * @note The function has effect at the next cycle start.
+ * @note Channel notification is not enabled.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] channel PWM channel identifier (0...channels-1)
+ * @param[in] width PWM pulse width as clock pulses number
+ *
+ * @notapi
+ */
+void pwm_lld_enable_channel(PWMDriver *pwmp,
+ pwmchannel_t channel,
+ pwmcnt_t width) {
+
+ /* Changing channel duty cycle on the fly.*/
+#if STM32_TIM_MAX_CHANNELS <= 4
+ pwmp->tim->CCR[channel] = width;
+#else
+ if (channel < 4)
+ pwmp->tim->CCR[channel] = width;
+ else
+ pwmp->tim->CCXR[channel - 4] = width;
+#endif
+}
+
+/**
+ * @brief Disables a PWM channel and its notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @post The channel is disabled and its output line returned to the
+ * idle state.
+ * @note The function has effect at the next cycle start.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] channel PWM channel identifier (0...channels-1)
+ *
+ * @notapi
+ */
+void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) {
+
+#if STM32_TIM_MAX_CHANNELS <= 4
+ pwmp->tim->CCR[channel] = 0;
+ pwmp->tim->DIER &= ~(2 << channel);
+#else
+ if (channel < 4) {
+ pwmp->tim->CCR[channel] = 0;
+ pwmp->tim->DIER &= ~(2 << channel);
+ }
+ else
+ pwmp->tim->CCXR[channel - 4] = 0;
+#endif
+}
+
+/**
+ * @brief Enables the periodic activation edge notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @note If the notification is already enabled then the call has no effect.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ *
+ * @notapi
+ */
+void pwm_lld_enable_periodic_notification(PWMDriver *pwmp) {
+ uint32_t dier = pwmp->tim->DIER;
+
+ /* If the IRQ is not already enabled care must be taken to clear it,
+ it is probably already pending because the timer is running.*/
+ if ((dier & STM32_TIM_DIER_UIE) == 0) {
+ pwmp->tim->SR = ~STM32_TIM_SR_UIF;
+ pwmp->tim->DIER = dier | STM32_TIM_DIER_UIE;
+ }
+}
+
+/**
+ * @brief Disables the periodic activation edge notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @note If the notification is already disabled then the call has no effect.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ *
+ * @notapi
+ */
+void pwm_lld_disable_periodic_notification(PWMDriver *pwmp) {
+
+ pwmp->tim->DIER &= ~STM32_TIM_DIER_UIE;
+}
+
+/**
+ * @brief Enables a channel de-activation edge notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @pre The channel must have been activated using @p pwmEnableChannel().
+ * @note If the notification is already enabled then the call has no effect.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] channel PWM channel identifier (0...channels-1)
+ *
+ * @notapi
+ */
+void pwm_lld_enable_channel_notification(PWMDriver *pwmp,
+ pwmchannel_t channel) {
+ uint32_t dier = pwmp->tim->DIER;
+
+#if STM32_TIM_MAX_CHANNELS > 4
+ /* Channels 4 and 5 do not support callbacks.*/
+ osalDbgAssert(channel < 4, "callback not supported");
+#endif
+
+ /* If the IRQ is not already enabled care must be taken to clear it,
+ it is probably already pending because the timer is running.*/
+ if ((dier & (2 << channel)) == 0) {
+ pwmp->tim->SR = ~(2 << channel);
+ pwmp->tim->DIER = dier | (2 << channel);
+ }
+}
+
+/**
+ * @brief Disables a channel de-activation edge notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @pre The channel must have been activated using @p pwmEnableChannel().
+ * @note If the notification is already disabled then the call has no effect.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] channel PWM channel identifier (0...channels-1)
+ *
+ * @notapi
+ */
+void pwm_lld_disable_channel_notification(PWMDriver *pwmp,
+ pwmchannel_t channel) {
+
+ pwmp->tim->DIER &= ~(2 << channel);
+}
+
+/**
+ * @brief Common TIM2...TIM5,TIM9 IRQ handler.
+ * @note It is assumed that the various sources are only activated if the
+ * associated callback pointer is not equal to @p NULL in order to not
+ * perform an extra check in a potentially critical interrupt handler.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ *
+ * @notapi
+ */
+void pwm_lld_serve_interrupt(PWMDriver *pwmp) {
+ uint32_t sr;
+
+ sr = pwmp->tim->SR;
+ sr &= pwmp->tim->DIER & STM32_TIM_DIER_IRQ_MASK;
+ pwmp->tim->SR = ~sr;
+ if (((sr & STM32_TIM_SR_CC1IF) != 0) &&
+ (pwmp->config->channels[0].callback != NULL))
+ pwmp->config->channels[0].callback(pwmp);
+ if (((sr & STM32_TIM_SR_CC2IF) != 0) &&
+ (pwmp->config->channels[1].callback != NULL))
+ pwmp->config->channels[1].callback(pwmp);
+ if (((sr & STM32_TIM_SR_CC3IF) != 0) &&
+ (pwmp->config->channels[2].callback != NULL))
+ pwmp->config->channels[2].callback(pwmp);
+ if (((sr & STM32_TIM_SR_CC4IF) != 0) &&
+ (pwmp->config->channels[3].callback != NULL))
+ pwmp->config->channels[3].callback(pwmp);
+ if (((sr & STM32_TIM_SR_UIF) != 0) && (pwmp->config->callback != NULL))
+ pwmp->config->callback(pwmp);
+}
+
+#endif /* HAL_USE_PWM */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.h
new file mode 100644
index 0000000..4cf0f7c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.h
@@ -0,0 +1,1034 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/hal_pwm_lld.h
+ * @brief STM32 PWM subsystem low level driver header.
+ *
+ * @addtogroup PWM
+ * @{
+ */
+
+#ifndef HAL_PWM_LLD_H
+#define HAL_PWM_LLD_H
+
+#if HAL_USE_PWM || defined(__DOXYGEN__)
+
+#include "stm32_tim.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of PWM channels per PWM driver.
+ */
+#define PWM_CHANNELS STM32_TIM_MAX_CHANNELS
+
+/**
+ * @name STM32-specific PWM complementary output mode macros
+ * @{
+ */
+/**
+ * @brief Complementary output modes mask.
+ * @note This is an STM32-specific setting.
+ */
+#define PWM_COMPLEMENTARY_OUTPUT_MASK 0xF0
+
+/**
+ * @brief Complementary output not driven.
+ * @note This is an STM32-specific setting.
+ */
+#define PWM_COMPLEMENTARY_OUTPUT_DISABLED 0x00
+
+/**
+ * @brief Complementary output, active is logic level one.
+ * @note This is an STM32-specific setting.
+ * @note This setting is only available if the configuration option
+ * @p STM32_PWM_USE_ADVANCED is set to TRUE and only for advanced
+ * timers TIM1 and TIM8.
+ */
+#define PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH 0x10
+
+/**
+ * @brief Complementary output, active is logic level zero.
+ * @note This is an STM32-specific setting.
+ * @note This setting is only available if the configuration option
+ * @p STM32_PWM_USE_ADVANCED is set to TRUE and only for advanced
+ * timers TIM1 and TIM8.
+ */
+#define PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW 0x20
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief If advanced timer features switch.
+ * @details If set to @p TRUE the advanced features for TIM1 and TIM8 are
+ * enabled.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_ADVANCED) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_ADVANCED FALSE
+#endif
+
+/**
+ * @brief PWMD1 driver enable switch.
+ * @details If set to @p TRUE the support for PWMD1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_TIM1) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_TIM1 FALSE
+#endif
+
+/**
+ * @brief PWMD2 driver enable switch.
+ * @details If set to @p TRUE the support for PWMD2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_TIM2) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_TIM2 FALSE
+#endif
+
+/**
+ * @brief PWMD3 driver enable switch.
+ * @details If set to @p TRUE the support for PWMD3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_TIM3) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_TIM3 FALSE
+#endif
+
+/**
+ * @brief PWMD4 driver enable switch.
+ * @details If set to @p TRUE the support for PWMD4 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_TIM4) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_TIM4 FALSE
+#endif
+
+/**
+ * @brief PWMD5 driver enable switch.
+ * @details If set to @p TRUE the support for PWMD5 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_TIM5) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_TIM5 FALSE
+#endif
+
+/**
+ * @brief PWMD8 driver enable switch.
+ * @details If set to @p TRUE the support for PWMD8 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_TIM8) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_TIM8 FALSE
+#endif
+
+/**
+ * @brief PWMD9 driver enable switch.
+ * @details If set to @p TRUE the support for PWMD9 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_TIM9) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_TIM9 FALSE
+#endif
+
+/**
+ * @brief PWMD10 driver enable switch.
+ * @details If set to @p TRUE the support for PWMD10 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_TIM10) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_TIM10 FALSE
+#endif
+
+/**
+ * @brief PWMD11 driver enable switch.
+ * @details If set to @p TRUE the support for PWMD11 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_TIM11) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_TIM11 FALSE
+#endif
+
+/**
+ * @brief PWMD12 driver enable switch.
+ * @details If set to @p TRUE the support for PWMD12 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_TIM12) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_TIM12 FALSE
+#endif
+
+/**
+ * @brief PWMD13 driver enable switch.
+ * @details If set to @p TRUE the support for PWMD13 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_TIM13) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_TIM13 FALSE
+#endif
+
+/**
+ * @brief PWMD14 driver enable switch.
+ * @details If set to @p TRUE the support for PWMD14 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_TIM14) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_TIM14 FALSE
+#endif
+
+/**
+ * @brief PWMD15 driver enable switch.
+ * @details If set to @p TRUE the support for PWMD15 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_TIM15) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_TIM15 FALSE
+#endif
+
+/**
+ * @brief PWMD16 driver enable switch.
+ * @details If set to @p TRUE the support for PWMD16 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_TIM16) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_TIM16 FALSE
+#endif
+
+/**
+ * @brief PWMD17 driver enable switch.
+ * @details If set to @p TRUE the support for PWMD17 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_TIM17) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_TIM17 FALSE
+#endif
+
+/**
+ * @brief PWMD20 driver enable switch.
+ * @details If set to @p TRUE the support for PWMD20 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_TIM20) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_TIM20 FALSE
+#endif
+
+/**
+ * @brief PWMD21 driver enable switch.
+ * @details If set to @p TRUE the support for PWMD21 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_TIM21) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_TIM21 FALSE
+#endif
+
+/**
+ * @brief PWMD22 driver enable switch.
+ * @details If set to @p TRUE the support for PWMD22 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_PWM_USE_TIM22) || defined(__DOXYGEN__)
+#define STM32_PWM_USE_TIM22 FALSE
+#endif
+
+/**
+ * @brief PWMD1 interrupt priority level setting.
+ */
+#if !defined(STM32_PWM_TIM1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_PWM_TIM1_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief PWMD2 interrupt priority level setting.
+ */
+#if !defined(STM32_PWM_TIM2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_PWM_TIM2_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief PWMD3 interrupt priority level setting.
+ */
+#if !defined(STM32_PWM_TIM3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_PWM_TIM3_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief PWMD4 interrupt priority level setting.
+ */
+#if !defined(STM32_PWM_TIM4_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_PWM_TIM4_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief PWMD5 interrupt priority level setting.
+ */
+#if !defined(STM32_PWM_TIM5_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_PWM_TIM5_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief PWMD8 interrupt priority level setting.
+ */
+#if !defined(STM32_PWM_TIM8_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_PWM_TIM8_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief PWMD9 interrupt priority level setting.
+ */
+#if !defined(STM32_PWM_TIM9_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_PWM_TIM9_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief PWMD10 interrupt priority level setting.
+ */
+#if !defined(STM32_PWM_TIM10_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_PWM_TIM10_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief PWMD11 interrupt priority level setting.
+ */
+#if !defined(STM32_PWM_TIM11_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_PWM_TIM11_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief PWMD12 interrupt priority level setting.
+ */
+#if !defined(STM32_PWM_TIM12_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_PWM_TIM12_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief PWMD13 interrupt priority level setting.
+ */
+#if !defined(STM32_PWM_TIM13_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_PWM_TIM13_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief PWMD14 interrupt priority level setting.
+ */
+#if !defined(STM32_PWM_TIM14_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_PWM_TIM14_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief PWMD15 interrupt priority level setting.
+ */
+#if !defined(STM32_PWM_TIM15_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_PWM_TIM15_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief PWMD16 interrupt priority level setting.
+ */
+#if !defined(STM32_PWM_TIM16_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_PWM_TIM16_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief PWMD17 interrupt priority level setting.
+ */
+#if !defined(STM32_PWM_TIM17_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_PWM_TIM17_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief PWMD20 interrupt priority level setting.
+ */
+#if !defined(STM32_PWM_TIM20_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_PWM_TIM20_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief PWMD21 interrupt priority level setting.
+ */
+#if !defined(STM32_PWM_TIM21_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_PWM_TIM21_IRQ_PRIORITY 7
+#endif
+
+/**
+ * @brief PWMD22 interrupt priority level setting.
+ */
+#if !defined(STM32_PWM_TIM22_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_PWM_TIM22_IRQ_PRIORITY 7
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Configuration checks. */
+/*===========================================================================*/
+
+#if !defined(STM32_HAS_TIM1)
+#define STM32_HAS_TIM1 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM2)
+#define STM32_HAS_TIM2 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM3)
+#define STM32_HAS_TIM3 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM4)
+#define STM32_HAS_TIM4 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM5)
+#define STM32_HAS_TIM5 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM8)
+#define STM32_HAS_TIM8 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM9)
+#define STM32_HAS_TIM9 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM10)
+#define STM32_HAS_TIM10 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM11)
+#define STM32_HAS_TIM11 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM12)
+#define STM32_HAS_TIM12 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM13)
+#define STM32_HAS_TIM13 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM14)
+#define STM32_HAS_TIM14 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM15)
+#define STM32_HAS_TIM15 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM16)
+#define STM32_HAS_TIM16 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM17)
+#define STM32_HAS_TIM17 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM20)
+#define STM32_HAS_TIM20 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM21)
+#define STM32_HAS_TIM21 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM22)
+#define STM32_HAS_TIM22 FALSE
+#endif
+
+#if STM32_PWM_USE_TIM1 && !STM32_HAS_TIM1
+#error "TIM1 not present in the selected device"
+#endif
+
+#if STM32_PWM_USE_TIM2 && !STM32_HAS_TIM2
+#error "TIM2 not present in the selected device"
+#endif
+
+#if STM32_PWM_USE_TIM3 && !STM32_HAS_TIM3
+#error "TIM3 not present in the selected device"
+#endif
+
+#if STM32_PWM_USE_TIM4 && !STM32_HAS_TIM4
+#error "TIM4 not present in the selected device"
+#endif
+
+#if STM32_PWM_USE_TIM5 && !STM32_HAS_TIM5
+#error "TIM5 not present in the selected device"
+#endif
+
+#if STM32_PWM_USE_TIM8 && !STM32_HAS_TIM8
+#error "TIM8 not present in the selected device"
+#endif
+
+#if STM32_PWM_USE_TIM9 && !STM32_HAS_TIM9
+#error "TIM9 not present in the selected device"
+#endif
+
+#if STM32_PWM_USE_TIM10 && !STM32_HAS_TIM10
+#error "TIM10 not present in the selected device"
+#endif
+
+#if STM32_PWM_USE_TIM11 && !STM32_HAS_TIM11
+#error "TIM11 not present in the selected device"
+#endif
+
+#if STM32_PWM_USE_TIM12 && !STM32_HAS_TIM12
+#error "TIM12 not present in the selected device"
+#endif
+
+#if STM32_PWM_USE_TIM13 && !STM32_HAS_TIM13
+#error "TIM13 not present in the selected device"
+#endif
+
+#if STM32_PWM_USE_TIM14 && !STM32_HAS_TIM14
+#error "TIM14 not present in the selected device"
+#endif
+
+#if STM32_PWM_USE_TIM15 && !STM32_HAS_TIM15
+#error "TIM15 not present in the selected device"
+#endif
+
+#if STM32_PWM_USE_TIM16 && !STM32_HAS_TIM16
+#error "TIM16 not present in the selected device"
+#endif
+
+#if STM32_PWM_USE_TIM17 && !STM32_HAS_TIM17
+#error "TIM17 not present in the selected device"
+#endif
+
+#if STM32_PWM_USE_TIM20 && !STM32_HAS_TIM20
+#error "TIM20 not present in the selected device"
+#endif
+
+#if STM32_PWM_USE_TIM21 && !STM32_HAS_TIM21
+#error "TIM21 not present in the selected device"
+#endif
+
+#if STM32_PWM_USE_TIM22 && !STM32_HAS_TIM22
+#error "TIM22 not present in the selected device"
+#endif
+
+#if !STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM2 && \
+ !STM32_PWM_USE_TIM3 && !STM32_PWM_USE_TIM4 && \
+ !STM32_PWM_USE_TIM5 && !STM32_PWM_USE_TIM8 && \
+ !STM32_PWM_USE_TIM9 && !STM32_PWM_USE_TIM10 && \
+ !STM32_PWM_USE_TIM11 && !STM32_PWM_USE_TIM11 && \
+ !STM32_PWM_USE_TIM13 && !STM32_PWM_USE_TIM13 && \
+ !STM32_PWM_USE_TIM15 && !STM32_PWM_USE_TIM15 && \
+ !STM32_PWM_USE_TIM17 && !STM32_PWM_USE_TIM20 && \
+ !STM32_PWM_USE_TIM21 && !STM32_PWM_USE_TIM22
+#error "PWM driver activated but no TIM peripheral assigned"
+#endif
+
+#if STM32_PWM_USE_ADVANCED && !STM32_PWM_USE_TIM1 && !STM32_PWM_USE_TIM8 && \
+ !STM32_PWM_USE_TIM20
+#error "advanced mode selected but no advanced timer assigned"
+#endif
+
+/* Checks on allocation of TIMx units.*/
+#if STM32_PWM_USE_TIM1
+#if defined(STM32_TIM1_IS_USED)
+#error "PWMD1 requires TIM1 but the timer is already used"
+#else
+#define STM32_TIM1_IS_USED
+#endif
+#endif
+
+#if STM32_PWM_USE_TIM2
+#if defined(STM32_TIM2_IS_USED)
+#error "PWMD2 requires TIM2 but the timer is already used"
+#else
+#define STM32_TIM2_IS_USED
+#endif
+#endif
+
+#if STM32_PWM_USE_TIM3
+#if defined(STM32_TIM3_IS_USED)
+#error "PWMD3 requires TIM3 but the timer is already used"
+#else
+#define STM32_TIM3_IS_USED
+#endif
+#endif
+
+#if STM32_PWM_USE_TIM4
+#if defined(STM32_TIM4_IS_USED)
+#error "PWMD4 requires TIM4 but the timer is already used"
+#else
+#define STM32_TIM4_IS_USED
+#endif
+#endif
+
+#if STM32_PWM_USE_TIM5
+#if defined(STM32_TIM5_IS_USED)
+#error "PWMD5 requires TIM5 but the timer is already used"
+#else
+#define STM32_TIM5_IS_USED
+#endif
+#endif
+
+#if STM32_PWM_USE_TIM8
+#if defined(STM32_TIM8_IS_USED)
+#error "PWMD8 requires TIM8 but the timer is already used"
+#else
+#define STM32_TIM8_IS_USED
+#endif
+#endif
+
+#if STM32_PWM_USE_TIM9
+#if defined(STM32_TIM9_IS_USED)
+#error "PWMD9 requires TIM9 but the timer is already used"
+#else
+#define STM32_TIM9_IS_USED
+#endif
+#endif
+
+#if STM32_PWM_USE_TIM10
+#if defined(STM32_TIM10_IS_USED)
+#error "PWMD10 requires TIM10 but the timer is already used"
+#else
+#define STM32_TIM10_IS_USED
+#endif
+#endif
+
+#if STM32_PWM_USE_TIM11
+#if defined(STM32_TIM11_IS_USED)
+#error "PWMD11 requires TIM11 but the timer is already used"
+#else
+#define STM32_TIM11_IS_USED
+#endif
+#endif
+
+#if STM32_PWM_USE_TIM12
+#if defined(STM32_TIM12_IS_USED)
+#error "PWMD12 requires TIM12 but the timer is already used"
+#else
+#define STM32_TIM12_IS_USED
+#endif
+#endif
+
+#if STM32_PWM_USE_TIM13
+#if defined(STM32_TIM13_IS_USED)
+#error "PWMD13 requires TIM13 but the timer is already used"
+#else
+#define STM32_TIM13_IS_USED
+#endif
+#endif
+
+#if STM32_PWM_USE_TIM14
+#if defined(STM32_TIM14_IS_USED)
+#error "PWMD14 requires TIM14 but the timer is already used"
+#else
+#define STM32_TIM14_IS_USED
+#endif
+#endif
+
+#if STM32_PWM_USE_TIM15
+#if defined(STM32_TIM15_IS_USED)
+#error "PWMD15 requires TIM15 but the timer is already used"
+#else
+#define STM32_TIM15_IS_USED
+#endif
+#endif
+
+#if STM32_PWM_USE_TIM16
+#if defined(STM32_TIM16_IS_USED)
+#error "PWMD16 requires TIM16 but the timer is already used"
+#else
+#define STM32_TIM16_IS_USED
+#endif
+#endif
+
+#if STM32_PWM_USE_TIM17
+#if defined(STM32_TIM17_IS_USED)
+#error "PWMD17 requires TIM17 but the timer is already used"
+#else
+#define STM32_TIM17_IS_USED
+#endif
+#endif
+
+#if STM32_PWM_USE_TIM20
+#if defined(STM32_TIM20_IS_USED)
+#error "PWMD20 requires TIM20 but the timer is already used"
+#else
+#define STM32_TIM20_IS_USED
+#endif
+#endif
+
+#if STM32_PWM_USE_TIM21
+#if defined(STM32_TIM21_IS_USED)
+#error "PWMD21 requires TIM21 but the timer is already used"
+#else
+#define STM32_TIM21_IS_USED
+#endif
+#endif
+
+#if STM32_PWM_USE_TIM22
+#if defined(STM32_TIM22_IS_USED)
+#error "PWMD22 requires TIM22 but the timer is already used"
+#else
+#define STM32_TIM22_IS_USED
+#endif
+#endif
+
+/* IRQ priority checks.*/
+#if STM32_PWM_USE_TIM1 && !defined(STM32_TIM1_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM1"
+#endif
+
+#if STM32_PWM_USE_TIM2 && !defined(STM32_TIM2_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM2"
+#endif
+
+#if STM32_PWM_USE_TIM3 && !defined(STM32_TIM3_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM3"
+#endif
+
+#if STM32_PWM_USE_TIM4 && !defined(STM32_TIM4_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM4_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM4"
+#endif
+
+#if STM32_PWM_USE_TIM5 && !defined(STM32_TIM5_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM5_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM5"
+#endif
+
+#if STM32_PWM_USE_TIM8 && !defined(STM32_TIM8_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM8_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM8"
+#endif
+
+#if STM32_PWM_USE_TIM9 && !defined(STM32_TIM9_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM9_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM9"
+#endif
+
+#if STM32_PWM_USE_TIM10 && !defined(STM32_TIM10_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM10_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM10"
+#endif
+
+#if STM32_PWM_USE_TIM11 && !defined(STM32_TIM11_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM11_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM11"
+#endif
+
+#if STM32_PWM_USE_TIM12 && !defined(STM32_TIM12_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM12_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM12"
+#endif
+
+#if STM32_PWM_USE_TIM13 && !defined(STM32_TIM13_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM13_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM13"
+#endif
+
+#if STM32_PWM_USE_TIM14 && !defined(STM32_TIM14_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM14_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM14"
+#endif
+
+#if STM32_PWM_USE_TIM15 && !defined(STM32_TIM15_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM15_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM15"
+#endif
+
+#if STM32_PWM_USE_TIM16 && !defined(STM32_TIM16_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM16_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM16"
+#endif
+
+#if STM32_PWM_USE_TIM17 && !defined(STM32_TIM17_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM17_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM17"
+#endif
+
+#if STM32_PWM_USE_TIM20 && !defined(STM32_TIM20_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM20_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM20"
+#endif
+
+#if STM32_PWM_USE_TIM21 && !defined(STM32_TIM21_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM21_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM21"
+#endif
+
+#if STM32_PWM_USE_TIM22 && !defined(STM32_TIM22_SUPPRESS_ISR) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_PWM_TIM22_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to TIM22"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a PWM mode.
+ */
+typedef uint32_t pwmmode_t;
+
+/**
+ * @brief Type of a PWM channel.
+ */
+typedef uint8_t pwmchannel_t;
+
+/**
+ * @brief Type of a channels mask.
+ */
+typedef uint32_t pwmchnmsk_t;
+
+/**
+ * @brief Type of a PWM counter.
+ */
+typedef uint32_t pwmcnt_t;
+
+/**
+ * @brief Type of a PWM driver channel configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief Channel active logic level.
+ */
+ pwmmode_t mode;
+ /**
+ * @brief Channel callback pointer.
+ * @note This callback is invoked on the channel compare event. If set to
+ * @p NULL then the callback is disabled.
+ */
+ pwmcallback_t callback;
+ /* End of the mandatory fields.*/
+} PWMChannelConfig;
+
+/**
+ * @brief Type of a PWM driver configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief Timer clock in Hz.
+ * @note The low level can use assertions in order to catch invalid
+ * frequency specifications.
+ */
+ uint32_t frequency;
+ /**
+ * @brief PWM period in ticks.
+ * @note The low level can use assertions in order to catch invalid
+ * period specifications.
+ */
+ pwmcnt_t period;
+ /**
+ * @brief Periodic callback pointer.
+ * @note This callback is invoked on PWM counter reset. If set to
+ * @p NULL then the callback is disabled.
+ */
+ pwmcallback_t callback;
+ /**
+ * @brief Channels configurations.
+ */
+ PWMChannelConfig channels[PWM_CHANNELS];
+ /* End of the mandatory fields.*/
+ /**
+ * @brief TIM CR2 register initialization data.
+ * @note The value of this field should normally be equal to zero.
+ */
+ uint32_t cr2;
+#if STM32_PWM_USE_ADVANCED || defined(__DOXYGEN__)
+ /**
+ * @brief TIM BDTR (break & dead-time) register initialization data.
+ * @note The value of this field should normally be equal to zero.
+ */ \
+ uint32_t bdtr;
+#endif
+ /**
+ * @brief TIM DIER register initialization data.
+ * @note The value of this field should normally be equal to zero.
+ * @note Only the DMA-related bits can be specified in this field.
+ */
+ uint32_t dier;
+} PWMConfig;
+
+/**
+ * @brief Structure representing a PWM driver.
+ */
+struct PWMDriver {
+ /**
+ * @brief Driver state.
+ */
+ pwmstate_t state;
+ /**
+ * @brief Current driver configuration data.
+ */
+ const PWMConfig *config;
+ /**
+ * @brief Current PWM period in ticks.
+ */
+ pwmcnt_t period;
+ /**
+ * @brief Mask of the enabled channels.
+ */
+ pwmchnmsk_t enabled;
+ /**
+ * @brief Number of channels in this instance.
+ */
+ pwmchannel_t channels;
+#if defined(PWM_DRIVER_EXT_FIELDS)
+ PWM_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Timer base clock.
+ */
+ uint32_t clock;
+ /**
+ * @brief Pointer to the TIMx registers block.
+ */
+ stm32_tim_t *tim;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Changes the period the PWM peripheral.
+ * @details This function changes the period of a PWM unit that has already
+ * been activated using @p pwmStart().
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @post The PWM unit period is changed to the new value.
+ * @note The function has effect at the next cycle start.
+ * @note If a period is specified that is shorter than the pulse width
+ * programmed in one of the channels then the behavior is not
+ * guaranteed.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] period new cycle time in ticks
+ *
+ * @notapi
+ */
+#define pwm_lld_change_period(pwmp, period) \
+ ((pwmp)->tim->ARR = ((period) - 1))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_PWM_USE_TIM1 && !defined(__DOXYGEN__)
+extern PWMDriver PWMD1;
+#endif
+
+#if STM32_PWM_USE_TIM2 && !defined(__DOXYGEN__)
+extern PWMDriver PWMD2;
+#endif
+
+#if STM32_PWM_USE_TIM3 && !defined(__DOXYGEN__)
+extern PWMDriver PWMD3;
+#endif
+
+#if STM32_PWM_USE_TIM4 && !defined(__DOXYGEN__)
+extern PWMDriver PWMD4;
+#endif
+
+#if STM32_PWM_USE_TIM5 && !defined(__DOXYGEN__)
+extern PWMDriver PWMD5;
+#endif
+
+#if STM32_PWM_USE_TIM8 && !defined(__DOXYGEN__)
+extern PWMDriver PWMD8;
+#endif
+
+#if STM32_PWM_USE_TIM9 && !defined(__DOXYGEN__)
+extern PWMDriver PWMD9;
+#endif
+
+#if STM32_PWM_USE_TIM10 && !defined(__DOXYGEN__)
+extern PWMDriver PWMD10;
+#endif
+
+#if STM32_PWM_USE_TIM11 && !defined(__DOXYGEN__)
+extern PWMDriver PWMD11;
+#endif
+
+#if STM32_PWM_USE_TIM12 && !defined(__DOXYGEN__)
+extern PWMDriver PWMD12;
+#endif
+
+#if STM32_PWM_USE_TIM13 && !defined(__DOXYGEN__)
+extern PWMDriver PWMD13;
+#endif
+
+#if STM32_PWM_USE_TIM14 && !defined(__DOXYGEN__)
+extern PWMDriver PWMD14;
+#endif
+
+#if STM32_PWM_USE_TIM15 && !defined(__DOXYGEN__)
+extern PWMDriver PWMD15;
+#endif
+
+#if STM32_PWM_USE_TIM16 && !defined(__DOXYGEN__)
+extern PWMDriver PWMD16;
+#endif
+
+#if STM32_PWM_USE_TIM17 && !defined(__DOXYGEN__)
+extern PWMDriver PWMD17;
+#endif
+
+#if STM32_PWM_USE_TIM20 && !defined(__DOXYGEN__)
+extern PWMDriver PWMD20;
+#endif
+
+#if STM32_PWM_USE_TIM21 && !defined(__DOXYGEN__)
+extern PWMDriver PWMD21;
+#endif
+
+#if STM32_PWM_USE_TIM22 && !defined(__DOXYGEN__)
+extern PWMDriver PWMD22;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void pwm_lld_init(void);
+ void pwm_lld_start(PWMDriver *pwmp);
+ void pwm_lld_stop(PWMDriver *pwmp);
+ void pwm_lld_enable_channel(PWMDriver *pwmp,
+ pwmchannel_t channel,
+ pwmcnt_t width);
+ void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel);
+ void pwm_lld_enable_periodic_notification(PWMDriver *pwmp);
+ void pwm_lld_disable_periodic_notification(PWMDriver *pwmp);
+ void pwm_lld_enable_channel_notification(PWMDriver *pwmp,
+ pwmchannel_t channel);
+ void pwm_lld_disable_channel_notification(PWMDriver *pwmp,
+ pwmchannel_t channel);
+ void pwm_lld_serve_interrupt(PWMDriver *pwmp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_PWM */
+
+#endif /* HAL_PWM_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c
new file mode 100644
index 0000000..4c657b5
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.c
@@ -0,0 +1,492 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/hal_st_lld.c
+ * @brief ST Driver subsystem low level driver code.
+ *
+ * @addtogroup ST
+ * @{
+ */
+
+#include "hal.h"
+
+#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING
+
+#if (OSAL_ST_RESOLUTION == 32)
+#define ST_ARR_INIT 0xFFFFFFFFU
+#else
+#define ST_ARR_INIT 0x0000FFFFU
+#endif
+
+#if STM32_ST_USE_TIMER == 2
+
+#if !STM32_HAS_TIM2
+#error "TIM2 not present in the selected device"
+#endif
+
+#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM2_IS_32BITS
+#error "TIM2 is not a 32bits timer"
+#endif
+
+#define ST_HANDLER STM32_TIM2_HANDLER
+#define ST_NUMBER STM32_TIM2_NUMBER
+#define ST_CLOCK_SRC STM32_TIMCLK1
+#define ST_ENABLE_CLOCK() rccEnableTIM2(true)
+#if defined(STM32F1XX)
+#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM2_STOP
+#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX)
+#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM2_STOP
+#elif defined(STM32G0XX)
+#define ST_ENABLE_STOP() DBG->APBFZ1 |= DBG_APB_FZ1_DBG_TIM2_STOP
+#elif defined(STM32H7XX)
+#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM2
+#else
+#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM2_STOP
+#endif
+
+#elif STM32_ST_USE_TIMER == 3
+
+#if !STM32_HAS_TIM3
+#error "TIM3 not present in the selected device"
+#endif
+
+#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM3_IS_32BITS
+#error "TIM3 is not a 32bits timer"
+#endif
+
+#define ST_HANDLER STM32_TIM3_HANDLER
+#define ST_NUMBER STM32_TIM3_NUMBER
+#define ST_CLOCK_SRC STM32_TIMCLK1
+#define ST_ENABLE_CLOCK() rccEnableTIM3(true)
+#if defined(STM32F1XX)
+#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM3_STOP
+#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX)
+#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM3_STOP
+#elif defined(STM32G0XX)
+#define ST_ENABLE_STOP() DBG->APBFZ1 |= DBG_APB_FZ1_DBG_TIM3_STOP
+#elif defined(STM32H7XX)
+#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM3
+#else
+#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM3_STOP
+#endif
+
+#elif STM32_ST_USE_TIMER == 4
+
+#if !STM32_HAS_TIM4
+#error "TIM4 not present in the selected device"
+#endif
+
+#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM4_IS_32BITS
+#error "TIM4 is not a 32bits timer"
+#endif
+
+#define ST_HANDLER STM32_TIM4_HANDLER
+#define ST_NUMBER STM32_TIM4_NUMBER
+#define ST_CLOCK_SRC STM32_TIMCLK1
+#define ST_ENABLE_CLOCK() rccEnableTIM4(true)
+#if defined(STM32F1XX)
+#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM4_STOP
+#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX)
+#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM4_STOP
+#elif defined(STM32H7XX)
+#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM4
+#else
+#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM4_STOP
+#endif
+
+#elif STM32_ST_USE_TIMER == 5
+
+#if !STM32_HAS_TIM5
+#error "TIM5 not present in the selected device"
+#endif
+
+#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM5_IS_32BITS
+#error "TIM5 is not a 32bits timer"
+#endif
+
+#define ST_HANDLER STM32_TIM5_HANDLER
+#define ST_NUMBER STM32_TIM5_NUMBER
+#define ST_CLOCK_SRC STM32_TIMCLK1
+#define ST_ENABLE_CLOCK() rccEnableTIM5(true)
+#if defined(STM32F1XX)
+#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM5_STOP
+#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX)
+#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM5_STOP
+#elif defined(STM32H7XX)
+#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM5
+#else
+#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM5_STOP
+#endif
+
+#elif STM32_ST_USE_TIMER == 9
+
+#if !STM32_HAS_TIM9
+#error "TIM9 not present in the selected device"
+#endif
+
+#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM9_IS_32BITS
+#error "TIM9 is not a 32bits timer"
+#endif
+
+#define ST_HANDLER STM32_TIM9_HANDLER
+#define ST_NUMBER STM32_TIM9_NUMBER
+#define ST_CLOCK_SRC STM32_TIMCLK2
+#define ST_ENABLE_CLOCK() rccEnableTIM9(true)
+#if defined(STM32F1XX)
+#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM9_STOP
+#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX)
+#define ST_ENABLE_STOP() DBGMCU->APB2FZR1 |= DBGMCU_APB2FZR1_DBG_TIM9_STOP
+#elif defined(STM32H7XX)
+#define ST_ENABLE_STOP() DBGMCU->APB2LFZ1 |= DBGMCU_APB2LFZ1_DBG_TIM9
+#else
+#define ST_ENABLE_STOP() DBGMCU->APB2FZ |= DBGMCU_APB2_FZ_DBG_TIM9_STOP
+#endif
+
+#elif STM32_ST_USE_TIMER == 10
+
+#if !STM32_HAS_TIM10
+#error "TIM10 not present in the selected device"
+#endif
+
+#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM10_IS_32BITS
+#error "TIM10 is not a 32bits timer"
+#endif
+
+#define ST_HANDLER STM32_TIM10_HANDLER
+#define ST_NUMBER STM32_TIM10_NUMBER
+#define ST_CLOCK_SRC STM32_TIMCLK2
+#define ST_ENABLE_CLOCK() rccEnableTIM10(true)
+#if defined(STM32F1XX)
+#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM10_STOP
+#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX)
+#define ST_ENABLE_STOP() DBGMCU->APB2FZR1 |= DBGMCU_APB2FZR1_DBG_TIM10_STOP
+#elif defined(STM32H7XX)
+#define ST_ENABLE_STOP() DBGMCU->APB2LFZ1 |= DBGMCU_APB2LFZ1_DBG_TIM10
+#else
+#define ST_ENABLE_STOP() DBGMCU->APB2FZ |= DBGMCU_APB2_FZ_DBG_TIM10_STOP
+#endif
+
+#elif STM32_ST_USE_TIMER == 11
+
+#if !STM32_HAS_TIM11
+#error "TIM11 not present in the selected device"
+#endif
+
+#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM11_IS_32BITS
+#error "TIM11 is not a 32bits timer"
+#endif
+
+#define ST_HANDLER STM32_TIM11_HANDLER
+#define ST_NUMBER STM32_TIM11_NUMBER
+#define ST_CLOCK_SRC STM32_TIMCLK2
+#define ST_ENABLE_CLOCK() rccEnableTIM11(true)
+#if defined(STM32F1XX)
+#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM11_STOP
+#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX)
+#define ST_ENABLE_STOP() DBGMCU->APB2FZR1 |= DBGMCU_APB2FZR1_DBG_TIM11_STOP
+#elif defined(STM32H7XX)
+#define ST_ENABLE_STOP() DBGMCU->APB2LFZ1 |= DBGMCU_APB2LFZ1_DBG_TIM11
+#else
+#define ST_ENABLE_STOP() DBGMCU->APB2FZ |= DBGMCU_APB2_FZ_DBG_TIM11_STOP
+#endif
+
+#elif STM32_ST_USE_TIMER == 12
+
+#if !STM32_HAS_TIM12
+#error "TIM12 not present in the selected device"
+#endif
+
+#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM12_IS_32BITS
+#error "TIM12 is not a 32bits timer"
+#endif
+
+#define ST_HANDLER STM32_TIM12_HANDLER
+#define ST_NUMBER STM32_TIM12_NUMBER
+#define ST_CLOCK_SRC STM32_TIMCLK1
+#define ST_ENABLE_CLOCK() rccEnableTIM12(true)
+#if defined(STM32F1XX)
+#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM12_STOP
+#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX)
+#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM12_STOP
+#elif defined(STM32H7XX)
+#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM12
+#else
+#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM12_STOP
+#endif
+
+#elif STM32_ST_USE_TIMER == 13
+
+#if !STM32_HAS_TIM13
+#error "TIM13 not present in the selected device"
+#endif
+
+#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM13_IS_32BITS
+#error "TIM13 is not a 32bits timer"
+#endif
+
+#define ST_HANDLER STM32_TIM13_HANDLER
+#define ST_NUMBER STM32_TIM13_NUMBER
+#define ST_CLOCK_SRC STM32_TIMCLK1
+#define ST_ENABLE_CLOCK() rccEnableTIM13(true)
+#if defined(STM32F1XX)
+#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM13_STOP
+#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX)
+#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM13_STOP
+#elif defined(STM32H7XX)
+#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM13
+#else
+#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM13_STOP
+#endif
+
+#elif STM32_ST_USE_TIMER == 14
+
+#if !STM32_HAS_TIM14
+#error "TIM14 not present in the selected device"
+#endif
+
+#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM14_IS_32BITS
+#error "TIM14 is not a 32bits timer"
+#endif
+
+#define ST_HANDLER STM32_TIM14_HANDLER
+#define ST_NUMBER STM32_TIM14_NUMBER
+#define ST_CLOCK_SRC STM32_TIMCLK1
+#define ST_ENABLE_CLOCK() rccEnableTIM14(true)
+#if defined(STM32F1XX)
+#define ST_ENABLE_STOP() DBGMCU->CR |= DBGMCU_CR_DBG_TIM14_STOP
+#elif defined(STM32L4XX) || defined(STM32L4XXP) || defined(STM32G4XX)
+#define ST_ENABLE_STOP() DBGMCU->APB1FZR1 |= DBGMCU_APB1FZR1_DBG_TIM14_STOP
+#elif defined(STM32H7XX)
+#define ST_ENABLE_STOP() DBGMCU->APB1LFZ1 |= DBGMCU_APB1LFZ1_DBG_TIM14
+#else
+#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM14_STOP
+#endif
+
+#elif STM32_ST_USE_TIMER == 21
+
+#if !STM32_HAS_TIM21
+#error "TIM21 not present in the selected device"
+#endif
+
+#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM21_IS_32BITS
+#error "TIM21 is not a 32bits timer"
+#endif
+
+#define ST_HANDLER STM32_TIM21_HANDLER
+#define ST_NUMBER STM32_TIM21_NUMBER
+#define ST_CLOCK_SRC STM32_TIMCLK2
+#define ST_ENABLE_CLOCK() rccEnableTIM21(true)
+#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB2_FZ_DBG_TIM21_STOP
+
+#elif STM32_ST_USE_TIMER == 22
+
+#if !STM32_HAS_TIM22
+#error "TIM22 not present in the selected device"
+#endif
+
+#if (OSAL_ST_RESOLUTION == 32) && !STM32_TIM22_IS_32BITS
+#error "TIM21 is not a 32bits timer"
+#endif
+
+#define ST_HANDLER STM32_TIM22_HANDLER
+#define ST_NUMBER STM32_TIM22_NUMBER
+#define ST_CLOCK_SRC STM32_TIMCLK2
+#define ST_ENABLE_CLOCK() rccEnableTIM22(true)
+#define ST_ENABLE_STOP() DBGMCU->APB1FZ |= DBGMCU_APB2_FZ_DBG_TIM21_STOP
+
+#else
+#error "STM32_ST_USE_TIMER specifies an unsupported timer"
+#endif
+
+#if ST_CLOCK_SRC % OSAL_ST_FREQUENCY != 0
+#error "the selected ST frequency is not obtainable because integer rounding"
+#endif
+
+#if (ST_CLOCK_SRC / OSAL_ST_FREQUENCY) - 1 > 0xFFFF
+#error "the selected ST frequency is not obtainable because TIM timer prescaler limits"
+#endif
+
+#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
+
+#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC
+
+#define ST_HANDLER SysTick_Handler
+
+#if defined(STM32_CORE_CK)
+#define SYSTICK_CK STM32_CORE_CK
+#else
+#define SYSTICK_CK STM32_HCLK
+#endif
+
+#if SYSTICK_CK % OSAL_ST_FREQUENCY != 0
+#error "the selected ST frequency is not obtainable because integer rounding"
+#endif
+
+#if (SYSTICK_CK / OSAL_ST_FREQUENCY) - 1 > 0xFFFFFF
+#error "the selected ST frequency is not obtainable because SysTick timer counter limits"
+#endif
+
+#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if !defined(STM32_SYSTICK_SUPPRESS_ISR)
+/**
+ * @brief Interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(ST_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ st_lld_serve_interrupt();
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level ST driver initialization.
+ *
+ * @notapi
+ */
+void st_lld_init(void) {
+
+#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING
+ /* Free running counter mode.*/
+
+ /* Enabling timer clock.*/
+ ST_ENABLE_CLOCK();
+
+ /* Enabling the stop mode during debug for this timer.*/
+ ST_ENABLE_STOP();
+
+ /* Initializing the counter in free running mode.*/
+ STM32_ST_TIM->PSC = (ST_CLOCK_SRC / OSAL_ST_FREQUENCY) - 1;
+ STM32_ST_TIM->ARR = ST_ARR_INIT;
+ STM32_ST_TIM->CCMR1 = 0;
+ STM32_ST_TIM->CCR[0] = 0;
+#if ST_LLD_NUM_ALARMS > 1
+ STM32_ST_TIM->CCR[1] = 0;
+#endif
+#if ST_LLD_NUM_ALARMS > 2
+ STM32_ST_TIM->CCR[2] = 0;
+#endif
+#if ST_LLD_NUM_ALARMS > 3
+ STM32_ST_TIM->CCR[3] = 0;
+#endif
+ STM32_ST_TIM->DIER = 0;
+ STM32_ST_TIM->CR2 = 0;
+ STM32_ST_TIM->EGR = TIM_EGR_UG;
+ STM32_ST_TIM->CR1 = TIM_CR1_CEN;
+
+#if !defined(STM32_SYSTICK_SUPPRESS_ISR)
+ /* IRQ enabled.*/
+ nvicEnableVector(ST_NUMBER, STM32_ST_IRQ_PRIORITY);
+#endif
+#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
+
+#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC
+ /* Periodic systick mode, the Cortex-Mx internal systick timer is used
+ in this mode.*/
+ SysTick->LOAD = (SYSTICK_CK / OSAL_ST_FREQUENCY) - 1;
+ SysTick->VAL = 0;
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_ENABLE_Msk |
+ SysTick_CTRL_TICKINT_Msk;
+
+ /* IRQ enabled.*/
+ nvicSetSystemHandlerPriority(HANDLER_SYSTICK, STM32_ST_IRQ_PRIORITY);
+#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */
+}
+
+/**
+ * @brief IRQ handling code.
+ */
+void st_lld_serve_interrupt(void) {
+#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING
+ uint32_t sr;
+ stm32_tim_t *timp = STM32_ST_TIM;
+
+ sr = timp->SR;
+ sr &= timp->DIER & STM32_TIM_DIER_IRQ_MASK;
+ timp->SR = ~sr;
+
+ if ((sr & TIM_SR_CC1IF) != 0U)
+#endif
+ {
+ osalSysLockFromISR();
+ osalOsTimerHandlerI();
+ osalSysUnlockFromISR();
+ }
+#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING
+#if ST_LLD_NUM_ALARMS > 1
+ if ((sr & TIM_SR_CC2IF) != 0U) {
+ if (st_callbacks[2] != NULL) {
+ st_callbacks[0](1U);
+ }
+ }
+#endif
+#if ST_LLD_NUM_ALARMS > 2
+ if ((sr & TIM_SR_CC3IF) != 0U) {
+ if (st_callbacks[2] != NULL) {
+ st_callbacks[1](2U);
+ }
+ }
+#endif
+#if ST_LLD_NUM_ALARMS > 3
+ if ((sr & TIM_SR_CC4IF) != 0U) {
+ if (st_callbacks[2] != NULL) {
+ st_callbacks[2](3U);
+ }
+ }
+#endif
+#endif
+}
+
+#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.h
new file mode 100644
index 0000000..2b7f537
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/hal_st_lld.h
@@ -0,0 +1,701 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/hal_st_lld.h
+ * @brief ST Driver subsystem low level driver header.
+ * @details This header is designed to be include-able without having to
+ * include other files from the HAL.
+ *
+ * @addtogroup ST
+ * @{
+ */
+
+#ifndef HAL_ST_LLD_H
+#define HAL_ST_LLD_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/* Feature currently disabled.*/
+#define STM32_ST_ENFORCE_ALARMS 1
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief SysTick timer IRQ priority.
+ */
+#if !defined(STM32_ST_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_ST_IRQ_PRIORITY 8
+#endif
+
+/**
+ * @brief TIMx unit (by number) to be used for free running operations.
+ * @note You must select a 32 bits timer if a 32 bits @p systick_t type
+ * is required.
+ * @note Timers 2, 3, 4, 5, 21 and 22 are supported.
+ */
+#if !defined(STM32_ST_USE_TIMER) || defined(__DOXYGEN__)
+#define STM32_ST_USE_TIMER 2
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* This has to go after transition to shared handlers is complete for all
+ platforms.*/
+#if !defined(STM32_HAS_TIM2)
+#define STM32_HAS_TIM2 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM3)
+#define STM32_HAS_TIM3 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM4)
+#define STM32_HAS_TIM4 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM5)
+#define STM32_HAS_TIM5 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM9)
+#define STM32_HAS_TIM9 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM10)
+#define STM32_HAS_TIM10 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM11)
+#define STM32_HAS_TIM11 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM12)
+#define STM32_HAS_TIM12 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM13)
+#define STM32_HAS_TIM13 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM14)
+#define STM32_HAS_TIM14 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM21)
+#define STM32_HAS_TIM21 FALSE
+#endif
+
+#if !defined(STM32_HAS_TIM22)
+#define STM32_HAS_TIM22 FALSE
+#endif
+/**/
+
+#if OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING
+
+#if STM32_ST_USE_TIMER == 2
+
+#if defined(STM32_TIM2_IS_USED)
+#error "ST requires TIM2 but the timer is already used"
+#else
+#define STM32_TIM2_IS_USED
+#endif
+
+#if defined(STM32_TIM2_SUPPRESS_ISR)
+#define STM32_SYSTICK_SUPPRESS_ISR
+#endif
+
+#define STM32_ST_TIM STM32_TIM2
+#define ST_LLD_NUM_ALARMS STM32_TIM2_CHANNELS
+#define STM32_ST_USE_SYSTICK FALSE
+#define STM32_ST_USE_TIM2 TRUE
+#define STM32_ST_USE_TIM3 FALSE
+#define STM32_ST_USE_TIM4 FALSE
+#define STM32_ST_USE_TIM5 FALSE
+#define STM32_ST_USE_TIM9 FALSE
+#define STM32_ST_USE_TIM10 FALSE
+#define STM32_ST_USE_TIM11 FALSE
+#define STM32_ST_USE_TIM12 FALSE
+#define STM32_ST_USE_TIM13 FALSE
+#define STM32_ST_USE_TIM14 FALSE
+#define STM32_ST_USE_TIM21 FALSE
+#define STM32_ST_USE_TIM22 FALSE
+
+#elif STM32_ST_USE_TIMER == 3
+
+#if defined(STM32_TIM3_IS_USED)
+#error "ST requires TIM3 but the timer is already used"
+#else
+#define STM32_TIM3_IS_USED
+#endif
+
+#if defined(STM32_TIM3_SUPPRESS_ISR)
+#define STM32_SYSTICK_SUPPRESS_ISR
+#endif
+
+#define STM32_ST_TIM STM32_TIM3
+#define ST_LLD_NUM_ALARMS STM32_TIM3_CHANNELS
+#define STM32_ST_USE_SYSTICK FALSE
+#define STM32_ST_USE_TIM2 FALSE
+#define STM32_ST_USE_TIM3 TRUE
+#define STM32_ST_USE_TIM4 FALSE
+#define STM32_ST_USE_TIM5 FALSE
+#define STM32_ST_USE_TIM9 FALSE
+#define STM32_ST_USE_TIM10 FALSE
+#define STM32_ST_USE_TIM11 FALSE
+#define STM32_ST_USE_TIM12 FALSE
+#define STM32_ST_USE_TIM13 FALSE
+#define STM32_ST_USE_TIM14 FALSE
+#define STM32_ST_USE_TIM21 FALSE
+#define STM32_ST_USE_TIM22 FALSE
+
+#elif STM32_ST_USE_TIMER == 4
+
+#if defined(STM32_TIM4_IS_USED)
+#error "ST requires TIM4 but the timer is already used"
+#else
+#define STM32_TIM4_IS_USED
+#endif
+
+#if defined(STM32_TIM4_SUPPRESS_ISR)
+#define STM32_SYSTICK_SUPPRESS_ISR
+#endif
+
+#define STM32_ST_TIM STM32_TIM4
+#define ST_LLD_NUM_ALARMS STM32_TIM4_CHANNELS
+#define STM32_ST_USE_SYSTICK FALSE
+#define STM32_ST_USE_TIM2 FALSE
+#define STM32_ST_USE_TIM3 FALSE
+#define STM32_ST_USE_TIM4 TRUE
+#define STM32_ST_USE_TIM5 FALSE
+#define STM32_ST_USE_TIM9 FALSE
+#define STM32_ST_USE_TIM10 FALSE
+#define STM32_ST_USE_TIM11 FALSE
+#define STM32_ST_USE_TIM12 FALSE
+#define STM32_ST_USE_TIM13 FALSE
+#define STM32_ST_USE_TIM14 FALSE
+#define STM32_ST_USE_TIM21 FALSE
+#define STM32_ST_USE_TIM22 FALSE
+
+#elif STM32_ST_USE_TIMER == 5
+
+#if defined(STM32_TIM5_IS_USED)
+#error "ST requires TIM5 but the timer is already used"
+#else
+#define STM32_TIM5_IS_USED
+#endif
+
+#if defined(STM32_TIM5_SUPPRESS_ISR)
+#define STM32_SYSTICK_SUPPRESS_ISR
+#endif
+
+#define STM32_ST_TIM STM32_TIM5
+#define ST_LLD_NUM_ALARMS STM32_TIM5_CHANNELS
+#define STM32_ST_USE_SYSTICK FALSE
+#define STM32_ST_USE_TIM2 FALSE
+#define STM32_ST_USE_TIM3 FALSE
+#define STM32_ST_USE_TIM4 FALSE
+#define STM32_ST_USE_TIM5 TRUE
+#define STM32_ST_USE_TIM9 FALSE
+#define STM32_ST_USE_TIM10 FALSE
+#define STM32_ST_USE_TIM11 FALSE
+#define STM32_ST_USE_TIM12 FALSE
+#define STM32_ST_USE_TIM13 FALSE
+#define STM32_ST_USE_TIM14 FALSE
+#define STM32_ST_USE_TIM21 FALSE
+#define STM32_ST_USE_TIM22 FALSE
+
+#elif STM32_ST_USE_TIMER == 9
+
+#if defined(STM32_TIM9_IS_USED)
+#error "ST requires TIM9 but the timer is already used"
+#else
+#define STM32_TIM9_IS_USED
+#endif
+
+#if defined(STM32_TIM9_SUPPRESS_ISR)
+#define STM32_SYSTICK_SUPPRESS_ISR
+#endif
+
+#define STM32_ST_TIM STM32_TIM9
+#define ST_LLD_NUM_ALARMS STM32_TIM9_CHANNELS
+#define STM32_ST_USE_SYSTICK FALSE
+#define STM32_ST_USE_TIM2 FALSE
+#define STM32_ST_USE_TIM3 FALSE
+#define STM32_ST_USE_TIM4 FALSE
+#define STM32_ST_USE_TIM5 FALSE
+#define STM32_ST_USE_TIM9 TRUE
+#define STM32_ST_USE_TIM10 FALSE
+#define STM32_ST_USE_TIM11 FALSE
+#define STM32_ST_USE_TIM12 FALSE
+#define STM32_ST_USE_TIM13 FALSE
+#define STM32_ST_USE_TIM14 FALSE
+#define STM32_ST_USE_TIM21 FALSE
+#define STM32_ST_USE_TIM22 FALSE
+
+#elif STM32_ST_USE_TIMER == 10
+
+#if defined(STM32_TIM10_IS_USED)
+#error "ST requires TIM10 but the timer is already used"
+#else
+#define STM32_TIM10_IS_USED
+#endif
+
+#if defined(STM32_TIM10_SUPPRESS_ISR)
+#define STM32_SYSTICK_SUPPRESS_ISR
+#endif
+
+#define STM32_ST_TIM STM32_TIM10
+#define ST_LLD_NUM_ALARMS STM32_TIM10_CHANNELS
+#define STM32_ST_USE_SYSTICK FALSE
+#define STM32_ST_USE_TIM2 FALSE
+#define STM32_ST_USE_TIM3 FALSE
+#define STM32_ST_USE_TIM4 FALSE
+#define STM32_ST_USE_TIM5 FALSE
+#define STM32_ST_USE_TIM9 FALSE
+#define STM32_ST_USE_TIM10 TRUE
+#define STM32_ST_USE_TIM11 FALSE
+#define STM32_ST_USE_TIM12 FALSE
+#define STM32_ST_USE_TIM13 FALSE
+#define STM32_ST_USE_TIM14 FALSE
+#define STM32_ST_USE_TIM21 FALSE
+#define STM32_ST_USE_TIM22 FALSE
+
+#elif STM32_ST_USE_TIMER == 11
+
+#if defined(STM32_TIM11_IS_USED)
+#error "ST requires TIM11 but the timer is already used"
+#else
+#define STM32_TIM11_IS_USED
+#endif
+
+#if defined(STM32_TIM11_SUPPRESS_ISR)
+#define STM32_SYSTICK_SUPPRESS_ISR
+#endif
+
+#define STM32_ST_TIM STM32_TIM11
+#define ST_LLD_NUM_ALARMS STM32_TIM11_CHANNELS
+#define STM32_ST_USE_SYSTICK FALSE
+#define STM32_ST_USE_TIM2 FALSE
+#define STM32_ST_USE_TIM3 FALSE
+#define STM32_ST_USE_TIM4 FALSE
+#define STM32_ST_USE_TIM5 FALSE
+#define STM32_ST_USE_TIM9 FALSE
+#define STM32_ST_USE_TIM10 FALSE
+#define STM32_ST_USE_TIM11 TRUE
+#define STM32_ST_USE_TIM12 FALSE
+#define STM32_ST_USE_TIM13 FALSE
+#define STM32_ST_USE_TIM14 FALSE
+#define STM32_ST_USE_TIM21 FALSE
+#define STM32_ST_USE_TIM22 FALSE
+
+#elif STM32_ST_USE_TIMER == 12
+
+#if defined(STM32_TIM12_IS_USED)
+#error "ST requires TIM12 but the timer is already used"
+#else
+#define STM32_TIM12_IS_USED
+#endif
+
+#if defined(STM32_TIM12_SUPPRESS_ISR)
+#define STM32_SYSTICK_SUPPRESS_ISR
+#endif
+
+#define STM32_ST_TIM STM32_TIM12
+#define ST_LLD_NUM_ALARMS STM32_TIM12_CHANNELS
+#define STM32_ST_USE_SYSTICK FALSE
+#define STM32_ST_USE_TIM2 FALSE
+#define STM32_ST_USE_TIM3 FALSE
+#define STM32_ST_USE_TIM4 FALSE
+#define STM32_ST_USE_TIM5 FALSE
+#define STM32_ST_USE_TIM9 FALSE
+#define STM32_ST_USE_TIM10 FALSE
+#define STM32_ST_USE_TIM11 FALSE
+#define STM32_ST_USE_TIM12 TRUE
+#define STM32_ST_USE_TIM13 FALSE
+#define STM32_ST_USE_TIM14 FALSE
+#define STM32_ST_USE_TIM21 FALSE
+#define STM32_ST_USE_TIM22 FALSE
+
+#elif STM32_ST_USE_TIMER == 13
+
+#if defined(STM32_TIM13_IS_USED)
+#error "ST requires TIM13 but the timer is already used"
+#else
+#define STM32_TIM13_IS_USED
+#endif
+
+#if defined(STM32_TIM13_SUPPRESS_ISR)
+#define STM32_SYSTICK_SUPPRESS_ISR
+#endif
+
+#define STM32_ST_TIM STM32_TIM13
+#define ST_LLD_NUM_ALARMS STM32_TIM13_CHANNELS
+#define STM32_ST_USE_SYSTICK FALSE
+#define STM32_ST_USE_TIM2 FALSE
+#define STM32_ST_USE_TIM3 FALSE
+#define STM32_ST_USE_TIM4 FALSE
+#define STM32_ST_USE_TIM5 FALSE
+#define STM32_ST_USE_TIM9 FALSE
+#define STM32_ST_USE_TIM10 FALSE
+#define STM32_ST_USE_TIM11 FALSE
+#define STM32_ST_USE_TIM12 FALSE
+#define STM32_ST_USE_TIM13 TRUE
+#define STM32_ST_USE_TIM14 FALSE
+#define STM32_ST_USE_TIM21 FALSE
+#define STM32_ST_USE_TIM22 FALSE
+
+#elif STM32_ST_USE_TIMER == 14
+
+#if defined(STM32_TIM14_IS_USED)
+#error "ST requires TIM14 but the timer is already used"
+#else
+#define STM32_TIM14_IS_USED
+#endif
+
+#if defined(STM32_TIM14_SUPPRESS_ISR)
+#define STM32_SYSTICK_SUPPRESS_ISR
+#endif
+
+#define STM32_ST_TIM STM32_TIM14
+#define ST_LLD_NUM_ALARMS STM32_TIM14_CHANNELS
+#define STM32_ST_USE_SYSTICK FALSE
+#define STM32_ST_USE_TIM2 FALSE
+#define STM32_ST_USE_TIM3 FALSE
+#define STM32_ST_USE_TIM4 FALSE
+#define STM32_ST_USE_TIM5 FALSE
+#define STM32_ST_USE_TIM9 FALSE
+#define STM32_ST_USE_TIM10 FALSE
+#define STM32_ST_USE_TIM11 FALSE
+#define STM32_ST_USE_TIM12 FALSE
+#define STM32_ST_USE_TIM13 FALSE
+#define STM32_ST_USE_TIM14 TRUE
+#define STM32_ST_USE_TIM21 FALSE
+#define STM32_ST_USE_TIM22 FALSE
+
+#elif STM32_ST_USE_TIMER == 21
+
+#if defined(STM32_TIM21_IS_USED)
+#error "ST requires TIM21 but the timer is already used"
+#else
+#define STM32_TIM21_IS_USED
+#endif
+
+#if defined(STM32_TIM21_SUPPRESS_ISR)
+#define STM32_SYSTICK_SUPPRESS_ISR
+#endif
+
+#define STM32_ST_TIM STM32_TIM21
+#define ST_LLD_NUM_ALARMS STM32_TIM21_CHANNELS
+#define STM32_ST_USE_SYSTICK FALSE
+#define STM32_ST_USE_TIM2 FALSE
+#define STM32_ST_USE_TIM3 FALSE
+#define STM32_ST_USE_TIM4 FALSE
+#define STM32_ST_USE_TIM5 FALSE
+#define STM32_ST_USE_TIM9 FALSE
+#define STM32_ST_USE_TIM10 FALSE
+#define STM32_ST_USE_TIM11 FALSE
+#define STM32_ST_USE_TIM12 FALSE
+#define STM32_ST_USE_TIM13 FALSE
+#define STM32_ST_USE_TIM14 FALSE
+#define STM32_ST_USE_TIM21 TRUE
+#define STM32_ST_USE_TIM22 FALSE
+
+#elif STM32_ST_USE_TIMER == 22
+
+#if defined(STM32_TIM22_IS_USED)
+#error "ST requires TIM22 but the timer is already used"
+#else
+#define STM32_TIM22_IS_USED
+#endif
+
+#if defined(STM32_TIM22_SUPPRESS_ISR)
+#define STM32_SYSTICK_SUPPRESS_ISR
+#endif
+
+#define STM32_ST_TIM STM32_TIM22
+#define ST_LLD_NUM_ALARMS STM32_TIM22_CHANNELS
+#define STM32_ST_USE_SYSTICK FALSE
+#define STM32_ST_USE_TIM2 FALSE
+#define STM32_ST_USE_TIM3 FALSE
+#define STM32_ST_USE_TIM4 FALSE
+#define STM32_ST_USE_TIM5 FALSE
+#define STM32_ST_USE_TIM9 FALSE
+#define STM32_ST_USE_TIM10 FALSE
+#define STM32_ST_USE_TIM11 FALSE
+#define STM32_ST_USE_TIM12 FALSE
+#define STM32_ST_USE_TIM13 FALSE
+#define STM32_ST_USE_TIM14 FALSE
+#define STM32_ST_USE_TIM21 FALSE
+#define STM32_ST_USE_TIM22 TRUE
+
+#else
+#error "STM32_ST_USE_TIMER specifies an unsupported timer"
+#endif
+
+#if defined(STM32_ST_ENFORCE_ALARMS)
+
+#if (STM32_ST_ENFORCE_ALARMS < 1) || (STM32_ST_ENFORCE_ALARMS > ST_LLD_NUM_ALARMS)
+#error "invalid STM32_ST_ENFORCE_ALARMS value"
+#endif
+
+#undef ST_LLD_NUM_ALARMS
+#define ST_LLD_NUM_ALARMS STM32_ST_ENFORCE_ALARMS
+#endif
+
+#elif OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING
+
+#define STM32_ST_USE_SYSTICK TRUE
+#define STM32_ST_USE_TIM2 FALSE
+#define STM32_ST_USE_TIM3 FALSE
+#define STM32_ST_USE_TIM4 FALSE
+#define STM32_ST_USE_TIM5 FALSE
+#define STM32_ST_USE_TIM9 FALSE
+#define STM32_ST_USE_TIM10 FALSE
+#define STM32_ST_USE_TIM11 FALSE
+#define STM32_ST_USE_TIM12 FALSE
+#define STM32_ST_USE_TIM13 FALSE
+#define STM32_ST_USE_TIM14 FALSE
+#define STM32_ST_USE_TIM21 FALSE
+#define STM32_ST_USE_TIM22 FALSE
+
+#else
+
+#define STM32_ST_USE_SYSTICK FALSE
+#define STM32_ST_USE_TIM2 FALSE
+#define STM32_ST_USE_TIM3 FALSE
+#define STM32_ST_USE_TIM4 FALSE
+#define STM32_ST_USE_TIM5 FALSE
+#define STM32_ST_USE_TIM9 FALSE
+#define STM32_ST_USE_TIM10 FALSE
+#define STM32_ST_USE_TIM11 FALSE
+#define STM32_ST_USE_TIM12 FALSE
+#define STM32_ST_USE_TIM13 FALSE
+#define STM32_ST_USE_TIM14 FALSE
+#define STM32_ST_USE_TIM21 FALSE
+#define STM32_ST_USE_TIM22 FALSE
+
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void st_lld_init(void);
+ void st_lld_serve_interrupt(void);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Driver inline functions. */
+/*===========================================================================*/
+
+
+#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__)
+
+/**
+ * @brief Returns the time counter value.
+ *
+ * @return The counter value.
+ *
+ * @notapi
+ */
+static inline systime_t st_lld_get_counter(void) {
+
+ return (systime_t)STM32_ST_TIM->CNT;
+}
+
+/**
+ * @brief Starts the alarm.
+ * @note Makes sure that no spurious alarms are triggered after
+ * this call.
+ *
+ * @param[in] abstime the time to be set for the first alarm
+ *
+ * @notapi
+ */
+static inline void st_lld_start_alarm(systime_t abstime) {
+
+ STM32_ST_TIM->CCR[0] = (uint32_t)abstime;
+ STM32_ST_TIM->SR = 0;
+#if ST_LLD_NUM_ALARMS == 1
+ STM32_ST_TIM->DIER = STM32_TIM_DIER_CC1IE;
+#else
+ STM32_ST_TIM->DIER |= STM32_TIM_DIER_CC1IE;
+#endif
+}
+
+/**
+ * @brief Stops the alarm interrupt.
+ *
+ * @notapi
+ */
+static inline void st_lld_stop_alarm(void) {
+
+#if ST_LLD_NUM_ALARMS == 1
+ STM32_ST_TIM->DIER = 0U;
+#else
+ STM32_ST_TIM->DIER &= ~STM32_TIM_DIER_CC1IE;
+#endif
+}
+
+/**
+ * @brief Sets the alarm time.
+ *
+ * @param[in] abstime the time to be set for the next alarm
+ *
+ * @notapi
+ */
+static inline void st_lld_set_alarm(systime_t abstime) {
+
+ STM32_ST_TIM->CCR[0] = (uint32_t)abstime;
+}
+
+/**
+ * @brief Returns the current alarm time.
+ *
+ * @return The currently set alarm time.
+ *
+ * @notapi
+ */
+static inline systime_t st_lld_get_alarm(void) {
+
+ return (systime_t)STM32_ST_TIM->CCR[0];
+}
+
+/**
+ * @brief Determines if the alarm is active.
+ *
+ * @return The alarm status.
+ * @retval false if the alarm is not active.
+ * @retval true is the alarm is active
+ *
+ * @notapi
+ */
+static inline bool st_lld_is_alarm_active(void) {
+
+ return (bool)((STM32_ST_TIM->DIER & STM32_TIM_DIER_CC1IE) != 0);
+}
+
+#if (ST_LLD_NUM_ALARMS > 1) || defined(__DOXYGEN__)
+/**
+ * @brief Starts an alarm.
+ * @note Makes sure that no spurious alarms are triggered after
+ * this call.
+ * @note This functionality is only available in free running mode, the
+ * behavior in periodic mode is undefined.
+ *
+ * @param[in] abstime the time to be set for the first alarm
+ * @param[in] alarm alarm channel number
+ *
+ * @notapi
+ */
+static inline void st_lld_start_alarm_n(unsigned alarm, systime_t abstime) {
+
+
+ STM32_ST_TIM->CCR[alarm] = (uint32_t)abstime;
+ STM32_ST_TIM->SR = 0;
+ STM32_ST_TIM->DIER |= (STM32_TIM_DIER_CC1IE << alarm);
+}
+
+/**
+ * @brief Stops an alarm interrupt.
+ * @note This functionality is only available in free running mode, the
+ * behavior in periodic mode is undefined.
+ *
+ * @param[in] alarm alarm channel number
+ *
+ * @notapi
+ */
+static inline void st_lld_stop_alarm_n(unsigned alarm) {
+
+ STM32_ST_TIM->DIER &= ~(STM32_TIM_DIER_CC1IE << alarm);
+}
+
+/**
+ * @brief Sets an alarm time.
+ * @note This functionality is only available in free running mode, the
+ * behavior in periodic mode is undefined.
+ *
+ * @param[in] alarm alarm channel number
+ * @param[in] abstime the time to be set for the next alarm
+ *
+ * @notapi
+ */
+static inline void st_lld_set_alarm_n(unsigned alarm, systime_t abstime) {
+
+ STM32_ST_TIM->CCR[alarm] = (uint32_t)abstime;
+}
+
+/**
+ * @brief Returns an alarm current time.
+ * @note This functionality is only available in free running mode, the
+ * behavior in periodic mode is undefined.
+ *
+ * @param[in] alarm alarm channel number
+ * @return The currently set alarm time.
+ *
+ * @notapi
+ */
+static inline systime_t st_lld_get_alarm_n(unsigned alarm) {
+
+ return (systime_t)STM32_ST_TIM->CCR[alarm];
+}
+
+/**
+ * @brief Determines if an alarm is active.
+ *
+ * @param[in] alarm alarm channel number
+ * @return The alarm status.
+ * @retval false if the alarm is not active.
+ * @retval true is the alarm is active
+ *
+ * @notapi
+ */
+static inline bool st_lld_is_alarm_active_n(unsigned alarm) {
+
+ return (bool)((STM32_ST_TIM->DIER & (STM32_TIM_DIER_CC1IE << alarm)) != 0);
+}
+#endif /* ST_LLD_NUM_ALARMS > 1 */
+
+#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
+
+#endif /* HAL_ST_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim.h
new file mode 100644
index 0000000..8f158fe
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim.h
@@ -0,0 +1,552 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim.h
+ * @brief STM32 TIM units common header.
+ * @note This file requires definitions from the ST STM32 header file.
+ *
+ * @addtogroup STM32_TIMv1
+ * @{
+ */
+
+#ifndef STM32_TIM_H
+#define STM32_TIM_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name TIM_CR1 register
+ * @{
+ */
+#define STM32_TIM_CR1_CEN (1U << 0)
+#define STM32_TIM_CR1_UDIS (1U << 1)
+#define STM32_TIM_CR1_URS (1U << 2)
+#define STM32_TIM_CR1_OPM (1U << 3)
+#define STM32_TIM_CR1_DIR (1U << 4)
+
+#define STM32_TIM_CR1_CMS_MASK (3U << 5)
+#define STM32_TIM_CR1_CMS(n) ((n) << 5)
+
+#define STM32_TIM_CR1_ARPE (1U << 7)
+
+#define STM32_TIM_CR1_CKD_MASK (3U << 8)
+#define STM32_TIM_CR1_CKD(n) ((n) << 8)
+
+#define STM32_TIM_CR1_UIFREMAP (1U << 11)
+/** @} */
+
+/**
+ * @name TIM_CR2 register
+ * @{
+ */
+#define STM32_TIM_CR2_CCPC (1U << 0)
+#define STM32_TIM_CR2_CCUS (1U << 2)
+#define STM32_TIM_CR2_CCDS (1U << 3)
+
+#define STM32_TIM_CR2_MMS_MASK (7U << 4)
+#define STM32_TIM_CR2_MMS(n) ((n) << 4)
+
+#define STM32_TIM_CR2_TI1S (1U << 7)
+#define STM32_TIM_CR2_OIS1 (1U << 8)
+#define STM32_TIM_CR2_OIS1N (1U << 9)
+#define STM32_TIM_CR2_OIS2 (1U << 10)
+#define STM32_TIM_CR2_OIS2N (1U << 11)
+#define STM32_TIM_CR2_OIS3 (1U << 12)
+#define STM32_TIM_CR2_OIS3N (1U << 13)
+#define STM32_TIM_CR2_OIS4 (1U << 14)
+#define STM32_TIM_CR2_OIS5 (1U << 16)
+#define STM32_TIM_CR2_OIS6 (1U << 18)
+
+#define STM32_TIM_CR2_MMS2_MASK (15U << 20)
+#define STM32_TIM_CR2_MMS2(n) ((n) << 20)
+/** @} */
+
+/**
+ * @name TIM_SMCR register
+ * @{
+ */
+#define STM32_TIM_SMCR_SMS_MASK ((7U << 0) | (1U << 16))
+#define STM32_TIM_SMCR_SMS(n) ((((n) & 7) << 0) | \
+ (((n) >> 3) << 16))
+
+#define STM32_TIM_SMCR_OCCS (1U << 3)
+
+#define STM32_TIM_SMCR_TS_MASK (7U << 4)
+#define STM32_TIM_SMCR_TS(n) ((n) << 4)
+
+#define STM32_TIM_SMCR_MSM (1U << 7)
+
+#define STM32_TIM_SMCR_ETF_MASK (15U << 8)
+#define STM32_TIM_SMCR_ETF(n) ((n) << 8)
+
+#define STM32_TIM_SMCR_ETPS_MASK (3U << 12)
+#define STM32_TIM_SMCR_ETPS(n) ((n) << 12)
+
+#define STM32_TIM_SMCR_ECE (1U << 14)
+#define STM32_TIM_SMCR_ETP (1U << 15)
+/** @} */
+
+/**
+ * @name TIM_DIER register
+ * @{
+ */
+#define STM32_TIM_DIER_UIE (1U << 0)
+#define STM32_TIM_DIER_CC1IE (1U << 1)
+#define STM32_TIM_DIER_CC2IE (1U << 2)
+#define STM32_TIM_DIER_CC3IE (1U << 3)
+#define STM32_TIM_DIER_CC4IE (1U << 4)
+#define STM32_TIM_DIER_COMIE (1U << 5)
+#define STM32_TIM_DIER_TIE (1U << 6)
+#define STM32_TIM_DIER_BIE (1U << 7)
+#define STM32_TIM_DIER_UDE (1U << 8)
+#define STM32_TIM_DIER_CC1DE (1U << 9)
+#define STM32_TIM_DIER_CC2DE (1U << 10)
+#define STM32_TIM_DIER_CC3DE (1U << 11)
+#define STM32_TIM_DIER_CC4DE (1U << 12)
+#define STM32_TIM_DIER_COMDE (1U << 13)
+#define STM32_TIM_DIER_TDE (1U << 14)
+
+#define STM32_TIM_DIER_IRQ_MASK (STM32_TIM_DIER_UIE | \
+ STM32_TIM_DIER_CC1IE | \
+ STM32_TIM_DIER_CC2IE | \
+ STM32_TIM_DIER_CC3IE | \
+ STM32_TIM_DIER_CC4IE | \
+ STM32_TIM_DIER_COMIE | \
+ STM32_TIM_DIER_TIE | \
+ STM32_TIM_DIER_BIE)
+
+/** @} */
+
+/**
+ * @name TIM_SR register
+ * @{
+ */
+#define STM32_TIM_SR_UIF (1U << 0)
+#define STM32_TIM_SR_CC1IF (1U << 1)
+#define STM32_TIM_SR_CC2IF (1U << 2)
+#define STM32_TIM_SR_CC3IF (1U << 3)
+#define STM32_TIM_SR_CC4IF (1U << 4)
+#define STM32_TIM_SR_COMIF (1U << 5)
+#define STM32_TIM_SR_TIF (1U << 6)
+#define STM32_TIM_SR_BIF (1U << 7)
+#define STM32_TIM_SR_B2IF (1U << 8)
+#define STM32_TIM_SR_CC1OF (1U << 9)
+#define STM32_TIM_SR_CC2OF (1U << 10)
+#define STM32_TIM_SR_CC3OF (1U << 11)
+#define STM32_TIM_SR_CC4OF (1U << 12)
+#define STM32_TIM_SR_CC5IF (1U << 16)
+#define STM32_TIM_SR_CC6IF (1U << 17)
+/** @} */
+
+/**
+ * @name TIM_EGR register
+ * @{
+ */
+#define STM32_TIM_EGR_UG (1U << 0)
+#define STM32_TIM_EGR_CC1G (1U << 1)
+#define STM32_TIM_EGR_CC2G (1U << 2)
+#define STM32_TIM_EGR_CC3G (1U << 3)
+#define STM32_TIM_EGR_CC4G (1U << 4)
+#define STM32_TIM_EGR_COMG (1U << 5)
+#define STM32_TIM_EGR_TG (1U << 6)
+#define STM32_TIM_EGR_BG (1U << 7)
+#define STM32_TIM_EGR_B2G (1U << 8)
+/** @} */
+
+/**
+ * @name TIM_CCMR1 register (output)
+ * @{
+ */
+#define STM32_TIM_CCMR1_CC1S_MASK (3U << 0)
+#define STM32_TIM_CCMR1_CC1S(n) ((n) << 0)
+
+#define STM32_TIM_CCMR1_OC1FE (1U << 2)
+#define STM32_TIM_CCMR1_OC1PE (1U << 3)
+
+#define STM32_TIM_CCMR1_OC1M_MASK ((7U << 4) | (1U << 16))
+#define STM32_TIM_CCMR1_OC1M(n) ((((n) & 7) << 4) | \
+ (((n) >> 3) << 16))
+
+#define STM32_TIM_CCMR1_OC1CE (1U << 7)
+
+#define STM32_TIM_CCMR1_CC2S_MASK (3U << 8)
+#define STM32_TIM_CCMR1_CC2S(n) ((n) << 8)
+
+#define STM32_TIM_CCMR1_OC2FE (1U << 10)
+#define STM32_TIM_CCMR1_OC2PE (1U << 11)
+
+#define STM32_TIM_CCMR1_OC2M_MASK ((7U << 12) | (1U << 24))
+#define STM32_TIM_CCMR1_OC2M(n) ((((n) & 7) << 12) | \
+ (((n) >> 3) << 24))
+
+#define STM32_TIM_CCMR1_OC2CE (1U << 15)
+/** @} */
+
+/**
+ * @name CCMR1 register (input)
+ * @{
+ */
+#define STM32_TIM_CCMR1_IC1PSC_MASK (3U << 2)
+#define STM32_TIM_CCMR1_IC1PSC(n) ((n) << 2)
+
+#define STM32_TIM_CCMR1_IC1F_MASK (15U << 4)
+#define STM32_TIM_CCMR1_IC1F(n) ((n) << 4)
+
+#define STM32_TIM_CCMR1_IC2PSC_MASK (3U << 10)
+#define STM32_TIM_CCMR1_IC2PSC(n) ((n) << 10)
+
+#define STM32_TIM_CCMR1_IC2F_MASK (15U << 12)
+#define STM32_TIM_CCMR1_IC2F(n) ((n) << 12)
+/** @} */
+
+/**
+ * @name TIM_CCMR2 register (output)
+ * @{
+ */
+#define STM32_TIM_CCMR2_CC3S_MASK (3U << 0)
+#define STM32_TIM_CCMR2_CC3S(n) ((n) << 0)
+
+#define STM32_TIM_CCMR2_OC3FE (1U << 2)
+#define STM32_TIM_CCMR2_OC3PE (1U << 3)
+
+#define STM32_TIM_CCMR2_OC3M_MASK ((7U << 4) | (1U << 16))
+#define STM32_TIM_CCMR2_OC3M(n) ((((n) & 7) << 4) | \
+ (((n) >> 3) << 16))
+
+#define STM32_TIM_CCMR2_OC3CE (1U << 7)
+
+#define STM32_TIM_CCMR2_CC4S_MASK (3U << 8)
+#define STM32_TIM_CCMR2_CC4S(n) ((n) << 8)
+
+#define STM32_TIM_CCMR2_OC4FE (1U << 10)
+#define STM32_TIM_CCMR2_OC4PE (1U << 11)
+
+#define STM32_TIM_CCMR2_OC4M_MASK ((7U << 12) | (1U << 24))
+#define STM32_TIM_CCMR2_OC4M(n) ((((n) & 7) << 12) | \
+ (((n) >> 3) << 24))
+
+#define STM32_TIM_CCMR2_OC4CE (1U << 15)
+/** @} */
+
+/**
+ * @name TIM_CCMR2 register (input)
+ * @{
+ */
+#define STM32_TIM_CCMR2_IC3PSC_MASK (3U << 2)
+#define STM32_TIM_CCMR2_IC3PSC(n) ((n) << 2)
+
+#define STM32_TIM_CCMR2_IC3F_MASK (15U << 4)
+#define STM32_TIM_CCMR2_IC3F(n) ((n) << 4)
+
+#define STM32_TIM_CCMR2_IC4PSC_MASK (3U << 10)
+#define STM32_TIM_CCMR2_IC4PSC(n) ((n) << 10)
+
+#define STM32_TIM_CCMR2_IC4F_MASK (15U << 12)
+#define STM32_TIM_CCMR2_IC4F(n) ((n) << 12)
+/** @} */
+
+/**
+ * @name TIM_CCER register
+ * @{
+ */
+#define STM32_TIM_CCER_CC1E (1U << 0)
+#define STM32_TIM_CCER_CC1P (1U << 1)
+#define STM32_TIM_CCER_CC1NE (1U << 2)
+#define STM32_TIM_CCER_CC1NP (1U << 3)
+#define STM32_TIM_CCER_CC2E (1U << 4)
+#define STM32_TIM_CCER_CC2P (1U << 5)
+#define STM32_TIM_CCER_CC2NE (1U << 6)
+#define STM32_TIM_CCER_CC2NP (1U << 7)
+#define STM32_TIM_CCER_CC3E (1U << 8)
+#define STM32_TIM_CCER_CC3P (1U << 9)
+#define STM32_TIM_CCER_CC3NE (1U << 10)
+#define STM32_TIM_CCER_CC3NP (1U << 11)
+#define STM32_TIM_CCER_CC4E (1U << 12)
+#define STM32_TIM_CCER_CC4P (1U << 13)
+#define STM32_TIM_CCER_CC4NE (1U << 14)
+#define STM32_TIM_CCER_CC4NP (1U << 15)
+#define STM32_TIM_CCER_CC5E (1U << 16)
+#define STM32_TIM_CCER_CC5P (1U << 17)
+#define STM32_TIM_CCER_CC6E (1U << 20)
+#define STM32_TIM_CCER_CC6P (1U << 21)
+/** @} */
+
+/**
+ * @name TIM_CNT register
+ * @{
+ */
+#define STM32_TIM_CNT_UIFCPY (1U << 31)
+/** @} */
+
+/**
+ * @name TIM_BDTR register
+ * @{
+ */
+#define STM32_TIM_BDTR_DTG_MASK (255U << 0)
+#define STM32_TIM_BDTR_DTG(n) ((n) << 0)
+
+#define STM32_TIM_BDTR_LOCK_MASK (3U << 8)
+#define STM32_TIM_BDTR_LOCK(n) ((n) << 8)
+
+#define STM32_TIM_BDTR_OSSI (1U << 10)
+#define STM32_TIM_BDTR_OSSR (1U << 11)
+#define STM32_TIM_BDTR_BKE (1U << 12)
+#define STM32_TIM_BDTR_BKP (1U << 13)
+#define STM32_TIM_BDTR_AOE (1U << 14)
+#define STM32_TIM_BDTR_MOE (1U << 15)
+
+#define STM32_TIM_BDTR_BKF_MASK (15U << 16)
+#define STM32_TIM_BDTR_BKF(n) ((n) << 16)
+#define STM32_TIM_BDTR_BK2F_MASK (15U << 20)
+#define STM32_TIM_BDTR_BK2F(n) ((n) << 20)
+
+#define STM32_TIM_BDTR_BK2E (1U << 24)
+#define STM32_TIM_BDTR_BK2P (1U << 25)
+/** @} */
+
+/**
+ * @name TIM_DCR register
+ * @{
+ */
+#define STM32_TIM_DCR_DBA_MASK (31U << 0)
+#define STM32_TIM_DCR_DBA(n) ((n) << 0)
+
+#define STM32_TIM_DCR_DBL_MASK (31U << 8)
+#define STM32_TIM_DCR_DBL(n) ((n) << 8)
+/** @} */
+
+/**
+ * @name TIM16_OR register
+ * @{
+ */
+#define STM32_TIM16_OR_TI1_RMP_MASK (3U << 6)
+#define STM32_TIM16_OR_TI1_RMP(n) ((n) << 6)
+/** @} */
+
+/**
+ * @name TIM_OR register
+ * @{
+ */
+#define STM32_TIM_OR_ETR_RMP_MASK (15U << 0)
+#define STM32_TIM_OR_ETR_RMP(n) ((n) << 0)
+/** @} */
+
+/**
+ * @name TIM_CCMR3 register
+ * @{
+ */
+#define STM32_TIM_CCMR3_OC5FE (1U << 2)
+#define STM32_TIM_CCMR3_OC5PE (1U << 3)
+
+#define STM32_TIM_CCMR3_OC5M_MASK ((7U << 4) | (1U << 16))
+#define STM32_TIM_CCMR3_OC5M(n) ((((n) & 7) << 4) | \
+ (((n) >> 2) << 16))
+
+#define STM32_TIM_CCMR3_OC5CE (1U << 7)
+
+#define STM32_TIM_CCMR3_OC6FE (1U << 10)
+#define STM32_TIM_CCMR3_OC6PE (1U << 11)
+
+#define STM32_TIM_CCMR3_OC6M_MASK ((7U << 12) | (1U << 24))
+#define STM32_TIM_CCMR3_OC6M(n) ((((n) & 7) << 12) | \
+ (((n) >> 2) << 24))
+
+#define STM32_TIM_CCMR3_OC6CE (1U << 15)
+/** @} */
+
+/**
+ * @name LPTIM_ISR register
+ * @{
+ */
+#define STM32_LPTIM_ISR_CMPM (1U << 0)
+#define STM32_LPTIM_ISR_ARRM (1U << 1)
+#define STM32_LPTIM_ISR_EXTTRIG (1U << 2)
+#define STM32_LPTIM_ISR_CMPOK (1U << 3)
+#define STM32_LPTIM_ISR_ARROK (1U << 4)
+#define STM32_LPTIM_ISR_UP (1U << 5)
+#define STM32_LPTIM_ISR_DOWN (1U << 6)
+/** @} */
+
+/**
+ * @name LPTIM_ICR register
+ * @{
+ */
+#define STM32_LPTIM_ICR_CMPMCF (1U << 0)
+#define STM32_LPTIM_ICR_ARRMCF (1U << 1)
+#define STM32_LPTIM_ICR_EXTTRIGCF (1U << 2)
+#define STM32_LPTIM_ICR_CMPOKCF (1U << 3)
+#define STM32_LPTIM_ICR_ARROKCF (1U << 4)
+#define STM32_LPTIM_ICR_UPCF (1U << 5)
+#define STM32_LPTIM_ICR_DOWNCF (1U << 6)
+/** @} */
+
+/**
+ * @name LPTIM_IER register
+ * @{
+ */
+#define STM32_LPTIM_IER_CMPMIE (1U << 0)
+#define STM32_LPTIM_IER_ARRMIE (1U << 1)
+#define STM32_LPTIM_IER_EXTTRIGIE (1U << 2)
+#define STM32_LPTIM_IER_CMPOKIE (1U << 3)
+#define STM32_LPTIM_IER_ARROKIE (1U << 4)
+#define STM32_LPTIM_IER_UPIE (1U << 5)
+#define STM32_LPTIM_IER_DOWNIE (1U << 6)
+/** @} */
+
+/**
+ * @name LPTIM_CFGR register
+ * @{
+ */
+#define STM32_LPTIM_CFGR_CKSEL (1U << 0)
+#define STM32_LPTIM_CFGR_CKPOL_MASK (3U << 1)
+#define STM32_LPTIM_CFGR_CKPOL(n) ((n) << 1)
+#define STM32_LPTIM_CFGR_CKFLT_MASK (3U << 3)
+#define STM32_LPTIM_CFGR_CKFLT(n) ((n) << 3)
+#define STM32_LPTIM_CFGR_TRGFLT_MASK (3U << 6)
+#define STM32_LPTIM_CFGR_TRGFLT(n) ((n) << 6)
+#define STM32_LPTIM_CFGR_PRESC_MASK (7U << 9)
+#define STM32_LPTIM_CFGR_PRESC(n) ((n) << 9)
+#define STM32_LPTIM_CFGR_TRIGSEL_MASK (7U << 13)
+#define STM32_LPTIM_CFGR_TRIGSEL(n) ((n) << 13)
+#define STM32_LPTIM_CFGR_TRIGEN_MASK (3U << 17)
+#define STM32_LPTIM_CFGR_TRIGEN(n) ((n) << 17)
+#define STM32_LPTIM_CFGR_TIMOUT (1U << 19)
+#define STM32_LPTIM_CFGR_WAVE (1U << 20)
+#define STM32_LPTIM_CFGR_WAVPOL (1U << 21)
+#define STM32_LPTIM_CFGR_PRELOAD (1U << 22)
+#define STM32_LPTIM_CFGR_COUNTMODE (1U << 23)
+#define STM32_LPTIM_CFGR_ENC (1U << 24)
+/** @} */
+
+/**
+ * @name LPTIM_CR register
+ * @{
+ */
+#define STM32_LPTIM_CR_ENABLE (1U << 0)
+#define STM32_LPTIM_CR_SNGSTRT (1U << 1)
+#define STM32_LPTIM_CR_CNTSTRT (1U << 2)
+/** @} */
+
+/**
+ * @name LPTIM_OR register
+ * @{
+ */
+#define STM32_LPTIM_OR_0 (1U << 0)
+#define STM32_LPTIM_OR_1 (1U << 1)
+/** @} */
+
+/**
+ * @name TIM units references
+ * @{
+ */
+#define STM32_TIM1 ((stm32_tim_t *)TIM1_BASE)
+#define STM32_TIM2 ((stm32_tim_t *)TIM2_BASE)
+#define STM32_TIM3 ((stm32_tim_t *)TIM3_BASE)
+#define STM32_TIM4 ((stm32_tim_t *)TIM4_BASE)
+#define STM32_TIM5 ((stm32_tim_t *)TIM5_BASE)
+#define STM32_TIM6 ((stm32_tim_t *)TIM6_BASE)
+#define STM32_TIM7 ((stm32_tim_t *)TIM7_BASE)
+#define STM32_TIM8 ((stm32_tim_t *)TIM8_BASE)
+#define STM32_TIM9 ((stm32_tim_t *)TIM9_BASE)
+#define STM32_TIM10 ((stm32_tim_t *)TIM10_BASE)
+#define STM32_TIM11 ((stm32_tim_t *)TIM11_BASE)
+#define STM32_TIM12 ((stm32_tim_t *)TIM12_BASE)
+#define STM32_TIM13 ((stm32_tim_t *)TIM13_BASE)
+#define STM32_TIM14 ((stm32_tim_t *)TIM14_BASE)
+#define STM32_TIM15 ((stm32_tim_t *)TIM15_BASE)
+#define STM32_TIM16 ((stm32_tim_t *)TIM16_BASE)
+#define STM32_TIM17 ((stm32_tim_t *)TIM17_BASE)
+#define STM32_TIM18 ((stm32_tim_t *)TIM18_BASE)
+#define STM32_TIM19 ((stm32_tim_t *)TIM19_BASE)
+#define STM32_TIM20 ((stm32_tim_t *)TIM20_BASE)
+#define STM32_TIM21 ((stm32_tim_t *)TIM21_BASE)
+#define STM32_TIM22 ((stm32_tim_t *)TIM22_BASE)
+
+#define STM32_LPTIM1 ((stm32_lptim_t *)LPTIM1_BASE)
+#define STM32_LPTIM2 ((stm32_lptim_t *)LPTIM2_BASE)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 TIM registers block.
+ * @note This is the most general known form, not all timers have
+ * necessarily all registers and bits.
+ */
+typedef struct {
+ volatile uint32_t CR1;
+ volatile uint32_t CR2;
+ volatile uint32_t SMCR;
+ volatile uint32_t DIER;
+ volatile uint32_t SR;
+ volatile uint32_t EGR;
+ volatile uint32_t CCMR1;
+ volatile uint32_t CCMR2;
+ volatile uint32_t CCER;
+ volatile uint32_t CNT;
+ volatile uint32_t PSC;
+ volatile uint32_t ARR;
+ volatile uint32_t RCR;
+ volatile uint32_t CCR[4];
+ volatile uint32_t BDTR;
+ volatile uint32_t DCR;
+ volatile uint32_t DMAR;
+ volatile uint32_t OR;
+ volatile uint32_t CCMR3;
+ volatile uint32_t CCXR[2];
+} stm32_tim_t;
+
+/**
+ * @brief STM32 LPTIM registers block.
+ * @note This is the most general known form, not all timers have
+ * necessarily all registers and bits.
+ */
+typedef struct {
+ volatile uint32_t ISR;
+ volatile uint32_t ICR;
+ volatile uint32_t IER;
+ volatile uint32_t CFGR;
+ volatile uint32_t CR;
+ volatile uint32_t CMP;
+ volatile uint32_t ARR;
+ volatile uint32_t CNT;
+ volatile uint32_t OR;
+} stm32_lptim_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#endif /* STM32_TIM_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim1.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim1.inc
new file mode 100644
index 0000000..eebaa8b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim1.inc
@@ -0,0 +1,172 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim1_tim15_tim16_tim17.inc
+ * @brief Shared TIM1 handler.
+ *
+ * @addtogroup STM32_TIM1_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_TIM1)
+#error "STM32_HAS_TIM1 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(STM32_GPT_USE_TIM1)
+#define STM32_GPT_USE_TIM1 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM1)
+#define STM32_ICU_USE_TIM1 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM1)
+#define STM32_PWM_USE_TIM1 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM1)
+#define STM32_ST_USE_TIM1 FALSE
+#endif
+
+#if STM32_HAS_TIM1
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_TIM1_UP_PRIORITY)
+#error "STM32_IRQ_TIM1_UP_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !defined(STM32_IRQ_TIM1_CC_PRIORITY)
+#error "STM32_IRQ_TIM1_CC_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM1_UP_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM1_UP_PRIORITY"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM1_CC_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM1_CC_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_TIM1 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tim1_irq_init(void) {
+#if defined(STM32_TIM1_IS_USED)
+ nvicEnableVector(STM32_TIM1_UP_NUMBER, STM32_IRQ_TIM1_UP_PRIORITY);
+ nvicEnableVector(STM32_TIM1_CC_NUMBER, STM32_IRQ_TIM1_CC_PRIORITY);
+#endif
+}
+
+static inline void tim1_irq_deinit(void) {
+#if defined(STM32_TIM1_IS_USED)
+ nvicDisableVector(STM32_TIM1_UP_NUMBER);
+ nvicDisableVector(STM32_TIM1_CC_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_TIM1_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TIM1-UP interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM1_UP_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM1
+ gpt_lld_serve_interrupt(&GPTD1);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM1
+ icu_lld_serve_interrupt(&ICUD1);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM1
+ pwm_lld_serve_interrupt(&PWMD1);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM1
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief TIM1-CC interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+ /* Not used by GPT.*/
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM1
+ icu_lld_serve_interrupt(&ICUD1);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM1
+ pwm_lld_serve_interrupt(&PWMD1);
+#endif
+#endif
+#if 1
+ /* Not used by ST.*/
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim14.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim14.inc
new file mode 100644
index 0000000..920af71
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim14.inc
@@ -0,0 +1,133 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim14.inc
+ * @brief Shared TIM14 handler.
+ *
+ * @addtogroup STM32_TIM14_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_TIM14)
+#error "STM32_HAS_TIM14 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(STM32_GPT_USE_TIM14)
+#define STM32_GPT_USE_TIM14 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM14)
+#define STM32_ICU_USE_TIM14 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM14)
+#define STM32_PWM_USE_TIM14 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM14)
+#define STM32_ST_USE_TIM14 FALSE
+#endif
+
+#if STM32_HAS_TIM14
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_TIM14_PRIORITY)
+#error "STM32_IRQ_TIM14_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM14_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM14_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_TIM14 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tim14_irq_init(void) {
+#if defined(STM32_TIM14_IS_USED)
+ nvicEnableVector(STM32_TIM14_NUMBER, STM32_IRQ_TIM14_PRIORITY);
+#endif
+}
+
+static inline void tim14_irq_deinit(void) {
+#if defined(STM32_TIM14_IS_USED)
+ nvicDisableVector(STM32_TIM14_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_TIM14_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TIM14 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM14_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM14
+ gpt_lld_serve_interrupt(&GPTD14);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM14
+ icu_lld_serve_interrupt(&ICUD14);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM14
+ pwm_lld_serve_interrupt(&PWMD14);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM14
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim15.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim15.inc
new file mode 100644
index 0000000..da90531
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim15.inc
@@ -0,0 +1,133 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim15.inc
+ * @brief Shared TIM15 handler.
+ *
+ * @addtogroup STM32_TIM15_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_TIM15)
+#error "STM32_HAS_TIM15 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(STM32_GPT_USE_TIM15)
+#define STM32_GPT_USE_TIM15 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM15)
+#define STM32_ICU_USE_TIM15 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM15)
+#define STM32_PWM_USE_TIM15 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM15)
+#define STM32_ST_USE_TIM15 FALSE
+#endif
+
+#if STM32_HAS_TIM15
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_TIM15_PRIORITY)
+#error "STM32_IRQ_TIM15_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM15_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM15_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_TIM15 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tim15_irq_init(void) {
+#if defined(STM32_TIM15_IS_USED)
+ nvicEnableVector(STM32_TIM15_NUMBER, STM32_IRQ_TIM15_PRIORITY);
+#endif
+}
+
+static inline void tim15_irq_deinit(void) {
+#if defined(STM32_TIM15_IS_USED)
+ nvicDisableVector(STM32_TIM15_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_TIM15_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TIM15 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM15_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM15
+ gpt_lld_serve_interrupt(&GPTD15);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM15
+ icu_lld_serve_interrupt(&ICUD15);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM15
+ pwm_lld_serve_interrupt(&PWMD15);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM15
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim16.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim16.inc
new file mode 100644
index 0000000..56517b1
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim16.inc
@@ -0,0 +1,133 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim16.inc
+ * @brief Shared TIM16 handler.
+ *
+ * @addtogroup STM32_TIM16_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_TIM16)
+#error "STM32_HAS_TIM16 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(STM32_GPT_USE_TIM16)
+#define STM32_GPT_USE_TIM16 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM16)
+#define STM32_ICU_USE_TIM16 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM16)
+#define STM32_PWM_USE_TIM16 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM16)
+#define STM32_ST_USE_TIM16 FALSE
+#endif
+
+#if STM32_HAS_TIM16
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_TIM16_PRIORITY)
+#error "STM32_IRQ_TIM16_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM16_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM16_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_TIM16 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tim16_irq_init(void) {
+#if defined(STM32_TIM16_IS_USED)
+ nvicEnableVector(STM32_TIM16_NUMBER, STM32_IRQ_TIM16_PRIORITY);
+#endif
+}
+
+static inline void tim16_irq_deinit(void) {
+#if defined(STM32_TIM16_IS_USED)
+ nvicDisableVector(STM32_TIM16_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_TIM16_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TIM16 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM16_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM16
+ gpt_lld_serve_interrupt(&GPTD16);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM16
+ icu_lld_serve_interrupt(&ICUD16);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM16
+ pwm_lld_serve_interrupt(&PWMD16);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM16
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim17.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim17.inc
new file mode 100644
index 0000000..eb6725b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim17.inc
@@ -0,0 +1,133 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim17.inc
+ * @brief Shared TIM17 handler.
+ *
+ * @addtogroup STM32_TIM17_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_TIM17)
+#error "STM32_HAS_TIM17 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(STM32_GPT_USE_TIM17)
+#define STM32_GPT_USE_TIM17 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM17)
+#define STM32_ICU_USE_TIM17 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM17)
+#define STM32_PWM_USE_TIM17 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM17)
+#define STM32_ST_USE_TIM17 FALSE
+#endif
+
+#if STM32_HAS_TIM17
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_TIM17_PRIORITY)
+#error "STM32_IRQ_TIM17_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM17_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM17_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_TIM17 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tim17_irq_init(void) {
+#if defined(STM32_TIM17_IS_USED)
+ nvicEnableVector(STM32_TIM17_NUMBER, STM32_IRQ_TIM17_PRIORITY);
+#endif
+}
+
+static inline void tim17_irq_deinit(void) {
+#if defined(STM32_TIM17_IS_USED)
+ nvicDisableVector(STM32_TIM17_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_TIM17_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TIM17 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM17_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM17
+ gpt_lld_serve_interrupt(&GPTD17);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM17
+ icu_lld_serve_interrupt(&ICUD17);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM17
+ pwm_lld_serve_interrupt(&PWMD17);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM17
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim1_15_16_17.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim1_15_16_17.inc
new file mode 100644
index 0000000..c40da37
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim1_15_16_17.inc
@@ -0,0 +1,341 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim1_15_16_17.inc
+ * @brief Shared TIM1, TIM15, TIM16, TIM17 handler.
+ *
+ * @addtogroup STM32_TIM1_TIM15_TIM16_TIM17_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_TIM1)
+#error "STM32_HAS_TIM1 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_TIM15)
+#error "STM32_HAS_TIM15 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_TIM16)
+#error "STM32_HAS_TIM16 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_TIM17)
+#error "STM32_HAS_TIM17 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(STM32_GPT_USE_TIM1)
+#define STM32_GPT_USE_TIM1 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM1)
+#define STM32_ICU_USE_TIM1 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM1)
+#define STM32_PWM_USE_TIM1 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM1)
+#define STM32_ST_USE_TIM1 FALSE
+#endif
+
+#if !defined(STM32_GPT_USE_TIM15)
+#define STM32_GPT_USE_TIM15 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM15)
+#define STM32_ICU_USE_TIM15 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM15)
+#define STM32_PWM_USE_TIM15 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM15)
+#define STM32_ST_USE_TIM15 FALSE
+#endif
+
+#if !defined(STM32_GPT_USE_TIM16)
+#define STM32_GPT_USE_TIM16 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM16)
+#define STM32_ICU_USE_TIM16 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM16)
+#define STM32_PWM_USE_TIM16 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM16)
+#define STM32_ST_USE_TIM16 FALSE
+#endif
+
+#if !defined(STM32_GPT_USE_TIM17)
+#define STM32_GPT_USE_TIM17 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM17)
+#define STM32_ICU_USE_TIM17 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM17)
+#define STM32_PWM_USE_TIM17 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM17)
+#define STM32_ST_USE_TIM17 FALSE
+#endif
+
+#if STM32_HAS_TIM1 || STM32_HAS_TIM15 || STM32_HAS_TIM16 || STM32_HAS_TIM17
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_TIM1_BRK_TIM15_PRIORITY)
+#error "STM32_IRQ_TIM1_BRK_TIM15_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !defined(STM32_IRQ_TIM1_UP_TIM16_PRIORITY)
+#error "STM32_IRQ_TIM1_UP_TIM16_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !defined(STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY)
+#error "STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !defined(STM32_IRQ_TIM1_CC_PRIORITY)
+#error "STM32_IRQ_TIM1_CC_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM1_BRK_TIM15_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM1_BRK_TIM15_PRIORITY"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM1_UP_TIM16_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM1_UP_TIM16_PRIORITY"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM1_CC_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM1_CC_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_TIM1 || STM32_HAS_TIM15 || STM32_HAS_TIM16 || STM32_HAS_TIM17 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tim1_tim15_tim16_tim17_irq_init(void) {
+#if defined(STM32_TIM1_IS_USED) || defined(STM32_TIM15_IS_USED)
+ nvicEnableVector(STM32_TIM1_BRK_TIM15_NUMBER,
+ STM32_IRQ_TIM1_BRK_TIM15_PRIORITY);
+#endif
+#if defined(STM32_TIM1_IS_USED) || defined(STM32_TIM16_IS_USED)
+ nvicEnableVector(STM32_TIM1_UP_TIM16_NUMBER,
+ STM32_IRQ_TIM1_UP_TIM16_PRIORITY);
+#endif
+#if defined(STM32_TIM1_IS_USED) || defined(STM32_TIM17_IS_USED)
+ nvicEnableVector(STM32_TIM1_TRGCO_TIM17_NUMBER,
+ STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY);
+#endif
+#if defined(STM32_TIM1_IS_USED)
+ nvicEnableVector(STM32_TIM1_CC_NUMBER,
+ STM32_IRQ_TIM1_CC_PRIORITY);
+#endif
+}
+
+static inline void tim1_tim15_tim16_tim17_irq_deinit(void) {
+#if defined(STM32_TIM1_IS_USED) || defined(STM32_TIM15_IS_USED)
+ nvicDisableVector(STM32_TIM1_BRK_TIM15_NUMBER);
+#endif
+#if defined(STM32_TIM1_IS_USED) || defined(STM32_TIM16_IS_USED)
+ nvicDisableVector(STM32_TIM1_UP_TIM16_NUMBER);
+#endif
+#if defined(STM32_TIM1_IS_USED) || defined(STM32_TIM17_IS_USED)
+ nvicDisableVector(STM32_TIM1_TRGCO_TIM17_NUMBER);
+#endif
+#if defined(STM32_TIM1_IS_USED)
+ nvicDisableVector(STM32_TIM1_CC_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_TIM1_IS_USED) || defined(STM32_TIM15_IS_USED) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief TIM1-BRK, TIM15 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM1_BRK_TIM15_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM15
+ gpt_lld_serve_interrupt(&GPTD15);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM15
+ icu_lld_serve_interrupt(&ICUD15);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM15
+ pwm_lld_serve_interrupt(&PWMD15);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM15
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_TIM1_IS_USED) || defined(STM32_TIM16_IS_USED) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief TIM1-UP, TIM16 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM1_UP_TIM16_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM1
+ gpt_lld_serve_interrupt(&GPTD1);
+#endif
+#if STM32_GPT_USE_TIM16
+ gpt_lld_serve_interrupt(&GPTD16);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM1
+ icu_lld_serve_interrupt(&ICUD1);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM1
+ pwm_lld_serve_interrupt(&PWMD1);
+#endif
+#if STM32_PWM_USE_TIM16
+ pwm_lld_serve_interrupt(&PWMD16);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM1
+ st_lld_serve_interrupt();
+#endif
+#if STM32_ST_USE_TIM16
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_TIM1_IS_USED) || defined(STM32_TIM17_IS_USED) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief TIM1-TRG-COM, TIM17 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM1_TRGCO_TIM17_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM17
+ gpt_lld_serve_interrupt(&GPTD17);
+#endif
+#endif
+#if HAL_USE_ICU
+ /* Not used by ICU.*/
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM17
+ pwm_lld_serve_interrupt(&PWMD17);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM17
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_TIM1_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TIM1-CC interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+ /* Not used by GPT.*/
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM1
+ icu_lld_serve_interrupt(&ICUD1);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM1
+ pwm_lld_serve_interrupt(&PWMD1);
+#endif
+#endif
+#if 1
+ /* Not used by ST.*/
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim1_9_10_11.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim1_9_10_11.inc
new file mode 100644
index 0000000..bebcf54
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim1_9_10_11.inc
@@ -0,0 +1,343 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim1_9_10_11.inc
+ * @brief Shared TIM1, TIM9, TIM10, TIM11 handler.
+ *
+ * @addtogroup STM32_TIM1_TIM9_TIM10_TIM11_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_TIM1)
+#error "STM32_HAS_TIM1 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_TIM9)
+#error "STM32_HAS_TIM9 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_TIM10)
+#error "STM32_HAS_TIM10 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_TIM11)
+#error "STM32_HAS_TIM11 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(STM32_GPT_USE_TIM1)
+#define STM32_GPT_USE_TIM1 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM1)
+#define STM32_ICU_USE_TIM1 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM1)
+#define STM32_PWM_USE_TIM1 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM1)
+#define STM32_ST_USE_TIM1 FALSE
+#endif
+
+#if !defined(STM32_GPT_USE_TIM9)
+#define STM32_GPT_USE_TIM9 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM9)
+#define STM32_ICU_USE_TIM9 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM9)
+#define STM32_PWM_USE_TIM9 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM9)
+#define STM32_ST_USE_TIM9 FALSE
+#endif
+
+#if !defined(STM32_GPT_USE_TIM10)
+#define STM32_GPT_USE_TIM10 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM10)
+#define STM32_ICU_USE_TIM10 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM10)
+#define STM32_PWM_USE_TIM10 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM10)
+#define STM32_ST_USE_TIM10 FALSE
+#endif
+
+#if !defined(STM32_GPT_USE_TIM11)
+#define STM32_GPT_USE_TIM11 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM11)
+#define STM32_ICU_USE_TIM11 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM11)
+#define STM32_PWM_USE_TIM11 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM11)
+#define STM32_ST_USE_TIM11 FALSE
+#endif
+
+#if STM32_HAS_TIM1 || STM32_HAS_TIM9 || STM32_HAS_TIM10 || STM32_HAS_TIM11
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_TIM1_BRK_TIM9_PRIORITY)
+#error "STM32_IRQ_TIM1_BRK_TIM9_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !defined(STM32_IRQ_TIM1_UP_TIM10_PRIORITY)
+#error "STM32_IRQ_TIM1_UP_TIM10_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !defined(STM32_IRQ_TIM1_TRGCO_TIM11_PRIORITY)
+#error "STM32_IRQ_TIM1_TRGCO_TIM11_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !defined(STM32_IRQ_TIM1_CC_PRIORITY)
+#error "STM32_IRQ_TIM1_CC_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM1_BRK_TIM9_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM1_BRK_TIM9_PRIORITY"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM1_UP_TIM10_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM1_UP_TIM10_PRIORITY"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM1_TRGCO_TIM11_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM1_TRGCO_TIM11_PRIORITY"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM1_CC_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM1_CC_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_TIM1 || STM32_HAS_TIM9 || STM32_HAS_TIM10 || STM32_HAS_TIM11 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tim1_tim9_tim10_tim11_irq_init(void) {
+#if defined(STM32_TIM1_IS_USED) || defined(STM32_TIM9_IS_USED)
+ nvicEnableVector(STM32_TIM1_BRK_TIM9_NUMBER,
+ STM32_IRQ_TIM1_BRK_TIM9_PRIORITY);
+#endif
+#if defined(STM32_TIM1_IS_USED) || defined(STM32_TIM10_IS_USED)
+ nvicEnableVector(STM32_TIM1_UP_TIM10_NUMBER,
+ STM32_IRQ_TIM1_UP_TIM10_PRIORITY);
+#endif
+#if defined(STM32_TIM1_IS_USED) || defined(STM32_TIM11_IS_USED)
+ nvicEnableVector(STM32_TIM1_TRGCO_TIM11_NUMBER,
+ STM32_IRQ_TIM1_TRGCO_TIM11_PRIORITY);
+#endif
+#if defined(STM32_TIM1_IS_USED)
+ nvicEnableVector(STM32_TIM1_CC_NUMBER,
+ STM32_IRQ_TIM1_CC_PRIORITY);
+#endif
+}
+
+static inline void tim1_tim9_tim10_tim11_irq_deinit(void) {
+#if defined(STM32_TIM1_IS_USED) || defined(STM32_TIM9_IS_USED)
+ nvicDisableVector(STM32_TIM1_BRK_TIM9_NUMBER);
+#endif
+#if defined(STM32_TIM1_IS_USED) || defined(STM32_TIM10_IS_USED)
+ nvicDisableVector(STM32_TIM1_UP_TIM10_NUMBER);
+#endif
+#if defined(STM32_TIM1_IS_USED) || defined(STM32_TIM11_IS_USED)
+ nvicDisableVector(STM32_TIM1_TRGCO_TIM11_NUMBER);
+#endif
+#if defined(STM32_TIM1_IS_USED)
+ nvicDisableVector(STM32_TIM1_CC_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_TIM1_IS_USED) || defined(STM32_TIM19_IS_USED) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief TIM1-BRK, TIM9 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM1_BRK_TIM9_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM9
+ gpt_lld_serve_interrupt(&GPTD9);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM9
+ icu_lld_serve_interrupt(&ICUD9);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM9
+ pwm_lld_serve_interrupt(&PWMD9);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM9
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_TIM1_IS_USED) || defined(STM32_TIM10_IS_USED) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief TIM1-UP, TIM10 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM1_UP_TIM10_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM1
+ gpt_lld_serve_interrupt(&GPTD1);
+#endif
+#if STM32_GPT_USE_TIM10
+ gpt_lld_serve_interrupt(&GPTD10);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM1
+ icu_lld_serve_interrupt(&ICUD1);
+#endif
+#if STM32_ICU_USE_TIM10
+ icu_lld_serve_interrupt(&ICUD10);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM1
+ pwm_lld_serve_interrupt(&PWMD1);
+#endif
+#if STM32_PWM_USE_TIM10
+ pwm_lld_serve_interrupt(&PWMD10);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM1
+ st_lld_serve_interrupt();
+#endif
+#if STM32_ST_USE_TIM10
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_TIM1_IS_USED) || defined(STM32_TIM11_IS_USED) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief TIM1-TRG-COM, TIM11 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM1_TRGCO_TIM11_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM11
+ gpt_lld_serve_interrupt(&GPTD11);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM11
+ icu_lld_serve_interrupt(&ICUD11);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM11
+ pwm_lld_serve_interrupt(&PWMD11);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM11
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_TIM1_IS_USED)
+/**
+ * @brief TIM1-CC interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM1_CC_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+ /* Not used by GPT.*/
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM1
+ icu_lld_serve_interrupt(&ICUD1);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM1
+ pwm_lld_serve_interrupt(&PWMD1);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim2.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim2.inc
new file mode 100644
index 0000000..435deae
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim2.inc
@@ -0,0 +1,133 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim2.inc
+ * @brief Shared TIM2 handler.
+ *
+ * @addtogroup STM32_TIM2_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_TIM2)
+#error "STM32_HAS_TIM2 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(STM32_GPT_USE_TIM2)
+#define STM32_GPT_USE_TIM2 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM2)
+#define STM32_ICU_USE_TIM2 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM2)
+#define STM32_PWM_USE_TIM2 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM2)
+#define STM32_ST_USE_TIM2 FALSE
+#endif
+
+#if STM32_HAS_TIM2
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_TIM2_PRIORITY)
+#error "STM32_IRQ_TIM2_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM2_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM2_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_TIM2 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tim2_irq_init(void) {
+#if defined(STM32_TIM2_IS_USED)
+ nvicEnableVector(STM32_TIM2_NUMBER, STM32_IRQ_TIM2_PRIORITY);
+#endif
+}
+
+static inline void tim2_irq_deinit(void) {
+#if defined(STM32_TIM2_IS_USED)
+ nvicDisableVector(STM32_TIM2_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_TIM2_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TIM2 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM2
+ gpt_lld_serve_interrupt(&GPTD2);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM2
+ icu_lld_serve_interrupt(&ICUD2);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM2
+ pwm_lld_serve_interrupt(&PWMD2);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM2
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim20.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim20.inc
new file mode 100644
index 0000000..1b08998
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim20.inc
@@ -0,0 +1,170 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim20.inc
+ * @brief Shared TIM20 handler.
+ *
+ * @addtogroup STM32_TIM20_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_TIM20)
+#error "STM32_HAS_TIM20 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(STM32_GPT_USE_TIM20)
+#define STM32_GPT_USE_TIM20 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM20)
+#define STM32_ICU_USE_TIM20 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM20)
+#define STM32_PWM_USE_TIM20 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM20)
+#define STM32_ST_USE_TIM20 FALSE
+#endif
+
+#if STM32_HAS_TIM20
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_TIM20_UP_PRIORITY)
+#error "STM32_IRQ_TIM20_UP_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !defined(STM32_IRQ_TIM20_CC_PRIORITY)
+#error "STM32_IRQ_TIM20_CC_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM20_UP_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM20_UP_PRIORITY"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM20_CC_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM20_CC_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_TIM20 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tim20_irq_init(void) {
+#if defined(STM32_TIM20_IS_USED)
+ nvicEnableVector(STM32_TIM20_UP_NUMBER, STM32_IRQ_TIM20_UP_PRIORITY);
+ nvicEnableVector(STM32_TIM20_CC_NUMBER, STM32_IRQ_TIM20_CC_PRIORITY);
+#endif
+}
+
+static inline void tim20_irq_deinit(void) {
+#if defined(STM32_TIM20_IS_USED)
+ nvicDisableVector(STM32_TIM20_UP_NUMBER);
+ nvicDisableVector(STM32_TIM20_CC_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_TIM20_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TIM20-UP interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM20_UP_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM20
+ pwm_lld_serve_interrupt(&GPTD20);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM20
+ pwm_lld_serve_interrupt(&ICUD20);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM20
+ pwm_lld_serve_interrupt(&PWMD20);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM20
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief TIM20-CC interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM20_CC_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+ /* Not used by GPT.*/
+#endif
+#if STM32_ICU_USE_TIM20
+ pwm_lld_serve_interrupt(&ICUD20);
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM20
+ pwm_lld_serve_interrupt(&PWMD20);
+#endif
+#endif
+#if 1
+ /* Not used by ST.*/
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim21.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim21.inc
new file mode 100644
index 0000000..4f98960
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim21.inc
@@ -0,0 +1,133 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim21.inc
+ * @brief Shared TIM21 handler.
+ *
+ * @addtogroup STM32_TIM21_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_TIM21)
+#error "STM32_HAS_TIM21 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(STM32_GPT_USE_TIM21)
+#define STM32_GPT_USE_TIM21 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM21)
+#define STM32_ICU_USE_TIM21 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM21)
+#define STM32_PWM_USE_TIM21 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM21)
+#define STM32_ST_USE_TIM21 FALSE
+#endif
+
+#if STM32_HAS_TIM21
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_TIM21_PRIORITY)
+#error "STM32_IRQ_TIM21_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM21_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM21_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_TIM21 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tim21_irq_init(void) {
+#if defined(STM32_TIM21_IS_USED)
+ nvicEnableVector(STM32_TIM21_NUMBER, STM32_IRQ_TIM21_PRIORITY);
+#endif
+}
+
+static inline void tim21_irq_deinit(void) {
+#if defined(STM32_TIM21_IS_USED)
+ nvicDisableVector(STM32_TIM21_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_TIM21_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TIM21 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM21_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM21
+ gpt_lld_serve_interrupt(&GPTD21);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM21
+ icu_lld_serve_interrupt(&ICUD21);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM21
+ pwm_lld_serve_interrupt(&PWMD21);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM21
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim22.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim22.inc
new file mode 100644
index 0000000..05ee7d3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim22.inc
@@ -0,0 +1,133 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim22.inc
+ * @brief Shared TIM22 handler.
+ *
+ * @addtogroup STM32_TIM22_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_TIM22)
+#error "STM32_HAS_TIM22 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(STM32_GPT_USE_TIM22)
+#define STM32_GPT_USE_TIM22 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM22)
+#define STM32_ICU_USE_TIM22 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM22)
+#define STM32_PWM_USE_TIM22 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM22)
+#define STM32_ST_USE_TIM22 FALSE
+#endif
+
+#if STM32_HAS_TIM22
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_TIM22_PRIORITY)
+#error "STM32_IRQ_TIM22_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM22_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM22_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_TIM22 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tim22_irq_init(void) {
+#if defined(STM32_TIM22_IS_USED)
+ nvicEnableVector(STM32_TIM22_NUMBER, STM32_IRQ_TIM22_PRIORITY);
+#endif
+}
+
+static inline void tim22_irq_deinit(void) {
+#if defined(STM32_TIM22_IS_USED)
+ nvicDisableVector(STM32_TIM22_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_TIM22_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TIM22 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM22_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM22
+ gpt_lld_serve_interrupt(&GPTD22);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM22
+ icu_lld_serve_interrupt(&ICUD22);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM22
+ pwm_lld_serve_interrupt(&PWMD22);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM22
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim3.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim3.inc
new file mode 100644
index 0000000..4521a92
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim3.inc
@@ -0,0 +1,133 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim3.inc
+ * @brief Shared TIM3 handler.
+ *
+ * @addtogroup STM32_TIM3_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_TIM3)
+#error "STM32_HAS_TIM3 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(STM32_GPT_USE_TIM3)
+#define STM32_GPT_USE_TIM3 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM3)
+#define STM32_ICU_USE_TIM3 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM3)
+#define STM32_PWM_USE_TIM3 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM3)
+#define STM32_ST_USE_TIM3 FALSE
+#endif
+
+#if STM32_HAS_TIM3
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_TIM3_PRIORITY)
+#error "STM32_IRQ_TIM3_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM3_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM3_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_TIM3 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tim3_irq_init(void) {
+#if defined(STM32_TIM3_IS_USED)
+ nvicEnableVector(STM32_TIM3_NUMBER, STM32_IRQ_TIM3_PRIORITY);
+#endif
+}
+
+static inline void tim3_irq_deinit(void) {
+#if defined(STM32_TIM3_IS_USED)
+ nvicDisableVector(STM32_TIM3_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_TIM3_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TIM3 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM3_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM3
+ gpt_lld_serve_interrupt(&GPTD3);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM3
+ icu_lld_serve_interrupt(&ICUD3);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM3
+ pwm_lld_serve_interrupt(&PWMD3);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM3
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim4.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim4.inc
new file mode 100644
index 0000000..6df48dc
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim4.inc
@@ -0,0 +1,133 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim4.inc
+ * @brief Shared TIM4 handler.
+ *
+ * @addtogroup STM32_TIM4_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_TIM4)
+#error "STM32_HAS_TIM4 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(STM32_GPT_USE_TIM4)
+#define STM32_GPT_USE_TIM4 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM4)
+#define STM32_ICU_USE_TIM4 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM4)
+#define STM32_PWM_USE_TIM4 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM4)
+#define STM32_ST_USE_TIM4 FALSE
+#endif
+
+#if STM32_HAS_TIM4
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_TIM4_PRIORITY)
+#error "STM32_IRQ_TIM4_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM4_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM4_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_TIM4 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tim4_irq_init(void) {
+#if defined(STM32_TIM4_IS_USED)
+ nvicEnableVector(STM32_TIM4_NUMBER, STM32_IRQ_TIM4_PRIORITY);
+#endif
+}
+
+static inline void tim4_irq_deinit(void) {
+#if defined(STM32_TIM4_IS_USED)
+ nvicDisableVector(STM32_TIM4_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_TIM4_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TIM4 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM4_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM4
+ gpt_lld_serve_interrupt(&GPTD4);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM4
+ icu_lld_serve_interrupt(&ICUD4);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM4
+ pwm_lld_serve_interrupt(&PWMD4);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM4
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim5.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim5.inc
new file mode 100644
index 0000000..35158b3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim5.inc
@@ -0,0 +1,133 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim5.inc
+ * @brief Shared TIM5 handler.
+ *
+ * @addtogroup STM32_TIM5_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_TIM5)
+#error "STM32_HAS_TIM5 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(STM32_GPT_USE_TIM5)
+#define STM32_GPT_USE_TIM5 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM5)
+#define STM32_ICU_USE_TIM5 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM5)
+#define STM32_PWM_USE_TIM5 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM5)
+#define STM32_ST_USE_TIM5 FALSE
+#endif
+
+#if STM32_HAS_TIM5
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_TIM5_PRIORITY)
+#error "STM32_IRQ_TIM5_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM5_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM5_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_TIM5 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tim5_irq_init(void) {
+#if defined(STM32_TIM5_IS_USED)
+ nvicEnableVector(STM32_TIM5_NUMBER, STM32_IRQ_TIM5_PRIORITY);
+#endif
+}
+
+static inline void tim5_irq_deinit(void) {
+#if defined(STM32_TIM5_IS_USED)
+ nvicDisableVector(STM32_TIM5_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_TIM5_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TIM5 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM5_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM5
+ gpt_lld_serve_interrupt(&GPTD5);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM5
+ icu_lld_serve_interrupt(&ICUD5);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM5
+ pwm_lld_serve_interrupt(&PWMD5);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM5
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim6.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim6.inc
new file mode 100644
index 0000000..200d103
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim6.inc
@@ -0,0 +1,133 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim6.inc
+ * @brief Shared TIM6 handler.
+ *
+ * @addtogroup STM32_TIM6_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_TIM6)
+#error "STM32_HAS_TIM6 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(STM32_GPT_USE_TIM6)
+#define STM32_GPT_USE_TIM6 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM6)
+#define STM32_ICU_USE_TIM6 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM6)
+#define STM32_PWM_USE_TIM6 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM6)
+#define STM32_ST_USE_TIM6 FALSE
+#endif
+
+#if STM32_HAS_TIM6
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_TIM6_PRIORITY)
+#error "STM32_IRQ_TIM6_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM6_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM6_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_TIM6 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tim6_irq_init(void) {
+#if defined(STM32_TIM6_IS_USED)
+ nvicEnableVector(STM32_TIM6_NUMBER, STM32_IRQ_TIM6_PRIORITY);
+#endif
+}
+
+static inline void tim6_irq_deinit(void) {
+#if defined(STM32_TIM6_IS_USED)
+ nvicDisableVector(STM32_TIM6_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_TIM6_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TIM6 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM6_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM6
+ gpt_lld_serve_interrupt(&GPTD6);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM6
+ icu_lld_serve_interrupt(&ICUD6);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM6
+ pwm_lld_serve_interrupt(&PWMD6);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM6
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim7.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim7.inc
new file mode 100644
index 0000000..8ea4e0f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim7.inc
@@ -0,0 +1,133 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim7.inc
+ * @brief Shared TIM7 handler.
+ *
+ * @addtogroup STM32_TIM7_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_TIM7)
+#error "STM32_HAS_TIM7 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(STM32_GPT_USE_TIM7)
+#define STM32_GPT_USE_TIM7 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM7)
+#define STM32_ICU_USE_TIM7 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM7)
+#define STM32_PWM_USE_TIM7 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM7)
+#define STM32_ST_USE_TIM7 FALSE
+#endif
+
+#if STM32_HAS_TIM7
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_TIM7_PRIORITY)
+#error "STM32_IRQ_TIM7_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM7_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM7_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_TIM7 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tim7_irq_init(void) {
+#if defined(STM32_TIM7_IS_USED)
+ nvicEnableVector(STM32_TIM7_NUMBER, STM32_IRQ_TIM7_PRIORITY);
+#endif
+}
+
+static inline void tim7_irq_deinit(void) {
+#if defined(STM32_TIM7_IS_USED)
+ nvicDisableVector(STM32_TIM7_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_TIM7_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TIM7 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM7_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM7
+ gpt_lld_serve_interrupt(&GPTD7);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM7
+ icu_lld_serve_interrupt(&ICUD7);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM7
+ pwm_lld_serve_interrupt(&PWMD7);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM7
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim8.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim8.inc
new file mode 100644
index 0000000..db9219c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim8.inc
@@ -0,0 +1,172 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim8.inc
+ * @brief Shared TIM8 handler.
+ *
+ * @addtogroup STM32_TIM8_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_TIM8)
+#error "STM32_HAS_TIM8 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(STM32_GPT_USE_TIM8)
+#define STM32_GPT_USE_TIM8 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM8)
+#define STM32_ICU_USE_TIM8 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM8)
+#define STM32_PWM_USE_TIM8 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM8)
+#define STM32_ST_USE_TIM8 FALSE
+#endif
+
+#if STM32_HAS_TIM8
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_TIM8_UP_PRIORITY)
+#error "STM32_IRQ_TIM8_UP_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !defined(STM32_IRQ_TIM8_CC_PRIORITY)
+#error "STM32_IRQ_TIM8_CC_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM8_UP_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM8_UP_PRIORITY"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM8_CC_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM8_CC_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_TIM8 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tim8_irq_init(void) {
+#if defined(STM32_TIM8_IS_USED)
+ nvicEnableVector(STM32_TIM8_UP_NUMBER, STM32_IRQ_TIM8_UP_PRIORITY);
+ nvicEnableVector(STM32_TIM8_CC_NUMBER, STM32_IRQ_TIM8_CC_PRIORITY);
+#endif
+}
+
+static inline void tim8_irq_deinit(void) {
+#if defined(STM32_TIM8_IS_USED)
+ nvicDisableVector(STM32_TIM8_UP_NUMBER);
+ nvicDisableVector(STM32_TIM8_CC_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_TIM8_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TIM8-UP interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM8_UP_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM8
+ gpt_lld_serve_interrupt(&GPTD8);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM8
+ icu_lld_serve_interrupt(&ICUD8);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM8
+ pwm_lld_serve_interrupt(&PWMD8);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM8
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief TIM8-CC interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+ /* Not used by GPT.*/
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM8
+ icu_lld_serve_interrupt(&ICUD8);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM8
+ pwm_lld_serve_interrupt(&PWMD8);
+#endif
+#endif
+#if 1
+ /* Not used by ST.*/
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim8_12_13_14.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim8_12_13_14.inc
new file mode 100644
index 0000000..fe23514
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/stm32_tim8_12_13_14.inc
@@ -0,0 +1,343 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file TIMv1/stm32_tim8_12_13_14.inc
+ * @brief Shared TIM8, TIM12, TIM13, TIM14 handler.
+ *
+ * @addtogroup STM32_TIM8_TIM12_TIM13_TIM14_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_TIM8)
+#error "STM32_HAS_TIM8 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_TIM12)
+#error "STM32_HAS_TIM12 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_TIM13)
+#error "STM32_HAS_TIM13 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_TIM14)
+#error "STM32_HAS_TIM14 not defined in registry"
+#endif
+
+/* Driver checks for robustness, undefined USE macros are defaulted to
+ FALSE. This makes this module independent from drivers implementation.*/
+#if !defined(STM32_GPT_USE_TIM8)
+#define STM32_GPT_USE_TIM8 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM8)
+#define STM32_ICU_USE_TIM8 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM8)
+#define STM32_PWM_USE_TIM8 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM8)
+#define STM32_ST_USE_TIM8 FALSE
+#endif
+
+#if !defined(STM32_GPT_USE_TIM12)
+#define STM32_GPT_USE_TIM12 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM12)
+#define STM32_ICU_USE_TIM12 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM12)
+#define STM32_PWM_USE_TIM12 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM12)
+#define STM32_ST_USE_TIM12 FALSE
+#endif
+
+#if !defined(STM32_GPT_USE_TIM13)
+#define STM32_GPT_USE_TIM13 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM13)
+#define STM32_ICU_USE_TIM13 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM13)
+#define STM32_PWM_USE_TIM13 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM13)
+#define STM32_ST_USE_TIM13 FALSE
+#endif
+
+#if !defined(STM32_GPT_USE_TIM14)
+#define STM32_GPT_USE_TIM14 FALSE
+#endif
+#if !defined(STM32_ICU_USE_TIM14)
+#define STM32_ICU_USE_TIM14 FALSE
+#endif
+#if !defined(STM32_PWM_USE_TIM14)
+#define STM32_PWM_USE_TIM14 FALSE
+#endif
+#if !defined(STM32_ST_USE_TIM14)
+#define STM32_ST_USE_TIM14 FALSE
+#endif
+
+#if STM32_HAS_TIM8 || STM32_HAS_TIM12 || STM32_HAS_TIM13 || STM32_HAS_TIM14
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_TIM8_BRK_TIM12_PRIORITY)
+#error "STM32_IRQ_TIM8_BRK_TIM12_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !defined(STM32_IRQ_TIM8_UP_TIM13_PRIORITY)
+#error "STM32_IRQ_TIM8_UP_TIM13_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !defined(STM32_IRQ_TIM8_TRGCO_TIM14_PRIORITY)
+#error "STM32_IRQ_TIM8_TRGCO_TIM14_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !defined(STM32_IRQ_TIM8_CC_PRIORITY)
+#error "STM32_IRQ_TIM8_CC_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM8_BRK_TIM12_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM8_BRK_TIM12_PRIORITY"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM8_UP_TIM13_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM8_UP_TIM13_PRIORITY"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM8_TRGCO_TIM14_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM8_TRGCO_TIM14_PRIORITY"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_TIM8_CC_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_TIM8_CC_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_TIM8 || STM32_HAS_TIM12 || STM32_HAS_TIM13 || STM32_HAS_TIM14 */
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void tim8_tim12_tim13_tim14_irq_init(void) {
+#if defined(STM32_TIM8_IS_USED) || defined(STM32_TIM12_IS_USED)
+ nvicEnableVector(STM32_TIM8_BRK_TIM12_NUMBER,
+ STM32_IRQ_TIM8_BRK_TIM12_PRIORITY);
+#endif
+#if defined(STM32_TIM8_IS_USED) || defined(STM32_TIM13_IS_USED)
+ nvicEnableVector(STM32_TIM8_UP_TIM13_NUMBER,
+ STM32_IRQ_TIM8_UP_TIM13_PRIORITY);
+#endif
+#if defined(STM32_TIM8_IS_USED) || defined(STM32_TIM14_IS_USED)
+ nvicEnableVector(STM32_TIM8_TRGCO_TIM14_NUMBER,
+ STM32_IRQ_TIM8_TRGCO_TIM14_PRIORITY);
+#endif
+#if defined(STM32_TIM8_IS_USED)
+ nvicEnableVector(STM32_TIM8_CC_NUMBER,
+ STM32_IRQ_TIM8_CC_PRIORITY);
+#endif
+}
+
+static inline void tim8_tim12_tim13_tim14_irq_deinit(void) {
+#if defined(STM32_TIM8_IS_USED) || defined(STM32_TIM12_IS_USED)
+ nvicDisableVector(STM32_TIM8_BRK_TIM12_NUMBER);
+#endif
+#if defined(STM32_TIM8_IS_USED) || defined(STM32_TIM13_IS_USED)
+ nvicDisableVector(STM32_TIM8_UP_TIM13_NUMBER);
+#endif
+#if defined(STM32_TIM8_IS_USED) || defined(STM32_TIM14_IS_USED)
+ nvicDisableVector(STM32_TIM8_TRGCO_TIM14_NUMBER);
+#endif
+#if defined(STM32_TIM8_IS_USED)
+ nvicDisableVector(STM32_TIM8_CC_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if defined(STM32_TIM8_IS_USED) || defined(STM32_TIM12_IS_USED) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief TIM8-BRK, TIM12 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM8_BRK_TIM12_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM12
+ gpt_lld_serve_interrupt(&GPTD12);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM12
+ icu_lld_serve_interrupt(&ICUD12);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM12
+ pwm_lld_serve_interrupt(&PWMD12);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM12
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_TIM8_IS_USED) || defined(STM32_TIM13_IS_USED) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief TIM8-UP, TIM13 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM8_UP_TIM13_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM8
+ gpt_lld_serve_interrupt(&GPTD8);
+#endif
+#if STM32_GPT_USE_TIM13
+ gpt_lld_serve_interrupt(&GPTD13);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM8
+ icu_lld_serve_interrupt(&ICUD8);
+#endif
+#if STM32_ICU_USE_TIM13
+ icu_lld_serve_interrupt(&ICUD13);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM8
+ pwm_lld_serve_interrupt(&PWMD8);
+#endif
+#if STM32_PWM_USE_TIM13
+ pwm_lld_serve_interrupt(&PWMD13);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM8
+ st_lld_serve_interrupt();
+#endif
+#if STM32_ST_USE_TIM13
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_TIM8_IS_USED) || defined(STM32_TIM14_IS_USED) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief TIM8-TRG-COM, TIM14 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM8_TRGCO_TIM14_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+#if STM32_GPT_USE_TIM14
+ gpt_lld_serve_interrupt(&GPTD14);
+#endif
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM14
+ icu_lld_serve_interrupt(&ICUD14);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM14
+ pwm_lld_serve_interrupt(&PWMD14);
+#endif
+#endif
+#if 1
+#if STM32_ST_USE_TIM14
+ st_lld_serve_interrupt();
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if defined(STM32_TIM8_IS_USED) || defined(__DOXYGEN__)
+/**
+ * @brief TIM8-CC interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_TIM8_CC_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_GPT
+ /* Not used by GPT.*/
+#endif
+#if HAL_USE_ICU
+#if STM32_ICU_USE_TIM8
+ icu_lld_serve_interrupt(&ICUD8);
+#endif
+#endif
+#if HAL_USE_PWM
+#if STM32_PWM_USE_TIM8
+ pwm_lld_serve_interrupt(&PWMD8);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/tim_irq_mapping.txt b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/tim_irq_mapping.txt
new file mode 100644
index 0000000..ed21572
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/TIMv1/tim_irq_mapping.txt
@@ -0,0 +1,14 @@
+TIM units IRQ collisions mapping.
+
+ 1B 1UP 1TC 1CC 2 3 4 5 6 7 8B 8UP 8TC 8CC 9 10 11 12 13 14 15 16 17 18 19 20 21 22 LP1 LP2
+F0xx 1---1 2---2 * * * * * * * *
+F030 1---1 2---2 * * * * *
+F1xx 1 2 3 * * * * * * * 1 2 3
+F100 1 2 3 * * * * * * * 1 2 3
+F3xx 1 2 3 * * * * * * * * * * 1 2 3
+F37x * * * * * * * * * * * * * *
+F4xx 1 2 3 * * * * * * * 4 5 6 * 1 2 3 4 5 6
+F7xx 1 2 3 * * * * * * * 4 5 6 * 1 2 3 4 5 6 *
+L0xx * * * * * * *
+L1xx * * * * * * * * *
+L4xx 1 2 3 * * * * * * * * * * * 1 2 3 * *
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv1/driver.mk
new file mode 100644
index 0000000..2f65c1f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv1/driver.mk
@@ -0,0 +1,13 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_SERIAL TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.c
+endif
+ifneq ($(findstring HAL_USE_UART TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.c
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.c
new file mode 100644
index 0000000..188740e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.c
@@ -0,0 +1,650 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv1/hal_serial_lld.c
+ * @brief STM32 low level serial driver code.
+ *
+ * @addtogroup SERIAL
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_SERIAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief USART1 serial driver identifier.*/
+#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__)
+SerialDriver SD1;
+#endif
+
+/** @brief USART2 serial driver identifier.*/
+#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__)
+SerialDriver SD2;
+#endif
+
+/** @brief USART3 serial driver identifier.*/
+#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__)
+SerialDriver SD3;
+#endif
+
+/** @brief UART4 serial driver identifier.*/
+#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__)
+SerialDriver SD4;
+#endif
+
+/** @brief UART5 serial driver identifier.*/
+#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__)
+SerialDriver SD5;
+#endif
+
+/** @brief USART6 serial driver identifier.*/
+#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__)
+SerialDriver SD6;
+#endif
+
+/** @brief UART7 serial driver identifier.*/
+#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__)
+SerialDriver SD7;
+#endif
+
+/** @brief UART8 serial driver identifier.*/
+#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__)
+SerialDriver SD8;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/** @brief Driver default configuration.*/
+static const SerialConfig default_config =
+{
+ SERIAL_DEFAULT_BITRATE,
+ 0,
+ USART_CR2_STOP1_BITS,
+ 0
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief USART initialization.
+ * @details This function must be invoked with interrupts disabled.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ * @param[in] config the architecture-dependent serial driver configuration
+ */
+static void usart_init(SerialDriver *sdp, const SerialConfig *config) {
+ uint32_t fck;
+ USART_TypeDef *u = sdp->usart;
+
+ /* Baud rate setting.*/
+#if STM32_HAS_USART6
+ if ((sdp->usart == USART1) || (sdp->usart == USART6))
+#else
+ if (sdp->usart == USART1)
+#endif
+ fck = STM32_PCLK2 / config->speed;
+ else
+ fck = STM32_PCLK1 / config->speed;
+
+ /* Correcting USARTDIV when oversampling by 8 instead of 16.
+ Fraction is still 4 bits wide, but only lower 3 bits used.
+ Mantissa is doubled, but Fraction is left the same.*/
+#if defined(USART_CR1_OVER8)
+ if (config->cr1 & USART_CR1_OVER8)
+ fck = ((fck & ~7) * 2) | (fck & 7);
+#endif
+ u->BRR = fck;
+
+ /* Note that some bits are enforced.*/
+ u->CR2 = config->cr2 | USART_CR2_LBDIE;
+ u->CR3 = config->cr3 | USART_CR3_EIE;
+ u->CR1 = config->cr1 | USART_CR1_UE | USART_CR1_PEIE |
+ USART_CR1_RXNEIE | USART_CR1_TE |
+ USART_CR1_RE;
+ u->SR = 0;
+ (void)u->SR; /* SR reset step 1.*/
+ (void)u->DR; /* SR reset step 2.*/
+
+ /* Deciding mask to be applied on the data register on receive, this is
+ required in order to mask out the parity bit.*/
+ if ((config->cr1 & (USART_CR1_M | USART_CR1_PCE)) == USART_CR1_PCE) {
+ sdp->rxmask = 0x7F;
+ }
+ else {
+ sdp->rxmask = 0xFF;
+ }
+}
+
+/**
+ * @brief USART de-initialization.
+ * @details This function must be invoked with interrupts disabled.
+ *
+ * @param[in] u pointer to an USART I/O block
+ */
+static void usart_deinit(USART_TypeDef *u) {
+
+ u->CR1 = 0;
+ u->CR2 = 0;
+ u->CR3 = 0;
+}
+
+/**
+ * @brief Error handling routine.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ * @param[in] sr USART SR register value
+ */
+static void set_error(SerialDriver *sdp, uint16_t sr) {
+ eventflags_t sts = 0;
+
+ if (sr & USART_SR_ORE)
+ sts |= SD_OVERRUN_ERROR;
+ if (sr & USART_SR_PE)
+ sts |= SD_PARITY_ERROR;
+ if (sr & USART_SR_FE)
+ sts |= SD_FRAMING_ERROR;
+ if (sr & USART_SR_NE)
+ sts |= SD_NOISE_ERROR;
+ chnAddFlagsI(sdp, sts);
+}
+
+/**
+ * @brief Common IRQ handler.
+ *
+ * @param[in] sdp communication channel associated to the USART
+ */
+static void serve_interrupt(SerialDriver *sdp) {
+ USART_TypeDef *u = sdp->usart;
+ uint16_t cr1 = u->CR1;
+ uint16_t sr = u->SR;
+
+ /* Special case, LIN break detection.*/
+ if (sr & USART_SR_LBD) {
+ osalSysLockFromISR();
+ chnAddFlagsI(sdp, SD_BREAK_DETECTED);
+ u->SR = ~USART_SR_LBD;
+ osalSysUnlockFromISR();
+ }
+
+ /* Data available.*/
+ osalSysLockFromISR();
+ while (sr & (USART_SR_RXNE | USART_SR_ORE | USART_SR_NE | USART_SR_FE |
+ USART_SR_PE)) {
+ uint8_t b;
+
+ /* Error condition detection.*/
+ if (sr & (USART_SR_ORE | USART_SR_NE | USART_SR_FE | USART_SR_PE))
+ set_error(sdp, sr);
+ b = (uint8_t)u->DR & sdp->rxmask;
+ if (sr & USART_SR_RXNE)
+ sdIncomingDataI(sdp, b);
+ sr = u->SR;
+ }
+ osalSysUnlockFromISR();
+
+ /* Transmission buffer empty.*/
+ if ((cr1 & USART_CR1_TXEIE) && (sr & USART_SR_TXE)) {
+ msg_t b;
+ osalSysLockFromISR();
+ b = oqGetI(&sdp->oqueue);
+ if (b < MSG_OK) {
+ chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
+ u->CR1 = cr1 & ~USART_CR1_TXEIE;
+ }
+ else
+ u->DR = b;
+ osalSysUnlockFromISR();
+ }
+
+ /* Physical transmission end.*/
+ if ((cr1 & USART_CR1_TCIE) && (sr & USART_SR_TC)) {
+ osalSysLockFromISR();
+ if (oqIsEmptyI(&sdp->oqueue)) {
+ chnAddFlagsI(sdp, CHN_TRANSMISSION_END);
+ u->CR1 = cr1 & ~USART_CR1_TCIE;
+ }
+ osalSysUnlockFromISR();
+ }
+}
+
+#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__)
+static void notify1(io_queue_t *qp) {
+
+ (void)qp;
+ USART1->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__)
+static void notify2(io_queue_t *qp) {
+
+ (void)qp;
+ USART2->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__)
+static void notify3(io_queue_t *qp) {
+
+ (void)qp;
+ USART3->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__)
+static void notify4(io_queue_t *qp) {
+
+ (void)qp;
+ UART4->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__)
+static void notify5(io_queue_t *qp) {
+
+ (void)qp;
+ UART5->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__)
+static void notify6(io_queue_t *qp) {
+
+ (void)qp;
+ USART6->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__)
+static void notify7(io_queue_t *qp) {
+
+ (void)qp;
+ UART7->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__)
+static void notify8(io_queue_t *qp) {
+
+ (void)qp;
+ UART8->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE;
+}
+#endif
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__)
+#if !defined(STM32_USART1_HANDLER)
+#error "STM32_USART1_HANDLER not defined"
+#endif
+/**
+ * @brief USART1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ serve_interrupt(&SD1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__)
+#if !defined(STM32_USART2_HANDLER)
+#error "STM32_USART2_HANDLER not defined"
+#endif
+/**
+ * @brief USART2 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ serve_interrupt(&SD2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__)
+#if !defined(STM32_USART3_HANDLER)
+#error "STM32_USART3_HANDLER not defined"
+#endif
+/**
+ * @brief USART3 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ serve_interrupt(&SD3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__)
+#if !defined(STM32_UART4_HANDLER)
+#error "STM32_UART4_HANDLER not defined"
+#endif
+/**
+ * @brief UART4 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ serve_interrupt(&SD4);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__)
+#if !defined(STM32_UART5_HANDLER)
+#error "STM32_UART5_HANDLER not defined"
+#endif
+/**
+ * @brief UART5 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ serve_interrupt(&SD5);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__)
+#if !defined(STM32_USART6_HANDLER)
+#error "STM32_USART6_HANDLER not defined"
+#endif
+/**
+ * @brief USART6 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ serve_interrupt(&SD6);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__)
+#if !defined(STM32_UART7_HANDLER)
+#error "STM32_UART7_HANDLER not defined"
+#endif
+/**
+ * @brief UART7 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART7_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ serve_interrupt(&SD7);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__)
+#if !defined(STM32_UART8_HANDLER)
+#error "STM32_UART8_HANDLER not defined"
+#endif
+/**
+ * @brief UART8 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART8_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ serve_interrupt(&SD8);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level serial driver initialization.
+ *
+ * @notapi
+ */
+void sd_lld_init(void) {
+
+#if STM32_SERIAL_USE_USART1
+ sdObjectInit(&SD1, NULL, notify1);
+ SD1.usart = USART1;
+#endif
+
+#if STM32_SERIAL_USE_USART2
+ sdObjectInit(&SD2, NULL, notify2);
+ SD2.usart = USART2;
+#endif
+
+#if STM32_SERIAL_USE_USART3
+ sdObjectInit(&SD3, NULL, notify3);
+ SD3.usart = USART3;
+#endif
+
+#if STM32_SERIAL_USE_UART4
+ sdObjectInit(&SD4, NULL, notify4);
+ SD4.usart = UART4;
+#endif
+
+#if STM32_SERIAL_USE_UART5
+ sdObjectInit(&SD5, NULL, notify5);
+ SD5.usart = UART5;
+#endif
+
+#if STM32_SERIAL_USE_USART6
+ sdObjectInit(&SD6, NULL, notify6);
+ SD6.usart = USART6;
+#endif
+
+#if STM32_SERIAL_USE_UART7
+ sdObjectInit(&SD7, NULL, notify7);
+ SD7.usart = UART7;
+#endif
+
+#if STM32_SERIAL_USE_UART8
+ sdObjectInit(&SD8, NULL, notify8);
+ SD8.usart = UART8;
+#endif
+}
+
+/**
+ * @brief Low level serial driver configuration and (re)start.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ * @param[in] config the architecture-dependent serial driver configuration.
+ * If this parameter is set to @p NULL then a default
+ * configuration is used.
+ *
+ * @notapi
+ */
+void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
+
+ if (config == NULL)
+ config = &default_config;
+
+ if (sdp->state == SD_STOP) {
+#if STM32_SERIAL_USE_USART1
+ if (&SD1 == sdp) {
+ rccEnableUSART1(true);
+ nvicEnableVector(STM32_USART1_NUMBER, STM32_SERIAL_USART1_PRIORITY);
+ }
+#endif
+#if STM32_SERIAL_USE_USART2
+ if (&SD2 == sdp) {
+ rccEnableUSART2(true);
+ nvicEnableVector(STM32_USART2_NUMBER, STM32_SERIAL_USART2_PRIORITY);
+ }
+#endif
+#if STM32_SERIAL_USE_USART3
+ if (&SD3 == sdp) {
+ rccEnableUSART3(true);
+ nvicEnableVector(STM32_USART3_NUMBER, STM32_SERIAL_USART3_PRIORITY);
+ }
+#endif
+#if STM32_SERIAL_USE_UART4
+ if (&SD4 == sdp) {
+ rccEnableUART4(true);
+ nvicEnableVector(STM32_UART4_NUMBER, STM32_SERIAL_UART4_PRIORITY);
+ }
+#endif
+#if STM32_SERIAL_USE_UART5
+ if (&SD5 == sdp) {
+ rccEnableUART5(true);
+ nvicEnableVector(STM32_UART5_NUMBER, STM32_SERIAL_UART5_PRIORITY);
+ }
+#endif
+#if STM32_SERIAL_USE_USART6
+ if (&SD6 == sdp) {
+ rccEnableUSART6(true);
+ nvicEnableVector(STM32_USART6_NUMBER, STM32_SERIAL_USART6_PRIORITY);
+ }
+#endif
+#if STM32_SERIAL_USE_UART7
+ if (&SD7 == sdp) {
+ rccEnableUART7(true);
+ nvicEnableVector(STM32_UART7_NUMBER, STM32_SERIAL_UART7_PRIORITY);
+ }
+#endif
+#if STM32_SERIAL_USE_UART8
+ if (&SD8 == sdp) {
+ rccEnableUART8(true);
+ nvicEnableVector(STM32_UART8_NUMBER, STM32_SERIAL_UART8_PRIORITY);
+ }
+#endif
+ }
+ usart_init(sdp, config);
+}
+
+/**
+ * @brief Low level serial driver stop.
+ * @details De-initializes the USART, stops the associated clock, resets the
+ * interrupt vector.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ *
+ * @notapi
+ */
+void sd_lld_stop(SerialDriver *sdp) {
+
+ if (sdp->state == SD_READY) {
+ usart_deinit(sdp->usart);
+#if STM32_SERIAL_USE_USART1
+ if (&SD1 == sdp) {
+ rccDisableUSART1();
+ nvicDisableVector(STM32_USART1_NUMBER);
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_USART2
+ if (&SD2 == sdp) {
+ rccDisableUSART2();
+ nvicDisableVector(STM32_USART2_NUMBER);
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_USART3
+ if (&SD3 == sdp) {
+ rccDisableUSART3();
+ nvicDisableVector(STM32_USART3_NUMBER);
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_UART4
+ if (&SD4 == sdp) {
+ rccDisableUART4();
+ nvicDisableVector(STM32_UART4_NUMBER);
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_UART5
+ if (&SD5 == sdp) {
+ rccDisableUART5();
+ nvicDisableVector(STM32_UART5_NUMBER);
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_USART6
+ if (&SD6 == sdp) {
+ rccDisableUSART6();
+ nvicDisableVector(STM32_USART6_NUMBER);
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_UART7
+ if (&SD7 == sdp) {
+ rccDisableUART7();
+ nvicDisableVector(STM32_UART7_NUMBER);
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_UART8
+ if (&SD8 == sdp) {
+ rccDisableUART8();
+ nvicDisableVector(STM32_UART8_NUMBER);
+ return;
+ }
+#endif
+ }
+}
+
+#endif /* HAL_USE_SERIAL */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.h
new file mode 100644
index 0000000..de259a7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv1/hal_serial_lld.h
@@ -0,0 +1,362 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv1/hal_serial_lld.h
+ * @brief STM32 low level serial driver header.
+ *
+ * @addtogroup SERIAL
+ * @{
+ */
+
+#ifndef HAL_SERIAL_LLD_H
+#define HAL_SERIAL_LLD_H
+
+#if HAL_USE_SERIAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief USART1 driver enable switch.
+ * @details If set to @p TRUE the support for USART1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SERIAL_USE_USART1) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USE_USART1 FALSE
+#endif
+
+/**
+ * @brief USART2 driver enable switch.
+ * @details If set to @p TRUE the support for USART2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SERIAL_USE_USART2) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USE_USART2 FALSE
+#endif
+
+/**
+ * @brief USART3 driver enable switch.
+ * @details If set to @p TRUE the support for USART3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SERIAL_USE_USART3) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USE_USART3 FALSE
+#endif
+
+/**
+ * @brief UART4 driver enable switch.
+ * @details If set to @p TRUE the support for UART4 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SERIAL_USE_UART4) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USE_UART4 FALSE
+#endif
+
+/**
+ * @brief UART5 driver enable switch.
+ * @details If set to @p TRUE the support for UART5 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SERIAL_USE_UART5) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USE_UART5 FALSE
+#endif
+
+/**
+ * @brief USART6 driver enable switch.
+ * @details If set to @p TRUE the support for USART6 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SERIAL_USE_USART6) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USE_USART6 FALSE
+#endif
+
+/**
+ * @brief UART7 driver enable switch.
+ * @details If set to @p TRUE the support for UART7 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SERIAL_USE_UART7) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USE_UART7 FALSE
+#endif
+
+/**
+ * @brief UART8 driver enable switch.
+ * @details If set to @p TRUE the support for UART8 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SERIAL_USE_UART8) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USE_UART8 FALSE
+#endif
+
+/**
+ * @brief USART1 interrupt priority level setting.
+ */
+#if !defined(STM32_SERIAL_USART1_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USART1_PRIORITY 12
+#endif
+
+/**
+ * @brief USART2 interrupt priority level setting.
+ */
+#if !defined(STM32_SERIAL_USART2_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USART2_PRIORITY 12
+#endif
+
+/**
+ * @brief USART3 interrupt priority level setting.
+ */
+#if !defined(STM32_SERIAL_USART3_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USART3_PRIORITY 12
+#endif
+
+/**
+ * @brief UART4 interrupt priority level setting.
+ */
+#if !defined(STM32_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SERIAL_UART4_PRIORITY 12
+#endif
+
+/**
+ * @brief UART5 interrupt priority level setting.
+ */
+#if !defined(STM32_SERIAL_UART5_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SERIAL_UART5_PRIORITY 12
+#endif
+
+/**
+ * @brief USART6 interrupt priority level setting.
+ */
+#if !defined(STM32_SERIAL_USART6_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USART6_PRIORITY 12
+#endif
+
+/**
+ * @brief UART7 interrupt priority level setting.
+ */
+#if !defined(STM32_SERIAL_UART7_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SERIAL_UART7_PRIORITY 12
+#endif
+
+/**
+ * @brief UART8 interrupt priority level setting.
+ */
+#if !defined(STM32_SERIAL_UART8_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SERIAL_UART8_PRIORITY 12
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if STM32_SERIAL_USE_USART1 && !STM32_HAS_USART1
+#error "USART1 not present in the selected device"
+#endif
+
+#if STM32_SERIAL_USE_USART2 && !STM32_HAS_USART2
+#error "USART2 not present in the selected device"
+#endif
+
+#if STM32_SERIAL_USE_USART3 && !STM32_HAS_USART3
+#error "USART3 not present in the selected device"
+#endif
+
+#if STM32_SERIAL_USE_UART4 && !STM32_HAS_UART4
+#error "UART4 not present in the selected device"
+#endif
+
+#if STM32_SERIAL_USE_UART5 && !STM32_HAS_UART5
+#error "UART5 not present in the selected device"
+#endif
+
+#if STM32_SERIAL_USE_USART6 && !STM32_HAS_USART6
+#error "USART6 not present in the selected device"
+#endif
+
+#if STM32_SERIAL_USE_UART7 && !STM32_HAS_UART7
+#error "UART7 not present in the selected device"
+#endif
+
+#if STM32_SERIAL_USE_UART8 && !STM32_HAS_UART8
+#error "UART8 not present in the selected device"
+#endif
+
+#if !STM32_SERIAL_USE_USART1 && !STM32_SERIAL_USE_USART2 && \
+ !STM32_SERIAL_USE_USART3 && !STM32_SERIAL_USE_UART4 && \
+ !STM32_SERIAL_USE_UART5 && !STM32_SERIAL_USE_USART6 && \
+ !STM32_SERIAL_USE_UART7 && !STM32_SERIAL_USE_UART8
+#error "SERIAL driver activated but no USART/UART peripheral assigned"
+#endif
+
+#if STM32_SERIAL_USE_USART1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART1_PRIORITY)
+#error "Invalid IRQ priority assigned to USART1"
+#endif
+
+#if STM32_SERIAL_USE_USART2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART2_PRIORITY)
+#error "Invalid IRQ priority assigned to USART2"
+#endif
+
+#if STM32_SERIAL_USE_USART3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART3_PRIORITY)
+#error "Invalid IRQ priority assigned to USART3"
+#endif
+
+#if STM32_SERIAL_USE_UART4 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART4_PRIORITY)
+#error "Invalid IRQ priority assigned to UART4"
+#endif
+
+#if STM32_SERIAL_USE_UART5 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART5_PRIORITY)
+#error "Invalid IRQ priority assigned to UART5"
+#endif
+
+#if STM32_SERIAL_USE_USART6 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART6_PRIORITY)
+#error "Invalid IRQ priority assigned to USART6"
+#endif
+
+#if STM32_SERIAL_USE_UART7 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART7_PRIORITY)
+#error "Invalid IRQ priority assigned to UART7"
+#endif
+
+#if STM32_SERIAL_USE_UART8 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART8_PRIORITY)
+#error "Invalid IRQ priority assigned to UART8"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 Serial Driver configuration structure.
+ * @details An instance of this structure must be passed to @p sdStart()
+ * in order to configure and start a serial driver operations.
+ * @note This structure content is architecture dependent, each driver
+ * implementation defines its own version and the custom static
+ * initializers.
+ */
+typedef struct {
+ /**
+ * @brief Bit rate.
+ */
+ uint32_t speed;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Initialization value for the CR1 register.
+ */
+ uint16_t cr1;
+ /**
+ * @brief Initialization value for the CR2 register.
+ */
+ uint16_t cr2;
+ /**
+ * @brief Initialization value for the CR3 register.
+ */
+ uint16_t cr3;
+} SerialConfig;
+
+/**
+ * @brief @p SerialDriver specific data.
+ */
+#define _serial_driver_data \
+ _base_asynchronous_channel_data \
+ /* Driver state.*/ \
+ sdstate_t state; \
+ /* Input queue.*/ \
+ input_queue_t iqueue; \
+ /* Output queue.*/ \
+ output_queue_t oqueue; \
+ /* Input circular buffer.*/ \
+ uint8_t ib[SERIAL_BUFFERS_SIZE]; \
+ /* Output circular buffer.*/ \
+ uint8_t ob[SERIAL_BUFFERS_SIZE]; \
+ /* End of the mandatory fields.*/ \
+ /* Pointer to the USART registers block.*/ \
+ USART_TypeDef *usart; \
+ /* Mask to be applied on received frames.*/ \
+ uint8_t rxmask;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*
+ * Extra USARTs definitions here (missing from the ST header file).
+ */
+#define USART_CR2_STOP1_BITS (0 << 12) /**< @brief CR2 1 stop bit value.*/
+#define USART_CR2_STOP0P5_BITS (1 << 12) /**< @brief CR2 0.5 stop bit value.*/
+#define USART_CR2_STOP2_BITS (2 << 12) /**< @brief CR2 2 stop bit value.*/
+#define USART_CR2_STOP1P5_BITS (3 << 12) /**< @brief CR2 1.5 stop bit value.*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_SERIAL_USE_USART1 && !defined(__DOXYGEN__)
+extern SerialDriver SD1;
+#endif
+#if STM32_SERIAL_USE_USART2 && !defined(__DOXYGEN__)
+extern SerialDriver SD2;
+#endif
+#if STM32_SERIAL_USE_USART3 && !defined(__DOXYGEN__)
+extern SerialDriver SD3;
+#endif
+#if STM32_SERIAL_USE_UART4 && !defined(__DOXYGEN__)
+extern SerialDriver SD4;
+#endif
+#if STM32_SERIAL_USE_UART5 && !defined(__DOXYGEN__)
+extern SerialDriver SD5;
+#endif
+#if STM32_SERIAL_USE_USART6 && !defined(__DOXYGEN__)
+extern SerialDriver SD6;
+#endif
+#if STM32_SERIAL_USE_UART7 && !defined(__DOXYGEN__)
+extern SerialDriver SD7;
+#endif
+#if STM32_SERIAL_USE_UART8 && !defined(__DOXYGEN__)
+extern SerialDriver SD8;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void sd_lld_init(void);
+ void sd_lld_start(SerialDriver *sdp, const SerialConfig *config);
+ void sd_lld_stop(SerialDriver *sdp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SERIAL */
+
+#endif /* HAL_SERIAL_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.c
new file mode 100644
index 0000000..d7da046
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.c
@@ -0,0 +1,1008 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv1/hal_uart_lld.c
+ * @brief STM32 low level UART driver code.
+ *
+ * @addtogroup UART
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_UART || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define USART1_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_USART1_RX_DMA_STREAM, \
+ STM32_USART1_RX_DMA_CHN)
+
+#define USART1_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_USART1_TX_DMA_STREAM, \
+ STM32_USART1_TX_DMA_CHN)
+
+#define USART2_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_USART2_RX_DMA_STREAM, \
+ STM32_USART2_RX_DMA_CHN)
+
+#define USART2_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_USART2_TX_DMA_STREAM, \
+ STM32_USART2_TX_DMA_CHN)
+
+#define USART3_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_USART3_RX_DMA_STREAM, \
+ STM32_USART3_RX_DMA_CHN)
+
+#define USART3_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_USART3_TX_DMA_STREAM, \
+ STM32_USART3_TX_DMA_CHN)
+
+#define UART4_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_UART4_RX_DMA_STREAM, \
+ STM32_UART4_RX_DMA_CHN)
+
+#define UART4_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_UART4_TX_DMA_STREAM, \
+ STM32_UART4_TX_DMA_CHN)
+
+#define UART5_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_UART5_RX_DMA_STREAM, \
+ STM32_UART5_RX_DMA_CHN)
+
+#define UART5_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_UART5_TX_DMA_STREAM, \
+ STM32_UART5_TX_DMA_CHN)
+
+#define USART6_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_USART6_RX_DMA_STREAM, \
+ STM32_USART6_RX_DMA_CHN)
+
+#define USART6_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_USART6_TX_DMA_STREAM, \
+ STM32_USART6_TX_DMA_CHN)
+
+#define UART7_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_UART7_RX_DMA_STREAM, \
+ STM32_UART7_RX_DMA_CHN)
+
+#define UART7_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_UART7_TX_DMA_STREAM, \
+ STM32_UART7_TX_DMA_CHN)
+
+#define UART8_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_UART8_RX_DMA_STREAM, \
+ STM32_UART8_RX_DMA_CHN)
+
+#define UART8_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_UART8_TX_DMA_STREAM, \
+ STM32_UART8_TX_DMA_CHN)
+
+#define STM32_UART45_CR2_CHECK_MASK \
+ (USART_CR2_STOP_0 | USART_CR2_CLKEN | USART_CR2_CPOL | USART_CR2_CPHA | \
+ USART_CR2_LBCL)
+
+#define STM32_UART45_CR3_CHECK_MASK \
+ (USART_CR3_CTSIE | USART_CR3_CTSE | USART_CR3_RTSE | USART_CR3_SCEN | \
+ USART_CR3_NACK)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief USART1 UART driver identifier.*/
+#if STM32_UART_USE_USART1 || defined(__DOXYGEN__)
+UARTDriver UARTD1;
+#endif
+
+/** @brief USART2 UART driver identifier.*/
+#if STM32_UART_USE_USART2 || defined(__DOXYGEN__)
+UARTDriver UARTD2;
+#endif
+
+/** @brief USART3 UART driver identifier.*/
+#if STM32_UART_USE_USART3 || defined(__DOXYGEN__)
+UARTDriver UARTD3;
+#endif
+
+/** @brief UART4 UART driver identifier.*/
+#if STM32_UART_USE_UART4 || defined(__DOXYGEN__)
+UARTDriver UARTD4;
+#endif
+
+/** @brief UART5 UART driver identifier.*/
+#if STM32_UART_USE_UART5 || defined(__DOXYGEN__)
+UARTDriver UARTD5;
+#endif
+
+/** @brief USART6 UART driver identifier.*/
+#if STM32_UART_USE_USART6 || defined(__DOXYGEN__)
+UARTDriver UARTD6;
+#endif
+
+/** @brief UART7 UART driver identifier.*/
+#if STM32_UART_USE_UART7 || defined(__DOXYGEN__)
+UARTDriver UARTD7;
+#endif
+
+/** @brief UART8 UART driver identifier.*/
+#if STM32_UART_USE_UART8 || defined(__DOXYGEN__)
+UARTDriver UARTD8;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Status bits translation.
+ *
+ * @param[in] sr USART SR register value
+ *
+ * @return The error flags.
+ */
+static uartflags_t translate_errors(uint16_t sr) {
+ uartflags_t sts = 0;
+
+ if (sr & USART_SR_ORE)
+ sts |= UART_OVERRUN_ERROR;
+ if (sr & USART_SR_PE)
+ sts |= UART_PARITY_ERROR;
+ if (sr & USART_SR_FE)
+ sts |= UART_FRAMING_ERROR;
+ if (sr & USART_SR_NE)
+ sts |= UART_NOISE_ERROR;
+ if (sr & USART_SR_LBD)
+ sts |= UART_BREAK_DETECTED;
+ return sts;
+}
+
+/**
+ * @brief Puts the receiver in the UART_RX_IDLE state.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+static void uart_enter_rx_idle_loop(UARTDriver *uartp) {
+ uint32_t mode;
+
+ /* RX DMA channel preparation, if the char callback is defined then the
+ TCIE interrupt is enabled too.*/
+ if (uartp->config->rxchar_cb == NULL)
+ mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC;
+ else
+ mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC | STM32_DMA_CR_TCIE;
+ dmaStreamSetMemory0(uartp->dmarx, &uartp->rxbuf);
+ dmaStreamSetTransactionSize(uartp->dmarx, 1);
+ dmaStreamSetMode(uartp->dmarx, uartp->dmarxmode | mode);
+ dmaStreamEnable(uartp->dmarx);
+}
+
+/**
+ * @brief USART de-initialization.
+ * @details This function must be invoked with interrupts disabled.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+static void usart_stop(UARTDriver *uartp) {
+
+ /* Stops RX and TX DMA channels.*/
+ dmaStreamDisable(uartp->dmarx);
+ dmaStreamDisable(uartp->dmatx);
+
+ /* Stops USART operations.*/
+ uartp->usart->CR1 = 0;
+ uartp->usart->CR2 = 0;
+ uartp->usart->CR3 = 0;
+}
+
+/**
+ * @brief USART initialization.
+ * @details This function must be invoked with interrupts disabled.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+static void usart_start(UARTDriver *uartp) {
+ uint32_t fck;
+ uint16_t cr1;
+ USART_TypeDef *u = uartp->usart;
+
+ /* Defensive programming, starting from a clean state.*/
+ usart_stop(uartp);
+
+ /* Baud rate setting.*/
+#if STM32_HAS_USART6
+ if ((uartp->usart == USART1) || (uartp->usart == USART6))
+#else
+ if (uartp->usart == USART1)
+#endif
+ fck = STM32_PCLK2 / uartp->config->speed;
+ else
+ fck = STM32_PCLK1 / uartp->config->speed;
+
+ /* Correcting USARTDIV when oversampling by 8 instead of 16.
+ Fraction is still 4 bits wide, but only lower 3 bits used.
+ Mantissa is doubled, but Fraction is left the same.*/
+#if defined(USART_CR1_OVER8)
+ if (uartp->config->cr1 & USART_CR1_OVER8)
+ fck = ((fck & ~7) * 2) | (fck & 7);
+#endif
+ u->BRR = fck;
+
+ /* Resetting eventual pending status flags.*/
+ (void)u->SR; /* SR reset step 1.*/
+ (void)u->DR; /* SR reset step 2.*/
+ u->SR = 0;
+
+ /* Note that some bits are enforced because required for correct driver
+ operations.*/
+ u->CR2 = uartp->config->cr2 | USART_CR2_LBDIE;
+ u->CR3 = uartp->config->cr3 | USART_CR3_DMAT | USART_CR3_DMAR |
+ USART_CR3_EIE;
+
+ /* Mustn't ever set TCIE here - if done, it causes an immediate
+ interrupt.*/
+ cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE;
+ u->CR1 = uartp->config->cr1 | cr1;
+
+ /* Starting the receiver idle loop.*/
+ uart_enter_rx_idle_loop(uartp);
+}
+
+/**
+ * @brief RX DMA common service routine.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void uart_lld_serve_rx_end_irq(UARTDriver *uartp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(STM32_UART_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_UART_DMA_ERROR_HOOK(uartp);
+ }
+#else
+ (void)flags;
+#endif
+
+ if (uartp->rxstate == UART_RX_IDLE) {
+ /* Receiver in idle state, a callback is generated, if enabled, for each
+ received character and then the driver stays in the same state.*/
+ _uart_rx_idle_code(uartp);
+ }
+ else {
+ /* Receiver in active state, a callback is generated, if enabled, after
+ a completed transfer.*/
+ dmaStreamDisable(uartp->dmarx);
+ _uart_rx_complete_isr_code(uartp);
+ }
+}
+
+/**
+ * @brief TX DMA common service routine.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(STM32_UART_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_UART_DMA_ERROR_HOOK(uartp);
+ }
+#else
+ (void)flags;
+#endif
+
+ dmaStreamDisable(uartp->dmatx);
+
+ /* A callback is generated, if enabled, after a completed transfer.*/
+ _uart_tx1_isr_code(uartp);
+}
+
+/**
+ * @brief USART common service routine.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+static void serve_usart_irq(UARTDriver *uartp) {
+ uint16_t sr;
+ USART_TypeDef *u = uartp->usart;
+ uint32_t cr1 = u->CR1;
+
+ sr = u->SR; /* SR reset step 1.*/
+ (void)u->DR; /* SR reset step 2.*/
+
+ if (sr & (USART_SR_LBD | USART_SR_ORE | USART_SR_NE |
+ USART_SR_FE | USART_SR_PE)) {
+ u->SR = ~USART_SR_LBD;
+ _uart_rx_error_isr_code(uartp, translate_errors(sr));
+ }
+
+ if ((sr & USART_SR_TC) && (cr1 & USART_CR1_TCIE)) {
+ /* TC interrupt cleared and disabled.*/
+ u->SR = ~USART_SR_TC;
+ u->CR1 = cr1 & ~USART_CR1_TCIE;
+
+ /* End of transmission, a callback is generated.*/
+ _uart_tx2_isr_code(uartp);
+ }
+
+ /* Timeout interrupt sources are only checked if enabled in CR1.*/
+ if ((cr1 & USART_CR1_IDLEIE) && (sr & USART_SR_IDLE)) {
+ _uart_timeout_isr_code(uartp);
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_UART_USE_USART1 || defined(__DOXYGEN__)
+#if !defined(STM32_USART1_HANDLER)
+#error "STM32_USART1_HANDLER not defined"
+#endif
+/**
+ * @brief USART1 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ serve_usart_irq(&UARTD1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* STM32_UART_USE_USART1 */
+
+#if STM32_UART_USE_USART2 || defined(__DOXYGEN__)
+#if !defined(STM32_USART2_HANDLER)
+#error "STM32_USART2_HANDLER not defined"
+#endif
+/**
+ * @brief USART2 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ serve_usart_irq(&UARTD2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* STM32_UART_USE_USART2 */
+
+#if STM32_UART_USE_USART3 || defined(__DOXYGEN__)
+#if !defined(STM32_USART3_HANDLER)
+#error "STM32_USART3_HANDLER not defined"
+#endif
+/**
+ * @brief USART3 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ serve_usart_irq(&UARTD3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* STM32_UART_USE_USART3 */
+
+#if STM32_UART_USE_UART4 || defined(__DOXYGEN__)
+#if !defined(STM32_UART4_HANDLER)
+#error "STM32_UART4_HANDLER not defined"
+#endif
+/**
+ * @brief UART4 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ serve_usart_irq(&UARTD4);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* STM32_UART_USE_UART4 */
+
+#if STM32_UART_USE_UART5 || defined(__DOXYGEN__)
+#if !defined(STM32_UART5_HANDLER)
+#error "STM32_UART5_HANDLER not defined"
+#endif
+/**
+ * @brief UART5 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ serve_usart_irq(&UARTD5);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* STM32_UART_USE_UART5 */
+
+#if STM32_UART_USE_USART6 || defined(__DOXYGEN__)
+#if !defined(STM32_USART6_HANDLER)
+#error "STM32_USART6_HANDLER not defined"
+#endif
+/**
+ * @brief USART6 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ serve_usart_irq(&UARTD6);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* STM32_UART_USE_USART6 */
+
+#if STM32_UART_USE_UART7 || defined(__DOXYGEN__)
+#if !defined(STM32_UART7_HANDLER)
+#error "STM32_UART7_HANDLER not defined"
+#endif
+/**
+ * @brief UART7 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART7_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ serve_usart_irq(&UARTD7);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* STM32_UART_USE_UART7 */
+
+#if STM32_UART_USE_UART8 || defined(__DOXYGEN__)
+#if !defined(STM32_UART8_HANDLER)
+#error "STM32_UART8_HANDLER not defined"
+#endif
+/**
+ * @brief UART8 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART8_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ serve_usart_irq(&UARTD8);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* STM32_UART_USE_UART8 */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level UART driver initialization.
+ *
+ * @notapi
+ */
+void uart_lld_init(void) {
+
+#if STM32_UART_USE_USART1
+ uartObjectInit(&UARTD1);
+ UARTD1.usart = USART1;
+ UARTD1.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD1.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD1.dmarx = NULL;
+ UARTD1.dmatx = NULL;
+#endif
+
+#if STM32_UART_USE_USART2
+ uartObjectInit(&UARTD2);
+ UARTD2.usart = USART2;
+ UARTD2.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD2.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD2.dmarx = NULL;
+ UARTD2.dmatx = NULL;
+#endif
+
+#if STM32_UART_USE_USART3
+ uartObjectInit(&UARTD3);
+ UARTD3.usart = USART3;
+ UARTD3.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD3.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD3.dmarx = NULL;
+ UARTD3.dmatx = NULL;
+#endif
+
+#if STM32_UART_USE_UART4
+ uartObjectInit(&UARTD4);
+ UARTD4.usart = UART4;
+ UARTD4.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD4.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD4.dmarx = NULL;
+ UARTD4.dmatx = NULL;
+#endif
+
+#if STM32_UART_USE_UART5
+ uartObjectInit(&UARTD5);
+ UARTD5.usart = UART5;
+ UARTD5.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD5.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD5.dmarx = NULL;
+ UARTD5.dmatx = NULL;
+#endif
+
+#if STM32_UART_USE_USART6
+ uartObjectInit(&UARTD6);
+ UARTD6.usart = USART6;
+ UARTD6.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD6.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD6.dmarx = NULL;
+ UARTD6.dmatx = NULL;
+#endif
+
+#if STM32_UART_USE_UART7
+ uartObjectInit(&UARTD7);
+ UARTD7.usart = UART7;
+ UARTD7.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD7.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD7.dmarx = NULL;
+ UARTD7.dmatx = NULL;
+#endif
+
+#if STM32_UART_USE_UART8
+ uartObjectInit(&UARTD8);
+ UARTD8.usart = UART8;
+ UARTD8.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD8.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD8.dmarx = NULL;
+ UARTD8.dmatx = NULL;
+#endif
+}
+
+/**
+ * @brief Configures and activates the UART peripheral.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+void uart_lld_start(UARTDriver *uartp) {
+
+ if (uartp->state == UART_STOP) {
+#if STM32_UART_USE_USART1
+ if (&UARTD1 == uartp) {
+ uartp->dmarx = dmaStreamAllocI(STM32_UART_USART1_RX_DMA_STREAM,
+ STM32_UART_USART1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(STM32_UART_USART1_TX_DMA_STREAM,
+ STM32_UART_USART1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableUSART1(true);
+ nvicEnableVector(STM32_USART1_NUMBER, STM32_UART_USART1_IRQ_PRIORITY);
+ uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART1_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY);
+ uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART1_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY);
+ }
+#endif
+
+#if STM32_UART_USE_USART2
+ if (&UARTD2 == uartp) {
+ uartp->dmarx = dmaStreamAllocI(STM32_UART_USART2_RX_DMA_STREAM,
+ STM32_UART_USART2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(STM32_UART_USART2_TX_DMA_STREAM,
+ STM32_UART_USART2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableUSART2(true);
+ nvicEnableVector(STM32_USART2_NUMBER, STM32_UART_USART2_IRQ_PRIORITY);
+ uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART2_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY);
+ uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART2_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY);
+ }
+#endif
+
+#if STM32_UART_USE_USART3
+ if (&UARTD3 == uartp) {
+ uartp->dmarx = dmaStreamAllocI(STM32_UART_USART3_RX_DMA_STREAM,
+ STM32_UART_USART3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(STM32_UART_USART3_TX_DMA_STREAM,
+ STM32_UART_USART3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableUSART3(true);
+ nvicEnableVector(STM32_USART3_NUMBER, STM32_UART_USART3_IRQ_PRIORITY);
+ uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART3_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY);
+ uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART3_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY);
+ }
+#endif
+
+#if STM32_UART_USE_UART4
+ if (&UARTD4 == uartp) {
+
+ osalDbgAssert((uartp->config->cr2 & STM32_UART45_CR2_CHECK_MASK) == 0,
+ "specified invalid bits in UART4 CR2 register settings");
+ osalDbgAssert((uartp->config->cr3 & STM32_UART45_CR3_CHECK_MASK) == 0,
+ "specified invalid bits in UART4 CR3 register settings");
+
+ uartp->dmarx = dmaStreamAllocI(STM32_UART_UART4_RX_DMA_STREAM,
+ STM32_UART_UART4_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(STM32_UART_UART4_TX_DMA_STREAM,
+ STM32_UART_UART4_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableUART4(true);
+ nvicEnableVector(STM32_UART4_NUMBER, STM32_UART_UART4_IRQ_PRIORITY);
+ uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART4_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_UART4_DMA_PRIORITY);
+ uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART4_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_UART4_DMA_PRIORITY);
+ }
+#endif
+
+#if STM32_UART_USE_UART5
+ if (&UARTD5 == uartp) {
+
+ osalDbgAssert((uartp->config->cr2 & STM32_UART45_CR2_CHECK_MASK) == 0,
+ "specified invalid bits in UART5 CR2 register settings");
+ osalDbgAssert((uartp->config->cr3 & STM32_UART45_CR3_CHECK_MASK) == 0,
+ "specified invalid bits in UART5 CR3 register settings");
+
+ uartp->dmarx = dmaStreamAllocI(STM32_UART_UART5_RX_DMA_STREAM,
+ STM32_UART_UART5_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(STM32_UART_UART5_TX_DMA_STREAM,
+ STM32_UART_UART5_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableUART5(true);
+ nvicEnableVector(STM32_UART5_NUMBER, STM32_UART_UART5_IRQ_PRIORITY);
+ uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART5_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_UART5_DMA_PRIORITY);
+ uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART5_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_UART5_DMA_PRIORITY);
+ }
+#endif
+
+#if STM32_UART_USE_USART6
+ if (&UARTD6 == uartp) {
+ uartp->dmarx = dmaStreamAllocI(STM32_UART_USART6_RX_DMA_STREAM,
+ STM32_UART_USART6_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(STM32_UART_USART6_TX_DMA_STREAM,
+ STM32_UART_USART6_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableUSART6(true);
+ nvicEnableVector(STM32_USART6_NUMBER, STM32_UART_USART6_IRQ_PRIORITY);
+ uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART6_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART6_DMA_PRIORITY);
+ uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART6_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART6_DMA_PRIORITY);
+ }
+#endif
+
+#if STM32_UART_USE_UART7
+ if (&UARTD7 == uartp) {
+
+ osalDbgAssert((uartp->config->cr2 & STM32_UART45_CR2_CHECK_MASK) == 0,
+ "specified invalid bits in UART7 CR2 register settings");
+ osalDbgAssert((uartp->config->cr3 & STM32_UART45_CR3_CHECK_MASK) == 0,
+ "specified invalid bits in UART7 CR3 register settings");
+
+ uartp->dmarx = dmaStreamAllocI(STM32_UART_UART7_RX_DMA_STREAM,
+ STM32_UART_UART7_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(STM32_UART_UART7_TX_DMA_STREAM,
+ STM32_UART_UART7_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableUART7(true);
+ nvicEnableVector(STM32_UART7_NUMBER, STM32_UART_UART7_IRQ_PRIORITY);
+ uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART7_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_UART7_DMA_PRIORITY);
+ uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART7_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_UART7_DMA_PRIORITY);
+ }
+#endif
+
+#if STM32_UART_USE_UART8
+ if (&UARTD8 == uartp) {
+
+ osalDbgAssert((uartp->config->cr2 & STM32_UART45_CR2_CHECK_MASK) == 0,
+ "specified invalid bits in UART8 CR2 register settings");
+ osalDbgAssert((uartp->config->cr3 & STM32_UART45_CR3_CHECK_MASK) == 0,
+ "specified invalid bits in UART8 CR3 register settings");
+
+ uartp->dmarx = dmaStreamAllocI(STM32_UART_UART8_RX_DMA_STREAM,
+ STM32_UART_UART8_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(STM32_UART_UART8_TX_DMA_STREAM,
+ STM32_UART_UART8_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableUART8(true);
+ nvicEnableVector(STM32_UART8_NUMBER, STM32_UART_UART8_IRQ_PRIORITY);
+ uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART8_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_UART8_DMA_PRIORITY);
+ uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART8_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_UART8_DMA_PRIORITY);
+ }
+#endif
+
+ /* Static DMA setup, the transfer size depends on the USART settings,
+ it is 16 bits if M=1 and PCE=0 else it is 8 bits.*/
+ if ((uartp->config->cr1 & (USART_CR1_M | USART_CR1_PCE)) == USART_CR1_M) {
+ uartp->dmarxmode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
+ uartp->dmatxmode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
+ }
+ dmaStreamSetPeripheral(uartp->dmarx, &uartp->usart->DR);
+ dmaStreamSetPeripheral(uartp->dmatx, &uartp->usart->DR);
+ uartp->rxbuf = 0;
+ }
+
+ uartp->rxstate = UART_RX_IDLE;
+ uartp->txstate = UART_TX_IDLE;
+ usart_start(uartp);
+}
+
+/**
+ * @brief Deactivates the UART peripheral.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+void uart_lld_stop(UARTDriver *uartp) {
+
+ if (uartp->state == UART_READY) {
+ usart_stop(uartp);
+ dmaStreamFreeI(uartp->dmarx);
+ dmaStreamFreeI(uartp->dmatx);
+ uartp->dmarx = NULL;
+ uartp->dmatx = NULL;
+
+#if STM32_UART_USE_USART1
+ if (&UARTD1 == uartp) {
+ nvicDisableVector(STM32_USART1_NUMBER);
+ rccDisableUSART1();
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_USART2
+ if (&UARTD2 == uartp) {
+ nvicDisableVector(STM32_USART2_NUMBER);
+ rccDisableUSART2();
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_USART3
+ if (&UARTD3 == uartp) {
+ nvicDisableVector(STM32_USART3_NUMBER);
+ rccDisableUSART3();
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_UART4
+ if (&UARTD4 == uartp) {
+ nvicDisableVector(STM32_UART4_NUMBER);
+ rccDisableUART4();
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_UART5
+ if (&UARTD5 == uartp) {
+ nvicDisableVector(STM32_UART5_NUMBER);
+ rccDisableUART5();
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_USART6
+ if (&UARTD6 == uartp) {
+ nvicDisableVector(STM32_USART6_NUMBER);
+ rccDisableUSART6();
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_UART7
+ if (&UARTD7 == uartp) {
+ nvicDisableVector(STM32_UART7_NUMBER);
+ rccDisableUART7();
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_UART8
+ if (&UARTD8 == uartp) {
+ nvicDisableVector(STM32_UART8_NUMBER);
+ rccDisableUART8();
+ return;
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Starts a transmission on the UART peripheral.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] n number of data frames to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @notapi
+ */
+void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) {
+
+ /* TX DMA channel preparation.*/
+ dmaStreamSetMemory0(uartp->dmatx, txbuf);
+ dmaStreamSetTransactionSize(uartp->dmatx, n);
+ dmaStreamSetMode(uartp->dmatx, uartp->dmatxmode | STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE);
+
+ /* Only enable TC interrupt if there's a callback attached to it or
+ if called from uartSendFullTimeout(). Also we need to clear TC flag
+ which could be set before.*/
+#if UART_USE_WAIT == TRUE
+ if ((uartp->config->txend2_cb != NULL) || (uartp->early == false)) {
+#else
+ if (uartp->config->txend2_cb != NULL) {
+#endif
+ uartp->usart->SR = ~USART_SR_TC;
+ uartp->usart->CR1 |= USART_CR1_TCIE;
+ }
+
+ /* Starting transfer.*/
+ dmaStreamEnable(uartp->dmatx);
+}
+
+/**
+ * @brief Stops any ongoing transmission.
+ * @note Stopping a transmission also suppresses the transmission callbacks.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @return The number of data frames not transmitted by the
+ * stopped transmit operation.
+ *
+ * @notapi
+ */
+size_t uart_lld_stop_send(UARTDriver *uartp) {
+
+ dmaStreamDisable(uartp->dmatx);
+
+ return dmaStreamGetTransactionSize(uartp->dmatx);
+}
+
+/**
+ * @brief Starts a receive operation on the UART peripheral.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] n number of data frames to send
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) {
+
+ /* Stopping previous activity (idle state).*/
+ dmaStreamDisable(uartp->dmarx);
+
+ /* RX DMA channel preparation.*/
+ dmaStreamSetMemory0(uartp->dmarx, rxbuf);
+ dmaStreamSetTransactionSize(uartp->dmarx, n);
+ dmaStreamSetMode(uartp->dmarx, uartp->dmarxmode | STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE);
+
+ /* Starting transfer.*/
+ dmaStreamEnable(uartp->dmarx);
+}
+
+/**
+ * @brief Stops any ongoing receive operation.
+ * @note Stopping a receive operation also suppresses the receive callbacks.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @return The number of data frames not received by the
+ * stopped receive operation.
+ *
+ * @notapi
+ */
+size_t uart_lld_stop_receive(UARTDriver *uartp) {
+ size_t n;
+
+ dmaStreamDisable(uartp->dmarx);
+ n = dmaStreamGetTransactionSize(uartp->dmarx);
+ uart_enter_rx_idle_loop(uartp);
+
+ return n;
+}
+
+#endif /* HAL_USE_UART */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.h
new file mode 100644
index 0000000..ae0f4d3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv1/hal_uart_lld.h
@@ -0,0 +1,758 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv1/hal_uart_lld.h
+ * @brief STM32 low level UART driver header.
+ *
+ * @addtogroup UART
+ * @{
+ */
+
+#ifndef HAL_UART_LLD_H
+#define HAL_UART_LLD_H
+
+#if HAL_USE_UART || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief UART driver on USART1 enable switch.
+ * @details If set to @p TRUE the support for USART1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_UART_USE_USART1) || defined(__DOXYGEN__)
+#define STM32_UART_USE_USART1 FALSE
+#endif
+
+/**
+ * @brief UART driver on USART2 enable switch.
+ * @details If set to @p TRUE the support for USART2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_UART_USE_USART2) || defined(__DOXYGEN__)
+#define STM32_UART_USE_USART2 FALSE
+#endif
+
+/**
+ * @brief UART driver on USART3 enable switch.
+ * @details If set to @p TRUE the support for USART3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_UART_USE_USART3) || defined(__DOXYGEN__)
+#define STM32_UART_USE_USART3 FALSE
+#endif
+
+/**
+ * @brief UART driver on UART4 enable switch.
+ * @details If set to @p TRUE the support for UART4 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_UART_USE_UART4) || defined(__DOXYGEN__)
+#define STM32_UART_USE_UART4 FALSE
+#endif
+
+/**
+ * @brief UART driver on UART5 enable switch.
+ * @details If set to @p TRUE the support for UART5 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_UART_USE_UART5) || defined(__DOXYGEN__)
+#define STM32_UART_USE_UART5 FALSE
+#endif
+
+/**
+ * @brief UART driver on USART6 enable switch.
+ * @details If set to @p TRUE the support for USART6 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_UART_USE_USART6) || defined(__DOXYGEN__)
+#define STM32_UART_USE_USART6 FALSE
+#endif
+
+/**
+ * @brief UART driver on UART7 enable switch.
+ * @details If set to @p TRUE the support for UART7 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_UART_USE_UART7) || defined(__DOXYGEN__)
+#define STM32_UART_USE_UART7 FALSE
+#endif
+
+/**
+ * @brief UART driver on UART8 enable switch.
+ * @details If set to @p TRUE the support for UART8 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_UART_USE_UART8) || defined(__DOXYGEN__)
+#define STM32_UART_USE_UART8 FALSE
+#endif
+
+/**
+ * @brief USART1 interrupt priority level setting.
+ */
+#if !defined(STM32_UART_USART1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_USART1_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief USART2 interrupt priority level setting.
+ */
+#if !defined(STM32_UART_USART2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_USART2_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief USART3 interrupt priority level setting.
+ */
+#if !defined(STM32_UART_USART3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_USART3_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief UART4 interrupt priority level setting.
+ */
+#if !defined(STM32_UART_UART4_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_UART4_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief UART5 interrupt priority level setting.
+ */
+#if !defined(STM32_UART_UART5_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_UART5_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief USART6 interrupt priority level setting.
+ */
+#if !defined(STM32_UART_USART6_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_USART6_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief UART7 interrupt priority level setting.
+ */
+#if !defined(STM32_UART_UART7_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_UART7_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief UART8 interrupt priority level setting.
+ */
+#if !defined(STM32_UART_UART8_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_UART8_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief USART1 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(STM32_UART_USART1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_USART1_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief USART2 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(STM32_UART_USART2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_USART2_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief USART3 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(STM32_UART_USART3_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_USART3_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief UART4 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(STM32_UART_UART4_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_UART4_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief UART5 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(STM32_UART_UART5_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_UART5_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief USART6 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(STM32_UART_USART6_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_USART6_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief UART7 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(STM32_UART_UART7_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_UART7_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief UART8 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(STM32_UART_UART8_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_UART8_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief USART DMA error hook.
+ * @note The default action for DMA errors is a system halt because DMA
+ * error can only happen because programming errors.
+ */
+#if !defined(STM32_UART_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if STM32_UART_USE_USART1 && !STM32_HAS_USART1
+#error "USART1 not present in the selected device"
+#endif
+
+#if STM32_UART_USE_USART2 && !STM32_HAS_USART2
+#error "USART2 not present in the selected device"
+#endif
+
+#if STM32_UART_USE_USART3 && !STM32_HAS_USART3
+#error "USART3 not present in the selected device"
+#endif
+
+#if STM32_UART_USE_UART4
+#if !STM32_HAS_UART4
+#error "UART4 not present in the selected device"
+#endif
+
+#if !defined(STM32F2XX) && !defined(STM32F4XX) && !defined(STM32L151xE) && \
+ !defined(STM32L152xE) && !defined(STM32L162xE)
+#error "UART4 DMA access not supported in this platform"
+#endif
+#endif /* STM32_UART_USE_UART4 */
+
+#if STM32_UART_USE_UART5
+#if !STM32_HAS_UART5
+#error "UART5 not present in the selected device"
+#endif
+
+#if !defined(STM32F2XX) && !defined(STM32F4XX) && !defined(STM32L151xE) && \
+ !defined(STM32L152xE) && !defined(STM32L162xE)
+#error "UART5 DMA access not supported in this platform"
+#endif
+#endif /* STM32_UART_USE_UART5 */
+
+#if STM32_UART_USE_USART6 && !STM32_HAS_USART6
+#error "USART6 not present in the selected device"
+#endif
+
+#if STM32_UART_USE_UART7 && !STM32_HAS_UART7
+#error "UART7 not present in the selected device"
+#endif
+
+#if STM32_UART_USE_UART8 && !STM32_HAS_UART8
+#error "UART8 not present in the selected device"
+#endif
+
+#if !STM32_UART_USE_USART1 && !STM32_UART_USE_USART2 && \
+ !STM32_UART_USE_USART3 && !STM32_UART_USE_UART4 && \
+ !STM32_UART_USE_UART5 && !STM32_UART_USE_USART6 && \
+ !STM32_UART_USE_UART7 && !STM32_UART_USE_UART8
+#error "UART driver activated but no USART/UART peripheral assigned"
+#endif
+
+#if STM32_UART_USE_USART1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to USART1"
+#endif
+
+#if STM32_UART_USE_USART2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to USART2"
+#endif
+
+#if STM32_UART_USE_USART3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to USART3"
+#endif
+
+#if STM32_UART_USE_UART4 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART4_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to UART4"
+#endif
+
+#if STM32_UART_USE_UART5 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART5_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to UART5"
+#endif
+
+#if STM32_UART_USE_USART6 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART6_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to USART6"
+#endif
+
+#if STM32_UART_USE_UART7 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART7_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to UART7"
+#endif
+
+#if STM32_UART_USE_UART8 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART8_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to UART8"
+#endif
+
+#if STM32_UART_USE_USART1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to USART1"
+#endif
+
+#if STM32_UART_USE_USART2 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to USART2"
+#endif
+
+#if STM32_UART_USE_USART3 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART3_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to USART3"
+#endif
+
+#if STM32_UART_USE_UART4 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART4_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to UART4"
+#endif
+
+#if STM32_UART_USE_UART5 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART5_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to UART5"
+#endif
+
+#if STM32_UART_USE_USART6 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART6_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to USART6"
+#endif
+
+#if STM32_UART_USE_UART7 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART7_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to UART7"
+#endif
+
+#if STM32_UART_USE_UART8 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART8_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to UART8"
+#endif
+
+/* The following checks are only required when there is a DMA able to
+ reassign streams to different channels.*/
+#if STM32_ADVANCED_DMA
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if STM32_UART_USE_USART1 && (!defined(STM32_UART_USART1_RX_DMA_STREAM) || \
+ !defined(STM32_UART_USART1_TX_DMA_STREAM))
+#error "USART1 DMA streams not defined"
+#endif
+
+#if STM32_UART_USE_USART2 && (!defined(STM32_UART_USART2_RX_DMA_STREAM) || \
+ !defined(STM32_UART_USART2_TX_DMA_STREAM))
+#error "USART2 DMA streams not defined"
+#endif
+
+#if STM32_UART_USE_USART3 && (!defined(STM32_UART_USART3_RX_DMA_STREAM) || \
+ !defined(STM32_UART_USART3_TX_DMA_STREAM))
+#error "USART3 DMA streams not defined"
+#endif
+
+#if STM32_UART_USE_UART4 && (!defined(STM32_UART_UART4_RX_DMA_STREAM) || \
+ !defined(STM32_UART_UART4_TX_DMA_STREAM))
+#error "UART4 DMA streams not defined"
+#endif
+
+#if STM32_UART_USE_UART5 && (!defined(STM32_UART_UART5_RX_DMA_STREAM) || \
+ !defined(STM32_UART_UART5_TX_DMA_STREAM))
+#error "UART5 DMA streams not defined"
+#endif
+
+#if STM32_UART_USE_USART6 && (!defined(STM32_UART_USART6_RX_DMA_STREAM) || \
+ !defined(STM32_UART_USART6_TX_DMA_STREAM))
+#error "USART6 DMA streams not defined"
+#endif
+
+#if STM32_UART_USE_UART7 && (!defined(STM32_UART_UART7_RX_DMA_STREAM) || \
+ !defined(STM32_UART_UART7_TX_DMA_STREAM))
+#error "UART7 DMA streams not defined"
+#endif
+
+#if STM32_UART_USE_UART8 && (!defined(STM32_UART_UART8_RX_DMA_STREAM) || \
+ !defined(STM32_UART_UART8_TX_DMA_STREAM))
+#error "UART8 DMA streams not defined"
+#endif
+
+/* Check on the validity of the assigned DMA channels.*/
+#if STM32_UART_USE_USART1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_RX_DMA_STREAM, \
+ STM32_USART1_RX_DMA_MSK)
+#error "invalid DMA stream associated to USART1 RX"
+#endif
+
+#if STM32_UART_USE_USART1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_TX_DMA_STREAM, \
+ STM32_USART1_TX_DMA_MSK)
+#error "invalid DMA stream associated to USART1 TX"
+#endif
+
+#if STM32_UART_USE_USART2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_RX_DMA_STREAM, \
+ STM32_USART2_RX_DMA_MSK)
+#error "invalid DMA stream associated to USART2 RX"
+#endif
+
+#if STM32_UART_USE_USART2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_TX_DMA_STREAM, \
+ STM32_USART2_TX_DMA_MSK)
+#error "invalid DMA stream associated to USART2 TX"
+#endif
+
+#if STM32_UART_USE_USART3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_RX_DMA_STREAM, \
+ STM32_USART3_RX_DMA_MSK)
+#error "invalid DMA stream associated to USART3 RX"
+#endif
+
+#if STM32_UART_USE_USART3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_TX_DMA_STREAM, \
+ STM32_USART3_TX_DMA_MSK)
+#error "invalid DMA stream associated to USART3 TX"
+#endif
+
+#if STM32_UART_USE_UART4 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_UART4_RX_DMA_STREAM, \
+ STM32_UART4_RX_DMA_MSK)
+#error "invalid DMA stream associated to UART4 RX"
+#endif
+
+#if STM32_UART_USE_UART4 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_UART4_TX_DMA_STREAM, \
+ STM32_UART4_TX_DMA_MSK)
+#error "invalid DMA stream associated to UART4 TX"
+#endif
+
+#if STM32_UART_USE_UART5 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_UART5_RX_DMA_STREAM, \
+ STM32_UART5_RX_DMA_MSK)
+#error "invalid DMA stream associated to UART5 RX"
+#endif
+
+#if STM32_UART_USE_UART5 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_UART5_TX_DMA_STREAM, \
+ STM32_UART5_TX_DMA_MSK)
+#error "invalid DMA stream associated to UART5 TX"
+#endif
+
+#if STM32_UART_USE_USART6 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_USART6_RX_DMA_STREAM, \
+ STM32_USART6_RX_DMA_MSK)
+#error "invalid DMA stream associated to USART6 RX"
+#endif
+
+#if STM32_UART_USE_USART6 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_USART6_TX_DMA_STREAM, \
+ STM32_USART6_TX_DMA_MSK)
+#error "invalid DMA stream associated to USART6 TX"
+#endif
+#endif /* STM32_ADVANCED_DMA */
+
+#if STM32_UART_USE_UART7 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_UART7_RX_DMA_STREAM, \
+ STM32_UART7_RX_DMA_MSK)
+#error "invalid DMA stream associated to UART7 RX"
+#endif
+
+#if STM32_UART_USE_UART7 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_UART7_TX_DMA_STREAM, \
+ STM32_UART7_TX_DMA_MSK)
+#error "invalid DMA stream associated to UART7 TX"
+#endif
+
+#if STM32_UART_USE_UART8 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_UART8_RX_DMA_STREAM, \
+ STM32_UART8_RX_DMA_MSK)
+#error "invalid DMA stream associated to UART8 RX"
+#endif
+
+#if STM32_UART_USE_UART8 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_UART8_TX_DMA_STREAM, \
+ STM32_UART8_TX_DMA_MSK)
+#error "invalid DMA stream associated to UART8 TX"
+#endif
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief UART driver condition flags type.
+ */
+typedef uint32_t uartflags_t;
+
+/**
+ * @brief Structure representing an UART driver.
+ */
+typedef struct UARTDriver UARTDriver;
+
+/**
+ * @brief Generic UART notification callback type.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+typedef void (*uartcb_t)(UARTDriver *uartp);
+
+/**
+ * @brief Character received UART notification callback type.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] c received character
+ */
+typedef void (*uartccb_t)(UARTDriver *uartp, uint16_t c);
+
+/**
+ * @brief Receive error UART notification callback type.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] e receive error mask
+ */
+typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e);
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+ /**
+ * @brief End of transmission buffer callback.
+ */
+ uartcb_t txend1_cb;
+ /**
+ * @brief Physical end of transmission callback.
+ */
+ uartcb_t txend2_cb;
+ /**
+ * @brief Receive buffer filled callback.
+ */
+ uartcb_t rxend_cb;
+ /**
+ * @brief Character received while out if the @p UART_RECEIVE state.
+ */
+ uartccb_t rxchar_cb;
+ /**
+ * @brief Receive error callback.
+ */
+ uartecb_t rxerr_cb;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Receiver timeout callback.
+ * @details Handles idle interrupts depending on configured
+ * flags in CR registers and supported hardware features.
+ */
+ uartcb_t timeout_cb;
+ /**
+ * @brief Bit rate.
+ */
+ uint32_t speed;
+ /**
+ * @brief Initialization value for the CR1 register.
+ */
+ uint16_t cr1;
+ /**
+ * @brief Initialization value for the CR2 register.
+ */
+ uint16_t cr2;
+ /**
+ * @brief Initialization value for the CR3 register.
+ */
+ uint16_t cr3;
+} UARTConfig;
+
+/**
+ * @brief Structure representing an UART driver.
+ */
+struct UARTDriver {
+ /**
+ * @brief Driver state.
+ */
+ uartstate_t state;
+ /**
+ * @brief Transmitter state.
+ */
+ uarttxstate_t txstate;
+ /**
+ * @brief Receiver state.
+ */
+ uartrxstate_t rxstate;
+ /**
+ * @brief Current configuration data.
+ */
+ const UARTConfig *config;
+#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Synchronization flag for transmit operations.
+ */
+ bool early;
+ /**
+ * @brief Waiting thread on RX.
+ */
+ thread_reference_t threadrx;
+ /**
+ * @brief Waiting thread on TX.
+ */
+ thread_reference_t threadtx;
+#endif /* UART_USE_WAIT */
+#if (UART_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Mutex protecting the peripheral.
+ */
+ mutex_t mutex;
+#endif /* UART_USE_MUTUAL_EXCLUSION */
+#if defined(UART_DRIVER_EXT_FIELDS)
+ UART_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Pointer to the USART registers block.
+ */
+ USART_TypeDef *usart;
+ /**
+ * @brief Receive DMA mode bit mask.
+ */
+ uint32_t dmarxmode;
+ /**
+ * @brief Send DMA mode bit mask.
+ */
+ uint32_t dmatxmode;
+ /**
+ * @brief Receive DMA channel.
+ */
+ const stm32_dma_stream_t *dmarx;
+ /**
+ * @brief Transmit DMA channel.
+ */
+ const stm32_dma_stream_t *dmatx;
+ /**
+ * @brief Default receive buffer while into @p UART_RX_IDLE state.
+ */
+ volatile uint16_t rxbuf;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_UART_USE_USART1 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD1;
+#endif
+
+#if STM32_UART_USE_USART2 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD2;
+#endif
+
+#if STM32_UART_USE_USART3 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD3;
+#endif
+
+#if STM32_UART_USE_UART4 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD4;
+#endif
+
+#if STM32_UART_USE_UART5 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD5;
+#endif
+
+#if STM32_UART_USE_USART6 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD6;
+#endif
+
+#if STM32_UART_USE_UART7 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD7;
+#endif
+
+#if STM32_UART_USE_UART8 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD8;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void uart_lld_init(void);
+ void uart_lld_start(UARTDriver *uartp);
+ void uart_lld_stop(UARTDriver *uartp);
+ void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf);
+ size_t uart_lld_stop_send(UARTDriver *uartp);
+ void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf);
+ size_t uart_lld_stop_receive(UARTDriver *uartp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_UART */
+
+#endif /* HAL_UART_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/driver.mk
new file mode 100644
index 0000000..2de63f8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/driver.mk
@@ -0,0 +1,13 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_SERIAL TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.c
+endif
+ifneq ($(findstring HAL_USE_UART TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.c
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.c
new file mode 100644
index 0000000..7c89ecf
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.c
@@ -0,0 +1,913 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv2/hal_serial_lld.c
+ * @brief STM32 low level serial driver code.
+ *
+ * @addtogroup SERIAL
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_SERIAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/* For compatibility for those devices without LIN support in the USARTs.*/
+#if !defined(USART_ISR_LBDF)
+#define USART_ISR_LBDF 0
+#endif
+
+#if !defined(USART_CR2_LBDIE)
+#define USART_CR2_LBDIE 0
+#endif
+
+/* Differences in L4+ headers.*/
+#if !defined(USART_CR1_TXEIE)
+#define USART_CR1_TXEIE USART_CR1_TXEIE_TXFNFIE
+#endif
+
+#if !defined(USART_CR1_RXNEIE)
+#define USART_CR1_RXNEIE USART_CR1_RXNEIE_RXFNEIE
+#endif
+
+#if !defined(USART_ISR_TXE)
+#define USART_ISR_TXE USART_ISR_TXE_TXFNF
+#endif
+
+#if !defined(USART_ISR_RXNE)
+#define USART_ISR_RXNE USART_ISR_RXNE_RXFNE
+#endif
+
+/* STM32L0xx/STM32F7xx ST headers difference.*/
+#if !defined(USART_ISR_LBDF)
+#define USART_ISR_LBDF USART_ISR_LBD
+#endif
+
+/* Handling differences in frame size bits.*/
+#if !defined(USART_CR1_M_0)
+#define USART_CR1_M_0 (1 << 12)
+#endif
+
+#if !defined(USART_CR1_M_1)
+#define USART_CR1_M_1 (1 << 28)
+#endif
+
+/* Workarounds for those devices where UARTs are USARTs.*/
+#if defined(USART4)
+#define UART4 USART4
+#endif
+#if defined(USART5)
+#define UART5 USART5
+#endif
+#if defined(USART7)
+#define UART7 USART7
+#endif
+#if defined(USART8)
+#define UART8 USART8
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief USART1 serial driver identifier.*/
+#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__)
+SerialDriver SD1;
+#endif
+
+/** @brief USART2 serial driver identifier.*/
+#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__)
+SerialDriver SD2;
+#endif
+
+/** @brief USART3 serial driver identifier.*/
+#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__)
+SerialDriver SD3;
+#endif
+
+/** @brief UART4 serial driver identifier.*/
+#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__)
+SerialDriver SD4;
+#endif
+
+/** @brief UART5 serial driver identifier.*/
+#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__)
+SerialDriver SD5;
+#endif
+
+/** @brief USART6 serial driver identifier.*/
+#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__)
+SerialDriver SD6;
+#endif
+
+/** @brief UART7 serial driver identifier.*/
+#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__)
+SerialDriver SD7;
+#endif
+
+/** @brief UART8 serial driver identifier.*/
+#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__)
+SerialDriver SD8;
+#endif
+
+/** @brief LPUART1 serial driver identifier.*/
+#if STM32_SERIAL_USE_LPUART1 || defined(__DOXYGEN__)
+SerialDriver LPSD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/** @brief Driver default configuration.*/
+static const SerialConfig default_config =
+{
+ SERIAL_DEFAULT_BITRATE,
+ 0,
+ USART_CR2_STOP1_BITS,
+ 0
+};
+
+#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__)
+/** @brief Input buffer for SD1.*/
+static uint8_t sd_in_buf1[STM32_SERIAL_USART1_IN_BUF_SIZE];
+
+/** @brief Output buffer for SD1.*/
+static uint8_t sd_out_buf1[STM32_SERIAL_USART1_OUT_BUF_SIZE];
+#endif
+
+#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__)
+/** @brief Input buffer for SD2.*/
+static uint8_t sd_in_buf2[STM32_SERIAL_USART2_IN_BUF_SIZE];
+
+/** @brief Output buffer for SD2.*/
+static uint8_t sd_out_buf2[STM32_SERIAL_USART2_OUT_BUF_SIZE];
+#endif
+
+#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__)
+/** @brief Input buffer for SD3.*/
+static uint8_t sd_in_buf3[STM32_SERIAL_USART3_IN_BUF_SIZE];
+
+/** @brief Output buffer for SD3.*/
+static uint8_t sd_out_buf3[STM32_SERIAL_USART3_OUT_BUF_SIZE];
+#endif
+
+#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__)
+/** @brief Input buffer for SD4.*/
+static uint8_t sd_in_buf4[STM32_SERIAL_UART4_IN_BUF_SIZE];
+
+/** @brief Output buffer for SD4.*/
+static uint8_t sd_out_buf4[STM32_SERIAL_UART4_OUT_BUF_SIZE];
+#endif
+
+#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__)
+/** @brief Input buffer for SD5.*/
+static uint8_t sd_in_buf5[STM32_SERIAL_UART5_IN_BUF_SIZE];
+
+/** @brief Output buffer for SD5.*/
+static uint8_t sd_out_buf5[STM32_SERIAL_UART5_OUT_BUF_SIZE];
+#endif
+
+#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__)
+/** @brief Input buffer for SD6.*/
+static uint8_t sd_in_buf6[STM32_SERIAL_USART6_IN_BUF_SIZE];
+
+/** @brief Output buffer for SD6.*/
+static uint8_t sd_out_buf6[STM32_SERIAL_USART6_OUT_BUF_SIZE];
+#endif
+
+#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__)
+/** @brief Input buffer for SD7.*/
+static uint8_t sd_in_buf7[STM32_SERIAL_UART7_IN_BUF_SIZE];
+
+/** @brief Output buffer for SD7.*/
+static uint8_t sd_out_buf7[STM32_SERIAL_UART7_OUT_BUF_SIZE];
+#endif
+
+#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__)
+/** @brief Input buffer for SD8.*/
+static uint8_t sd_in_buf8[STM32_SERIAL_UART8_IN_BUF_SIZE];
+
+/** @brief Output buffer for SD8.*/
+static uint8_t sd_out_buf8[STM32_SERIAL_UART8_OUT_BUF_SIZE];
+#endif
+
+#if STM32_SERIAL_USE_LPUART1 || defined(__DOXYGEN__)
+/** @brief Input buffer for LPSD1.*/
+static uint8_t sd_in_buflp1[STM32_SERIAL_LPUART1_IN_BUF_SIZE];
+
+/** @brief Output buffer for LPSD1.*/
+static uint8_t sd_out_buflp1[STM32_SERIAL_LPUART1_OUT_BUF_SIZE];
+#endif
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief USART initialization.
+ * @details This function must be invoked with interrupts disabled.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ * @param[in] config the architecture-dependent serial driver configuration
+ */
+static void usart_init(SerialDriver *sdp, const SerialConfig *config) {
+ uint32_t brr;
+ USART_TypeDef *u = sdp->usart;
+
+ /* Baud rate setting.*/
+#if STM32_SERIAL_USE_LPUART1
+ if (sdp == &LPSD1) {
+ osalDbgAssert((sdp->clock >= config->speed * 3U) &&
+ (sdp->clock <= config->speed * 4096U),
+ "invalid baud rate vs input clock");
+
+ brr = (uint32_t)(((uint64_t)sdp->clock * 256) / config->speed);
+
+ osalDbgAssert((brr >= 0x300) && (brr < 0x100000), "invalid BRR value");
+ }
+ else
+#endif
+ {
+ brr = (uint32_t)(sdp->clock / config->speed);
+
+ /* Correcting BRR value when oversampling by 8 instead of 16.
+ Fraction is still 4 bits wide, but only lower 3 bits used.
+ Mantissa is doubled, but Fraction is left the same.*/
+ if (config->cr1 & USART_CR1_OVER8)
+ brr = ((brr & ~7) * 2) | (brr & 7);
+
+ osalDbgAssert(brr < 0x10000, "invalid BRR value");
+ }
+ u->BRR = brr;
+
+ /* Note that some bits are enforced.*/
+ u->CR2 = config->cr2 | USART_CR2_LBDIE;
+ u->CR3 = config->cr3 | USART_CR3_EIE;
+ u->CR1 = config->cr1 | USART_CR1_UE | USART_CR1_PEIE |
+ USART_CR1_RXNEIE | USART_CR1_TE |
+ USART_CR1_RE;
+ u->ICR = 0xFFFFFFFFU;
+
+ /* Deciding mask to be applied on the data register on receive, this is
+ required in order to mask out the parity bit.*/
+ if ((config->cr1 & USART_CR1_PCE) != 0U) {
+ switch (config->cr1 & (USART_CR1_M_1 | USART_CR1_M_0)) {
+ case 0:
+ sdp->rxmask = 0x7F;
+ break;
+ case USART_CR1_M_1:
+ sdp->rxmask = 0x3F;
+ break;
+ default:
+ sdp->rxmask = 0xFF;
+ }
+ }
+ else {
+ sdp->rxmask = 0xFF;
+ }
+}
+
+/**
+ * @brief USART de-initialization.
+ * @details This function must be invoked with interrupts disabled.
+ *
+ * @param[in] u pointer to an USART I/O block
+ */
+static void usart_deinit(USART_TypeDef *u) {
+
+ u->CR1 = 0;
+ u->CR2 = 0;
+ u->CR3 = 0;
+}
+
+/**
+ * @brief Error handling routine.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ * @param[in] isr USART ISR register value
+ */
+static void set_error(SerialDriver *sdp, uint32_t isr) {
+ eventflags_t sts = 0;
+
+ if (isr & USART_ISR_ORE)
+ sts |= SD_OVERRUN_ERROR;
+ if (isr & USART_ISR_PE)
+ sts |= SD_PARITY_ERROR;
+ if (isr & USART_ISR_FE)
+ sts |= SD_FRAMING_ERROR;
+ if (isr & USART_ISR_NE)
+ sts |= SD_NOISE_ERROR;
+ osalSysLockFromISR();
+ chnAddFlagsI(sdp, sts);
+ osalSysUnlockFromISR();
+}
+
+#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__)
+static void notify1(io_queue_t *qp) {
+
+ (void)qp;
+ USART1->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__)
+static void notify2(io_queue_t *qp) {
+
+ (void)qp;
+ USART2->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__)
+static void notify3(io_queue_t *qp) {
+
+ (void)qp;
+ USART3->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__)
+static void notify4(io_queue_t *qp) {
+
+ (void)qp;
+ UART4->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__)
+static void notify5(io_queue_t *qp) {
+
+ (void)qp;
+ UART5->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__)
+static void notify6(io_queue_t *qp) {
+
+ (void)qp;
+ USART6->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__)
+static void notify7(io_queue_t *qp) {
+
+ (void)qp;
+ UART7->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__)
+static void notify8(io_queue_t *qp) {
+
+ (void)qp;
+ UART8->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE;
+}
+#endif
+
+#if STM32_SERIAL_USE_LPUART1 || defined(__DOXYGEN__)
+static void notifylp1(io_queue_t *qp) {
+
+ (void)qp;
+ LPUART1->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE;
+}
+#endif
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_SERIAL_USE_USART1 || defined(__DOXYGEN__)
+#if !defined(STM32_USART1_SUPPRESS_ISR)
+#if !defined(STM32_USART1_HANDLER)
+#error "STM32_USART1_HANDLER not defined"
+#endif
+/**
+ * @brief USART1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ sd_lld_serve_interrupt(&SD1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if STM32_SERIAL_USE_USART2 || defined(__DOXYGEN__)
+#if !defined(STM32_USART2_SUPPRESS_ISR)
+#if !defined(STM32_USART2_HANDLER)
+#error "STM32_USART2_HANDLER not defined"
+#endif
+/**
+ * @brief USART2 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ sd_lld_serve_interrupt(&SD2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if STM32_SERIAL_USE_USART3 || defined(__DOXYGEN__)
+#if !defined(STM32_USART3_SUPPRESS_ISR)
+#if !defined(STM32_USART3_HANDLER)
+#error "STM32_USART3_HANDLER not defined"
+#endif
+/**
+ * @brief USART3 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ sd_lld_serve_interrupt(&SD3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if STM32_SERIAL_USE_UART4 || defined(__DOXYGEN__)
+#if !defined(STM32_UART4_SUPPRESS_ISR)
+#if !defined(STM32_UART4_HANDLER)
+#error "STM32_UART4_HANDLER not defined"
+#endif
+/**
+ * @brief UART4 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ sd_lld_serve_interrupt(&SD4);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if STM32_SERIAL_USE_UART5 || defined(__DOXYGEN__)
+#if !defined(STM32_UART5_SUPPRESS_ISR)
+#if !defined(STM32_UART5_HANDLER)
+#error "STM32_UART5_HANDLER not defined"
+#endif
+/**
+ * @brief UART5 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ sd_lld_serve_interrupt(&SD5);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if STM32_SERIAL_USE_USART6 || defined(__DOXYGEN__)
+#if !defined(STM32_USART6_SUPPRESS_ISR)
+#if !defined(STM32_USART6_HANDLER)
+#error "STM32_USART6_HANDLER not defined"
+#endif
+/**
+ * @brief USART6 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ sd_lld_serve_interrupt(&SD6);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if STM32_SERIAL_USE_UART7 || defined(__DOXYGEN__)
+#if !defined(STM32_UART7_SUPPRESS_ISR)
+#if !defined(STM32_UART7_HANDLER)
+#error "STM32_UART7_HANDLER not defined"
+#endif
+/**
+ * @brief UART7 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART7_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ sd_lld_serve_interrupt(&SD7);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if STM32_SERIAL_USE_UART8 || defined(__DOXYGEN__)
+#if !defined(STM32_UART8_SUPPRESS_ISR)
+#if !defined(STM32_UART8_HANDLER)
+#error "STM32_UART8_HANDLER not defined"
+#endif
+/**
+ * @brief UART8 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART8_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ sd_lld_serve_interrupt(&SD8);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if STM32_SERIAL_USE_LPUART1 || defined(__DOXYGEN__)
+#if !defined(STM32_LPUART1_SUPPRESS_ISR)
+#if !defined(STM32_LPUART1_HANDLER)
+#error "STM32_LPUART1_HANDLER not defined"
+#endif
+/**
+ * @brief LPUART1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_LPUART1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ sd_lld_serve_interrupt(&LPSD1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level serial driver initialization.
+ *
+ * @notapi
+ */
+void sd_lld_init(void) {
+
+#if STM32_SERIAL_USE_USART1
+ sdObjectInit(&SD1);
+ iqObjectInit(&SD1.iqueue, sd_in_buf1, sizeof sd_in_buf1, NULL, &SD1);
+ oqObjectInit(&SD1.oqueue, sd_out_buf1, sizeof sd_out_buf1, notify1, &SD1);
+ SD1.usart = USART1;
+ SD1.clock = STM32_USART1CLK;
+#if !defined(STM32_USART1_SUPPRESS_ISR) && defined(STM32_USART1_NUMBER)
+ nvicEnableVector(STM32_USART1_NUMBER, STM32_SERIAL_USART1_PRIORITY);
+#endif
+#endif
+
+#if STM32_SERIAL_USE_USART2
+ sdObjectInit(&SD2);
+ iqObjectInit(&SD2.iqueue, sd_in_buf2, sizeof sd_in_buf2, NULL, &SD2);
+ oqObjectInit(&SD2.oqueue, sd_out_buf2, sizeof sd_out_buf2, notify2, &SD2);
+ SD2.usart = USART2;
+ SD2.clock = STM32_USART2CLK;
+#if !defined(STM32_USART2_SUPPRESS_ISR) && defined(STM32_USART2_NUMBER)
+ nvicEnableVector(STM32_USART2_NUMBER, STM32_SERIAL_USART2_PRIORITY);
+#endif
+#endif
+
+#if STM32_SERIAL_USE_USART3
+ sdObjectInit(&SD3);
+ iqObjectInit(&SD3.iqueue, sd_in_buf3, sizeof sd_in_buf3, NULL, &SD3);
+ oqObjectInit(&SD3.oqueue, sd_out_buf3, sizeof sd_out_buf3, notify3, &SD3);
+ SD3.usart = USART3;
+ SD3.clock = STM32_USART3CLK;
+#if !defined(STM32_USART3_SUPPRESS_ISR) && defined(STM32_USART3_NUMBER)
+ nvicEnableVector(STM32_USART3_NUMBER, STM32_SERIAL_USART3_PRIORITY);
+#endif
+#endif
+
+#if STM32_SERIAL_USE_UART4
+ sdObjectInit(&SD4);
+ iqObjectInit(&SD4.iqueue, sd_in_buf4, sizeof sd_in_buf4, NULL, &SD4);
+ oqObjectInit(&SD4.oqueue, sd_out_buf4, sizeof sd_out_buf4, notify4, &SD4);
+ SD4.usart = UART4;
+ SD4.clock = STM32_UART4CLK;
+#if !defined(STM32_UART4_SUPPRESS_ISR) && defined(STM32_UART4_NUMBER)
+ nvicEnableVector(STM32_UART4_NUMBER, STM32_SERIAL_UART4_PRIORITY);
+#endif
+#endif
+
+#if STM32_SERIAL_USE_UART5
+ sdObjectInit(&SD5);
+ iqObjectInit(&SD5.iqueue, sd_in_buf5, sizeof sd_in_buf5, NULL, &SD5);
+ oqObjectInit(&SD5.oqueue, sd_out_buf5, sizeof sd_out_buf5, notify5, &SD5);
+ SD5.usart = UART5;
+ SD5.clock = STM32_UART5CLK;
+#if !defined(STM32_UART5_SUPPRESS_ISR) && defined(STM32_UART5_NUMBER)
+ nvicEnableVector(STM32_UART5_NUMBER, STM32_SERIAL_UART5_PRIORITY);
+#endif
+#endif
+
+#if STM32_SERIAL_USE_USART6
+ sdObjectInit(&SD6);
+ iqObjectInit(&SD6.iqueue, sd_in_buf6, sizeof sd_in_buf6, NULL, &SD6);
+ oqObjectInit(&SD6.oqueue, sd_out_buf6, sizeof sd_out_buf6, notify6, &SD6);
+ SD6.usart = USART6;
+ SD6.clock = STM32_USART6CLK;
+#if !defined(STM32_USART6_SUPPRESS_ISR) && defined(STM32_USART6_NUMBER)
+ nvicEnableVector(STM32_USART6_NUMBER, STM32_SERIAL_USART6_PRIORITY);
+#endif
+#endif
+
+#if STM32_SERIAL_USE_UART7
+ sdObjectInit(&SD7);
+ iqObjectInit(&SD7.iqueue, sd_in_buf7, sizeof sd_in_buf7, NULL, &SD7);
+ oqObjectInit(&SD7.oqueue, sd_out_buf7, sizeof sd_out_buf7, notify7, &SD7);
+ SD7.usart = UART7;
+ SD7.clock = STM32_UART7CLK;
+#if !defined(STM32_UART7_SUPPRESS_ISR) && defined(STM32_UART7_NUMBER)
+ nvicEnableVector(STM32_UART7_NUMBER, STM32_SERIAL_UART7_PRIORITY);
+#endif
+#endif
+
+#if STM32_SERIAL_USE_UART8
+ sdObjectInit(&SD8);
+ iqObjectInit(&SD8.iqueue, sd_in_buf8, sizeof sd_in_buf8, NULL, &SD8);
+ oqObjectInit(&SD8.oqueue, sd_out_buf8, sizeof sd_out_buf8, notify8, &SD8);
+ SD8.usart = UART8;
+ SD8.clock = STM32_UART8CLK;
+#if !defined(STM32_UART8_SUPPRESS_ISR) && defined(STM32_UART8_NUMBER)
+ nvicEnableVector(STM32_UART8_NUMBER, STM32_SERIAL_UART8_PRIORITY);
+#endif
+#endif
+
+#if STM32_SERIAL_USE_LPUART1
+ sdObjectInit(&LPSD1);
+ iqObjectInit(&LPSD1.iqueue, sd_in_buflp1, sizeof sd_in_buflp1, NULL, &LPSD1);
+ oqObjectInit(&LPSD1.oqueue, sd_out_buflp1, sizeof sd_out_buflp1, notifylp1, &LPSD1);
+ LPSD1.usart = LPUART1;
+ LPSD1.clock = STM32_LPUART1CLK;
+#if !defined(STM32_LPUART1_SUPPRESS_ISR) && defined(STM32_LPUART1_NUMBER)
+ nvicEnableVector(STM32_LPUART1_NUMBER, STM32_SERIAL_LPUART1_PRIORITY);
+#endif
+#endif
+}
+
+/**
+ * @brief Low level serial driver configuration and (re)start.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ * @param[in] config the architecture-dependent serial driver configuration.
+ * If this parameter is set to @p NULL then a default
+ * configuration is used.
+ *
+ * @notapi
+ */
+void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
+
+ if (config == NULL)
+ config = &default_config;
+
+ if (sdp->state == SD_STOP) {
+#if STM32_SERIAL_USE_USART1
+ if (&SD1 == sdp) {
+ rccEnableUSART1(true);
+ }
+#endif
+#if STM32_SERIAL_USE_USART2
+ if (&SD2 == sdp) {
+ rccEnableUSART2(true);
+ }
+#endif
+#if STM32_SERIAL_USE_USART3
+ if (&SD3 == sdp) {
+ rccEnableUSART3(true);
+ }
+#endif
+#if STM32_SERIAL_USE_UART4
+ if (&SD4 == sdp) {
+ rccEnableUART4(true);
+ }
+#endif
+#if STM32_SERIAL_USE_UART5
+ if (&SD5 == sdp) {
+ rccEnableUART5(true);
+ }
+#endif
+#if STM32_SERIAL_USE_USART6
+ if (&SD6 == sdp) {
+ rccEnableUSART6(true);
+ }
+#endif
+#if STM32_SERIAL_USE_UART7
+ if (&SD7 == sdp) {
+ rccEnableUART7(true);
+ }
+#endif
+#if STM32_SERIAL_USE_UART8
+ if (&SD8 == sdp) {
+ rccEnableUART8(true);
+ }
+#endif
+#if STM32_SERIAL_USE_LPUART1
+ if (&LPSD1 == sdp) {
+ rccEnableLPUART1(true);
+ }
+#endif
+ }
+ usart_init(sdp, config);
+}
+
+/**
+ * @brief Low level serial driver stop.
+ * @details De-initializes the USART, stops the associated clock, resets the
+ * interrupt vector.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ *
+ * @notapi
+ */
+void sd_lld_stop(SerialDriver *sdp) {
+
+ if (sdp->state == SD_READY) {
+ /* UART is de-initialized then clocks are disabled.*/
+ usart_deinit(sdp->usart);
+
+#if STM32_SERIAL_USE_USART1
+ if (&SD1 == sdp) {
+ rccDisableUSART1();
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_USART2
+ if (&SD2 == sdp) {
+ rccDisableUSART2();
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_USART3
+ if (&SD3 == sdp) {
+ rccDisableUSART3();
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_UART4
+ if (&SD4 == sdp) {
+ rccDisableUART4();
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_UART5
+ if (&SD5 == sdp) {
+ rccDisableUART5();
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_USART6
+ if (&SD6 == sdp) {
+ rccDisableUSART6();
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_UART7
+ if (&SD7 == sdp) {
+ rccDisableUART7();
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_UART8
+ if (&SD8 == sdp) {
+ rccDisableUART8();
+ return;
+ }
+#endif
+#if STM32_SERIAL_USE_LPUART1
+ if (&LPSD1 == sdp) {
+ rccDisableLPUART1();
+ return;
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Common IRQ handler.
+ *
+ * @param[in] sdp communication channel associated to the USART
+ */
+void sd_lld_serve_interrupt(SerialDriver *sdp) {
+ USART_TypeDef *u = sdp->usart;
+ uint32_t cr1 = u->CR1;
+ uint32_t isr;
+
+ /* Reading and clearing status.*/
+ isr = u->ISR;
+ u->ICR = isr;
+
+ /* Error condition detection.*/
+ if (isr & (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE | USART_ISR_PE))
+ set_error(sdp, isr);
+
+ /* Special case, LIN break detection.*/
+ if (isr & USART_ISR_LBDF) {
+ osalSysLockFromISR();
+ chnAddFlagsI(sdp, SD_BREAK_DETECTED);
+ osalSysUnlockFromISR();
+ }
+
+ /* Data available, note it is a while in order to handle two situations:
+ 1) Another byte arrived after removing the previous one, this would cause
+ an extra interrupt to serve.
+ 2) FIFO mode is enabled on devices that support it, we need to empty
+ the FIFO.*/
+ while (isr & USART_ISR_RXNE) {
+ osalSysLockFromISR();
+ sdIncomingDataI(sdp, (uint8_t)u->RDR & sdp->rxmask);
+ osalSysUnlockFromISR();
+
+ isr = u->ISR;
+ }
+
+ /* Transmission buffer empty, note it is a while in order to handle two
+ situations:
+ 1) The data registers has been emptied immediately after writing it, this
+ would cause an extra interrupt to serve.
+ 2) FIFO mode is enabled on devices that support it, we need to fill
+ the FIFO.*/
+ if (cr1 & USART_CR1_TXEIE) {
+ while (isr & USART_ISR_TXE) {
+ msg_t b;
+
+ osalSysLockFromISR();
+ b = oqGetI(&sdp->oqueue);
+ if (b < MSG_OK) {
+ chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
+ u->CR1 = cr1 & ~USART_CR1_TXEIE;
+ osalSysUnlockFromISR();
+ break;
+ }
+ u->TDR = b;
+ osalSysUnlockFromISR();
+
+ isr = u->ISR;
+ }
+ }
+
+ /* Physical transmission end.*/
+ if ((cr1 & USART_CR1_TCIE) && (isr & USART_ISR_TC)) {
+ osalSysLockFromISR();
+ if (oqIsEmptyI(&sdp->oqueue)) {
+ chnAddFlagsI(sdp, CHN_TRANSMISSION_END);
+ u->CR1 = cr1 & ~USART_CR1_TCIE;
+ }
+ osalSysUnlockFromISR();
+ }
+}
+
+#endif /* HAL_USE_SERIAL */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.h
new file mode 100644
index 0000000..19ee329
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/hal_serial_lld.h
@@ -0,0 +1,534 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv2/hal_serial_lld.h
+ * @brief STM32 low level serial driver header.
+ *
+ * @addtogroup SERIAL
+ * @{
+ */
+
+#ifndef HAL_SERIAL_LLD_H
+#define HAL_SERIAL_LLD_H
+
+#if HAL_USE_SERIAL || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Advanced buffering support switch.
+ * @details This constants enables the advanced buffering support in the
+ * low level driver, the queue buffer is no more part of the
+ * @p SerialDriver structure, each driver can have a different
+ * queue size.
+ */
+#define SERIAL_ADVANCED_BUFFERING_SUPPORT TRUE
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief USART1 driver enable switch.
+ * @details If set to @p TRUE the support for USART1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SERIAL_USE_USART1) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USE_USART1 FALSE
+#endif
+
+/**
+ * @brief USART2 driver enable switch.
+ * @details If set to @p TRUE the support for USART2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SERIAL_USE_USART2) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USE_USART2 FALSE
+#endif
+
+/**
+ * @brief USART3 driver enable switch.
+ * @details If set to @p TRUE the support for USART3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SERIAL_USE_USART3) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USE_USART3 FALSE
+#endif
+
+/**
+ * @brief UART4 driver enable switch.
+ * @details If set to @p TRUE the support for UART4 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SERIAL_USE_UART4) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USE_UART4 FALSE
+#endif
+
+/**
+ * @brief UART5 driver enable switch.
+ * @details If set to @p TRUE the support for UART5 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SERIAL_USE_UART5) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USE_UART5 FALSE
+#endif
+
+/**
+ * @brief USART6 driver enable switch.
+ * @details If set to @p TRUE the support for USART6 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SERIAL_USE_USART6) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USE_USART6 FALSE
+#endif
+
+/**
+ * @brief UART7 driver enable switch.
+ * @details If set to @p TRUE the support for UART7 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SERIAL_USE_UART7) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USE_UART7 FALSE
+#endif
+
+/**
+ * @brief UART8 driver enable switch.
+ * @details If set to @p TRUE the support for UART8 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SERIAL_USE_UART8) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USE_UART8 FALSE
+#endif
+
+/**
+ * @brief LPUART1 driver enable switch.
+ * @details If set to @p TRUE the support for LPUART is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_SERIAL_USE_LPUART1) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USE_LPUART1 FALSE
+#endif
+
+/**
+ * @brief USART1 interrupt priority level setting.
+ */
+#if !defined(STM32_SERIAL_USART1_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USART1_PRIORITY 12
+#endif
+
+/**
+ * @brief USART2 interrupt priority level setting.
+ */
+#if !defined(STM32_SERIAL_USART2_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USART2_PRIORITY 12
+#endif
+
+/**
+ * @brief USART3 interrupt priority level setting.
+ */
+#if !defined(STM32_SERIAL_USART3_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USART3_PRIORITY 12
+#endif
+
+/**
+ * @brief UART4 interrupt priority level setting.
+ */
+#if !defined(STM32_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SERIAL_UART4_PRIORITY 12
+#endif
+
+/**
+ * @brief UART5 interrupt priority level setting.
+ */
+#if !defined(STM32_SERIAL_UART5_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SERIAL_UART5_PRIORITY 12
+#endif
+
+/**
+ * @brief USART6 interrupt priority level setting.
+ */
+#if !defined(STM32_SERIAL_USART6_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USART6_PRIORITY 12
+#endif
+
+/**
+ * @brief UART7 interrupt priority level setting.
+ */
+#if !defined(STM32_SERIAL_UART7_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SERIAL_UART7_PRIORITY 12
+#endif
+
+/**
+ * @brief UART8 interrupt priority level setting.
+ */
+#if !defined(STM32_SERIAL_UART8_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SERIAL_UART8_PRIORITY 12
+#endif
+
+/**
+ * @brief LPUART1 interrupt priority level setting.
+ */
+#if !defined(STM32_SERIAL_LPUART1_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_SERIAL_LPUART1_PRIORITY 12
+#endif
+
+/**
+ * @brief Input buffer size for USART1.
+ */
+#if !defined(STM32_SERIAL_USART1_IN_BUF_SIZE) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USART1_IN_BUF_SIZE SERIAL_BUFFERS_SIZE
+#endif
+
+/**
+ * @brief Output buffer size for USART1.
+ */
+#if !defined(STM32_SERIAL_USART1_OUT_BUF_SIZE) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USART1_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE
+#endif
+
+/**
+ * @brief Input buffer size for USART2.
+ */
+#if !defined(STM32_SERIAL_USART2_IN_BUF_SIZE) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USART2_IN_BUF_SIZE SERIAL_BUFFERS_SIZE
+#endif
+
+/**
+ * @brief Output buffer size for USART2.
+ */
+#if !defined(STM32_SERIAL_USART2_OUT_BUF_SIZE) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USART2_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE
+#endif
+
+/**
+ * @brief Input buffer size for USART3.
+ */
+#if !defined(STM32_SERIAL_USART3_IN_BUF_SIZE) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USART3_IN_BUF_SIZE SERIAL_BUFFERS_SIZE
+#endif
+
+/**
+ * @brief Output buffer size for USART3.
+ */
+#if !defined(STM32_SERIAL_USART3_OUT_BUF_SIZE) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USART3_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE
+#endif
+
+/**
+ * @brief Input buffer size for UART4.
+ */
+#if !defined(STM32_SERIAL_UART4_IN_BUF_SIZE) || defined(__DOXYGEN__)
+#define STM32_SERIAL_UART4_IN_BUF_SIZE SERIAL_BUFFERS_SIZE
+#endif
+
+/**
+ * @brief Output buffer size for UART4.
+ */
+#if !defined(STM32_SERIAL_UART4_OUT_BUF_SIZE) || defined(__DOXYGEN__)
+#define STM32_SERIAL_UART4_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE
+#endif
+
+/**
+ * @brief Input buffer size for UART5.
+ */
+#if !defined(STM32_SERIAL_UART5_IN_BUF_SIZE) || defined(__DOXYGEN__)
+#define STM32_SERIAL_UART5_IN_BUF_SIZE SERIAL_BUFFERS_SIZE
+#endif
+
+/**
+ * @brief Output buffer size for UART5.
+ */
+#if !defined(STM32_SERIAL_UART5_OUT_BUF_SIZE) || defined(__DOXYGEN__)
+#define STM32_SERIAL_UART5_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE
+#endif
+
+/**
+ * @brief Input buffer size for USART6.
+ */
+#if !defined(STM32_SERIAL_USART6_IN_BUF_SIZE) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USART6_IN_BUF_SIZE SERIAL_BUFFERS_SIZE
+#endif
+
+/**
+ * @brief Output buffer size for USART6.
+ */
+#if !defined(STM32_SERIAL_USART6_OUT_BUF_SIZE) || defined(__DOXYGEN__)
+#define STM32_SERIAL_USART6_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE
+#endif
+
+/**
+ * @brief Input buffer size for UART7.
+ */
+#if !defined(STM32_SERIAL_UART7_IN_BUF_SIZE) || defined(__DOXYGEN__)
+#define STM32_SERIAL_UART7_IN_BUF_SIZE SERIAL_BUFFERS_SIZE
+#endif
+
+/**
+ * @brief Output buffer size for UART7.
+ */
+#if !defined(STM32_SERIAL_UART7_OUT_BUF_SIZE) || defined(__DOXYGEN__)
+#define STM32_SERIAL_UART7_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE
+#endif
+
+/**
+ * @brief Input buffer size for UART8.
+ */
+#if !defined(STM32_SERIAL_UART8_IN_BUF_SIZE) || defined(__DOXYGEN__)
+#define STM32_SERIAL_UART8_IN_BUF_SIZE SERIAL_BUFFERS_SIZE
+#endif
+
+/**
+ * @brief Output buffer size for UART8.
+ */
+#if !defined(STM32_SERIAL_UART8_OUT_BUF_SIZE) || defined(__DOXYGEN__)
+#define STM32_SERIAL_UART8_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE
+#endif
+
+/**
+ * @brief Input buffer size for LPUART1.
+ */
+#if !defined(STM32_SERIAL_LPUART1_IN_BUF_SIZE) || defined(__DOXYGEN__)
+#define STM32_SERIAL_LPUART1_IN_BUF_SIZE SERIAL_BUFFERS_SIZE
+#endif
+
+/**
+ * @brief Output buffer size for LPUART1.
+ */
+#if !defined(STM32_SERIAL_LPUART1_OUT_BUF_SIZE) || defined(__DOXYGEN__)
+#define STM32_SERIAL_LPUART1_OUT_BUF_SIZE SERIAL_BUFFERS_SIZE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if STM32_SERIAL_USE_USART1 && !STM32_HAS_USART1
+#error "USART1 not present in the selected device"
+#endif
+
+#if STM32_SERIAL_USE_USART2 && !STM32_HAS_USART2
+#error "USART2 not present in the selected device"
+#endif
+
+#if STM32_SERIAL_USE_USART3 && !STM32_HAS_USART3
+#error "USART3 not present in the selected device"
+#endif
+
+#if STM32_SERIAL_USE_UART4 && !STM32_HAS_UART4
+#error "UART4 not present in the selected device"
+#endif
+
+#if STM32_SERIAL_USE_UART5 && !STM32_HAS_UART5
+#error "UART5 not present in the selected device"
+#endif
+
+#if STM32_SERIAL_USE_USART6 && !STM32_HAS_USART6
+#error "USART6 not present in the selected device"
+#endif
+
+#if STM32_SERIAL_USE_UART7 && !STM32_HAS_UART7
+#error "UART7 not present in the selected device"
+#endif
+
+#if STM32_SERIAL_USE_UART8 && !STM32_HAS_UART8
+#error "UART8 not present in the selected device"
+#endif
+
+#if STM32_SERIAL_USE_LPUART1 && !STM32_HAS_LPUART1
+#error "LPUART1 not present in the selected device"
+#endif
+
+#if !STM32_SERIAL_USE_USART1 && !STM32_SERIAL_USE_USART2 && \
+ !STM32_SERIAL_USE_USART3 && !STM32_SERIAL_USE_UART4 && \
+ !STM32_SERIAL_USE_UART5 && !STM32_SERIAL_USE_USART6 && \
+ !STM32_SERIAL_USE_UART7 && !STM32_SERIAL_USE_UART8 && \
+ !STM32_SERIAL_USE_LPUART1
+#error "SERIAL driver activated but no USART/UART peripheral assigned"
+#endif
+
+#if !defined(STM32_USART1_SUPPRESS_ISR) && \
+ STM32_SERIAL_USE_USART1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART1_PRIORITY)
+#error "Invalid IRQ priority assigned to USART1"
+#endif
+
+#if !defined(STM32_USART2_SUPPRESS_ISR) && \
+ STM32_SERIAL_USE_USART2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART2_PRIORITY)
+#error "Invalid IRQ priority assigned to USART2"
+#endif
+
+#if !defined(STM32_USART3_SUPPRESS_ISR) && \
+ STM32_SERIAL_USE_USART3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART3_PRIORITY)
+#error "Invalid IRQ priority assigned to USART3"
+#endif
+
+#if !defined(STM32_UART4_SUPPRESS_ISR) && \
+ STM32_SERIAL_USE_UART4 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART4_PRIORITY)
+#error "Invalid IRQ priority assigned to UART4"
+#endif
+
+#if !defined(STM32_UART5_SUPPRESS_ISR) && \
+ STM32_SERIAL_USE_UART5 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART5_PRIORITY)
+#error "Invalid IRQ priority assigned to UART5"
+#endif
+
+#if !defined(STM32_USART6_SUPPRESS_ISR) && \
+ STM32_SERIAL_USE_USART6 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_USART6_PRIORITY)
+#error "Invalid IRQ priority assigned to USART6"
+#endif
+
+#if !defined(STM32_UART7_SUPPRESS_ISR) && \
+ STM32_SERIAL_USE_UART7 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART7_PRIORITY)
+#error "Invalid IRQ priority assigned to UART7"
+#endif
+
+#if !defined(STM32_UART8_SUPPRESS_ISR) && \
+ STM32_SERIAL_USE_UART8 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_UART8_PRIORITY)
+#error "Invalid IRQ priority assigned to UART8"
+#endif
+
+#if !defined(STM32_LPUART1_SUPPRESS_ISR) && \
+ STM32_SERIAL_USE_LPUART1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SERIAL_LPUART1_PRIORITY)
+#error "Invalid IRQ priority assigned to LPUART1"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 Serial Driver configuration structure.
+ * @details An instance of this structure must be passed to @p sdStart()
+ * in order to configure and start a serial driver operations.
+ * @note This structure content is architecture dependent, each driver
+ * implementation defines its own version and the custom static
+ * initializers.
+ */
+typedef struct {
+ /**
+ * @brief Bit rate.
+ */
+ uint32_t speed;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Initialization value for the CR1 register.
+ */
+ uint32_t cr1;
+ /**
+ * @brief Initialization value for the CR2 register.
+ */
+ uint32_t cr2;
+ /**
+ * @brief Initialization value for the CR3 register.
+ */
+ uint32_t cr3;
+} SerialConfig;
+
+/**
+ * @brief @p SerialDriver specific data.
+ */
+#define _serial_driver_data \
+ _base_asynchronous_channel_data \
+ /* Driver state.*/ \
+ sdstate_t state; \
+ /* Input queue.*/ \
+ input_queue_t iqueue; \
+ /* Output queue.*/ \
+ output_queue_t oqueue; \
+ /* End of the mandatory fields.*/ \
+ /* Pointer to the USART registers block.*/ \
+ USART_TypeDef *usart; \
+ /* Clock frequency for the associated USART/UART.*/ \
+ uint32_t clock; \
+ /* Mask to be applied on received frames.*/ \
+ uint8_t rxmask;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*
+ * Extra USARTs definitions here (missing from the ST header file).
+ */
+#define USART_CR2_STOP1_BITS (0 << 12) /**< @brief CR2 1 stop bit value.*/
+#define USART_CR2_STOP0P5_BITS (1 << 12) /**< @brief CR2 0.5 stop bit value.*/
+#define USART_CR2_STOP2_BITS (2 << 12) /**< @brief CR2 2 stop bit value.*/
+#define USART_CR2_STOP1P5_BITS (3 << 12) /**< @brief CR2 1.5 stop bit value.*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_SERIAL_USE_USART1 && !defined(__DOXYGEN__)
+extern SerialDriver SD1;
+#endif
+#if STM32_SERIAL_USE_USART2 && !defined(__DOXYGEN__)
+extern SerialDriver SD2;
+#endif
+#if STM32_SERIAL_USE_USART3 && !defined(__DOXYGEN__)
+extern SerialDriver SD3;
+#endif
+#if STM32_SERIAL_USE_UART4 && !defined(__DOXYGEN__)
+extern SerialDriver SD4;
+#endif
+#if STM32_SERIAL_USE_UART5 && !defined(__DOXYGEN__)
+extern SerialDriver SD5;
+#endif
+#if STM32_SERIAL_USE_USART6 && !defined(__DOXYGEN__)
+extern SerialDriver SD6;
+#endif
+#if STM32_SERIAL_USE_UART7 && !defined(__DOXYGEN__)
+extern SerialDriver SD7;
+#endif
+#if STM32_SERIAL_USE_UART8 && !defined(__DOXYGEN__)
+extern SerialDriver SD8;
+#endif
+#if STM32_SERIAL_USE_LPUART1 && !defined(__DOXYGEN__)
+extern SerialDriver LPSD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void sd_lld_init(void);
+ void sd_lld_start(SerialDriver *sdp, const SerialConfig *config);
+ void sd_lld_stop(SerialDriver *sdp);
+ void sd_lld_serve_interrupt(SerialDriver *sdp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SERIAL */
+
+#endif /* HAL_SERIAL_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.c
new file mode 100644
index 0000000..3787716
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.c
@@ -0,0 +1,1075 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv2/hal_uart_lld.c
+ * @brief STM32 low level UART driver code.
+ *
+ * @addtogroup UART
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_UART || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/* For compatibility for those devices without LIN support in the USARTs.*/
+#if !defined(USART_ISR_LBDF)
+#define USART_ISR_LBDF 0
+#endif
+
+#if !defined(USART_CR2_LBDIE)
+#define USART_CR2_LBDIE 0
+#endif
+
+/* STM32L0xx/STM32F7xx ST headers difference.*/
+#if !defined(USART_ISR_LBDF)
+#define USART_ISR_LBDF USART_ISR_LBD
+#endif
+
+/* STM32L0xx/STM32F7xx ST headers difference.*/
+#if !defined(USART_ISR_LBDF)
+#define USART_ISR_LBDF USART_ISR_LBD
+#endif
+
+#define USART1_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_USART1_RX_DMA_STREAM, \
+ STM32_USART1_RX_DMA_CHN)
+
+#define USART1_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_USART1_TX_DMA_STREAM, \
+ STM32_USART1_TX_DMA_CHN)
+
+#define USART2_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_USART2_RX_DMA_STREAM, \
+ STM32_USART2_RX_DMA_CHN)
+
+#define USART2_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_USART2_TX_DMA_STREAM, \
+ STM32_USART2_TX_DMA_CHN)
+
+#define USART3_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_USART3_RX_DMA_STREAM, \
+ STM32_USART3_RX_DMA_CHN)
+
+#define USART3_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_USART3_TX_DMA_STREAM, \
+ STM32_USART3_TX_DMA_CHN)
+
+#define UART4_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_UART4_RX_DMA_STREAM, \
+ STM32_UART4_RX_DMA_CHN)
+
+#define UART4_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_UART4_TX_DMA_STREAM, \
+ STM32_UART4_TX_DMA_CHN)
+
+#define UART5_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_UART5_RX_DMA_STREAM, \
+ STM32_UART5_RX_DMA_CHN)
+
+#define UART5_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_UART5_TX_DMA_STREAM, \
+ STM32_UART5_TX_DMA_CHN)
+
+#define USART6_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_USART6_RX_DMA_STREAM, \
+ STM32_USART6_RX_DMA_CHN)
+
+#define USART6_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_USART6_TX_DMA_STREAM, \
+ STM32_USART6_TX_DMA_CHN)
+
+#define UART7_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_UART7_RX_DMA_STREAM, \
+ STM32_UART7_RX_DMA_CHN)
+
+#define UART7_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_UART7_TX_DMA_STREAM, \
+ STM32_UART7_TX_DMA_CHN)
+
+#define UART8_RX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_UART8_RX_DMA_STREAM, \
+ STM32_UART8_RX_DMA_CHN)
+
+#define UART8_TX_DMA_CHANNEL \
+ STM32_DMA_GETCHANNEL(STM32_UART_UART8_TX_DMA_STREAM, \
+ STM32_UART8_TX_DMA_CHN)
+
+/* Workarounds for those devices where UARTs are USARTs.*/
+#if defined(USART4)
+#define UART4 USART4
+#endif
+#if defined(USART5)
+#define UART5 USART5
+#endif
+#if defined(USART7)
+#define UART7 USART7
+#endif
+#if defined(USART8)
+#define UART8 USART8
+#endif
+
+/* Workaround for more differences in headers.*/
+#if !defined(USART_CR1_M0)
+#define USART_CR1_M0 USART_CR1_M
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief USART1 UART driver identifier.*/
+#if STM32_UART_USE_USART1 || defined(__DOXYGEN__)
+UARTDriver UARTD1;
+#endif
+
+/** @brief USART2 UART driver identifier.*/
+#if STM32_UART_USE_USART2 || defined(__DOXYGEN__)
+UARTDriver UARTD2;
+#endif
+
+/** @brief USART3 UART driver identifier.*/
+#if STM32_UART_USE_USART3 || defined(__DOXYGEN__)
+UARTDriver UARTD3;
+#endif
+
+/** @brief UART4 UART driver identifier.*/
+#if STM32_UART_USE_UART4 || defined(__DOXYGEN__)
+UARTDriver UARTD4;
+#endif
+
+/** @brief UART5 UART driver identifier.*/
+#if STM32_UART_USE_UART5 || defined(__DOXYGEN__)
+UARTDriver UARTD5;
+#endif
+
+/** @brief USART6 UART driver identifier.*/
+#if STM32_UART_USE_USART6 || defined(__DOXYGEN__)
+UARTDriver UARTD6;
+#endif
+
+/** @brief UART7 UART driver identifier.*/
+#if STM32_UART_USE_UART7 || defined(__DOXYGEN__)
+UARTDriver UARTD7;
+#endif
+
+/** @brief UART8 UART driver identifier.*/
+#if STM32_UART_USE_UART8 || defined(__DOXYGEN__)
+UARTDriver UARTD8;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Status bits translation.
+ *
+ * @param[in] isr USART SR register value
+ *
+ * @return The error flags.
+ */
+static uartflags_t translate_errors(uint32_t isr) {
+ uartflags_t sts = 0;
+
+ if (isr & USART_ISR_ORE)
+ sts |= UART_OVERRUN_ERROR;
+ if (isr & USART_ISR_PE)
+ sts |= UART_PARITY_ERROR;
+ if (isr & USART_ISR_FE)
+ sts |= UART_FRAMING_ERROR;
+ if (isr & USART_ISR_NE)
+ sts |= UART_NOISE_ERROR;
+ if (isr & USART_ISR_LBDF)
+ sts |= UART_BREAK_DETECTED;
+ return sts;
+}
+
+/**
+ * @brief Puts the receiver in the UART_RX_IDLE state.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+static void uart_enter_rx_idle_loop(UARTDriver *uartp) {
+ uint32_t mode;
+
+ /* RX DMA channel preparation, if the char callback is defined then the
+ TCIE interrupt is enabled too.*/
+ if (uartp->config->rxchar_cb == NULL)
+ mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC;
+ else
+ mode = STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_CIRC | STM32_DMA_CR_TCIE;
+ dmaStreamSetMemory0(uartp->dmarx, &uartp->rxbuf);
+ dmaStreamSetTransactionSize(uartp->dmarx, 1);
+ dmaStreamSetMode(uartp->dmarx, uartp->dmarxmode | mode);
+ dmaStreamEnable(uartp->dmarx);
+}
+
+/**
+ * @brief USART de-initialization.
+ * @details This function must be invoked with interrupts disabled.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+static void usart_stop(UARTDriver *uartp) {
+
+ /* Stops RX and TX DMA channels.*/
+ dmaStreamDisable(uartp->dmarx);
+ dmaStreamDisable(uartp->dmatx);
+
+ /* Stops USART operations.*/
+ uartp->usart->CR1 = 0;
+ uartp->usart->CR2 = 0;
+ uartp->usart->CR3 = 0;
+}
+
+/**
+ * @brief USART initialization.
+ * @details This function must be invoked with interrupts disabled.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+static void usart_start(UARTDriver *uartp) {
+ uint32_t fck;
+ uint32_t cr1;
+ const uint32_t tmo = uartp->config->timeout;
+ USART_TypeDef *u = uartp->usart;
+
+ /* Defensive programming, starting from a clean state.*/
+ usart_stop(uartp);
+
+ /* Baud rate setting.*/
+ fck = (uint32_t)(uartp->clock / uartp->config->speed);
+
+ /* Correcting USARTDIV when oversampling by 8 instead of 16.
+ Fraction is still 4 bits wide, but only lower 3 bits used.
+ Mantissa is doubled, but Fraction is left the same.*/
+ if (uartp->config->cr1 & USART_CR1_OVER8)
+ fck = ((fck & ~7) * 2) | (fck & 7);
+ u->BRR = fck;
+
+ /* Resetting eventual pending status flags.*/
+ u->ICR = 0xFFFFFFFFU;
+
+ /* Note that some bits are enforced because required for correct driver
+ operations.*/
+ u->CR2 = uartp->config->cr2 | USART_CR2_LBDIE;
+ u->CR3 = uartp->config->cr3 | USART_CR3_DMAT | USART_CR3_DMAR |
+ USART_CR3_EIE;
+
+ /* Mustn't ever set TCIE here - if done, it causes an immediate
+ interrupt.*/
+ cr1 = USART_CR1_UE | USART_CR1_PEIE | USART_CR1_TE | USART_CR1_RE;
+ u->CR1 = uartp->config->cr1 | cr1;
+
+ /* Set receive timeout and checks if it is really applied.*/
+ if (tmo > 0) {
+ osalDbgAssert(tmo <= USART_RTOR_RTO, "Timeout overflow");
+ u->RTOR = tmo;
+ osalDbgAssert(tmo == u->RTOR, "Timeout feature unsupported in this UART");
+ }
+
+ /* Starting the receiver idle loop.*/
+ uart_enter_rx_idle_loop(uartp);
+}
+
+/**
+ * @brief RX DMA common service routine.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void uart_lld_serve_rx_end_irq(UARTDriver *uartp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(STM32_UART_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_UART_DMA_ERROR_HOOK(uartp);
+ }
+#else
+ (void)flags;
+#endif
+
+ if (uartp->rxstate == UART_RX_IDLE) {
+ /* Receiver in idle state, a callback is generated, if enabled, for each
+ received character and then the driver stays in the same state.*/
+ _uart_rx_idle_code(uartp);
+ }
+ else {
+ /* Receiver in active state, a callback is generated, if enabled, after
+ a completed transfer.*/
+ dmaStreamDisable(uartp->dmarx);
+ _uart_rx_complete_isr_code(uartp);
+ }
+}
+
+/**
+ * @brief TX DMA common service routine.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] flags pre-shifted content of the ISR register
+ */
+static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) {
+
+ /* DMA errors handling.*/
+#if defined(STM32_UART_DMA_ERROR_HOOK)
+ if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) {
+ STM32_UART_DMA_ERROR_HOOK(uartp);
+ }
+#else
+ (void)flags;
+#endif
+
+ dmaStreamDisable(uartp->dmatx);
+
+ /* A callback is generated, if enabled, after a completed transfer.*/
+ _uart_tx1_isr_code(uartp);
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_UART_USE_USART1 || defined(__DOXYGEN__)
+#if !defined(STM32_USART1_SUPPRESS_ISR)
+#if !defined(STM32_USART1_HANDLER)
+#error "STM32_USART1_HANDLER not defined"
+#endif
+/**
+ * @brief USART1 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ uart_lld_serve_interrupt(&UARTD1);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if STM32_UART_USE_USART2 || defined(__DOXYGEN__)
+#if !defined(STM32_USART2_SUPPRESS_ISR)
+#if !defined(STM32_USART2_HANDLER)
+#error "STM32_USART2_HANDLER not defined"
+#endif
+/**
+ * @brief USART2 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ uart_lld_serve_interrupt(&UARTD2);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if STM32_UART_USE_USART3 || defined(__DOXYGEN__)
+#if !defined(STM32_USART3_SUPPRESS_ISR)
+#if !defined(STM32_USART3_HANDLER)
+#error "STM32_USART3_HANDLER not defined"
+#endif
+/**
+ * @brief USART3 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ uart_lld_serve_interrupt(&UARTD3);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if STM32_UART_USE_UART4 || defined(__DOXYGEN__)
+#if !defined(STM32_UART4_SUPPRESS_ISR)
+#if !defined(STM32_UART4_HANDLER)
+#error "STM32_UART4_HANDLER not defined"
+#endif
+/**
+ * @brief UART4 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ uart_lld_serve_interrupt(&UARTD4);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if STM32_UART_USE_UART5 || defined(__DOXYGEN__)
+#if !defined(STM32_UART5_SUPPRESS_ISR)
+#if !defined(STM32_UART5_HANDLER)
+#error "STM32_UART5_HANDLER not defined"
+#endif
+/**
+ * @brief UART5 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ uart_lld_serve_interrupt(&UARTD5);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if STM32_UART_USE_USART6 || defined(__DOXYGEN__)
+#if !defined(STM32_USART6_SUPPRESS_ISR)
+#if !defined(STM32_USART6_HANDLER)
+#error "STM32_USART6_HANDLER not defined"
+#endif
+/**
+ * @brief USART6 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ uart_lld_serve_interrupt(&UARTD6);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if STM32_UART_USE_UART7 || defined(__DOXYGEN__)
+#if !defined(STM32_UART7_SUPPRESS_ISR)
+#if !defined(STM32_UART7_HANDLER)
+#error "STM32_UART7_HANDLER not defined"
+#endif
+/**
+ * @brief UART7 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART7_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ uart_lld_serve_interrupt(&UARTD7);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+#if STM32_UART_USE_UART8 || defined(__DOXYGEN__)
+#if !defined(STM32_UART8_SUPPRESS_ISR)
+#if !defined(STM32_UART8_HANDLER)
+#error "STM32_UART8_HANDLER not defined"
+#endif
+/**
+ * @brief UART8 IRQ handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART8_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ uart_lld_serve_interrupt(&UARTD8);
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level UART driver initialization.
+ *
+ * @notapi
+ */
+void uart_lld_init(void) {
+
+#if STM32_UART_USE_USART1
+ uartObjectInit(&UARTD1);
+ UARTD1.usart = USART1;
+ UARTD1.clock = STM32_USART1CLK;
+ UARTD1.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD1.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD1.dmarx = NULL;
+ UARTD1.dmatx = NULL;
+#if !defined(STM32_USART1_SUPPRESS_ISR) && defined(STM32_USART1_NUMBER)
+ nvicEnableVector(STM32_USART1_NUMBER, STM32_UART_USART1_IRQ_PRIORITY);
+#endif
+#endif
+
+#if STM32_UART_USE_USART2
+ uartObjectInit(&UARTD2);
+ UARTD2.usart = USART2;
+ UARTD2.clock = STM32_USART2CLK;
+ UARTD2.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD2.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD2.dmarx = NULL;
+ UARTD2.dmatx = NULL;
+#if !defined(STM32_USART2_SUPPRESS_ISR) && defined(STM32_USART2_NUMBER)
+ nvicEnableVector(STM32_USART2_NUMBER, STM32_UART_USART2_IRQ_PRIORITY);
+#endif
+#endif
+
+#if STM32_UART_USE_USART3
+ uartObjectInit(&UARTD3);
+ UARTD3.usart = USART3;
+ UARTD3.clock = STM32_USART3CLK;
+ UARTD3.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD3.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD3.dmarx = NULL;
+ UARTD3.dmatx = NULL;
+#if !defined(STM32_USART3_SUPPRESS_ISR) && defined(STM32_USART3_NUMBER)
+ nvicEnableVector(STM32_USART3_NUMBER, STM32_UART_USART3_IRQ_PRIORITY);
+#endif
+#endif
+
+#if STM32_UART_USE_UART4
+ uartObjectInit(&UARTD4);
+ UARTD4.usart = UART4;
+ UARTD4.clock = STM32_UART4CLK;
+ UARTD4.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD4.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD4.dmarx = NULL;
+ UARTD4.dmatx = NULL;
+#if !defined(STM32_UART4_SUPPRESS_ISR) && defined(STM32_UART4_NUMBER)
+ nvicEnableVector(STM32_UART4_NUMBER, STM32_UART_UART4_IRQ_PRIORITY);
+#endif
+#endif
+
+#if STM32_UART_USE_UART5
+ uartObjectInit(&UARTD5);
+ UARTD5.usart = UART5;
+ UARTD5.clock = STM32_UART5CLK;
+ UARTD5.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD5.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD5.dmarx = NULL;
+ UARTD5.dmatx = NULL;
+#if !defined(STM32_UART5_SUPPRESS_ISR) && defined(STM32_UART5_NUMBER)
+ nvicEnableVector(STM32_UART5_NUMBER, STM32_UART_UART5_IRQ_PRIORITY);
+#endif
+#endif
+
+#if STM32_UART_USE_USART6
+ uartObjectInit(&UARTD6);
+ UARTD6.usart = USART6;
+ UARTD6.clock = STM32_USART6CLK;
+ UARTD6.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD6.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD6.dmarx = NULL;
+ UARTD6.dmatx = NULL;
+#if !defined(STM32_USART6_SUPPRESS_ISR) && defined(STM32_USART6_NUMBER)
+ nvicEnableVector(STM32_USART6_NUMBER, STM32_UART_USART6_IRQ_PRIORITY);
+#endif
+#endif
+
+#if STM32_UART_USE_UART7
+ uartObjectInit(&UARTD7);
+ UARTD7.usart = UART7;
+ UARTD7.clock = STM32_UART7CLK;
+ UARTD7.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD7.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD7.dmarx = NULL;
+ UARTD7.dmatx = NULL;
+#if !defined(STM32_UART7_SUPPRESS_ISR) && defined(STM32_UART7_NUMBER)
+ nvicEnableVector(STM32_UART7_NUMBER, STM32_UART_UART7_IRQ_PRIORITY);
+#endif
+#endif
+
+#if STM32_UART_USE_UART8
+ uartObjectInit(&UARTD8);
+ UARTD8.usart = UART8;
+ UARTD8.clock = STM32_UART8CLK;
+ UARTD8.dmarxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD8.dmatxmode = STM32_DMA_CR_DMEIE | STM32_DMA_CR_TEIE;
+ UARTD8.dmarx = NULL;
+ UARTD8.dmatx = NULL;
+#if !defined(STM32_UART8_SUPPRESS_ISR) && defined(STM32_UART8_NUMBER)
+ nvicEnableVector(STM32_UART8_NUMBER, STM32_UART_UART8_IRQ_PRIORITY);
+#endif
+#endif
+}
+
+/**
+ * @brief Configures and activates the UART peripheral.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+void uart_lld_start(UARTDriver *uartp) {
+
+ if (uartp->state == UART_STOP) {
+#if STM32_UART_USE_USART1
+ if (&UARTD1 == uartp) {
+ uartp->dmarx = dmaStreamAllocI(STM32_UART_USART1_RX_DMA_STREAM,
+ STM32_UART_USART1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(STM32_UART_USART1_TX_DMA_STREAM,
+ STM32_UART_USART1_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableUSART1(true);
+ uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART1_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY);
+ uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART1_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART1_DMA_PRIORITY);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_USART1_RX);
+ dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_USART1_TX);
+#endif
+ }
+#endif
+
+#if STM32_UART_USE_USART2
+ if (&UARTD2 == uartp) {
+ uartp->dmarx = dmaStreamAllocI(STM32_UART_USART2_RX_DMA_STREAM,
+ STM32_UART_USART2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(STM32_UART_USART2_TX_DMA_STREAM,
+ STM32_UART_USART2_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableUSART2(true);
+ uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART2_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY);
+ uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART2_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART2_DMA_PRIORITY);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_USART2_RX);
+ dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_USART2_TX);
+#endif
+ }
+#endif
+
+#if STM32_UART_USE_USART3
+ if (&UARTD3 == uartp) {
+ uartp->dmarx = dmaStreamAllocI(STM32_UART_USART3_RX_DMA_STREAM,
+ STM32_UART_USART3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(STM32_UART_USART3_TX_DMA_STREAM,
+ STM32_UART_USART3_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableUSART3(true);
+ uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART3_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY);
+ uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART3_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART3_DMA_PRIORITY);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_USART3_RX);
+ dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_USART3_TX);
+#endif
+ }
+#endif
+
+#if STM32_UART_USE_UART4
+ if (&UARTD4 == uartp) {
+ uartp->dmarx = dmaStreamAllocI(STM32_UART_UART4_RX_DMA_STREAM,
+ STM32_UART_UART4_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(STM32_UART_UART4_TX_DMA_STREAM,
+ STM32_UART_UART4_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableUART4(true);
+ uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART4_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_UART4_DMA_PRIORITY);
+ uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART4_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_UART4_DMA_PRIORITY);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_UART4_RX);
+ dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_UART4_TX);
+#endif
+ }
+#endif
+
+#if STM32_UART_USE_UART5
+ if (&UARTD5 == uartp) {
+ uartp->dmarx = dmaStreamAllocI(STM32_UART_UART5_RX_DMA_STREAM,
+ STM32_UART_UART5_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(STM32_UART_UART5_TX_DMA_STREAM,
+ STM32_UART_UART5_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableUART5(true);
+ uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART5_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_UART5_DMA_PRIORITY);
+ uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART5_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_UART5_DMA_PRIORITY);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_UART5_RX);
+ dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_UART5_TX);
+#endif
+ }
+#endif
+
+#if STM32_UART_USE_USART6
+ if (&UARTD6 == uartp) {
+ uartp->dmarx = dmaStreamAllocI(STM32_UART_USART6_RX_DMA_STREAM,
+ STM32_UART_USART6_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(STM32_UART_USART6_TX_DMA_STREAM,
+ STM32_UART_USART6_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableUSART6(true);
+ uartp->dmarxmode |= STM32_DMA_CR_CHSEL(USART6_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART6_DMA_PRIORITY);
+ uartp->dmatxmode |= STM32_DMA_CR_CHSEL(USART6_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_USART6_DMA_PRIORITY);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_USART6_RX);
+ dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_USART6_TX);
+#endif
+ }
+#endif
+
+#if STM32_UART_USE_UART7
+ if (&UARTD7 == uartp) {
+ uartp->dmarx = dmaStreamAllocI(STM32_UART_UART7_RX_DMA_STREAM,
+ STM32_UART_UART7_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(STM32_UART_UART7_TX_DMA_STREAM,
+ STM32_UART_UART7_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableUART7(true);
+ uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART7_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_UART7_DMA_PRIORITY);
+ uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART7_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_UART7_DMA_PRIORITY);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_UART7_RX);
+ dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_UART7_TX);
+#endif
+ }
+#endif
+
+#if STM32_UART_USE_UART8
+ if (&UARTD8 == uartp) {
+ uartp->dmarx = dmaStreamAllocI(STM32_UART_UART8_RX_DMA_STREAM,
+ STM32_UART_UART8_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_rx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmarx != NULL, "unable to allocate stream");
+ uartp->dmatx = dmaStreamAllocI(STM32_UART_UART8_TX_DMA_STREAM,
+ STM32_UART_UART8_IRQ_PRIORITY,
+ (stm32_dmaisr_t)uart_lld_serve_tx_end_irq,
+ (void *)uartp);
+ osalDbgAssert(uartp->dmatx != NULL, "unable to allocate stream");
+
+ rccEnableUART8(true);
+ uartp->dmarxmode |= STM32_DMA_CR_CHSEL(UART8_RX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_UART8_DMA_PRIORITY);
+ uartp->dmatxmode |= STM32_DMA_CR_CHSEL(UART8_TX_DMA_CHANNEL) |
+ STM32_DMA_CR_PL(STM32_UART_UART8_DMA_PRIORITY);
+#if STM32_DMA_SUPPORTS_DMAMUX
+ dmaSetRequestSource(uartp->dmarx, STM32_DMAMUX1_UART8_RX);
+ dmaSetRequestSource(uartp->dmatx, STM32_DMAMUX1_UART8_TX);
+#endif
+ }
+#endif
+
+ /* Static DMA setup, the transfer size depends on the USART settings,
+ it is 16 bits if M=1 and PCE=0 else it is 8 bits.*/
+ if ((uartp->config->cr1 & (USART_CR1_M | USART_CR1_PCE)) == USART_CR1_M0) {
+ uartp->dmarxmode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
+ uartp->dmatxmode |= STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD;
+ }
+ dmaStreamSetPeripheral(uartp->dmarx, &uartp->usart->RDR);
+ dmaStreamSetPeripheral(uartp->dmatx, &uartp->usart->TDR);
+ uartp->rxbuf = 0;
+ }
+
+ uartp->rxstate = UART_RX_IDLE;
+ uartp->txstate = UART_TX_IDLE;
+ usart_start(uartp);
+}
+
+/**
+ * @brief Deactivates the UART peripheral.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+void uart_lld_stop(UARTDriver *uartp) {
+
+ if (uartp->state == UART_READY) {
+ usart_stop(uartp);
+ dmaStreamFreeI(uartp->dmarx);
+ dmaStreamFreeI(uartp->dmatx);
+ uartp->dmarx = NULL;
+ uartp->dmatx = NULL;
+
+#if STM32_UART_USE_USART1
+ if (&UARTD1 == uartp) {
+ rccDisableUSART1();
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_USART2
+ if (&UARTD2 == uartp) {
+ rccDisableUSART2();
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_USART3
+ if (&UARTD3 == uartp) {
+ rccDisableUSART3();
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_UART4
+ if (&UARTD4 == uartp) {
+ rccDisableUART4();
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_UART5
+ if (&UARTD5 == uartp) {
+ rccDisableUART5();
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_USART6
+ if (&UARTD6 == uartp) {
+ rccDisableUSART6();
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_UART7
+ if (&UARTD7 == uartp) {
+ rccDisableUART7();
+ return;
+ }
+#endif
+
+#if STM32_UART_USE_UART8
+ if (&UARTD8 == uartp) {
+ rccDisableUART8();
+ return;
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Starts a transmission on the UART peripheral.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] n number of data frames to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @notapi
+ */
+void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) {
+
+ /* TX DMA channel preparation.*/
+ dmaStreamSetMemory0(uartp->dmatx, txbuf);
+ dmaStreamSetTransactionSize(uartp->dmatx, n);
+ dmaStreamSetMode(uartp->dmatx, uartp->dmatxmode | STM32_DMA_CR_DIR_M2P |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE);
+
+ /* Only enable TC interrupt if there's a callback attached to it or
+ if called from uartSendFullTimeout(). Also we need to clear TC flag
+ which could be set before.*/
+#if UART_USE_WAIT == TRUE
+ if ((uartp->config->txend2_cb != NULL) || (uartp->early == false)) {
+#else
+ if (uartp->config->txend2_cb != NULL) {
+#endif
+ uartp->usart->ICR = USART_ICR_TCCF;
+ uartp->usart->CR1 |= USART_CR1_TCIE;
+ }
+
+ /* Starting transfer.*/
+ dmaStreamEnable(uartp->dmatx);
+}
+
+/**
+ * @brief Stops any ongoing transmission.
+ * @note Stopping a transmission also suppresses the transmission callbacks.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @return The number of data frames not transmitted by the
+ * stopped transmit operation.
+ *
+ * @notapi
+ */
+size_t uart_lld_stop_send(UARTDriver *uartp) {
+
+ dmaStreamDisable(uartp->dmatx);
+
+ return dmaStreamGetTransactionSize(uartp->dmatx);
+}
+
+/**
+ * @brief Starts a receive operation on the UART peripheral.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] n number of data frames to send
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) {
+
+ /* Stopping previous activity (idle state).*/
+ dmaStreamDisable(uartp->dmarx);
+
+ /* RX DMA channel preparation.*/
+ dmaStreamSetMemory0(uartp->dmarx, rxbuf);
+ dmaStreamSetTransactionSize(uartp->dmarx, n);
+ dmaStreamSetMode(uartp->dmarx, uartp->dmarxmode | STM32_DMA_CR_DIR_P2M |
+ STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE);
+
+ /* Starting transfer.*/
+ dmaStreamEnable(uartp->dmarx);
+}
+
+/**
+ * @brief Stops any ongoing receive operation.
+ * @note Stopping a receive operation also suppresses the receive callbacks.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @return The number of data frames not received by the
+ * stopped receive operation.
+ *
+ * @notapi
+ */
+size_t uart_lld_stop_receive(UARTDriver *uartp) {
+ size_t n;
+
+ dmaStreamDisable(uartp->dmarx);
+ n = dmaStreamGetTransactionSize(uartp->dmarx);
+ uart_enter_rx_idle_loop(uartp);
+
+ return n;
+}
+
+/**
+ * @brief USART common service routine.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+void uart_lld_serve_interrupt(UARTDriver *uartp) {
+ uint32_t isr;
+ USART_TypeDef *u = uartp->usart;
+ uint32_t cr1 = u->CR1;
+
+ /* Reading and clearing status.*/
+ isr = u->ISR;
+ u->ICR = isr;
+
+ if (isr & (USART_ISR_LBDF | USART_ISR_ORE | USART_ISR_NE |
+ USART_ISR_FE | USART_ISR_PE)) {
+ _uart_rx_error_isr_code(uartp, translate_errors(isr));
+ }
+
+ if ((isr & USART_ISR_TC) && (cr1 & USART_CR1_TCIE)) {
+ /* TC interrupt disabled.*/
+ u->CR1 = cr1 & ~USART_CR1_TCIE;
+
+ /* End of transmission, a callback is generated.*/
+ _uart_tx2_isr_code(uartp);
+ }
+
+ /* Timeout interrupt sources are only checked if enabled in CR1.*/
+ if (((cr1 & USART_CR1_IDLEIE) && (isr & USART_ISR_IDLE)) ||
+ ((cr1 & USART_CR1_RTOIE) && (isr & USART_ISR_RTOF))) {
+ _uart_timeout_isr_code(uartp);
+ }
+}
+
+#endif /* HAL_USE_UART */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.h
new file mode 100644
index 0000000..ec5a694
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/hal_uart_lld.h
@@ -0,0 +1,842 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv2/hal_uart_lld.h
+ * @brief STM32 low level UART driver header.
+ *
+ * @addtogroup UART
+ * @{
+ */
+
+#ifndef HAL_UART_LLD_H
+#define HAL_UART_LLD_H
+
+#if HAL_USE_UART || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief UART driver on USART1 enable switch.
+ * @details If set to @p TRUE the support for USART1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_UART_USE_USART1) || defined(__DOXYGEN__)
+#define STM32_UART_USE_USART1 FALSE
+#endif
+
+/**
+ * @brief UART driver on USART2 enable switch.
+ * @details If set to @p TRUE the support for USART2 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_UART_USE_USART2) || defined(__DOXYGEN__)
+#define STM32_UART_USE_USART2 FALSE
+#endif
+
+/**
+ * @brief UART driver on USART3 enable switch.
+ * @details If set to @p TRUE the support for USART3 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_UART_USE_USART3) || defined(__DOXYGEN__)
+#define STM32_UART_USE_USART3 FALSE
+#endif
+
+/**
+ * @brief UART driver on UART4 enable switch.
+ * @details If set to @p TRUE the support for UART4 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_UART_USE_UART4) || defined(__DOXYGEN__)
+#define STM32_UART_USE_UART4 FALSE
+#endif
+
+/**
+ * @brief UART driver on UART5 enable switch.
+ * @details If set to @p TRUE the support for UART5 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_UART_USE_UART5) || defined(__DOXYGEN__)
+#define STM32_UART_USE_UART5 FALSE
+#endif
+
+/**
+ * @brief UART driver on USART6 enable switch.
+ * @details If set to @p TRUE the support for USART6 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_UART_USE_USART6) || defined(__DOXYGEN__)
+#define STM32_UART_USE_USART6 FALSE
+#endif
+
+/**
+ * @brief UART driver on UART7 enable switch.
+ * @details If set to @p TRUE the support for UART7 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_UART_USE_UART7) || defined(__DOXYGEN__)
+#define STM32_UART_USE_UART7 FALSE
+#endif
+
+/**
+ * @brief UART driver on UART8 enable switch.
+ * @details If set to @p TRUE the support for UART8 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_UART_USE_UART8) || defined(__DOXYGEN__)
+#define STM32_UART_USE_UART8 FALSE
+#endif
+
+/**
+ * @brief USART1 interrupt priority level setting.
+ */
+#if !defined(STM32_UART_USART1_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_USART1_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief USART2 interrupt priority level setting.
+ */
+#if !defined(STM32_UART_USART2_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_USART2_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief USART3 interrupt priority level setting.
+ */
+#if !defined(STM32_UART_USART3_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_USART3_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief UART4 interrupt priority level setting.
+ */
+#if !defined(STM32_UART_UART4_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_UART4_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief UART5 interrupt priority level setting.
+ */
+#if !defined(STM32_UART_UART5_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_UART5_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief USART6 interrupt priority level setting.
+ */
+#if !defined(STM32_UART_USART6_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_USART6_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief UART7 interrupt priority level setting.
+ */
+#if !defined(STM32_UART_UART7_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_UART7_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief UART8 interrupt priority level setting.
+ */
+#if !defined(STM32_UART_UART8_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_UART8_IRQ_PRIORITY 12
+#endif
+
+/**
+ * @brief USART1 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(STM32_UART_USART1_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_USART1_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief USART2 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(STM32_UART_USART2_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_USART2_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief USART3 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(STM32_UART_USART3_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_USART3_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief UART4 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(STM32_UART_UART4_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_UART4_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief UART5 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(STM32_UART_UART5_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_UART5_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief USART6 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(STM32_UART_USART6_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_USART6_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief UART7 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(STM32_UART_UART7_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_UART7_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief UART8 DMA priority (0..3|lowest..highest).
+ * @note The priority level is used for both the TX and RX DMA channels but
+ * because of the channels ordering the RX channel has always priority
+ * over the TX channel.
+ */
+#if !defined(STM32_UART_UART8_DMA_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_UART_UART8_DMA_PRIORITY 0
+#endif
+
+/**
+ * @brief UART DMA error hook.
+ * @note The default action for DMA errors is a system halt because DMA
+ * error can only happen because programming errors.
+ */
+#if !defined(STM32_UART_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
+#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if STM32_UART_USE_USART1 && !STM32_HAS_USART1
+#error "USART1 not present in the selected device"
+#endif
+
+#if STM32_UART_USE_USART2 && !STM32_HAS_USART2
+#error "USART2 not present in the selected device"
+#endif
+
+#if STM32_UART_USE_USART3 && !STM32_HAS_USART3
+#error "USART3 not present in the selected device"
+#endif
+
+#if STM32_UART_USE_UART4 && !STM32_HAS_UART4
+#error "UART4 not present in the selected device"
+#endif
+
+#if STM32_UART_USE_UART5 && !STM32_HAS_UART5
+#error "UART5 not present in the selected device"
+#endif
+
+#if STM32_UART_USE_UART7 && !STM32_HAS_UART7
+#error "UART7 not present in the selected device"
+#endif
+
+#if STM32_UART_USE_UART8 && !STM32_HAS_UART8
+#error "UART8 not present in the selected device"
+#endif
+
+#if !STM32_UART_USE_USART1 && !STM32_UART_USE_USART2 && \
+ !STM32_UART_USE_USART3 && !STM32_UART_USE_UART4 && \
+ !STM32_UART_USE_UART5 && !STM32_UART_USE_USART6 && \
+ !STM32_UART_USE_UART7 && !STM32_UART_USE_UART8
+#error "UART driver activated but no USART/UART peripheral assigned"
+#endif
+
+#if !defined(STM32_USART1_SUPPRESS_ISR) && \
+ STM32_UART_USE_USART1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART1_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to USART1"
+#endif
+
+#if !defined(STM32_USART2_SUPPRESS_ISR) && \
+ STM32_UART_USE_USART2 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART2_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to USART2"
+#endif
+
+#if !defined(STM32_USART3_SUPPRESS_ISR) && \
+ STM32_UART_USE_USART3 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART3_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to USART3"
+#endif
+
+#if !defined(STM32_UART4_SUPPRESS_ISR) && \
+ STM32_UART_USE_UART4 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART4_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to UART4"
+#endif
+
+#if !defined(STM32_UART5_SUPPRESS_ISR) && \
+ STM32_UART_USE_UART5 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART5_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to UART5"
+#endif
+
+#if !defined(STM32_USART6_SUPPRESS_ISR) && \
+ STM32_UART_USE_USART6 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_USART6_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to USART6"
+#endif
+
+#if !defined(STM32_UART7_SUPPRESS_ISR) && \
+ STM32_UART_USE_UART7 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART7_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to UART7"
+#endif
+
+#if !defined(STM32_UART8_SUPPRESS_ISR) && \
+ STM32_UART_USE_UART8 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_UART_UART8_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to UART8"
+#endif
+
+/* Check on DMA priorities.*/
+#if STM32_UART_USE_USART1 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART1_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to USART1"
+#endif
+
+#if STM32_UART_USE_USART2 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART2_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to USART2"
+#endif
+
+#if STM32_UART_USE_USART3 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART3_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to USART3"
+#endif
+
+#if STM32_UART_USE_UART4 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART4_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to UART4"
+#endif
+
+#if STM32_UART_USE_UART5 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART5_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to UART5"
+#endif
+
+#if STM32_UART_USE_USART6 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_USART6_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to USART6"
+#endif
+
+#if STM32_UART_USE_UART7 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART7_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to UART7"
+#endif
+
+#if STM32_UART_USE_UART8 && \
+ !STM32_DMA_IS_VALID_PRIORITY(STM32_UART_UART8_DMA_PRIORITY)
+#error "Invalid DMA priority assigned to UART8"
+#endif
+
+/* Check on the presence of the DMA streams settings in mcuconf.h.*/
+#if STM32_UART_USE_USART1 && (!defined(STM32_UART_USART1_RX_DMA_STREAM) || \
+ !defined(STM32_UART_USART1_TX_DMA_STREAM))
+#error "USART1 DMA streams not defined"
+#endif
+
+#if STM32_UART_USE_USART2 && (!defined(STM32_UART_USART2_RX_DMA_STREAM) || \
+ !defined(STM32_UART_USART2_TX_DMA_STREAM))
+#error "USART2 DMA streams not defined"
+#endif
+
+#if STM32_UART_USE_USART3 && (!defined(STM32_UART_USART3_RX_DMA_STREAM) || \
+ !defined(STM32_UART_USART3_TX_DMA_STREAM))
+#error "USART3 DMA streams not defined"
+#endif
+
+#if STM32_UART_USE_UART4 && (!defined(STM32_UART_UART4_RX_DMA_STREAM) || \
+ !defined(STM32_UART_UART4_TX_DMA_STREAM))
+#error "UART4 DMA streams not defined"
+#endif
+
+#if STM32_UART_USE_UART5 && (!defined(STM32_UART_UART5_RX_DMA_STREAM) || \
+ !defined(STM32_UART_UART5_TX_DMA_STREAM))
+#error "UART5 DMA streams not defined"
+#endif
+
+#if STM32_UART_USE_USART6 && (!defined(STM32_UART_USART6_RX_DMA_STREAM) || \
+ !defined(STM32_UART_USART6_TX_DMA_STREAM))
+#error "USART6 DMA streams not defined"
+#endif
+
+#if STM32_UART_USE_UART7 && (!defined(STM32_UART_UART7_RX_DMA_STREAM) || \
+ !defined(STM32_UART_UART7_TX_DMA_STREAM))
+#error "UART7 DMA streams not defined"
+#endif
+
+#if STM32_UART_USE_UART8 && (!defined(STM32_UART_UART8_RX_DMA_STREAM) || \
+ !defined(STM32_UART_UART8_TX_DMA_STREAM))
+#error "UART8 DMA streams not defined"
+#endif
+
+/* Check on the validity of the assigned DMA channels.*/
+#if STM32_UART_USE_USART1 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART1_RX_DMA_STREAM)
+#error "Invalid DMA channel assigned to USART1 RX"
+#endif
+
+#if STM32_UART_USE_USART1 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART1_TX_DMA_STREAM)
+#error "Invalid DMA channel assigned to USART1 TX"
+#endif
+
+#if STM32_UART_USE_USART2 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART2_RX_DMA_STREAM)
+#error "Invalid DMA channel assigned to USART2 RX"
+#endif
+
+#if STM32_UART_USE_USART2 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART2_TX_DMA_STREAM)
+#error "Invalid DMA channel assigned to USART2 TX"
+#endif
+
+#if STM32_UART_USE_USART3 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART3_RX_DMA_STREAM)
+#error "Invalid DMA channel assigned to USART3 RX"
+#endif
+
+#if STM32_UART_USE_USART3 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART3_TX_DMA_STREAM)
+#error "Invalid DMA channel assigned to USART3 TX"
+#endif
+
+#if STM32_UART_USE_UART4 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART4_RX_DMA_STREAM)
+#error "Invalid DMA channel assigned to UART4 RX"
+#endif
+
+#if STM32_UART_USE_UART4 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART4_TX_DMA_STREAM)
+#error "Invalid DMA channel assigned to UART4 TX"
+#endif
+
+#if STM32_UART_USE_UART5 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART5_RX_DMA_STREAM)
+#error "Invalid DMA channel assigned to UART5 RX"
+#endif
+
+#if STM32_UART_USE_UART5 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART5_TX_DMA_STREAM)
+#error "Invalid DMA channel assigned to UART5 TX"
+#endif
+
+#if STM32_UART_USE_USART6 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART6_RX_DMA_STREAM)
+#error "Invalid DMA channel assigned to USART6 RX"
+#endif
+
+#if STM32_UART_USE_USART6 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_UART_USART6_TX_DMA_STREAM)
+#error "Invalid DMA channel assigned to USART6 TX"
+#endif
+
+#if STM32_UART_USE_UART7 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART7_RX_DMA_STREAM)
+#error "Invalid DMA channel assigned to UART7 RX"
+#endif
+
+#if STM32_UART_USE_UART7 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART7_TX_DMA_STREAM)
+#error "Invalid DMA channel assigned to UART7 TX"
+#endif
+
+#if STM32_UART_USE_UART8 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART8_RX_DMA_STREAM)
+#error "Invalid DMA channel assigned to UART8 RX"
+#endif
+
+#if STM32_UART_USE_UART8 && \
+ !STM32_DMA_IS_VALID_STREAM(STM32_UART_UART8_TX_DMA_STREAM)
+#error "Invalid DMA channel assigned to UART8 TX"
+#endif
+
+/* Devices without DMAMUX require an additional check.*/
+#if STM32_ADVANCED_DMA && !STM32_DMA_SUPPORTS_DMAMUX
+
+/* Check on the validity of the assigned DMA channels.*/
+#if STM32_UART_USE_USART1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_RX_DMA_STREAM, \
+ STM32_USART1_RX_DMA_MSK)
+#error "invalid DMA stream associated to USART1 RX"
+#endif
+
+#if STM32_UART_USE_USART1 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_USART1_TX_DMA_STREAM, \
+ STM32_USART1_TX_DMA_MSK)
+#error "invalid DMA stream associated to USART1 TX"
+#endif
+
+#if STM32_UART_USE_USART2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_RX_DMA_STREAM, \
+ STM32_USART2_RX_DMA_MSK)
+#error "invalid DMA stream associated to USART2 RX"
+#endif
+
+#if STM32_UART_USE_USART2 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_USART2_TX_DMA_STREAM, \
+ STM32_USART2_TX_DMA_MSK)
+#error "invalid DMA stream associated to USART2 TX"
+#endif
+
+#if STM32_UART_USE_USART3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_RX_DMA_STREAM, \
+ STM32_USART3_RX_DMA_MSK)
+#error "invalid DMA stream associated to USART3 RX"
+#endif
+
+#if STM32_UART_USE_USART3 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_USART3_TX_DMA_STREAM, \
+ STM32_USART3_TX_DMA_MSK)
+#error "invalid DMA stream associated to USART3 TX"
+#endif
+
+#if STM32_UART_USE_UART4 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_UART4_RX_DMA_STREAM, \
+ STM32_UART4_RX_DMA_MSK)
+#error "invalid DMA stream associated to UART4 RX"
+#endif
+
+#if STM32_UART_USE_UART4 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_UART4_TX_DMA_STREAM, \
+ STM32_UART4_TX_DMA_MSK)
+#error "invalid DMA stream associated to UART4 TX"
+#endif
+
+#if STM32_UART_USE_UART5 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_UART5_RX_DMA_STREAM, \
+ STM32_UART5_RX_DMA_MSK)
+#error "invalid DMA stream associated to UART5 RX"
+#endif
+
+#if STM32_UART_USE_UART5 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_UART5_TX_DMA_STREAM, \
+ STM32_UART5_TX_DMA_MSK)
+#error "invalid DMA stream associated to UART5 TX"
+#endif
+
+#if STM32_UART_USE_USART6 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_USART6_RX_DMA_STREAM, \
+ STM32_USART6_RX_DMA_MSK)
+#error "invalid DMA stream associated to USART6 RX"
+#endif
+
+#if STM32_UART_USE_USART6 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_USART6_TX_DMA_STREAM, \
+ STM32_USART6_TX_DMA_MSK)
+#error "invalid DMA stream associated to USART6 TX"
+#endif
+
+#if STM32_UART_USE_UART7 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_UART7_RX_DMA_STREAM, \
+ STM32_UART7_RX_DMA_MSK)
+#error "invalid DMA stream associated to UART7 RX"
+#endif
+
+#if STM32_UART_USE_UART7 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_UART7_TX_DMA_STREAM, \
+ STM32_UART7_TX_DMA_MSK)
+#error "invalid DMA stream associated to UART7 TX"
+#endif
+
+#if STM32_UART_USE_UART8 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_UART8_RX_DMA_STREAM, \
+ STM32_UART8_RX_DMA_MSK)
+#error "invalid DMA stream associated to UART8 RX"
+#endif
+
+#if STM32_UART_USE_UART8 && \
+ !STM32_DMA_IS_VALID_ID(STM32_UART_UART8_TX_DMA_STREAM, \
+ STM32_UART8_TX_DMA_MSK)
+#error "invalid DMA stream associated to UART8 TX"
+#endif
+
+#endif /* STM32_ADVANCED_DMA && !STM32_DMA_SUPPORTS_DMAMUX */
+
+#if !defined(STM32_DMA_REQUIRED)
+#define STM32_DMA_REQUIRED
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief UART driver condition flags type.
+ */
+typedef uint32_t uartflags_t;
+
+/**
+ * @brief Structure representing an UART driver.
+ */
+typedef struct UARTDriver UARTDriver;
+
+/**
+ * @brief Generic UART notification callback type.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+typedef void (*uartcb_t)(UARTDriver *uartp);
+
+/**
+ * @brief Character received UART notification callback type.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] c received character
+ */
+typedef void (*uartccb_t)(UARTDriver *uartp, uint16_t c);
+
+/**
+ * @brief Receive error UART notification callback type.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] e receive error mask
+ */
+typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e);
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+ /**
+ * @brief End of transmission buffer callback.
+ */
+ uartcb_t txend1_cb;
+ /**
+ * @brief Physical end of transmission callback.
+ */
+ uartcb_t txend2_cb;
+ /**
+ * @brief Receive buffer filled callback.
+ */
+ uartcb_t rxend_cb;
+ /**
+ * @brief Character received while out if the @p UART_RECEIVE state.
+ */
+ uartccb_t rxchar_cb;
+ /**
+ * @brief Receive error callback.
+ */
+ uartecb_t rxerr_cb;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Receiver timeout callback.
+ * @details Handles both idle and timeout interrupts depending on configured
+ * flags in CR registers and supported hardware features.
+ */
+ uartcb_t timeout_cb;
+ /**
+ * @brief Receiver timeout value in terms of number of bit duration.
+ * @details Set it to 0 when you want to handle idle interrupt instead of
+ * hardware timeout.
+ */
+ uint32_t timeout;
+ /**
+ * @brief Bit rate.
+ */
+ uint32_t speed;
+ /**
+ * @brief Initialization value for the CR1 register.
+ */
+ uint32_t cr1;
+ /**
+ * @brief Initialization value for the CR2 register.
+ */
+ uint32_t cr2;
+ /**
+ * @brief Initialization value for the CR3 register.
+ */
+ uint32_t cr3;
+} UARTConfig;
+
+/**
+ * @brief Structure representing an UART driver.
+ */
+struct UARTDriver {
+ /**
+ * @brief Driver state.
+ */
+ uartstate_t state;
+ /**
+ * @brief Transmitter state.
+ */
+ uarttxstate_t txstate;
+ /**
+ * @brief Receiver state.
+ */
+ uartrxstate_t rxstate;
+ /**
+ * @brief Current configuration data.
+ */
+ const UARTConfig *config;
+#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Synchronization flag for transmit operations.
+ */
+ bool early;
+ /**
+ * @brief Waiting thread on RX.
+ */
+ thread_reference_t threadrx;
+ /**
+ * @brief Waiting thread on TX.
+ */
+ thread_reference_t threadtx;
+#endif /* UART_USE_WAIT */
+#if (UART_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Mutex protecting the peripheral.
+ */
+ mutex_t mutex;
+#endif /* UART_USE_MUTUAL_EXCLUSION */
+#if defined(UART_DRIVER_EXT_FIELDS)
+ UART_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Pointer to the USART registers block.
+ */
+ USART_TypeDef *usart;
+ /**
+ * @brief Clock frequency for the associated USART/UART.
+ */
+ uint32_t clock;
+ /**
+ * @brief Receive DMA mode bit mask.
+ */
+ uint32_t dmarxmode;
+ /**
+ * @brief Send DMA mode bit mask.
+ */
+ uint32_t dmatxmode;
+ /**
+ * @brief Receive DMA channel.
+ */
+ const stm32_dma_stream_t *dmarx;
+ /**
+ * @brief Transmit DMA channel.
+ */
+ const stm32_dma_stream_t *dmatx;
+ /**
+ * @brief Default receive buffer while into @p UART_RX_IDLE state.
+ */
+ volatile uint16_t rxbuf;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_UART_USE_USART1 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD1;
+#endif
+
+#if STM32_UART_USE_USART2 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD2;
+#endif
+
+#if STM32_UART_USE_USART3 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD3;
+#endif
+
+#if STM32_UART_USE_UART4 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD4;
+#endif
+
+#if STM32_UART_USE_UART5 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD5;
+#endif
+
+#if STM32_UART_USE_USART6 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD6;
+#endif
+
+#if STM32_UART_USE_UART7 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD7;
+#endif
+
+#if STM32_UART_USE_UART8 && !defined(__DOXYGEN__)
+extern UARTDriver UARTD8;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void uart_lld_init(void);
+ void uart_lld_start(UARTDriver *uartp);
+ void uart_lld_stop(UARTDriver *uartp);
+ void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf);
+ size_t uart_lld_stop_send(UARTDriver *uartp);
+ void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf);
+ size_t uart_lld_stop_receive(UARTDriver *uartp);
+ void uart_lld_serve_interrupt(UARTDriver *uartp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_UART */
+
+#endif /* HAL_UART_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_lpuart1.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_lpuart1.inc
new file mode 100644
index 0000000..223ce2e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_lpuart1.inc
@@ -0,0 +1,110 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv2/stm32_lpuart1.inc
+ * @brief Shared LPUART1 handler.
+ *
+ * @addtogroup STM32_LPUART1_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_LPUART1)
+#error "STM32_HAS_LPUART1 not defined in registry"
+#endif
+
+#if STM32_HAS_LPUART1
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_LPUART1_PRIORITY)
+#error "STM32_IRQ_LPUART1_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_LPUART1_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_LPUART1_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_LPUART1 */
+
+/* Other checks.*/
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_LPUART1)
+#define STM32_LPUART1_IS_USED TRUE
+#else
+#define STM32_LPUART1_IS_USED FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void lpuart1_irq_init(void) {
+#if STM32_LPUART1_IS_USED
+ nvicEnableVector(STM32_LPUART1_NUMBER, STM32_IRQ_LPUART1_PRIORITY);
+#endif
+}
+
+static inline void lpuart1_irq_deinit(void) {
+#if STM32_LPUART1_IS_USED
+ nvicDisableVector(STM32_LPUART1_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_LPUART1_IS_USED || defined(__DOXYGEN__)
+/**
+ * @brief LPUART1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_LPUART1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if STM32_SERIAL_USE_LPUART1
+ sd_lld_serve_interrupt(&LPSD1);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_uart4.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_uart4.inc
new file mode 100644
index 0000000..5dd7b51
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_uart4.inc
@@ -0,0 +1,121 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv2/stm32_uart4.inc
+ * @brief Shared UART4 handler.
+ *
+ * @addtogroup STM32_UART4_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_UART4)
+#error "STM32_HAS_UART4 not defined in registry"
+#endif
+
+#if STM32_HAS_UART4
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_UART4_PRIORITY)
+#error "STM32_IRQ_UART4_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_UART4_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_UART4_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_UART4 */
+
+/* Other checks.*/
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_UART4) && \
+ (HAL_USE_UART && STM32_UART_USE_UART4)
+#error "UART4 used by multiple drivers"
+#endif
+
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_UART4) || \
+ (HAL_USE_UART && STM32_UART_USE_UART4)
+#define STM32_UART4_IS_USED TRUE
+#else
+#define STM32_UART4_IS_USED FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void uart4_irq_init(void) {
+#if STM32_UART4_IS_USED
+ nvicEnableVector(STM32_UART4_NUMBER, STM32_IRQ_UART4_PRIORITY);
+#endif
+}
+
+static inline void uart4_irq_deinit(void) {
+#if STM32_UART4_IS_USED
+ nvicDisableVector(STM32_UART4_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_UART4_IS_USED || defined(__DOXYGEN__)
+/**
+ * @brief UART4 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART4_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if STM32_SERIAL_USE_UART4
+ sd_lld_serve_interrupt(&SD4);
+#endif
+#endif
+#if HAL_USE_UART
+#if STM32_UART_USE_UART4
+ uart_lld_serve_interrupt(&UARTD4);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_uart5.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_uart5.inc
new file mode 100644
index 0000000..b382d84
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_uart5.inc
@@ -0,0 +1,121 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv2/stm32_uart5.inc
+ * @brief Shared UART5 handler.
+ *
+ * @addtogroup STM32_UART5_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_UART5)
+#error "STM32_HAS_UART5 not defined in registry"
+#endif
+
+#if STM32_HAS_UART5
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_UART5_PRIORITY)
+#error "STM32_IRQ_UART5_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_UART5_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_UART5_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_UART5 */
+
+/* Other checks.*/
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_UART5) && \
+ (HAL_USE_UART && STM32_UART_USE_UART5)
+#error "UART5 used by multiple drivers"
+#endif
+
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_UART5) || \
+ (HAL_USE_UART && STM32_UART_USE_UART5)
+#define STM32_UART5_IS_USED TRUE
+#else
+#define STM32_UART5_IS_USED FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void uart5_irq_init(void) {
+#if STM32_UART5_IS_USED
+ nvicEnableVector(STM32_UART5_NUMBER, STM32_IRQ_UART5_PRIORITY);
+#endif
+}
+
+static inline void uart5_irq_deinit(void) {
+#if STM32_UART5_IS_USED
+ nvicDisableVector(STM32_UART5_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_UART5_IS_USED || defined(__DOXYGEN__)
+/**
+ * @brief UART5 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART5_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if STM32_SERIAL_USE_UART5
+ sd_lld_serve_interrupt(&SD5);
+#endif
+#endif
+#if HAL_USE_UART
+#if STM32_UART_USE_UART5
+ uart_lld_serve_interrupt(&UARTD5);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_uart7.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_uart7.inc
new file mode 100644
index 0000000..2ec791e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_uart7.inc
@@ -0,0 +1,121 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv2/stm32_uart7.inc
+ * @brief Shared UART7 handler.
+ *
+ * @addtogroup STM32_UART7_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_UART7)
+#error "STM32_HAS_UART7 not defined in registry"
+#endif
+
+#if STM32_HAS_UART7
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_UART7_PRIORITY)
+#error "STM32_IRQ_UART7_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_UART7_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_UART7_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_UART7 */
+
+/* Other checks.*/
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_UART7) && \
+ (HAL_USE_UART && STM32_UART_USE_UART7)
+#error "UART7 used by multiple drivers"
+#endif
+
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_UART7) || \
+ (HAL_USE_UART && STM32_UART_USE_UART7)
+#define STM32_UART7_IS_USED TRUE
+#else
+#define STM32_UART7_IS_USED FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void uart7_irq_init(void) {
+#if STM32_UART7_IS_USED
+ nvicEnableVector(STM32_UART7_NUMBER, STM32_IRQ_UART7_PRIORITY);
+#endif
+}
+
+static inline void uart7_irq_deinit(void) {
+#if STM32_UART7_IS_USED
+ nvicDisableVector(STM32_UART7_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_UART7_IS_USED || defined(__DOXYGEN__)
+/**
+ * @brief UART7 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART7_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if STM32_SERIAL_USE_UART7
+ sd_lld_serve_interrupt(&SD7);
+#endif
+#endif
+#if HAL_USE_UART
+#if STM32_UART_USE_UART7
+ uart_lld_serve_interrupt(&UARTD7);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_uart8.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_uart8.inc
new file mode 100644
index 0000000..8958431
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_uart8.inc
@@ -0,0 +1,121 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv2/stm32_uart8.inc
+ * @brief Shared UART8 handler.
+ *
+ * @addtogroup STM32_UART8_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_UART8)
+#error "STM32_HAS_UART8 not defined in registry"
+#endif
+
+#if STM32_HAS_UART8
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_UART8_PRIORITY)
+#error "STM32_IRQ_UART8_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_UART8_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_UART8_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_UART8 */
+
+/* Other checks.*/
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_UART8) && \
+ (HAL_USE_UART && STM32_UART_USE_UART8)
+#error "UART8 used by multiple drivers"
+#endif
+
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_UART8) || \
+ (HAL_USE_UART && STM32_UART_USE_UART8)
+#define STM32_UART8_IS_USED TRUE
+#else
+#define STM32_UART8_IS_USED FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void uart8_irq_init(void) {
+#if STM32_UART8_IS_USED
+ nvicEnableVector(STM32_UART8_NUMBER, STM32_IRQ_UART8_PRIORITY);
+#endif
+}
+
+static inline void uart8_irq_deinit(void) {
+#if STM32_UART8_IS_USED
+ nvicDisableVector(STM32_UART8_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_UART8_IS_USED || defined(__DOXYGEN__)
+/**
+ * @brief UART8 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_UART8_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if STM32_SERIAL_USE_UART8
+ sd_lld_serve_interrupt(&SD8);
+#endif
+#endif
+#if HAL_USE_UART
+#if STM32_UART_USE_UART8
+ uart_lld_serve_interrupt(&UARTD8);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_usart1.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_usart1.inc
new file mode 100644
index 0000000..19aac10
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_usart1.inc
@@ -0,0 +1,121 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv2/stm32_usart1.inc
+ * @brief Shared USART1 handler.
+ *
+ * @addtogroup STM32_USART1_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_USART1)
+#error "STM32_HAS_USART1 not defined in registry"
+#endif
+
+#if STM32_HAS_USART1
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_USART1_PRIORITY)
+#error "STM32_IRQ_USART1_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_USART1_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_USART1_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_USART1 */
+
+/* Other checks.*/
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_USART1) && \
+ (HAL_USE_UART && STM32_UART_USE_USART1)
+#error "USART1 used by multiple drivers"
+#endif
+
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_USART1) || \
+ (HAL_USE_UART && STM32_UART_USE_USART1)
+#define STM32_USART1_IS_USED TRUE
+#else
+#define STM32_USART1_IS_USED FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void usart1_irq_init(void) {
+#if STM32_USART1_IS_USED
+ nvicEnableVector(STM32_USART1_NUMBER, STM32_IRQ_USART1_PRIORITY);
+#endif
+}
+
+static inline void usart1_irq_deinit(void) {
+#if STM32_USART1_IS_USED
+ nvicDisableVector(STM32_USART1_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_USART1_IS_USED|| defined(__DOXYGEN__)
+/**
+ * @brief USART1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if STM32_SERIAL_USE_USART1
+ sd_lld_serve_interrupt(&SD1);
+#endif
+#endif
+#if HAL_USE_UART
+#if STM32_UART_USE_USART1
+ uart_lld_serve_interrupt(&UARTD1);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_usart2.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_usart2.inc
new file mode 100644
index 0000000..c4b9000
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_usart2.inc
@@ -0,0 +1,121 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv2/stm32_usart2.inc
+ * @brief Shared USART2 handler.
+ *
+ * @addtogroup STM32_USART2_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_USART2)
+#error "STM32_HAS_USART2 not defined in registry"
+#endif
+
+#if STM32_HAS_USART2
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_USART2_PRIORITY)
+#error "STM32_IRQ_USART2_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_USART2_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_USART2_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_USART2 */
+
+/* Other checks.*/
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_USART2) && \
+ (HAL_USE_UART && STM32_UART_USE_USART2)
+#error "USART2 used by multiple drivers"
+#endif
+
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_USART2) || \
+ (HAL_USE_UART && STM32_UART_USE_USART2)
+#define STM32_USART2_IS_USED TRUE
+#else
+#define STM32_USART2_IS_USED FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void usart2_irq_init(void) {
+#if STM32_USART2_IS_USED
+ nvicEnableVector(STM32_USART2_NUMBER, STM32_IRQ_USART2_PRIORITY);
+#endif
+}
+
+static inline void usart2_irq_deinit(void) {
+#if STM32_USART2_IS_USED
+ nvicDisableVector(STM32_USART2_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_USART2_IS_USED || defined(__DOXYGEN__)
+/**
+ * @brief USART2 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if STM32_SERIAL_USE_USART2
+ sd_lld_serve_interrupt(&SD2);
+#endif
+#endif
+#if HAL_USE_UART
+#if STM32_UART_USE_USART2
+ uart_lld_serve_interrupt(&UARTD2);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_usart3.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_usart3.inc
new file mode 100644
index 0000000..ff5dbda
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_usart3.inc
@@ -0,0 +1,121 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv2/stm32_usart3.inc
+ * @brief Shared USART3 handler.
+ *
+ * @addtogroup STM32_USART3_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_USART3)
+#error "STM32_HAS_USART3 not defined in registry"
+#endif
+
+#if STM32_HAS_USART3
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_USART3_PRIORITY)
+#error "STM32_IRQ_USART3_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_USART3_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_USART3_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_USART3 */
+
+/* Other checks.*/
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_USART3) && \
+ (HAL_USE_UART && STM32_UART_USE_USART3)
+#error "USART3 used by multiple drivers"
+#endif
+
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_USART3) || \
+ (HAL_USE_UART && STM32_UART_USE_USART3)
+#define STM32_USART3_IS_USED TRUE
+#else
+#define STM32_USART3_IS_USED FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void usart3_irq_init(void) {
+#if STM32_USART3_IS_USED
+ nvicEnableVector(STM32_USART3_NUMBER, STM32_IRQ_USART3_PRIORITY);
+#endif
+}
+
+static inline void usart3_irq_deinit(void) {
+#if STM32_USART3_IS_USED
+ nvicDisableVector(STM32_USART3_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_USART3_IS_USED || defined(__DOXYGEN__)
+/**
+ * @brief USART3 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART3_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if STM32_SERIAL_USE_USART3
+ sd_lld_serve_interrupt(&SD3);
+#endif
+#endif
+#if HAL_USE_UART
+#if STM32_UART_USE_USART3
+ uart_lld_serve_interrupt(&UARTD3);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_usart3_4_lp1.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_usart3_4_lp1.inc
new file mode 100644
index 0000000..596237f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_usart3_4_lp1.inc
@@ -0,0 +1,157 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv2/stm32_usart3_4_lp1.inc
+ * @brief Shared USART3, USART4, LPUART1 handler.
+ *
+ * @addtogroup STM32_USART3_4_LP1_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_USART3)
+#error "STM32_HAS_USART3 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_UART4)
+#error "STM32_HAS_UART4 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_LPUART1)
+#error "STM32_HAS_LPUART1 not defined in registry"
+#endif
+
+#if STM32_HAS_USART3 || STM32_HAS_UART4 || STM32_HAS_LPUART1
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_USART3_4_LP1_PRIORITY)
+#error "STM32_IRQ_USART3_4_LP1_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_USART3_4_LP1_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_USART3_4_LP1_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_USART3 || STM32_HAS_UART4 || STM32_HAS_LPUART1 */
+
+/* Other checks.*/
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_USART3) && \
+ (HAL_USE_UART && STM32_UART_USE_USART3)
+#error "USART3 used by multiple drivers"
+#endif
+
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_UART4) && \
+ (HAL_USE_UART && STM32_UART_USE_UART4)
+#error "USART4 used by multiple drivers"
+#endif
+
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_USART3) || \
+ (HAL_USE_UART && STM32_UART_USE_USART3)
+#define STM32_USART3_IS_USED TRUE
+#else
+#define STM32_USART3_IS_USED FALSE
+#endif
+
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_UART4) || \
+ (HAL_USE_UART && STM32_UART_USE_UART4)
+#define STM32_USART4_IS_USED TRUE
+#else
+#define STM32_USART4_IS_USED FALSE
+#endif
+
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_LPUART1)
+#define STM32_LPUART1_IS_USED TRUE
+#else
+#define STM32_LPUART1_IS_USED FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void usart3_usart4_lpuart1_irq_init(void) {
+#if STM32_USART3_IS_USED || STM32_USART4_IS_USED || STM32_LPUART1_IS_USED
+ nvicEnableVector(STM32_USART3_4_LP1_NUMBER, STM32_IRQ_USART3_4_LP1_PRIORITY);
+#endif
+}
+
+static inline void usart3_usart4_lpuart1_irq_deinit(void) {
+#if STM32_USART3_IS_USED || STM32_USART4_IS_USED || STM32_LPUART1_IS_USED
+ nvicDisableVector(STM32_USART3_4_LP1_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_USART3_IS_USED || STM32_USART4_IS_USED || \
+ STM32_LPUART1_IS_USED || defined(__DOXYGEN__)
+/**
+ * @brief USART4, USART5, LPUART1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART3_4_LP1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if STM32_SERIAL_USE_USART3
+ sd_lld_serve_interrupt(&SD3);
+#endif
+#if STM32_SERIAL_USE_UART4
+ sd_lld_serve_interrupt(&SD4);
+#endif
+#if STM32_SERIAL_USE_LPUART1
+ sd_lld_serve_interrupt(&LPSD1);
+#endif
+#endif
+#if HAL_USE_UART
+#if STM32_UART_USE_USART3
+ uart_lld_serve_interrupt(&UARTD3);
+#endif
+#if STM32_UART_USE_UART4
+ uart_lld_serve_interrupt(&UARTD4);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_usart4_5.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_usart4_5.inc
new file mode 100644
index 0000000..7d003a3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_usart4_5.inc
@@ -0,0 +1,144 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv2/stm32_usart4_5.inc
+ * @brief Shared USART4, USART5 handler.
+ *
+ * @addtogroup STM32_USART4_5_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_UART4)
+#error "STM32_HAS_UART4 not defined in registry"
+#endif
+
+#if !defined(STM32_HAS_UART5)
+#error "STM32_HAS_UART5 not defined in registry"
+#endif
+
+#if STM32_HAS_UART4 || STM32_HAS_UART5
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_USART4_5_PRIORITY)
+#error "STM32_IRQ_USART4_5_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_USART4_5_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_USART4_5_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_UART4 || STM32_HAS_UART5 */
+
+/* Other checks.*/
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_UART4) && \
+ (HAL_USE_UART && STM32_UART_USE_UART4)
+#error "USART4 used by multiple drivers"
+#endif
+
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_UART5) && \
+ (HAL_USE_UART && STM32_UART_USE_UART5)
+#error "USART5 used by multiple drivers"
+#endif
+
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_UART4) || \
+ (HAL_USE_UART && STM32_UART_USE_UART4)
+#define STM32_USART4_IS_USED TRUE
+#else
+#define STM32_USART4_IS_USED FALSE
+#endif
+
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_UART5) || \
+ (HAL_USE_UART && STM32_UART_USE_UART45)
+#define STM32_USART5_IS_USED TRUE
+#else
+#define STM32_USART5_IS_USED FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void usart4_usart5_irq_init(void) {
+#if STM32_USART4_IS_USED || STM32_USART5_IS_USED
+ nvicEnableVector(STM32_USART4_5_NUMBER, STM32_IRQ_USART4_5_PRIORITY);
+#endif
+}
+
+static inline void usart4_usart5_irq_deinit(void) {
+#if STM32_USART4_IS_USED || STM32_USART5_IS_USED
+ nvicDisableVector(STM32_USART4_5_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_USART4_IS_USED || STM32_USART5_IS_USED || \
+ defined(__DOXYGEN__)
+/**
+ * @brief USART4, USART5, LPUART1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART4_5_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if STM32_SERIAL_USE_UART4
+ sd_lld_serve_interrupt(&SD4);
+#endif
+#if STM32_SERIAL_USE_UART5
+ sd_lld_serve_interrupt(&SD5);
+#endif
+#endif
+#if HAL_USE_UART
+#if STM32_UART_USE_UART4
+ uart_lld_serve_interrupt(&UARTD4);
+#endif
+#if STM32_UART_USE_UART5
+ uart_lld_serve_interrupt(&UARTD5);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_usart6.inc b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_usart6.inc
new file mode 100644
index 0000000..ea812a8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USARTv2/stm32_usart6.inc
@@ -0,0 +1,121 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USARTv2/stm32_usart6.inc
+ * @brief Shared USART6 handler.
+ *
+ * @addtogroup STM32_USART6_HANDLER
+ * @{
+ */
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Registry checks for robustness.*/
+#if !defined(STM32_HAS_USART6)
+#error "STM32_HAS_USART6 not defined in registry"
+#endif
+
+#if STM32_HAS_USART6
+
+/* Priority settings checks.*/
+#if !defined(STM32_IRQ_USART6_PRIORITY)
+#error "STM32_IRQ_USART6_PRIORITY not defined in mcuconf.h"
+#endif
+
+#if !OSAL_IRQ_IS_VALID_PRIORITY(STM32_IRQ_USART6_PRIORITY)
+#error "Invalid IRQ priority assigned to STM32_IRQ_USART6_PRIORITY"
+#endif
+
+#endif /* STM32_HAS_USART6 */
+
+/* Other checks.*/
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_USART6) && \
+ (HAL_USE_UART && STM32_UART_USE_USART6)
+#error "USART6 used by multiple drivers"
+#endif
+
+#if (HAL_USE_SERIAL && STM32_SERIAL_USE_USART6) || \
+ (HAL_USE_UART && STM32_UART_USE_USART6)
+#define STM32_USART6_IS_USED TRUE
+#else
+#define STM32_USART6_IS_USED FALSE
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void usart6_irq_init(void) {
+#if STM32_USART6_IS_USED
+ nvicEnableVector(STM32_USART6_NUMBER, STM32_IRQ_USART6_PRIORITY);
+#endif
+}
+
+static inline void usart6_irq_deinit(void) {
+#if STM32_USART6_IS_USED
+ nvicDisableVector(STM32_USART6_NUMBER);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_USART6_IS_USED || defined(__DOXYGEN__)
+/**
+ * @brief USART6 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USART6_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+#if HAL_USE_SERIAL
+#if STM32_SERIAL_USE_USART6
+ sd_lld_serve_interrupt(&SD6);
+#endif
+#endif
+#if HAL_USE_UART
+#if STM32_UART_USE_USART6
+ uart_lld_serve_interrupt(&UARTD6);
+#endif
+#endif
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USBv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USBv1/driver.mk
new file mode 100644
index 0000000..1a6d862
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USBv1/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_USB TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.c
new file mode 100644
index 0000000..20607b7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.c
@@ -0,0 +1,874 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USBv1/hal_usb_lld.c
+ * @brief STM32 USB subsystem low level driver source.
+ *
+ * @addtogroup USB
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+
+#if HAL_USE_USB || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define BTABLE_ADDR 0x0000
+
+#define EPR_EP_TYPE_IS_ISO(bits) ((bits & EPR_EP_TYPE_MASK) == EPR_EP_TYPE_ISO)
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief USB1 driver identifier.*/
+#if STM32_USB_USE_USB1 || defined(__DOXYGEN__)
+USBDriver USBD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief EP0 state.
+ * @note It is an union because IN and OUT endpoints are never used at the
+ * same time for EP0.
+ */
+static union {
+ /**
+ * @brief IN EP0 state.
+ */
+ USBInEndpointState in;
+ /**
+ * @brief OUT EP0 state.
+ */
+ USBOutEndpointState out;
+} ep0_state;
+
+/**
+ * @brief Buffer for the EP0 setup packets.
+ */
+static uint8_t ep0setup_buffer[8];
+
+/**
+ * @brief EP0 initialization structure.
+ */
+static const USBEndpointConfig ep0config = {
+ USB_EP_MODE_TYPE_CTRL,
+ _usb_ep0setup,
+ _usb_ep0in,
+ _usb_ep0out,
+ 0x40,
+ 0x40,
+ &ep0_state.in,
+ &ep0_state.out,
+ 1,
+ ep0setup_buffer
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Resets the packet memory allocator.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ */
+static void usb_pm_reset(USBDriver *usbp) {
+
+ /* The first 64 bytes are reserved for the descriptors table. The effective
+ available RAM for endpoint buffers is just 448 bytes.*/
+ usbp->pmnext = 64;
+}
+
+/**
+ * @brief Resets the packet memory allocator.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] size size of the packet buffer to allocate
+ * @return The packet buffer address.
+ */
+static uint32_t usb_pm_alloc(USBDriver *usbp, size_t size) {
+ uint32_t next;
+
+ next = usbp->pmnext;
+ usbp->pmnext += (size + 1) & ~1;
+ osalDbgAssert(usbp->pmnext <= STM32_USB_PMA_SIZE, "PMA overflow");
+ return next;
+}
+
+/**
+ * @brief Reads from a dedicated packet buffer.
+ *
+ * @param[in] ep endpoint number
+ * @param[out] buf buffer where to copy the packet data
+ * @return The size of the receivee packet.
+ *
+ * @notapi
+ */
+static size_t usb_packet_read_to_buffer(usbep_t ep, uint8_t *buf) {
+ size_t i, n;
+ stm32_usb_descriptor_t *udp = USB_GET_DESCRIPTOR(ep);
+ stm32_usb_pma_t *pmap = USB_ADDR2PTR(udp->RXADDR0);
+#if STM32_USB_USE_ISOCHRONOUS
+ uint32_t epr = STM32_USB->EPR[ep];
+
+ /* Double buffering is always enabled for isochronous endpoints, and
+ although we overlap the two buffers for simplicity, we still need
+ to read from the right counter. The DTOG_RX bit indicates the buffer
+ that is currently in use by the USB peripheral, that is, the buffer
+ in which the next received packet will be stored, so we need to
+ read the counter of the OTHER buffer, which is where the last
+ received packet was stored.*/
+ if (EPR_EP_TYPE_IS_ISO(epr) && !(epr & EPR_DTOG_RX))
+ n = (size_t)udp->RXCOUNT1 & RXCOUNT_COUNT_MASK;
+ else
+ n = (size_t)udp->RXCOUNT0 & RXCOUNT_COUNT_MASK;
+#else
+ n = (size_t)udp->RXCOUNT0 & RXCOUNT_COUNT_MASK;
+#endif
+
+ i = n;
+
+#if STM32_USB_USE_FAST_COPY
+ while (i >= 16) {
+ uint32_t w;
+
+ w = *(pmap + 0);
+ *(buf + 0) = (uint8_t)w;
+ *(buf + 1) = (uint8_t)(w >> 8);
+ w = *(pmap + 1);
+ *(buf + 2) = (uint8_t)w;
+ *(buf + 3) = (uint8_t)(w >> 8);
+ w = *(pmap + 2);
+ *(buf + 4) = (uint8_t)w;
+ *(buf + 5) = (uint8_t)(w >> 8);
+ w = *(pmap + 3);
+ *(buf + 6) = (uint8_t)w;
+ *(buf + 7) = (uint8_t)(w >> 8);
+ w = *(pmap + 4);
+ *(buf + 8) = (uint8_t)w;
+ *(buf + 9) = (uint8_t)(w >> 8);
+ w = *(pmap + 5);
+ *(buf + 10) = (uint8_t)w;
+ *(buf + 11) = (uint8_t)(w >> 8);
+ w = *(pmap + 6);
+ *(buf + 12) = (uint8_t)w;
+ *(buf + 13) = (uint8_t)(w >> 8);
+ w = *(pmap + 7);
+ *(buf + 14) = (uint8_t)w;
+ *(buf + 15) = (uint8_t)(w >> 8);
+
+ i -= 16;
+ buf += 16;
+ pmap += 8;
+ }
+#endif /* STM32_USB_USE_FAST_COPY */
+
+ while (i >= 2) {
+ uint32_t w = *pmap++;
+ *buf++ = (uint8_t)w;
+ *buf++ = (uint8_t)(w >> 8);
+ i -= 2;
+ }
+
+ if (i >= 1) {
+ *buf = (uint8_t)*pmap;
+ }
+
+ return n;
+}
+
+/**
+ * @brief Writes to a dedicated packet buffer.
+ *
+ * @param[in] ep endpoint number
+ * @param[in] buf buffer where to fetch the packet data
+ * @param[in] n maximum number of bytes to copy. This value must
+ * not exceed the maximum packet size for this endpoint.
+ *
+ * @notapi
+ */
+static void usb_packet_write_from_buffer(usbep_t ep,
+ const uint8_t *buf,
+ size_t n) {
+ stm32_usb_descriptor_t *udp = USB_GET_DESCRIPTOR(ep);
+ stm32_usb_pma_t *pmap = USB_ADDR2PTR(udp->TXADDR0);
+ int i = (int)n;
+
+#if STM32_USB_USE_ISOCHRONOUS
+ uint32_t epr = STM32_USB->EPR[ep];
+
+ /* Double buffering is always enabled for isochronous endpoints, and
+ although we overlap the two buffers for simplicity, we still need
+ to write to the right counter. The DTOG_TX bit indicates the buffer
+ that is currently in use by the USB peripheral, that is, the buffer
+ from which the next packet will be sent, so we need to write the
+ counter of that buffer.*/
+ if (EPR_EP_TYPE_IS_ISO(epr) && (epr & EPR_DTOG_TX))
+ udp->TXCOUNT1 = (stm32_usb_pma_t)n;
+ else
+ udp->TXCOUNT0 = (stm32_usb_pma_t)n;
+#else
+ udp->TXCOUNT0 = (stm32_usb_pma_t)n;
+#endif
+
+#if STM32_USB_USE_FAST_COPY
+ while (i >= 16) {
+ uint32_t w;
+
+ w = *(buf + 0);
+ w |= *(buf + 1) << 8;
+ *(pmap + 0) = (stm32_usb_pma_t)w;
+ w = *(buf + 2);
+ w |= *(buf + 3) << 8;
+ *(pmap + 1) = (stm32_usb_pma_t)w;
+ w = *(buf + 4);
+ w |= *(buf + 5) << 8;
+ *(pmap + 2) = (stm32_usb_pma_t)w;
+ w = *(buf + 6);
+ w |= *(buf + 7) << 8;
+ *(pmap + 3) = (stm32_usb_pma_t)w;
+ w = *(buf + 8);
+ w |= *(buf + 9) << 8;
+ *(pmap + 4) = (stm32_usb_pma_t)w;
+ w = *(buf + 10);
+ w |= *(buf + 11) << 8;
+ *(pmap + 5) = (stm32_usb_pma_t)w;
+ w = *(buf + 12);
+ w |= *(buf + 13) << 8;
+ *(pmap + 6) = (stm32_usb_pma_t)w;
+ w = *(buf + 14);
+ w |= *(buf + 15) << 8;
+ *(pmap + 7) = (stm32_usb_pma_t)w;
+
+ i -= 16;
+ buf += 16;
+ pmap += 8;
+ }
+#endif /* STM32_USB_USE_FAST_COPY */
+
+ while (i > 0) {
+ uint32_t w;
+
+ w = *buf++;
+ w |= *buf++ << 8;
+ *pmap++ = (stm32_usb_pma_t)w;
+ i -= 2;
+ }
+}
+
+/**
+ * @brief Common ISR code, serves the EP-related interrupts.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+static void usb_serve_endpoints(USBDriver *usbp, uint32_t ep) {
+ size_t n;
+ uint32_t epr = STM32_USB->EPR[ep];
+ const USBEndpointConfig *epcp = usbp->epc[ep];
+
+ if (epr & EPR_CTR_TX) {
+ /* IN endpoint, transmission.*/
+ USBInEndpointState *isp = epcp->in_state;
+
+ EPR_CLEAR_CTR_TX(ep);
+
+ isp->txcnt += isp->txlast;
+ n = isp->txsize - isp->txcnt;
+ if (n > 0) {
+ /* Transfer not completed, there are more packets to send.*/
+ if (n > epcp->in_maxsize)
+ n = epcp->in_maxsize;
+
+ /* Writes the packet from the defined buffer.*/
+ isp->txbuf += isp->txlast;
+ isp->txlast = n;
+ usb_packet_write_from_buffer(ep, isp->txbuf, n);
+
+ /* Starting IN operation.*/
+ EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID);
+ }
+ else {
+ /* Transfer completed, invokes the callback.*/
+ _usb_isr_invoke_in_cb(usbp, ep);
+ }
+ }
+ if (epr & EPR_CTR_RX) {
+ /* OUT endpoint, receive.*/
+
+ EPR_CLEAR_CTR_RX(ep);
+
+ if (epr & EPR_SETUP) {
+ /* Setup packets handling, setup packets are handled using a
+ specific callback.*/
+ _usb_isr_invoke_setup_cb(usbp, ep);
+ }
+ else {
+ USBOutEndpointState *osp = epcp->out_state;
+
+ /* Reads the packet into the defined buffer.*/
+ n = usb_packet_read_to_buffer(ep, osp->rxbuf);
+ osp->rxbuf += n;
+
+ /* Transaction data updated.*/
+ osp->rxcnt += n;
+ osp->rxsize -= n;
+ osp->rxpkts -= 1;
+
+ /* The transaction is completed if the specified number of packets
+ has been received or the current packet is a short packet.*/
+ if ((n < epcp->out_maxsize) || (osp->rxpkts == 0)) {
+ /* Transfer complete, invokes the callback.*/
+ _usb_isr_invoke_out_cb(usbp, ep);
+ }
+ else {
+ /* Transfer not complete, there are more packets to receive.*/
+ EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID);
+ }
+ }
+ }
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#if STM32_USB_USE_USB1 || defined(__DOXYGEN__)
+#if STM32_USB1_HP_NUMBER != STM32_USB1_LP_NUMBER
+#if STM32_USB_USE_ISOCHRONOUS
+/**
+ * @brief USB high priority interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USB1_HP_HANDLER) {
+ uint32_t istr;
+ USBDriver *usbp = &USBD1;
+
+ OSAL_IRQ_PROLOGUE();
+
+ /* Endpoint events handling.*/
+ istr = STM32_USB->ISTR;
+ while (istr & ISTR_CTR) {
+ usb_serve_endpoints(usbp, istr & ISTR_EP_ID_MASK);
+ istr = STM32_USB->ISTR;
+ }
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* STM32_USB_USE_ISOCHRONOUS */
+#endif /* STM32_USB1_LP_NUMBER != STM32_USB1_HP_NUMBER */
+
+/**
+ * @brief USB low priority interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(STM32_USB1_LP_HANDLER) {
+ uint32_t istr;
+ USBDriver *usbp = &USBD1;
+
+ OSAL_IRQ_PROLOGUE();
+
+ istr = STM32_USB->ISTR;
+
+ /* USB bus reset condition handling.*/
+ if (istr & ISTR_RESET) {
+ STM32_USB->ISTR = ~ISTR_RESET;
+
+ _usb_reset(usbp);
+ }
+
+ /* USB bus SUSPEND condition handling.*/
+ if (istr & ISTR_SUSP) {
+ STM32_USB->CNTR |= CNTR_FSUSP;
+#if STM32_USB_LOW_POWER_ON_SUSPEND
+ STM32_USB->CNTR |= CNTR_LP_MODE;
+#endif
+ STM32_USB->ISTR = ~ISTR_SUSP;
+
+ _usb_suspend(usbp);
+ }
+
+ /* USB bus WAKEUP condition handling.*/
+ if (istr & ISTR_WKUP) {
+ uint32_t fnr = STM32_USB->FNR;
+ if (!(fnr & FNR_RXDP)) {
+ STM32_USB->CNTR &= ~CNTR_FSUSP;
+
+ _usb_wakeup(usbp);
+ }
+#if STM32_USB_LOW_POWER_ON_SUSPEND
+ else {
+ /* Just noise, going back in SUSPEND mode, reference manual 22.4.5,
+ table 169.*/
+ STM32_USB->CNTR |= CNTR_LP_MODE;
+ }
+#endif
+ STM32_USB->ISTR = ~ISTR_WKUP;
+ }
+
+ /* SOF handling.*/
+ if (istr & ISTR_SOF) {
+ _usb_isr_invoke_sof_cb(usbp);
+ STM32_USB->ISTR = ~ISTR_SOF;
+ }
+
+ /* Endpoint events handling.*/
+ while (istr & ISTR_CTR) {
+ usb_serve_endpoints(usbp, istr & ISTR_EP_ID_MASK);
+ istr = STM32_USB->ISTR;
+ }
+
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* STM32_USB_USE_USB1 */
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level USB driver initialization.
+ *
+ * @notapi
+ */
+void usb_lld_init(void) {
+
+ /* Driver initialization.*/
+ usbObjectInit(&USBD1);
+}
+
+/**
+ * @brief Configures and activates the USB peripheral.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+void usb_lld_start(USBDriver *usbp) {
+
+ if (usbp->state == USB_STOP) {
+ /* Clock activation.*/
+#if STM32_USB_USE_USB1
+ if (&USBD1 == usbp) {
+ /* USB clock enabled.*/
+ rccEnableUSB(true);
+ /* Powers up the transceiver while holding the USB in reset state.*/
+ STM32_USB->CNTR = CNTR_FRES;
+ /* Enabling the USB IRQ vectors, this also gives enough time to allow
+ the transceiver power up (1uS).*/
+#if STM32_USB1_HP_NUMBER != STM32_USB1_LP_NUMBER
+ nvicEnableVector(STM32_USB1_HP_NUMBER, STM32_USB_USB1_HP_IRQ_PRIORITY);
+#endif
+ nvicEnableVector(STM32_USB1_LP_NUMBER, STM32_USB_USB1_LP_IRQ_PRIORITY);
+ /* Releases the USB reset.*/
+ STM32_USB->CNTR = 0;
+ }
+#endif
+ /* Reset procedure enforced on driver start.*/
+ usb_lld_reset(usbp);
+ }
+}
+
+/**
+ * @brief Deactivates the USB peripheral.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+void usb_lld_stop(USBDriver *usbp) {
+
+ /* If in ready state then disables the USB clock.*/
+ if (usbp->state != USB_STOP) {
+#if STM32_USB_USE_USB1
+ if (&USBD1 == usbp) {
+#if STM32_USB1_HP_NUMBER != STM32_USB1_LP_NUMBER
+ nvicDisableVector(STM32_USB1_HP_NUMBER);
+#endif
+ nvicDisableVector(STM32_USB1_LP_NUMBER);
+ STM32_USB->CNTR = CNTR_PDWN | CNTR_FRES;
+ rccDisableUSB();
+ }
+#endif
+ }
+}
+
+/**
+ * @brief USB low level reset routine.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+void usb_lld_reset(USBDriver *usbp) {
+ uint32_t cntr;
+
+ /* Post reset initialization.*/
+ STM32_USB->BTABLE = BTABLE_ADDR;
+ STM32_USB->ISTR = 0;
+ STM32_USB->DADDR = DADDR_EF;
+ cntr = /*CNTR_ESOFM | */ CNTR_RESETM | CNTR_SUSPM |
+ CNTR_WKUPM | /*CNTR_ERRM | CNTR_PMAOVRM |*/ CNTR_CTRM;
+ /* The SOF interrupt is only enabled if a callback is defined for
+ this service because it is an high rate source.*/
+ if (usbp->config->sof_cb != NULL)
+ cntr |= CNTR_SOFM;
+ STM32_USB->CNTR = cntr;
+
+ /* Resets the packet memory allocator.*/
+ usb_pm_reset(usbp);
+
+ /* EP0 initialization.*/
+ usbp->epc[0] = &ep0config;
+ usb_lld_init_endpoint(usbp, 0);
+}
+
+/**
+ * @brief Sets the USB address.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+void usb_lld_set_address(USBDriver *usbp) {
+
+ STM32_USB->DADDR = (uint32_t)(usbp->address) | DADDR_EF;
+}
+
+/**
+ * @brief Enables an endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
+ uint16_t epr;
+ stm32_usb_descriptor_t *dp;
+ const USBEndpointConfig *epcp = usbp->epc[ep];
+
+ /* Setting the endpoint type. Note that isochronous endpoints cannot be
+ bidirectional because it uses double buffering and both transmit and
+ receive descriptor fields are used for either direction.*/
+ switch (epcp->ep_mode & USB_EP_MODE_TYPE) {
+ case USB_EP_MODE_TYPE_ISOC:
+#if STM32_USB_USE_ISOCHRONOUS
+ osalDbgAssert((epcp->in_state == NULL) || (epcp->out_state == NULL),
+ "isochronous EP cannot be IN and OUT");
+ epr = EPR_EP_TYPE_ISO;
+ break;
+#else
+ osalDbgAssert(false, "isochronous support disabled");
+#endif
+ /* Falls through.*/
+ case USB_EP_MODE_TYPE_BULK:
+ epr = EPR_EP_TYPE_BULK;
+ break;
+ case USB_EP_MODE_TYPE_INTR:
+ epr = EPR_EP_TYPE_INTERRUPT;
+ break;
+ default:
+ epr = EPR_EP_TYPE_CONTROL;
+ }
+
+ dp = USB_GET_DESCRIPTOR(ep);
+
+ /* IN endpoint handling.*/
+ if (epcp->in_state != NULL) {
+ dp->TXCOUNT0 = 0;
+ dp->TXADDR0 = usb_pm_alloc(usbp, epcp->in_maxsize);
+
+#if STM32_USB_USE_ISOCHRONOUS
+ if (epr == EPR_EP_TYPE_ISO) {
+ epr |= EPR_STAT_TX_VALID;
+ dp->TXCOUNT1 = dp->TXCOUNT0;
+ dp->TXADDR1 = dp->TXADDR0; /* Both buffers overlapped.*/
+ }
+ else {
+ epr |= EPR_STAT_TX_NAK;
+ }
+#else
+ epr |= EPR_STAT_TX_NAK;
+#endif
+ }
+
+ /* OUT endpoint handling.*/
+ if (epcp->out_state != NULL) {
+ uint16_t nblocks;
+
+ /* Endpoint size and address initialization.*/
+ if (epcp->out_maxsize > 62)
+ nblocks = (((((epcp->out_maxsize - 1) | 0x1f) + 1) / 32) << 10) |
+ 0x8000;
+ else
+ nblocks = ((((epcp->out_maxsize - 1) | 1) + 1) / 2) << 10;
+ dp->RXCOUNT0 = nblocks;
+ dp->RXADDR0 = usb_pm_alloc(usbp, epcp->out_maxsize);
+
+#if STM32_USB_USE_ISOCHRONOUS
+ if (epr == EPR_EP_TYPE_ISO) {
+ epr |= EPR_STAT_RX_VALID;
+ dp->RXCOUNT1 = dp->RXCOUNT0;
+ dp->RXADDR1 = dp->RXADDR0; /* Both buffers overlapped.*/
+ }
+ else {
+ epr |= EPR_STAT_RX_NAK;
+ }
+#else
+ epr |= EPR_STAT_RX_NAK;
+#endif
+ }
+
+ /* Resetting the data toggling bits for this endpoint.*/
+ if (STM32_USB->EPR[ep] & EPR_DTOG_RX) {
+ epr |= EPR_DTOG_RX;
+ }
+
+ if (STM32_USB->EPR[ep] & EPR_DTOG_TX) {
+ epr |= EPR_DTOG_TX;
+ }
+
+ /* EPxR register setup.*/
+ EPR_SET(ep, epr | ep);
+ EPR_TOGGLE(ep, epr);
+}
+
+/**
+ * @brief Disables all the active endpoints except the endpoint zero.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+void usb_lld_disable_endpoints(USBDriver *usbp) {
+ unsigned i;
+
+ /* Resets the packet memory allocator.*/
+ usb_pm_reset(usbp);
+
+ /* Disabling all endpoints.*/
+ for (i = 1; i <= USB_ENDOPOINTS_NUMBER; i++) {
+ EPR_TOGGLE(i, 0);
+ EPR_SET(i, 0);
+ }
+}
+
+/**
+ * @brief Returns the status of an OUT endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @return The endpoint status.
+ * @retval EP_STATUS_DISABLED The endpoint is not active.
+ * @retval EP_STATUS_STALLED The endpoint is stalled.
+ * @retval EP_STATUS_ACTIVE The endpoint is active.
+ *
+ * @notapi
+ */
+usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+ switch (STM32_USB->EPR[ep] & EPR_STAT_RX_MASK) {
+ case EPR_STAT_RX_DIS:
+ return EP_STATUS_DISABLED;
+ case EPR_STAT_RX_STALL:
+ return EP_STATUS_STALLED;
+ default:
+ return EP_STATUS_ACTIVE;
+ }
+}
+
+/**
+ * @brief Returns the status of an IN endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @return The endpoint status.
+ * @retval EP_STATUS_DISABLED The endpoint is not active.
+ * @retval EP_STATUS_STALLED The endpoint is stalled.
+ * @retval EP_STATUS_ACTIVE The endpoint is active.
+ *
+ * @notapi
+ */
+usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+ switch (STM32_USB->EPR[ep] & EPR_STAT_TX_MASK) {
+ case EPR_STAT_TX_DIS:
+ return EP_STATUS_DISABLED;
+ case EPR_STAT_TX_STALL:
+ return EP_STATUS_STALLED;
+ default:
+ return EP_STATUS_ACTIVE;
+ }
+}
+
+/**
+ * @brief Reads a setup packet from the dedicated packet buffer.
+ * @details This function must be invoked in the context of the @p setup_cb
+ * callback in order to read the received setup packet.
+ * @pre In order to use this function the endpoint must have been
+ * initialized as a control endpoint.
+ * @post The endpoint is ready to accept another packet.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[out] buf buffer where to copy the packet data
+ *
+ * @notapi
+ */
+void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) {
+ stm32_usb_pma_t *pmap;
+ stm32_usb_descriptor_t *udp;
+ uint32_t n;
+
+ (void)usbp;
+ udp = USB_GET_DESCRIPTOR(ep);
+ pmap = USB_ADDR2PTR(udp->RXADDR0);
+ for (n = 0; n < 4; n++) {
+ *(uint16_t *)buf = (uint16_t)*pmap++;
+ buf += 2;
+ }
+}
+
+/**
+ * @brief Starts a receive operation on an OUT endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
+ USBOutEndpointState *osp = usbp->epc[ep]->out_state;
+
+ /* Transfer initialization.*/
+ if (osp->rxsize == 0) /* Special case for zero sized packets.*/
+ osp->rxpkts = 1;
+ else
+ osp->rxpkts = (uint16_t)((osp->rxsize + usbp->epc[ep]->out_maxsize - 1) /
+ usbp->epc[ep]->out_maxsize);
+
+ EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID);
+}
+
+/**
+ * @brief Starts a transmit operation on an IN endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
+ size_t n;
+ USBInEndpointState *isp = usbp->epc[ep]->in_state;
+
+ /* Transfer initialization.*/
+ n = isp->txsize;
+ if (n > (size_t)usbp->epc[ep]->in_maxsize)
+ n = (size_t)usbp->epc[ep]->in_maxsize;
+
+ isp->txlast = n;
+ usb_packet_write_from_buffer(ep, isp->txbuf, n);
+
+ EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID);
+}
+
+/**
+ * @brief Brings an OUT endpoint in the stalled state.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+
+ EPR_SET_STAT_RX(ep, EPR_STAT_RX_STALL);
+}
+
+/**
+ * @brief Brings an IN endpoint in the stalled state.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+
+ EPR_SET_STAT_TX(ep, EPR_STAT_TX_STALL);
+}
+
+/**
+ * @brief Brings an OUT endpoint in the active state.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+
+ /* Makes sure to not put to NAK an endpoint that is already
+ transferring.*/
+ if ((STM32_USB->EPR[ep] & EPR_STAT_RX_MASK) != EPR_STAT_RX_VALID)
+ EPR_SET_STAT_TX(ep, EPR_STAT_RX_NAK);
+}
+
+/**
+ * @brief Brings an IN endpoint in the active state.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+
+ /* Makes sure to not put to NAK an endpoint that is already
+ transferring.*/
+ if ((STM32_USB->EPR[ep] & EPR_STAT_TX_MASK) != EPR_STAT_TX_VALID)
+ EPR_SET_STAT_TX(ep, EPR_STAT_TX_NAK);
+}
+
+#endif /* HAL_USE_USB */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.h
new file mode 100644
index 0000000..1270172
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USBv1/hal_usb_lld.h
@@ -0,0 +1,521 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USBv1/hal_usb_lld.h
+ * @brief STM32 USB subsystem low level driver header.
+ *
+ * @addtogroup USB
+ * @{
+ */
+
+#ifndef HAL_USB_LLD_H
+#define HAL_USB_LLD_H
+
+#if HAL_USE_USB || defined(__DOXYGEN__)
+
+#include "stm32_usb.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Maximum endpoint address.
+ */
+#define USB_MAX_ENDPOINTS USB_ENDOPOINTS_NUMBER
+
+/**
+ * @brief Status stage handling method.
+ */
+#define USB_EP0_STATUS_STAGE USB_EP0_STATUS_STAGE_SW
+
+/**
+ * @brief This device requires the address change after the status packet.
+ */
+#define USB_SET_ADDRESS_MODE USB_LATE_SET_ADDRESS
+
+/**
+ * @brief Method for set address acknowledge.
+ */
+#define USB_SET_ADDRESS_ACK_HANDLING USB_SET_ADDRESS_ACK_SW
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief USB1 driver enable switch.
+ * @details If set to @p TRUE the support for USB1 is included.
+ * @note The default is @p TRUE.
+ */
+#if !defined(STM32_USB_USE_USB1) || defined(__DOXYGEN__)
+#define STM32_USB_USE_USB1 FALSE
+#endif
+
+/**
+ * @brief Enables the USB device low power mode on suspend.
+ */
+#if !defined(STM32_USB_LOW_POWER_ON_SUSPEND) || defined(__DOXYGEN__)
+#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE
+#endif
+
+/**
+ * @brief USB1 interrupt priority level setting.
+ */
+#if (!defined(STM32_USB_USB1_HP_IRQ_PRIORITY) && \
+ (STM32_USB1_HP_NUMBER != STM32_USB1_LP_NUMBER)) || defined(__DOXYGEN__)
+#define STM32_USB_USB1_HP_IRQ_PRIORITY 13
+#endif
+
+/**
+ * @brief USB1 interrupt priority level setting.
+ */
+#if !defined(STM32_USB_USB1_LP_IRQ_PRIORITY) || defined(__DOXYGEN__)
+#define STM32_USB_USB1_LP_IRQ_PRIORITY 14
+#endif
+
+/**
+ * @brief Enables isochronous support.
+ * @note Isochronous support requires special handling and this makes the
+ * code size increase significantly.
+ */
+#if !defined(STM32_USB_USE_ISOCHRONOUS) || defined(__DOXYGEN__)
+#define STM32_USB_USE_ISOCHRONOUS FALSE
+#endif
+
+/**
+ * @brief Use faster copy for packets.
+ * @note Makes the driver larger.
+ */
+#if !defined(STM32_USB_USE_FAST_COPY) || defined(__DOXYGEN__)
+#define STM32_USB_USE_FAST_COPY FALSE
+#endif
+
+/**
+ * @brief Host wake-up procedure duration.
+ */
+#if !defined(STM32_USB_HOST_WAKEUP_DURATION) || defined(__DOXYGEN__)
+#define STM32_USB_HOST_WAKEUP_DURATION 2
+#endif
+
+/**
+ * @brief Allowed deviation for the 48MHz clock.
+ */
+#if !defined(STM32_USB_48MHZ_DELTA) || defined(__DOXYGEN__)
+#define STM32_USB_48MHZ_DELTA 0
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if STM32_USB_USE_USB1 && !STM32_HAS_USB
+#error "USB not present in the selected device"
+#endif
+
+#if !STM32_USB_USE_USB1
+#error "USB driver activated but no USB peripheral assigned"
+#endif
+
+#if STM32_USB_USE_USB1 && \
+ (STM32_USB1_HP_NUMBER != STM32_USB1_LP_NUMBER) && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_USB_USB1_HP_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to USB HP"
+#endif
+
+#if STM32_USB_USE_USB1 && \
+ !OSAL_IRQ_IS_VALID_PRIORITY(STM32_USB_USB1_LP_IRQ_PRIORITY)
+#error "Invalid IRQ priority assigned to USB LP"
+#endif
+
+#if !defined(STM32_USB1_HP_HANDLER)
+#error "STM32_USB1_HP_HANDLER not defined"
+#endif
+
+#if !defined(STM32_USB1_HP_NUMBER)
+#error "STM32_USB1_HP_NUMBER not defined"
+#endif
+
+#if !defined(STM32_USB1_LP_HANDLER)
+#error "STM32_USB1_LP_HANDLER not defined"
+#endif
+
+#if !defined(STM32_USB1_LP_NUMBER)
+#error "STM32_USB1_LP_NUMBER not defined"
+#endif
+
+#if (STM32_USB_HOST_WAKEUP_DURATION < 2) || (STM32_USB_HOST_WAKEUP_DURATION > 15)
+#error "invalid STM32_USB_HOST_WAKEUP_DURATION setting, it must be between 2 and 15"
+#endif
+
+#if (STM32_USB_48MHZ_DELTA < 0) || (STM32_USB_48MHZ_DELTA > 250000)
+#error "invalid STM32_USB_48MHZ_DELTA setting, it must not exceed 250000"
+#endif
+
+#if (STM32_USBCLK < (48000000 - STM32_USB_48MHZ_DELTA)) || \
+ (STM32_USBCLK > (48000000 + STM32_USB_48MHZ_DELTA))
+#error "the USB driver requires a 48MHz clock"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of an IN endpoint state structure.
+ */
+typedef struct {
+ /**
+ * @brief Requested transmit transfer size.
+ */
+ size_t txsize;
+ /**
+ * @brief Transmitted bytes so far.
+ */
+ size_t txcnt;
+ /**
+ * @brief Pointer to the transmission linear buffer.
+ */
+ const uint8_t *txbuf;
+#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Waiting thread.
+ */
+ thread_reference_t thread;
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Size of the last transmitted packet.
+ */
+ size_t txlast;
+} USBInEndpointState;
+
+/**
+ * @brief Type of an OUT endpoint state structure.
+ */
+typedef struct {
+ /**
+ * @brief Requested receive transfer size.
+ */
+ size_t rxsize;
+ /**
+ * @brief Received bytes so far.
+ */
+ size_t rxcnt;
+ /**
+ * @brief Pointer to the receive linear buffer.
+ */
+ uint8_t *rxbuf;
+#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Waiting thread.
+ */
+ thread_reference_t thread;
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Number of packets to receive.
+ */
+ uint16_t rxpkts;
+} USBOutEndpointState;
+
+/**
+ * @brief Type of an USB endpoint configuration structure.
+ * @note Platform specific restrictions may apply to endpoints.
+ */
+typedef struct {
+ /**
+ * @brief Type and mode of the endpoint.
+ */
+ uint32_t ep_mode;
+ /**
+ * @brief Setup packet notification callback.
+ * @details This callback is invoked when a setup packet has been
+ * received.
+ * @post The application must immediately call @p usbReadPacket() in
+ * order to access the received packet.
+ * @note This field is only valid for @p USB_EP_MODE_TYPE_CTRL
+ * endpoints, it should be set to @p NULL for other endpoint
+ * types.
+ */
+ usbepcallback_t setup_cb;
+ /**
+ * @brief IN endpoint notification callback.
+ * @details This field must be set to @p NULL if callback is not required.
+ */
+ usbepcallback_t in_cb;
+ /**
+ * @brief OUT endpoint notification callback.
+ * @details This field must be set to @p NULL if callback is not required.
+ */
+ usbepcallback_t out_cb;
+ /**
+ * @brief IN endpoint maximum packet size.
+ * @details This field must be set to zero if the IN endpoint is not used.
+ */
+ uint16_t in_maxsize;
+ /**
+ * @brief OUT endpoint maximum packet size.
+ * @details This field must be set to zero if the OUT endpoint is not used.
+ */
+ uint16_t out_maxsize;
+ /**
+ * @brief @p USBEndpointState associated to the IN endpoint.
+ * @details This field must be set to @p NULL if the IN endpoint is not
+ * used.
+ */
+ USBInEndpointState *in_state;
+ /**
+ * @brief @p USBEndpointState associated to the OUT endpoint.
+ * @details This field must be set to @p NULL if the OUT endpoint is not
+ * used.
+ */
+ USBOutEndpointState *out_state;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Reserved field, not currently used.
+ * @note Initialize this field to 1 in order to be forward compatible.
+ */
+ uint16_t ep_buffers;
+ /**
+ * @brief Pointer to a buffer for setup packets.
+ * @details Setup packets require a dedicated 8-bytes buffer, set this
+ * field to @p NULL for non-control endpoints.
+ */
+ uint8_t *setup_buf;
+} USBEndpointConfig;
+
+/**
+ * @brief Type of an USB driver configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief USB events callback.
+ * @details This callback is invoked when an USB driver event is registered.
+ */
+ usbeventcb_t event_cb;
+ /**
+ * @brief Device GET_DESCRIPTOR request callback.
+ * @note This callback is mandatory and cannot be set to @p NULL.
+ */
+ usbgetdescriptor_t get_descriptor_cb;
+ /**
+ * @brief Requests hook callback.
+ * @details This hook allows to be notified of standard requests or to
+ * handle non standard requests.
+ */
+ usbreqhandler_t requests_hook_cb;
+ /**
+ * @brief Start Of Frame callback.
+ */
+ usbcallback_t sof_cb;
+ /* End of the mandatory fields.*/
+} USBConfig;
+
+/**
+ * @brief Structure representing an USB driver.
+ */
+struct USBDriver {
+ /**
+ * @brief Driver state.
+ */
+ usbstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const USBConfig *config;
+ /**
+ * @brief Bit map of the transmitting IN endpoints.
+ */
+ uint16_t transmitting;
+ /**
+ * @brief Bit map of the receiving OUT endpoints.
+ */
+ uint16_t receiving;
+ /**
+ * @brief Active endpoints configurations.
+ */
+ const USBEndpointConfig *epc[USB_MAX_ENDPOINTS + 1];
+ /**
+ * @brief Fields available to user, it can be used to associate an
+ * application-defined handler to an IN endpoint.
+ * @note The base index is one, the endpoint zero does not have a
+ * reserved element in this array.
+ */
+ void *in_params[USB_MAX_ENDPOINTS];
+ /**
+ * @brief Fields available to user, it can be used to associate an
+ * application-defined handler to an OUT endpoint.
+ * @note The base index is one, the endpoint zero does not have a
+ * reserved element in this array.
+ */
+ void *out_params[USB_MAX_ENDPOINTS];
+ /**
+ * @brief Endpoint 0 state.
+ */
+ usbep0state_t ep0state;
+ /**
+ * @brief Next position in the buffer to be transferred through endpoint 0.
+ */
+ uint8_t *ep0next;
+ /**
+ * @brief Number of bytes yet to be transferred through endpoint 0.
+ */
+ size_t ep0n;
+ /**
+ * @brief Endpoint 0 end transaction callback.
+ */
+ usbcallback_t ep0endcb;
+ /**
+ * @brief Setup packet buffer.
+ */
+ uint8_t setup[8];
+ /**
+ * @brief Current USB device status.
+ */
+ uint16_t status;
+ /**
+ * @brief Assigned USB address.
+ */
+ uint8_t address;
+ /**
+ * @brief Current USB device configuration.
+ */
+ uint8_t configuration;
+ /**
+ * @brief State of the driver when a suspend happened.
+ */
+ usbstate_t saved_state;
+#if defined(USB_DRIVER_EXT_FIELDS)
+ USB_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Pointer to the next address in the packet memory.
+ */
+ uint32_t pmnext;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Returns the current frame number.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @return The current frame number.
+ *
+ * @notapi
+ */
+#define usb_lld_get_frame_number(usbp) (STM32_USB->FNR & FNR_FN_MASK)
+
+/**
+ * @brief Returns the exact size of a receive transaction.
+ * @details The received size can be different from the size specified in
+ * @p usbStartReceiveI() because the last packet could have a size
+ * different from the expected one.
+ * @pre The OUT endpoint must have been configured in transaction mode
+ * in order to use this function.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @return Received data size.
+ *
+ * @notapi
+ */
+#define usb_lld_get_transaction_size(usbp, ep) \
+ ((usbp)->epc[ep]->out_state->rxcnt)
+
+#if STM32_USB_HAS_BCDR || defined(__DOXYGEN__)
+/**
+ * @brief Connects the USB device.
+ *
+ * @notapi
+ */
+#if !defined(usb_lld_connect_bus)
+#define usb_lld_connect_bus(usbp) (STM32_USB->BCDR |= USB_BCDR_DPPU)
+#endif
+
+/**
+ * @brief Disconnect the USB device.
+ *
+ * @notapi
+ */
+#if !defined(usb_lld_disconnect_bus)
+#define usb_lld_disconnect_bus(usbp) (STM32_USB->BCDR &= ~USB_BCDR_DPPU)
+#endif
+#endif /* STM32_USB_HAS_BCDR */
+
+#if defined(STM32L1XX)
+#if !defined(usb_lld_connect_bus)
+#define usb_lld_connect_bus(usbp) (SYSCFG->PMC |= SYSCFG_PMC_USB_PU)
+#endif
+
+#if !defined(usb_lld_disconnect_bus)
+#define usb_lld_disconnect_bus(usbp) (SYSCFG->PMC &= ~SYSCFG_PMC_USB_PU)
+#endif
+#endif /* STM32L1XX */
+
+/**
+ * @brief Start of host wake-up procedure.
+ *
+ * @notapi
+ */
+#define usb_lld_wakeup_host(usbp) \
+ do { \
+ STM32_USB->CNTR |= USB_CNTR_RESUME; \
+ osalThreadSleepMilliseconds(STM32_USB_HOST_WAKEUP_DURATION); \
+ STM32_USB->CNTR &= ~USB_CNTR_RESUME; \
+ } while (false)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_USB_USE_USB1 && !defined(__DOXYGEN__)
+extern USBDriver USBD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void usb_lld_init(void);
+ void usb_lld_start(USBDriver *usbp);
+ void usb_lld_stop(USBDriver *usbp);
+ void usb_lld_reset(USBDriver *usbp);
+ void usb_lld_set_address(USBDriver *usbp);
+ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep);
+ void usb_lld_disable_endpoints(USBDriver *usbp);
+ usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep);
+ usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep);
+ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf);
+ void usb_lld_start_out(USBDriver *usbp, usbep_t ep);
+ void usb_lld_start_in(USBDriver *usbp, usbep_t ep);
+ void usb_lld_stall_out(USBDriver *usbp, usbep_t ep);
+ void usb_lld_stall_in(USBDriver *usbp, usbep_t ep);
+ void usb_lld_clear_out(USBDriver *usbp, usbep_t ep);
+ void usb_lld_clear_in(USBDriver *usbp, usbep_t ep);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_USB */
+
+#endif /* HAL_USB_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USBv1/stm32_usb.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USBv1/stm32_usb.h
new file mode 100644
index 0000000..9a8595e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/USBv1/stm32_usb.h
@@ -0,0 +1,266 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file USBv1/stm32_usb.h
+ * @brief STM32 USB registers layout header.
+ * @note This file requires definitions from the ST STM32 header files
+ * stm32f10x.h or stm32l1xx.h.
+ *
+ * @addtogroup USB
+ * @{
+ */
+
+#ifndef STM32_USB_H
+#define STM32_USB_H
+
+/**
+ * @brief Number of the available endpoints.
+ * @details This value does not include the endpoint 0 which is always present.
+ */
+#define USB_ENDOPOINTS_NUMBER 7
+
+/**
+ * @brief Width of USB packet memory accesses.
+ */
+#if STM32_USB_ACCESS_SCHEME_2x16
+typedef uint16_t stm32_usb_pma_t;
+#else
+typedef uint32_t stm32_usb_pma_t;
+#endif
+
+/**
+ * @brief USB registers block.
+ */
+typedef struct {
+ /**
+ * @brief Endpoint registers.
+ */
+ volatile uint32_t EPR[USB_ENDOPOINTS_NUMBER + 1];
+ /*
+ * @brief Reserved space.
+ */
+ volatile uint32_t _r20[8];
+ /*
+ * @brief Control Register.
+ */
+ volatile uint32_t CNTR;
+ /*
+ * @brief Interrupt Status Register.
+ */
+ volatile uint32_t ISTR;
+ /*
+ * @brief Frame Number Register.
+ */
+ volatile uint32_t FNR;
+ /*
+ * @brief Device Address Register.
+ */
+ volatile uint32_t DADDR;
+ /*
+ * @brief Buffer Table Address.
+ */
+ volatile uint32_t BTABLE;
+ /*
+ * @brief LPM Control and Status Register.
+ */
+ volatile uint32_t LPMCSR;
+#if STM32_USB_HAS_BCDR
+ /*
+ * @brief Battery Charging Detector
+ */
+ volatile uint32_t BCDR;
+#endif
+} stm32_usb_t;
+
+/**
+ * @brief USB descriptor registers block.
+ */
+typedef struct {
+ /**
+ * @brief TX buffer offset register.
+ */
+ volatile stm32_usb_pma_t TXADDR0;
+ /**
+ * @brief TX counter register 0.
+ */
+ volatile stm32_usb_pma_t TXCOUNT0;
+ /**
+ * @brief RX buffer offset register.
+ */
+ volatile stm32_usb_pma_t RXADDR0;
+ /**
+ * @brief RX counter register 0.
+ */
+ volatile stm32_usb_pma_t RXCOUNT0;
+} stm32_usb_descriptor_t;
+
+/**
+ * @name Register aliases
+ * @{
+ */
+#define RXCOUNT1 TXCOUNT0
+#define TXCOUNT1 RXCOUNT0
+#define RXADDR1 TXADDR0
+#define TXADDR1 RXADDR0
+/** @} */
+
+/**
+ * @brief USB registers block numeric address.
+ */
+#if defined(USB_BASE) || defined(__DOXYGEN__)
+#define STM32_USB_BASE USB_BASE
+#else
+#define STM32_USB_BASE (APB1PERIPH_BASE + 0x5C00)
+#endif
+
+/**
+ * @brief USB RAM numeric address.
+ */
+#if defined(USB_PMAADDR) || defined(__DOXYGEN__)
+#define STM32_USBRAM_BASE USB_PMAADDR
+#else
+#define STM32_USBRAM_BASE (APB1PERIPH_BASE + 0x6000)
+#endif
+
+/**
+ * @brief Pointer to the USB registers block.
+ */
+#define STM32_USB ((stm32_usb_t *)STM32_USB_BASE)
+
+/**
+ * @brief Pointer to the USB RAM.
+ */
+#define STM32_USBRAM ((stm32_usb_pma_t *)STM32_USBRAM_BASE)
+
+/**
+ * @brief Mask of all the toggling bits in the EPR register.
+ */
+#define EPR_TOGGLE_MASK (EPR_STAT_TX_MASK | EPR_DTOG_TX | \
+ EPR_STAT_RX_MASK | EPR_DTOG_RX | \
+ EPR_SETUP)
+
+#define EPR_EA_MASK 0x000F
+#define EPR_STAT_TX_MASK 0x0030
+#define EPR_STAT_TX_DIS 0x0000
+#define EPR_STAT_TX_STALL 0x0010
+#define EPR_STAT_TX_NAK 0x0020
+#define EPR_STAT_TX_VALID 0x0030
+#define EPR_DTOG_TX 0x0040
+#define EPR_SWBUF_RX EPR_DTOG_TX
+#define EPR_CTR_TX 0x0080
+#define EPR_EP_KIND 0x0100
+#define EPR_EP_DBL_BUF EPR_EP_KIND
+#define EPR_EP_STATUS_OUT EPR_EP_KIND
+#define EPR_EP_TYPE_MASK 0x0600
+#define EPR_EP_TYPE_BULK 0x0000
+#define EPR_EP_TYPE_CONTROL 0x0200
+#define EPR_EP_TYPE_ISO 0x0400
+#define EPR_EP_TYPE_INTERRUPT 0x0600
+#define EPR_SETUP 0x0800
+#define EPR_STAT_RX_MASK 0x3000
+#define EPR_STAT_RX_DIS 0x0000
+#define EPR_STAT_RX_STALL 0x1000
+#define EPR_STAT_RX_NAK 0x2000
+#define EPR_STAT_RX_VALID 0x3000
+#define EPR_DTOG_RX 0x4000
+#define EPR_SWBUF_TX EPR_DTOG_RX
+#define EPR_CTR_RX 0x8000
+
+#define CNTR_FRES 0x0001
+#define CNTR_PDWN 0x0002
+#define CNTR_LP_MODE 0x0004
+#define CNTR_FSUSP 0x0008
+#define CNTR_RESUME 0x0010
+#define CNTR_ESOFM 0x0100
+#define CNTR_SOFM 0x0200
+#define CNTR_RESETM 0x0400
+#define CNTR_SUSPM 0x0800
+#define CNTR_WKUPM 0x1000
+#define CNTR_ERRM 0x2000
+#define CNTR_PMAOVRM 0x4000
+#define CNTR_CTRM 0x8000
+
+#define ISTR_EP_ID_MASK 0x000F
+#define ISTR_DIR 0x0010
+#define ISTR_ESOF 0x0100
+#define ISTR_SOF 0x0200
+#define ISTR_RESET 0x0400
+#define ISTR_SUSP 0x0800
+#define ISTR_WKUP 0x1000
+#define ISTR_ERR 0x2000
+#define ISTR_PMAOVR 0x4000
+#define ISTR_CTR 0x8000
+
+#define FNR_FN_MASK 0x07FF
+#define FNR_LSOF 0x1800
+#define FNR_LCK 0x2000
+#define FNR_RXDM 0x4000
+#define FNR_RXDP 0x8000
+
+#define DADDR_ADD_MASK 0x007F
+#define DADDR_EF 0x0080
+
+#define RXCOUNT_COUNT_MASK 0x03FF
+#define TXCOUNT_COUNT_MASK 0x03FF
+
+#define EPR_CTR_MASK (EPR_CTR_TX | EPR_CTR_RX)
+
+#define EPR_SET(ep, epr) \
+ STM32_USB->EPR[ep] = ((epr) & ~EPR_TOGGLE_MASK) | EPR_CTR_MASK
+
+#define EPR_TOGGLE(ep, epr) \
+ STM32_USB->EPR[ep] = (STM32_USB->EPR[ep] ^ ((epr) & EPR_TOGGLE_MASK)) \
+ | EPR_CTR_MASK
+
+#define EPR_SET_STAT_RX(ep, epr) \
+ STM32_USB->EPR[ep] = ((STM32_USB->EPR[ep] & \
+ ~(EPR_TOGGLE_MASK & ~EPR_STAT_RX_MASK)) ^ \
+ (epr)) | EPR_CTR_MASK
+
+#define EPR_SET_STAT_TX(ep, epr) \
+ STM32_USB->EPR[ep] = ((STM32_USB->EPR[ep] & \
+ ~(EPR_TOGGLE_MASK & ~EPR_STAT_TX_MASK)) ^ \
+ (epr)) | EPR_CTR_MASK
+
+#define EPR_CLEAR_CTR_RX(ep) \
+ STM32_USB->EPR[ep] = (STM32_USB->EPR[ep] & ~EPR_CTR_RX & ~EPR_TOGGLE_MASK)\
+ | EPR_CTR_TX
+
+#define EPR_CLEAR_CTR_TX(ep) \
+ STM32_USB->EPR[ep] = (STM32_USB->EPR[ep] & ~EPR_CTR_TX & ~EPR_TOGGLE_MASK)\
+ | EPR_CTR_RX
+
+/**
+ * @brief Returns an endpoint descriptor pointer.
+ */
+#define USB_GET_DESCRIPTOR(ep) \
+ ((stm32_usb_descriptor_t *)((uint32_t)STM32_USBRAM_BASE + \
+ (uint32_t)STM32_USB->BTABLE + \
+ (uint32_t)(ep) * \
+ sizeof(stm32_usb_descriptor_t)))
+
+/**
+ * @brief Converts from a PMA address to a physical address.
+ */
+#define USB_ADDR2PTR(addr) \
+ ((stm32_usb_pma_t *)((addr) * \
+ (sizeof(stm32_usb_pma_t) / 2) + \
+ STM32_USBRAM_BASE))
+
+#endif /* STM32_USB_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/xWDGv1/driver.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/xWDGv1/driver.mk
new file mode 100644
index 0000000..a4d8bdd
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/xWDGv1/driver.mk
@@ -0,0 +1,9 @@
+ifeq ($(USE_SMART_BUILD),yes)
+ifneq ($(findstring HAL_USE_WDG TRUE,$(HALCONF)),)
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.c
+endif
+else
+PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.c
+endif
+
+PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.c
new file mode 100644
index 0000000..42a620e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.c
@@ -0,0 +1,144 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file xWDGv1/hal_wdg_lld.c
+ * @brief WDG Driver subsystem low level driver source.
+ *
+ * @addtogroup WDG
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define KR_KEY_RELOAD 0xAAAAU
+#define KR_KEY_ENABLE 0xCCCCU
+#define KR_KEY_WRITE 0x5555U
+#define KR_KEY_PROTECT 0x0000U
+
+#if !defined(IWDG) && defined(IWDG1)
+#define IWDG IWDG1
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+#if STM32_WDG_USE_IWDG || defined(__DOXYGEN__)
+WDGDriver WDGD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level WDG driver initialization.
+ *
+ * @notapi
+ */
+void wdg_lld_init(void) {
+
+#if STM32_WDG_USE_IWDG
+ WDGD1.state = WDG_STOP;
+ WDGD1.wdg = IWDG;
+#endif
+}
+
+/**
+ * @brief Configures and activates the WDG peripheral.
+ *
+ * @param[in] wdgp pointer to the @p WDGDriver object
+ *
+ * @notapi
+ */
+void wdg_lld_start(WDGDriver *wdgp) {
+
+#if STM32_IWDG_IS_WINDOWED
+ /* Enable IWDG and unlock for write.*/
+ wdgp->wdg->KR = KR_KEY_ENABLE;
+ wdgp->wdg->KR = KR_KEY_WRITE;
+
+ /* Write configuration.*/
+ wdgp->wdg->PR = wdgp->config->pr;
+ wdgp->wdg->RLR = wdgp->config->rlr;
+ while (wdgp->wdg->SR != 0)
+ ;
+
+ /* This also triggers a refresh.*/
+ wdgp->wdg->WINR = wdgp->config->winr;
+#else
+ /* Unlock IWDG.*/
+ wdgp->wdg->KR = KR_KEY_WRITE;
+
+ /* Write configuration.*/
+ while (wdgp->wdg->SR != 0)
+ ;
+ wdgp->wdg->PR = wdgp->config->pr;
+ wdgp->wdg->RLR = wdgp->config->rlr;
+
+ /* Start operations.*/
+ wdgp->wdg->KR = KR_KEY_RELOAD;
+ wdgp->wdg->KR = KR_KEY_ENABLE;
+#endif
+}
+
+/**
+ * @brief Deactivates the WDG peripheral.
+ *
+ * @param[in] wdgp pointer to the @p WDGDriver object
+ *
+ * @notapi
+ */
+void wdg_lld_stop(WDGDriver *wdgp) {
+
+ osalDbgAssert(wdgp->state == WDG_STOP,
+ "IWDG cannot be stopped once activated");
+}
+
+/**
+ * @brief Reloads WDG's counter.
+ *
+ * @param[in] wdgp pointer to the @p WDGDriver object
+ *
+ * @notapi
+ */
+void wdg_lld_reset(WDGDriver * wdgp) {
+
+ wdgp->wdg->KR = KR_KEY_RELOAD;
+}
+
+#endif /* HAL_USE_WDG == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.h
new file mode 100644
index 0000000..7528899
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/LLD/xWDGv1/hal_wdg_lld.h
@@ -0,0 +1,183 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file xWDGv1/hal_wdg_lld.h
+ * @brief WDG Driver subsystem low level driver header.
+ *
+ * @addtogroup WDG
+ * @{
+ */
+
+#ifndef HAL_WDG_LLD_H
+#define HAL_WDG_LLD_H
+
+#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name RLR register definitions
+ * @{
+ */
+#define STM32_IWDG_RL_MASK (0x00000FFF << 0)
+#define STM32_IWDG_RL(n) ((n) << 0)
+/** @} */
+
+/**
+ * @name PR register definitions
+ * @{
+ */
+#define STM32_IWDG_PR_MASK (7 << 0)
+#define STM32_IWDG_PR_4 0U
+#define STM32_IWDG_PR_8 1U
+#define STM32_IWDG_PR_16 2U
+#define STM32_IWDG_PR_32 3U
+#define STM32_IWDG_PR_64 4U
+#define STM32_IWDG_PR_128 5U
+#define STM32_IWDG_PR_256 6U
+/** @} */
+
+/**
+ * @name WINR register definitions
+ * @{
+ */
+#define STM32_IWDG_WIN_MASK (0x00000FFF << 0)
+#define STM32_IWDG_WIN(n) ((n) << 0)
+#define STM32_IWDG_WIN_DISABLED STM32_IWDG_WIN(0x00000FFF)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief IWDG driver enable switch.
+ * @details If set to @p TRUE the support for IWDG is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(STM32_WDG_USE_IWDG) || defined(__DOXYGEN__)
+#define STM32_WDG_USE_IWDG FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if STM32_WDG_USE_IWDG && !STM32_HAS_IWDG
+#error "IWDG not present in the selected device"
+#endif
+
+#if !STM32_WDG_USE_IWDG
+#error "WDG driver activated but no xWDG peripheral assigned"
+#endif
+
+#if !defined(STM32_LSI_ENABLED)
+#error "STM32_LSI_ENABLED not defined"
+#endif
+
+#if (STM32_WDG_USE_IWDG == TRUE) && (STM32_LSI_ENABLED == FALSE)
+#error "IWDG requires LSI clock"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a structure representing an WDG driver.
+ */
+typedef struct WDGDriver WDGDriver;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+ /**
+ * @brief Configuration of the IWDG_PR register.
+ * @details See the STM32 reference manual for details.
+ */
+ uint32_t pr;
+ /**
+ * @brief Configuration of the IWDG_RLR register.
+ * @details See the STM32 reference manual for details.
+ */
+ uint32_t rlr;
+#if STM32_IWDG_IS_WINDOWED || defined(__DOXYGEN__)
+ /**
+ * @brief Configuration of the IWDG_WINR register.
+ * @details See the STM32 reference manual for details.
+ * @note This field is not present in F1, F2, F4, L1 sub-families.
+ */
+ uint32_t winr;
+#endif
+} WDGConfig;
+
+/**
+ * @brief Structure representing an WDG driver.
+ */
+struct WDGDriver {
+ /**
+ * @brief Driver state.
+ */
+ wdgstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const WDGConfig *config;
+ /* End of the mandatory fields.*/
+ /**
+ * @brief Pointer to the IWDG registers block.
+ */
+ IWDG_TypeDef *wdg;
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if STM32_WDG_USE_IWDG && !defined(__DOXYGEN__)
+extern WDGDriver WDGD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void wdg_lld_init(void);
+ void wdg_lld_start(WDGDriver *wdgp);
+ void wdg_lld_stop(WDGDriver *wdgp);
+ void wdg_lld_reset(WDGDriver *wdgp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_WDG == TRUE */
+
+#endif /* HAL_WDG_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/hal_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/hal_lld.c
new file mode 100644
index 0000000..ab01d60
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/hal_lld.c
@@ -0,0 +1,263 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32G4xx/hal_lld.c
+ * @brief STM32G4xx HAL subsystem low level driver source.
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#include "hal.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief CMSIS system core clock variable.
+ * @note It is declared in system_stm32g4xx.h.
+ */
+uint32_t SystemCoreClock = STM32_HCLK;
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes the backup domain.
+ * @note WARNING! Changing RTC clock source impossible without resetting
+ * of the whole BKP domain.
+ */
+static void hal_lld_backup_domain_init(void) {
+
+ /* Reset BKP domain if different clock source selected.*/
+ if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) {
+ /* Backup domain reset.*/
+ RCC->BDCR = RCC_BDCR_BDRST;
+ RCC->BDCR = 0;
+ }
+
+#if STM32_LSE_ENABLED
+ /* LSE activation.*/
+#if defined(STM32_LSE_BYPASS)
+ /* LSE Bypass.*/
+ RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP;
+#else
+ /* No LSE Bypass.*/
+ RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON;
+#endif
+ while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0)
+ ; /* Wait until LSE is stable. */
+#endif
+
+#if HAL_USE_RTC
+ /* If the backup domain hasn't been initialized yet then proceed with
+ initialization.*/
+ if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) {
+ /* Selects clock source.*/
+ RCC->BDCR |= STM32_RTCSEL;
+
+ /* RTC clock enabled.*/
+ RCC->BDCR |= RCC_BDCR_RTCEN;
+ }
+#endif /* HAL_USE_RTC */
+
+ /* Low speed output mode.*/
+ RCC->BDCR |= STM32_LSCOSEL;
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level HAL driver initialization.
+ *
+ * @notapi
+ */
+void hal_lld_init(void) {
+
+ /* Initializes the backup domain.*/
+ hal_lld_backup_domain_init();
+
+ /* DMA subsystems initialization.*/
+#if defined(STM32_DMA_REQUIRED)
+ dmaInit();
+#endif
+
+ /* IRQ subsystem initialization.*/
+ irqInit();
+
+ /* Programmable voltage detector settings.*/
+ PWR->CR2 = STM32_PWR_CR2;
+}
+
+/**
+ * @brief STM32L4xx clocks and PLL initialization.
+ * @note All the involved constants come from the file @p board.h.
+ * @note This function should be invoked just after the system reset.
+ *
+ * @special
+ */
+void stm32_clock_init(void) {
+
+#if !STM32_NO_INIT
+
+ /* Reset of all peripherals.
+ Note, GPIOs are not reset because initialized before this point in
+ board files.*/
+ rccResetAHB1(~0);
+ rccResetAHB2(~STM32_GPIO_EN_MASK);
+ rccResetAHB3(~0);
+ rccResetAPB1R1(~0);
+ rccResetAPB1R2(~0);
+ rccResetAPB2(~0);
+
+ /* PWR clock enable.*/
+#if defined(HAL_USE_RTC) && defined(RCC_APBENR1_RTCAPBEN)
+ rccEnableAPB1R1(RCC_APB1ENR1_PWREN | RCC_APB1ENR1_RTCAPBEN, false)
+#else
+ rccEnableAPB1R1(RCC_APB1ENR1_PWREN, false)
+#endif
+
+ /* Core voltage setup.*/
+ PWR->CR1 = STM32_VOS;
+ while ((PWR->SR2 & PWR_SR2_VOSF) != 0) /* Wait until regulator is */
+ ; /* stable. */
+
+ /* Additional PWR configurations.*/
+ PWR->CR2 = STM32_PWR_CR2;
+ PWR->CR3 = STM32_PWR_CR3;
+ PWR->CR4 = STM32_PWR_CR4;
+ PWR->CR5 = STM32_CR5BITS;
+
+#if STM32_HSI16_ENABLED
+ /* HSI activation.*/
+ RCC->CR |= RCC_CR_HSION;
+ while ((RCC->CR & RCC_CR_HSIRDY) == 0)
+ ; /* Wait until HSI16 is stable. */
+#endif
+
+#if STM32_HSI48_ENABLED
+ /* HSI activation.*/
+ RCC->CRRCR |= RCC_CRRCR_HSI48ON;
+ while ((RCC->CRRCR & RCC_CRRCR_HSI48RDY) == 0)
+ ; /* Wait until HSI48 is stable. */
+#endif
+
+#if STM32_HSE_ENABLED
+#if defined(STM32_HSE_BYPASS)
+ /* HSE Bypass.*/
+ RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP;
+#endif
+ /* HSE activation.*/
+ RCC->CR |= RCC_CR_HSEON;
+ while ((RCC->CR & RCC_CR_HSERDY) == 0)
+ ; /* Wait until HSE is stable. */
+#endif
+
+#if STM32_LSI_ENABLED
+ /* LSI activation.*/
+ RCC->CSR |= RCC_CSR_LSION;
+ while ((RCC->CSR & RCC_CSR_LSIRDY) == 0)
+ ; /* Wait until LSI is stable. */
+#endif
+
+ /* Backup domain access enabled and left open.*/
+ PWR->CR1 |= PWR_CR1_DBP;
+
+#if STM32_LSE_ENABLED
+ /* LSE activation.*/
+#if defined(STM32_LSE_BYPASS)
+ /* LSE Bypass.*/
+ RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP;
+#else
+ /* No LSE Bypass.*/
+ RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON;
+#endif
+ while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0)
+ ; /* Wait until LSE is stable. */
+#endif
+
+#if STM32_ACTIVATE_PLL
+ /* PLLM and PLLSRC are common to all PLLs.*/
+ RCC->PLLCFGR = STM32_PLLPDIV |
+ STM32_PLLR | STM32_PLLREN |
+ STM32_PLLQ | STM32_PLLQEN |
+ STM32_PLLP | STM32_PLLPEN |
+ STM32_PLLN | STM32_PLLM |
+ STM32_PLLSRC;
+#endif
+
+#if STM32_ACTIVATE_PLL
+ /* PLL activation.*/
+ RCC->CR |= RCC_CR_PLLON;
+
+ /* Waiting for PLL lock.*/
+ while ((RCC->CR & RCC_CR_PLLRDY) == 0)
+ ;
+#endif
+
+ /* Other clock-related settings (dividers, MCO etc).*/
+ RCC->CFGR = STM32_MCOPRE | STM32_MCOSEL | STM32_PPRE2 | STM32_PPRE1 |
+ STM32_HPRE;
+
+ /* CCIPR registers initialization, note.*/
+ RCC->CCIPR = STM32_ADC345SEL | STM32_ADC12SEL | STM32_CLK48SEL |
+ STM32_FDCANSEL | STM32_I2S23SEL | STM32_SAI1SEL |
+ STM32_LPTIM1SEL | STM32_I2C3SEL | STM32_I2C2SEL |
+ STM32_I2C1SEL | STM32_LPUART1SEL | STM32_UART5SEL |
+ STM32_UART4SEL | STM32_USART3SEL | STM32_USART2SEL |
+ STM32_USART1SEL;
+ RCC->CCIPR2 = STM32_QSPISEL | STM32_I2C4SEL;
+
+ /* Set flash WS's for SYSCLK source */
+ FLASH->ACR = FLASH_ACR_DBG_SWEN | FLASH_ACR_DCEN | FLASH_ACR_ICEN |
+ FLASH_ACR_PRFTEN | STM32_FLASHBITS;
+ while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) !=
+ (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) {
+ }
+
+ /* Switching to the configured SYSCLK source if it is different from HSI16.*/
+#if STM32_SW != STM32_SW_HSI16
+ RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */
+ /* Wait until SYSCLK is stable.*/
+ while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2))
+ ;
+#endif
+
+#endif /* STM32_NO_INIT */
+
+ /* SYSCFG clock enabled here because it is a multi-functional unit shared
+ among multiple drivers.*/
+ rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true);
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/hal_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/hal_lld.h
new file mode 100644
index 0000000..45bf317
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/hal_lld.h
@@ -0,0 +1,1858 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32G4xx/hal_lld.h
+ * @brief STM32G4xx HAL subsystem low level driver header.
+ * @pre This module requires the following macros to be defined in the
+ * @p board.h file:
+ * - STM32_LSECLK.
+ * - STM32_LSEDRV.
+ * - STM32_LSE_BYPASS (optionally).
+ * - STM32_HSECLK.
+ * - STM32_HSE_BYPASS (optionally).
+ * .
+ * One of the following macros must also be defined:
+ * - STM32G431xx, STM32G441xx, STM32G471xx.
+ * - STM32G473xx, STM32G483xx.
+ * - STM32G474xx, STM32G484xx.
+ * - STM32GBK1CB.
+ * .
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#ifndef HAL_LLD_H
+#define HAL_LLD_H
+
+#include "stm32_registry.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Platform identification
+ * @{
+ */
+#if defined(STM32G431xx) || defined(STM32G441xx) || defined(STM32G471xx) || \
+ defined(__DOXYGEN__)
+#define PLATFORM_NAME "STM32G4 Access Line"
+
+#elif defined(STM32G473xx)
+#define PLATFORM_NAME "STM32G4 Performance Line"
+
+#elif defined(STM32G483xx)
+#define PLATFORM_NAME "STM32G4 Performance Line with Crypto"
+
+#elif defined(STM32G474xx)
+#define PLATFORM_NAME "STM32G4 Hi-resolution Line"
+
+#elif defined(STM32G484xx)
+#define PLATFORM_NAME "STM32G4 Hi-resolution Line with Crypto"
+
+#elif defined(STM32GBK1CB)
+#define PLATFORM_NAME "STM32G4 Mystery Line"
+
+#else
+#error "STM32G4 device not specified"
+#endif
+
+/**
+ * @brief Sub-family identifier.
+ */
+#if !defined(STM32G4XX) || defined(__DOXYGEN__)
+#define STM32G4XX
+#endif
+/** @} */
+
+/**
+ * @name Internal clock sources
+ * @{
+ */
+#define STM32_HSI16CLK 16000000U /**< 16MHz internal clock. */
+#define STM32_HSI48CLK 48000000U /**< 48MHz internal clock. */
+#define STM32_LSICLK 32000U /**< Low speed internal clock. */
+/** @} */
+
+/**
+ * @name VOS field definitions
+ * @{
+ */
+#define STM32_VOS_MASK (3U << 9U) /**< Core voltage mask. */
+#define STM32_VOS_RANGE1 (1U << 9U) /**< Core voltage 1.2 Volts. */
+#define STM32_VOS_RANGE2 (2U << 9U) /**< Core voltage 1.0 Volts. */
+/** @} */
+
+/**
+ * @name RCC_CFGR register bits definitions
+ * @{
+ */
+#define STM32_SW_MASK (3U << 0U) /**< SW field mask. */
+#define STM32_SW_HSI16 (1U << 0U) /**< SYSCLK source is HSI16. */
+#define STM32_SW_HSE (2U << 0U) /**< SYSCLK source is HSE. */
+#define STM32_SW_PLLRCLK (3U << 0U) /**< SYSCLK source is PLL. */
+
+#define STM32_HPRE_MASK (15U << 4U) /**< HPRE field mask. */
+#define STM32_HPRE_FIELD(n) ((n) << 4U) /**< HPRE field value. */
+#define STM32_HPRE_DIV1 STM32_HPRE_FIELD(0U)
+#define STM32_HPRE_DIV2 STM32_HPRE_FIELD(8U)
+#define STM32_HPRE_DIV4 STM32_HPRE_FIELD(9U)
+#define STM32_HPRE_DIV8 STM32_HPRE_FIELD(10U)
+#define STM32_HPRE_DIV16 STM32_HPRE_FIELD(11U)
+#define STM32_HPRE_DIV64 STM32_HPRE_FIELD(12U)
+#define STM32_HPRE_DIV128 STM32_HPRE_FIELD(13U)
+#define STM32_HPRE_DIV256 STM32_HPRE_FIELD(14U)
+#define STM32_HPRE_DIV512 STM32_HPRE_FIELD(15U)
+
+#define STM32_PPRE1_MASK (7U << 8U) /**< PPRE1 field mask. */
+#define STM32_PPRE1_FIELD(n) ((n) << 8U) /**< PPRE1 field value. */
+#define STM32_PPRE1_DIV1 STM32_PPRE1_FIELD(0U)
+#define STM32_PPRE1_DIV2 STM32_PPRE1_FIELD(4U)
+#define STM32_PPRE1_DIV4 STM32_PPRE1_FIELD(5U)
+#define STM32_PPRE1_DIV8 STM32_PPRE1_FIELD(6U)
+#define STM32_PPRE1_DIV16 STM32_PPRE1_FIELD(7U)
+
+#define STM32_PPRE2_MASK (7U << 11U) /**< PPRE2 field mask. */
+#define STM32_PPRE2_FIELD(n) ((n) << 11U) /**< PPRE2 field value. */
+#define STM32_PPRE2_DIV1 STM32_PPRE2_FIELD(0U)
+#define STM32_PPRE2_DIV2 STM32_PPRE2_FIELD(4U)
+#define STM32_PPRE2_DIV4 STM32_PPRE2_FIELD(5U)
+#define STM32_PPRE2_DIV8 STM32_PPRE2_FIELD(6U)
+#define STM32_PPRE2_DIV16 STM32_PPRE2_FIELD(7U)
+
+#define STM32_MCOSEL_MASK (15U << 24U)/**< MCOSEL field mask. */
+#define STM32_MCOSEL_NOCLOCK (0U << 24U) /**< No clock on MCO pin. */
+#define STM32_MCOSEL_SYSCLK (1U << 24U) /**< SYSCLK on MCO pin. */
+#define STM32_MCOSEL_HSI16 (3U << 24U) /**< HSI16 clock on MCO pin. */
+#define STM32_MCOSEL_HSE (4U << 24U) /**< HSE clock on MCO pin. */
+#define STM32_MCOSEL_PLLRCLK (5U << 24U) /**< PLLR clock on MCO pin. */
+#define STM32_MCOSEL_LSI (6U << 24U) /**< LSI clock on MCO pin. */
+#define STM32_MCOSEL_LSE (7U << 24U) /**< LSE clock on MCO pin. */
+#define STM32_MCOSEL_HSI48 (8U << 24U) /**< HSI48 clock on MCO pin. */
+
+#define STM32_MCOPRE_MASK (7U << 28U) /**< MCOPRE field mask. */
+#define STM32_MCOPRE_FIELD(n) ((n) << 28U)/**< MCOPRE field value */
+#define STM32_MCOPRE_DIV1 STM32_MCOPRE_FIELD(0U)
+#define STM32_MCOPRE_DIV2 STM32_MCOPRE_FIELD(1U)
+#define STM32_MCOPRE_DIV4 STM32_MCOPRE_FIELD(2U)
+#define STM32_MCOPRE_DIV8 STM32_MCOPRE_FIELD(3U)
+#define STM32_MCOPRE_DIV16 STM32_MCOPRE_FIELD(4U)
+/** @} */
+
+/**
+ * @name RCC_PLLCFGR register bits definitions
+ * @{
+ */
+#define STM32_PLLSRC_MASK (3 << 0) /**< PLL clock source mask. */
+#define STM32_PLLSRC_NOCLOCK (0 << 0) /**< PLL clock source disabled. */
+#define STM32_PLLSRC_HSI16 (2 << 0) /**< PLL clock source is HSI16. */
+#define STM32_PLLSRC_HSE (3 << 0) /**< PLL clock source is HSE. */
+/** @} */
+
+/**
+ * @name RCC_CCIPR register bits definitions
+ * @{
+ */
+#define STM32_USART1SEL_MASK (3U << 0U) /**< USART1SEL mask. */
+#define STM32_USART1SEL_PCLK2 (0U << 0U) /**< USART1 source is PCLK2. */
+#define STM32_USART1SEL_SYSCLK (1U << 0U) /**< USART1 source is SYSCLK. */
+#define STM32_USART1SEL_HSI16 (2U << 0U) /**< USART1 source is HSI16. */
+#define STM32_USART1SEL_LSE (3U << 0U) /**< USART1 source is LSE. */
+
+#define STM32_USART2SEL_MASK (3U << 2U) /**< USART2 mask. */
+#define STM32_USART2SEL_PCLK1 (0U << 2U) /**< USART2 source is PCLK1. */
+#define STM32_USART2SEL_SYSCLK (1U << 2U) /**< USART2 source is SYSCLK. */
+#define STM32_USART2SEL_HSI16 (2U << 2U) /**< USART2 source is HSI16. */
+#define STM32_USART2SEL_LSE (3U << 2U) /**< USART2 source is LSE. */
+
+#define STM32_USART3SEL_MASK (3U << 4U) /**< USART3 mask. */
+#define STM32_USART3SEL_PCLK1 (0U << 4U) /**< USART3 source is PCLK1. */
+#define STM32_USART3SEL_SYSCLK (1U << 4U) /**< USART3 source is SYSCLK. */
+#define STM32_USART3SEL_HSI16 (2U << 4U) /**< USART3 source is HSI16. */
+#define STM32_USART3SEL_LSE (3U << 4U) /**< USART3 source is LSE. */
+
+#define STM32_UART4SEL_MASK (3U << 6U) /**< UART4 mask. */
+#define STM32_UART4SEL_PCLK1 (0U << 6U) /**< UART4 source is PCLK1. */
+#define STM32_UART4SEL_SYSCLK (1U << 6U) /**< UART4 source is SYSCLK. */
+#define STM32_UART4SEL_HSI16 (2U << 6U) /**< UART4 source is HSI16. */
+#define STM32_UART4SEL_LSE (3U << 6U) /**< UART4 source is LSE. */
+
+#define STM32_UART5SEL_MASK (3U << 8U) /**< UART5 mask. */
+#define STM32_UART5SEL_PCLK1 (0U << 8U) /**< UART5 source is PCLK1. */
+#define STM32_UART5SEL_SYSCLK (1U << 8U) /**< UART5 source is SYSCLK. */
+#define STM32_UART5SEL_HSI16 (2U << 8U) /**< UART5 source is HSI16. */
+#define STM32_UART5SEL_LSE (3U << 8U) /**< UART5 source is LSE. */
+
+#define STM32_LPUART1SEL_MASK (3U << 10U) /**< LPUART1 mask. */
+#define STM32_LPUART1SEL_PCLK1 (0U << 10U) /**< LPUART1 source is PCLK1. */
+#define STM32_LPUART1SEL_SYSCLK (1U << 10U) /**< LPUART1 source is SYSCLK. */
+#define STM32_LPUART1SEL_HSI16 (2U << 10U) /**< LPUART1 source is HSI16. */
+#define STM32_LPUART1SEL_LSE (3U << 10U) /**< LPUART1 source is LSE. */
+
+#define STM32_I2C1SEL_MASK (3U << 12U) /**< I2C1SEL mask. */
+#define STM32_I2C1SEL_PCLK1 (0U << 12U) /**< I2C1 source is PCLK1. */
+#define STM32_I2C1SEL_SYSCLK (1U << 12U) /**< I2C1 source is SYSCLK. */
+#define STM32_I2C1SEL_HSI16 (2U << 12U) /**< I2C1 source is HSI16. */
+
+#define STM32_I2C2SEL_MASK (3U << 14U) /**< I2C2SEL mask. */
+#define STM32_I2C2SEL_PCLK1 (0U << 14U) /**< I2C2 source is PCLK1. */
+#define STM32_I2C2SEL_SYSCLK (1U << 14U) /**< I2C2 source is SYSCLK. */
+#define STM32_I2C2SEL_HSI16 (2U << 14U) /**< I2C2 source is HSI16. */
+
+#define STM32_I2C3SEL_MASK (3U << 16U) /**< I2C3SEL mask. */
+#define STM32_I2C3SEL_PCLK1 (0U << 16U) /**< I2C3 source is PCLK1. */
+#define STM32_I2C3SEL_SYSCLK (1U << 16U) /**< I2C3 source is SYSCLK. */
+#define STM32_I2C3SEL_HSI16 (2U << 16U) /**< I2C3 source is HSI16. */
+
+#define STM32_LPTIM1SEL_MASK (3U << 18U) /**< LPTIM1SEL mask. */
+#define STM32_LPTIM1SEL_PCLK1 (0U << 18U) /**< LPTIM1 source is PCLK1. */
+#define STM32_LPTIM1SEL_LSI (1U << 18U) /**< LPTIM1 source is LSI. */
+#define STM32_LPTIM1SEL_HSI16 (2U << 18U) /**< LPTIM1 source is HSI16. */
+#define STM32_LPTIM1SEL_LSE (3U << 18U) /**< LPTIM1 source is LSE. */
+
+#define STM32_SAI1SEL_MASK (3U << 20U) /**< SAI1SEL mask. */
+#define STM32_SAI1SEL_SYSCLK (0U << 20U) /**< SAI1 source is SYSCLK. */
+#define STM32_SAI1SEL_PLLQCLK (1U << 20U) /**< SAI1 source is PLLQCLK. */
+#define STM32_SAI1SEL_CKIN (2U << 20U) /**< SAI1 source is CKIN. */
+#define STM32_SAI1SEL_HSI16 (3U << 20U) /**< SAI1 source is HSI16. */
+
+#define STM32_I2S23SEL_MASK (3U << 22U) /**< I2S23SEL mask. */
+#define STM32_I2S23SEL_SYSCLK (0U << 22U) /**< I2S23 source is SYSCLK. */
+#define STM32_I2S23SEL_PLLQCLK (1U << 22U) /**< I2S23 source is PLLQCLK. */
+#define STM32_I2S23SEL_CKIN (2U << 22U) /**< I2S23 source is CKIN. */
+#define STM32_I2S23SEL_HSI16 (3U << 22U) /**< I2S23 source is HSI16. */
+
+#define STM32_FDCANSEL_MASK (3U << 24U) /**< FDCANSEL mask. */
+#define STM32_FDCANSEL_HSE (0U << 24U) /**< FDCAN source is HSE. */
+#define STM32_FDCANSEL_PLLQCLK (1U << 24U) /**< FDCAN source is PLLQCLK. */
+#define STM32_FDCANSEL_PCLK1 (2U << 24U) /**< FDCAN source is PCLK1. */
+
+#define STM32_CLK48SEL_MASK (3U << 26U) /**< CLK48SEL mask. */
+#define STM32_CLK48SEL_HSI48 (0U << 26U) /**< CLK48 source is HSI48. */
+#define STM32_CLK48SEL_PLLQCLK (2U << 26U) /**< CLK48 source is PLLQCLK. */
+
+#define STM32_ADC12SEL_MASK (3U << 28U) /**< ADC12SEL mask. */
+#define STM32_ADC12SEL_NOCLK (0U << 28U) /**< ADC12 source is none. */
+#define STM32_ADC12SEL_PLLPCLK (1U << 28U) /**< ADC12 source is PLLPCLK. */
+#define STM32_ADC12SEL_SYSCLK (2U << 28U) /**< ADC12 source is SYSCLK. */
+
+#define STM32_ADC345SEL_MASK (3U << 30U) /**< ADC345SEL mask. */
+#define STM32_ADC345SEL_NOCLK (0U << 30U) /**< ADC345 source is none. */
+#define STM32_ADC345SEL_PLLPCLK (1U << 30U) /**< ADC345 source is PLLPCLK. */
+#define STM32_ADC345SEL_SYSCLK (2U << 30U) /**< ADC345 source is SYSCLK. */
+/** @} */
+
+/**
+ * @name RCC_CCIPR2 register bits definitions
+ * @{
+ */
+#define STM32_I2C4SEL_MASK (3U << 0U) /**< I2C4SEL mask. */
+#define STM32_I2C4SEL_PCLK1 (0U << 0U) /**< I2C4 source is PCLK1. */
+#define STM32_I2C4SEL_SYSCLK (1U << 0U) /**< I2C4 source is SYSCLK. */
+#define STM32_I2C4SEL_HSI16 (2U << 0U) /**< I2C4 source is HSI16. */
+
+#define STM32_QSPISEL_MASK (3U << 20U) /**< QSPISEL mask. */
+#define STM32_QSPISEL_SYSCLK (0U << 20U) /**< QSPI source is SYSCLK. */
+#define STM32_QSPISEL_HSI16 (1U << 20U) /**< QSPI source is HSI16. */
+#define STM32_QSPISEL_PLLQCLK (2U << 20U) /**< QSPI source is PLLQCLK. */
+/** @} */
+
+/**
+ * @name RCC_BDCR register bits definitions
+ * @{
+ */
+#define STM32_RTCSEL_MASK (3U << 8U) /**< RTC source mask. */
+#define STM32_RTCSEL_NOCLOCK (0U << 8U) /**< No RTC source. */
+#define STM32_RTCSEL_LSE (1U << 8U) /**< RTC source is LSE. */
+#define STM32_RTCSEL_LSI (2U << 8U) /**< RTC source is LSI. */
+#define STM32_RTCSEL_HSEDIV (3U << 8U) /**< RTC source is HSE divided. */
+
+#define STM32_LSCOSEL_MASK (3U << 24U) /**< LSCO pin clock source. */
+#define STM32_LSCOSEL_NOCLOCK (0U << 24U) /**< No clock on LSCO pin. */
+#define STM32_LSCOSEL_LSI (1U << 24U) /**< LSI on LSCO pin. */
+#define STM32_LSCOSEL_LSE (3U << 24U) /**< LSE on LSCO pin. */
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief Disables the PWR/RCC initialization in the HAL.
+ */
+#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__)
+#define STM32_NO_INIT FALSE
+#endif
+
+/**
+ * @brief Core voltage selection.
+ * @note This setting affects all the performance and clock related
+ * settings, the maximum performance is only obtainable selecting
+ * the maximum voltage.
+ */
+#if !defined(STM32_VOS) || defined(__DOXYGEN__)
+#define STM32_VOS STM32_VOS_RANGE1
+#endif
+
+/**
+ * @brief PWR CR2 register initialization value.
+ */
+#if !defined(STM32_PWR_CR2) || defined(__DOXYGEN__)
+#define STM32_PWR_CR2 (PWR_CR2_PLS_LEV0)
+#endif
+
+/**
+ * @brief PWR CR3 register initialization value.
+ */
+#if !defined(STM32_PWR_CR3) || defined(__DOXYGEN__)
+#define STM32_PWR_CR3 (PWR_CR3_EIWF)
+#endif
+
+/**
+ * @brief PWR CR4 register initialization value.
+ */
+#if !defined(STM32_PWR_CR4) || defined(__DOXYGEN__)
+#define STM32_PWR_CR4 (0U)
+#endif
+
+/**
+ * @brief Enables or disables the HSI16 clock source.
+ */
+#if !defined(STM32_HSI16_ENABLED) || defined(__DOXYGEN__)
+#define STM32_HSI16_ENABLED FALSE
+#endif
+
+/**
+ * @brief Enables or disables the HSI48 clock source.
+ */
+#if !defined(STM32_HSI48_ENABLED) || defined(__DOXYGEN__)
+#define STM32_HSI48_ENABLED FALSE
+#endif
+
+/**
+ * @brief Enables or disables the HSE clock source.
+ */
+#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__)
+#define STM32_HSE_ENABLED FALSE
+#endif
+
+/**
+ * @brief Enables or disables the LSI clock source.
+ */
+#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__)
+#define STM32_LSI_ENABLED FALSE
+#endif
+
+/**
+ * @brief Enables or disables the LSE clock source.
+ */
+#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__)
+#define STM32_LSE_ENABLED FALSE
+#endif
+
+/**
+ * @brief Main clock source selection.
+ * @note If the selected clock source is not the PLL then the PLL is not
+ * initialized and started.
+ * @note The default value is calculated for a 170MHz system clock from
+ * the internal 16MHz HSI clock.
+ */
+#if !defined(STM32_SW) || defined(__DOXYGEN__)
+#define STM32_SW STM32_SW_PLLRCLK
+#endif
+
+/**
+ * @brief Clock source for the PLL.
+ * @note This setting has only effect if the PLL is selected as the
+ * system clock source.
+ * @note The default value is calculated for a 170MHz system clock from
+ * the internal 16MHz HSI clock.
+ */
+#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__)
+#define STM32_PLLSRC STM32_PLLSRC_HSI16
+#endif
+
+/**
+ * @brief PLLM divider value.
+ * @note The allowed values are 1..16.
+ * @note The default value is calculated for a 170MHz system clock from
+ * the internal 16MHz HSI clock.
+ */
+#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLM_VALUE 4
+#endif
+
+/**
+ * @brief PLLN multiplier value.
+ * @note The allowed values are 8..127.
+ * @note The default value is calculated for a 170MHz system clock from
+ * the internal 16MHz HSI clock.
+ */
+#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLN_VALUE 84
+#endif
+
+/**
+ * @brief PLLPDIV divider value or zero if disabled.
+ * @note The allowed values are 0, 2..31.
+ */
+#if !defined(STM32_PLLPDIV_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLPDIV_VALUE 0
+#endif
+
+/**
+ * @brief PLLP divider value.
+ * @note The allowed values are 7, 17.
+ */
+#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLP_VALUE 7
+#endif
+
+/**
+ * @brief PLLQ divider value.
+ * @note The allowed values are 2, 4, 6, 8.
+ */
+#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLQ_VALUE 8
+#endif
+
+/**
+ * @brief PLLR divider value.
+ * @note The allowed values are 2, 4, 6, 8.
+ * @note The default value is calculated for a 170MHz system clock from
+ * the internal 16MHz HSI clock.
+ */
+#if !defined(STM32_PLLR_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLR_VALUE 2
+#endif
+
+/**
+ * @brief AHB prescaler value.
+ * @note The default value is calculated for a 170MHz system clock from
+ * the internal 16MHz HSI clock.
+ */
+#if !defined(STM32_HPRE) || defined(__DOXYGEN__)
+#define STM32_HPRE STM32_HPRE_DIV1
+#endif
+
+/**
+ * @brief APB1 prescaler value.
+ */
+#if !defined(STM32_PPRE1) || defined(__DOXYGEN__)
+#define STM32_PPRE1 STM32_PPRE1_DIV2
+#endif
+
+/**
+ * @brief APB2 prescaler value.
+ */
+#if !defined(STM32_PPRE2) || defined(__DOXYGEN__)
+#define STM32_PPRE2 STM32_PPRE2_DIV1
+#endif
+
+/**
+ * @brief MCO clock source.
+ */
+#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__)
+#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK
+#endif
+
+/**
+ * @brief MCO divider setting.
+ */
+#if !defined(STM32_MCOPRE) || defined(__DOXYGEN__)
+#define STM32_MCOPRE STM32_MCOPRE_DIV1
+#endif
+
+/**
+ * @brief LSCO clock source.
+ */
+#if !defined(STM32_LSCOSEL) || defined(__DOXYGEN__)
+#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK
+#endif
+
+/**
+ * @brief USART1 clock source.
+ */
+#if !defined(STM32_USART1SEL) || defined(__DOXYGEN__)
+#define STM32_USART1SEL STM32_USART1SEL_SYSCLK
+#endif
+
+/**
+ * @brief USART2 clock source.
+ */
+#if !defined(STM32_USART2SEL) || defined(__DOXYGEN__)
+#define STM32_USART2SEL STM32_USART2SEL_SYSCLK
+#endif
+
+/**
+ * @brief USART3 clock source.
+ */
+#if !defined(STM32_USART3SEL) || defined(__DOXYGEN__)
+#define STM32_USART3SEL STM32_USART3SEL_SYSCLK
+#endif
+
+/**
+ * @brief UART4 clock source.
+ */
+#if !defined(STM32_UART4SEL) || defined(__DOXYGEN__)
+#define STM32_UART4SEL STM32_UART4SEL_SYSCLK
+#endif
+
+/**
+ * @brief UART5 clock source.
+ */
+#if !defined(STM32_UART5SEL) || defined(__DOXYGEN__)
+#define STM32_UART5SEL STM32_UART5SEL_SYSCLK
+#endif
+
+/**
+ * @brief LPUART1 clock source.
+ */
+#if !defined(STM32_LPUART1SEL) || defined(__DOXYGEN__)
+#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK
+#endif
+
+/**
+ * @brief I2C1 clock source.
+ */
+#if !defined(STM32_I2C1SEL) || defined(__DOXYGEN__)
+#define STM32_I2C1SEL STM32_I2C1SEL_PCLK1
+#endif
+
+/**
+ * @brief I2C2 clock source.
+ */
+#if !defined(STM32_I2C2SEL) || defined(__DOXYGEN__)
+#define STM32_I2C2SEL STM32_I2C2SEL_PCLK1
+#endif
+
+/**
+ * @brief I2C3 clock source.
+ */
+#if !defined(STM32_I2C3SEL) || defined(__DOXYGEN__)
+#define STM32_I2C3SEL STM32_I2C3SEL_PCLK1
+#endif
+
+/**
+ * @brief I2C4 clock source.
+ */
+#if !defined(STM32_I2C4SEL) || defined(__DOXYGEN__)
+#define STM32_I2C4SEL STM32_I2C4SEL_PCLK1
+#endif
+
+/**
+ * @brief LPTIM1 clock source.
+ */
+#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__)
+#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1
+#endif
+
+/**
+ * @brief SAI1 clock source.
+ */
+#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__)
+#define STM32_SAI1SEL STM32_SAI1SEL_SYSCLK
+#endif
+
+/**
+ * @brief I2S23 clock source.
+ */
+#if !defined(STM32_I2S23SEL) || defined(__DOXYGEN__)
+#define STM32_I2S23SEL STM32_I2S23SEL_SYSCLK
+#endif
+
+/**
+ * @brief FDCAN clock source.
+ */
+#if !defined(STM32_FDCANSEL) || defined(__DOXYGEN__)
+#define STM32_FDCANSEL STM32_FDCANSEL_HSE
+#endif
+
+/**
+ * @brief CLK48 clock source.
+ */
+#if !defined(STM32_CLK48SEL) || defined(__DOXYGEN__)
+#define STM32_CLK48SEL STM32_CLK48SEL_HSI48
+#endif
+
+/**
+ * @brief ADC12 clock source.
+ */
+#if !defined(STM32_ADC12SEL) || defined(__DOXYGEN__)
+#define STM32_ADC12SEL STM32_ADC12SEL_PLLPCLK
+#endif
+
+/**
+ * @brief ADC34 clock source.
+ */
+#if !defined(STM32_ADC345SEL) || defined(__DOXYGEN__)
+#define STM32_ADC345SEL STM32_ADC345SEL_PLLPCLK
+#endif
+
+/**
+ * @brief QSPI clock source.
+ */
+#if !defined(STM32_QSPISEL) || defined(__DOXYGEN__)
+#define STM32_QSPISEL STM32_QSPISEL_SYSCLK
+#endif
+
+/**
+ * @brief RTC clock source.
+ */
+#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__)
+#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*
+ * Configuration-related checks.
+ */
+#if !defined(STM32G4xx_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32G4xx_MCUCONF not defined"
+#endif
+
+#if defined(STM32G431xx) && !defined(STM32G431_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32G431_MCUCONF not defined"
+
+#elif defined(STM32G441xx) && !defined(STM32G441_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32G441_MCUCONF not defined"
+
+#elif defined(STM32G471xx) && !defined(STM32G471_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32G471_MCUCONF not defined"
+
+#elif defined(STM32G473xx) && !defined(STM32G473_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32G473_MCUCONF not defined"
+
+#elif defined(STM32G483xx) && !defined(STM32G473_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32G483_MCUCONF not defined"
+
+#elif defined(STM32G474xx) && !defined(STM32G474_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32G474_MCUCONF not defined"
+
+#elif defined(STM32G484xx) && !defined(STM32G484_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32G484_MCUCONF not defined"
+
+#elif defined(STM32GBK1CB) && !defined(STM32GBK1CB_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32GBK1CB_MCUCONF not defined"
+
+#endif
+
+/*
+ * Board files sanity checks.
+ */
+#if !defined(STM32_LSECLK)
+#error "STM32_LSECLK not defined in board.h"
+#endif
+
+#if !defined(STM32_LSEDRV)
+#error "STM32_LSEDRV not defined in board.h"
+#endif
+
+#if !defined(STM32_HSECLK)
+#error "STM32_HSECLK not defined in board.h"
+#endif
+
+/* Voltage related limits.*/
+#if (STM32_VOS == STM32_VOS_RANGE1) || defined(__DOXYGEN__)
+/**
+ * @name System Limits
+ * @{
+ */
+/**
+ * @brief Maximum SYSCLK clock frequency.
+ */
+#define STM32_SYSCLK_MAX 170000000
+
+/**
+ * @brief Maximum SYSCLK clock frequency without voltage boost.
+ */
+#define STM32_SYSCLK_MAX_NOBOOST 150000000
+
+/**
+ * @brief Maximum HSE clock frequency at current voltage setting.
+ */
+#define STM32_HSECLK_MAX 48000000
+
+/**
+ * @brief Maximum HSE clock frequency using an external source.
+ */
+#define STM32_HSECLK_BYP_MAX 48000000
+
+/**
+ * @brief Minimum HSE clock frequency.
+ */
+#define STM32_HSECLK_MIN 8000000
+
+/**
+ * @brief Minimum HSE clock frequency using an external source.
+ */
+#define STM32_HSECLK_BYP_MIN 8000000
+
+/**
+ * @brief Maximum LSE clock frequency.
+ */
+#define STM32_LSECLK_MAX 32768
+
+/**
+ * @brief Maximum LSE clock frequency.
+ */
+#define STM32_LSECLK_BYP_MAX 1000000
+
+/**
+ * @brief Minimum LSE clock frequency.
+ */
+#define STM32_LSECLK_MIN 32768
+
+/**
+ * @brief Minimum LSE clock frequency.
+ */
+#define STM32_LSECLK_BYP_MIN 32768
+
+/**
+ * @brief Maximum PLLs input clock frequency.
+ */
+#define STM32_PLLIN_MAX 16000000
+
+/**
+ * @brief Minimum PLLs input clock frequency.
+ */
+#define STM32_PLLIN_MIN 2660000
+
+/**
+ * @brief Maximum VCO clock frequency at current voltage setting.
+ */
+#define STM32_PLLVCO_MAX 344000000
+
+/**
+ * @brief Minimum VCO clock frequency at current voltage setting.
+ */
+#define STM32_PLLVCO_MIN 96000000
+
+/**
+ * @brief Maximum PLL-P output clock frequency.
+ */
+#define STM32_PLLP_MAX 170000000
+
+/**
+ * @brief Minimum PLL-P output clock frequency.
+ */
+#define STM32_PLLP_MIN 2064500
+
+/**
+ * @brief Maximum PLL-Q output clock frequency.
+ */
+#define STM32_PLLQ_MAX 170000000
+
+/**
+ * @brief Minimum PLL-Q output clock frequency.
+ */
+#define STM32_PLLQ_MIN 8000000
+
+/**
+ * @brief Maximum PLL-R output clock frequency.
+ */
+#define STM32_PLLR_MAX 170000000
+
+/**
+ * @brief Minimum PLL-R output clock frequency.
+ */
+#define STM32_PLLR_MIN 8000000
+
+/**
+ * @brief Maximum APB clock frequency.
+ */
+#define STM32_PCLK1_MAX 170000000
+
+/**
+ * @brief Maximum APB clock frequency.
+ */
+#define STM32_PCLK2_MAX 170000000
+
+/**
+ * @brief Maximum ADC clock frequency.
+ */
+#define STM32_ADCCLK_MAX 60000000
+/** @} */
+
+/**
+ * @name Flash Wait states
+ * @{
+ */
+#define STM32_0WS_THRESHOLD 20000000
+#define STM32_1WS_THRESHOLD 40000000
+#define STM32_2WS_THRESHOLD 60000000
+#define STM32_3WS_THRESHOLD 80000000
+#define STM32_4WS_THRESHOLD 100000000
+#define STM32_5WS_THRESHOLD 120000000
+#define STM32_6WS_THRESHOLD 140000000
+#define STM32_7WS_THRESHOLD 160000000
+#define STM32_8WS_THRESHOLD 170000000
+/** @} */
+
+#elif STM32_VOS == STM32_VOS_RANGE2
+#define STM32_SYSCLK_MAX 26000000
+#define STM32_SYSCLK_MAX_NOBOOST 150000000
+#define STM32_HSECLK_MAX 26000000
+#define STM32_HSECLK_BYP_MAX 26000000
+#define STM32_HSECLK_MIN 8000000
+#define STM32_HSECLK_BYP_MIN 8000000
+#define STM32_LSECLK_MAX 32768
+#define STM32_LSECLK_BYP_MAX 1000000
+#define STM32_LSECLK_MIN 32768
+#define STM32_LSECLK_BYP_MIN 32768
+#define STM32_PLLIN_MAX 16000000
+#define STM32_PLLIN_MIN 2660000
+#define STM32_PLLVCO_MAX 128000000
+#define STM32_PLLVCO_MIN 96000000
+#define STM32_PLLP_MAX 26000000
+#define STM32_PLLP_MIN 2064500
+#define STM32_PLLQ_MAX 26000000
+#define STM32_PLLQ_MIN 8000000
+#define STM32_PLLR_MAX 26000000
+#define STM32_PLLR_MIN 8000000
+#define STM32_PCLK1_MAX 26000000
+#define STM32_PCLK2_MAX 26000000
+#define STM32_ADCCLK_MAX 26000000
+
+#define STM32_0WS_THRESHOLD 8000000
+#define STM32_1WS_THRESHOLD 16000000
+#define STM32_2WS_THRESHOLD 26000000
+#define STM32_3WS_THRESHOLD 0
+#define STM32_4WS_THRESHOLD 0
+#define STM32_5WS_THRESHOLD 0
+#define STM32_6WS_THRESHOLD 0
+#define STM32_7WS_THRESHOLD 0
+#define STM32_8WS_THRESHOLD 0
+
+#else
+#error "invalid STM32_VOS value specified"
+#endif
+
+/*
+ * HSI16 related checks.
+ */
+#if STM32_HSI16_ENABLED
+#else /* !STM32_HSI16_ENABLED */
+
+ #if STM32_SW == STM32_SW_HSI16
+ #error "HSI16 not enabled, required by STM32_SW"
+ #endif
+
+ #if (STM32_SW == STM32_SW_PLLRCLK) && (STM32_PLLSRC == STM32_PLLSRC_HSI16)
+ #error "HSI16 not enabled, required by STM32_SW and STM32_PLLSRC"
+ #endif
+
+ #if (STM32_MCOSEL == STM32_MCOSEL_HSI16) || \
+ ((STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) && \
+ (STM32_PLLSRC == STM32_PLLSRC_HSI16))
+ #error "HSI16 not enabled, required by STM32_MCOSEL"
+ #endif
+
+ #if (STM32_USART1SEL == STM32_USART1SEL_HSI16)
+ #error "HSI16 not enabled, required by STM32_USART1SEL"
+ #endif
+ #if (STM32_USART2SEL == STM32_USART2SEL_HSI16)
+ #error "HSI16 not enabled, required by STM32_USART2SEL"
+ #endif
+ #if (STM32_USART3SEL == STM32_USART3SEL_HSI16)
+ #error "HSI16 not enabled, required by STM32_USART3SEL"
+ #endif
+ #if (STM32_UART4SEL == STM32_UART4SEL_HSI16)
+ #error "HSI16 not enabled, required by STM32_UART4SEL_HSI16"
+ #endif
+ #if (STM32_UART5SEL == STM32_UART5SEL_HSI16)
+ #error "HSI16 not enabled, required by STM32_UART5SEL_HSI16"
+ #endif
+ #if (STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16)
+ #error "HSI16 not enabled, required by STM32_LPUART1SEL"
+ #endif
+
+ #if (STM32_I2C1SEL == STM32_I2C1SEL_HSI16)
+ #error "HSI16 not enabled, required by STM32_I2C1SEL"
+ #endif
+ #if (STM32_I2C2SEL == STM32_I2C2SEL_HSI16)
+ #error "HSI16 not enabled, required by STM32_I2C2SEL"
+ #endif
+ #if (STM32_I2C3SEL == STM32_I2C3SEL_HSI16)
+ #error "HSI16 not enabled, required by STM32_I2C3SEL"
+ #endif
+ #if (STM32_I2C4SEL == STM32_I2C4SEL_HSI16)
+ #error "HSI16 not enabled, required by STM32_I2C4SEL"
+ #endif
+
+ #if (STM32_SAI1SEL == STM32_SAI1SEL_HSI16)
+ #error "HSI16 not enabled, required by STM32_SAI1SEL"
+ #endif
+ #if (STM32_I2S23SEL == STM32_I2S23SEL_HSI16)
+ #error "HSI16 not enabled, required by STM32_I2S23SEL"
+ #endif
+
+ #if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16)
+ #error "HSI16 not enabled, required by STM32_LPTIM1SEL"
+ #endif
+
+ #if (STM32_QSPISEL == STM32_QSPISEL_HSI16)
+ #error "HSI16 not enabled, required by STM32_QSPISEL_HSI16"
+ #endif
+
+#endif /* !STM32_HSI16_ENABLED */
+
+/*
+ * HSI48 related checks.
+ */
+#if STM32_HSI48_ENABLED
+#else /* !STM32_HSI48_ENABLED */
+
+ #if STM32_MCOSEL == STM32_MCOSEL_HSI48
+ #error "HSI48 not enabled, required by STM32_MCOSEL"
+ #endif
+
+ #if STM32_CLK48SEL == STM32_CLK48SEL_HSI48
+ #error "HSI48 not enabled, required by STM32_CLK48SEL"
+ #endif
+
+#endif /* !STM32_HSI48_ENABLED */
+
+/*
+ * HSE related checks.
+ */
+#if STM32_HSE_ENABLED
+
+ #if STM32_HSECLK == 0
+ #error "HSE frequency not defined"
+ #else /* STM32_HSECLK != 0 */
+ #if defined(STM32_HSE_BYPASS)
+ #if (STM32_HSECLK < STM32_HSECLK_BYP_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX)
+ #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_BYP_MIN...STM32_HSECLK_BYP_MAX)"
+ #endif
+ #else /* !defined(STM32_HSE_BYPASS) */
+ #if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX)
+ #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)"
+ #endif
+ #endif /* !defined(STM32_HSE_BYPASS) */
+ #endif /* STM32_HSECLK != 0 */
+
+#else /* !STM32_HSE_ENABLED */
+
+ #if STM32_SW == STM32_SW_HSE
+ #error "HSE not enabled, required by STM32_SW"
+ #endif
+
+ #if (STM32_SW == STM32_SW_PLLRCLK) && (STM32_PLLSRC == STM32_PLLSRC_HSE)
+ #error "HSE not enabled, required by STM32_SW and STM32_PLLSRC"
+ #endif
+
+ #if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \
+ ((STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) && \
+ (STM32_PLLSRC == STM32_PLLSRC_HSE))
+ #error "HSE not enabled, required by STM32_MCOSEL"
+ #endif
+
+ #if STM32_RTCSEL == STM32_RTCSEL_HSEDIV
+ #error "HSE not enabled, required by STM32_RTCSEL"
+ #endif
+
+#endif /* !STM32_HSE_ENABLED */
+
+/*
+ * LSI related checks.
+ */
+#if STM32_LSI_ENABLED
+#else /* !STM32_LSI_ENABLED */
+
+ #if STM32_RTCSEL == STM32_RTCSEL_LSI
+ #error "LSI not enabled, required by STM32_RTCSEL"
+ #endif
+
+ #if STM32_MCOSEL == STM32_MCOSEL_LSI
+ #error "LSI not enabled, required by STM32_MCOSEL"
+ #endif
+
+ #if STM32_LSCOSEL == STM32_LSCOSEL_LSI
+ #error "LSI not enabled, required by STM32_LSCOSEL"
+ #endif
+
+#endif /* !STM32_LSI_ENABLED */
+
+/*
+ * LSE related checks.
+ */
+#if STM32_LSE_ENABLED
+
+ #if (STM32_LSECLK == 0)
+ #error "LSE frequency not defined"
+ #endif
+
+ #if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX)
+ #error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)"
+ #endif
+
+#else /* !STM32_LSE_ENABLED */
+
+ #if STM32_RTCSEL == STM32_RTCSEL_LSE
+ #error "LSE not enabled, required by STM32_RTCSEL"
+ #endif
+
+ #if STM32_MCOSEL == STM32_MCOSEL_LSE
+ #error "LSE not enabled, required by STM32_MCOSEL"
+ #endif
+
+ #if STM32_LSCOSEL == STM32_LSCOSEL_LSE
+ #error "LSE not enabled, required by STM32_LSCOSEL"
+ #endif
+
+#endif /* !STM32_LSE_ENABLED */
+
+/**
+ * @brief STM32_PLLM field.
+ */
+#if ((STM32_PLLM_VALUE >= 1) && (STM32_PLLM_VALUE <= 16)) || \
+ defined(__DOXYGEN__)
+ #define STM32_PLLM ((STM32_PLLM_VALUE - 1) << 4)
+#else
+ #error "invalid STM32_PLLM_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL input clock frequency.
+ */
+#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__)
+ #define STM32_PLLCLKIN (STM32_HSECLK / STM32_PLLM_VALUE)
+
+#elif STM32_PLLSRC == STM32_PLLSRC_HSI16
+ #define STM32_PLLCLKIN (STM32_HSI16CLK / STM32_PLLM_VALUE)
+
+#elif STM32_PLLSRC == STM32_PLLSRC_NOCLOCK
+ #define STM32_PLLCLKIN 0
+
+#else
+ #error "invalid STM32_PLLSRC value specified"
+#endif
+
+/*
+ * PLL input frequency range check.
+ */
+#if (STM32_PLLCLKIN != 0) && \
+ ((STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX))
+ #error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)"
+#endif
+
+/*
+ * PLL enable check.
+ */
+#if (STM32_SW == STM32_SW_PLLRCLK) || \
+ (STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) || \
+ (STM32_ADC12SEL == STM32_ADC12SEL_PLLPCLK) || \
+ (STM32_ADC345SEL == STM32_ADC345SEL_PLLPCLK) || \
+ (STM32_SAI1SEL == STM32_SAI1SEL_PLLQCLK) || \
+ (STM32_I2S23SEL == STM32_I2S23SEL_PLLQCLK) || \
+ (STM32_FDCANSEL == STM32_FDCANSEL_PLLQCLK) || \
+ (STM32_CLK48SEL == STM32_CLK48SEL_PLLQCLK) || \
+ (STM32_QSPISEL == STM32_QSPISEL_PLLQCLK) || \
+ defined(__DOXYGEN__)
+
+ #if STM32_PLLCLKIN == 0
+ #error "PLL activation required but no PLL clock selected"
+ #endif
+
+ /**
+ * @brief PLL activation flag.
+ */
+ #define STM32_ACTIVATE_PLL TRUE
+#else
+ #define STM32_ACTIVATE_PLL FALSE
+#endif
+
+/**
+ * @brief STM32_PLLN field.
+ */
+#if ((STM32_PLLN_VALUE >= 8) && (STM32_PLLN_VALUE <= 127)) || \
+ defined(__DOXYGEN__)
+ #define STM32_PLLN (STM32_PLLN_VALUE << 8)
+#else
+ #error "invalid STM32_PLLN_VALUE value specified"
+#endif
+
+/**
+ * @brief STM32_PLLP field.
+ */
+#if (STM32_PLLP_VALUE == 7) || defined(__DOXYGEN__)
+ #define STM32_PLLP (0 << 17)
+
+#elif STM32_PLLP_VALUE == 17
+ #define STM32_PLLP (1 << 17)
+
+#else
+ #error "invalid STM32_PLLP_VALUE value specified"
+#endif
+
+/**
+ * @brief STM32_PLLQ field.
+ */
+#if (STM32_PLLQ_VALUE == 2) || defined(__DOXYGEN__)
+ #define STM32_PLLQ (0 << 21)
+
+#elif STM32_PLLQ_VALUE == 4
+ #define STM32_PLLQ (1 << 21)
+
+#elif STM32_PLLQ_VALUE == 6
+ #define STM32_PLLQ (2 << 21)
+
+#elif STM32_PLLQ_VALUE == 8
+ #define STM32_PLLQ (3 << 21)
+
+#else
+ #error "invalid STM32_PLLQ_VALUE value specified"
+#endif
+
+/**
+ * @brief STM32_PLLR field.
+ */
+#if (STM32_PLLR_VALUE == 2) || defined(__DOXYGEN__)
+ #define STM32_PLLR (0 << 25)
+
+#elif STM32_PLLR_VALUE == 4
+ #define STM32_PLLR (1 << 25)
+
+#elif STM32_PLLR_VALUE == 6
+ #define STM32_PLLR (2 << 25)
+
+#elif STM32_PLLR_VALUE == 8
+ #define STM32_PLLR (3 << 25)
+
+#else
+ #error "invalid STM32_PLLR_VALUE value specified"
+#endif
+
+/**
+ * @brief STM32_PLLPDIV field.
+ */
+#if (STM32_PLLPDIV_VALUE == 0) || \
+ ((STM32_PLLPDIV_VALUE >= 2) && (STM32_PLLPDIV_VALUE <= 31)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLLPDIV (STM32_PLLPDIV_VALUE << 27)
+#else
+#error "invalid STM32_PLLPDIV_VALUE value specified"
+#endif
+
+/**
+ * @brief STM32_PLLPEN field.
+ */
+#if (STM32_ADC12SEL == STM32_ADC12SEL_PLLPCLK) || \
+ (STM32_ADC345SEL == STM32_ADC345SEL_PLLPCLK) || \
+ defined(__DOXYGEN__)
+ #define STM32_PLLPEN (1 << 16)
+#else
+ #define STM32_PLLPEN (0 << 16)
+#endif
+
+/**
+ * @brief STM32_PLLQEN field.
+ */
+#if (STM32_QSPISEL == STM32_QSPISEL_PLLQCLK) || \
+ (STM32_FDCANSEL == STM32_FDCANSEL_PLLQCLK) || \
+ (STM32_CLK48SEL == STM32_CLK48SEL_PLLQCLK) || \
+ (STM32_SAI1SEL == STM32_SAI1SEL_PLLQCLK) || \
+ (STM32_I2S23SEL == STM32_I2S23SEL_PLLQCLK) || \
+ defined(__DOXYGEN__)
+ #define STM32_PLLQEN (1 << 20)
+#else
+ #define STM32_PLLQEN (0 << 20)
+#endif
+
+/**
+ * @brief STM32_PLLREN field.
+ */
+#if (STM32_SW == STM32_SW_PLLRCLK) || \
+ (STM32_MCOSEL == STM32_MCOSEL_PLLRCLK) || \
+ defined(__DOXYGEN__)
+ #define STM32_PLLREN (1 << 24)
+#else
+ #define STM32_PLLREN (0 << 24)
+#endif
+
+/**
+ * @brief PLL VCO frequency.
+ */
+#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE)
+
+/*
+ * PLL VCO frequency range check.
+ */
+#if STM32_ACTIVATE_PLL && \
+ ((STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX))
+ #error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)"
+#endif
+
+/**
+ * @brief PLL P output clock frequency.
+ */
+#if (STM32_PLLPDIV_VALUE == 0) || defined(__DOXYGEN__)
+ #define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE)
+#else
+ #define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLPDIV_VALUE)
+#endif
+
+/**
+ * @brief PLL Q output clock frequency.
+ */
+#define STM32_PLL_Q_CLKOUT (STM32_PLLVCO / STM32_PLLQ_VALUE)
+
+/**
+ * @brief PLL R output clock frequency.
+ */
+#define STM32_PLL_R_CLKOUT (STM32_PLLVCO / STM32_PLLR_VALUE)
+
+/*
+ * PLL-P output frequency range check.
+ */
+#if STM32_ACTIVATE_PLL && \
+ ((STM32_PLL_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLL_P_CLKOUT > STM32_PLLP_MAX))
+ #error "STM32_PLL_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)"
+#endif
+
+/*
+ * PLL-Q output frequency range check.
+ */
+#if STM32_ACTIVATE_PLL && \
+ ((STM32_PLL_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLL_Q_CLKOUT > STM32_PLLQ_MAX))
+ #error "STM32_PLL_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)"
+#endif
+
+/*
+ * PLL-R output frequency range check.
+ */
+#if STM32_ACTIVATE_PLL && \
+ ((STM32_PLL_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLL_R_CLKOUT > STM32_PLLR_MAX))
+ #error "STM32_PLL_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)"
+#endif
+
+/**
+ * @brief System clock source.
+ */
+#if STM32_NO_INIT || defined(__DOXYGEN__)
+ #define STM32_SYSCLK STM32_HSI16CLK
+
+#elif (STM32_SW == STM32_SW_HSI16)
+ #define STM32_SYSCLK STM32_HSI16CLK
+
+#elif (STM32_SW == STM32_SW_HSE)
+ #define STM32_SYSCLK STM32_HSECLK
+
+#elif (STM32_SW == STM32_SW_PLLRCLK)
+ #define STM32_SYSCLK STM32_PLL_R_CLKOUT
+
+#else
+ #error "invalid STM32_SW value specified"
+#endif
+
+/*
+ * Check on the system clock.
+ */
+#if STM32_SYSCLK > STM32_SYSCLK_MAX
+ #error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)"
+#endif
+
+/**
+ * @brief AHB frequency.
+ */
+#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__)
+ #define STM32_HCLK (STM32_SYSCLK / 1)
+
+#elif STM32_HPRE == STM32_HPRE_DIV2
+ #define STM32_HCLK (STM32_SYSCLK / 2)
+
+#elif STM32_HPRE == STM32_HPRE_DIV4
+ #define STM32_HCLK (STM32_SYSCLK / 4)
+
+#elif STM32_HPRE == STM32_HPRE_DIV8
+ #define STM32_HCLK (STM32_SYSCLK / 8)
+
+#elif STM32_HPRE == STM32_HPRE_DIV16
+ #define STM32_HCLK (STM32_SYSCLK / 16)
+
+#elif STM32_HPRE == STM32_HPRE_DIV64
+ #define STM32_HCLK (STM32_SYSCLK / 64)
+
+#elif STM32_HPRE == STM32_HPRE_DIV128
+ #define STM32_HCLK (STM32_SYSCLK / 128)
+
+#elif STM32_HPRE == STM32_HPRE_DIV256
+ #define STM32_HCLK (STM32_SYSCLK / 256)
+
+#elif STM32_HPRE == STM32_HPRE_DIV512
+ #define STM32_HCLK (STM32_SYSCLK / 512)
+
+#else
+ #error "invalid STM32_HPRE value specified"
+#endif
+
+/*
+ * AHB frequency check.
+ */
+#if STM32_HCLK > STM32_SYSCLK_MAX
+ #error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)"
+#endif
+
+/**
+ * @brief APB1 frequency.
+ */
+#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__)
+ #define STM32_PCLK1 (STM32_HCLK / 1)
+
+#elif STM32_PPRE1 == STM32_PPRE1_DIV2
+ #define STM32_PCLK1 (STM32_HCLK / 2)
+
+#elif STM32_PPRE1 == STM32_PPRE1_DIV4
+ #define STM32_PCLK1 (STM32_HCLK / 4)
+
+#elif STM32_PPRE1 == STM32_PPRE1_DIV8
+ #define STM32_PCLK1 (STM32_HCLK / 8)
+
+#elif STM32_PPRE1 == STM32_PPRE1_DIV16
+ #define STM32_PCLK1 (STM32_HCLK / 16)
+
+#else
+ #error "invalid STM32_PPRE1 value specified"
+#endif
+
+/*
+ * APB1 frequency check.
+ */
+#if STM32_PCLK1 > STM32_PCLK1_MAX
+#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)"
+#endif
+
+/**
+ * @brief APB2 frequency.
+ */
+#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__)
+ #define STM32_PCLK2 (STM32_HCLK / 1)
+
+#elif STM32_PPRE2 == STM32_PPRE2_DIV2
+ #define STM32_PCLK2 (STM32_HCLK / 2)
+
+#elif STM32_PPRE2 == STM32_PPRE2_DIV4
+ #define STM32_PCLK2 (STM32_HCLK / 4)
+
+#elif STM32_PPRE2 == STM32_PPRE2_DIV8
+ #define STM32_PCLK2 (STM32_HCLK / 8)
+
+#elif STM32_PPRE2 == STM32_PPRE2_DIV16
+ #define STM32_PCLK2 (STM32_HCLK / 16)
+
+#else
+ #error "invalid STM32_PPRE2 value specified"
+#endif
+
+/*
+ * APB2 frequency check.
+ */
+#if STM32_PCLK2 > STM32_PCLK2_MAX
+#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)"
+#endif
+
+/**
+ * @brief MCO divider clock frequency.
+ */
+#if (STM32_MCOSEL == STM32_MCOSEL_NOCLOCK) || defined(__DOXYGEN__)
+ #define STM32_MCODIVCLK 0
+
+#elif STM32_MCOSEL == STM32_MCOSEL_SYSCLK
+ #define STM32_MCODIVCLK STM32_SYSCLK
+
+#elif STM32_MCOSEL == STM32_MCOSEL_HSI16
+ #define STM32_MCODIVCLK STM32_HSI16CLK
+
+#elif STM32_MCOSEL == STM32_MCOSEL_HSE
+ #define STM32_MCODIVCLK STM32_HSECLK
+
+#elif STM32_MCOSEL == STM32_MCOSEL_PLLRCLK
+ #define STM32_MCODIVCLK STM32_PLL_R_CLKOUT
+
+#elif STM32_MCOSEL == STM32_MCOSEL_LSI
+ #define STM32_MCODIVCLK STM32_LSICLK
+
+#elif STM32_MCOSEL == STM32_MCOSEL_LSE
+ #define STM32_MCODIVCLK STM32_LSECLK
+
+#elif STM32_MCOSEL == STM32_MCOSEL_HSI48
+ #define STM32_MCODIVCLK STM32_HSI48CLK
+
+#else
+ #error "invalid STM32_MCOSEL value specified"
+#endif
+
+/**
+ * @brief MCO output pin clock frequency.
+ */
+#if (STM32_MCOPRE == STM32_MCOPRE_DIV1) || defined(__DOXYGEN__)
+ #define STM32_MCOCLK STM32_MCODIVCLK
+
+#elif STM32_MCOPRE == STM32_MCOPRE_DIV2
+ #define STM32_MCOCLK (STM32_MCODIVCLK / 2)
+
+#elif STM32_MCOPRE == STM32_MCOPRE_DIV4
+ #define STM32_MCOCLK (STM32_MCODIVCLK / 4)
+
+#elif STM32_MCOPRE == STM32_MCOPRE_DIV8
+ #define STM32_MCOCLK (STM32_MCODIVCLK / 8)
+
+#elif STM32_MCOPRE == STM32_MCOPRE_DIV16
+ #define STM32_MCOCLK (STM32_MCODIVCLK / 16)
+
+#else
+#error "invalid STM32_MCOPRE value specified"
+#endif
+
+/**
+ * @brief RTC clock frequency.
+ */
+#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__)
+ #define STM32_RTCCLK 0
+
+#elif STM32_RTCSEL == STM32_RTCSEL_LSE
+ #define STM32_RTCCLK STM32_LSECLK
+
+#elif STM32_RTCSEL == STM32_RTCSEL_LSI
+ #define STM32_RTCCLK STM32_LSICLK
+
+#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV
+ #define STM32_RTCCLK (STM32_HSECLK / 32)
+
+#else
+ #error "invalid STM32_RTCSEL value specified"
+#endif
+
+/**
+ * @brief USART1 clock frequency.
+ */
+#if (STM32_USART1SEL == STM32_USART1SEL_PCLK2) || defined(__DOXYGEN__)
+ #define STM32_USART1CLK STM32_PCLK2
+
+#elif STM32_USART1SEL == STM32_USART1SEL_SYSCLK
+ #define STM32_USART1CLK STM32_SYSCLK
+
+#elif STM32_USART1SEL == STM32_USART1SEL_HSI16
+ #define STM32_USART1CLK STM32_HSI16CLK
+
+#elif STM32_USART1SEL == STM32_USART1SEL_LSE
+ #define STM32_USART1CLK STM32_LSECLK
+
+#else
+ #error "invalid source selected for USART1 clock"
+#endif
+
+ /**
+ * @brief USART2 clock frequency.
+ */
+ #if (STM32_USART2SEL == STM32_USART2SEL_PCLK1) || defined(__DOXYGEN__)
+ #define STM32_USART2CLK STM32_PCLK1
+
+ #elif STM32_USART2SEL == STM32_USART2SEL_SYSCLK
+ #define STM32_USART2CLK STM32_SYSCLK
+
+ #elif STM32_USART2SEL == STM32_USART2SEL_HSI16
+ #define STM32_USART2CLK STM32_HSI16CLK
+
+ #elif STM32_USART2SEL == STM32_USART2SEL_LSE
+ #define STM32_USART2CLK STM32_LSECLK
+
+ #else
+ #error "invalid source selected for USART2 clock"
+ #endif
+
+ /**
+ * @brief USART3 clock frequency.
+ */
+ #if (STM32_USART3SEL == STM32_USART3SEL_PCLK1) || defined(__DOXYGEN__)
+ #define STM32_USART3CLK STM32_PCLK1
+
+ #elif STM32_USART3SEL == STM32_USART3SEL_SYSCLK
+ #define STM32_USART3CLK STM32_SYSCLK
+
+ #elif STM32_USART3SEL == STM32_USART3SEL_HSI16
+ #define STM32_USART3CLK STM32_HSI16CLK
+
+ #elif STM32_USART3SEL == STM32_USART3SEL_LSE
+ #define STM32_USART3CLK STM32_LSECLK
+
+ #else
+ #error "invalid source selected for USART3 clock"
+ #endif
+
+/**
+ * @brief UART4 clock frequency.
+ */
+#if (STM32_UART4SEL == STM32_UART4SEL_PCLK1) || defined(__DOXYGEN__)
+ #define STM32_UART4CLK STM32_PCLK1
+
+#elif STM32_UART4SEL == STM32_UART4SEL_SYSCLK
+ #define STM32_UART4CLK STM32_SYSCLK
+
+#elif STM32_UART4SEL == STM32_UART4SEL_HSI16
+ #define STM32_UART4CLK STM32_HSI16CLK
+
+#elif STM32_UART4SEL == STM32_UART4SEL_LSE
+ #define STM32_UART4CLK STM32_LSECLK
+
+#else
+ #error "invalid source selected for UART4 clock"
+#endif
+
+/**
+ * @brief UART5 clock frequency.
+ */
+#if (STM32_UART5SEL == STM32_UART5SEL_PCLK1) || defined(__DOXYGEN__)
+ #define STM32_UART5CLK STM32_PCLK1
+
+#elif STM32_UART5SEL == STM32_UART5SEL_SYSCLK
+ #define STM32_UART5CLK STM32_SYSCLK
+
+#elif STM32_UART5SEL == STM32_UART5SEL_HSI16
+ #define STM32_UART5CLK STM32_HSI16CLK
+
+#elif STM32_UART5SEL == STM32_UART5SEL_LSE
+ #define STM32_UART5CLK STM32_LSECLK
+
+#else
+ #error "invalid source selected for UART5 clock"
+#endif
+
+/**
+ * @brief LPUART1 clock frequency.
+ */
+#if (STM32_LPUART1SEL == STM32_LPUART1SEL_PCLK1) || defined(__DOXYGEN__)
+ #define STM32_LPUART1CLK STM32_PCLK1
+
+#elif STM32_LPUART1SEL == STM32_LPUART1SEL_SYSCLK
+ #define STM32_LPUART1CLK STM32_SYSCLK
+
+#elif STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16
+ #define STM32_LPUART1CLK STM32_HSI16CLK
+
+#elif STM32_LPUART1SEL == STM32_LPUART1SEL_LSE
+ #define STM32_LPUART1CLK STM32_LSECLK
+
+#else
+#error "invalid source selected for LPUART1 clock"
+#endif
+
+/**
+ * @brief I2C1 clock frequency.
+ */
+#if (STM32_I2C1SEL == STM32_I2C1SEL_PCLK1) || defined(__DOXYGEN__)
+ #define STM32_I2C1CLK STM32_PCLK1
+
+#elif STM32_I2C1SEL == STM32_I2C1SEL_SYSCLK
+ #define STM32_I2C1CLK STM32_SYSCLK
+
+#elif STM32_I2C1SEL == STM32_I2C1SEL_HSI16
+ #define STM32_I2C1CLK STM32_HSI16CLK
+
+#else
+ #error "invalid source selected for I2C1 clock"
+#endif
+
+/**
+ * @brief I2C2 clock frequency.
+ */
+#if (STM32_I2C2SEL == STM32_I2C2SEL_PCLK1) || defined(__DOXYGEN__)
+ #define STM32_I2C2CLK STM32_PCLK1
+
+#elif STM32_I2C2SEL == STM32_I2C2SEL_SYSCLK
+ #define STM32_I2C2CLK STM32_SYSCLK
+
+#elif STM32_I2C2SEL == STM32_I2C2SEL_HSI16
+ #define STM32_I2C2CLK STM32_HSI16CLK
+
+#else
+ #error "invalid source selected for I2C1 clock"
+#endif
+
+/**
+ * @brief I2C3 clock frequency.
+ */
+#if (STM32_I2C3SEL == STM32_I2C3SEL_PCLK1) || defined(__DOXYGEN__)
+ #define STM32_I2C3CLK STM32_PCLK1
+
+#elif STM32_I2C3SEL == STM32_I2C3SEL_SYSCLK
+ #define STM32_I2C3CLK STM32_SYSCLK
+
+#elif STM32_I2C3SEL == STM32_I2C3SEL_HSI16
+ #define STM32_I2C3CLK STM32_HSI16CLK
+
+#else
+ #error "invalid source selected for I2C3 clock"
+#endif
+
+/**
+ * @brief I2C4 clock frequency.
+ */
+#if (STM32_I2C4SEL == STM32_I2C4SEL_PCLK1) || defined(__DOXYGEN__)
+ #define STM32_I2C4CLK STM32_PCLK1
+
+#elif STM32_I2C4SEL == STM32_I2C4SEL_SYSCLK
+ #define STM32_I2C4CLK STM32_SYSCLK
+
+#elif STM32_I2C4SEL == STM32_I2C4SEL_HSI16
+ #define STM32_I2C4CLK STM32_HSI16CLK
+
+#else
+ #error "invalid source selected for I2C4 clock"
+#endif
+
+/**
+ * @brief LPTIM1 clock frequency.
+ */
+#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_PCLK1) || defined(__DOXYGEN__)
+ #define STM32_LPTIM1CLK STM32_PCLK1
+
+#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI
+ #define STM32_LPTIM1CLK STM32_LSICLK
+
+#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16
+ #define STM32_LPTIM1CLK STM32_HSI16CLK
+
+#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE
+ #define STM32_LPTIM1CLK STM32_LSECLK
+
+#else
+ #error "invalid source selected for LPTIM1 clock"
+#endif
+
+/**
+ * @brief SAI1 clock frequency.
+ */
+#if (STM32_SAI1SEL == STM32_SAI1SEL_SYSCLK) || defined(__DOXYGEN__)
+ #define STM32_SAI1CLK STM32_SYSCLK
+
+#elif STM32_SAI1SEL == STM32_SAI1SEL_PLLQCLK
+ #define STM32_SAI1CLK STM32_PLL_Q_CLKOUT
+
+#elif STM32_SAI1SEL == STM32_SAI1SEL_HSI16
+ #define STM32_SAI1CLK STM32_HSI16CLK
+
+#elif STM32_SAI1SEL == STM32_SAI1SEL_CKIN
+ #define STM32_SAI1CLK 0 /* Unknown, would require a board value */
+
+#else
+ #error "invalid source selected for SAI1 clock"
+#endif
+
+/**
+ * @brief I2S23 clock frequency.
+ */
+#if (STM32_I2S23SEL == STM32_I2S23SEL_SYSCLK) || defined(__DOXYGEN__)
+ #define STM32_I2S23CLK STM32_SYSCLK
+
+#elif STM32_I2S23SEL == STM32_I2S23SEL_PLLPCLK
+ #define STM32_I2S23CLK STM32_PLL_P_CLKOUT
+
+#elif STM32_I2S23SEL == STM32_I2S23SEL_HSI16
+ #define STM32_I2S23CLK STM32_HSI16CLK
+
+#elif STM32_I2S23SEL == STM32_I2S23SEL_CKIN
+ #define STM32_I2S23CLK 0 /* Unknown, would require a board value */
+
+#else
+ #error "invalid source selected for SAI1 clock"
+#endif
+
+/**
+ * @brief FDCAN clock frequency.
+ */
+#if (STM32_FDCANSEL == STM32_FDCANSEL_HSE) || defined(__DOXYGEN__)
+ #define STM32_FDCANCLK STM32_HSECLK
+
+#elif STM32_FDCANSEL == STM32_FDCANSEL_PLLQCLK
+ #define STM32_FDCANCLK STM32_PLL_Q_CLKOUT
+
+#elif STM32_FDCANSEL == STM32_FDCANSEL_PCLK1
+ #define STM32_FDCANCLK STM32_PCLK1
+
+#else
+ #error "invalid source selected for FDCAN clock"
+#endif
+
+/**
+ * @brief 48MHz clock frequency.
+ */
+#if (STM32_CLK48SEL == STM32_CLK48SEL_HSI48) || defined(__DOXYGEN__)
+ #define STM32_48CLK STM32_HSI48CLK
+
+#elif STM32_CLK48SEL == STM32_CLK48SEL_PLLQCLK
+ #define STM32_48CLK STM32_PLL_Q_CLKOUT
+
+#else
+ #error "invalid source selected for 48MHz clock"
+#endif
+
+/**
+ * @brief ADC clock frequency.
+ */
+#if (STM32_ADC12SEL == STM32_ADC12SEL_NOCLK) || defined(__DOXYGEN__)
+ #define STM32_ADC12CLK 0
+
+#elif STM32_ADC12SEL == STM32_ADC12SEL_PLLPCLK
+ #define STM32_ADC12CLK STM32_PLL_P_CLKOUT
+
+#elif STM32_ADC12SEL == STM32_ADC12SEL_SYSCLK
+ #define STM32_ADC12CLK STM32_SYSCLK
+
+#else
+ #error "invalid source selected for ADC clock"
+#endif
+
+/**
+ * @brief ADC clock frequency.
+ */
+#if (STM32_ADC345SEL == STM32_ADC345SEL_NOCLK) || defined(__DOXYGEN__)
+ #define STM32_ADC345CLK 0
+
+#elif STM32_ADC345SEL == STM32_ADC345SEL_PLLPCLK
+ #define STM32_ADC345CLK STM32_PLL_P_CLKOUT
+
+#elif STM32_ADC345SEL == STM32_ADC345SEL_SYSCLK
+ #define STM32_ADC345CLK STM32_SYSCLK
+
+#else
+ #error "invalid source selected for ADC clock"
+#endif
+
+/**
+ * @brief TIMP1CLK clock frequency.
+ */
+#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__)
+ #define STM32_TIMP1CLK (STM32_PCLK1 * 1)
+#else
+ #define STM32_TIMP1CLK (STM32_PCLK1 * 2)
+#endif
+
+/**
+ * @brief TIMP2CLK clock frequency.
+ */
+#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__)
+ #define STM32_TIMP2CLK (STM32_PCLK2 * 1)
+#else
+ #define STM32_TIMP2CLK (STM32_PCLK2 * 2)
+#endif
+
+/**
+ * @brief Clock of timers connected to APB1.
+ */
+#define STM32_TIMCLK1 STM32_TIMP1CLK
+
+/**
+ * @brief Clock of timers connected to APB2.
+ */
+#define STM32_TIMCLK2 STM32_TIMP2CLK
+
+/**
+ * @brief RNG clock point.
+ */
+#define STM32_RNGCLK STM32_48CLK
+
+/**
+ * @brief USB clock point.
+ */
+#define STM32_USBCLK STM32_48CLK
+
+/**
+ * @brief Flash settings.
+ */
+#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__)
+ #define STM32_FLASHBITS 0
+
+#elif STM32_HCLK <= STM32_1WS_THRESHOLD
+ #define STM32_FLASHBITS FLASH_ACR_LATENCY_0WS
+
+#elif STM32_HCLK <= STM32_2WS_THRESHOLD
+ #define STM32_FLASHBITS FLASH_ACR_LATENCY_1WS
+
+#elif STM32_HCLK <= STM32_3WS_THRESHOLD
+ #define STM32_FLASHBITS FLASH_ACR_LATENCY_2WS
+
+#elif STM32_HCLK <= STM32_4WS_THRESHOLD
+ #define STM32_FLASHBITS FLASH_ACR_LATENCY_3WS
+
+#elif STM32_HCLK <= STM32_5WS_THRESHOLD
+ #define STM32_FLASHBITS FLASH_ACR_LATENCY_4WS
+
+#elif STM32_HCLK <= STM32_6WS_THRESHOLD
+ #define STM32_FLASHBITS FLASH_ACR_LATENCY_5WS
+
+#elif STM32_HCLK <= STM32_7WS_THRESHOLD
+ #define STM32_FLASHBITS FLASH_ACR_LATENCY_6WS
+
+#elif STM32_HCLK <= STM32_8WS_THRESHOLD
+ #define STM32_FLASHBITS FLASH_ACR_LATENCY_7WS
+
+#else
+ #define STM32_FLASHBITS FLASH_ACR_LATENCY_8WS
+#endif
+
+/* Frequency-dependent settings for PWR_CR5.*/
+#if STM32_SYSCLK > STM32_SYSCLK_MAX_NOBOOST
+#define STM32_CR5BITS 0
+#else
+#define STM32_CR5BITS PWR_CR5_R1MODE
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/* Various helpers.*/
+#include "nvic.h"
+#include "cache.h"
+#include "mpu_v7m.h"
+#include "stm32_isr.h"
+#include "stm32_dma.h"
+#include "stm32_exti.h"
+#include "stm32_rcc.h"
+#include "stm32_tim.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void hal_lld_init(void);
+ void stm32_clock_init(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/platform.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/platform.mk
new file mode 100644
index 0000000..f1d83a1
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/platform.mk
@@ -0,0 +1,46 @@
+# Required platform files.
+PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \
+ $(CHIBIOS)/os/hal/ports/STM32/STM32G4xx/stm32_isr.c \
+ $(CHIBIOS)/os/hal/ports/STM32/STM32G4xx/hal_lld.c
+
+# Required include directories.
+PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \
+ $(CHIBIOS)/os/hal/ports/STM32/STM32G4xx
+
+# Optional platform files.
+ifeq ($(USE_SMART_BUILD),yes)
+
+# Configuration files directory
+ifeq ($(HALCONFDIR),)
+ ifeq ($(CONFDIR),)
+ HALCONFDIR = .
+ else
+ HALCONFDIR := $(CONFDIR)
+ endif
+endif
+
+HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define"))
+
+else
+endif
+
+# Drivers compatible with the platform.
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/FDCANv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv3/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk
+
+# Shared variables
+ALLCSRC += $(PLATFORMSRC)
+ALLINC += $(PLATFORMINC)
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/stm32_dmamux.h b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/stm32_dmamux.h
new file mode 100644
index 0000000..f4aec57
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/stm32_dmamux.h
@@ -0,0 +1,183 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32G4xx/stm32_dmamux.h
+ * @brief STM32G4xx DMAMUX handler header.
+ *
+ * @addtogroup STM32G4xx_DMAMUX
+ * @{
+ */
+
+#ifndef STM32_DMAMUX_H
+#define STM32_DMAMUX_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name DMAMUX1 request sources
+ * @{
+ */
+#define STM32_DMAMUX1_REQ_GEN0 1
+#define STM32_DMAMUX1_REQ_GEN1 2
+#define STM32_DMAMUX1_REQ_GEN2 3
+#define STM32_DMAMUX1_REQ_GEN3 4
+#define STM32_DMAMUX1_ADC1 5
+#define STM32_DMAMUX1_DAC1_CH1 6
+#define STM32_DMAMUX1_DAC1_CH2 7
+#define STM32_DMAMUX1_TIM6_UP 8
+#define STM32_DMAMUX1_TIM7_UP 9
+#define STM32_DMAMUX1_SPI1_RX 10
+#define STM32_DMAMUX1_SPI1_TX 11
+#define STM32_DMAMUX1_SPI2_RX 12
+#define STM32_DMAMUX1_SPI2_TX 13
+#define STM32_DMAMUX1_SPI3_RX 14
+#define STM32_DMAMUX1_SPI3_TX 15
+#define STM32_DMAMUX1_I2C1_RX 16
+#define STM32_DMAMUX1_I2C1_TX 17
+#define STM32_DMAMUX1_I2C2_RX 18
+#define STM32_DMAMUX1_I2C2_TX 19
+#define STM32_DMAMUX1_I2C3_RX 20
+#define STM32_DMAMUX1_I2C3_TX 21
+#define STM32_DMAMUX1_I2C4_RX 22
+#define STM32_DMAMUX1_I2C4_TX 23
+#define STM32_DMAMUX1_USART1_RX 24
+#define STM32_DMAMUX1_USART1_TX 25
+#define STM32_DMAMUX1_USART2_RX 26
+#define STM32_DMAMUX1_USART2_TX 27
+#define STM32_DMAMUX1_USART3_RX 28
+#define STM32_DMAMUX1_USART3_TX 29
+#define STM32_DMAMUX1_UART4_RX 30
+#define STM32_DMAMUX1_UART4_TX 31
+#define STM32_DMAMUX1_UART5_RX 32
+#define STM32_DMAMUX1_UART5_TX 33
+#define STM32_DMAMUX1_LPUART1_RX 34
+#define STM32_DMAMUX1_LPUART1_TX 35
+#define STM32_DMAMUX1_ADC2 36
+#define STM32_DMAMUX1_ADC3 37
+#define STM32_DMAMUX1_ADC4 38
+#define STM32_DMAMUX1_ADC5 39
+#define STM32_DMAMUX1_QUADSPI 40
+#define STM32_DMAMUX1_DAC2_CH1 41
+#define STM32_DMAMUX1_TIM1_CH1 42
+#define STM32_DMAMUX1_TIM1_CH2 43
+#define STM32_DMAMUX1_TIM1_CH3 44
+#define STM32_DMAMUX1_TIM1_CH4 45
+#define STM32_DMAMUX1_TIM1_UP 46
+#define STM32_DMAMUX1_TIM1_TRIG 47
+#define STM32_DMAMUX1_TIM1_COM 48
+#define STM32_DMAMUX1_TIM8_CH1 49
+#define STM32_DMAMUX1_TIM8_CH2 50
+#define STM32_DMAMUX1_TIM8_CH3 51
+#define STM32_DMAMUX1_TIM8_CH4 52
+#define STM32_DMAMUX1_TIM8_UP 53
+#define STM32_DMAMUX1_TIM8_TRIG 54
+#define STM32_DMAMUX1_TIM8_COM 55
+#define STM32_DMAMUX1_TIM2_CH1 56
+#define STM32_DMAMUX1_TIM2_CH2 57
+#define STM32_DMAMUX1_TIM2_CH3 58
+#define STM32_DMAMUX1_TIM2_CH4 59
+#define STM32_DMAMUX1_TIM2_UP 60
+#define STM32_DMAMUX1_TIM3_CH1 61
+#define STM32_DMAMUX1_TIM3_CH2 62
+#define STM32_DMAMUX1_TIM3_CH3 63
+#define STM32_DMAMUX1_TIM3_CH4 64
+#define STM32_DMAMUX1_TIM3_UP 65
+#define STM32_DMAMUX1_TIM3_TRIG 66
+#define STM32_DMAMUX1_TIM4_CH1 67
+#define STM32_DMAMUX1_TIM4_CH2 68
+#define STM32_DMAMUX1_TIM4_CH3 69
+#define STM32_DMAMUX1_TIM4_CH4 70
+#define STM32_DMAMUX1_TIM4_UP 71
+#define STM32_DMAMUX1_TIM5_CH1 72
+#define STM32_DMAMUX1_TIM5_CH2 73
+#define STM32_DMAMUX1_TIM5_CH3 74
+#define STM32_DMAMUX1_TIM5_CH4 75
+#define STM32_DMAMUX1_TIM5_UP 76
+#define STM32_DMAMUX1_TIM5_TRIG 77
+#define STM32_DMAMUX1_TIM15_CH1 78
+#define STM32_DMAMUX1_TIM15_UP 79
+#define STM32_DMAMUX1_TIM15_TRIG 80
+#define STM32_DMAMUX1_TIM15_COM 81
+#define STM32_DMAMUX1_TIM16_CH1 82
+#define STM32_DMAMUX1_TIM16_UP 83
+#define STM32_DMAMUX1_TIM17_CH1 84
+#define STM32_DMAMUX1_TIM17_UP 85
+#define STM32_DMAMUX1_TIM20_CH1 86
+#define STM32_DMAMUX1_TIM20_CH2 87
+#define STM32_DMAMUX1_TIM20_CH3 88
+#define STM32_DMAMUX1_TIM20_CH4 89
+#define STM32_DMAMUX1_TIM20_UP 90
+#define STM32_DMAMUX1_AES_IN 91
+#define STM32_DMAMUX1_AES_OUT 92
+#define STM32_DMAMUX1_TIM20_TRIG 93
+#define STM32_DMAMUX1_TIM20_COM 94
+#define STM32_DMAMUX1_HRTIM_MASTER 95
+#define STM32_DMAMUX1_HRTIM_TIMA 96
+#define STM32_DMAMUX1_HRTIM_TIMB 97
+#define STM32_DMAMUX1_HRTIM_TIMC 98
+#define STM32_DMAMUX1_HRTIM_TIMD 99
+#define STM32_DMAMUX1_HRTIM_TIME 100
+#define STM32_DMAMUX1_HRTIM_TIMF 101
+#define STM32_DMAMUX1_DAC3_CH1 102
+#define STM32_DMAMUX1_DAC3_CH2 103
+#define STM32_DMAMUX1_DAC4_CH1 104
+#define STM32_DMAMUX1_DAC4_CH2 105
+#define STM32_DMAMUX1_SPI4_RX 106
+#define STM32_DMAMUX1_SPI4_TX 107
+#define STM32_DMAMUX1_SAI1_A 108
+#define STM32_DMAMUX1_SAI1_B 109
+#define STM32_DMAMUX1_FMAC_READ 110
+#define STM32_DMAMUX1_FMAC_WRITE 111
+#define STM32_DMAMUX1_CORDIC_READ 112
+#define STM32_DMAMUX1_CORDIC_WRITE 113
+#define STM32_DMAMUX1_UCPD1_RX 114
+#define STM32_DMAMUX1_UCPD1_TX 115
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32_DMAMUX_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/stm32_isr.c b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/stm32_isr.c
new file mode 100644
index 0000000..44138bd
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/stm32_isr.c
@@ -0,0 +1,183 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32G4xx/stm32_isr.c
+ * @brief STM32G4xx ISR handler code.
+ *
+ * @addtogroup STM32G4xx_ISR
+ * @{
+ */
+
+#include "hal.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define exti_serve_irq(pr, channel) { \
+ \
+ if ((pr) & (1U << (channel))) { \
+ _pal_isr_code(channel); \
+ } \
+}
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#include "stm32_exti0.inc"
+#include "stm32_exti1.inc"
+#include "stm32_exti2.inc"
+#include "stm32_exti3.inc"
+#include "stm32_exti4.inc"
+#include "stm32_exti5_9.inc"
+#include "stm32_exti10_15.inc"
+#include "stm32_exti16-40_41.inc"
+#include "stm32_exti17.inc"
+#include "stm32_exti18.inc"
+#include "stm32_exti19.inc"
+#include "stm32_exti20.inc"
+#include "stm32_exti21_22-29.inc"
+#include "stm32_exti30_32.inc"
+#include "stm32_exti33.inc"
+
+#include "stm32_fdcan1.inc"
+#include "stm32_fdcan2.inc"
+#include "stm32_fdcan3.inc"
+
+#include "stm32_usart1.inc"
+#include "stm32_usart2.inc"
+#include "stm32_usart3.inc"
+#include "stm32_uart4.inc"
+#include "stm32_uart5.inc"
+#include "stm32_lpuart1.inc"
+
+#include "stm32_tim1_15_16_17.inc"
+#include "stm32_tim2.inc"
+#include "stm32_tim3.inc"
+#include "stm32_tim4.inc"
+#include "stm32_tim5.inc"
+#include "stm32_tim6.inc"
+#include "stm32_tim7.inc"
+#include "stm32_tim8.inc"
+#include "stm32_tim20.inc"
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables IRQ sources.
+ *
+ * @notapi
+ */
+void irqInit(void) {
+
+ exti0_irq_init();
+ exti1_irq_init();
+ exti2_irq_init();
+ exti3_irq_init();
+ exti4_irq_init();
+ exti5_9_irq_init();
+ exti10_15_irq_init();
+ exti16_exti40_exti41_irq_init();
+ exti17_irq_init();
+ exti18_irq_init();
+ exti19_irq_init();
+ exti21_exti22_exti29_irq_init();
+ exti30_32_irq_init();
+ exti33_irq_init();
+
+ fdcan1_irq_init();
+ fdcan2_irq_init();
+ fdcan3_irq_init();
+
+ tim1_tim15_tim16_tim17_irq_init();
+ tim2_irq_init();
+ tim3_irq_init();
+ tim4_irq_init();
+ tim5_irq_init();
+ tim6_irq_init();
+ tim7_irq_init();
+ tim8_irq_init();
+ tim20_irq_init();
+
+ usart1_irq_init();
+ usart2_irq_init();
+ usart3_irq_init();
+ uart4_irq_init();
+ uart5_irq_init();
+ lpuart1_irq_init();
+}
+
+/**
+ * @brief Disables IRQ sources.
+ *
+ * @notapi
+ */
+void irqDeinit(void) {
+
+ exti0_irq_deinit();
+ exti1_irq_deinit();
+ exti2_irq_deinit();
+ exti3_irq_deinit();
+ exti4_irq_deinit();
+ exti5_9_irq_deinit();
+ exti10_15_irq_deinit();
+ exti16_exti40_exti41_irq_deinit();
+ exti17_irq_deinit();
+ exti18_irq_deinit();
+ exti19_irq_deinit();
+ exti21_exti22_exti29_irq_deinit();
+ exti30_32_irq_deinit();
+ exti33_irq_deinit();
+
+ fdcan1_irq_deinit();
+ fdcan2_irq_deinit();
+ fdcan3_irq_deinit();
+
+ tim1_tim15_tim16_tim17_irq_deinit();
+ tim2_irq_deinit();
+ tim3_irq_deinit();
+ tim4_irq_deinit();
+ tim5_irq_deinit();
+ tim6_irq_deinit();
+ tim7_irq_deinit();
+ tim8_irq_deinit();
+ tim20_irq_deinit();
+
+ usart1_irq_deinit();
+ usart2_irq_deinit();
+ usart3_irq_deinit();
+ uart4_irq_deinit();
+ uart5_irq_deinit();
+ lpuart1_irq_deinit();
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/stm32_isr.h b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/stm32_isr.h
new file mode 100644
index 0000000..a785fe6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/stm32_isr.h
@@ -0,0 +1,290 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32G4xx/stm32_isr.h
+ * @brief STM32G4xx ISR handler header.
+ *
+ * @addtogroup STM32G4xx_ISR
+ * @{
+ */
+
+#ifndef STM32_ISR_H
+#define STM32_ISR_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name ISRs suppressed in standard drivers
+ * @{
+ */
+#define STM32_TIM1_SUPPRESS_ISR
+#define STM32_TIM2_SUPPRESS_ISR
+#define STM32_TIM3_SUPPRESS_ISR
+#define STM32_TIM4_SUPPRESS_ISR
+#define STM32_TIM5_SUPPRESS_ISR
+#define STM32_TIM6_SUPPRESS_ISR
+#define STM32_TIM7_SUPPRESS_ISR
+#define STM32_TIM8_SUPPRESS_ISR
+#define STM32_TIM15_SUPPRESS_ISR
+#define STM32_TIM16_SUPPRESS_ISR
+#define STM32_TIM17_SUPPRESS_ISR
+#define STM32_TIM20_SUPPRESS_ISR
+
+#define STM32_USART1_SUPPRESS_ISR
+#define STM32_USART2_SUPPRESS_ISR
+#define STM32_USART3_SUPPRESS_ISR
+#define STM32_UART4_SUPPRESS_ISR
+#define STM32_UART5_SUPPRESS_ISR
+#define STM32_LPUART1_SUPPRESS_ISR
+/** @} */
+
+/**
+ * @name ISR names and numbers
+ * @{
+ */
+/*
+ * ADC unit.
+ */
+#define STM32_ADC1_HANDLER Vector88
+#define STM32_ADC2_HANDLER Vector88
+#define STM32_ADC3_HANDLER VectorFC
+#define STM32_ADC4_HANDLER Vector134
+#define STM32_ADC5_HANDLER Vector138
+
+#define STM32_ADC1_NUMBER 18
+#define STM32_ADC2_NUMBER 18
+#define STM32_ADC3_NUMBER 47
+#define STM32_ADC4_NUMBER 61
+#define STM32_ADC5_NUMBER 62
+
+/*
+ * DMA unit.
+ */
+#define STM32_DMA1_CH1_HANDLER Vector6C
+#define STM32_DMA1_CH2_HANDLER Vector70
+#define STM32_DMA1_CH3_HANDLER Vector74
+#define STM32_DMA1_CH4_HANDLER Vector78
+#define STM32_DMA1_CH5_HANDLER Vector7C
+#define STM32_DMA1_CH6_HANDLER Vector80
+#define STM32_DMA1_CH7_HANDLER Vector84
+#define STM32_DMA1_CH8_HANDLER Vector1C0
+#define STM32_DMA2_CH1_HANDLER Vector120
+#define STM32_DMA2_CH2_HANDLER Vector124
+#define STM32_DMA2_CH3_HANDLER Vector128
+#define STM32_DMA2_CH4_HANDLER Vector12C
+#define STM32_DMA2_CH5_HANDLER Vector130
+#define STM32_DMA2_CH6_HANDLER Vector1C4
+#define STM32_DMA2_CH7_HANDLER Vector1C8
+#define STM32_DMA2_CH8_HANDLER Vector1CC
+
+#define STM32_DMA1_CH1_NUMBER 11
+#define STM32_DMA1_CH2_NUMBER 12
+#define STM32_DMA1_CH3_NUMBER 13
+#define STM32_DMA1_CH4_NUMBER 14
+#define STM32_DMA1_CH5_NUMBER 15
+#define STM32_DMA1_CH6_NUMBER 16
+#define STM32_DMA1_CH7_NUMBER 17
+#define STM32_DMA1_CH8_NUMBER 96
+#define STM32_DMA2_CH1_NUMBER 56
+#define STM32_DMA2_CH2_NUMBER 57
+#define STM32_DMA2_CH3_NUMBER 58
+#define STM32_DMA2_CH4_NUMBER 59
+#define STM32_DMA2_CH5_NUMBER 60
+#define STM32_DMA2_CH6_NUMBER 97
+#define STM32_DMA2_CH7_NUMBER 98
+#define STM32_DMA2_CH8_NUMBER 99
+
+/*
+ * EXTI unit.
+ */
+#define STM32_EXTI0_HANDLER Vector58
+#define STM32_EXTI1_HANDLER Vector5C
+#define STM32_EXTI2_HANDLER Vector60
+#define STM32_EXTI3_HANDLER Vector64
+#define STM32_EXTI4_HANDLER Vector68
+#define STM32_EXTI5_9_HANDLER Vector9C
+#define STM32_EXTI10_15_HANDLER VectorE0
+#define STM32_EXTI164041_HANDLER Vector44 /* PVD PVM */
+#define STM32_EXTI17_HANDLER VectorE4 /* RTC ALARM */
+#define STM32_EXTI18_HANDLER VectorE8 /* USB WAKEUP */
+#define STM32_EXTI19_HANDLER Vector48 /* RTC TAMP CSS */
+#define STM32_EXTI20_HANDLER Vector4C /* RTC WAKEUP */
+#define STM32_EXTI212229_HANDLER Vector140 /* COMP1..3 */
+#define STM32_EXTI30_32_HANDLER Vector144 /* COMP4..6 */
+#define STM32_EXTI33_HANDLER Vector148 /* COMP7 */
+
+#define STM32_EXTI0_NUMBER 6
+#define STM32_EXTI1_NUMBER 7
+#define STM32_EXTI2_NUMBER 8
+#define STM32_EXTI3_NUMBER 9
+#define STM32_EXTI4_NUMBER 10
+#define STM32_EXTI5_9_NUMBER 23
+#define STM32_EXTI10_15_NUMBER 40
+#define STM32_EXTI164041_NUMBER 1
+#define STM32_EXTI17_NUMBER 41
+#define STM32_EXTI18_NUMBER 42
+#define STM32_EXTI19_NUMBER 2
+#define STM32_EXTI20_NUMBER 3
+#define STM32_EXTI212229_NUMBER 64
+#define STM32_EXTI30_32_NUMBER 65
+#define STM32_EXTI33_NUMBER 66
+
+/*
+ * FDCAN units.
+ */
+#define STM32_FDCAN1_IT0_HANDLER Vector94
+#define STM32_FDCAN1_IT1_HANDLER Vector98
+#define STM32_FDCAN2_IT0_HANDLER Vector198
+#define STM32_FDCAN2_IT1_HANDLER Vector19C
+#define STM32_FDCAN3_IT0_HANDLER Vector1A0
+#define STM32_FDCAN3_IT1_HANDLER Vector1A4
+
+#define STM32_FDCAN1_IT0_NUMBER 21
+#define STM32_FDCAN1_IT1_NUMBER 22
+#define STM32_FDCAN2_IT0_NUMBER 86
+#define STM32_FDCAN2_IT1_NUMBER 87
+#define STM32_FDCAN3_IT0_NUMBER 88
+#define STM32_FDCAN3_IT1_NUMBER 89
+
+/*
+ * I2C units.
+ */
+#define STM32_I2C1_EVENT_HANDLER VectorBC
+#define STM32_I2C1_ERROR_HANDLER VectorC0
+#define STM32_I2C2_EVENT_HANDLER VectorC4
+#define STM32_I2C2_ERROR_HANDLER VectorC8
+#define STM32_I2C3_EVENT_HANDLER Vector1B0
+#define STM32_I2C3_ERROR_HANDLER Vector1B4
+#define STM32_I2C4_EVENT_HANDLER Vector188
+#define STM32_I2C4_ERROR_HANDLER Vector18C
+
+#define STM32_I2C1_EVENT_NUMBER 31
+#define STM32_I2C1_ERROR_NUMBER 32
+#define STM32_I2C2_EVENT_NUMBER 33
+#define STM32_I2C2_ERROR_NUMBER 34
+#define STM32_I2C3_EVENT_NUMBER 92
+#define STM32_I2C3_ERROR_NUMBER 93
+#define STM32_I2C4_EVENT_NUMBER 82
+#define STM32_I2C4_ERROR_NUMBER 83
+
+/*
+ * QUADSPI unit.
+ */
+#define STM32_QUADSPI1_HANDLER Vector1BC
+#define STM32_QUADSPI1_NUMBER 95
+
+/*
+ * TIM units.
+ */
+#define STM32_TIM1_BRK_TIM15_HANDLER VectorA0
+#define STM32_TIM1_UP_TIM16_HANDLER VectorA4
+#define STM32_TIM1_TRGCO_TIM17_HANDLER VectorA8
+#define STM32_TIM1_CC_HANDLER VectorAC
+#define STM32_TIM2_HANDLER VectorB0
+#define STM32_TIM3_HANDLER VectorB4
+#define STM32_TIM4_HANDLER VectorB8
+#define STM32_TIM5_HANDLER Vector108
+#define STM32_TIM6_HANDLER Vector118
+#define STM32_TIM7_HANDLER Vector11C
+#define STM32_TIM8_BRK_HANDLER VectorEC
+#define STM32_TIM8_UP_HANDLER VectorF0
+#define STM32_TIM8_TRGCO_HANDLER VectorF4
+#define STM32_TIM8_CC_HANDLER VectorF8
+#define STM32_TIM20_BRK_HANDLER Vector174
+#define STM32_TIM20_UP_HANDLER Vector178
+#define STM32_TIM20_TRGCO_HANDLER Vector17C
+#define STM32_TIM20_CC_HANDLER Vector180
+
+#define STM32_TIM1_BRK_TIM15_NUMBER 24
+#define STM32_TIM1_UP_TIM16_NUMBER 25
+#define STM32_TIM1_TRGCO_TIM17_NUMBER 26
+#define STM32_TIM1_CC_NUMBER 27
+#define STM32_TIM2_NUMBER 28
+#define STM32_TIM3_NUMBER 29
+#define STM32_TIM4_NUMBER 30
+#define STM32_TIM5_NUMBER 50
+#define STM32_TIM6_NUMBER 54
+#define STM32_TIM7_NUMBER 55
+#define STM32_TIM8_BRK_NUMBER 43
+#define STM32_TIM8_UP_NUMBER 44
+#define STM32_TIM8_TRGCO_NUMBER 45
+#define STM32_TIM8_CC_NUMBER 46
+#define STM32_TIM20_BRK_NUMBER 77
+#define STM32_TIM20_UP_NUMBER 78
+#define STM32_TIM20_TRGCO_NUMBER 79
+#define STM32_TIM20_CC_NUMBER 80
+
+/*
+ * USART/UART units.
+ */
+#define STM32_USART1_HANDLER VectorD4
+#define STM32_USART2_HANDLER VectorD8
+#define STM32_USART3_HANDLER VectorDC
+#define STM32_UART4_HANDLER Vector110
+#define STM32_UART5_HANDLER Vector114
+#define STM32_LPUART1_HANDLER Vector1AC
+
+#define STM32_USART1_NUMBER 37
+#define STM32_USART2_NUMBER 38
+#define STM32_USART3_NUMBER 39
+#define STM32_UART4_NUMBER 52
+#define STM32_UART5_NUMBER 53
+#define STM32_LPUART1_NUMBER 91
+
+/*
+ * USB units.
+ */
+#define STM32_USB1_HP_HANDLER Vector8C
+#define STM32_USB1_LP_HANDLER Vector90
+#define STM32_USB1_HP_NUMBER 19
+#define STM32_USB1_LP_NUMBER 20
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void irqInit(void);
+ void irqDeinit(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32_ISR_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/stm32_rcc.h b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/stm32_rcc.h
new file mode 100644
index 0000000..9877f63
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/stm32_rcc.h
@@ -0,0 +1,1366 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32G4xx/stm32_rcc.h
+ * @brief RCC helper driver header.
+ * @note This file requires definitions from the ST header file
+ * @p stm32g4xx.h.
+ *
+ * @addtogroup STM32G4xx_RCC
+ * @{
+ */
+#ifndef STM32_RCC_H
+#define STM32_RCC_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Generic RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the clock of one or more peripheral on the APB1 bus (R1).
+ *
+ * @param[in] mask APB1 R1 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAPB1R1(mask, lp) { \
+ RCC->APB1ENR1 |= (mask); \
+ if (lp) \
+ RCC->APB1SMENR1 |= (mask); \
+ else \
+ RCC->APB1SMENR1 &= ~(mask); \
+ (void)RCC->APB1SMENR1; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the APB1 bus (R1).
+ *
+ * @param[in] mask APB1 R1 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAPB1R1(mask) { \
+ RCC->APB1ENR1 &= ~(mask); \
+ RCC->APB1SMENR1 &= ~(mask); \
+ (void)RCC->APB1SMENR1; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the APB1 bus (R1).
+ *
+ * @param[in] mask APB1 R1 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAPB1R1(mask) { \
+ RCC->APB1RSTR1 |= (mask); \
+ RCC->APB1RSTR1 &= ~(mask); \
+ (void)RCC->APB1RSTR1; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the APB1 bus (R2).
+ *
+ * @param[in] mask APB1 R2 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAPB1R2(mask, lp) { \
+ RCC->APB1ENR2 |= (mask); \
+ if (lp) \
+ RCC->APB1SMENR2 |= (mask); \
+ else \
+ RCC->APB1SMENR2 &= ~(mask); \
+ (void)RCC->APB1SMENR2; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the APB1 bus (R2).
+ *
+ * @param[in] mask APB1 R2 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAPB1R2(mask) { \
+ RCC->APB1ENR2 &= ~(mask); \
+ RCC->APB1SMENR2 &= ~(mask); \
+ (void)RCC->APB1SMENR2; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the APB1 bus (R2).
+ *
+ * @param[in] mask APB1 R2 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAPB1R2(mask) { \
+ RCC->APB1RSTR2 |= (mask); \
+ RCC->APB1RSTR2 &= ~(mask); \
+ (void)RCC->APB1RSTR2; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the APB2 bus.
+ *
+ * @param[in] mask APB2 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAPB2(mask, lp) { \
+ RCC->APB2ENR |= (mask); \
+ if (lp) \
+ RCC->APB2SMENR |= (mask); \
+ else \
+ RCC->APB2SMENR &= ~(mask); \
+ (void)RCC->APB2SMENR; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the APB2 bus.
+ *
+ * @param[in] mask APB2 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAPB2(mask) { \
+ RCC->APB2ENR &= ~(mask); \
+ RCC->APB2SMENR &= ~(mask); \
+ (void)RCC->APB2SMENR; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the APB2 bus.
+ *
+ * @param[in] mask APB2 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAPB2(mask) { \
+ RCC->APB2RSTR |= (mask); \
+ RCC->APB2RSTR &= ~(mask); \
+ (void)RCC->APB2RSTR; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the AHB1 bus.
+ *
+ * @param[in] mask AHB1 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAHB1(mask, lp) { \
+ RCC->AHB1ENR |= (mask); \
+ if (lp) \
+ RCC->AHB1SMENR |= (mask); \
+ else \
+ RCC->AHB1SMENR &= ~(mask); \
+ (void)RCC->AHB1SMENR; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the AHB1 bus.
+ *
+ * @param[in] mask AHB1 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAHB1(mask) { \
+ RCC->AHB1ENR &= ~(mask); \
+ RCC->AHB1SMENR &= ~(mask); \
+ (void)RCC->AHB1SMENR; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the AHB1 bus.
+ *
+ * @param[in] mask AHB1 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAHB1(mask) { \
+ RCC->AHB1RSTR |= (mask); \
+ RCC->AHB1RSTR &= ~(mask); \
+ (void)RCC->AHB1RSTR; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the AHB2 bus.
+ *
+ * @param[in] mask AHB2 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAHB2(mask, lp) { \
+ RCC->AHB2ENR |= (mask); \
+ if (lp) \
+ RCC->AHB2SMENR |= (mask); \
+ else \
+ RCC->AHB2SMENR &= ~(mask); \
+ (void)RCC->AHB2SMENR; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the AHB2 bus.
+ *
+ * @param[in] mask AHB2 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAHB2(mask) { \
+ RCC->AHB2ENR &= ~(mask); \
+ RCC->AHB2SMENR &= ~(mask); \
+ (void)RCC->AHB2SMENR; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the AHB2 bus.
+ *
+ * @param[in] mask AHB2 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAHB2(mask) { \
+ RCC->AHB2RSTR |= (mask); \
+ RCC->AHB2RSTR &= ~(mask); \
+ (void)RCC->AHB2RSTR; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the AHB3 (FSMC) bus.
+ *
+ * @param[in] mask AHB3 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAHB3(mask, lp) { \
+ RCC->AHB3ENR |= (mask); \
+ if (lp) \
+ RCC->AHB3SMENR |= (mask); \
+ else \
+ RCC->AHB3SMENR &= ~(mask); \
+ (void)RCC->AHB3SMENR; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus.
+ *
+ * @param[in] mask AHB3 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAHB3(mask) { \
+ RCC->AHB3ENR &= ~(mask); \
+ RCC->AHB3SMENR &= ~(mask); \
+ (void)RCC->AHB3SMENR; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the AHB3 (FSMC) bus.
+ *
+ * @param[in] mask AHB3 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAHB3(mask) { \
+ RCC->AHB3RSTR |= (mask); \
+ RCC->AHB3RSTR &= ~(mask); \
+ (void)RCC->AHB3RSTR; \
+}
+/** @} */
+
+/**
+ * @name ADC peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the ADC1/ADC2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableADC12(lp) rccEnableAHB2(RCC_AHB2ENR_ADC12EN, lp)
+
+/**
+ * @brief Disables the ADC1/ADC2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableADC12() rccDisableAHB2(RCC_AHB2ENR_ADC12EN)
+
+/**
+ * @brief Resets the ADC1/ADC2 peripheral.
+ *
+ * @api
+ */
+#define rccResetADC12() rccResetAHB2(RCC_AHB2RSTR_ADC12RST)
+
+/**
+ * @brief Enables the ADC3/ADC4/ADC5 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableADC345(lp) rccEnableAHB2(RCC_AHB2ENR_ADC345EN, lp)
+
+/**
+ * @brief Disables the ADC3/ADC4/ADC5 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableADC345() rccDisableAHB2(RCC_AHB2ENR_ADC345EN)
+
+/**
+ * @brief Resets the ADC3/ADC4/ADC5 peripheral.
+ *
+ * @api
+ */
+#define rccResetADC345() rccResetAHB2(RCC_AHB2RSTR_ADC345RST)
+/** @} */
+
+/**
+ * @name DAC peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the DAC1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableDAC1(lp) rccEnableAHB2(RCC_AHB2ENR_DAC1EN, lp)
+
+/**
+ * @brief Disables the DAC1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableDAC1() rccDisableAHB2(RCC_AHB2ENR_DAC1EN)
+
+/**
+ * @brief Resets the DAC1 peripheral.
+ *
+ * @api
+ */
+#define rccResetDAC1() rccResetAHB2(RCC_AHB2RSTR_DAC1RST)
+
+/**
+ * @brief Enables the DAC2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableDAC2(lp) rccEnableAHB2(RCC_AHB2ENR_DAC2EN, lp)
+
+/**
+ * @brief Disables the DAC2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableDAC2() rccDisableAHB2(RCC_AHB2ENR_DAC2EN)
+
+/**
+ * @brief Resets the DAC2 peripheral.
+ *
+ * @api
+ */
+#define rccResetDAC2() rccResetAHB2(RCC_AHB2RSTR_DAC2RST)
+
+/**
+ * @brief Enables the DAC3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableDAC3(lp) rccEnableAHB2(RCC_AHB2ENR_DAC3EN, lp)
+
+/**
+ * @brief Disables the DAC3 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableDAC3() rccDisableAHB2(RCC_AHB2ENR_DAC3EN)
+
+/**
+ * @brief Resets the DAC3 peripheral.
+ *
+ * @api
+ */
+#define rccResetDAC3() rccResetAHB2(RCC_AHB2RSTR_DAC3RST)
+
+/**
+ * @brief Enables the DAC4 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableDAC4(lp) rccEnableAHB2(RCC_AHB2ENR_DAC4EN, lp)
+
+/**
+ * @brief Disables the DAC4 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableDAC4() rccDisableAHB2(RCC_AHB2ENR_DAC4EN)
+
+/**
+ * @brief Resets the DAC4 peripheral.
+ *
+ * @api
+ */
+#define rccResetDAC4() rccResetAHB2(RCC_AHB2RSTR_DAC4RST)
+/** @} */
+
+/**
+ * @name DMA peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the DMA1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp)
+
+/**
+ * @brief Disables the DMA1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableDMA1() rccDisableAHB1(RCC_AHB1ENR_DMA1EN)
+
+/**
+ * @brief Resets the DMA1 peripheral.
+ *
+ * @api
+ */
+#define rccResetDMA1() rccResetAHB1(RCC_AHB1RSTR_DMA1RST)
+
+/**
+ * @brief Enables the DMA2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableDMA2(lp) rccEnableAHB1(RCC_AHB1ENR_DMA2EN, lp)
+
+/**
+ * @brief Disables the DMA2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableDMA2() rccDisableAHB1(RCC_AHB1ENR_DMA2EN)
+
+/**
+ * @brief Resets the DMA2 peripheral.
+ *
+ * @api
+ */
+#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST)
+/** @} */
+
+/**
+ * @name DMAMUX peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the DMAMUX peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableDMAMUX(lp) rccEnableAHB1(RCC_AHB1ENR_DMAMUX1EN, lp)
+
+/**
+ * @brief Disables the DMAMUX peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableDMAMUX() rccDisableAHB1(RCC_AHB1ENR_DMAMUX1EN)
+
+/**
+ * @brief Resets the DMAMUX peripheral.
+ *
+ * @api
+ */
+#define rccResetDMAMUX() rccResetAHB1(RCC_AHB1RSTR_DMAMUX1RST)
+/** @} */
+
+/**
+ * @name FDCAN peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the FDCAN peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableFDCAN(lp) rccEnableAPB1R1(RCC_APB1ENR1_FDCANEN, lp)
+
+/**
+ * @brief Disables the FDCAN peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableFDCAN() rccDisableAPB1R1(RCC_APB1ENR1_FDCANEN)
+
+/**
+ * @brief Resets the FDCAN peripheral.
+ *
+ * @api
+ */
+#define rccResetFDCAN() rccResetAPB1R1(RCC_APB1RSTR1_FDCANRST)
+/** @} */
+
+/**
+ * @name PWR interface specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the PWR interface clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnablePWRInterface(lp) rccEnableAPB1R1(RCC_APB1ENR1_PWREN, lp)
+
+/**
+ * @brief Disables PWR interface clock.
+ *
+ * @api
+ */
+#define rccDisablePWRInterface() rccDisableAPB1R1(RCC_APB1ENR1_PWREN)
+
+/**
+ * @brief Resets the PWR interface.
+ *
+ * @api
+ */
+#define rccResetPWRInterface() rccResetAPB1R1(RCC_APB1RSTR1_PWRRST)
+/** @} */
+
+/**
+ * @name FDCAN peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the FDCAN1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableFDCAN1(lp) rccEnableAPB1R1(RCC_APB1ENR1_FDCANEN, lp)
+
+/**
+ * @brief Disables the FDCAN1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableFDCAN1() rccDisableAPB1R1(RCC_APB1ENR1_FDCANEN)
+
+/**
+ * @brief Resets the FDCAN1 peripheral.
+ *
+ * @api
+ */
+#define rccResetFDCAN1() rccResetAPB1R1(RCC_APB1RSTR1_FDCANRST)
+/** @} */
+
+/**
+ * @name I2C peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the I2C1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableI2C1(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C1EN, lp)
+
+/**
+ * @brief Disables the I2C1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableI2C1() rccDisableAPB1R1(RCC_APB1ENR1_I2C1EN)
+
+/**
+ * @brief Resets the I2C1 peripheral.
+ *
+ * @api
+ */
+#define rccResetI2C1() rccResetAPB1R1(RCC_APB1RSTR1_I2C1RST)
+
+/**
+ * @brief Enables the I2C2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableI2C2(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C2EN, lp)
+
+/**
+ * @brief Disables the I2C2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableI2C2() rccDisableAPB1R1(RCC_APB1ENR1_I2C2EN)
+
+/**
+ * @brief Resets the I2C2 peripheral.
+ *
+ * @api
+ */
+#define rccResetI2C2() rccResetAPB1R1(RCC_APB1RSTR1_I2C2RST)
+
+/**
+ * @brief Enables the I2C3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableI2C3(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C3EN, lp)
+
+/**
+ * @brief Disables the I2C3 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableI2C3() rccDisableAPB1R1(RCC_APB1ENR1_I2C3EN)
+
+/**
+ * @brief Resets the I2C3 peripheral.
+ *
+ * @api
+ */
+#define rccResetI2C3() rccResetAPB1R1(RCC_APB1RSTR1_I2C3RST)
+
+/**
+ * @brief Enables the I2C4 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableI2C4(lp) rccEnableAPB1R2(RCC_APB1ENR2_I2C4EN, lp)
+
+/**
+ * @brief Disables the I2C4 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableI2C4() rccDisableAPB1R1(RCC_APB1ENR2_I2C4EN)
+
+/**
+ * @brief Resets the I2C4 peripheral.
+ *
+ * @api
+ */
+#define rccResetI2C4() rccResetAPB1R1(RCC_APB1RSTR2_I2C4RST)
+/** @} */
+
+/**
+ * @name QUADSPI peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the QUADSPI1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableQUADSPI1(lp) rccEnableAHB3(RCC_AHB3ENR_QSPIEN, lp)
+
+/**
+ * @brief Disables the QUADSPI1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableQUADSPI1() rccDisableAHB3(RCC_AHB3ENR_QSPIEN)
+
+/**
+ * @brief Resets the QUADSPI1 peripheral.
+ *
+ * @api
+ */
+#define rccResetQUADSPI1() rccResetAHB3(RCC_AHB3RSTR_QSPIRST)
+/** @} */
+
+/**
+ * @name RNG peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the RNG peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableRNG(lp) rccEnableAHB2(RCC_AHB2ENR_RNGEN, lp)
+
+/**
+ * @brief Disables the RNG peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableRNG() rccDisableAHB2(RCC_AHB2ENR_RNGEN)
+
+/**
+ * @brief Resets the RNG peripheral.
+ *
+ * @api
+ */
+#define rccResetRNG() rccResetAHB2(RCC_AHB2RSTR_RNGRST)
+/** @} */
+
+/**
+ * @name SPI peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the SPI1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp)
+
+/**
+ * @brief Disables the SPI1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN)
+
+/**
+ * @brief Resets the SPI1 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI1() rccResetAPB2(RCC_APB2RSTR_SPI1RST)
+
+/**
+ * @brief Enables the SPI2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI2(lp) rccEnableAPB1R1(RCC_APB1ENR1_SPI2EN, lp)
+
+/**
+ * @brief Disables the SPI2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableSPI2() rccDisableAPB1R1(RCC_APB1ENR1_SPI2EN)
+
+/**
+ * @brief Resets the SPI2 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI2() rccResetAPB1R1(RCC_APB1RSTR1_SPI2RST)
+
+/**
+ * @brief Enables the SPI3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI3(lp) rccEnableAPB1R1(RCC_APB1ENR1_SPI3EN, lp)
+
+/**
+ * @brief Disables the SPI3 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableSPI3() rccDisableAPB1R1(RCC_APB1ENR1_SPI3EN)
+
+/**
+ * @brief Resets the SPI3 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI3() rccResetAPB1R1(RCC_APB1RSTR1_SPI3RST)
+
+/**
+ * @brief Enables the SPI4 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI4(lp) rccEnableAPB2(RCC_APB2ENR_SPI4EN, lp)
+
+/**
+ * @brief Disables the SPI4 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableSPI4() rccDisableAPB2(RCC_APB2ENR_SPI4EN)
+
+/**
+ * @brief Resets the SPI4 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI4() rccResetAPB2(RCC_APB2RSTR_SPI4RST)
+/** @} */
+
+/**
+ * @name TIM peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the TIM1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp)
+
+/**
+ * @brief Disables the TIM1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN)
+
+/**
+ * @brief Resets the TIM1 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM1() rccResetAPB2(RCC_APB2RSTR_TIM1RST)
+
+/**
+ * @brief Enables the TIM2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM2(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM2EN, lp)
+
+/**
+ * @brief Disables the TIM2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM2() rccDisableAPB1R1(RCC_APB1ENR1_TIM2EN)
+
+/**
+ * @brief Resets the TIM2 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM2() rccResetAPB1R1(RCC_APB1RSTR1_TIM2RST)
+
+/**
+ * @brief Enables the TIM3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM3(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM3EN, lp)
+
+/**
+ * @brief Disables the TIM3 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM3() rccDisableAPB1R1(RCC_APB1ENR1_TIM3EN)
+
+/**
+ * @brief Resets the TIM3 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM3() rccResetAPB1R1(RCC_APB1RSTR1_TIM3RST)
+
+/**
+ * @brief Enables the TIM4 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM4(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM4EN, lp)
+
+/**
+ * @brief Disables the TIM4 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM4() rccDisableAPB1R1(RCC_APB1ENR1_TIM4EN)
+
+/**
+ * @brief Resets the TIM4 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM4() rccResetAPB1R1(RCC_APB1RSTR1_TIM4RST)
+
+/**
+ * @brief Enables the TIM5 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM5(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM5EN, lp)
+
+/**
+ * @brief Disables the TIM5 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM5() rccDisableAPB1R1(RCC_APB1ENR1_TIM5EN)
+
+/**
+ * @brief Resets the TIM5 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM5() rccResetAPB1R1(RCC_APB1RSTR1_TIM5RST)
+
+/**
+ * @brief Enables the TIM6 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM6(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM6EN, lp)
+
+/**
+ * @brief Disables the TIM6 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM6() rccDisableAPB1R1(RCC_APB1ENR1_TIM6EN)
+
+/**
+ * @brief Resets the TIM6 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM6() rccResetAPB1R1(RCC_APB1RSTR1_TIM6RST)
+
+/**
+ * @brief Enables the TIM7 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM7(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM7EN, lp)
+
+/**
+ * @brief Disables the TIM7 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM7() rccDisableAPB1R1(RCC_APB1ENR1_TIM7EN)
+
+/**
+ * @brief Resets the TIM7 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM7() rccResetAPB1R1(RCC_APB1RSTR1_TIM7RST)
+
+/**
+ * @brief Enables the TIM8 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp)
+
+/**
+ * @brief Disables the TIM8 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN)
+
+/**
+ * @brief Resets the TIM8 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST)
+
+/**
+ * @brief Enables the TIM15 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp)
+
+/**
+ * @brief Disables the TIM15 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN)
+
+/**
+ * @brief Resets the TIM15 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST)
+
+/**
+ * @brief Enables the TIM16 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp)
+
+/**
+ * @brief Disables the TIM16 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN)
+
+/**
+ * @brief Resets the TIM16 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST)
+
+/**
+ * @brief Enables the TIM17 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp)
+
+/**
+ * @brief Disables the TIM17 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN)
+
+/**
+ * @brief Resets the TIM17 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST)
+
+/**
+ * @brief Enables the TIM20 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM20(lp) rccEnableAPB2(RCC_APB2ENR_TIM20EN, lp)
+
+/**
+ * @brief Disables the TIM20 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM20() rccDisableAPB2(RCC_APB2ENR_TIM20EN)
+
+/**
+ * @brief Resets the TIM20 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM20() rccResetAPB2(RCC_APB2RSTR_TIM20RST)
+/** @} */
+
+/**
+ * @name USART/UART peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the USART1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp)
+
+/**
+ * @brief Disables the USART1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN)
+
+/**
+ * @brief Resets the USART1 peripheral.
+ *
+ * @api
+ */
+#define rccResetUSART1() rccResetAPB2(RCC_APB2RSTR_USART1RST)
+
+/**
+ * @brief Enables the USART2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSART2(lp) rccEnableAPB1R1(RCC_APB1ENR1_USART2EN, lp)
+
+/**
+ * @brief Disables the USART2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUSART2() rccDisableAPB1R1(RCC_APB1ENR1_USART2EN)
+
+/**
+ * @brief Resets the USART2 peripheral.
+ *
+ * @api
+ */
+#define rccResetUSART2() rccResetAPB1R1(RCC_APB1RSTR1_USART2RST)
+
+/**
+ * @brief Enables the USART3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSART3(lp) rccEnableAPB1R1(RCC_APB1ENR1_USART3EN, lp)
+
+/**
+ * @brief Disables the USART3 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUSART3() rccDisableAPB1R1(RCC_APB1ENR1_USART3EN)
+
+/**
+ * @brief Resets the USART3 peripheral.
+ *
+ * @api
+ */
+#define rccResetUSART3() rccResetAPB1R1(RCC_APB1RSTR1_USART3RST)
+
+/**
+ * @brief Enables the UART4 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUART4(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART4EN, lp)
+
+/**
+ * @brief Disables the UART4 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUART4() rccDisableAPB1R1(RCC_APB1ENR1_UART4EN)
+
+/**
+ * @brief Resets the UART4 peripheral.
+ *
+ * @api
+ */
+#define rccResetUART4() rccResetAPB1R1(RCC_APB1RSTR1_UART4RST)
+
+/**
+ * @brief Enables the UART5 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUART5(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART5EN, lp)
+
+/**
+ * @brief Disables the UART5 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUART5() rccDisableAPB1R1(RCC_APB1ENR1_UART5EN)
+
+/**
+ * @brief Resets the UART5 peripheral.
+ *
+ * @api
+ */
+#define rccResetUART5() rccResetAPB1R1(RCC_APB1RSTR1_UART5RST)
+
+/**
+ * @brief Enables the LPUART1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableLPUART1(lp) rccEnableAPB1R2(RCC_APB1ENR2_LPUART1EN, lp)
+
+/**
+ * @brief Disables the LPUART1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableLPUART1() rccDisableAPB1R2(RCC_APB1ENR2_LPUART1EN)
+
+/**
+ * @brief Resets the USART1 peripheral.
+ *
+ * @api
+ */
+#define rccResetLPUART1() rccResetAPB1R2(RCC_APB1RSTR2_LPUART1RST)
+/** @} */
+
+/**
+ * @name USB peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the USB peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSB(lp) rccEnableAPB1R1(RCC_APB1ENR1_USBEN, lp)
+
+/**
+ * @brief Disables the USB peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUSB() rccDisableAPB1R1(RCC_APB1ENR1_USBEN)
+
+/**
+ * @brief Resets the USB peripheral.
+ *
+ * @api
+ */
+#define rccResetUSB() rccResetAPB1R1(RCC_APB1RSTR1_USBRST)
+/** @} */
+
+/**
+ * @name CRC peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the CRC peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableCRC(lp) rccEnableAHB1(RCC_AHB1ENR_CRCEN, lp)
+
+/**
+ * @brief Disables the CRC peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableCRC() rccDisableAHB1(RCC_AHB1ENR_CRCEN)
+
+/**
+ * @brief Resets the CRC peripheral.
+ *
+ * @api
+ */
+#define rccResetCRC() rccResetAHB1(RCC_AHB1RSTR_CRCRST)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32_RCC_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/stm32_registry.h b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/stm32_registry.h
new file mode 100644
index 0000000..f86ef00
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32G4xx/stm32_registry.h
@@ -0,0 +1,524 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32G4xx/stm32_registry.h
+ * @brief STM32G4xx capabilities registry.
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#ifndef STM32_REGISTRY_H
+#define STM32_REGISTRY_H
+
+/*===========================================================================*/
+/* Platform capabilities. */
+/*===========================================================================*/
+
+/**
+ * @name STM32G4xx capabilities
+ * @{
+ */
+
+/*===========================================================================*/
+/* Common. */
+/*===========================================================================*/
+
+/* RNG attributes.*/
+#define STM32_HAS_RNG1 TRUE
+
+/* RTC attributes.*/
+#define STM32_HAS_RTC TRUE
+#define STM32_RTC_HAS_SUBSECONDS TRUE
+#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE
+#define STM32_RTC_NUM_ALARMS 2
+#define STM32_RTC_STORAGE_SIZE 128
+#define STM32_RTC_TAMP_STAMP_HANDLER Vector48
+#define STM32_RTC_WKUP_HANDLER Vector4C
+#define STM32_RTC_ALARM_HANDLER VectorE4
+#define STM32_RTC_TAMP_STAMP_NUMBER 2
+#define STM32_RTC_WKUP_NUMBER 3
+#define STM32_RTC_ALARM_NUMBER 41
+#define STM32_RTC_ALARM_EXTI 18
+#define STM32_RTC_TAMP_STAMP_EXTI 19
+#define STM32_RTC_WKUP_EXTI 20
+#define STM32_RTC_IRQ_ENABLE() do { \
+ nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \
+ nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \
+ nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI18_PRIORITY); \
+} while (false)
+
+ /* Enabling RTC-related EXTI lines.*/
+#define STM32_RTC_ENABLE_ALL_EXTI() do { \
+ extiEnableGroup1(EXTI_MASK1(STM32_RTC_ALARM_EXTI) | \
+ EXTI_MASK1(STM32_RTC_TAMP_STAMP_EXTI) | \
+ EXTI_MASK1(STM32_RTC_WKUP_EXTI), \
+ EXTI_MODE_RISING_EDGE | EXTI_MODE_ACTION_INTERRUPT); \
+} while (false)
+
+/* Clearing EXTI interrupts. */
+#define STM32_RTC_CLEAR_ALL_EXTI() do { \
+ extiClearGroup1(EXTI_MASK1(STM32_RTC_ALARM_EXTI) | \
+ EXTI_MASK1(STM32_RTC_TAMP_STAMP_EXTI) | \
+ EXTI_MASK1(STM32_RTC_WKUP_EXTI)); \
+} while (false)
+
+/* Masks used to preserve state of RTC and TAMP register reserved bits. */
+#define STM32_RTC_CR_MASK 0xE7FFFF7F
+#define STM32_RTC_PRER_MASK 0x007F7FFF
+#define STM32_TAMP_CR1_MASK 0x003C0007
+#define STM32_TAMP_CR2_MASK 0x07070007
+#define STM32_TAMP_FLTCR_MASK 0x000000FF
+#define STM32_TAMP_IER_MASK 0x003C0007
+
+#if defined(STM32G441xx) || defined(STM32G483xx) || defined(STM32G484xx) || \
+ defined(__DOXYGEN__)
+#define STM32_HAS_HASH1 TRUE
+#define STM32_HAS_CRYP1 TRUE
+#else
+#define STM32_HAS_HASH1 FALSE
+#define STM32_HAS_CRYP1 FALSE
+#endif
+
+/*===========================================================================*/
+/* STM32G473xx, STM32G4843xx, STM32G474xx, STM32G484xx. */
+/*===========================================================================*/
+
+#if defined(STM32G473xx) || defined(STM32G483xx) || \
+ defined(STM32G474xx) || defined(STM32G484xx) || \
+ defined(__DOXYGEN__)
+
+/* ADC attributes.*/
+#define STM32_HAS_ADC1 TRUE
+#define STM32_HAS_ADC2 TRUE
+#define STM32_HAS_ADC3 TRUE
+#define STM32_HAS_ADC4 TRUE
+#define STM32_HAS_ADC5 TRUE
+
+/* CAN attributes.*/
+#define STM32_HAS_FDCAN1 TRUE
+#define STM32_HAS_FDCAN2 TRUE
+#define STM32_HAS_FDCAN3 TRUE
+#define STM32_FDCAN_FLS_NBR 28U
+#define STM32_FDCAN_FLE_NBR 8U
+#define STM32_FDCAN_RF0_NBR 3U
+#define STM32_FDCAN_RF1_NBR 3U
+#define STM32_FDCAN_RB_NBR 0U
+#define STM32_FDCAN_TEF_NBR 3U
+#define STM32_FDCAN_TB_NBR 3U
+#define STM32_FDCAN_TM_NBR 0U
+
+/* DAC attributes.*/
+#define STM32_HAS_DAC1_CH1 TRUE
+#define STM32_HAS_DAC1_CH2 TRUE
+#define STM32_HAS_DAC2_CH1 TRUE
+#define STM32_HAS_DAC2_CH2 FALSE
+#define STM32_HAS_DAC3_CH1 TRUE
+#define STM32_HAS_DAC3_CH2 TRUE
+#define STM32_HAS_DAC4_CH1 TRUE
+#define STM32_HAS_DAC4_CH2 TRUE
+
+/* DMA attributes.*/
+#define STM32_ADVANCED_DMA TRUE
+#define STM32_DMA_SUPPORTS_DMAMUX TRUE
+#define STM32_DMA_SUPPORTS_CSELR FALSE
+#define STM32_DMA1_NUM_CHANNELS 8
+#define STM32_DMA2_NUM_CHANNELS 8
+
+/* ETH attributes.*/
+#define STM32_HAS_ETH FALSE
+
+/* EXTI attributes.*/
+#define STM32_EXTI_HAS_CR FALSE
+#define STM32_EXTI_SEPARATE_RF FALSE
+#define STM32_EXTI_NUM_LINES 44
+#define STM32_EXTI_IMR1_MASK 0x1F840000U
+#define STM32_EXTI_IMR2_MASK 0xFFFFFF3CU
+
+
+/* Flash attributes.*/
+#define STM32_FLASH_NUMBER_OF_BANKS 2
+
+/* GPIO attributes.*/
+#define STM32_HAS_GPIOA TRUE
+#define STM32_HAS_GPIOB TRUE
+#define STM32_HAS_GPIOC TRUE
+#define STM32_HAS_GPIOD TRUE
+#define STM32_HAS_GPIOE TRUE
+#define STM32_HAS_GPIOF TRUE
+#define STM32_HAS_GPIOG TRUE
+#define STM32_HAS_GPIOH FALSE
+#define STM32_HAS_GPIOI FALSE
+#define STM32_HAS_GPIOJ FALSE
+#define STM32_HAS_GPIOK FALSE
+#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \
+ RCC_AHB2ENR_GPIOBEN | \
+ RCC_AHB2ENR_GPIOCEN | \
+ RCC_AHB2ENR_GPIODEN | \
+ RCC_AHB2ENR_GPIOEEN | \
+ RCC_AHB2ENR_GPIOFEN | \
+ RCC_AHB2ENR_GPIOGEN)
+
+/* I2C attributes.*/
+#define STM32_HAS_I2C1 TRUE
+#define STM32_HAS_I2C2 TRUE
+#define STM32_HAS_I2C3 TRUE
+#define STM32_HAS_I2C4 TRUE
+
+/* OCTOSPI attributes.*/
+#define STM32_HAS_OCTOSPI1 FALSE
+#define STM32_HAS_OCTOSPI2 FALSE
+
+/* QUADSPI attributes.*/
+#define STM32_HAS_QUADSPI1 TRUE
+
+/* SDMMC attributes.*/
+#define STM32_HAS_SDMMC1 FALSE
+#define STM32_HAS_SDMMC2 FALSE
+
+/* SPI attributes.*/
+#define STM32_HAS_SPI1 TRUE
+#define STM32_SPI1_SUPPORTS_I2S FALSE
+
+#define STM32_HAS_SPI2 TRUE
+#define STM32_SPI2_SUPPORTS_I2S TRUE
+
+#define STM32_HAS_SPI3 TRUE
+#define STM32_SPI3_SUPPORTS_I2S TRUE
+
+#define STM32_HAS_SPI4 TRUE
+#define STM32_SPI4_SUPPORTS_I2S FALSE
+
+#define STM32_HAS_SPI5 FALSE
+#define STM32_HAS_SPI6 FALSE
+
+/* TIM attributes.*/
+#define STM32_TIM_MAX_CHANNELS 6
+
+#define STM32_HAS_TIM1 TRUE
+#define STM32_TIM1_IS_32BITS FALSE
+#define STM32_TIM1_CHANNELS 6
+
+#define STM32_HAS_TIM2 TRUE
+#define STM32_TIM2_IS_32BITS TRUE
+#define STM32_TIM2_CHANNELS 4
+
+#define STM32_HAS_TIM3 TRUE
+#define STM32_TIM3_IS_32BITS FALSE
+#define STM32_TIM3_CHANNELS 4
+
+#define STM32_HAS_TIM4 TRUE
+#define STM32_TIM4_IS_32BITS FALSE
+#define STM32_TIM4_CHANNELS 4
+
+#define STM32_HAS_TIM5 TRUE
+#define STM32_TIM5_IS_32BITS TRUE
+#define STM32_TIM5_CHANNELS 4
+
+#define STM32_HAS_TIM6 TRUE
+#define STM32_TIM6_IS_32BITS FALSE
+#define STM32_TIM6_CHANNELS 0
+
+#define STM32_HAS_TIM7 TRUE
+#define STM32_TIM7_IS_32BITS FALSE
+#define STM32_TIM7_CHANNELS 0
+
+#define STM32_HAS_TIM8 TRUE
+#define STM32_TIM8_IS_32BITS FALSE
+#define STM32_TIM8_CHANNELS 6
+
+#define STM32_HAS_TIM15 TRUE
+#define STM32_TIM15_IS_32BITS FALSE
+#define STM32_TIM15_CHANNELS 2
+
+#define STM32_HAS_TIM16 TRUE
+#define STM32_TIM16_IS_32BITS FALSE
+#define STM32_TIM16_CHANNELS 1
+
+#define STM32_HAS_TIM17 TRUE
+#define STM32_TIM17_IS_32BITS FALSE
+#define STM32_TIM17_CHANNELS 1
+
+#define STM32_HAS_TIM20 TRUE
+#define STM32_TIM20_IS_32BITS FALSE
+#define STM32_TIM20_CHANNELS 6
+
+#define STM32_HAS_TIM9 FALSE
+#define STM32_HAS_TIM10 FALSE
+#define STM32_HAS_TIM11 FALSE
+#define STM32_HAS_TIM12 FALSE
+#define STM32_HAS_TIM13 FALSE
+#define STM32_HAS_TIM14 FALSE
+#define STM32_HAS_TIM18 FALSE
+#define STM32_HAS_TIM19 FALSE
+#define STM32_HAS_TIM21 FALSE
+#define STM32_HAS_TIM22 FALSE
+
+/* USART attributes.*/
+#define STM32_HAS_USART1 TRUE
+#define STM32_HAS_USART2 TRUE
+#define STM32_HAS_USART3 TRUE
+#define STM32_HAS_UART4 TRUE
+#define STM32_HAS_UART5 TRUE
+#define STM32_HAS_LPUART1 TRUE
+#define STM32_HAS_USART6 FALSE
+#define STM32_HAS_UART7 FALSE
+#define STM32_HAS_UART8 FALSE
+
+/* OTG/USB attributes.*/
+#define STM32_HAS_OTG1 FALSE
+#define STM32_HAS_OTG2 FALSE
+
+#define STM32_HAS_USB TRUE
+#define STM32_USB_ACCESS_SCHEME_2x16 TRUE
+#define STM32_USB_PMA_SIZE 1024
+#define STM32_USB_HAS_BCDR TRUE
+
+/* IWDG attributes.*/
+#define STM32_HAS_IWDG TRUE
+#define STM32_IWDG_IS_WINDOWED TRUE
+
+/* LTDC attributes.*/
+#define STM32_HAS_LTDC FALSE
+
+/* DMA2D attributes.*/
+#define STM32_HAS_DMA2D FALSE
+
+/* FSMC attributes.*/
+#define STM32_HAS_FSMC FALSE
+
+/* CRC attributes.*/
+#define STM32_HAS_CRC TRUE
+#define STM32_CRC_PROGRAMMABLE TRUE
+
+/* DCMI attributes.*/
+#define STM32_HAS_DCMI FALSE
+
+#endif /* defined(STM32G474xx) || defined(STM32G484xx) */
+
+/*===========================================================================*/
+/* STM32G431xx, STM32G441xx, STM32G471xx. */
+/*===========================================================================*/
+
+#if defined(STM32G431xx) || defined(STM32G441xx) || \
+ defined(__DOXYGEN__)
+
+/* ADC attributes.*/
+#define STM32_HAS_ADC1 TRUE
+#define STM32_HAS_ADC2 TRUE
+#define STM32_HAS_ADC3 FALSE
+#define STM32_HAS_ADC4 FALSE
+#define STM32_HAS_ADC5 FALSE
+
+/* CAN attributes.*/
+#define STM32_HAS_FDCAN1 TRUE
+#define STM32_HAS_FDCAN2 FALSE
+#define STM32_HAS_FDCAN3 FALSE
+#define STM32_FDCAN_FLS_NBR 28U
+#define STM32_FDCAN_FLE_NBR 8U
+#define STM32_FDCAN_RF0_NBR 3U
+#define STM32_FDCAN_RF1_NBR 3U
+#define STM32_FDCAN_RB_NBR 0U
+#define STM32_FDCAN_TEF_NBR 3U
+#define STM32_FDCAN_TB_NBR 3U
+#define STM32_FDCAN_TM_NBR 0U
+
+/* DAC attributes.*/
+#define STM32_HAS_DAC1_CH1 TRUE
+#define STM32_HAS_DAC1_CH2 TRUE
+#define STM32_HAS_DAC2_CH1 FALSE
+#define STM32_HAS_DAC2_CH2 FALSE
+#define STM32_HAS_DAC3_CH1 TRUE
+#define STM32_HAS_DAC3_CH2 TRUE
+#define STM32_HAS_DAC4_CH1 FALSE
+#define STM32_HAS_DAC4_CH2 FALSE
+
+/* DMA attributes.*/
+#define STM32_ADVANCED_DMA TRUE
+#define STM32_DMA_SUPPORTS_DMAMUX TRUE
+#define STM32_DMA_SUPPORTS_CSELR FALSE
+#define STM32_DMA1_NUM_CHANNELS 6
+#define STM32_DMA2_NUM_CHANNELS 6
+
+/* ETH attributes.*/
+#define STM32_HAS_ETH FALSE
+
+/* EXTI attributes.*/
+#define STM32_EXTI_HAS_CR FALSE
+#define STM32_EXTI_SEPARATE_RF FALSE
+#define STM32_EXTI_NUM_LINES 44
+#define STM32_EXTI_IMR1_MASK 0x1F840000U
+#define STM32_EXTI_IMR2_MASK 0xFFFFFF3CU
+
+
+/* Flash attributes.*/
+#define STM32_FLASH_NUMBER_OF_BANKS 2
+
+/* GPIO attributes.*/
+#define STM32_HAS_GPIOA TRUE
+#define STM32_HAS_GPIOB TRUE
+#define STM32_HAS_GPIOC TRUE
+#define STM32_HAS_GPIOD TRUE
+#define STM32_HAS_GPIOE TRUE
+#define STM32_HAS_GPIOF TRUE
+#define STM32_HAS_GPIOG TRUE
+#define STM32_HAS_GPIOH FALSE
+#define STM32_HAS_GPIOI FALSE
+#define STM32_HAS_GPIOJ FALSE
+#define STM32_HAS_GPIOK FALSE
+#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \
+ RCC_AHB2ENR_GPIOBEN | \
+ RCC_AHB2ENR_GPIOCEN | \
+ RCC_AHB2ENR_GPIODEN | \
+ RCC_AHB2ENR_GPIOEEN | \
+ RCC_AHB2ENR_GPIOFEN | \
+ RCC_AHB2ENR_GPIOGEN)
+
+/* I2C attributes.*/
+#define STM32_HAS_I2C1 TRUE
+#define STM32_HAS_I2C2 TRUE
+#define STM32_HAS_I2C3 TRUE
+#define STM32_HAS_I2C4 FALSE
+
+/* OCTOSPI attributes.*/
+#define STM32_HAS_OCTOSPI1 FALSE
+#define STM32_HAS_OCTOSPI2 FALSE
+
+/* QUADSPI attributes.*/
+#define STM32_HAS_QUADSPI1 FALSE
+
+/* SDMMC attributes.*/
+#define STM32_HAS_SDMMC1 FALSE
+#define STM32_HAS_SDMMC2 FALSE
+
+/* SPI attributes.*/
+#define STM32_HAS_SPI1 TRUE
+#define STM32_SPI1_SUPPORTS_I2S FALSE
+
+#define STM32_HAS_SPI2 TRUE
+#define STM32_SPI2_SUPPORTS_I2S TRUE
+
+#define STM32_HAS_SPI3 TRUE
+#define STM32_SPI3_SUPPORTS_I2S TRUE
+
+#define STM32_HAS_SPI4 FALSE
+#define STM32_HAS_SPI5 FALSE
+#define STM32_HAS_SPI6 FALSE
+
+/* TIM attributes.*/
+#define STM32_TIM_MAX_CHANNELS 6
+
+#define STM32_HAS_TIM1 TRUE
+#define STM32_TIM1_IS_32BITS FALSE
+#define STM32_TIM1_CHANNELS 6
+
+#define STM32_HAS_TIM2 TRUE
+#define STM32_TIM2_IS_32BITS TRUE
+#define STM32_TIM2_CHANNELS 4
+
+#define STM32_HAS_TIM3 TRUE
+#define STM32_TIM3_IS_32BITS FALSE
+#define STM32_TIM3_CHANNELS 4
+
+#define STM32_HAS_TIM4 TRUE
+#define STM32_TIM4_IS_32BITS FALSE
+#define STM32_TIM4_CHANNELS 4
+
+#define STM32_HAS_TIM6 TRUE
+#define STM32_TIM6_IS_32BITS FALSE
+#define STM32_TIM6_CHANNELS 0
+
+#define STM32_HAS_TIM7 TRUE
+#define STM32_TIM7_IS_32BITS FALSE
+#define STM32_TIM7_CHANNELS 0
+
+#define STM32_HAS_TIM8 TRUE
+#define STM32_TIM8_IS_32BITS FALSE
+#define STM32_TIM8_CHANNELS 6
+
+#define STM32_HAS_TIM15 TRUE
+#define STM32_TIM15_IS_32BITS FALSE
+#define STM32_TIM15_CHANNELS 2
+
+#define STM32_HAS_TIM16 TRUE
+#define STM32_TIM16_IS_32BITS FALSE
+#define STM32_TIM16_CHANNELS 1
+
+#define STM32_HAS_TIM17 TRUE
+#define STM32_TIM17_IS_32BITS FALSE
+#define STM32_TIM17_CHANNELS 1
+
+#define STM32_HAS_TIM5 FALSE
+#define STM32_HAS_TIM9 FALSE
+#define STM32_HAS_TIM10 FALSE
+#define STM32_HAS_TIM11 FALSE
+#define STM32_HAS_TIM12 FALSE
+#define STM32_HAS_TIM13 FALSE
+#define STM32_HAS_TIM14 FALSE
+#define STM32_HAS_TIM18 FALSE
+#define STM32_HAS_TIM19 FALSE
+#define STM32_HAS_TIM20 FALSE
+#define STM32_HAS_TIM21 FALSE
+#define STM32_HAS_TIM22 FALSE
+
+/* USART attributes.*/
+#define STM32_HAS_USART1 TRUE
+#define STM32_HAS_USART2 TRUE
+#define STM32_HAS_USART3 TRUE
+#define STM32_HAS_UART4 TRUE
+#define STM32_HAS_UART5 FALSE
+#define STM32_HAS_LPUART1 TRUE
+#define STM32_HAS_USART6 FALSE
+#define STM32_HAS_UART7 FALSE
+#define STM32_HAS_UART8 FALSE
+
+/* OTG/USB attributes.*/
+#define STM32_HAS_OTG1 FALSE
+#define STM32_HAS_OTG2 FALSE
+
+#define STM32_HAS_USB TRUE
+#define STM32_USB_ACCESS_SCHEME_2x16 TRUE
+#define STM32_USB_PMA_SIZE 1024
+#define STM32_USB_HAS_BCDR TRUE
+
+/* IWDG attributes.*/
+#define STM32_HAS_IWDG TRUE
+#define STM32_IWDG_IS_WINDOWED TRUE
+
+/* LTDC attributes.*/
+#define STM32_HAS_LTDC FALSE
+
+/* DMA2D attributes.*/
+#define STM32_HAS_DMA2D FALSE
+
+/* FSMC attributes.*/
+#define STM32_HAS_FSMC FALSE
+
+/* CRC attributes.*/
+#define STM32_HAS_CRC TRUE
+#define STM32_CRC_PROGRAMMABLE TRUE
+
+/* DCMI attributes.*/
+#define STM32_HAS_DCMI FALSE
+
+#endif /* defined(STM32G431xx) || defined(STM32G441xx) */
+
+/** @} */
+
+#endif /* STM32_REGISTRY_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/hal_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/hal_lld.c
new file mode 100644
index 0000000..20992be
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/hal_lld.c
@@ -0,0 +1,452 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32H7xx/hal_lld.c
+ * @brief STM32H7xx HAL subsystem low level driver source.
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#include "hal.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief CMSIS system core clock variable.
+ * @note It is declared in system_stm32f7xx.h.
+ */
+uint32_t SystemCoreClock = STM32_CORE_CK;
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes the backup domain.
+ * @note WARNING! Changing clock source impossible without resetting
+ * of the whole BKP domain.
+ */
+static inline void init_bkp_domain(void) {
+
+ /* Backup domain access enabled and left open.*/
+ PWR->CR1 |= PWR_CR1_DBP;
+
+ /* Reset BKP domain if different clock source selected.*/
+ if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) {
+ /* Backup domain reset.*/
+ RCC->BDCR = RCC_BDCR_BDRST;
+ RCC->BDCR = 0;
+ }
+
+#if STM32_LSE_ENABLED
+#if defined(STM32_LSE_BYPASS)
+ /* LSE Bypass.*/
+ RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP;
+#else
+ /* No LSE Bypass.*/
+ RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON;
+#endif
+ while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0)
+ ; /* Waits until LSE is stable. */
+#endif
+
+#if HAL_USE_RTC
+ /* If the backup domain hasn't been initialized yet then proceed with
+ initialization.*/
+ if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) {
+ /* Selects clock source.*/
+ RCC->BDCR |= STM32_RTCSEL;
+
+ /* RTC clock enabled.*/
+ RCC->BDCR |= RCC_BDCR_RTCEN;
+ }
+#endif /* HAL_USE_RTC */
+}
+
+/**
+ * @brief Initializes the PWR unit.
+ */
+static inline void init_pwr(void) {
+#if 0
+ PWR_TypeDef *pwr = PWR; /* For inspection.*/
+ (void)pwr;
+#endif
+
+ /* Lower C3 byte, it must be programmed at very first, then waiting for
+ power supply to stabilize.*/
+ PWR->CR3 = STM32_PWR_CR3 & 0x000000FFU;
+ while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0)
+ ; /* CHTODO timeout handling.*/
+
+ PWR->CR1 = STM32_PWR_CR1 | 0xF0000000U;
+ PWR->CR2 = STM32_PWR_CR2;
+ PWR->CR3 = STM32_PWR_CR3; /* Other bits, lower byte is not changed. */
+ PWR->CPUCR = STM32_PWR_CPUCR;
+ PWR->D3CR = STM32_VOS;
+#if !defined(STM32_ENFORCE_H7_REV_XY) && !defined(STM32H723xx)
+ SYSCFG->PWRCR = STM32_ODEN;
+#endif
+ while ((PWR->D3CR & PWR_D3CR_VOSRDY) == 0)
+ ; /* CHTODO timeout handling.*/
+#if STM32_PWR_CR2 & PWR_CR2_BREN
+// while ((PWR->CR2 & PWR_CR2_BRRDY) == 0)
+// ;
+// rccEnableBKPRAM(true);
+#endif
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level HAL driver initialization.
+ *
+ * @notapi
+ */
+void hal_lld_init(void) {
+
+#if STM32_NO_INIT == FALSE
+ /* Reset of all peripherals. AHB3 is not reset entirely because FMC could
+ have been initialized in the board initialization file (board.c).
+ Note, GPIOs are not reset because initialized before this point in
+ board files.*/
+ rccResetAHB1(~0);
+ rccResetAHB2(~0);
+ rccResetAHB3(~(RCC_AHB3RSTR_FMCRST |
+ 0x80000000U)); /* Was RCC_AHB3RSTR_CPURST in Rev-V.*/
+ rccResetAHB4(~(RCC_APB4RSTR_SYSCFGRST | STM32_GPIO_EN_MASK));
+ rccResetAPB1L(~0);
+ rccResetAPB1H(~0);
+ rccResetAPB2(~0);
+ rccResetAPB3(~0);
+ rccResetAPB4(~0);
+#endif /* STM32_NO_INIT == FALSE */
+
+ /* DMA subsystems initialization.*/
+#if defined(STM32_BDMA_REQUIRED)
+ bdmaInit();
+#endif
+#if defined(STM32_DMA_REQUIRED)
+ dmaInit();
+#endif
+#if defined(STM32_MDMA_REQUIRED)
+ mdmaInit();
+#endif
+
+ /* IRQ subsystem initialization.*/
+ irqInit();
+
+ /* MPU initialization.*/
+#if (STM32_NOCACHE_SRAM1_SRAM2 == TRUE) || (STM32_NOCACHE_SRAM3 == TRUE) || \
+ (STM32_NOCACHE_ALLSRAM == TRUE)
+ {
+ uint32_t base, size;
+
+#if (STM32_NOCACHE_ALLSRAM == TRUE)
+ base = 0x30000000U;
+ size = MPU_RASR_SIZE_256M;
+#elif (STM32_NOCACHE_SRAM1_SRAM2 == TRUE) && (STM32_NOCACHE_SRAM3 == TRUE)
+ base = 0x30000000U;
+ size = MPU_RASR_SIZE_512K;
+#elif (STM32_NOCACHE_SRAM1_SRAM2 == TRUE) && (STM32_NOCACHE_SRAM3 == FALSE)
+ base = 0x30000000U;
+ size = MPU_RASR_SIZE_256K;
+#elif (STM32_NOCACHE_SRAM1_SRAM2 == FALSE) && (STM32_NOCACHE_SRAM3 == TRUE)
+ base = 0x30040000U;
+ size = MPU_RASR_SIZE_16K;
+#else
+#error "invalid constants used in mcuconf.h"
+#endif
+
+ /* The SRAM2 bank can optionally made a non cache-able area for use by
+ DMA engines.*/
+ mpuConfigureRegion(STM32_NOCACHE_MPU_REGION,
+ base,
+ MPU_RASR_ATTR_AP_RW_RW |
+ MPU_RASR_ATTR_NON_CACHEABLE |
+ size |
+ MPU_RASR_ENABLE);
+ mpuEnable(MPU_CTRL_PRIVDEFENA);
+
+ /* Invalidating data cache to make sure that the MPU settings are taken
+ immediately.*/
+ SCB_CleanInvalidateDCache();
+ }
+#endif
+}
+
+/**
+ * @brief STM32H7xx clocks and PLL initialization.
+ * @note All the involved constants come from the file @p board.h.
+ * @note This function should be invoked just after the system reset.
+ *
+ * @special
+ */
+void stm32_clock_init(void) {
+#if STM32_NO_INIT == FALSE
+ uint32_t cfgr;
+
+#if 0
+ RCC_TypeDef *rcc = RCC; /* For inspection.*/
+ (void)rcc;
+#endif
+
+#if defined(STM32_ENFORCE_H7_REV_XY)
+ /* Fix for errata 2.2.15: Reading from AXI SRAM might lead to data
+ read corruption.
+ AXI->TARG7_FN_MOD.*/
+ *((volatile uint32_t *)(0x51000000 + 0x1108 + 0x7000)) = 0x00000001U;
+#endif
+
+ /* SYSCFG clock enabled here because it is a multi-functional unit shared
+ among multiple drivers.*/
+ rccEnableAPB4(RCC_APB4ENR_SYSCFGEN, true);
+
+ /* PWR initialization.*/
+ init_pwr();
+
+ /* Backup domain initialization.*/
+ init_bkp_domain();
+
+ /* HSI setup, it enforces the reset situation in order to handle possible
+ problems with JTAG probes and re-initializations.*/
+ RCC->CR |= RCC_CR_HSION; /* Make sure HSI is ON. */
+ while (!(RCC->CR & RCC_CR_HSIRDY))
+ ; /* Wait until HSI is stable. */
+
+ /* HSI is selected as new source without touching the other fields in
+ CFGR. This is only required when using a debugger than can cause
+ restarts.*/
+ RCC->CFGR = 0x00000000U; /* Reset SW to HSI. */
+ while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
+ ; /* Wait until HSI is selected. */
+
+ /* Registers cleared to reset values.*/
+#if STM32_HSI_ENABLED == FALSE
+ RCC->CR = RCC_CR_HSION; /* CR Reset value. */
+#else
+ RCC->CR = RCC_CR_HSION | STM32_HSIDIV; /* CR Reset value. */
+#endif
+ RCC->HSICFGR = 0x40000000U; /* HSICFGR Reset value. */
+#if !defined(STM32_ENFORCE_H7_REV_XY)
+ RCC->CSICFGR = 0x20000000U; /* CSICFGR Reset value. */
+#endif
+ RCC->CSR = 0x00000000U; /* CSR reset value. */
+ RCC->PLLCFGR = 0x01FF0000U; /* PLLCFGR reset value. */
+
+ /* Other clock-related settings, done before other things because
+ recommended in the RM.*/
+ cfgr = STM32_MCO2SEL | RCC_CFGR_MCO2PRE_VALUE(STM32_MCO2PRE_VALUE) |
+ STM32_MCO1SEL | RCC_CFGR_MCO1PRE_VALUE(STM32_MCO1PRE_VALUE) |
+ RCC_CFGR_RTCPRE_VALUE(STM32_RTCPRE_VALUE) |
+ STM32_HRTIMSEL | STM32_STOPKERWUCK | STM32_STOPWUCK;
+#if STM32_TIMPRE_ENABLE == TRUE
+ cfgr |= RCC_CFGR_TIMPRE;
+#endif
+ RCC->CFGR = cfgr;
+
+ /* HSE activation with optional bypass.*/
+#if STM32_HSE_ENABLED == TRUE
+#if defined(STM32_HSE_BYPASS)
+ RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP;
+#else
+ RCC->CR |= RCC_CR_HSEON;
+#endif
+ while ((RCC->CR & RCC_CR_HSERDY) == 0)
+ ; /* Waits until HSE is stable. */
+#endif /* STM32_HSE_ENABLED == TRUE */
+
+ /* HSI48 activation.*/
+#if STM32_HSI48_ENABLED == TRUE
+ RCC->CR |= RCC_CR_HSI48ON;
+ while ((RCC->CR & RCC_CR_HSI48RDY) == 0)
+ ; /* Waits until HSI48 is stable. */
+
+#endif /* STM32_HSI48_ENABLED == TRUE */
+
+ /* CSI activation.*/
+#if STM32_CSI_ENABLED == TRUE
+ RCC->CR |= RCC_CR_CSION;
+ while ((RCC->CR & RCC_CR_CSIRDY) == 0)
+ ; /* Waits until CSI is stable. */
+#endif /* STM32_CSI_ENABLED == TRUE */
+
+ /* LSI activation.*/
+#if STM32_LSI_ENABLED == TRUE
+ RCC->CSR |= RCC_CSR_LSION;
+ while ((RCC->CSR & RCC_CSR_LSIRDY) == 0)
+ ; /* Waits until LSI is stable. */
+#endif /* STM32_LSI_ENABLED == TRUE */
+
+ /* PLLs activation, it happens in parallel in order to
+ reduce boot time.*/
+#if (STM32_PLL1_ENABLED == TRUE) || \
+ (STM32_PLL2_ENABLED == TRUE) || \
+ (STM32_PLL3_ENABLED == TRUE)
+ {
+ uint32_t onmask = 0;
+ uint32_t rdymask = 0;
+ uint32_t cfgmask = 0;
+
+ RCC->PLLCKSELR = RCC_PLLCKSELR_DIVM3_VALUE(STM32_PLL3_DIVM_VALUE) |
+ RCC_PLLCKSELR_DIVM2_VALUE(STM32_PLL2_DIVM_VALUE) |
+ RCC_PLLCKSELR_DIVM1_VALUE(STM32_PLL1_DIVM_VALUE) |
+ RCC_PLLCKSELR_PLLSRC_VALUE(STM32_PLLSRC);
+
+ cfgmask = STM32_PLLCFGR_PLL3RGE | STM32_PLLCFGR_PLL3VCOSEL | RCC_PLLCFGR_PLL3FRACEN |
+ STM32_PLLCFGR_PLL2RGE | STM32_PLLCFGR_PLL2VCOSEL | RCC_PLLCFGR_PLL2FRACEN |
+ STM32_PLLCFGR_PLL1RGE | STM32_PLLCFGR_PLL1VCOSEL | RCC_PLLCFGR_PLL1FRACEN;
+
+#if STM32_PLL1_ENABLED == TRUE
+ RCC->PLL1FRACR = STM32_PLL1_FRACN;
+ RCC->PLL1DIVR = STM32_PLL1_DIVR | STM32_PLL1_DIVQ |
+ STM32_PLL1_DIVP | STM32_PLL1_DIVN;
+ onmask |= RCC_CR_PLL1ON;
+ rdymask |= RCC_CR_PLL1RDY;
+#if STM32_PLL1_P_ENABLED == TRUE
+ cfgmask |= RCC_PLLCFGR_DIVP1EN;
+#endif
+#if STM32_PLL1_Q_ENABLED == TRUE
+ cfgmask |= RCC_PLLCFGR_DIVQ1EN;
+#endif
+#if STM32_PLL1_R_ENABLED == TRUE
+ cfgmask |= RCC_PLLCFGR_DIVR1EN;
+#endif
+#endif /* STM32_PLL1_ENABLED == TRUE */
+
+#if STM32_PLL2_ENABLED == TRUE
+ RCC->PLL2FRACR = STM32_PLL2_FRACN;
+ RCC->PLL2DIVR = STM32_PLL2_DIVR | STM32_PLL2_DIVQ |
+ STM32_PLL2_DIVP | STM32_PLL2_DIVN;
+ onmask |= RCC_CR_PLL2ON;
+ rdymask |= RCC_CR_PLL2RDY;
+#if STM32_PLL2_P_ENABLED == TRUE
+ cfgmask |= RCC_PLLCFGR_DIVP2EN;
+#endif
+#if STM32_PLL2_Q_ENABLED == TRUE
+ cfgmask |= RCC_PLLCFGR_DIVQ2EN;
+#endif
+#if STM32_PLL2_R_ENABLED == TRUE
+ cfgmask |= RCC_PLLCFGR_DIVR2EN;
+#endif
+#endif /* STM32_PLL2_ENABLED == TRUE */
+
+#if STM32_PLL3_ENABLED == TRUE
+ RCC->PLL3FRACR = STM32_PLL3_FRACN;
+ RCC->PLL3DIVR = STM32_PLL3_DIVR | STM32_PLL3_DIVQ |
+ STM32_PLL3_DIVP | STM32_PLL3_DIVN;
+ onmask |= RCC_CR_PLL3ON;
+ rdymask |= RCC_CR_PLL3RDY;
+#if STM32_PLL3_P_ENABLED == TRUE
+ cfgmask |= RCC_PLLCFGR_DIVP3EN;
+#endif
+#if STM32_PLL3_Q_ENABLED == TRUE
+ cfgmask |= RCC_PLLCFGR_DIVQ3EN;
+#endif
+#if STM32_PLL3_R_ENABLED == TRUE
+ cfgmask |= RCC_PLLCFGR_DIVR3EN;
+#endif
+#endif /* STM32_PLL3_ENABLED == TRUE */
+
+ /* Activating enabled PLLs and waiting for all of them to become ready.*/
+ RCC->PLLCFGR = cfgmask & STM32_PLLCFGR_MASK;
+ RCC->CR |= onmask;
+ while ((RCC->CR & rdymask) != rdymask)
+ ;
+ }
+#endif /* STM32_PLL1_ENABLED || STM32_PLL2_ENABLED || STM32_PLL3_ENABLED */
+
+ /* AHB and APB dividers.*/
+ RCC->D1CFGR = STM32_D1CPRE | STM32_D1PPRE3 | STM32_D1HPRE;
+ RCC->D2CFGR = STM32_D2PPRE2 | STM32_D2PPRE1;
+ RCC->D3CFGR = STM32_D3PPRE4;
+
+ /* Peripherals clocks.*/
+ RCC->D1CCIPR = STM32_CKPERSEL | STM32_SDMMCSEL
+#if !defined(STM32H723xx)
+ | STM32_QSPISEL | STM32_FMCSEL
+#endif
+ ;
+ RCC->D2CCIP1R = STM32_SWPSEL | STM32_FDCANSEL | STM32_DFSDM1SEL |
+ STM32_SPDIFSEL | STM32_SPDIFSEL | STM32_SPI45SEL |
+ STM32_SPI123SEL | STM32_SAI1SEL
+#if !defined(STM32H723xx)
+ | STM32_SAI23SEL
+#endif
+ ;
+ RCC->D2CCIP2R = STM32_LPTIM1SEL | STM32_CECSEL | STM32_USBSEL |
+ STM32_RNGSEL | STM32_USART234578SEL
+#if !defined(STM32H723xx)
+ | STM32_USART16SEL | STM32_I2C123SEL;
+#else
+ | STM32_USART16910SEL | STM32_I2C1235SEL;
+#endif
+ RCC->D3CCIPR = STM32_SPI6SEL | STM32_SAI4BSEL | STM32_SAI4ASEL |
+ STM32_ADCSEL | STM32_LPTIM345SEL | STM32_LPTIM2SEL |
+ STM32_I2C4SEL | STM32_LPUART1SEL;
+
+ /* Flash setup.*/
+ FLASH->ACR = FLASH_ACR_WRHIGHFREQ_1 | FLASH_ACR_WRHIGHFREQ_0 |
+ STM32_FLASHBITS;
+ while ((FLASH->ACR & FLASH_ACR_LATENCY) !=
+ (STM32_FLASHBITS & FLASH_ACR_LATENCY)) {
+ }
+
+ /* Switching to the configured clock source if it is different
+ from HSI.*/
+#if STM32_SW != STM32_SW_HSI_CK
+ RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */
+ while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 3U))
+ ;
+#endif
+
+#if 0
+ /* Peripheral clock sources.*/
+ RCC->DCKCFGR2 = STM32_SDMMCSEL | STM32_CK48MSEL | STM32_CECSEL |
+ STM32_LPTIM1SEL | STM32_I2C4SEL | STM32_I2C3SEL |
+ STM32_I2C2SEL | STM32_I2C1SEL | STM32_UART8SEL |
+ STM32_UART7SEL | STM32_USART6SEL | STM32_UART5SEL |
+ STM32_UART4SEL | STM32_USART3SEL | STM32_USART2SEL |
+ STM32_USART1SEL;
+#endif
+
+ /* RAM1 2 and 3 clocks enabled.*/
+ rccEnableSRAM1(true);
+ rccEnableSRAM2(true);
+#if !defined(STM32H723xx)
+ rccEnableSRAM3(true);
+#endif
+#endif /* STM32_NO_INIT */
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/hal_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/hal_lld.h
new file mode 100644
index 0000000..517ff16
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/hal_lld.h
@@ -0,0 +1,3200 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32H7xx/hal_lld.h
+ * @brief STM32H7xx HAL subsystem low level driver header.
+ * @pre This module requires the following macros to be defined in the
+ * @p board.h file:
+ * - STM32_LSECLK.
+ * - STM32_LSEDRV.
+ * - STM32_LSE_BYPASS (optionally).
+ * - STM32_HSECLK.
+ * - STM32_HSE_BYPASS (optionally).
+ * - STM32_VDD (as hundredths of Volt).
+ * .
+ * One of the following macros must also be defined:
+ * - STM32H743xx, STM32H753xx very high-performance MCUs.
+ * .
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#ifndef HAL_LLD_H
+#define HAL_LLD_H
+
+#include "stm32_registry.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Platform identification macros
+ * @{
+ */
+#if defined(STM32H723xx) || defined(__DOXYGEN__)
+#define PLATFORM_NAME "STM32H723 Single Core Very High Performance with DSP and FPU"
+
+#elif defined(STM32H742xx) || defined(__DOXYGEN__)
+#define PLATFORM_NAME "STM32H742 Single Core Very High Performance with DSP and FPU"
+
+#elif defined(STM32H743xx) || defined(__DOXYGEN__)
+#define PLATFORM_NAME "STM32H743 Single Core Very High Performance with DSP and FPU"
+
+#elif defined(STM32H753xx)
+#define PLATFORM_NAME "STM32H753 Single Core Very High Performance with DSP and FPU"
+
+#elif defined(STM32H745xx) || defined(__DOXYGEN__)
+#define PLATFORM_NAME "STM32H745 Dual Core Very High Performance with DSP and FPU"
+
+#elif defined(STM32H755xx)
+#define PLATFORM_NAME "STM32H755 Dual Core Very High Performance with DSP and FPU"
+
+#elif defined(STM32H747xx) || defined(__DOXYGEN__)
+#define PLATFORM_NAME "STM32H747 Dual Core Very High Performance with DSP and FPU"
+
+#elif defined(STM32H757xx)
+#define PLATFORM_NAME "STM32H757 Dual Core Very High Performance with DSP and FPU"
+
+#elif defined(STM32H750xx)
+#define PLATFORM_NAME "STM32H750 Value Line Very High Performance with DSP and FPU"
+
+#else
+#error "STM32H7xx device not specified"
+#endif
+/** @} */
+
+/**
+ * @name Sub-family identifier
+ */
+#if !defined(STM32H7XX) || defined(__DOXYGEN__)
+#define STM32H7XX
+#endif
+/** @} */
+
+#if !defined(STM32_ENFORCE_H7_REV_XY)
+/**
+ * @name Absolute Maximum Ratings
+ * @{
+ */
+
+#if !defined(STM32H723xx)
+
+/**
+ * @brief Absolute maximum system clock.
+ */
+#define STM32_SYSCLK_MAX 480000000
+
+/**
+ * @brief Maximum SYSCLK clock frequency without voltage boost.
+ */
+#define STM32_SYSCLK_MAX_NOBOOST 400000000
+
+#else // then defined(STM32H723xx)
+
+/**
+ * @brief Absolute maximum system clock.
+ */
+#define STM32_SYSCLK_MAX 550000000
+
+/**
+ * @brief Maximum SYSCLK clock frequency without voltage boost.
+ */
+#define STM32_SYSCLK_MAX_NOBOOST 550000000
+
+#endif // !defined(STM32H723xx)
+
+/**
+ * @brief Absolute maximum HCLK clock.
+ */
+#define STM32_HCLK_MAX (STM32_SYSCLK_MAX / 2)
+
+/**
+ * @brief Maximum HSE clock frequency.
+ */
+#define STM32_HSECLK_MAX 48000000
+
+/**
+ * @brief Maximum HSE clock frequency using an external source.
+ */
+#define STM32_HSECLK_BYP_MAX 50000000
+
+/**
+ * @brief Minimum HSE clock frequency.
+ */
+#define STM32_HSECLK_MIN 4000000
+
+/**
+ * @brief Minimum HSE clock frequency.
+ */
+#define STM32_HSECLK_BYP_MIN 4000000
+
+/**
+ * @brief Maximum LSE clock frequency.
+ */
+#define STM32_LSE_CK_MAX 32768
+
+/**
+ * @brief Maximum LSE clock frequency.
+ */
+#define STM32_LSE_CK_BYP_MAX 1000000
+
+/**
+ * @brief Minimum LSE clock frequency.
+ */
+#define STM32_LSE_CK_MIN 32768
+
+/**
+ * @brief Minimum PLLs input clock frequency..
+ */
+#define STM32_PLLIN_MIN 1000000
+
+/**
+ * @brief PLLs input threshold frequency 1.
+ */
+#define STM32_PLLIN_THRESHOLD1 2000000
+
+/**
+ * @brief PLLs input threshold frequency 2.
+ */
+#define STM32_PLLIN_THRESHOLD2 4000000
+
+/**
+ * @brief PLLs input threshold frequency 3.
+ */
+#define STM32_PLLIN_THRESHOLD3 8000000
+
+/**
+ * @brief Maximum PLLs input clock frequency.
+ */
+#define STM32_PLLIN_MAX 16000000
+
+/**
+ * @brief Minimum PLLs VCO clock frequency.
+ */
+#define STM32_PLLVCO_MIN 150000000 /* DS says 192, RM says 150. */
+
+/**
+ * @brief Threshold PLLs clock frequency.
+ */
+#define STM32_PLLVCO_THRESHOLD 420000000
+
+/**
+ * @brief Maximum PLLs VCOH clock frequency.
+ */
+#define STM32_PLLVCO_MAX 960000000
+
+/**
+ * @brief Maximum APB1 clock frequency.
+ */
+#define STM32_PCLK1_MAX (STM32_HCLK_MAX / 2)
+
+/**
+ * @brief Maximum APB2 clock frequency.
+ */
+#define STM32_PCLK2_MAX (STM32_HCLK_MAX / 2)
+
+/**
+ * @brief Maximum APB3 clock frequency.
+ */
+#define STM32_PCLK3_MAX (STM32_HCLK_MAX / 2)
+
+/**
+ * @brief Maximum APB4 clock frequency.
+ */
+#define STM32_PCLK4_MAX (STM32_HCLK_MAX / 2)
+
+/**
+ * @brief Maximum SPI1, SPI2 and SPI3 clock frequency.
+ */
+#define STM32_SPI123_MAX 200000000
+
+/**
+ * @brief Maximum SPI4, SPI5 and SPI6 clock frequency.
+ */
+#define STM32_SPI456_MAX 125000000
+
+/**
+ * @brief Maximum ADC clock frequency.
+ */
+#define STM32_ADCCLK_MAX 50000000
+/** @} */
+
+#else /* defined(STM32_ENFORCE_H7_REV_XY) */
+
+#define STM32_SYSCLK_MAX 400000000
+#define STM32_SYSCLK_MAX_NOBOOST 400000000
+#define STM32_HCLK_MAX (STM32_SYSCLK_MAX / 2)
+#define STM32_HSECLK_MAX 48000000
+#define STM32_HSECLK_BYP_MAX 50000000
+#define STM32_HSECLK_MIN 4000000
+#define STM32_HSECLK_BYP_MIN 4000000
+#define STM32_LSE_CK_MAX 32768
+#define STM32_LSE_CK_BYP_MAX 1000000
+#define STM32_LSE_CK_MIN 32768
+#define STM32_PLLIN_MIN 1000000
+#define STM32_PLLIN_THRESHOLD1 2000000
+#define STM32_PLLIN_THRESHOLD2 4000000
+#define STM32_PLLIN_THRESHOLD3 8000000
+#define STM32_PLLIN_MAX 16000000
+#define STM32_PLLVCO_MIN 150000000
+#define STM32_PLLVCO_THRESHOLD 420000000
+#define STM32_PLLVCO_MAX 836000000
+#define STM32_PCLK1_MAX (STM32_HCLK_MAX / 2)
+#define STM32_PCLK2_MAX (STM32_HCLK_MAX / 2)
+#define STM32_PCLK3_MAX (STM32_HCLK_MAX / 2)
+#define STM32_PCLK4_MAX (STM32_HCLK_MAX / 2)
+#define STM32_SPI123_MAX 133000000
+#define STM32_SPI456_MAX 100000000
+#define STM32_ADCCLK_MAX 36000000
+
+#endif /* defined(STM32_ENFORCE_H7_REV_XY) */
+
+/**
+ * @name Internal clock sources frequencies
+ * @{
+ */
+#define STM32_HSI_OSC 64000000
+#define STM32_HSI48_OSC 48000000
+#define STM32_CSI_OSC 4000000
+#define STM32_LSI_OSC 32000
+/** @} */
+
+/**
+ * @name Register helpers not found in ST headers
+ * @{
+ */
+#define RCC_CR_HSIDIV_VALUE(n) ((n) << 3U)
+
+#define RCC_CFGR_SW_VALUE(n) ((n) << 0U)
+#define RCC_CFGR_RTCPRE_VALUE(n) ((n) << 8U)
+#define RCC_CFGR_MCO1PRE_VALUE(n) ((n) << 18U)
+#define RCC_CFGR_MCO1_VALUE(n) ((n) << 22U)
+#define RCC_CFGR_MCO2PRE_VALUE(n) ((n) << 25U)
+#define RCC_CFGR_MCO2_VALUE(n) ((n) << 29U)
+
+#define RCC_D1CFGR_D1HPRE_VALUE(n) ((n) << RCC_D1CFGR_HPRE_Pos)
+#define RCC_D1CFGR_D1CPRE_VALUE(n) ((n) << RCC_D1CFGR_D1CPRE_Pos)
+#define RCC_D1CFGR_D1PPRE3_VALUE(n) ((n) << RCC_D1CFGR_D1PPRE_Pos)
+
+#define RCC_D2CFGR_D2PPRE1_VALUE(n) ((n) << RCC_D2CFGR_D2PPRE1_Pos)
+#define RCC_D2CFGR_D2PPRE2_VALUE(n) ((n) << RCC_D2CFGR_D2PPRE2_Pos)
+
+#define RCC_D3CFGR_D3PPRE4_VALUE(n) ((n) << RCC_D3CFGR_D3PPRE_Pos)
+
+#define RCC_PLLCKSELR_PLLSRC_VALUE(n) ((n) << RCC_PLLCKSELR_PLLSRC_Pos)
+
+#define RCC_PLLCKSELR_DIVM1_VALUE(n) ((n) << RCC_PLLCKSELR_DIVM1_Pos)
+#define RCC_PLLCKSELR_DIVM2_VALUE(n) ((n) << RCC_PLLCKSELR_DIVM2_Pos)
+#define RCC_PLLCKSELR_DIVM3_VALUE(n) ((n) << RCC_PLLCKSELR_DIVM3_Pos)
+
+#define RCC_PLL1DIVR_DIVN1_VALUE(n) ((n) << RCC_PLL1DIVR_N1)
+#define RCC_PLL1DIVR_DIVP1_VALUE(n) ((n) << RCC_PLL1DIVR_P1)
+#define RCC_PLL1DIVR_DIVQ1_VALUE(n) ((n) << RCC_PLL1DIVR_Q1)
+#define RCC_PLL1DIVR_DIVR1_VALUE(n) ((n) << RCC_PLL1DIVR_R1)
+
+#define RCC_PLL1FRACR_FRACN1_VALUE(n) ((n) << RCC_PLL1FRACR_FRACN1_Pos)
+
+#define RCC_PLL2DIVR_DIVN2_VALUE(n) ((n) << RCC_PLL2DIVR_N2)
+#define RCC_PLL2DIVR_DIVP2_VALUE(n) ((n) << RCC_PLL2DIVR_P2)
+#define RCC_PLL2DIVR_DIVQ2_VALUE(n) ((n) << RCC_PLL2DIVR_Q2)
+#define RCC_PLL2DIVR_DIVR2_VALUE(n) ((n) << RCC_PLL2DIVR_R2)
+
+#define RCC_PLL2FRACR_FRACN2_VALUE(n) ((n) << RCC_PLL2FRACR_FRACN2_Pos)
+
+#define RCC_PLL3DIVR_DIVN3_VALUE(n) ((n) << RCC_PLL3DIVR_N3)
+#define RCC_PLL3DIVR_DIVP3_VALUE(n) ((n) << RCC_PLL3DIVR_P3)
+#define RCC_PLL3DIVR_DIVQ3_VALUE(n) ((n) << RCC_PLL3DIVR_Q3)
+#define RCC_PLL3DIVR_DIVR3_VALUE(n) ((n) << RCC_PLL3DIVR_R3)
+
+#define RCC_PLL3FRACR_FRACN3_VALUE(n) ((n) << RCC_PLL3FRACR_FRACN3_Pos)
+
+#define RCC_D1CCIPR_CKPERSEL_VALUE(n) ((n) << RCC_D1CCIPR_CKPERSEL_Pos)
+#define RCC_D1CCIPR_SDMMCSEL_VALUE(n) ((n) << RCC_D1CCIPR_SDMMCSEL_Pos)
+#if !defined(STM32H723xx)
+#define RCC_D1CCIPR_QSPISEL_VALUE(n) ((n) << RCC_D1CCIPR_QSPISEL_Pos)
+#endif
+#define RCC_D1CCIPR_FMCSEL_VALUE(n) ((n) << RCC_D1CCIPR_FMCSEL_Pos)
+
+#define RCC_D2CCIP1R_SWPSEL_VALUE(n) ((n) << RCC_D2CCIP1R_SWPSEL_Pos)
+#define RCC_D2CCIP1R_FDCANSEL_VALUE(n) ((n) << RCC_D2CCIP1R_FDCANSEL_Pos)
+#define RCC_D2CCIP1R_DFSDM1SEL_VALUE(n) ((n) << RCC_D2CCIP1R_DFSDM1SEL_Pos)
+#define RCC_D2CCIP1R_SPDIFSEL_VALUE(n) ((n) << RCC_D2CCIP1R_SPDIFSEL_Pos)
+#define RCC_D2CCIP1R_SPI45SEL_VALUE(n) ((n) << RCC_D2CCIP1R_SPI45SEL_Pos)
+#define RCC_D2CCIP1R_SPI123SEL_VALUE(n) ((n) << RCC_D2CCIP1R_SPI123SEL_Pos)
+#if !defined(STM32H723xx)
+#define RCC_D2CCIP1R_SAI23SEL_VALUE(n) ((n) << RCC_D2CCIP1R_SAI23SEL_Pos)
+#endif
+#define RCC_D2CCIP1R_SAI1SEL_VALUE(n) ((n) << RCC_D2CCIP1R_SAI1SEL_Pos)
+
+#define RCC_D2CCIP2R_LPTIM1SEL_VALUE(n) ((n) << RCC_D2CCIP2R_LPTIM1SEL_Pos)
+#define RCC_D2CCIP2R_CECSEL_VALUE(n) ((n) << RCC_D2CCIP2R_CECSEL_Pos)
+#define RCC_D2CCIP2R_USBSEL_VALUE(n) ((n) << RCC_D2CCIP2R_USBSEL_Pos)
+#if !defined(STM32H723xx)
+#define RCC_D2CCIP2R_I2C123SEL_VALUE(n) ((n) << RCC_D2CCIP2R_I2C123SEL_Pos)
+#else
+#define RCC_D2CCIP2R_I2C1235SEL_VALUE(n) ((n) << RCC_D2CCIP2R_I2C1235SEL_Pos)
+#endif
+#define RCC_D2CCIP2R_RNGSEL_VALUE(n) ((n) << RCC_D2CCIP2R_RNGSEL_Pos)
+#if !defined(STM32H723xx)
+#define RCC_D2CCIP2R_USART16SEL_VALUE(n) ((n) << RCC_D2CCIP2R_USART16SEL_Pos)
+#else
+#define RCC_D2CCIP2R_USART16910SEL_VALUE(n) ((n) << RCC_D2CCIP2R_USART16910SEL_Pos)
+#endif
+#define RCC_D2CCIP2R_USART234578SEL_VALUE(n) ((n) << RCC_D2CCIP2R_USART28SEL_Pos)
+
+#define RCC_D3CCIPR_SPI6SEL_VALUE(n) ((n) << RCC_D3CCIPR_SPI6SEL_Pos)
+#define RCC_D3CCIPR_SAI4BSEL_VALUE(n) ((n) << RCC_D3CCIPR_SAI4BSEL_Pos)
+#define RCC_D3CCIPR_SAI4ASEL_VALUE(n) ((n) << RCC_D3CCIPR_SAI4ASEL_Pos)
+#define RCC_D3CCIPR_ADCSEL_VALUE(n) ((n) << RCC_D3CCIPR_ADCSEL_Pos)
+#define RCC_D3CCIPR_LPTIM345SEL_VALUE(n) ((n) << RCC_D3CCIPR_LPTIM345SEL_Pos)
+#define RCC_D3CCIPR_LPTIM2SEL_VALUE(n) ((n) << RCC_D3CCIPR_LPTIM2SEL_Pos)
+#define RCC_D3CCIPR_I2C4SEL_VALUE(n) ((n) << RCC_D3CCIPR_I2C4SEL_Pos)
+#define RCC_D3CCIPR_LPUART1SEL_VALUE(n) ((n) << RCC_D3CCIPR_LPUART1SEL_Pos)
+
+#define RCC_BDCR_RTCSEL_VALUE(n) ((n) << RCC_BDCR_RTCSEL_Pos)
+/** @} */
+
+/**
+ * @name Configuration switches to be used in @p mcuconf.h
+ * @{
+ */
+#define STM32_ODEN_DISABLED 0U
+#define STM32_ODEN_ENABLED (SYSCFG_PWRCR_ODEN)
+
+#define STM32_VOS_SCALE0 0U
+#define STM32_VOS_SCALE3 (PWR_D3CR_VOS_0)
+#define STM32_VOS_SCALE2 (PWR_D3CR_VOS_1)
+#define STM32_VOS_SCALE1 (PWR_D3CR_VOS_1 | PWR_D3CR_VOS_0)
+
+#define STM32_SW_HSI_CK RCC_CFGR_SW_VALUE(0U)
+#define STM32_SW_CSI_CK RCC_CFGR_SW_VALUE(1U)
+#define STM32_SW_HSE_CK RCC_CFGR_SW_VALUE(2U)
+#define STM32_SW_PLL1_P_CK RCC_CFGR_SW_VALUE(3U)
+
+#define STM32_D1CPRE_DIV1 RCC_D1CFGR_D1CPRE_VALUE(0U)
+#define STM32_D1CPRE_DIV2 RCC_D1CFGR_D1CPRE_VALUE(8U)
+#define STM32_D1CPRE_DIV4 RCC_D1CFGR_D1CPRE_VALUE(9U)
+#define STM32_D1CPRE_DIV8 RCC_D1CFGR_D1CPRE_VALUE(10U)
+#define STM32_D1CPRE_DIV16 RCC_D1CFGR_D1CPRE_VALUE(11U)
+#define STM32_D1CPRE_DIV64 RCC_D1CFGR_D1CPRE_VALUE(12U)
+#define STM32_D1CPRE_DIV128 RCC_D1CFGR_D1CPRE_VALUE(13U)
+#define STM32_D1CPRE_DIV256 RCC_D1CFGR_D1CPRE_VALUE(14U)
+#define STM32_D1CPRE_DIV512 RCC_D1CFGR_D1CPRE_VALUE(15U)
+
+#define STM32_D1HPRE_DIV1 RCC_D1CFGR_D1HPRE_VALUE(0U)
+#define STM32_D1HPRE_DIV2 RCC_D1CFGR_D1HPRE_VALUE(8U)
+#define STM32_D1HPRE_DIV4 RCC_D1CFGR_D1HPRE_VALUE(9U)
+#define STM32_D1HPRE_DIV8 RCC_D1CFGR_D1HPRE_VALUE(10U)
+#define STM32_D1HPRE_DIV16 RCC_D1CFGR_D1HPRE_VALUE(11U)
+#define STM32_D1HPRE_DIV64 RCC_D1CFGR_D1HPRE_VALUE(12U)
+#define STM32_D1HPRE_DIV128 RCC_D1CFGR_D1HPRE_VALUE(13U)
+#define STM32_D1HPRE_DIV256 RCC_D1CFGR_D1HPRE_VALUE(14U)
+#define STM32_D1HPRE_DIV512 RCC_D1CFGR_D1HPRE_VALUE(15U)
+
+#define STM32_D1PPRE3_DIV1 RCC_D1CFGR_D1PPRE3_VALUE(0U)
+#define STM32_D1PPRE3_DIV2 RCC_D1CFGR_D1PPRE3_VALUE(4U)
+#define STM32_D1PPRE3_DIV4 RCC_D1CFGR_D1PPRE3_VALUE(5U)
+#define STM32_D1PPRE3_DIV8 RCC_D1CFGR_D1PPRE3_VALUE(6U)
+#define STM32_D1PPRE3_DIV16 RCC_D1CFGR_D1PPRE3_VALUE(7U)
+
+#define STM32_D2PPRE1_DIV1 RCC_D2CFGR_D2PPRE1_VALUE(0U)
+#define STM32_D2PPRE1_DIV2 RCC_D2CFGR_D2PPRE1_VALUE(4U)
+#define STM32_D2PPRE1_DIV4 RCC_D2CFGR_D2PPRE1_VALUE(5U)
+#define STM32_D2PPRE1_DIV8 RCC_D2CFGR_D2PPRE1_VALUE(6U)
+#define STM32_D2PPRE1_DIV16 RCC_D2CFGR_D2PPRE1_VALUE(7U)
+
+#define STM32_D2PPRE2_DIV1 RCC_D2CFGR_D2PPRE2_VALUE(0U)
+#define STM32_D2PPRE2_DIV2 RCC_D2CFGR_D2PPRE2_VALUE(4U)
+#define STM32_D2PPRE2_DIV4 RCC_D2CFGR_D2PPRE2_VALUE(5U)
+#define STM32_D2PPRE2_DIV8 RCC_D2CFGR_D2PPRE2_VALUE(6U)
+#define STM32_D2PPRE2_DIV16 RCC_D2CFGR_D2PPRE2_VALUE(7U)
+
+#define STM32_D3PPRE4_DIV1 RCC_D3CFGR_D3PPRE4_VALUE(0U)
+#define STM32_D3PPRE4_DIV2 RCC_D3CFGR_D3PPRE4_VALUE(4U)
+#define STM32_D3PPRE4_DIV4 RCC_D3CFGR_D3PPRE4_VALUE(5U)
+#define STM32_D3PPRE4_DIV8 RCC_D3CFGR_D3PPRE4_VALUE(6U)
+#define STM32_D3PPRE4_DIV16 RCC_D3CFGR_D3PPRE4_VALUE(7U)
+
+#define STM32_HSIDIV_DIV1 RCC_CR_HSIDIV_VALUE(0U)
+#define STM32_HSIDIV_DIV2 RCC_CR_HSIDIV_VALUE(1U)
+#define STM32_HSIDIV_DIV4 RCC_CR_HSIDIV_VALUE(2U)
+#define STM32_HSIDIV_DIV8 RCC_CR_HSIDIV_VALUE(3U)
+
+#define STM32_MCO1SEL_HSI_CK RCC_CFGR_MCO1_VALUE(0U)
+#define STM32_MCO1SEL_LSE_CK RCC_CFGR_MCO1_VALUE(1U)
+#define STM32_MCO1SEL_HSE_CK RCC_CFGR_MCO1_VALUE(2U)
+#define STM32_MCO1SEL_PLL1_Q_CK RCC_CFGR_MCO1_VALUE(3U)
+#define STM32_MCO1SEL_HSI48_CK RCC_CFGR_MCO1_VALUE(4U)
+
+#define STM32_MCO2SEL_SYS_CK RCC_CFGR_MCO2_VALUE(0U)
+#define STM32_MCO2SEL_PLL2_P_CK RCC_CFGR_MCO2_VALUE(1U)
+#define STM32_MCO2SEL_HSE_CK RCC_CFGR_MCO2_VALUE(2U)
+#define STM32_MCO2SEL_PLL1_P_CK RCC_CFGR_MCO2_VALUE(3U)
+#define STM32_MCO2SEL_CSI_CK RCC_CFGR_MCO2_VALUE(4U)
+#define STM32_MCO2SEL_LSI_CK RCC_CFGR_MCO2_VALUE(5U)
+
+#define STM32_RTCSEL_MASK RCC_BDCR_RTCSEL_Msk
+#define STM32_RTCSEL_NOCLK RCC_BDCR_RTCSEL_VALUE(0U)
+#define STM32_RTCSEL_LSE_CK RCC_BDCR_RTCSEL_VALUE(1U)
+#define STM32_RTCSEL_LSI_CK RCC_BDCR_RTCSEL_VALUE(2U)
+#define STM32_RTCSEL_HSE_1M_CK RCC_BDCR_RTCSEL_VALUE(3U)
+
+#define STM32_HRTIMSEL_C_CLK RCC_CFGR_HRTIMSEL
+
+#define STM32_STOPKERWUCK_ENABLED RCC_CFGR_STOPKERWUCK
+
+#define STM32_STOPWUCK_ENABLED RCC_CFGR_STOPKERWUCK
+
+#define STM32_PLLSRC_HSI_CK RCC_PLLCKSELR_PLLSRC_VALUE(0U)
+#define STM32_PLLSRC_CSI_CK RCC_PLLCKSELR_PLLSRC_VALUE(1U)
+#define STM32_PLLSRC_HSE_CK RCC_PLLCKSELR_PLLSRC_VALUE(2U)
+#define STM32_PLLSRC_DISABLE RCC_PLLCKSELR_PLLSRC_VALUE(23U)
+
+#define STM32_CKPERSEL_HSI_CK RCC_D1CCIPR_CKPERSEL_VALUE(0U)
+#define STM32_CKPERSEL_CSI_CK RCC_D1CCIPR_CKPERSEL_VALUE(1U)
+#define STM32_CKPERSEL_HSE_CK RCC_D1CCIPR_CKPERSEL_VALUE(2U)
+
+#define STM32_SDMMCSEL_PLL1_Q_CK RCC_D1CCIPR_SDMMCSEL_VALUE(0U)
+#define STM32_SDMMCSEL_PLL2_R_CK RCC_D1CCIPR_SDMMCSEL_VALUE(1U)
+
+#if !defined(STM32H723xx)
+#define STM32_QSPISEL_HCLK RCC_D1CCIPR_QSPISEL_VALUE(0U)
+#define STM32_QSPISEL_PLL1_Q_CK RCC_D1CCIPR_QSPISEL_VALUE(1U)
+#define STM32_QSPISEL_PLL2_R_CK RCC_D1CCIPR_QSPISEL_VALUE(2U)
+#define STM32_QSPISEL_PER_CK RCC_D1CCIPR_QSPISEL_VALUE(3U)
+#endif
+
+#define STM32_FMCSEL_HCLK RCC_D1CCIPR_FMCSEL_VALUE(0U)
+#define STM32_FMCSEL_PLL1_Q_CK RCC_D1CCIPR_FMCSEL_VALUE(1U)
+#define STM32_FMCSEL_PLL2_R_CK RCC_D1CCIPR_FMCSEL_VALUE(2U)
+#define STM32_FMCSEL_PER_CK RCC_D1CCIPR_FMCSEL_VALUE(3U)
+
+#define STM32_SWPSEL_PCLK1 RCC_D2CCIP1R_SWPSEL_VALUE(0U)
+#define STM32_SWPSEL_HSI_KER_CK RCC_D2CCIP1R_SWPSEL_VALUE(1U)
+
+#define STM32_FDCANSEL_HSE_CK RCC_D2CCIP1R_FDCANSEL_VALUE(0U)
+#define STM32_FDCANSEL_PLL1_Q_CK RCC_D2CCIP1R_FDCANSEL_VALUE(1U)
+#define STM32_FDCANSEL_PLL2_Q_CK RCC_D2CCIP1R_FDCANSEL_VALUE(2U)
+
+#define STM32_DFSDM1SEL_PCLK2 RCC_D2CCIP1R_DFSDM1SEL_VALUE(0U)
+#define STM32_DFSDM1SEL_SYS_CK RCC_D2CCIP1R_DFSDM1SEL_VALUE(1U)
+
+#define STM32_SPDIFSEL_PLL1_Q_CK RCC_D2CCIP1R_SPDIFSEL_VALUE(0U)
+#define STM32_SPDIFSEL_PLL2_R_CK RCC_D2CCIP1R_SPDIFSEL_VALUE(1U)
+#define STM32_SPDIFSEL_PLL3_R_CK RCC_D2CCIP1R_SPDIFSEL_VALUE(2U)
+#define STM32_SPDIFSEL_HSI_KET_CLK RCC_D2CCIP1R_SPDIFSEL_VALUE(3U)
+
+#define STM32_SPI45SEL_PCLK2 RCC_D2CCIP1R_SPI45SEL_VALUE(0U)
+#define STM32_SPI45SEL_PLL2_Q_CK RCC_D2CCIP1R_SPI45SEL_VALUE(1U)
+#define STM32_SPI45SEL_PLL3_Q_CK RCC_D2CCIP1R_SPI45SEL_VALUE(2U)
+#define STM32_SPI45SEL_HSI_KER_CK RCC_D2CCIP1R_SPI45SEL_VALUE(3U)
+#define STM32_SPI45SEL_CSI_KER_CK RCC_D2CCIP1R_SPI45SEL_VALUE(4U)
+#define STM32_SPI45SEL_HSE_CK RCC_D2CCIP1R_SPI45SEL_VALUE(5U)
+
+#define STM32_SPI123SEL_PLL1_Q_CK RCC_D2CCIP1R_SPI123SEL_VALUE(0U)
+#define STM32_SPI123SEL_PLL2_P_CK RCC_D2CCIP1R_SPI123SEL_VALUE(1U)
+#define STM32_SPI123SEL_PLL3_P_CK RCC_D2CCIP1R_SPI123SEL_VALUE(2U)
+#define STM32_SPI123SEL_I2S_CKIN RCC_D2CCIP1R_SPI123SEL_VALUE(3U)
+#define STM32_SPI123SEL_PER_CK RCC_D2CCIP1R_SPI123SEL_VALUE(4U)
+
+#if !defined(STM32H723xx)
+#define STM32_SAI23SEL_PLL1_Q_CK RCC_D2CCIP1R_SAI23SEL_VALUE(0U)
+#define STM32_SAI23SEL_PLL2_P_CK RCC_D2CCIP1R_SAI23SEL_VALUE(1U)
+#define STM32_SAI23SEL_PLL3_P_CK RCC_D2CCIP1R_SAI23SEL_VALUE(2U)
+#define STM32_SAI23SEL_I2S_CKIN RCC_D2CCIP1R_SAI23SEL_VALUE(3U)
+#define STM32_SAI23SEL_PER_CK RCC_D2CCIP1R_SAI23SEL_VALUE(4U)
+#endif
+
+#define STM32_SAI1SEL_PLL1_Q_CK RCC_D2CCIP1R_SAI1SEL_VALUE(0U)
+#define STM32_SAI1SEL_PLL2_P_CK RCC_D2CCIP1R_SAI1SEL_VALUE(1U)
+#define STM32_SAI1SEL_PLL3_P_CK RCC_D2CCIP1R_SAI1SEL_VALUE(2U)
+#define STM32_SAI1SEL_I2S_CKIN RCC_D2CCIP1R_SAI1SEL_VALUE(3U)
+#define STM32_SAI1SEL_PER_CK RCC_D2CCIP1R_SAI1SEL_VALUE(4U)
+
+#define STM32_LPTIM1SEL_PCLK1 RCC_D2CCIP2R_LPTIM1SEL_VALUE(0U)
+#define STM32_LPTIM1SEL_PLL2_P_CK RCC_D2CCIP2R_LPTIM1SEL_VALUE(1U)
+#define STM32_LPTIM1SEL_PLL3_R_CK RCC_D2CCIP2R_LPTIM1SEL_VALUE(2U)
+#define STM32_LPTIM1SEL_LSE_CK RCC_D2CCIP2R_LPTIM1SEL_VALUE(3U)
+#define STM32_LPTIM1SEL_LSI_CK RCC_D2CCIP2R_LPTIM1SEL_VALUE(4U)
+#define STM32_LPTIM1SEL_PER_CK RCC_D2CCIP2R_LPTIM1SEL_VALUE(5U)
+
+#define STM32_CECSEL_LSE_CK RCC_D2CCIP2R_CECSEL_VALUE(0U)
+#define STM32_CECSEL_LSI_CK RCC_D2CCIP2R_CECSEL_VALUE(1U)
+#define STM32_CECSEL_CSI_KER_CK RCC_D2CCIP2R_CECSEL_VALUE(2U)
+#define STM32_CECSEL_DISABLE RCC_D2CCIP2R_CECSEL_VALUE(3U)
+
+#define STM32_USBSEL_DISABLE RCC_D2CCIP2R_USBSEL_VALUE(0U)
+#define STM32_USBSEL_PLL1_Q_CK RCC_D2CCIP2R_USBSEL_VALUE(1U)
+#define STM32_USBSEL_PLL3_Q_CK RCC_D2CCIP2R_USBSEL_VALUE(2U)
+#define STM32_USBSEL_HSI48_CK RCC_D2CCIP2R_USBSEL_VALUE(3U)
+
+#define STM32_I2C1235SEL_PCLK1 RCC_D2CCIP2R_I2C1235SEL_VALUE(0U)
+#define STM32_I2C1235SEL_PLL3_R_CK RCC_D2CCIP2R_I2C1235SEL_VALUE(1U)
+#define STM32_I2C1235SEL_HSI_KER_CK RCC_D2CCIP2R_I2C1235SEL_VALUE(2U)
+#define STM32_I2C1235SEL_CSI_KER_CK RCC_D2CCIP2R_I2C1235SEL_VALUE(3U)
+
+#define STM32_RNGSEL_HSI48_CK RCC_D2CCIP2R_RNGSEL_VALUE(0U)
+#define STM32_RNGSEL_PLL1_Q_CK RCC_D2CCIP2R_RNGSEL_VALUE(1U)
+#define STM32_RNGSEL_LSE_CK RCC_D2CCIP2R_RNGSEL_VALUE(2U)
+#define STM32_RNGSEL_LSI_CK RCC_D2CCIP2R_RNGSEL_VALUE(3U)
+
+#if !defined(STM32H723xx)
+#define STM32_USART16SEL_PCLK2 RCC_D2CCIP2R_USART16SEL_VALUE(0U)
+#define STM32_USART16SEL_PLL2_Q_CK RCC_D2CCIP2R_USART16SEL_VALUE(1U)
+#define STM32_USART16SEL_PLL3_Q_CK RCC_D2CCIP2R_USART16SEL_VALUE(2U)
+#define STM32_USART16SEL_HSI_KER_CK RCC_D2CCIP2R_USART16SEL_VALUE(3U)
+#define STM32_USART16SEL_CSI_KER_CK RCC_D2CCIP2R_USART16SEL_VALUE(4U)
+#define STM32_USART16SEL_LSE_CK RCC_D2CCIP2R_USART16SEL_VALUE(5U)
+#else
+#define STM32_USART16910SEL_PCLK2 RCC_D2CCIP2R_USART16910SEL_VALUE(0U)
+#define STM32_USART16910SEL_PLL2_Q_CK RCC_D2CCIP2R_USART16910SEL_VALUE(1U)
+#define STM32_USART16910SEL_PLL3_Q_CK RCC_D2CCIP2R_USART16910SEL_VALUE(2U)
+#define STM32_USART16910SEL_HSI_KER_CK RCC_D2CCIP2R_USART16910SEL_VALUE(3U)
+#define STM32_USART16910SEL_CSI_KER_CK RCC_D2CCIP2R_USART16910SEL_VALUE(4U)
+#define STM32_USART16910SEL_LSE_CK RCC_D2CCIP2R_USART16910SEL_VALUE(5U)
+#endif
+
+#define STM32_USART234578SEL_PCLK1 RCC_D2CCIP2R_USART234578SEL_VALUE(0U)
+#define STM32_USART234578SEL_PLL2_Q_CK RCC_D2CCIP2R_USART234578SEL_VALUE(1U)
+#define STM32_USART234578SEL_PLL3_Q_CK RCC_D2CCIP2R_USART234578SEL_VALUE(2U)
+#define STM32_USART234578SEL_HSI_KER_CK RCC_D2CCIP2R_USART234578SEL_VALUE(3U)
+#define STM32_USART234578SEL_CSI_KER_CK RCC_D2CCIP2R_USART234578SEL_VALUE(4U)
+#define STM32_USART234578SEL_LSE_CK RCC_D2CCIP2R_USART234578SEL_VALUE(5U)
+
+#define STM32_SPI6SEL_PCLK4 RCC_D3CCIPR_SPI6SEL_VALUE(0U)
+#define STM32_SPI6SEL_PLL2_Q_CK RCC_D3CCIPR_SPI6SEL_VALUE(1U)
+#define STM32_SPI6SEL_PLL3_Q_CK RCC_D3CCIPR_SPI6SEL_VALUE(2U)
+#define STM32_SPI6SEL_HSI_KER_CK RCC_D3CCIPR_SPI6SEL_VALUE(3U)
+#define STM32_SPI6SEL_CSI_KER_CK RCC_D3CCIPR_SPI6SEL_VALUE(4U)
+#define STM32_SPI6SEL_HSE_CK RCC_D3CCIPR_SPI6SEL_VALUE(5U)
+
+#define STM32_SAI4BSEL_PLL1_Q_CK RCC_D3CCIPR_SAI4BSEL_VALUE(0U)
+#define STM32_SAI4BSEL_PLL2_P_CK RCC_D3CCIPR_SAI4BSEL_VALUE(1U)
+#define STM32_SAI4BSEL_PLL3_P_CK RCC_D3CCIPR_SAI4BSEL_VALUE(2U)
+#define STM32_SAI4BSEL_I2S_CKIN RCC_D3CCIPR_SAI4BSEL_VALUE(3U)
+#define STM32_SAI4BSEL_PER_CK RCC_D3CCIPR_SAI4BSEL_VALUE(4U)
+
+#define STM32_SAI4ASEL_PLL1_Q_CK RCC_D3CCIPR_SAI4ASEL_VALUE(0U)
+#define STM32_SAI4ASEL_PLL2_P_CK RCC_D3CCIPR_SAI4ASEL_VALUE(1U)
+#define STM32_SAI4ASEL_PLL3_P_CK RCC_D3CCIPR_SAI4ASEL_VALUE(2U)
+#define STM32_SAI4ASEL_I2S_CKIN RCC_D3CCIPR_SAI4ASEL_VALUE(3U)
+#define STM32_SAI4ASEL_PER_CK RCC_D3CCIPR_SAI4ASEL_VALUE(4U)
+
+#define STM32_ADCSEL_PLL2_P_CK RCC_D3CCIPR_ADCSEL_VALUE(0U)
+#define STM32_ADCSEL_PLL3_R_CK RCC_D3CCIPR_ADCSEL_VALUE(1U)
+#define STM32_ADCSEL_PER_CK RCC_D3CCIPR_ADCSEL_VALUE(2U)
+#define STM32_ADCSEL_DISABLE RCC_D3CCIPR_ADCSEL_VALUE(3U)
+
+#define STM32_LPTIM345SEL_PCLK4 RCC_D3CCIPR_LPTIM345SEL_VALUE(0U)
+#define STM32_LPTIM345SEL_PLL2_P_CK RCC_D3CCIPR_LPTIM345SEL_VALUE(1U)
+#define STM32_LPTIM345SEL_PLL3_P_CK RCC_D3CCIPR_LPTIM345SEL_VALUE(2U)
+#define STM32_LPTIM345SEL_LSE_CK RCC_D3CCIPR_LPTIM345SEL_VALUE(3U)
+#define STM32_LPTIM345SEL_LSI_CK RCC_D3CCIPR_LPTIM345SEL_VALUE(4U)
+#define STM32_LPTIM345SEL_PER_CK RCC_D3CCIPR_LPTIM345SEL_VALUE(5U)
+
+#define STM32_LPTIM2SEL_PCLK4 RCC_D3CCIPR_LPTIM2SEL_VALUE(0U)
+#define STM32_LPTIM2SEL_PLL2_P_CK RCC_D3CCIPR_LPTIM2SEL_VALUE(1U)
+#define STM32_LPTIM2SEL_PLL3_P_CK RCC_D3CCIPR_LPTIM2SEL_VALUE(2U)
+#define STM32_LPTIM2SEL_LSE_CK RCC_D3CCIPR_LPTIM2SEL_VALUE(3U)
+#define STM32_LPTIM2SEL_LSI_CK RCC_D3CCIPR_LPTIM2SEL_VALUE(4U)
+#define STM32_LPTIM2SEL_PER_CK RCC_D3CCIPR_LPTIM2SEL_VALUE(5U)
+
+#define STM32_I2C4SEL_PCLK4 RCC_D3CCIPR_I2C4SEL_VALUE(0U)
+#define STM32_I2C4SEL_PLL3_R_CK RCC_D3CCIPR_I2C4SEL_VALUE(1U)
+#define STM32_I2C4SEL_HSI_KER_CK RCC_D3CCIPR_I2C4SEL_VALUE(2U)
+#define STM32_I2C4SEL_CSI_KER_CK RCC_D3CCIPR_I2C4SEL_VALUE(3U)
+
+#define STM32_LPUART1SEL_PCLK4 RCC_D3CCIPR_LPUART1SEL_VALUE(0U)
+#define STM32_LPUART1SEL_PLL2_Q_CK RCC_D3CCIPR_LPUART1SEL_VALUE(1U)
+#define STM32_LPUART1SEL_PLL3_Q_CK RCC_D3CCIPR_LPUART1SEL_VALUE(2U)
+#define STM32_LPUART1SEL_HSI_KER_CK RCC_D3CCIPR_LPUART1SEL_VALUE(3U)
+#define STM32_LPUART1SEL_CSI_KER_CK RCC_D3CCIPR_LPUART1SEL_VALUE(4U)
+#define STM32_LPUART1SEL_LSE_CK RCC_D3CCIPR_LPUART1SEL_VALUE(5U)
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief Disables the PWR/RCC initialization in the HAL.
+ * @note All the clock tree constants are calculated but the initialization
+ * is not performed.
+ */
+#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__)
+#define STM32_NO_INIT FALSE
+#endif
+
+/**
+ * @brief Target code for this HAL configuration.
+ * @note Core 1 is the Cortex-M7, core 2 is the Cortex-M4.
+ */
+#if !defined(STM32_TARGET_CORE) || defined(__DOXYGEN__)
+#define STM32_TARGET_CORE 1
+#endif
+
+/**
+ * @brief MPU region to be used for no-cache RAM area.
+ */
+#if !defined(STM32_NOCACHE_MPU_REGION) || defined(__DOXYGEN__)
+#define STM32_NOCACHE_MPU_REGION MPU_REGION_6
+#endif
+
+/**
+ * @brief Add no-cache attribute to SRAM1 and SRAM2.
+ * @note MPU region 7 is used if enabled.
+ */
+#if !defined(STM32_NOCACHE_SRAM1_SRAM2) || defined(__DOXYGEN__)
+#define STM32_NOCACHE_SRAM1_SRAM2 FALSE
+#endif
+
+/**
+ * @brief Add no-cache attribute to SRAM3.
+ * @note MPU region 7 is used if enabled.
+ */
+#if !defined(STM32_NOCACHE_SRAM3) || defined(__DOXYGEN__)
+#define STM32_NOCACHE_SRAM3 TRUE
+#endif
+
+/**
+ * @brief PWR CR1 initializer.
+ */
+#if !defined(STM32_PWR_CR1) || defined(__DOXYGEN__)
+#define STM32_PWR_CR1 (PWR_CR1_SVOS_1 | \
+ PWR_CR1_SVOS_0)
+#endif
+
+/**
+ * @brief PWR CR2 initializer.
+ */
+#if !defined(STM32_PWR_CR2) || defined(__DOXYGEN__)
+#define STM32_PWR_CR2 (PWR_CR2_BREN)
+#endif
+
+/**
+ * @brief PWR CR3 initializer.
+ */
+#if !defined(STM32_PWR_CR3) || defined(__DOXYGEN__)
+#define STM32_PWR_CR3 (PWR_CR3_LDOEN | \
+ PWR_CR3_USBREGEN | \
+ PWR_CR3_USB33DEN)
+#endif
+
+/**
+ * @brief PWR CPUCR initializer.
+ */
+#if !defined(STM32_PWR_CPUCR) || defined(__DOXYGEN__)
+#define STM32_PWR_CPUCR 0
+#endif
+
+/**
+ * @brief VOS setting.
+ */
+#if !defined(STM32_VOS) || defined(__DOXYGEN__)
+#define STM32_VOS STM32_VOS_SCALE1
+#endif
+
+/**
+ * @brief Enables or disables the HSI clock source.
+ */
+#if !defined(STM32_HSI_ENABLED) || defined(__DOXYGEN__)
+#define STM32_HSI_ENABLED TRUE
+#endif
+
+/**
+ * @brief Enables or disables the LSI clock source.
+ */
+#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__)
+#define STM32_LSI_ENABLED FALSE
+#endif
+
+/**
+ * @brief Enables or disables the LSI clock source.
+ */
+#if !defined(STM32_CSI_ENABLED) || defined(__DOXYGEN__)
+#define STM32_CSI_ENABLED FALSE
+#endif
+
+/**
+ * @brief Enables or disables the HSI48 clock source.
+ */
+#if !defined(STM32_HSI48_ENABLED) || defined(__DOXYGEN__)
+#define STM32_HSI48_ENABLED TRUE
+#endif
+
+/**
+ * @brief Enables or disables the HSE clock source.
+ */
+#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__)
+#define STM32_HSE_ENABLED TRUE
+#endif
+
+/**
+ * @brief Enables or disables the LSE clock source.
+ */
+#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__)
+#define STM32_LSE_ENABLED TRUE
+#endif
+
+/**
+ * @brief HSI divider.
+ */
+#if !defined(STM32_HSIDIV) || defined(__DOXYGEN__)
+#define STM32_HSIDIV STM32_HSIDIV_DIV1
+#endif
+
+/**
+ * @brief Clock source for all PLLs.
+ */
+#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__)
+#define STM32_PLLSRC STM32_PLLSRC_HSE_CK
+#endif
+
+/**
+ * @brief Masking of PLLCFGR register.
+ * @note By default all options in PLLCFGR are enabled, this option
+ * allows to mask specific bits for power saving reasons.
+ * Use with caution.
+ */
+#if !defined(STM32_PLLCFGR_MASK) || defined(__DOXYGEN__)
+#define STM32_PLLCFGR_MASK ~0
+#endif
+
+/**
+ * @brief Enables or disables the PLL1.
+ */
+#if !defined(STM32_PLL1_ENABLED) || defined(__DOXYGEN__)
+#define STM32_PLL1_ENABLED TRUE
+#endif
+
+/**
+ * @brief Enables or disables the PLL1 P output.
+ */
+#if !defined(STM32_PLL1_P_ENABLED) || defined(__DOXYGEN__)
+#define STM32_PLL1_P_ENABLED TRUE
+#endif
+
+/**
+ * @brief Enables or disables the PLL1 Q output.
+ */
+#if !defined(STM32_PLL1_Q_ENABLED) || defined(__DOXYGEN__)
+#define STM32_PLL1_Q_ENABLED TRUE
+#endif
+
+/**
+ * @brief Enables or disables the PLL1 R output.
+ */
+#if !defined(STM32_PLL1_R_ENABLED) || defined(__DOXYGEN__)
+#define STM32_PLL1_R_ENABLED TRUE
+#endif
+
+/**
+ * @brief PLL1 DIVM divider.
+ * @note The allowed values are 1..63.
+ */
+#if !defined(STM32_PLL1_DIVM_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLL1_DIVM_VALUE 4
+#endif
+
+/**
+ * @brief PLL1 DIVN multiplier.
+ * @note The allowed values are 4..512.
+ */
+#if !defined(STM32_PLL1_DIVN_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLL1_DIVN_VALUE 400
+#endif
+
+/**
+ * @brief PLL1 FRACN multiplier, zero if no fractional part.
+ * @note The allowed values are 0..8191.
+ */
+#if !defined(STM32_PLL1_FRACN_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLL1_FRACN_VALUE 0
+#endif
+
+/**
+ * @brief PLL1 DIVP divider.
+ * @note The allowed values are 2..128, odd values not allowed.
+ */
+#if !defined(STM32_PLL1_DIVP_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLL1_DIVP_VALUE 2
+#endif
+
+/**
+ * @brief PLL1 DIVQ divider.
+ * @note The allowed values are 1..128.
+ */
+#if !defined(STM32_PLL1_DIVQ_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLL1_DIVQ_VALUE 8
+#endif
+
+/**
+ * @brief PLL1 DIVR divider.
+ * @note The allowed values are 1..128.
+ */
+#if !defined(STM32_PLL1_DIVR_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLL1_DIVR_VALUE 8
+#endif
+
+/**
+ * @brief Enables or disables the PLL2.
+ */
+#if !defined(STM32_PLL2_ENABLED) || defined(__DOXYGEN__)
+#define STM32_PLL2_ENABLED TRUE
+#endif
+
+/**
+ * @brief Enables or disables the PLL2 P output.
+ */
+#if !defined(STM32_PLL2_P_ENABLED) || defined(__DOXYGEN__)
+#define STM32_PLL1_2_ENABLED TRUE
+#endif
+
+/**
+ * @brief Enables or disables the PLL2 Q output.
+ */
+#if !defined(STM32_PLL2_Q_ENABLED) || defined(__DOXYGEN__)
+#define STM32_PLL2_Q_ENABLED TRUE
+#endif
+
+/**
+ * @brief Enables or disables the PLL2 R output.
+ */
+#if !defined(STM32_PLL2_R_ENABLED) || defined(__DOXYGEN__)
+#define STM32_PLL2_R_ENABLED TRUE
+#endif
+
+/**
+ * @brief PLL2 DIVM divider.
+ * @note The allowed values are 1..63.
+ */
+#if !defined(STM32_PLL2_DIVM_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLL2_DIVM_VALUE 4
+#endif
+
+/**
+ * @brief PLL2 DIVN multiplier.
+ * @note The allowed values are 4..512.
+ */
+#if !defined(STM32_PLL2_DIVN_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLL2_DIVN_VALUE 400
+#endif
+
+/**
+ * @brief PLL2 FRACN multiplier, zero if no fractional part.
+ * @note The allowed values are 0..8191.
+ */
+#if !defined(STM32_PLL2_FRACN_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLL2_FRACN_VALUE 0
+#endif
+
+/**
+ * @brief PLL2 DIVP divider.
+ * @note The allowed values are 2..128, odd values not allowed.
+ */
+#if !defined(STM32_PLL2_DIVP_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLL2_DIVP_VALUE 40
+#endif
+
+/**
+ * @brief PLL2 DIVQ divider.
+ * @note The allowed values are 1..128.
+ */
+#if !defined(STM32_PLL2_DIVQ_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLL2_DIVQ_VALUE 8
+#endif
+
+/**
+ * @brief PLL2 DIVR divider.
+ * @note The allowed values are 1..128.
+ */
+#if !defined(STM32_PLL2_DIVR_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLL2_DIVR_VALUE 8
+#endif
+
+/**
+ * @brief Enables or disables the PLL3.
+ */
+#if !defined(STM32_PLL3_ENABLED) || defined(__DOXYGEN__)
+#define STM32_PLL3_ENABLED TRUE
+#endif
+
+/**
+ * @brief Enables or disables the PLL3 P output.
+ */
+#if !defined(STM32_PLL3_P_ENABLED) || defined(__DOXYGEN__)
+#define STM32_PLL3_P_ENABLED TRUE
+#endif
+
+/**
+ * @brief Enables or disables the PLL3 Q output.
+ */
+#if !defined(STM32_PLL3_Q_ENABLED) || defined(__DOXYGEN__)
+#define STM32_PLL3_Q_ENABLED TRUE
+#endif
+
+/**
+ * @brief Enables or disables the PLL3 R output.
+ */
+#if !defined(STM32_PLL3_R_ENABLED) || defined(__DOXYGEN__)
+#define STM32_PLL3_R_ENABLED TRUE
+#endif
+
+/**
+ * @brief PLL3 DIVM divider.
+ * @note The allowed values are 1..63.
+ */
+#if !defined(STM32_PLL3_DIVM_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLL3_DIVM_VALUE 4
+#endif
+
+/**
+ * @brief PLL3 DIVN multiplier.
+ * @note The allowed values are 4..512.
+ */
+#if !defined(STM32_PLL3_DIVN_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLL3_DIVN_VALUE 400
+#endif
+
+/**
+ * @brief PLL3 FRACN multiplier, zero if no fractional part.
+ * @note The allowed values are 0..8191.
+ */
+#if !defined(STM32_PLL3_FRACN_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLL3_FRACN_VALUE 0
+#endif
+
+/**
+ * @brief PLL3 DIVP divider.
+ * @note The allowed values are 2..128, odd values not allowed.
+ */
+#if !defined(STM32_PLL3_DIVP_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLL3_DIVP_VALUE 8
+#endif
+
+/**
+ * @brief PLL3 DIVQ divider.
+ * @note The allowed values are 1..128.
+ */
+#if !defined(STM32_PLL3_DIVQ_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLL3_DIVQ_VALUE 8
+#endif
+
+/**
+ * @brief PLL3 DIVR divider.
+ * @note The allowed values are 1..128.
+ */
+#if !defined(STM32_PLL3_DIVR_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLL3_DIVR_VALUE 8
+#endif
+
+/**
+ * @brief Peripherals clock selector.
+ */
+#if !defined(STM32_CKPERSEL) || defined(__DOXYGEN__)
+#define STM32_CKPERSEL STM32_CKPERSEL_HSE_CK
+#endif
+
+/**
+ * @brief MCO1 clock selector.
+ */
+#if !defined(STM32_MCO1SEL) || defined(__DOXYGEN__)
+#define STM32_MCO1SEL STM32_MCO1SEL_HSI_CK
+#endif
+
+/**
+ * @brief MCO1 clock prescaler.
+ */
+#if !defined(STM32_MCO1PRE_VALUE) || defined(__DOXYGEN__)
+#define STM32_MCO1PRE_VALUE 4
+#endif
+
+/**
+ * @brief MCO2 clock selector.
+ */
+#if !defined(STM32_MCO2SEL) || defined(__DOXYGEN__)
+#define STM32_MCO2SEL STM32_MCO2SEL_SYS_CK
+#endif
+
+/**
+ * @brief MCO2 clock prescaler.
+ */
+#if !defined(STM32_MCO2PRE_VALUE) || defined(__DOXYGEN__)
+#define STM32_MCO2PRE_VALUE 4
+#endif
+
+/**
+ * @brief TIM clock prescaler selection.
+ */
+#if !defined(STM32_TIMPRE_ENABLE) || defined(__DOXYGEN__)
+#define STM32_TIMPRE_ENABLE FALSE
+#endif
+
+/**
+ * @brief HRTIM clock prescaler selection.
+ */
+#if !defined(STM32_HRTIMSEL) || defined(__DOXYGEN__)
+#define STM32_HRTIMSEL 0
+#endif
+
+/**
+ * @brief Kernel clock selection after a wake up from system Stop.
+ */
+#if !defined(STM32_STOPKERWUCK) || defined(__DOXYGEN__)
+#define STM32_STOPKERWUCK 0
+#endif
+
+/**
+ * @brief System clock selection after a wake up from system Stop.
+ */
+#if !defined(STM32_STOPWUCK) || defined(__DOXYGEN__)
+#define STM32_STOPWUCK 0
+#endif
+
+/**
+ * @brief RTC HSE prescaler value.
+ * @note The allowed values are 2..63.
+ */
+#if !defined(STM32_RTCPRE_VALUE) || defined(__DOXYGEN__)
+#define STM32_RTCPRE_VALUE 8
+#endif
+
+/**
+ * @brief Main clock source selection.
+ * @note This setting can be modified at runtime.
+ */
+#if !defined(STM32_SW) || defined(__DOXYGEN__)
+#define STM32_SW STM32_SW_PLL1_P_CK1_P_CK
+#endif
+
+/**
+ * @brief RTC clock selector.
+ * @note This setting can be modified at runtime.
+ */
+#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__)
+#define STM32_RTCSEL STM32_RTCSEL_LSE_CK
+#endif
+
+/**
+ * @brief Clock domain 1 core bus prescaler.
+ * @note This setting can be modified at runtime.
+ */
+#if !defined(STM32_D1CPRE) || defined(__DOXYGEN__)
+#define STM32_D1CPRE STM32_D1CPRE_DIV1
+#endif
+
+/**
+ * @brief Clock domain 1 HPRE prescaler.
+ * @note This setting can be modified at runtime.
+ */
+#if !defined(STM32_D1HPRE) || defined(__DOXYGEN__)
+#define STM32_D1HPRE STM32_D1HPRE_DIV4
+#endif
+
+/**
+ * @brief Clock domain 1 peripherals bus prescaler.
+ * @note This setting can be modified at runtime.
+ */
+#if !defined(STM32_D1PPRE3) || defined(__DOXYGEN__)
+#define STM32_D1PPRE3 STM32_D1PPRE3_DIV1
+#endif
+
+/**
+ * @brief Clock domain 2 peripherals bus 1 prescaler.
+ * @note This setting can be modified at runtime.
+ */
+#if !defined(STM32_D2PPRE1) || defined(__DOXYGEN__)
+#define STM32_D2PPRE1 STM32_D2PPRE1_DIV1
+#endif
+
+/**
+ * @brief Clock domain 2 peripherals bus 2 prescaler.
+ * @note This setting can be modified at runtime.
+ */
+#if !defined(STM32_D2PPRE2) || defined(__DOXYGEN__)
+#define STM32_D2PPRE2 STM32_D2PPRE2_DIV1
+#endif
+
+/**
+ * @brief Clock domain 3 peripherals bus prescaler.
+ * @note This setting can be modified at runtime.
+ */
+#if !defined(STM32_D3PPRE4) || defined(__DOXYGEN__)
+#define STM32_D3PPRE4 STM32_D3PPRE4_DIV1
+#endif
+
+/**
+ * @brief SDMMC clock source.
+ */
+#if !defined(STM32_SDMMCSEL) || defined(__DOXYGEN__)
+#define STM32_SDMMCSEL STM32_SDMMCSEL_PLL1_Q_CK
+#endif
+
+/**
+ * @brief QSPI clock source.
+ */
+#if !defined(STM32H723xx) && (!defined(STM32_QSPISEL) || defined(__DOXYGEN__))
+#define STM32_QSPISEL STM32_QSPISEL_HCLK
+#endif
+
+/**
+ * @brief FMC clock source.
+ */
+#if !defined(STM32H723xx) && (!defined(STM32_FMCSEL) || defined(__DOXYGEN__))
+#define STM32_FMCSEL STM32_QSPISEL_HCLK
+#endif
+
+/**
+ * @brief SWP clock source.
+ */
+#if !defined(STM32_SWPSEL) || defined(__DOXYGEN__)
+#define STM32_SWPSEL STM32_SWPSEL_PCLK1
+#endif
+
+/**
+ * @brief FDCAN clock source.
+ */
+#if !defined(STM32_FDCANSEL) || defined(__DOXYGEN__)
+#define STM32_FDCANSEL STM32_FDCANSEL_HSE_CK
+#endif
+
+/**
+ * @brief DFSDM1 clock source.
+ */
+#if !defined(STM32_DFSDM1SEL) || defined(__DOXYGEN__)
+#define STM32_DFSDM1SEL STM32_DFSDM1SEL_PCLK2
+#endif
+
+/**
+ * @brief SPDIF clock source.
+ */
+#if !defined(STM32_SPDIFSEL) || defined(__DOXYGEN__)
+#define STM32_SPDIFSEL STM32_SPDIFSEL_PLL1_Q_CK
+#endif
+
+/**
+ * @brief SPI45 clock source.
+ */
+#if !defined(STM32_SPI45SEL) || defined(__DOXYGEN__)
+#define STM32_SPI45SEL STM32_SPI45SEL_PCLK2
+#endif
+
+/**
+ * @brief SPI123 clock source.
+ */
+#if !defined(STM32_SPI123SEL) || defined(__DOXYGEN__)
+#define STM32_SPI123SEL STM32_SPI123SEL_PLL1_Q_CK
+#endif
+
+/**
+ * @brief SAI23 clock source.
+ */
+#if !defined(STM32H723xx) && (!defined(STM32_SAI23SEL) || defined(__DOXYGEN__))
+#define STM32_SAI23SEL STM32_SAI23SEL_PLL1_Q_CK
+#endif
+
+/**
+ * @brief SAI1 clock source.
+ */
+#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__)
+#define STM32_SAI1SEL STM32_SAI1SEL_PLL1_Q_CK
+#endif
+
+/**
+ * @brief LPTIM1 clock source.
+ */
+#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__)
+#define STM32_LPTIM1SEL STM32_LPTIM1_PCLK1
+#endif
+
+/**
+ * @brief CEC clock source.
+ */
+#if !defined(STM32_CECSEL) || defined(__DOXYGEN__)
+#define STM32_CECSEL STM32_CECSEL_LSE_CK
+#endif
+
+/**
+ * @brief USB clock source.
+ */
+#if !defined(STM32_USBSEL) || defined(__DOXYGEN__)
+#define STM32_USBSEL STM32_USBSEL_PLL3_Q_CK
+#endif
+
+#if !defined(STM32H723xx)
+
+/**
+ * @brief I2C123 clock source.
+ */
+#if !defined(STM32_I2C123SEL) || defined(__DOXYGEN__)
+#define STM32_I2C123SEL STM32_I2C123SEL_PCLK1
+#endif
+
+#else // below for defined(STM32H723xx)
+
+#if !defined(STM32_I2C1235SEL) || defined(__DOXYGEN__)
+#define STM32_I2C1235SEL STM32_I2C1235SEL_PCLK1
+#endif
+
+#endif // defined(STM32H723xx)
+
+/**
+ * @brief RNG clock source.
+ */
+#if !defined(STM32_RNGSEL) || defined(__DOXYGEN__)
+#define STM32_RNGSEL STM32_RNGSEL_HSI48_CK
+#endif
+
+#if !defined(STM32H723xx)
+/**
+ * @brief USART16 clock source.
+ */
+#if !defined(STM32_USART16SEL) || defined(__DOXYGEN__)
+#define STM32_USART16SEL STM32_USART16SEL_PCLK2
+#endif
+#else
+/**
+ * @brief USART16910 clock source.
+ */
+#if !defined(STM32_USART16910SEL) || defined(__DOXYGEN__)
+#define STM32_USART16910SEL STM32_USART16910SEL_PCLK2
+#endif
+#endif // !defined(STM32H723xx)
+
+/**
+ * @brief USART234578 clock source.
+ */
+#if !defined(STM32_USART234578SEL) || defined(__DOXYGEN__)
+#define STM32_USART234578SEL STM32_USART234578SEL_PCLK1
+#endif
+
+/**
+ * @brief SPI6SEL clock source.
+ */
+#if !defined(STM32_SPI6SEL) || defined(__DOXYGEN__)
+#define STM32_SPI6SEL STM32_SPI6SEL_PCLK4
+#endif
+
+/**
+ * @brief SAI4BSEL clock source.
+ */
+#if !defined(STM32_SAI4BSEL) || defined(__DOXYGEN__)
+#define STM32_SAI4BSEL STM32_SAI4BSEL_PLL1_Q_CK
+#endif
+
+/**
+ * @brief SAI4ASEL clock source.
+ */
+#if !defined(STM32_SAI4ASEL) || defined(__DOXYGEN__)
+#define STM32_SAI4ASEL STM32_SAI4ASEL_PLL1_Q_CK
+#endif
+
+/**
+ * @brief ADCSEL clock source.
+ */
+#if !defined(STM32_ADCSEL) || defined(__DOXYGEN__)
+#define STM32_ADCSEL STM32_ADCSEL_PLL2_P_CK
+#endif
+
+/**
+ * @brief LPTIM345SEL clock source.
+ */
+#if !defined(STM32_LPTIM345SEL) || defined(__DOXYGEN__)
+#define STM32_LPTIM345SEL STM32_LPTIM345SEL_PCLK4
+#endif
+
+/**
+ * @brief LPTIM2SEL clock source.
+ */
+#if !defined(STM32_LPTIM2SEL) || defined(__DOXYGEN__)
+#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK4
+#endif
+
+/**
+ * @brief I2C4SEL clock source.
+ */
+#if !defined(STM32_I2C4SEL) || defined(__DOXYGEN__)
+#define STM32_I2C4SEL STM32_I2C4SEL_PCLK4
+#endif
+
+/**
+ * @brief LPUART1SEL clock source.
+ */
+#if !defined(STM32_LPUART1SEL) || defined(__DOXYGEN__)
+#define STM32_LPUART1SEL STM32_LPUART1SEL_PCLK4
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*
+ * Configuration-related checks.
+ */
+#if !defined(STM32H7xx_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32H7xx_MCUCONF not defined"
+#endif
+
+#if defined(STM32H750xx)&& !defined(STM32H750_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32H750_MCUCONF not defined"
+#endif
+
+#if defined(STM32H742xx)&& !defined(STM32H742_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32H742_MCUCONF not defined"
+#endif
+
+#if defined(STM32H743xx)&& !defined(STM32H743_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32H743_MCUCONF not defined"
+#endif
+
+#if defined(STM32H753xx)&& !defined(STM32H753_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32H753_MCUCONF not defined"
+#endif
+
+#if defined(STM32H745xx)&& !defined(STM32H745_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32H745_MCUCONF not defined"
+#endif
+
+#if defined(STM32H755xx)&& !defined(STM32H755_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32H755_MCUCONF not defined"
+#endif
+
+#if defined(STM32H747xx)&& !defined(STM32H747_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32H747_MCUCONF not defined"
+#endif
+
+#if defined(STM32H757xx)&& !defined(STM32H757_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32H757_MCUCONF not defined"
+#endif
+
+/*
+ * Board file checks.
+ */
+#if !defined(STM32_LSECLK)
+#error "STM32_LSECLK not defined in board.h"
+#endif
+#if !defined(STM32_LSEDRV)
+#error "STM32_LSEDRV not defined in board.h"
+#endif
+#if !defined(STM32_HSECLK)
+#error "STM32_HSECLK not defined in board.h"
+#endif
+
+/**
+ * @name Constants depending on VOS and ODEN setting
+ * @{
+ */
+#if STM32_VOS == STM32_VOS_SCALE1 || STM32_VOS == STM32_VOS_SCALE0
+#define STM32_0WS_THRESHOLD 70000000U
+#define STM32_1WS_THRESHOLD 140000000U
+#define STM32_2WS_THRESHOLD 210000000U
+#define STM32_3WS_THRESHOLD 225000000U
+#define STM32_4WS_THRESHOLD 240000000U
+#define STM32_PLLOUT_MAX 480000000U
+#define STM32_PLLOUT_MIN 1500000U
+
+#elif STM32_VOS == STM32_VOS_SCALE2
+#define STM32_0WS_THRESHOLD 55000000U
+#define STM32_1WS_THRESHOLD 110000000U
+#define STM32_2WS_THRESHOLD 165000000U
+#define STM32_3WS_THRESHOLD 225000000U
+#define STM32_4WS_THRESHOLD 0U
+#define STM32_PLLOUT_MAX 300000000U
+#define STM32_PLLOUT_MIN 1500000U
+
+#elif STM32_VOS == STM32_VOS_SCALE3
+#define STM32_0WS_THRESHOLD 45000000U
+#define STM32_1WS_THRESHOLD 90000000U
+#define STM32_2WS_THRESHOLD 135000000U
+#define STM32_3WS_THRESHOLD 180000000U
+#define STM32_4WS_THRESHOLD 225000000U
+#define STM32_PLLOUT_MAX 200000000U
+#define STM32_PLLOUT_MIN 1500000U
+
+#else
+#error "invalid STM32_VOS setting specified"
+#endif
+/** @} */
+
+/*
+ * HSI related checks.
+ */
+#if STM32_HSI_ENABLED
+#define STM32_HSICLK STM32_HSI_OSC
+
+#else /* !STM32_HSI_ENABLED */
+#define STM32_HSICLK 0U
+
+#if STM32_SW == STM32_SW_HSI_CK
+#error "HSI not enabled, required by STM32_SW"
+#endif
+
+#if (STM32_PLLSRC == STM32_PLLSRC_HSI_CK) && \
+ (STM32_PLL1_ENABLED || STM32_PLL2_ENABLED || STM32_PLL3_ENABLED)
+#error "HSI not enabled, required by STM32_PLLSRC and STM32_PLLx_ENABLED"
+#endif
+
+#if STM32_CKPERSEL == STM32_CKPERSEL_HSI_CK
+#error "HSI not enabled, required by STM32_CKPERSEL"
+#endif
+
+#if STM32_MCO1SEL == STM32_MCO1SEL_HSI_CK
+#error "HSI not enabled, required by STM32_MCO1SEL"
+#endif
+
+#endif /* !STM32_HSI_ENABLED */
+
+/*
+ * HSI48 related checks.
+ */
+#if STM32_HSI48_ENABLED
+#define STM32_HSI48_CK STM32_HSI48_OSC
+
+#else /* !STM32_HSI48_ENABLED */
+#define STM32_HSI48_CK 0U
+
+#if STM32_MCO1SEL == STM32_MCO1SEL_HSI48_CK
+#error "HSI48 not enabled, required by STM32_MCO1SEL"
+#endif
+
+#endif /* !STM32_HSI48_ENABLED */
+
+/*
+ * CSI related checks.
+ */
+#if STM32_CSI_ENABLED
+#define STM32_CSI_CK STM32_CSI_OSC
+
+#else /* !STM32_CSI_ENABLED */
+#define STM32_CSI_CK 0U
+
+#if STM32_SW == STM32_SW_CSI_CK
+#error "CSI not enabled, required by STM32_SW"
+#endif
+
+#if (STM32_PLLSRC == STM32_PLLSRC_CSI_CK) && \
+ (STM32_PLL1_ENABLED || STM32_PLL2_ENABLED || STM32_PLL3_ENABLED)
+#error "CSI not enabled, required by STM32_PLLSRC and STM32_PLLx_ENABLED"
+#endif
+
+#if STM32_CKPERSEL == STM32_CKPERSEL_CSI_CK
+#error "CSI not enabled, required by STM32_CKPERSEL"
+#endif
+
+#if STM32_MCO2SEL == STM32_MCO2SEL_CSI_CK
+#error "CSI not enabled, required by STM32_MCO2SEL"
+#endif
+
+#endif /* !STM32_CSI_ENABLED */
+
+/*
+ * HSE related checks.
+ */
+#if STM32_HSE_ENABLED
+
+#if !defined(STM32_HSECLK)
+#error "HSE frequency not defined"
+#endif
+
+#define STM32_HSE_CK STM32_HSECLK
+
+#if STM32_HSECLK == 0
+#error "HSE oscllator not available"
+#else /* STM32_HSECLK != 0 */
+#if defined(STM32_HSE_BYPASS)
+#if (STM32_HSECLK < STM32_HSECLK_BYP_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX)
+#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_BYP_MIN..STM32_HSECLK_BYP_MAX)"
+#endif
+#else /* !defined(STM32_HSE_BYPASS) */
+#if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX)
+#error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN..STM32_HSECLK_MAX)"
+#endif
+#endif /* !defined(STM32_HSE_BYPASS) */
+#endif /* STM32_HSECLK != 0 */
+#else /* !STM32_HSE_ENABLED */
+
+#if STM32_SW == STM32_SW_HSE_CK
+#error "HSE not enabled, required by STM32_SW"
+#endif
+
+#if (STM32_PLLSRC == STM32_PLLSRC_HSE_CK) && \
+ (STM32_PLL1_ENABLED || STM32_PLL2_ENABLED || STM32_PLL3_ENABLED)
+#error "HSE not enabled, required by STM32_PLLSRC and STM32_PLLx_ENABLED"
+#endif
+
+#if STM32_MCO1SEL == STM32_MCO1SEL_HSE_CK
+#error "HSE not enabled, required by STM32_MCO1SEL"
+#endif
+
+#if STM32_MCO2SEL == STM32_MCO2SEL_HSE_CK
+#error "HSE not enabled, required by STM32_MCO2SEL"
+#endif
+
+#if STM32_RTCSEL == STM32_RTCSEL_HSE_1M_CK
+#error "HSE not enabled, required by STM32_RTCSEL"
+#endif
+
+#endif /* !STM32_HSE_ENABLED */
+
+/*
+ * LSI related checks.
+ */
+#if STM32_LSI_ENABLED
+#define STM32_LSI_CK STM32_LSI_OSC
+
+#else /* !STM32_LSI_ENABLED */
+#define STM32_LSI_CK 0U
+
+#if STM32_RTCSEL == STM32_RTCSEL_LSI_CK
+#error "LSI not enabled, required by STM32_RTCSEL"
+#endif
+
+#if STM32_MCO2SEL == STM32_MCO2SEL_LSI_CK
+#error "HSE not enabled, required by STM32_MCO2SEL"
+#endif
+
+#endif /* !STM32_LSI_ENABLED */
+
+/*
+ * LSE related checks.
+ */
+#if STM32_LSE_ENABLED
+
+#if !defined(STM32_LSECLK)
+#error "LSE frequency not defined"
+#endif
+
+#define STM32_LSE_CK STM32_LSECLK
+
+#if (STM32_LSE_CK == 0)
+#error "LSE oscillator not available"
+#endif
+
+#if defined(STM32_LSE_BYPASS)
+#if (STM32_LSE_CK < STM32_LSE_CK_MIN) || (STM32_LSE_CK > STM32_LSE_CK_BYP_MAX)
+#error "STM32_LSE_CK outside acceptable range (STM32_LSE_CK_MIN..STM32_LSE_CK_BYP_MAX)"
+#endif
+#else
+#if (STM32_LSE_CK < STM32_LSE_CK_MIN) || (STM32_LSE_CK > STM32_LSE_CK_MAX)
+#error "STM32_LSE_CK outside acceptable range (STM32_LSE_CK_MIN..STM32_LSE_CK_MAX)"
+#endif
+#endif
+
+#if !defined(STM32_LSEDRV)
+#error "STM32_LSEDRV not defined"
+#endif
+
+#if (STM32_LSEDRV >> 3) > 3
+#error "STM32_LSEDRV outside acceptable range ((0<<3)..(3<<3))"
+#endif
+
+#else /* !STM32_LSE_ENABLED */
+
+#if STM32_RTCSEL == STM32_RTCSEL_LSE_CK
+#error "LSE not enabled, required by STM32_RTCSEL"
+#endif
+
+#if STM32_MCO1SEL == STM32_MCO1SEL_LSE_CK
+#error "LSE not enabled, required by STM32_MCO1SEL"
+#endif
+
+#endif /* !STM32_LSE_ENABLED */
+
+/**
+ * @brief HSI divided clock.
+ */
+#if (STM32_HSIDIV == STM32_HSIDIV_DIV1) || defined(__DOXYGEN__)
+#define STM32_HSI_CK (STM32_HSICLK / 1U)
+#elif STM32_HSIDIV == STM32_HSIDIV_DIV2
+#define STM32_HSI_CK (STM32_HSICLK / 2U)
+#elif STM32_HSIDIV == STM32_HSIDIV_DIV4
+#define STM32_HSI_CK (STM32_HSICLK / 4U)
+#elif STM32_HSIDIV == STM32_HSIDIV_DIV8
+#define STM32_HSI_CK (STM32_HSICLK / 8U)
+#else
+#error "invalid STM32_HSIDIV value specified"
+#endif
+
+/**
+ * @brief HSE divided clock for RTC.
+ */
+#if ((STM32_RTCPRE_VALUE >= 2) && (STM32_RTCPRE_VALUE <= 63)) || \
+ defined(__DOXYGEN__)
+#define STM32_HSE_1M_CK (STM32_HSE_CK / STM32_RTCPRE_VALUE)
+#else
+#error "invalid STM32_RTCPRE_VALUE value specified"
+#endif
+
+/**
+ * @brief PLLs input clock frequency.
+ */
+#if (STM32_PLLSRC == STM32_PLLSRC_HSE_CK) || defined(__DOXYGEN__)
+#define STM32_PLLCLKIN STM32_HSE_CK
+
+#elif STM32_PLLSRC == STM32_PLLSRC_HSI_CK
+#define STM32_PLLCLKIN STM32_HSI_CK
+
+#elif STM32_PLLSRC == STM32_PLLSRC_CSI_CK
+#define STM32_PLLCLKIN STM32_CSI_CK
+
+#elif STM32_PLLSRC == STM32_PLLSRC_DISABLE
+
+#else
+#error "invalid STM32_PLLSRC value specified"
+#endif
+
+#if STM32_PLLSRC != STM32_PLLSRC_DISABLE
+
+/**
+ * @brief PLL1 DIVM field.
+ */
+#if ((STM32_PLL1_DIVM_VALUE >= 1) && (STM32_PLL1_DIVM_VALUE <= 63)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLL1_DIVM (STM32_PLL1_DIVM_VALUE << 4)
+#define STM32_PLL1_REF_CK (STM32_PLLCLKIN / STM32_PLL1_DIVM_VALUE)
+#else
+#error "invalid STM32_PLL1_DIVM_VALUE value specified"
+#endif
+
+/*
+ * PLL1 input frequency range check.
+ */
+#if (STM32_PLL1_REF_CK < STM32_PLLIN_MIN) || (STM32_PLL1_REF_CK > STM32_PLLIN_MAX)
+#error "STM32_PLL1_REF_CK outside acceptable range (STM32_PLLIN_MIN..STM32_PLLIN_MAX)"
+#endif
+
+/**
+ * @brief PLL1 input range selector.
+ */
+#if (STM32_PLL1_REF_CK < STM32_PLLIN_THRESHOLD1) || defined(__DOXYGEN__)
+#define STM32_PLLCFGR_PLL1RGE RCC_PLLCFGR_PLL1RGE_0
+#elif STM32_PLL1_REF_CK < STM32_PLLIN_THRESHOLD2
+#define STM32_PLLCFGR_PLL1RGE RCC_PLLCFGR_PLL1RGE_1
+#elif STM32_PLL1_REF_CK < STM32_PLLIN_THRESHOLD3
+#define STM32_PLLCFGR_PLL1RGE RCC_PLLCFGR_PLL1RGE_2
+#else
+#define STM32_PLLCFGR_PLL1RGE RCC_PLLCFGR_PLL1RGE_3
+#endif
+
+/**
+ * @brief PLL2 DIVM field.
+ */
+#if ((STM32_PLL2_DIVM_VALUE >= 1) && (STM32_PLL2_DIVM_VALUE <= 63)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLL2_DIVM (STM32_PLL2_DIVM_VALUE << 12)
+#define STM32_PLL2_REF_CK (STM32_PLLCLKIN / STM32_PLL2_DIVM_VALUE)
+#else
+#error "invalid STM32_PLL2_DIVM_VALUE value specified"
+#endif
+
+/*
+ * PLL2 input frequency range check.
+ */
+#if (STM32_PLL2_REF_CK < STM32_PLLIN_MIN) || (STM32_PLL2_REF_CK > STM32_PLLIN_MAX)
+#error "STM32_PLL2_REF_CK outside acceptable range (STM32_PLLIN_MIN..STM32_PLLIN_MAX)"
+#endif
+
+/**
+ * @brief PLL2 input range selector.
+ */
+#if (STM32_PLL2_REF_CK < STM32_PLLIN_THRESHOLD1) || defined(__DOXYGEN__)
+#define STM32_PLLCFGR_PLL2RGE RCC_PLLCFGR_PLL2RGE_0
+#elif STM32_PLL2_REF_CK < STM32_PLLIN_THRESHOLD2
+#define STM32_PLLCFGR_PLL2RGE RCC_PLLCFGR_PLL2RGE_1
+#elif STM32_PLL2_REF_CK < STM32_PLLIN_THRESHOLD3
+#define STM32_PLLCFGR_PLL2RGE RCC_PLLCFGR_PLL2RGE_2
+#else
+#define STM32_PLLCFGR_PLL2RGE RCC_PLLCFGR_PLL2RGE_3
+#endif
+
+/**
+ * @brief PLL3 DIVM field.
+ */
+#if ((STM32_PLL3_DIVM_VALUE >= 1) && (STM32_PLL3_DIVM_VALUE <= 63)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLL3_DIVM (STM32_PLL3_DIVM_VALUE << 20)
+#define STM32_PLL3_REF_CK (STM32_PLLCLKIN / STM32_PLL3_DIVM_VALUE)
+#else
+#error "invalid STM32_PLL3_DIVM_VALUE value specified"
+#endif
+
+/*
+ * PLL3 input frequency range check.
+ */
+#if (STM32_PLL3_REF_CK < STM32_PLLIN_MIN) || (STM32_PLL3_REF_CK > STM32_PLLIN_MAX)
+#error "STM32_PLL3_REF_CK outside acceptable range (STM32_PLLIN_MIN..STM32_PLLIN_MAX)"
+#endif
+
+/**
+ * @brief PLL3 input range selector.
+ */
+#if (STM32_PLL3_REF_CK < STM32_PLLIN_THRESHOLD1) || defined(__DOXYGEN__)
+#define STM32_PLLCFGR_PLL3RGE RCC_PLLCFGR_PLL3RGE_0
+#elif STM32_PLL3_REF_CK < STM32_PLLIN_THRESHOLD2
+#define STM32_PLLCFGR_PLL3RGE RCC_PLLCFGR_PLL3RGE_1
+#elif STM32_PLL3_REF_CK < STM32_PLLIN_THRESHOLD3
+#define STM32_PLLCFGR_PLL3RGE RCC_PLLCFGR_PLL3RGE_2
+#else
+#define STM32_PLLCFGR_PLL3RGE RCC_PLLCFGR_PLL3RGE_3
+#endif
+
+/**
+ * @brief PLL1 DIVN field.
+ */
+#if ((STM32_PLL1_DIVN_VALUE >= 4) && (STM32_PLL1_DIVN_VALUE <= 512)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLL1_DIVN ((STM32_PLL1_DIVN_VALUE - 1U) << 0U)
+#else
+#error "invalid STM32_PLL1_DIVN_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL2 DIVN field.
+ */
+#if ((STM32_PLL2_DIVN_VALUE >= 4) && (STM32_PLL2_DIVN_VALUE <= 512)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLL2_DIVN ((STM32_PLL2_DIVN_VALUE - 1U) << 0U)
+#else
+#error "invalid STM32_PLL2_DIVN_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL3 DIVN field.
+ */
+#if ((STM32_PLL3_DIVN_VALUE >= 4) && (STM32_PLL3_DIVN_VALUE <= 512)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLL3_DIVN ((STM32_PLL3_DIVN_VALUE - 1U) << 0U)
+#else
+#error "invalid STM32_PLL3_DIVN_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL1 FRACN field.
+ */
+#if ((STM32_PLL1_FRACN_VALUE >= 0) && (STM32_PLL1_FRACN_VALUE <= 8191)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLL1_FRACN (STM32_PLL1_FRACN_VALUE << 3U)
+#else
+#error "invalid STM32_PLL1_FRACN_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL2 FRACN field.
+ */
+#if ((STM32_PLL2_FRACN_VALUE >= 0) && (STM32_PLL2_FRACN_VALUE <= 8191)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLL2_FRACN (STM32_PLL2_FRACN_VALUE << 3U)
+#else
+#error "invalid STM32_PLL2_FRACN_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL3 FRACN field.
+ */
+#if ((STM32_PLL3_FRACN_VALUE >= 0) && (STM32_PLL3_FRACN_VALUE <= 8191)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLL3_FRACN (STM32_PLL3_FRACN_VALUE << 3U)
+#else
+#error "invalid STM32_PLL3_FRACN_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL1 DIVP field.
+ */
+#if ((STM32_PLL1_DIVP_VALUE >= 1) && (STM32_PLL1_DIVP_VALUE <= 128) && \
+ ((STM32_PLL1_DIVP_VALUE & 1U) == 0U || STM32_PLL1_DIVP_VALUE == 1)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLL1_DIVP ((STM32_PLL1_DIVP_VALUE - 1U) << 9U)
+#else
+#error "invalid STM32_PLL1_DIVP_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL2 DIVP field.
+ */
+#if ((STM32_PLL2_DIVP_VALUE >= 2) && (STM32_PLL2_DIVP_VALUE <= 128)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLL2_DIVP ((STM32_PLL2_DIVP_VALUE - 1U) << 9U)
+#else
+#error "invalid STM32_PLL2_DIVP_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL3 DIVP field.
+ */
+#if ((STM32_PLL3_DIVP_VALUE >= 2) && (STM32_PLL3_DIVP_VALUE <= 128)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLL3_DIVP ((STM32_PLL3_DIVP_VALUE - 1U) << 9U)
+#else
+#error "invalid STM32_PLL3_DIVP_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL1 DIVQ field.
+ */
+#if ((STM32_PLL1_DIVQ_VALUE >= 1) && (STM32_PLL1_DIVQ_VALUE <= 128)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLL1_DIVQ ((STM32_PLL1_DIVQ_VALUE - 1U) << 16U)
+#else
+#error "invalid STM32_PLL1_DIVQ_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL2 DIVQ field.
+ */
+#if ((STM32_PLL2_DIVQ_VALUE >= 1) && (STM32_PLL2_DIVQ_VALUE <= 128)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLL2_DIVQ ((STM32_PLL2_DIVQ_VALUE - 1U) << 16U)
+#else
+#error "invalid STM32_PLL2_DIVQ_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL3 DIVQ field.
+ */
+#if ((STM32_PLL3_DIVQ_VALUE >= 1) && (STM32_PLL3_DIVQ_VALUE <= 128)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLL3_DIVQ ((STM32_PLL3_DIVQ_VALUE - 1U) << 16U)
+#else
+#error "invalid STM32_PLL3_DIVQ_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL1 DIVR field.
+ */
+#if ((STM32_PLL1_DIVR_VALUE >= 1) && (STM32_PLL1_DIVR_VALUE <= 128)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLL1_DIVR ((STM32_PLL1_DIVR_VALUE - 1U) << 24U)
+#else
+#error "invalid STM32_PLL1_DIVR_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL2 DIVR field.
+ */
+#if ((STM32_PLL2_DIVR_VALUE >= 1) && (STM32_PLL2_DIVR_VALUE <= 128)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLL2_DIVR ((STM32_PLL2_DIVR_VALUE - 1U) << 24U)
+#else
+#error "invalid STM32_PLL2_DIVR_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL3 DIVR field.
+ */
+#if ((STM32_PLL3_DIVR_VALUE >= 1) && (STM32_PLL3_DIVR_VALUE <= 128)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLL3_DIVR ((STM32_PLL3_DIVR_VALUE - 1U) << 24U)
+#else
+#error "invalid STM32_PLL3_DIVR_VALUE value specified"
+#endif
+
+/**
+ * @brief PLL1 VCO frequency.
+ */
+#define STM32_PLL1_VCO_CK (STM32_PLL1_REF_CK * STM32_PLL1_DIVN_VALUE)
+
+/*
+ * PLL1 VCO frequency range check.
+ */
+#if (STM32_PLL1_VCO_CK < STM32_PLLVCO_MIN) || (STM32_PLL1_VCO_CK > STM32_PLLVCO_MAX)
+#error "STM32_PLL1_VCO_CK outside acceptable range (STM32_PLLVCO_MIN..STM32_PLLVCO_MAX)"
+#endif
+
+/*
+ * PLL1 VCO mode.
+ */
+#if (STM32_PLL1_VCO_CK > STM32_PLLVCO_THRESHOLD) || defined(__DOXYGEN__)
+#define STM32_PLLCFGR_PLL1VCOSEL 0U
+#else
+#define STM32_PLLCFGR_PLL1VCOSEL RCC_PLLCFGR_PLL1VCOSEL
+#endif
+
+/**
+ * @brief PLL2 VCO frequency.
+ */
+#define STM32_PLL2_VCO_CK (STM32_PLL2_REF_CK * STM32_PLL2_DIVN_VALUE)
+
+/*
+ * PLL2 VCO frequency range check.
+ */
+#if STM32_PLL2_ENABLED == TRUE
+#if (STM32_PLL2_VCO_CK < STM32_PLLVCO_MIN) || (STM32_PLL2_VCO_CK > STM32_PLLVCO_MAX)
+#error "STM32_PLL2_VCO_CK outside acceptable range (STM32_PLLVCO_MIN..STM32_PLLVCO_MAX)"
+#endif
+#endif // STM32_PLL2_ENABLED == TRUE
+
+/*
+ * PLL2 VCO mode.
+ */
+#if (STM32_PLL2_VCO_CK > STM32_PLLVCO_THRESHOLD) || defined(__DOXYGEN__)
+#define STM32_PLLCFGR_PLL2VCOSEL 0U
+#else
+#define STM32_PLLCFGR_PLL2VCOSEL RCC_PLLCFGR_PLL2VCOSEL
+#endif
+
+/**
+ * @brief PLL3 VCO frequency.
+ */
+#define STM32_PLL3_VCO_CK (STM32_PLL3_REF_CK * STM32_PLL3_DIVN_VALUE)
+
+/*
+ * PLL3 VCO frequency range check.
+ */
+#if STM32_PLL3_ENABLED == TRUE
+#if (STM32_PLL3_VCO_CK < STM32_PLLVCO_MIN) || (STM32_PLL3_VCO_CK > STM32_PLLVCO_MAX)
+#error "STM32_PLL3_VCO_CK outside acceptable range (STM32_PLLVCO_MIN..STM32_PLLVCO_MAX)"
+#endif
+#endif // STM32_PLL3_ENABLED == TRUE
+
+/*
+ * PLL3 VCO mode.
+ */
+#if (STM32_PLL3_VCO_CK > STM32_PLLVCO_THRESHOLD) || defined(__DOXYGEN__)
+#define STM32_PLLCFGR_PLL3VCOSEL 0U
+#else
+#define STM32_PLLCFGR_PLL3VCOSEL RCC_PLLCFGR_PLL3VCOSEL
+#endif
+
+#endif // STM32_PLLSRC != STM32_PLLSRC_DISABLE
+
+#if ((STM32_PLL1_ENABLED == TRUE) && (STM32_PLL1_P_ENABLED == TRUE)) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief PLL1 P output clock frequency.
+ */
+#define STM32_PLL1_P_CK (STM32_PLL1_VCO_CK / STM32_PLL1_DIVP_VALUE)
+
+/*
+ * PLL1 P output frequency range check.
+ */
+#if (STM32_PLL1_P_CK < STM32_PLLOUT_MIN) || (STM32_PLL1_P_CK > STM32_PLLOUT_MAX)
+#error "STM32_PLL1_P_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)"
+#endif
+#else
+#define STM32_PLL1_P_CK 0U
+#endif
+
+#if ((STM32_PLL2_ENABLED == TRUE) && (STM32_PLL2_P_ENABLED == TRUE)) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief PLL2 P output clock frequency.
+ */
+#define STM32_PLL2_P_CK (STM32_PLL2_VCO_CK / STM32_PLL2_DIVP_VALUE)
+
+/*
+ * PLL2 P output frequency range check.
+ */
+#if (STM32_PLL2_P_CK < STM32_PLLOUT_MIN) || (STM32_PLL2_P_CK > STM32_PLLOUT_MAX)
+#error "STM32_PLL2_P_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)"
+#endif
+#else
+#define STM32_PLL2_P_CK 0U
+#endif
+
+#if ((STM32_PLL3_ENABLED == TRUE) && (STM32_PLL3_P_ENABLED == TRUE)) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief PLL3 P output clock frequency.
+ */
+#define STM32_PLL3_P_CK (STM32_PLL3_VCO_CK / STM32_PLL3_DIVP_VALUE)
+
+/*
+ * PLL3 P output frequency range check.
+ */
+#if (STM32_PLL3_P_CK < STM32_PLLOUT_MIN) || (STM32_PLL3_P_CK > STM32_PLLOUT_MAX)
+#error "STM32_PLL3_P_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)"
+#endif
+#else
+#define STM32_PLL3_P_CK 0U
+#endif
+
+#if ((STM32_PLL1_ENABLED == TRUE) && (STM32_PLL1_Q_ENABLED == TRUE)) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief PLL1 Q output clock frequency.
+ */
+#define STM32_PLL1_Q_CK (STM32_PLL1_VCO_CK / STM32_PLL1_DIVQ_VALUE)
+
+/*
+ * PLL1 Q output frequency range check.
+ */
+#if (STM32_PLL1_Q_CK < STM32_PLLOUT_MIN) || (STM32_PLL1_Q_CK > STM32_PLLOUT_MAX)
+#error "STM32_PLL1_Q_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)"
+#endif
+#else
+#define STM32_PLL1_Q_CK 0U
+#endif
+
+#if ((STM32_PLL2_ENABLED == TRUE) && (STM32_PLL2_Q_ENABLED == TRUE)) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief PLL2 Q output clock frequency.
+ */
+#define STM32_PLL2_Q_CK (STM32_PLL2_VCO_CK / STM32_PLL2_DIVQ_VALUE)
+
+/*
+ * PLL2 Q output frequency range check.
+ */
+#if (STM32_PLL2_Q_CK < STM32_PLLOUT_MIN) || (STM32_PLL2_Q_CK > STM32_PLLOUT_MAX)
+#error "STM32_PLL2_Q_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)"
+#endif
+#else
+#define STM32_PLL2_Q_CK 0U
+#endif
+
+#if ((STM32_PLL3_ENABLED == TRUE) && (STM32_PLL3_Q_ENABLED == TRUE)) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief PLL3 Q output clock frequency.
+ */
+#define STM32_PLL3_Q_CK (STM32_PLL3_VCO_CK / STM32_PLL3_DIVQ_VALUE)
+
+/*
+ * PLL3 Q output frequency range check.
+ */
+#if (STM32_PLL3_Q_CK < STM32_PLLOUT_MIN) || (STM32_PLL3_Q_CK > STM32_PLLOUT_MAX)
+#error "STM32_PLL3_Q_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)"
+#endif
+#else
+#define STM32_PLL3_Q_CK 0U
+#endif
+
+#if ((STM32_PLL1_ENABLED == TRUE) && (STM32_PLL1_R_ENABLED == TRUE)) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief PLL1 R output clock frequency.
+ */
+#define STM32_PLL1_R_CK (STM32_PLL1_VCO_CK / STM32_PLL1_DIVR_VALUE)
+
+/*
+ * PLL1 R output frequency range check.
+ */
+#if (STM32_PLL1_R_CK < STM32_PLLOUT_MIN) || (STM32_PLL1_R_CK > STM32_PLLOUT_MAX)
+#error "STM32_PLL1_R_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)"
+#endif
+#else
+#define STM32_PLL1_R_CK 0U
+#endif
+
+#if ((STM32_PLL2_ENABLED == TRUE) && (STM32_PLL2_R_ENABLED == TRUE)) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief PLL2 R output clock frequency.
+ */
+#define STM32_PLL2_R_CK (STM32_PLL2_VCO_CK / STM32_PLL2_DIVR_VALUE)
+
+/*
+ * PLL2 R output frequency range check.
+ */
+#if (STM32_PLL2_R_CK < STM32_PLLOUT_MIN) || (STM32_PLL2_R_CK > STM32_PLLOUT_MAX)
+#error "STM32_PLL2_R_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)"
+#endif
+#else
+#define STM32_PLL2_R_CK 0U
+#endif
+
+#if ((STM32_PLL3_ENABLED == TRUE) && (STM32_PLL3_R_ENABLED == TRUE)) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief PLL3 R output clock frequency.
+ */
+#define STM32_PLL3_R_CK (STM32_PLL3_VCO_CK / STM32_PLL3_DIVR_VALUE)
+
+/*
+ * PLL3 R output frequency range check.
+ */
+#if (STM32_PLL3_R_CK < STM32_PLLOUT_MIN) || (STM32_PLL3_R_CK > STM32_PLLOUT_MAX)
+#error "STM32_PLL3_R_CLKOUT outside acceptable range (STM32_PLLOUT_MIN..STM32_PLLOUT_MAX)"
+#endif
+#else
+#define STM32_PLL3_R_CK 0U
+#endif
+
+/**
+ * @brief System clock source.
+ */
+#if (STM32_SW == STM32_SW_HSI_CK) || defined(__DOXYGEN__)
+#define STM32_SYS_CK STM32_HSI_CK
+
+#elif (STM32_SW == STM32_SW_CSI_CK)
+#define STM32_SYS_CK STM32_CSI_CK
+
+#elif (STM32_SW == STM32_SW_HSE_CK)
+#define STM32_SYS_CK STM32_HSE_CK
+
+#elif (STM32_SW == STM32_SW_PLL1_P_CK)
+#define STM32_SYS_CK STM32_PLL1_P_CK
+
+#else
+#error "invalid STM32_SW value specified"
+#endif
+
+/*
+ * Check on the system clock.
+ */
+#if STM32_SYS_CK > STM32_SYSCLK_MAX
+#error "STM32_SYS_CK above maximum rated frequency (STM32_SYSCLK_MAX)"
+#endif
+
+/*
+ * ODEN setting based on clock frequency.
+ */
+#if STM32_SYS_CK > STM32_SYSCLK_MAX_NOBOOST
+#define STM32_ODEN STM32_ODEN_ENABLED
+#else
+#define STM32_ODEN STM32_ODEN_DISABLED
+#endif
+
+/**
+ * @brief Peripherals clock source.
+ */
+#if (STM32_CKPERSEL == STM32_CKPERSEL_HSI_CK) || defined(__DOXYGEN__)
+#define STM32_PER_CK STM32_HSI_CK
+
+#elif (STM32_CKPERSEL == STM32_CKPERSEL_CSI_CK)
+#define STM32_PER_CK STM32_CSI_CK
+
+#elif (STM32_CKPERSEL == STM32_CKPERSEL_HSE_CK)
+#define STM32_PER_CK STM32_HSE_CK
+
+#else
+#error "invalid STM32_CKPERSEL value specified"
+#endif
+
+/*
+ * Check on the peripherals clock.
+ */
+#if STM32_PER_CK > STM32_HCLK_MAX
+#error "STM32_PER_CK above maximum rated frequency (STM32_HCLK_MAX)"
+#endif
+
+/**
+ * @brief MCO1 divider clock.
+ */
+#if (STM32_MCO1SEL == STM32_MCO1SEL_HSI_CK) || defined(__DOXYGEN__)
+#define STM32_MCO1DIVCLK STM32_HSI_CK
+
+#elif STM32_MCO1SEL == STM32_MCO1SEL_LSE_CK
+#define STM32_MCO1DIVCLK STM32_LSE_CK
+
+#elif STM32_MCO1SEL == STM32_MCO1SEL_HSE_CK
+#define STM32_MCO1DIVCLK STM32_HSE_CK
+
+#elif STM32_MCO1SEL == STM32_MCO1SEL_PLL1_Q_CK
+#define STM32_MCO1DIVCLK STM32_PLL1_P_CK
+
+#elif STM32_MCO1SEL == STM32_MCO1SEL_HSI48_CK
+#define STM32_MCO1DIVCLK STM32_HSI48_CK
+
+#else
+#error "invalid STM32_MCO1SEL value specified"
+#endif
+
+/**
+ * @brief MCO1 output pin clock.
+ */
+#if (STM32_MCO1PRE_VALUE < 1) || (STM32_MCO1PRE_VALUE > 15)
+#error "STM32_MCO1PRE_VALUE outside acceptable range (1..15)"
+#endif
+
+/**
+ * @brief MCO2 divider clock.
+ */
+#if (STM32_MCO2SEL == STM32_MCO2SEL_SYS_CK) || defined(__DOXYGEN__)
+#define STM32_MCO2DIVCLK STM32_SYS_CK
+
+#elif STM32_MCO2SEL == STM32_MCO2SEL_PLL1_P_CK
+#define STM32_MCO2DIVCLK STM32_PLL2_P_CK
+
+#elif STM32_MCO2SEL == STM32_MCO2SEL_HSE_CK
+#define STM32_MCO2DIVCLK STM32_HSE_CK
+
+#elif STM32_MCO2SEL == STM32_MCO2SEL_PLL2_P_CK
+#define STM32_MCO2DIVCLK STM32_PLL2_P_CK
+
+#elif STM32_MCO2SEL == STM32_MCO2SEL_CSI_CK
+#define STM32_MCO2DIVCLK STM32_CSI_CK
+
+#elif STM32_MCO2SEL == STM32_MCO2SEL_LSI_CK
+#define STM32_MCO2DIVCLK STM32_LSI_CK
+
+#else
+#error "invalid STM32_MCO2SEL value specified"
+#endif
+
+/**
+ * @brief MCO2 output pin clock.
+ */
+#if (STM32_MCO2PRE_VALUE < 1) || (STM32_MCO2PRE_VALUE > 15)
+#error "STM32_MCO2PRE_VALUE outside acceptable range (1..15)"
+#endif
+
+/**
+ * @brief RTC clock.
+ */
+#if (STM32_RTCSEL == STM32_RTCSEL_NOCLK) || defined(__DOXYGEN__)
+#define STM32_RTC_CK 0
+
+#elif STM32_RTCSEL == STM32_RTCSEL_LSE_CK
+#define STM32_RTC_CK STM32_LSE_CK
+
+#elif STM32_RTCSEL == STM32_RTCSEL_LSI_CK
+#define STM32_RTC_CK STM32_LSI_CK
+
+#elif STM32_RTCSEL == STM32_RTCSEL_HSE_1M_CK
+#define STM32_RTC_CK STM32_HSE_1M_CK
+
+#else
+#error "invalid STM32_RTCSEL value specified"
+#endif
+
+/*
+ * Check on the RTC clock.
+ */
+#if STM32_RTC_CK > 1000000
+#error "STM32_RTC_CK above maximum rated frequency (1000000)"
+#endif
+
+/**
+ * @brief D1CPRE clock.
+ */
+#if (STM32_D1CPRE == STM32_D1CPRE_DIV1) || defined(__DOXYGEN__)
+#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 1U)
+#elif STM32_D1CPRE == STM32_D1CPRE_DIV2
+#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 2U)
+#elif STM32_D1CPRE == STM32_D1CPRE_DIV4
+#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 4U)
+#elif STM32_D1CPRE == STM32_D1CPRE_DIV8
+#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 8U)
+#elif STM32_D1CPRE == STM32_D1CPRE_DIV16
+#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 16U)
+#elif STM32_D1CPRE == STM32_D1CPRE_DIV64
+#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 64U)
+#elif STM32_D1CPRE == STM32_D1CPRE_DIV128
+#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 128U)
+#elif STM32_D1CPRE == STM32_D1CPRE_DIV256
+#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 256U)
+#elif STM32_D1CPRE == STM32_D1CPRE_DIV512
+#define STM32_SYS_D1CPRE_CK (STM32_SYS_CK / 512U)
+#else
+#error "invalid STM32_D1CPRE value specified"
+#endif
+
+/**
+ * @brief HCLK clock.
+ */
+#if (STM32_D1HPRE == STM32_D1HPRE_DIV1) || defined(__DOXYGEN__)
+#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 1U)
+#elif STM32_D1HPRE == STM32_D1HPRE_DIV2
+#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 2U)
+#elif STM32_D1HPRE == STM32_D1HPRE_DIV4
+#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 4U)
+#elif STM32_D1HPRE == STM32_D1HPRE_DIV8
+#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 8U)
+#elif STM32_D1HPRE == STM32_D1HPRE_DIV16
+#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 16U)
+#elif STM32_D1HPRE == STM32_D1HPRE_DIV64
+#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 64U)
+#elif STM32_D1HPRE == STM32_D1HPRE_DIV128
+#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 128U)
+#elif STM32_D1HPRE == STM32_D1HPRE_DIV256
+#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 256U)
+#elif STM32_D1HPRE == STM32_D1HPRE_DIV512
+#define STM32_HCLK (STM32_SYS_D1CPRE_CK / 512U)
+#else
+#error "invalid STM32_D1HPRE value specified"
+#endif
+
+/**
+ * @brief Core clock.
+ */
+#define STM32_CORE1_CK STM32_SYS_D1CPRE_CK
+
+/**
+ * @brief Core clock.
+ */
+#define STM32_CORE2_CK STM32_HCLK
+
+#if (STM32_TARGET_CORE == 1) || defined(__DOXYGEN__)
+
+#if STM32_HAS_M7 != TRUE
+#error "Cortex-M7 not present in this device"
+#endif
+#define STM32_CORE_CK STM32_CORE1_CK
+
+#elif STM32_TARGET_CORE == 2
+
+#if STM32_HAS_M4 != TRUE
+#error "Cortex-M4 not present in this device"
+#endif
+#define STM32_CORE_CK STM32_CORE2_CK
+
+#else
+#error "invalid STM32_TARGET_CORE value specified"
+#endif
+
+/*
+ * AHB frequency check.
+ */
+#if STM32_HCLK > STM32_HCLK_MAX
+#error "STM32_HCLK exceeding maximum frequency (STM32_HCLK_MAX)"
+#endif
+
+/**
+ * @brief D1 PCLK3 clock.
+ */
+#if (STM32_D1PPRE3 == STM32_D1PPRE3_DIV1) || defined(__DOXYGEN__)
+#define STM32_PCLK3 (STM32_HCLK / 1U)
+#elif STM32_D1PPRE3 == STM32_D1PPRE3_DIV2
+#define STM32_PCLK3 (STM32_HCLK / 2U)
+#elif STM32_D1PPRE3 == STM32_D1PPRE3_DIV4
+#define STM32_PCLK3 (STM32_HCLK / 4U)
+#elif STM32_D1PPRE3 == STM32_D1PPRE3_DIV8
+#define STM32_PCLK3 (STM32_HCLK / 8U)
+#elif STM32_D1PPRE3 == STM32_D1PPRE3_DIV16
+#define STM32_PCLK3 (STM32_HCLK / 16U)
+#else
+#error "invalid STM32_D1PPRE3 value specified"
+#endif
+
+/*
+ * D1 PCLK3 frequency check.
+ */
+#if STM32_PCLK3 > STM32_PCLK3_MAX
+#error "STM32_PCLK3 exceeding maximum frequency (STM32_PCLK3_MAX)"
+#endif
+
+/**
+ * @brief D2 PCLK1 clock.
+ */
+#if (STM32_D2PPRE1 == STM32_D2PPRE1_DIV1) || defined(__DOXYGEN__)
+#define STM32_PCLK1 (STM32_HCLK / 1U)
+#elif STM32_D2PPRE1 == STM32_D2PPRE1_DIV2
+#define STM32_PCLK1 (STM32_HCLK / 2U)
+#elif STM32_D2PPRE1 == STM32_D2PPRE1_DIV4
+#define STM32_PCLK1 (STM32_HCLK / 4U)
+#elif STM32_D2PPRE1 == STM32_D2PPRE1_DIV8
+#define STM32_PCLK1 (STM32_HCLK / 8U)
+#elif STM32_D2PPRE1 == STM32_D2PPRE1_DIV16
+#define STM32_PCLK1 (STM32_HCLK / 16U)
+#else
+#error "invalid STM32_D2PPRE1 value specified"
+#endif
+
+/*
+ * D2 PCLK1 frequency check.
+ */
+#if STM32_PCLK1 > STM32_PCLK1_MAX
+#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)"
+#endif
+
+/**
+ * @brief D2 PCLK2 clock.
+ */
+#if (STM32_D2PPRE2 == STM32_D2PPRE2_DIV1) || defined(__DOXYGEN__)
+#define STM32_PCLK2 (STM32_HCLK / 1U)
+#elif STM32_D2PPRE2 == STM32_D2PPRE2_DIV2
+#define STM32_PCLK2 (STM32_HCLK / 2U)
+#elif STM32_D2PPRE2 == STM32_D2PPRE2_DIV4
+#define STM32_PCLK2 (STM32_HCLK / 4U)
+#elif STM32_D2PPRE2 == STM32_D2PPRE2_DIV8
+#define STM32_PCLK2 (STM32_HCLK / 8U)
+#elif STM32_D2PPRE2 == STM32_D2PPRE2_DIV16
+#define STM32_PCLK2 (STM32_HCLK / 16U)
+#else
+#error "invalid STM32_D2PPRE2 value specified"
+#endif
+
+/*
+ * D2 PCLK2 frequency check.
+ */
+#if STM32_PCLK2 > STM32_PCLK2_MAX
+#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)"
+#endif
+
+/**
+ * @brief D3 PCLK4 clock.
+ */
+#if (STM32_D3PPRE4 == STM32_D3PPRE4_DIV1) || defined(__DOXYGEN__)
+#define STM32_PCLK4 (STM32_HCLK / 1U)
+#elif STM32_D3PPRE4 == STM32_D3PPRE4_DIV2
+#define STM32_PCLK4 (STM32_HCLK / 2U)
+#elif STM32_D3PPRE4 == STM32_D3PPRE4_DIV4
+#define STM32_PCLK4 (STM32_HCLK / 4U)
+#elif STM32_D3PPRE4 == STM32_D3PPRE4_DIV8
+#define STM32_PCLK4 (STM32_HCLK / 8U)
+#elif STM32_D3PPRE4 == STM32_D3PPRE4_DIV16
+#define STM32_PCLK4 (STM32_HCLK / 16U)
+#else
+#error "invalid STM32_D3PPRE4 value specified"
+#endif
+
+/*
+ * D3 PCLK4 frequency check.
+ */
+#if STM32_PCLK4 > STM32_PCLK4_MAX
+#error "STM32_PCLK4 exceeding maximum frequency (STM32_PCLK4_MAX)"
+#endif
+
+/**
+ * @brief Flash settings.
+ */
+#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__)
+#define STM32_FLASHBITS 0x00000000
+
+#elif STM32_HCLK <= STM32_1WS_THRESHOLD
+#define STM32_FLASHBITS 0x00000001
+
+#elif STM32_HCLK <= STM32_2WS_THRESHOLD
+#define STM32_FLASHBITS 0x00000002
+
+#elif STM32_HCLK <= STM32_3WS_THRESHOLD
+#define STM32_FLASHBITS 0x00000003
+
+#elif STM32_HCLK <= STM32_4WS_THRESHOLD
+#define STM32_FLASHBITS 0x00000004
+
+#else
+#define STM32_FLASHBITS 0x00000007
+#endif
+
+#if (STM32_D2PPRE1 == STM32_D2PPRE1_DIV1) || defined(__DOXYGEN__)
+/**
+ * @brief Clock of timers connected to APB1
+ */
+#define STM32_TIMCLK1 (STM32_PCLK1 * 1)
+#else
+#if (STM32_TIMPRE_ENABLE == FALSE) || (STM32_D2PPRE1 == STM32_D2PPRE1_DIV2)
+#define STM32_TIMCLK1 (STM32_PCLK1 * 2)
+#else
+#define STM32_TIMCLK1 (STM32_PCLK1 * 4)
+#endif
+#endif
+
+#if (STM32_D2PPRE2 == STM32_D2PPRE2_DIV1) || defined(__DOXYGEN__)
+/**
+ * @brief Clock of timers connected to APB2.
+ */
+#define STM32_TIMCLK2 (STM32_PCLK2 * 1)
+#else
+#if (STM32_TIMPRE_ENABLE == FALSE) || (STM32_D2PPRE2 == STM32_D2PPRE2_DIV2)
+#define STM32_TIMCLK2 (STM32_PCLK2 * 2)
+#else
+#define STM32_TIMCLK2 (STM32_PCLK2 * 4)
+#endif
+#endif
+
+#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_PCLK1) || defined(__DOXYGEN__)
+/**
+ * @brief LPTIM1 clock.
+ */
+#define STM32_LPTIM1CLK STM32_PCLK1
+
+#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_PLL2_P_CK
+#define STM32_LPTIM1CLK STM32_PLL2_P_CK
+#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_PLL3_R_CK
+#define STM32_LPTIM1CLK STM32_PLL3_R_CK
+#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE_CK
+#define STM32_LPTIM1CLK STM32_LSE_CK
+#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI_CK
+#define STM32_LPTIM1CLK STM32_LSI_CK
+#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_PER_CK
+#define STM32_LPTIM1CLK STM32_PER_CK
+#else
+#error "invalid source selected for STM32_LPTIM1SEL clock"
+#endif
+
+#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_PCLK4) || defined(__DOXYGEN__)
+/**
+ * @brief LPTIM2 clock.
+ */
+#define STM32_LPTIM2CLK STM32_PCLK4
+
+#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_PLL2_P_CK
+#define STM32_LPTIM2CLK STM32_PLL2_P_CK
+#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_PLL3_P_CK
+#define STM32_LPTIM2CLK STM32_PLL3_P_CK
+#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSE_CK
+#define STM32_LPTIM2CLK STM32_LSE_CK
+#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSI_CK
+#define STM32_LPTIM2CLK STM32_LSI_CK
+#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_PER_CK
+#define STM32_LPTIM2CLK STM32_PER_CK
+#else
+#error "invalid source selected for STM32_LPTIM2SEL clock"
+#endif
+
+#if (STM32_LPTIM345SEL == STM32_LPTIM345SEL_PCLK4) || defined(__DOXYGEN__)
+/**
+ * @brief LPTIM3 clock.
+ */
+#define STM32_LPTIM3CLK STM32_PCLK4
+
+/**
+ * @brief LPTIM4 clock.
+ */
+#define STM32_LPTIM4CLK STM32_PCLK4
+
+/**
+ * @brief LPTIM5 clock.
+ */
+#define STM32_LPTIM5CLK STM32_PCLK4
+
+#elif STM32_LPTIM345SEL == STM32_LPTIM345SEL_PLL2_P_CK
+#define STM32_LPTIM3CLK STM32_PLL2_P_CK
+#define STM32_LPTIM4CLK STM32_PLL2_P_CK
+#define STM32_LPTIM5CLK STM32_PLL2_P_CK
+#elif STM32_LPTIM345SEL == STM32_LPTIM345SEL_PLL3_P_CK
+#define STM32_LPTIM3CLK STM32_PLL3_P_CK
+#define STM32_LPTIM4CLK STM32_PLL3_P_CK
+#define STM32_LPTIM5CLK STM32_PLL3_P_CK
+#elif STM32_LPTIM345SEL == STM32_LPTIM345SEL_LSE_CK
+#define STM32_LPTIM3CLK STM32_LSE_CK
+#define STM32_LPTIM4CLK STM32_LSE_CK
+#define STM32_LPTIM5CLK STM32_LSE_CK
+#elif STM32_LPTIM345SEL == STM32_LPTIM345SEL_LSI_CK
+#define STM32_LPTIM3CLK STM32_LSI_CK
+#define STM32_LPTIM4CLK STM32_LSI_CK
+#define STM32_LPTIM5CLK STM32_LSI_CK
+#elif STM32_LPTIM345SEL == STM32_LPTIM345SEL_PER_CK
+#define STM32_LPTIM3CLK STM32_PER_CK
+#define STM32_LPTIM4CLK STM32_PER_CK
+#define STM32_LPTIM5CLK STM32_PER_CK
+#else
+#error "invalid source selected for STM32_LPTIM345SEL clock"
+#endif
+
+#if !defined(STM32H723xx)
+#if (STM32_USART16SEL == STM32_USART16SEL_PCLK2) || defined(__DOXYGEN__)
+/**
+ * @brief USART1 clock.
+ */
+#define STM32_USART1CLK STM32_PCLK2
+
+/**
+ * @brief USART6 clock.
+ */
+#define STM32_USART6CLK STM32_PCLK2
+
+#elif STM32_USART16SEL == STM32_USART16SEL_PLL2_Q_CK
+#define STM32_USART1CLK STM32_PLL2_Q_CK
+#define STM32_USART6CLK STM32_PLL2_Q_CK
+#elif STM32_USART16SEL == STM32_USART16SEL_PLL3_Q_CK
+#define STM32_USART1CLK STM32_PLL3_Q_CK
+#define STM32_USART6CLK STM32_PLL3_Q_CK
+#elif STM32_USART16SEL == STM32_USART16SEL_HSI_KER_CK
+#define STM32_USART1CLK STM32_HSI_CK
+#define STM32_USART6CLK STM32_HSI_CK
+#elif STM32_USART16SEL == STM32_USART16SEL_CSI_KER_CK
+#define STM32_USART1CLK STM32_CSI_CK
+#define STM32_USART6CLK STM32_CSI_CK
+#elif STM32_USART16SEL == STM32_USART16SEL_LSE_CK
+#define STM32_USART1CLK STM32_LSE_CK
+#define STM32_USART6CLK STM32_LSE_CK
+#else
+#error "invalid source selected for STM32_USART16SEL clock"
+#endif
+#else // then defined(STM32H723xx)
+#if (STM32_USART16910SEL == STM32_USART16910SEL_PCLK2) || defined(__DOXYGEN__)
+
+#define STM32_USART1CLK STM32_PCLK2
+#define STM32_USART6CLK STM32_PCLK2
+#define STM32_USART9CLK STM32_PCLK2
+#define STM32_USART10CLK STM32_PCLK2
+
+#elif STM32_USART16910SEL == STM32_USART16910SEL_PLL2_Q_CK
+#define STM32_USART1CLK STM32_PLL2_Q_CK
+#define STM32_USART6CLK STM32_PLL2_Q_CK
+#define STM32_USART9CLK STM32_PLL2_Q_CK
+#define STM32_USART10CLK STM32_PLL2_Q_CK
+#elif STM32_USART16910SEL == STM32_USART16910SEL_PLL3_Q_CK
+#define STM32_USART1CLK STM32_PLL3_Q_CK
+#define STM32_USART6CLK STM32_PLL3_Q_CK
+#define STM32_USART9CLK STM32_PLL3_Q_CK
+#define STM32_USART10CLK STM32_PLL3_Q_CK
+#elif STM32_USART16910SEL == STM32_USART16910SEL_HSI_KER_CK
+#define STM32_USART1CLK STM32_HSI_CK
+#define STM32_USART6CLK STM32_HSI_CK
+#define STM32_USART9CLK STM32_HSI_CK
+#define STM32_USART10CLK STM32_HSI_CK
+#elif STM32_USART16910SEL == STM32_USART16910SEL_CSI_KER_CK
+#define STM32_USART1CLK STM32_CSI_CK
+#define STM32_USART6CLK STM32_CSI_CK
+#define STM32_USART9CLK STM32_CSI_CK
+#define STM32_USART10CLK STM32_CSI_CK
+#elif STM32_USART16910SEL == STM32_USART16910SEL_LSE_CK
+#define STM32_USART1CLK STM32_LSE_CK
+#define STM32_USART6CLK STM32_LSE_CK
+#define STM32_USART9CLK STM32_LSE_CK
+#define STM32_USART10CLK STM32_LSE_CK
+#else
+#error "invalid source selected for STM32_USART16910SEL clock"
+#endif
+#endif // !defined(STM32H723xx)
+
+#if (STM32_USART234578SEL == STM32_USART234578SEL_PCLK1) || defined(__DOXYGEN__)
+/**
+ * @brief USART2 clock.
+ */
+#define STM32_USART2CLK STM32_PCLK1
+
+/**
+ * @brief USART3 clock.
+ */
+#define STM32_USART3CLK STM32_PCLK1
+
+/**
+ * @brief USART4 clock.
+ */
+#define STM32_UART4CLK STM32_PCLK1
+
+/**
+ * @brief USART5 clock.
+ */
+#define STM32_UART5CLK STM32_PCLK1
+
+/**
+ * @brief USART7 clock.
+ */
+#define STM32_UART7CLK STM32_PCLK1
+
+/**
+ * @brief USART8 clock.
+ */
+#define STM32_UART8CLK STM32_PCLK1
+
+#elif STM32_USART234578SEL == STM32_USART234578SEL_PLL2_Q_CK
+#define STM32_USART2CLK STM32_PLL2_Q_CK
+#define STM32_USART3CLK STM32_PLL2_Q_CK
+#define STM32_UART4CLK STM32_PLL2_Q_CK
+#define STM32_UART5CLK STM32_PLL2_Q_CK
+#define STM32_UART7CLK STM32_PLL2_Q_CK
+#define STM32_UART8CLK STM32_PLL2_Q_CK
+#elif STM32_USART234578SEL == STM32_USART234578SEL_PLL3_Q_CK
+#define STM32_USART2CLK STM32_PLL3_Q_CK
+#define STM32_USART3CLK STM32_PLL3_Q_CK
+#define STM32_UART4CLK STM32_PLL3_Q_CK
+#define STM32_UART5CLK STM32_PLL3_Q_CK
+#define STM32_UART7CLK STM32_PLL3_Q_CK
+#define STM32_UART8CLK STM32_PLL3_Q_CK
+#elif STM32_USART234578SEL == STM32_USART234578SEL_HSI_KER_CK
+#define STM32_USART2CLK STM32_HSI_CK
+#define STM32_USART3CLK STM32_HSI_CK
+#define STM32_UART4CLK STM32_HSI_CK
+#define STM32_UART5CLK STM32_HSI_CK
+#define STM32_UART7CLK STM32_HSI_CK
+#define STM32_UART8CLK STM32_HSI_CK
+#elif STM32_USART234578SEL == STM32_USART234578SEL_CSI_KER_CK
+#define STM32_USART2CLK STM32_CSI_CK
+#define STM32_USART3CLK STM32_CSI_CK
+#define STM32_UART4CLK STM32_CSI_CK
+#define STM32_UART5CLK STM32_CSI_CK
+#define STM32_UART7CLK STM32_CSI_CK
+#define STM32_UART8CLK STM32_CSI_CK
+#elif STM32_USART234578SEL == STM32_USART234578SEL_LSE_CK
+#define STM32_USART2CLK STM32_LSE_CK
+#define STM32_USART3CLK STM32_LSE_CK
+#define STM32_UART4CLK STM32_LSE_CK
+#define STM32_UART6CLK STM32_LSE_CK
+#define STM32_UART7CLK STM32_LSE_CK
+#define STM32_UART8CLK STM32_LSE_CK
+#else
+#error "invalid source selected for STM32_USART234578SEL clock"
+#endif
+
+#if (STM32_LPUART1SEL == STM32_LPUART1SEL_PCLK4) || defined(__DOXYGEN__)
+/**
+ * @brief LPUART1 clock.
+ */
+#define STM32_LPUART1CLK STM32_PCLK4
+
+#elif STM32_LPUART1SEL == STM32_LPUART1SEL_PLL2_Q_CK
+#define STM32_LPUART1CLK STM32_PLL2_Q_CK
+#elif STM32_LPUART1SEL == STM32_LPUART1SEL_PLL3_Q_CK
+#define STM32_LPUART1CLK STM32_PLL3_Q_CK
+#elif STM32_LPUART1SEL == STM32_LPUART1SEL_HSI_KER_CK
+#define STM32_LPUART1CLK STM32_HSI_CK
+#elif STM32_LPUART1SEL == STM32_LPUART1SEL_CSI_KER_CK
+#define STM32_LPUART1CLK STM32_CSI_CK
+#elif STM32_LPUART1SEL == STM32_LPUART1SEL_LSE_CK
+#define STM32_LPUART1CLK STM32_LSE_CK
+#else
+#error "invalid source selected for STM32_LPUART1SEL clock"
+#endif
+
+#if (STM32_SPI123SEL == STM32_SPI123SEL_PLL1_Q_CK) || defined(__DOXYGEN__)
+/**
+ * @brief SPI1 clock.
+ */
+#define STM32_SPI1CLK STM32_PLL1_Q_CK
+
+/**
+ * @brief SPI2 clock.
+ */
+#define STM32_SPI2CLK STM32_PLL1_Q_CK
+
+/**
+ * @brief SPI3 clock.
+ */
+#define STM32_SPI3CLK STM32_PLL1_Q_CK
+#elif STM32_SPI123SEL == STM32_SPI123SEL_PLL2_P_CK
+#define STM32_SPI1CLK STM32_PLL2_P_CK
+#define STM32_SPI2CLK STM32_PLL2_P_CK
+#define STM32_SPI3CLK STM32_PLL2_P_CK
+#elif STM32_SPI123SEL == STM32_SPI123SEL_PLL3_P_CK
+#define STM32_SPI1CLK STM32_PLL3_P_CK
+#define STM32_SPI2CLK STM32_PLL3_P_CK
+#define STM32_SPI3CLK STM32_PLL3_P_CK
+#elif STM32_SPI123SEL == STM32_SPI123SEL_I2S_CKIN
+#define STM32_SPI1CLK 0 /* Unknown, would require a board value */
+#define STM32_SPI2CLK 0 /* Unknown, would require a board value */
+#define STM32_SPI3CLK 0 /* Unknown, would require a board value */
+#elif STM32_SPI123SEL == STM32_SPI123SEL_PER_CK
+#define STM32_SPI1CLK STM32_PER_CK
+#define STM32_SPI2CLK STM32_PER_CK
+#define STM32_SPI3CLK STM32_PER_CK
+#else
+#error "invalid source selected for STM32_SPI123SEL clock"
+#endif
+
+#if (STM32_SPI45SEL == STM32_SPI45SEL_PCLK2) || defined(__DOXYGEN__)
+/**
+ * @brief SPI4 clock.
+ */
+#define STM32_SPI4CLK STM32_PCLK2
+
+/**
+ * @brief SPI5 clock.
+ */
+#define STM32_SPI5CLK STM32_PCLK2
+
+#elif STM32_SPI45SEL == STM32_SPI45SEL_PLL2_Q_CK
+#define STM32_SPI4CLK STM32_PLL2_Q_CK
+#define STM32_SPI5CLK STM32_PLL2_Q_CK
+#elif STM32_SPI45SEL == STM32_SPI45SEL_PLL3_Q_CK
+#define STM32_SPI4CLK STM32_PLL3_Q_CK
+#define STM32_SPI5CLK STM32_PLL3_Q_CK
+#elif STM32_SPI45SEL == STM32_SPI45SEL_HSI_KER_CK
+#define STM32_SPI4CLK STM32_HSI_CK
+#define STM32_SPI5CLK STM32_HSI_CK
+#elif STM32_SPI45SEL == STM32_SPI45SEL_CSI_KER_CK
+#define STM32_SPI4CLK STM32_CSI_CK
+#define STM32_SPI5CLK STM32_CSI_CK
+#elif STM32_SPI45SEL == STM32_SPI45SEL_HSE_CK
+#define STM32_SPI4CLK STM32_HSE_CK
+#define STM32_SPI5CLK STM32_HSE_CK
+#else
+#error "invalid source selected for STM32_SPI45SEL clock"
+#endif
+
+#if (STM32_SPI6SEL == STM32_SPI6SEL_PCLK4) || defined(__DOXYGEN__)
+/**
+ * @brief SPI6 clock.
+ */
+#define STM32_SPI6CLK STM32_PCLK4
+
+#elif STM32_SPI6SEL == STM32_SPI6SEL_PLL2_Q_CK
+#define STM32_SPI6CLK STM32_PLL2_Q_CK
+#elif STM32_SPI6SEL == STM32_SPI6SEL_PLL3_Q_CK
+#define STM32_SPI6CLK STM32_PLL3_Q_CK
+#elif STM32_SPI6SEL == STM32_SPI6SEL_HSI_KER_CK
+#define STM32_SPI6CLK STM32_HSI_CK
+#elif STM32_SPI6SEL == STM32_SPI6SEL_CSI_KER_CK
+#define STM32_SPI6CLK STM32_CSI_CK
+#elif STM32_SPI6SEL == STM32_SPI6SEL_HSE_CK
+#define STM32_SPI6CLK STM32_HSE_CK
+#else
+#error "invalid source selected for STM32_SPI6SEL clock"
+#endif
+
+#if !defined(STM32H723xx)
+#if (STM32_I2C123SEL == STM32_I2C123SEL_PCLK1) || defined(__DOXYGEN__)
+/**
+ * @brief I2C1 clock.
+ */
+#define STM32_I2C1CLK STM32_PCLK1
+
+/**
+ * @brief I2C2 clock.
+ */
+#define STM32_I2C2CLK STM32_PCLK1
+
+/**
+ * @brief I2C3 clock.
+ */
+#define STM32_I2C3CLK STM32_PCLK1
+
+#elif STM32_I2C123SEL == STM32_I2C123SEL_PLL3_R_CK
+#define STM32_I2C1CLK STM32_PLL3_R_CK
+#define STM32_I2C2CLK STM32_PLL3_R_CK
+#define STM32_I2C2CLK STM32_PLL3_R_CK
+
+#elif STM32_I2C123SEL == STM32_I2C123SEL_HSI_KER_CK
+#define STM32_I2C1CLK STM32_HSI_CK
+#define STM32_I2C2CLK STM32_HSI_CK
+#define STM32_I2C2CLK STM32_HSI_CK
+
+#elif STM32_I2C123SEL == STM32_I2C123SEL_CSI_KER_CK
+#define STM32_I2C1CLK STM32_CSI_CK
+#define STM32_I2C2CLK STM32_CSI_CK
+#define STM32_I2C2CLK STM32_CSI_CK
+#else
+#error "invalid source selected for STM32_I2C123SEL clock"
+#endif
+#else // then defined(STM32H723xx)
+#if (STM32_I2C1235SEL == STM32_I2C1235SEL_PCLK1) || defined(__DOXYGEN__)
+
+#define STM32_I2C1CLK STM32_PCLK1
+#define STM32_I2C2CLK STM32_PCLK1
+#define STM32_I2C3CLK STM32_PCLK1
+#define STM32_I2C5CLK STM32_PCLK1
+
+#elif STM32_I2C1235SEL == STM32_I2C1235SEL_PLL3_R_CK
+#define STM32_I2C1CLK STM32_PLL3_R_CK
+#define STM32_I2C2CLK STM32_PLL3_R_CK
+#define STM32_I2C3CLK STM32_PLL3_R_CK
+#define STM32_I2C5CLK STM32_PLL3_R_CK
+
+#elif STM32_I2C1235SEL == STM32_I2C1235SEL_HSI_KER_CK
+#define STM32_I2C1CLK STM32_HSI_CK
+#define STM32_I2C2CLK STM32_HSI_CK
+#define STM32_I2C3CLK STM32_HSI_CK
+#define STM32_I2C5CLK STM32_HSI_CK
+
+#elif STM32_I2C1235SEL == STM32_I2C1235SEL_CSI_KER_CK
+#define STM32_I2C1CLK STM32_CSI_CK
+#define STM32_I2C2CLK STM32_CSI_CK
+#define STM32_I2C3CLK STM32_CSI_CK
+#define STM32_I2C5CLK STM32_CSI_CK
+#else
+#error "invalid source selected for STM32_I2C1235SEL clock"
+#endif
+#endif // !defined(STM32H723xx)
+
+#if (STM32_I2C4SEL == STM32_I2C4SEL_PCLK4) || defined(__DOXYGEN__)
+/**
+ * @brief I2C1 clock.
+ */
+#define STM32_I2C4CLK STM32_PCLK4
+
+#elif STM32_I2C4SEL == STM32_I2C4SEL_PLL3_R_CK
+#define STM32_I2C4CLK STM32_PLL3_R_CK
+#elif STM32_I2C4SEL == STM32_I2C4SEL_HSI_KER_CK
+#define STM32_I2C4CLK STM32_HSI_CK
+#elif STM32_I2C4SEL == STM32_I2C4SEL_CSI_KER_CK
+#define STM32_I2C4CLK STM32_CSI_CK
+#else
+#error "invalid source selected for STM32_I2C4SEL clock"
+#endif
+
+#if (STM32_SAI1SEL == STM32_SAI1SEL_PLL1_Q_CK) || defined(__DOXYGEN__)
+/**
+ * @brief SAI1 clock.
+ */
+#define STM32_SAI1CLK STM32_PLL1_Q_CK
+
+#elif STM32_SAI1SEL == STM32_SAI1SEL_PLL2_P_CK
+#define STM32_SAI1CLK STM32_PLL2_P_CK
+#elif STM32_SAI1SEL == STM32_SAI1SEL_PLL3_P_CK
+#define STM32_SAI1CLK STM32_PLL3_P_CK
+#elif STM32_SAI1SEL == STM32_SAI1SEL_I2S_CKIN
+#define STM32_SAI1CLK 0 /* Unknown, would require a board value */
+#elif STM32_SAI1SEL == STM32_SAI1SEL_PER_CK
+#define STM32_SAI1CLK STM32_PER_CK
+#else
+#error "invalid source selected for STM32_SAI1SEL clock"
+#endif
+
+#if !defined(STM32H723xx)
+#if (STM32_SAI23SEL == STM32_SAI23SEL_PLL1_Q_CK) || defined(__DOXYGEN__)
+/**
+ * @brief SAI2 clock.
+ */
+#define STM32_SAI2CLK STM32_PLL1_Q_CK
+
+/**
+ * @brief SAI3 clock.
+ */
+#define STM32_SAI3CLK STM32_PLL1_Q_CK
+
+#elif STM32_SAI23SEL == STM32_SAI23SEL_PLL2_P_CK
+#define STM32_SAI2CLK STM32_PLL2_P_CK
+#define STM32_SAI3CLK STM32_PLL2_P_CK
+#elif STM32_SAI23SEL == STM32_SAI23SEL_PLL3_P_CK
+#define STM32_SAI2CLK STM32_PLL3_P_CK
+#define STM32_SAI3CLK STM32_PLL3_P_CK
+#elif STM32_SAI23SEL == STM32_SAI23SEL_I2S_CKIN
+#define STM32_SAI2CLK 0 /* Unknown, would require a board value */
+#define STM32_SAI3CLK 0 /* Unknown, would require a board value */
+#elif STM32_SAI23SEL == STM32_SAI23SEL_PER_CK
+#define STM32_SAI2CLK STM32_PER_CK
+#define STM32_SAI3CLK STM32_PER_CK
+#else
+#error "invalid source selected for STM32_SAI23SEL clock"
+#endif
+#endif // !defined(STM32H723xx)
+
+#if (STM32_SAI4ASEL == STM32_SAI4ASEL_PLL1_Q_CK) || defined(__DOXYGEN__)
+/**
+ * @brief SAI4A clock.
+ */
+#define STM32_SAI4ACLK STM32_PLL1_Q_CK
+
+#elif STM32_SAI4ASEL == STM32_SAI4ASEL_PLL2_P_CK
+#define STM32_SAI4ACLK STM32_PLL2_P_CK
+#elif STM32_SAI4ASEL == STM32_SAI4ASEL_PLL3_P_CK
+#define STM32_SAI4ACLK STM32_PLL3_P_CK
+#elif STM32_SAI4ASEL == STM32_SAI4ASEL_I2S_CKIN
+#define STM32_SAI4ACLK 0 /* Unknown, would require a board value */
+#elif STM32_SAI4ASEL == STM32_SAI4ASEL_PER_CK
+#define STM32_SAI4ACLK STM32_PER_CK
+#else
+#error "invalid source selected for STM32_SAI4ASEL clock"
+#endif
+
+#if (STM32_SAI4BSEL == STM32_SAI4BSEL_PLL1_Q_CK) || defined(__DOXYGEN__)
+/**
+ * @brief SAI4B clock.
+ */
+#define STM32_SAI4BCLK STM32_PLL1_Q_CK
+
+#elif STM32_SAI4BSEL == STM32_SAI4BSEL_PLL2_P_CK
+#define STM32_SAI4BCLK STM32_PLL2_P_CK
+#elif STM32_SAI4BSEL == STM32_SAI4BSEL_PLL3_P_CK
+#define STM32_SAI4BCLK STM32_PLL3_P_CK
+#elif STM32_SAI4BSEL == STM32_SAI4BSEL_I2S_CKIN
+#define STM32_SAI4BCLK 0 /* Unknown, would require a board value */
+#elif STM32_SAI4BSEL == STM32_SAI4BSEL_PER_CK
+#define STM32_SAI4BCLK STM32_PER_CK
+#else
+#error "invalid source selected for STM32_SAI4BSEL clock"
+#endif
+
+#if (STM32_USBSEL == STM32_USBSEL_DISABLE) || defined(__DOXYGEN__)
+/**
+ * @brief USB clock.
+ */
+#define STM32_USBCLK 0
+
+#elif STM32_USBSEL == STM32_USBSEL_PLL1_Q_CK
+#define STM32_USBCLK STM32_PLL1_Q_CK
+#elif STM32_USBSEL == STM32_USBSEL_PLL3_Q_CK
+#define STM32_USBCLK STM32_PLL3_Q_CK
+#elif STM32_USBSEL == STM32_USBSEL_HSI48_CK
+#define STM32_USBCLK STM32_HSI48_CK
+#else
+#error "invalid source selected for STM32_USBSEL clock"
+#endif
+
+#if (STM32_SDMMCSEL == STM32_SDMMCSEL_PLL1_Q_CK) || defined(__DOXYGEN__)
+/**
+ * @brief SDMMC1 frequency.
+ */
+#define STM32_SDMMC1CLK STM32_PLL1_Q_CK
+
+/**
+ * @brief SDMMC2 frequency.
+ */
+#define STM32_SDMMC2CLK STM32_PLL1_Q_CK
+
+#elif STM32_SDMMCSEL == STM32_SDMMCSEL_PLL2_R_CK
+#define STM32_SDMMC1CLK STM32_PLL2_R_CK
+#define STM32_SDMMC2CLK STM32_PLL2_R_CK
+#else
+#error "invalid source selected for STM32_SDMMCxSEL clock"
+#endif
+
+#if !defined(STM32H723xx)
+#if (STM32_QSPISEL == STM32_QSPISEL_HCLK) || defined(__DOXYGEN__)
+/**
+ * @brief QSPI frequency.
+ */
+#define STM32_QSPICLK STM32_HCLK
+
+#elif STM32_QSPISEL == STM32_QSPISEL_PLL1_Q_CK
+#define STM32_QSPICLK STM32_PLL1_Q_CK
+#elif STM32_QSPISEL == STM32_QSPISEL_PLL2_R_CK
+#define STM32_QSPICLK STM32_PLL2_R_CK
+#elif STM32_QSPISEL == STM32_QSPISEL_PER_CK
+#define STM32_QSPICLK STM32_PER_CK
+#else
+#error "invalid source selected for STM32_QSPISEL clock"
+#endif
+
+#if (STM32_FMCSEL == STM32_FMCSEL_HCLK) || defined(__DOXYGEN__)
+/**
+ * @brief FMC frequency.
+ */
+#define STM32_FMCCLK STM32_HCLK
+
+#elif STM32_FMCSEL == STM32_FMCSEL_PLL1_Q_CK
+#define STM32_FMCCLK STM32_PLL1_Q_CK
+#elif STM32_FMCSEL == STM32_FMCSEL_PLL2_R_CK
+#define STM32_FMCCLK STM32_PLL2_R_CK
+#elif STM32_FMCSEL == STM32_FMCSEL_PER_CK
+#define STM32_FMCCLK STM32_PER_CK
+#else
+#error "invalid source selected for STM32_FMCSEL clock"
+#endif
+#endif // !defined(STM32H723xx)
+
+#if (STM32_SWPSEL == STM32_SWPSEL_PCLK1) || defined(__DOXYGEN__)
+/**
+ * @brief SDMMC frequency.
+ */
+#define STM32_SWPCLK STM32_PCLK1
+
+#elif STM32_SWPSEL == STM32_SWPSEL_HSI_KER_CK
+#define STM32_SWPCLK STM32_HSI_CK
+#else
+#error "invalid source selected for STM32_SWPSEL clock"
+#endif
+
+#if (STM32_FDCANSEL == STM32_FDCANSEL_HSE_CK) || defined(__DOXYGEN__)
+/**
+ * @brief FDCAN frequency.
+ */
+#define STM32_FDCANCLK STM32_HSE_CK
+
+#elif STM32_FDCANSEL == STM32_FDCANSEL_PLL1_Q_CK
+#define STM32_FDCANCLK STM32_PLL1_Q_CK
+#elif STM32_FDCANSEL == STM32_FDCANSEL_PLL2_Q_CK
+#define STM32_FDCANCLK STM32_PLL2_Q_CK
+#else
+#error "invalid source selected for STM32_FDCANSEL clock"
+#endif
+
+#if (STM32_DFSDM1SEL == STM32_DFSDM1SEL_PCLK2) || defined(__DOXYGEN__)
+/**
+ * @brief SDMMC frequency.
+ */
+#define STM32_DFSDM1CLK STM32_PCLK2
+
+#elif STM32_DFSDM1SEL == STM32_DFSDM1SEL_SYS_CK
+#define STM32_DFSDM1CLK STM32_SYS_CK
+#else
+#error "invalid source selected for STM32_DFSDM1SEL clock"
+#endif
+
+#if (STM32_SPDIFSEL == STM32_SPDIFSEL_PLL1_Q_CK) || defined(__DOXYGEN__)
+/**
+ * @brief SPDIF frequency.
+ */
+#define STM32_SPDIFCLK STM32_PLL1_Q_CK
+
+#elif STM32_SPDIFSEL == STM32_SPDIFSEL_PLL2_R_CK
+#define STM32_SPDIFCLK STM32_PLL2_R_CK
+#elif STM32_SPDIFSEL == STM32_SPDIFSEL_PLL3_R_CK
+#define STM32_SPDIFCLK STM32_PLL3_R_CK
+#elif STM32_SPDIFSEL == STM32_SPDIFSEL_HSI_KET_CLK
+#define STM32_SPDIFCLK STM32_HSI_CK
+#else
+#error "invalid source selected for STM32_SPDIFSEL clock"
+#endif
+
+#if (STM32_CECSEL == STM32_CECSEL_LSE_CK) || defined(__DOXYGEN__)
+/**
+ * @brief CEC frequency.
+ */
+#define STM32_CECCLK STM32_LSE_CK
+
+#elif STM32_CECSEL == STM32_CECSEL_LSI_CK
+#define STM32_CECCLK STM32_LSI_CK
+#elif STM32_CECSEL == STM32_CECSEL_CSI_KER_CK
+#define STM32_CECCLK STM32_CSI_CK
+#elif STM32_CECSEL == STM32_CECSEL_DISABLE
+#define STM32_CECCLK 0
+#else
+#error "invalid source selected for STM32_CECSEL clock"
+#endif
+
+#if (STM32_RNGSEL == STM32_RNGSEL_HSI48_CK) || defined(__DOXYGEN__)
+/**
+ * @brief RNG frequency.
+ */
+#define STM32_RNGCLK STM32_HSI48_CK
+
+#elif STM32_RNGSEL == STM32_RNGSEL_PLL1_Q_CK
+#define STM32_RNGCLK STM32_PLL1_Q_CK
+#elif STM32_RNGSEL == STM32_RNGSEL_LSE_CK
+#define STM32_RNGCLK STM32_LSE_CK
+#elif STM32_RNGSEL == STM32_RNGSEL_LSI_CK
+#define STM32_RNGCLK STM32_LSI_CK
+#else
+#error "invalid source selected for STM32_RNGSEL clock"
+#endif
+
+#if (STM32_ADCSEL == STM32_ADCSEL_PLL2_P_CK) || defined(__DOXYGEN__)
+/**
+ * @brief ADC frequency.
+ */
+#define STM32_ADCCLK STM32_PLL2_P_CK
+
+#elif STM32_ADCSEL == STM32_ADCSEL_PLL3_R_CK
+#define STM32_ADCCLK STM32_PLL3_R_CK
+#elif STM32_ADCSEL == STM32_ADCSEL_PER_CK
+#define STM32_ADCCLK STM32_PER_CK
+#elif STM32_ADCSEL == STM32_ADCSEL_DISABLE
+#define STM32_ADCCLK 0
+#else
+#error "invalid source selected for STM32_ADCSEL clock"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/* Various helpers.*/
+#include "nvic.h"
+#include "cache.h"
+#include "mpu_v7m.h"
+#include "stm32_isr.h"
+#include "stm32_mdma.h"
+#include "stm32_dma.h"
+#include "stm32_bdma.h"
+#include "stm32_exti.h"
+#include "stm32_rcc.h"
+#include "stm32_tim.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void hal_lld_init(void);
+ void stm32_clock_init(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/platform.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/platform.mk
new file mode 100644
index 0000000..05c12ef
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/platform.mk
@@ -0,0 +1,50 @@
+# Required platform files.
+PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \
+ $(CHIBIOS)/os/hal/ports/STM32/STM32H7xx/stm32_isr.c \
+ $(CHIBIOS)/os/hal/ports/STM32/STM32H7xx/hal_lld.c
+
+# Required include directories.
+PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \
+ $(CHIBIOS)/os/hal/ports/STM32/STM32H7xx
+
+# Optional platform files.
+ifeq ($(USE_SMART_BUILD),yes)
+
+# Configuration files directory
+ifeq ($(HALCONFDIR),)
+ ifeq ($(CONFDIR),)
+ HALCONFDIR = .
+ else
+ HALCONFDIR := $(CONFDIR)
+ endif
+endif
+
+HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define"))
+
+else
+endif
+
+# Drivers compatible with the platform.
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv4/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/BDMAv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/FDCANv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv3/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/MDMAv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv3/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk
+
+# Shared variables
+ALLCSRC += $(PLATFORMSRC)
+ALLINC += $(PLATFORMINC)
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/stm32_dmamux.h b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/stm32_dmamux.h
new file mode 100644
index 0000000..c4bace0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/stm32_dmamux.h
@@ -0,0 +1,206 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32H7xx/stm32_dmamux.h
+ * @brief STM32H7xx DMAMUX handler header.
+ *
+ * @addtogroup STM32H7xx_DMAMUX
+ * @{
+ */
+
+#ifndef STM32_DMAMUX_H
+#define STM32_DMAMUX_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name DMAMUX1 request sources
+ * @{
+ */
+#define STM32_DMAMUX1_REQ_GEN0 1
+#define STM32_DMAMUX1_REQ_GEN1 2
+#define STM32_DMAMUX1_REQ_GEN2 3
+#define STM32_DMAMUX1_REQ_GEN3 4
+#define STM32_DMAMUX1_REQ_GEN4 5
+#define STM32_DMAMUX1_REQ_GEN5 6
+#define STM32_DMAMUX1_REQ_GEN6 7
+#define STM32_DMAMUX1_REQ_GEN7 8
+#define STM32_DMAMUX1_ADC1 9
+#define STM32_DMAMUX1_ADC2 10
+#define STM32_DMAMUX1_TIM1_CH1 11
+#define STM32_DMAMUX1_TIM1_CH2 12
+#define STM32_DMAMUX1_TIM1_CH3 13
+#define STM32_DMAMUX1_TIM1_CH4 14
+#define STM32_DMAMUX1_TIM1_UP 15
+#define STM32_DMAMUX1_TIM1_TRIG 16
+#define STM32_DMAMUX1_TIM1_COM 17
+#define STM32_DMAMUX1_TIM2_CH1 18
+#define STM32_DMAMUX1_TIM2_CH2 19
+#define STM32_DMAMUX1_TIM2_CH3 20
+#define STM32_DMAMUX1_TIM2_CH4 21
+#define STM32_DMAMUX1_TIM2_UP 22
+#define STM32_DMAMUX1_TIM3_CH1 23
+#define STM32_DMAMUX1_TIM3_CH2 24
+#define STM32_DMAMUX1_TIM3_CH3 25
+#define STM32_DMAMUX1_TIM3_CH4 26
+#define STM32_DMAMUX1_TIM3_UP 27
+#define STM32_DMAMUX1_TIM3_TRIG 28
+#define STM32_DMAMUX1_TIM4_CH1 29
+#define STM32_DMAMUX1_TIM4_CH2 30
+#define STM32_DMAMUX1_TIM4_CH3 31
+#define STM32_DMAMUX1_TIM4_UP 32
+#define STM32_DMAMUX1_I2C1_RX 33
+#define STM32_DMAMUX1_I2C1_TX 34
+#define STM32_DMAMUX1_I2C2_RX 35
+#define STM32_DMAMUX1_I2C2_TX 36
+#define STM32_DMAMUX1_SPI1_RX 37
+#define STM32_DMAMUX1_SPI1_TX 38
+#define STM32_DMAMUX1_SPI2_RX 39
+#define STM32_DMAMUX1_SPI2_TX 40
+#define STM32_DMAMUX1_USART1_RX 41
+#define STM32_DMAMUX1_USART1_TX 42
+#define STM32_DMAMUX1_USART2_RX 43
+#define STM32_DMAMUX1_USART2_TX 44
+#define STM32_DMAMUX1_USART3_RX 45
+#define STM32_DMAMUX1_USART3_TX 46
+#define STM32_DMAMUX1_TIM8_CH1 47
+#define STM32_DMAMUX1_TIM8_CH2 48
+#define STM32_DMAMUX1_TIM8_CH3 49
+#define STM32_DMAMUX1_TIM8_CH4 50
+#define STM32_DMAMUX1_TIM8_UP 51
+#define STM32_DMAMUX1_TIM8_TRIG 52
+#define STM32_DMAMUX1_TIM8_COM 53
+#define STM32_DMAMUX1_RESERVED54 54
+#define STM32_DMAMUX1_TIM5_CH1 55
+#define STM32_DMAMUX1_TIM5_CH2 56
+#define STM32_DMAMUX1_TIM5_CH3 57
+#define STM32_DMAMUX1_TIM5_CH4 58
+#define STM32_DMAMUX1_TIM5_UP 59
+#define STM32_DMAMUX1_TIM5_TRIG 60
+#define STM32_DMAMUX1_SPI3_RX 61
+#define STM32_DMAMUX1_SPI3_TX 62
+#define STM32_DMAMUX1_UART4_RX 63
+#define STM32_DMAMUX1_UART4_TX 64
+#define STM32_DMAMUX1_UART5_RX 65
+#define STM32_DMAMUX1_UART5_TX 66
+#define STM32_DMAMUX1_DAC1_CH1 67 /* Renamed to L4 name.*/
+#define STM32_DMAMUX1_DAC1_CH2 68 /* Renamed to L4 name.*/
+#define STM32_DMAMUX1_TIM6_UP 69
+#define STM32_DMAMUX1_TIM7_UP 70
+#define STM32_DMAMUX1_USART6_RX 71
+#define STM32_DMAMUX1_USART6_TX 72
+#define STM32_DMAMUX1_I2C3_RX 73
+#define STM32_DMAMUX1_I2C3_TX 74
+#define STM32_DMAMUX1_DCMI 75
+#define STM32_DMAMUX1_CRYP_IN 76
+#define STM32_DMAMUX1_CRYP_OUT 77
+#define STM32_DMAMUX1_HASH_IN 78
+#define STM32_DMAMUX1_UART7_RX 79
+#define STM32_DMAMUX1_UART7_TX 80
+#define STM32_DMAMUX1_UART8_RX 81
+#define STM32_DMAMUX1_UART8_TX 82
+#define STM32_DMAMUX1_SPI4_RX 83
+#define STM32_DMAMUX1_SPI4_TX 84
+#define STM32_DMAMUX1_SPI5_RX 85
+#define STM32_DMAMUX1_SPI5_TX 86
+#define STM32_DMAMUX1_SAI1_A 87
+#define STM32_DMAMUX1_SAI1_B 88
+#define STM32_DMAMUX1_SAI2_A 89
+#define STM32_DMAMUX1_SAI2_B 90
+#define STM32_DMAMUX1_SWPMI_RX 91
+#define STM32_DMAMUX1_SQPMI_TX 92
+#define STM32_DMAMUX1_SPDIFRX_DT 93
+#define STM32_DMAMUX1_SPDIFRX_CS 94
+#define STM32_DMAMUX1_HR_REQ1 95
+#define STM32_DMAMUX1_HR_REQ2 96
+#define STM32_DMAMUX1_HR_REQ3 97
+#define STM32_DMAMUX1_HR_REQ4 98
+#define STM32_DMAMUX1_HR_REQ5 99
+#define STM32_DMAMUX1_HR_REQ6 100
+#define STM32_DMAMUX1_DFSDM1_DMA0 101
+#define STM32_DMAMUX1_DFSDM1_DMA1 102
+#define STM32_DMAMUX1_DFSDM1_DMA2 103
+#define STM32_DMAMUX1_DFSDM1_DMA3 104
+#define STM32_DMAMUX1_TIM15_CH1 105
+#define STM32_DMAMUX1_TIM15_UP 106
+#define STM32_DMAMUX1_TIM15_TRIG 107
+#define STM32_DMAMUX1_TIM15_COM 108
+#define STM32_DMAMUX1_TIM16_CH1 109
+#define STM32_DMAMUX1_TIM16_UP 110
+#define STM32_DMAMUX1_TIM17_CH1 111
+#define STM32_DMAMUX1_TIM17_UP 112
+#define STM32_DMAMUX1_SAI3A 113
+#define STM32_DMAMUX1_SAI3B 114
+#define STM32_DMAMUX1_ADC3 115
+/** @} */
+
+/**
+ * @name DMAMUX2 request sources
+ * @{
+ */
+#define STM32_DMAMUX2_REQ_GEN0 1
+#define STM32_DMAMUX2_REQ_GEN1 2
+#define STM32_DMAMUX2_REQ_GEN2 3
+#define STM32_DMAMUX2_REQ_GEN3 4
+#define STM32_DMAMUX2_REQ_GEN4 5
+#define STM32_DMAMUX2_REQ_GEN5 6
+#define STM32_DMAMUX2_REQ_GEN6 7
+#define STM32_DMAMUX2_REQ_GEN7 8
+#define STM32_DMAMUX2_LP_UART1_RX 9
+#define STM32_DMAMUX2_LP_UART1_TX 10
+#define STM32_DMAMUX2_SPI6_RX 11
+#define STM32_DMAMUX2_SPI6_TX 12
+#define STM32_DMAMUX2_I2C4_RX 13
+#define STM32_DMAMUX2_I2C4_TX 14
+#define STM32_DMAMUX2_SAI4A 15
+#define STM32_DMAMUX2_SAI4B 16
+#define STM32_DMAMUX2_ADC3_REQ 17
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32_DMAMUX_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/stm32_isr.c b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/stm32_isr.c
new file mode 100644
index 0000000..8ed4d72
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/stm32_isr.c
@@ -0,0 +1,198 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32H7xx/stm32_isr.c
+ * @brief STM32H7xx ISR handler code.
+ *
+ * @addtogroup STM32H7xx_ISR
+ * @{
+ */
+
+#include "hal.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define exti_serve_irq(pr, channel) { \
+ \
+ if ((pr) & (1U << (channel))) { \
+ _pal_isr_code(channel); \
+ } \
+}
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#include "stm32_exti0.inc"
+#include "stm32_exti1.inc"
+#include "stm32_exti2.inc"
+#include "stm32_exti3.inc"
+#include "stm32_exti4.inc"
+#include "stm32_exti5_9.inc"
+#include "stm32_exti10_15.inc"
+#include "stm32_exti16.inc"
+#include "stm32_exti17.inc"
+#include "stm32_exti18.inc"
+#include "stm32_exti19.inc"
+#include "stm32_exti20_21.inc"
+
+#include "stm32_fdcan1.inc"
+#include "stm32_fdcan2.inc"
+
+#include "stm32_quadspi1.inc"
+
+#include "stm32_sdmmc1.inc"
+#include "stm32_sdmmc2.inc"
+
+#include
+#include "stm32_usart2.inc"
+#include "stm32_usart3.inc"
+#include "stm32_uart4.inc"
+#include "stm32_uart5.inc"
+#include "stm32_usart6.inc"
+#include "stm32_uart7.inc"
+#include "stm32_uart8.inc"
+#include "stm32_lpuart1.inc"
+
+#include "stm32_tim1.inc"
+#include "stm32_tim2.inc"
+#include "stm32_tim3.inc"
+#include "stm32_tim4.inc"
+#include "stm32_tim5.inc"
+#include "stm32_tim6.inc"
+#include "stm32_tim7.inc"
+#include "stm32_tim8_12_13_14.inc"
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables IRQ sources.
+ *
+ * @notapi
+ */
+void irqInit(void) {
+
+ exti0_irq_init();
+ exti1_irq_init();
+ exti2_irq_init();
+ exti3_irq_init();
+ exti4_irq_init();
+ exti5_9_irq_init();
+ exti10_15_irq_init();
+ exti16_irq_init();
+ exti17_irq_init();
+ exti18_irq_init();
+ exti19_irq_init();
+ exti20_exti21_irq_init();
+
+ fdcan1_irq_init();
+ fdcan2_irq_init();
+
+ mdma_irq_init();
+
+ quadspi1_irq_init();
+
+ sdmmc1_irq_init();
+ sdmmc2_irq_init();
+
+ tim1_irq_init();
+ tim2_irq_init();
+ tim3_irq_init();
+ tim4_irq_init();
+ tim5_irq_init();
+ tim6_irq_init();
+ tim7_irq_init();
+ tim8_tim12_tim13_tim14_irq_init();
+
+ usart1_irq_init();
+ usart2_irq_init();
+ usart3_irq_init();
+ uart4_irq_init();
+ uart5_irq_init();
+ usart6_irq_init();
+ uart7_irq_init();
+ uart8_irq_init();
+ lpuart1_irq_init();
+}
+
+/**
+ * @brief Disables IRQ sources.
+ *
+ * @notapi
+ */
+void irqDeinit(void) {
+
+ exti0_irq_deinit();
+ exti1_irq_deinit();
+ exti2_irq_deinit();
+ exti3_irq_deinit();
+ exti4_irq_deinit();
+ exti5_9_irq_deinit();
+ exti10_15_irq_deinit();
+ exti16_irq_deinit();
+ exti17_irq_deinit();
+ exti18_irq_deinit();
+ exti19_irq_deinit();
+ exti20_exti21_irq_deinit();
+
+ fdcan1_irq_deinit();
+ fdcan2_irq_deinit();
+
+ mdma_irq_deinit();
+
+ quadspi1_irq_deinit();
+
+ sdmmc1_irq_deinit();
+ sdmmc2_irq_deinit();
+
+ tim1_irq_deinit();
+ tim2_irq_deinit();
+ tim3_irq_deinit();
+ tim4_irq_deinit();
+ tim5_irq_deinit();
+ tim6_irq_deinit();
+ tim7_irq_deinit();
+ tim8_tim12_tim13_tim14_irq_deinit();
+
+ usart1_irq_deinit();
+ usart2_irq_deinit();
+ usart3_irq_deinit();
+ uart4_irq_deinit();
+ uart5_irq_deinit();
+ usart6_irq_deinit();
+ uart7_irq_deinit();
+ uart8_irq_deinit();
+ lpuart1_irq_deinit();
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/stm32_isr.h b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/stm32_isr.h
new file mode 100644
index 0000000..e9b776a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/stm32_isr.h
@@ -0,0 +1,384 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32H7xx/stm32_isr.h
+ * @brief STM32H7xx ISR handler header.
+ *
+ * @addtogroup STM32H7xx_ISR
+ * @{
+ */
+
+#ifndef STM32_ISR_H
+#define STM32_ISR_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name ISRs suppressed in standard drivers
+ * @{
+ */
+#define STM32_TIM1_SUPPRESS_ISR
+#define STM32_TIM2_SUPPRESS_ISR
+#define STM32_TIM3_SUPPRESS_ISR
+#define STM32_TIM4_SUPPRESS_ISR
+#define STM32_TIM5_SUPPRESS_ISR
+#define STM32_TIM6_SUPPRESS_ISR
+#define STM32_TIM7_SUPPRESS_ISR
+#define STM32_TIM8_SUPPRESS_ISR
+#define STM32_TIM12_SUPPRESS_ISR
+#define STM32_TIM13_SUPPRESS_ISR
+#define STM32_TIM14_SUPPRESS_ISR
+#define STM32_TIM15_SUPPRESS_ISR
+#define STM32_TIM16_SUPPRESS_ISR
+#define STM32_TIM17_SUPPRESS_ISR
+
+#define STM32_USART1_SUPPRESS_ISR
+#define STM32_USART2_SUPPRESS_ISR
+#define STM32_USART3_SUPPRESS_ISR
+#define STM32_UART4_SUPPRESS_ISR
+#define STM32_UART5_SUPPRESS_ISR
+#define STM32_USART6_SUPPRESS_ISR
+#define STM32_UART7_SUPPRESS_ISR
+#define STM32_UART8_SUPPRESS_ISR
+#define STM32_LPUART1_SUPPRESS_ISR
+/** @} */
+
+/**
+ * @name ISR names and numbers
+ * @{
+ */
+/*
+ * ADC units.
+ */
+#define STM32_ADC12_HANDLER Vector88
+#define STM32_ADC3_HANDLER Vector23C
+
+#define STM32_ADC12_NUMBER 18
+#define STM32_ADC3_NUMBER 127
+
+/*
+ * BDMA units.
+ */
+#define STM32_BDMA1_CH0_HANDLER Vector244
+#define STM32_BDMA1_CH1_HANDLER Vector248
+#define STM32_BDMA1_CH2_HANDLER Vector24C
+#define STM32_BDMA1_CH3_HANDLER Vector250
+#define STM32_BDMA1_CH4_HANDLER Vector254
+#define STM32_BDMA1_CH5_HANDLER Vector258
+#define STM32_BDMA1_CH6_HANDLER Vector25C
+#define STM32_BDMA1_CH7_HANDLER Vector260
+
+#define STM32_BDMA1_CH0_NUMBER 129
+#define STM32_BDMA1_CH1_NUMBER 130
+#define STM32_BDMA1_CH2_NUMBER 131
+#define STM32_BDMA1_CH3_NUMBER 132
+#define STM32_BDMA1_CH4_NUMBER 133
+#define STM32_BDMA1_CH5_NUMBER 134
+#define STM32_BDMA1_CH6_NUMBER 135
+#define STM32_BDMA1_CH7_NUMBER 136
+
+/*
+ * DMA units.
+ */
+#define STM32_DMA1_CH0_HANDLER Vector6C
+#define STM32_DMA1_CH1_HANDLER Vector70
+#define STM32_DMA1_CH2_HANDLER Vector74
+#define STM32_DMA1_CH3_HANDLER Vector78
+#define STM32_DMA1_CH4_HANDLER Vector7C
+#define STM32_DMA1_CH5_HANDLER Vector80
+#define STM32_DMA1_CH6_HANDLER Vector84
+#define STM32_DMA1_CH7_HANDLER VectorFC
+#define STM32_DMA2_CH0_HANDLER Vector120
+#define STM32_DMA2_CH1_HANDLER Vector124
+#define STM32_DMA2_CH2_HANDLER Vector128
+#define STM32_DMA2_CH3_HANDLER Vector12C
+#define STM32_DMA2_CH4_HANDLER Vector130
+#define STM32_DMA2_CH5_HANDLER Vector150
+#define STM32_DMA2_CH6_HANDLER Vector154
+#define STM32_DMA2_CH7_HANDLER Vector158
+
+#define STM32_DMA1_CH0_NUMBER 11
+#define STM32_DMA1_CH1_NUMBER 12
+#define STM32_DMA1_CH2_NUMBER 13
+#define STM32_DMA1_CH3_NUMBER 14
+#define STM32_DMA1_CH4_NUMBER 15
+#define STM32_DMA1_CH5_NUMBER 16
+#define STM32_DMA1_CH6_NUMBER 17
+#define STM32_DMA1_CH7_NUMBER 47
+#define STM32_DMA2_CH0_NUMBER 56
+#define STM32_DMA2_CH1_NUMBER 57
+#define STM32_DMA2_CH2_NUMBER 58
+#define STM32_DMA2_CH3_NUMBER 59
+#define STM32_DMA2_CH4_NUMBER 60
+#define STM32_DMA2_CH5_NUMBER 68
+#define STM32_DMA2_CH6_NUMBER 69
+#define STM32_DMA2_CH7_NUMBER 70
+
+/*
+ * MDMA units.
+ */
+#define STM32_MDMA_HANDLER Vector228
+
+#define STM32_MDMA_NUMBER 122
+
+/*
+ * ETH units.
+ */
+#define STM32_ETH_HANDLER Vector134
+
+#define STM32_ETH_NUMBER 61
+
+/*
+ * EXTI units.
+ */
+#define STM32_EXTI0_HANDLER Vector58
+#define STM32_EXTI1_HANDLER Vector5C
+#define STM32_EXTI2_HANDLER Vector60
+#define STM32_EXTI3_HANDLER Vector64
+#define STM32_EXTI4_HANDLER Vector68
+#define STM32_EXTI5_9_HANDLER Vector9C
+#define STM32_EXTI10_15_HANDLER VectorE0
+#define STM32_EXTI16_HANDLER Vector44 /* PVD */
+#define STM32_EXTI17_HANDLER VectorE4 /* RTC ALARM */
+#define STM32_EXTI18_HANDLER Vector48 /* RTC TAMP CSS */
+#define STM32_EXTI19_HANDLER Vector4C /* RTC WAKEUP */
+#define STM32_EXTI2021_HANDLER Vector264 /* COMP1 COMP2 */
+
+#define STM32_EXTI0_NUMBER 6
+#define STM32_EXTI1_NUMBER 7
+#define STM32_EXTI2_NUMBER 8
+#define STM32_EXTI3_NUMBER 9
+#define STM32_EXTI4_NUMBER 10
+#define STM32_EXTI5_9_NUMBER 23
+#define STM32_EXTI10_15_NUMBER 40
+#define STM32_EXTI16_NUMBER 1
+#define STM32_EXTI17_NUMBER 41
+#define STM32_EXTI18_NUMBER 42
+#define STM32_EXTI19_NUMBER 3
+#define STM32_EXTI2021_NUMBER 137
+
+/*
+ * FDCAN units.
+ */
+#define STM32_FDCAN1_IT0_HANDLER Vector8C
+#define STM32_FDCAN1_IT1_HANDLER Vector94
+#define STM32_FDCAN2_IT0_HANDLER Vector90
+#define STM32_FDCAN2_IT1_HANDLER Vector98
+
+#define STM32_FDCAN1_IT0_NUMBER 19
+#define STM32_FDCAN1_IT1_NUMBER 21
+#define STM32_FDCAN2_IT0_NUMBER 20
+#define STM32_FDCAN2_IT1_NUMBER 22
+
+/*
+ * I2C units.
+ */
+#define STM32_I2C1_EVENT_HANDLER VectorBC
+#define STM32_I2C1_ERROR_HANDLER VectorC0
+#define STM32_I2C2_EVENT_HANDLER VectorC4
+#define STM32_I2C2_ERROR_HANDLER VectorC8
+#define STM32_I2C3_EVENT_HANDLER Vector160
+#define STM32_I2C3_ERROR_HANDLER Vector164
+#define STM32_I2C4_EVENT_HANDLER Vector1BC
+#define STM32_I2C4_ERROR_HANDLER Vector1C0
+
+#define STM32_I2C1_EVENT_NUMBER 31
+#define STM32_I2C1_ERROR_NUMBER 32
+#define STM32_I2C2_EVENT_NUMBER 33
+#define STM32_I2C2_ERROR_NUMBER 34
+#define STM32_I2C3_EVENT_NUMBER 72
+#define STM32_I2C3_ERROR_NUMBER 73
+#define STM32_I2C4_EVENT_NUMBER 95
+#define STM32_I2C4_ERROR_NUMBER 96
+
+/*
+ * QUADSPI units.
+ */
+#define STM32_QUADSPI1_HANDLER Vector1B0
+
+#define STM32_QUADSPI1_NUMBER 92
+
+/*
+ * SDMMC units.
+ */
+#define STM32_SDMMC1_HANDLER Vector104
+#define STM32_SDMMC2_HANDLER Vector230
+
+#define STM32_SDMMC1_NUMBER 49
+#define STM32_SDMMC2_NUMBER 131
+
+/*
+ * SPI units.
+ */
+#define STM32_SPI1_HANDLER VectorCC
+#define STM32_SPI2_HANDLER VectorD0
+#define STM32_SPI3_HANDLER Vector10C
+#define STM32_SPI4_HANDLER Vector190
+#define STM32_SPI5_HANDLER Vector194
+#define STM32_SPI6_HANDLER Vector198
+
+#define STM32_SPI1_NUMBER 35
+#define STM32_SPI2_NUMBER 36
+#define STM32_SPI3_NUMBER 51
+#define STM32_SPI4_NUMBER 84
+#define STM32_SPI5_NUMBER 85
+#define STM32_SPI6_NUMBER 86
+
+/*
+ * TIM units.
+ */
+#define STM32_TIM1_BRK_HANDLER VectorA0
+#define STM32_TIM1_UP_HANDLER VectorA4
+#define STM32_TIM1_TRGCO_HANDLER VectorA8
+#define STM32_TIM1_CC_HANDLER VectorAC
+#define STM32_TIM2_HANDLER VectorB0
+#define STM32_TIM3_HANDLER VectorB4
+#define STM32_TIM4_HANDLER VectorB8
+#define STM32_TIM5_HANDLER Vector108
+#define STM32_TIM6_HANDLER Vector118
+#define STM32_TIM7_HANDLER Vector11C
+#define STM32_TIM8_BRK_TIM12_HANDLER VectorEC
+#define STM32_TIM8_UP_TIM13_HANDLER VectorF0
+#define STM32_TIM8_TRGCO_TIM14_HANDLER VectorF4
+#define STM32_TIM8_CC_HANDLER VectorF8
+#define STM32_TIM15_HANDLER Vector210
+#define STM32_TIM16_HANDLER Vector214
+#define STM32_TIM17_HANDLER Vector218
+
+#define STM32_TIM1_BRK_NUMBER 24
+#define STM32_TIM1_UP_NUMBER 25
+#define STM32_TIM1_TRGCO_NUMBER 26
+#define STM32_TIM1_CC_NUMBER 27
+#define STM32_TIM2_NUMBER 28
+#define STM32_TIM3_NUMBER 29
+#define STM32_TIM4_NUMBER 30
+#define STM32_TIM5_NUMBER 50
+#define STM32_TIM6_NUMBER 54
+#define STM32_TIM7_NUMBER 55
+#define STM32_TIM8_BRK_TIM12_NUMBER 43
+#define STM32_TIM8_UP_TIM13_NUMBER 44
+#define STM32_TIM8_TRGCO_TIM14_NUMBER 45
+#define STM32_TIM8_CC_NUMBER 46
+#define STM32_TIM15_NUMBER 116
+#define STM32_TIM16_NUMBER 117
+#define STM32_TIM17_NUMBER 118
+
+/*
+ * USART/UART units.
+ */
+#define STM32_USART1_HANDLER VectorD4
+#define STM32_USART2_HANDLER VectorD8
+#define STM32_USART3_HANDLER VectorDC
+#define STM32_UART4_HANDLER Vector110
+#define STM32_UART5_HANDLER Vector114
+#define STM32_USART6_HANDLER Vector15C
+#define STM32_UART7_HANDLER Vector188
+#define STM32_UART8_HANDLER Vector18C
+#define STM32_LPUART1_HANDLER Vector278
+
+#define STM32_USART1_NUMBER 37
+#define STM32_USART2_NUMBER 38
+#define STM32_USART3_NUMBER 39
+#define STM32_UART4_NUMBER 52
+#define STM32_UART5_NUMBER 53
+#define STM32_USART6_NUMBER 71
+#define STM32_UART7_NUMBER 82
+#define STM32_UART8_NUMBER 83
+#define STM32_LPUART1_NUMBER 142
+
+/*
+ * USB/OTG units.
+ */
+#define STM32_OTG1_HANDLER Vector1D4
+#define STM32_OTG1_EP1OUT_HANDLER Vector1C8
+#define STM32_OTG1_EP1IN_HANDLER Vector1CC
+#define STM32_OTG2_HANDLER Vector174
+#define STM32_OTG2_EP1OUT_HANDLER Vector168
+#define STM32_OTG2_EP1IN_HANDLER Vector16C
+
+#define STM32_OTG1_NUMBER 101
+#define STM32_OTG1_EP1OUT_NUMBER 98
+#define STM32_OTG1_EP1IN_NUMBER 99
+#define STM32_OTG2_NUMBER 77
+#define STM32_OTG2_EP1OUT_NUMBER 74
+#define STM32_OTG2_EP1IN_NUMBER 75
+
+/*
+ * LTDC units.
+ */
+#define STM32_LTDC_EV_HANDLER Vector1A0
+#define STM32_LTDC_ER_HANDLER Vector1A4
+
+#define STM32_LTDC_EV_NUMBER 88
+#define STM32_LTDC_ER_NUMBER 89
+
+/*
+ * DMA2D units.
+ */
+#define STM32_DMA2D_HANDLER Vector1A8
+
+#define STM32_DMA2D_NUMBER 90
+
+/*
+ * FSMC units.
+ */
+#define STM32_FSMC_HANDLER Vector100
+
+#define STM32_FSMC_NUMBER 48
+
+/*
+ * DCMI units.
+ */
+#define STM32_DCMI_HANDLER Vector178
+
+#define STM32_DCMI_NUMBER 78
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void irqInit(void);
+ void irqDeinit(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32_ISR_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/stm32_rcc.h b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/stm32_rcc.h
new file mode 100644
index 0000000..91d1086
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/stm32_rcc.h
@@ -0,0 +1,1834 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32F7xx/stm32_rcc.h
+ * @brief RCC helper driver header.
+ * @note This file requires definitions from the ST header file
+ * @p stm32f7xx.h.
+ *
+ * @addtogroup STM32F7xx_RCC
+ * @{
+ */
+#ifndef STM32_RCC_H
+#define STM32_RCC_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Generic RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the clock of one or more peripheral on the APB1 bus.
+ *
+ * @param[in] mask APB1 peripherals mask, low set
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAPB1L(mask, lp) { \
+ RCC->APB1LENR |= (mask); \
+ if (lp) \
+ RCC->APB1LLPENR |= (mask); \
+ else \
+ RCC->APB1LLPENR &= ~(mask); \
+ (void)RCC->APB1LLPENR; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the APB1 bus.
+ *
+ * @param[in] mask APB1 peripherals mask, high set
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAPB1H(mask, lp) { \
+ RCC->APB1HENR |= (mask); \
+ if (lp) \
+ RCC->APB1HLPENR |= (mask); \
+ else \
+ RCC->APB1HLPENR &= ~(mask); \
+ (void)RCC->APB1HLPENR; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the APB1 bus.
+ *
+ * @param[in] mask APB1 peripherals mask, low set
+ *
+ * @api
+ */
+#define rccDisableAPB1L(mask) { \
+ RCC->APB1LENR &= ~(mask); \
+ RCC->APB1LLPENR &= ~(mask); \
+ (void)RCC->APB1LLPENR; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the APB1 bus.
+ *
+ * @param[in] mask APB1 peripherals mask, high set
+ *
+ * @api
+ */
+#define rccDisableAPB1H(mask) { \
+ RCC->APB1HENR &= ~(mask); \
+ RCC->APB1HLPENR &= ~(mask); \
+ (void)RCC->APB1HLPENR; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the APB1 bus.
+ *
+ * @param[in] mask APB1 peripherals mask, low set
+ *
+ * @api
+ */
+#define rccResetAPB1L(mask) { \
+ RCC->APB1LRSTR |= (mask); \
+ RCC->APB1LRSTR &= ~(mask); \
+ (void)RCC->APB1LRSTR; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the APB1 bus.
+ *
+ * @param[in] mask APB1 peripherals mask, high set
+ *
+ * @api
+ */
+#define rccResetAPB1H(mask) { \
+ RCC->APB1HRSTR |= (mask); \
+ RCC->APB1HRSTR &= ~(mask); \
+ (void)RCC->APB1HRSTR; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the APB2 bus.
+ *
+ * @param[in] mask APB2 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAPB2(mask, lp) { \
+ RCC->APB2ENR |= (mask); \
+ if (lp) \
+ RCC->APB2LPENR |= (mask); \
+ else \
+ RCC->APB2LPENR &= ~(mask); \
+ (void)RCC->APB2LPENR; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the APB2 bus.
+ *
+ * @param[in] mask APB2 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAPB2(mask) { \
+ RCC->APB2ENR &= ~(mask); \
+ RCC->APB2LPENR &= ~(mask); \
+ (void)RCC->APB2LPENR; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the APB2 bus.
+ *
+ * @param[in] mask APB2 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAPB2(mask) { \
+ RCC->APB2RSTR |= (mask); \
+ RCC->APB2RSTR &= ~(mask); \
+ (void)RCC->APB2RSTR; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the APB3 bus.
+ *
+ * @param[in] mask APB3 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAPB3(mask, lp) { \
+ RCC->APB3ENR |= (mask); \
+ if (lp) \
+ RCC->APB3LPENR |= (mask); \
+ else \
+ RCC->APB3LPENR &= ~(mask); \
+ (void)RCC->APB3LPENR; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the APB3 bus.
+ *
+ * @param[in] mask APB3 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAPB3(mask) { \
+ RCC->APB3ENR &= ~(mask); \
+ RCC->APB3LPENR &= ~(mask); \
+ (void)RCC->APB3LPENR; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the APB3 bus.
+ *
+ * @param[in] mask APB2 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAPB3(mask) { \
+ RCC->APB3RSTR |= (mask); \
+ RCC->APB3RSTR &= ~(mask); \
+ (void)RCC->APB3RSTR; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the APB4 bus.
+ *
+ * @param[in] mask APB4 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAPB4(mask, lp) { \
+ RCC->APB4ENR |= (mask); \
+ if (lp) \
+ RCC->APB4LPENR |= (mask); \
+ else \
+ RCC->APB4LPENR &= ~(mask); \
+ (void)RCC->APB4LPENR; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the APB4 bus.
+ *
+ * @param[in] mask APB4 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAPB4(mask) { \
+ RCC->APB4ENR &= ~(mask); \
+ RCC->APB4LPENR &= ~(mask); \
+ (void)RCC->APB4LPENR; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the APB4 bus.
+ *
+ * @param[in] mask APB4 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAPB4(mask) { \
+ RCC->APB4RSTR |= (mask); \
+ RCC->APB4RSTR &= ~(mask); \
+ (void)RCC->APB4RSTR; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the AHB1 bus.
+ *
+ * @param[in] mask AHB1 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAHB1(mask, lp) { \
+ RCC->AHB1ENR |= (mask); \
+ if (lp) \
+ RCC->AHB1LPENR |= (mask); \
+ else \
+ RCC->AHB1LPENR &= ~(mask); \
+ (void)RCC->AHB1LPENR; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the AHB1 bus.
+ *
+ * @param[in] mask AHB1 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAHB1(mask) { \
+ RCC->AHB1ENR &= ~(mask); \
+ RCC->AHB1LPENR &= ~(mask); \
+ (void)RCC->AHB1LPENR; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the AHB1 bus.
+ *
+ * @param[in] mask AHB1 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAHB1(mask) { \
+ RCC->AHB1RSTR |= (mask); \
+ RCC->AHB1RSTR &= ~(mask); \
+ (void)RCC->AHB1RSTR; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the AHB2 bus.
+ *
+ * @param[in] mask AHB2 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAHB2(mask, lp) { \
+ RCC->AHB2ENR |= (mask); \
+ if (lp) \
+ RCC->AHB2LPENR |= (mask); \
+ else \
+ RCC->AHB2LPENR &= ~(mask); \
+ (void)RCC->AHB2LPENR; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the AHB2 bus.
+ *
+ * @param[in] mask AHB2 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAHB2(mask) { \
+ RCC->AHB2ENR &= ~(mask); \
+ RCC->AHB2LPENR &= ~(mask); \
+ (void)RCC->AHB2LPENR; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the AHB2 bus.
+ *
+ * @param[in] mask AHB2 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAHB2(mask) { \
+ RCC->AHB2RSTR |= (mask); \
+ RCC->AHB2RSTR &= ~(mask); \
+ (void)RCC->AHB2RSTR; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the AHB3 bus.
+ *
+ * @param[in] mask AHB3 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAHB3(mask, lp) { \
+ RCC->AHB3ENR |= (mask); \
+ if (lp) \
+ RCC->AHB3LPENR |= (mask); \
+ else \
+ RCC->AHB3LPENR &= ~(mask); \
+ (void)RCC->AHB3LPENR; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the AHB3 bus.
+ *
+ * @param[in] mask AHB3 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAHB3(mask) { \
+ RCC->AHB3ENR &= ~(mask); \
+ RCC->AHB3LPENR &= ~(mask); \
+ (void)RCC->AHB3LPENR; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the AHB3 bus.
+ *
+ * @param[in] mask AHB3 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAHB3(mask) { \
+ RCC->AHB3RSTR |= (mask); \
+ RCC->AHB3RSTR &= ~(mask); \
+ (void)RCC->AHB3RSTR; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the AHB4 bus.
+ *
+ * @param[in] mask AHB4 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAHB4(mask, lp) { \
+ RCC->AHB4ENR |= (mask); \
+ if (lp) \
+ RCC->AHB4LPENR |= (mask); \
+ else \
+ RCC->AHB4LPENR &= ~(mask); \
+ (void)RCC->AHB4LPENR; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the AHB4 bus.
+ *
+ * @param[in] mask AHB4 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAHB4(mask) { \
+ RCC->AHB4ENR &= ~(mask); \
+ RCC->AHB4LPENR &= ~(mask); \
+ (void)RCC->AHB4LPENR; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the AHB4 bus.
+ *
+ * @param[in] mask AHB4 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAHB4(mask) { \
+ RCC->AHB4RSTR |= (mask); \
+ RCC->AHB4RSTR &= ~(mask); \
+ (void)RCC->AHB4RSTR; \
+}
+/** @} */
+
+/**
+ * @name ADC peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the ADC1/ADC2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableADC12(lp) rccEnableAHB1(RCC_AHB1ENR_ADC12EN, lp)
+
+/**
+ * @brief Disables the ADC1/ADC2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableADC12() rccDisableAHB1(RCC_AHB1ENR_ADC12EN)
+
+/**
+ * @brief Resets the ADC1/ADC2 peripheral.
+ *
+ * @api
+ */
+#define rccResetADC12() rccResetAHB1(RCC_AHB1RSTR_ADC12RST)
+
+/**
+ * @brief Enables the ADC3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableADC3(lp) rccEnableAHB4(RCC_AHB4ENR_ADC3EN, lp)
+
+/**
+ * @brief Disables the ADC3 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableADC3() rccDisableAHB4(RCC_AHB4ENR_ADC3EN)
+
+/**
+ * @brief Resets the ADC3 peripheral.
+ *
+ * @api
+ */
+#define rccResetADC3() rccResetAHB4(RCC_AHB4RSTR_ADC3RST)
+/** @} */
+
+/**
+ * @name DAC peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the DAC1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableDAC1(lp) rccEnableAPB1L(RCC_APB1LENR_DAC12EN, lp)
+
+/**
+ * @brief Disables the DAC1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableDAC1() rccDisableAPB1L(RCC_APB1LENR_DAC12EN)
+
+/**
+ * @brief Resets the DAC1 peripheral.
+ *
+ * @api
+ */
+#define rccResetDAC1() rccResetAPB1L(RCC_APB1LRSTR_DAC12RST)
+/** @} */
+
+/**
+ * @name DMA peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the BDMA1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableBDMA1(lp) rccEnableAHB4(RCC_AHB4ENR_BDMAEN, lp)
+
+/**
+ * @brief Disables the BDMA1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableBDMA1() rccDisableAHB4(RCC_AHB4ENR_BDMAEN)
+
+/**
+ * @brief Resets the BDMA1 peripheral.
+ *
+ * @api
+ */
+#define rccResetBDMA1() rccResetAHB4(RCC_AHB4RSTR_BDMARST)
+
+/**
+ * @brief Enables the DMA1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp)
+
+/**
+ * @brief Disables the DMA1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableDMA1() rccDisableAHB1(RCC_AHB1ENR_DMA1EN)
+
+/**
+ * @brief Resets the DMA1 peripheral.
+ *
+ * @api
+ */
+#define rccResetDMA1() rccResetAHB1(RCC_AHB1RSTR_DMA1RST)
+
+/**
+ * @brief Enables the DMA2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableDMA2(lp) rccEnableAHB1(RCC_AHB1ENR_DMA2EN, lp)
+
+/**
+ * @brief Disables the DMA2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableDMA2() rccDisableAHB1(RCC_AHB1ENR_DMA2EN)
+
+/**
+ * @brief Resets the DMA2 peripheral.
+ *
+ * @api
+ */
+#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST)
+
+/**
+ * @brief Enables the MDMA peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableMDMA(lp) rccEnableAHB3(RCC_AHB3ENR_MDMAEN, lp)
+
+/**
+ * @brief Disables the MDMA peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableMDMA() rccDisableAHB3(RCC_AHB3ENR_MDMAEN)
+
+/**
+ * @brief Resets the MDMA peripheral.
+ *
+ * @api
+ */
+#define rccResetMDMA() rccResetAHB3(RCC_AHB3ENR_MDMARST)
+/** @} */
+
+/**
+ * @name RAM specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the BKPRAM clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableBKPRAM(lp) rccEnableAHB4(RCC_AHB4ENR_BKPRAMEN, lp)
+
+/**
+ * @brief Disables the BKPRAM clock.
+ *
+ * @api
+ */
+#define rccDisableBKPRAM() rccDisableAHB4(RCC_AHB4ENR_BKPRAMEN)
+
+/**
+ * @brief Enables the SRAM1 clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSRAM1(lp) rccEnableAHB2(RCC_AHB2ENR_D2SRAM1EN, lp)
+
+/**
+ * @brief Disables the SRAM1 clock.
+ *
+ * @api
+ */
+#define rccDisableSRAM1() rccDisableAHB2(RCC_AHB2ENR_D2SRAM1EN)
+
+/**
+ * @brief Enables the SRAM2 clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSRAM2(lp) rccEnableAHB2(RCC_AHB2ENR_D2SRAM2EN, lp)
+
+/**
+ * @brief Disables the SRAM2 clock.
+ *
+ * @api
+ */
+#define rccDisableSRAM2() rccDisableAHB2(RCC_AHB2ENR_D2SRAM2EN)
+
+#if !defined(STM32H723xx)
+/**
+ * @brief Enables the SRAM3 clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSRAM3(lp) rccEnableAHB2(RCC_AHB2ENR_D2SRAM3EN, lp)
+
+/**
+ * @brief Disables the SRAM3 clock.
+ *
+ * @api
+ */
+#define rccDisableSRAM3() rccDisableAHB2(RCC_AHB2ENR_D2SRAM3EN)
+#endif // !defined(STM32H723xx)
+/** @} */
+
+/**
+ * @name ETH peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the ETH peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableETH(lp) rccEnableAHB1(RCC_AHB1ENR_ETHMACEN | \
+ RCC_AHB1ENR_ETHMACTXEN | \
+ RCC_AHB1ENR_ETHMACRXEN, lp)
+
+/**
+ * @brief Disables the ETH peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableETH() rccDisableAHB1(RCC_AHB1ENR_ETHMACEN | \
+ RCC_AHB1ENR_ETHMACTXEN | \
+ RCC_AHB1ENR_ETHMACRXEN)
+
+/**
+ * @brief Resets the ETH peripheral.
+ *
+ * @api
+ */
+#define rccResetETH() rccResetAHB1(RCC_AHB1RSTR_ETHMACRST)
+/** @} */
+
+/**
+ * @name FDCAN peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the FDCAN peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableFDCAN(lp) rccEnableAPB1H(RCC_APB1HENR_FDCANEN, lp)
+
+/**
+ * @brief Disables the FDCAN peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableFDCAN() rccDisableAPB1H(RCC_APB1HENR_FDCANEN)
+
+/**
+ * @brief Resets the FDCAN peripheral.
+ *
+ * @api
+ */
+#define rccResetFDCAN() rccResetAPB1H(RCC_APB1HRSTR_FDCANRST)
+/** @} */
+
+/**
+ * @name I2C peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the I2C1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableI2C1(lp) rccEnableAPB1L(RCC_APB1LENR_I2C1EN, lp)
+
+/**
+ * @brief Disables the I2C1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableI2C1() rccDisableAPB1L(RCC_APB1LENR_I2C1EN)
+
+/**
+ * @brief Resets the I2C1 peripheral.
+ *
+ * @api
+ */
+#define rccResetI2C1() rccResetAPB1L(RCC_APB1LRSTR_I2C1RST)
+
+/**
+ * @brief Enables the I2C2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableI2C2(lp) rccEnableAPB1L(RCC_APB1LENR_I2C2EN, lp)
+
+/**
+ * @brief Disables the I2C2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableI2C2() rccDisableAPB1L(RCC_APB1LENR_I2C2EN)
+
+/**
+ * @brief Resets the I2C2 peripheral.
+ *
+ * @api
+ */
+#define rccResetI2C2() rccResetAPB1L(RCC_APB1LRSTR_I2C2RST)
+
+/**
+ * @brief Enables the I2C3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableI2C3(lp) rccEnableAPB1L(RCC_APB1LENR_I2C3EN, lp)
+
+/**
+ * @brief Disables the I2C3 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableI2C3() rccDisableAPB1L(RCC_APB1LENR_I2C3EN)
+
+/**
+ * @brief Resets the I2C3 peripheral.
+ *
+ * @api
+ */
+#define rccResetI2C3() rccResetAPB1L(RCC_APB1LRSTR_I2C3RST)
+
+/**
+ * @brief Enables the I2C4 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableI2C4(lp) rccEnableAPB4(RCC_APB4ENR_I2C4EN, lp)
+
+/**
+ * @brief Disables the I2C4 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableI2C4() rccDisableAPB4(RCC_APB4ENR_I2C4EN)
+
+/**
+ * @brief Resets the I2C4 peripheral.
+ *
+ * @api
+ */
+#define rccResetI2C4() rccResetAPB4(RCC_APB4RSTR_I2C4RST)
+/** @} */
+
+/**
+ * @name OTG peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the USB1_OTG_HS peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSB1_OTG_HS(lp) rccEnableAHB1(RCC_AHB1ENR_USB1OTGHSEN, lp)
+
+/**
+ * @brief Disables the USB1_OTG_HS peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUSB1_OTG_HS() rccDisableAHB1(RCC_AHB1ENR_USB1OTGHSEN)
+
+/**
+ * @brief Resets the USB1_OTG_HS peripheral.
+ *
+ * @api
+ */
+#define rccResetUSB1_OTG_HS() rccResetAHB1(RCC_AHB1RSTR_USB1OTGHSRST)
+
+#if !defined(STM32H723xx)
+
+/**
+ * @brief Enables the USB2_OTG_HS peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSB2_OTG_HS(lp) rccEnableAHB1(RCC_AHB1ENR_USB2OTGHSEN, lp)
+
+/**
+ * @brief Disables the USB2_OTG_HS peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUSB2_OTG_HS() rccDisableAHB1(RCC_AHB1ENR_USB2OTGHSEN)
+
+/**
+ * @brief Resets the USB2_OTG_HS peripheral.
+ *
+ * @api
+ */
+#define rccResetUSB2_OTG_HS() rccResetAHB1(RCC_AHB1RSTR_USB2OTGHSRST)
+
+#endif // !defined(STM32H723xx)
+
+/**
+ * @brief Enables the USB1_OTG_HS ULPI peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSB1_HSULPI(lp) rccEnableAHB1(RCC_AHB1ENR_USB1OTGHSULPIEN, lp)
+
+/**
+ * @brief Disables the USB1_OTG_HS peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUSB1_HSULPI() rccDisableAHB1(RCC_AHB1ENR_USB1OTGHSULPIEN)
+
+#if !defined(STM32H723xx)
+
+/**
+ * @brief Enables the USB2_OTG_HS ULPI peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSB2_HSULPI(lp) rccEnableAHB1(RCC_AHB1ENR_USB2OTGHSULPIEN, lp)
+
+/**
+ * @brief Disables the USB2_OTG_HS peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUSB2_HSULPI() rccDisableAHB1(RCC_AHB1ENR_USB2OTGHSULPIEN)
+
+#endif // !defined(STM32H723xx)
+/** @} */
+
+/**
+ * @name QUADSPI peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the QUADSPI1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableQUADSPI1(lp) rccEnableAHB3(RCC_AHB3ENR_QSPIEN, lp)
+
+/**
+ * @brief Disables the QUADSPI1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableQUADSPI1() rccDisableAHB3(RCC_AHB3ENR_QSPIEN)
+
+/**
+ * @brief Resets the QUADSPI1 peripheral.
+ *
+ * @api
+ */
+#define rccResetQUADSPI1() rccResetAHB3(RCC_AHB3RSTR_QSPIRST)
+/** @} */
+
+/**
+ * @name RNG peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the RNG peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableRNG(lp) rccEnableAHB2(RCC_AHB2ENR_RNGEN, lp)
+
+/**
+ * @brief Disables the RNG peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableRNG() rccDisableAHB2(RCC_AHB2ENR_RNGEN)
+
+/**
+ * @brief Resets the RNG peripheral.
+ *
+ * @api
+ */
+#define rccResetRNG() rccResetAHB2(RCC_AHB2RSTR_RNGRST)
+/** @} */
+
+/**
+ * @name SDMMC peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the SDMMC1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSDMMC1(lp) rccEnableAHB3(RCC_AHB3ENR_SDMMC1EN, lp)
+
+/**
+ * @brief Disables the SDMMC1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableSDMMC1() rccDisableAHB3(RCC_AHB3ENR_SDMMC1EN)
+
+/**
+ * @brief Resets the SDMMC1 peripheral.
+ *
+ * @api
+ */
+#define rccResetSDMMC1() rccResetAHB3(RCC_AHB3RSTR_SDMMC1RST)
+
+/**
+ * @brief Enables the SDMMC2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSDMMC2(lp) rccEnableAHB3(RCC_AHB3ENR_SDMMC2EN, lp)
+
+/**
+ * @brief Disables the SDMMC2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableSDMMC2() rccDisableAHB3(RCC_AHB3ENR_SDMMC2EN)
+
+/**
+ * @brief Resets the SDMMC2 peripheral.
+ *
+ * @api
+ */
+#define rccResetSDMMC2() rccResetAHB3(RCC_AHB3RSTR_SDMMC2RST)
+/** @} */
+
+/**
+ * @name SPI peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the SPI1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp)
+
+/**
+ * @brief Disables the SPI1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN)
+
+/**
+ * @brief Resets the SPI1 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI1() rccResetAPB2(RCC_APB2RSTR_SPI1RST)
+
+/**
+ * @brief Enables the SPI2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI2(lp) rccEnableAPB1L(RCC_APB1LENR_SPI2EN, lp)
+
+/**
+ * @brief Disables the SPI2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableSPI2() rccDisableAPB1L(RCC_APB1LENR_SPI2EN)
+
+/**
+ * @brief Resets the SPI2 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI2() rccResetAPB1L(RCC_APB1LRSTR_SPI2RST)
+
+/**
+ * @brief Enables the SPI3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI3(lp) rccEnableAPB1L(RCC_APB1LENR_SPI3EN, lp)
+
+/**
+ * @brief Disables the SPI3 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableSPI3() rccDisableAPB1L(RCC_APB1LENR_SPI3EN)
+
+/**
+ * @brief Resets the SPI3 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI3() rccResetAPB1L(RCC_APB1LRSTR_SPI3RST)
+
+/**
+ * @brief Enables the SPI4 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI4(lp) rccEnableAPB2(RCC_APB2ENR_SPI4EN, lp)
+
+/**
+ * @brief Disables the SPI4 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableSPI4() rccDisableAPB2(RCC_APB2ENR_SPI4EN)
+
+/**
+ * @brief Resets the SPI4 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI4() rccResetAPB2(RCC_APB2RSTR_SPI4RST)
+
+/**
+ * @brief Enables the SPI5 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI5(lp) rccEnableAPB2(RCC_APB2ENR_SPI5EN, lp)
+
+/**
+ * @brief Disables the SPI5 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableSPI5() rccDisableAPB2(RCC_APB2ENR_SPI5EN)
+
+/**
+ * @brief Resets the SPI5 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI5() rccResetAPB2(RCC_APB2RSTR_SPI5RST)
+
+/**
+ * @brief Enables the SPI6 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI6(lp) rccEnableAPB4(RCC_APB4ENR_SPI6EN, lp)
+
+/**
+ * @brief Disables the SPI6 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableSPI6() rccDisableAPB4(RCC_APB4ENR_SPI6EN)
+
+/**
+ * @brief Resets the SPI6 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI6() rccResetAPB4(RCC_APB4RSTR_SPI6RST)
+/** @} */
+
+/**
+ * @name TIM peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the TIM1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp)
+
+/**
+ * @brief Disables the TIM1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN)
+
+/**
+ * @brief Resets the TIM1 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM1() rccResetAPB2(RCC_APB2RSTR_TIM1RST)
+
+/**
+ * @brief Enables the TIM2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM2(lp) rccEnableAPB1L(RCC_APB1LENR_TIM2EN, lp)
+
+/**
+ * @brief Disables the TIM2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM2() rccDisableAPB1L(RCC_APB1LENR_TIM2EN)
+
+/**
+ * @brief Resets the TIM2 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM2() rccResetAPB1L(RCC_APB1LRSTR_TIM2RST)
+
+/**
+ * @brief Enables the TIM3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM3(lp) rccEnableAPB1L(RCC_APB1LENR_TIM3EN, lp)
+
+/**
+ * @brief Disables the TIM3 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM3() rccDisableAPB1L(RCC_APB1LENR_TIM3EN)
+
+/**
+ * @brief Resets the TIM3 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM3() rccResetAPB1L(RCC_APB1LRSTR_TIM3RST)
+
+/**
+ * @brief Enables the TIM4 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM4(lp) rccEnableAPB1L(RCC_APB1LENR_TIM4EN, lp)
+
+/**
+ * @brief Disables the TIM4 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM4() rccDisableAPB1L(RCC_APB1LENR_TIM4EN)
+
+/**
+ * @brief Resets the TIM4 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM4() rccResetAPB1L(RCC_APB1LRSTR_TIM4RST)
+
+/**
+ * @brief Enables the TIM5 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM5(lp) rccEnableAPB1L(RCC_APB1LENR_TIM5EN, lp)
+
+/**
+ * @brief Disables the TIM5 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM5() rccDisableAPB1L(RCC_APB1LENR_TIM5EN)
+
+/**
+ * @brief Resets the TIM5 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM5() rccResetAPB1L(RCC_APB1LRSTR_TIM5RST)
+
+/**
+ * @brief Enables the TIM6 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM6(lp) rccEnableAPB1L(RCC_APB1LENR_TIM6EN, lp)
+
+/**
+ * @brief Disables the TIM6 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM6() rccDisableAPB1L(RCC_APB1LENR_TIM6EN)
+
+/**
+ * @brief Resets the TIM6 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM6() rccResetAPB1L(RCC_APB1LRSTR_TIM6RST)
+
+/**
+ * @brief Enables the TIM7 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM7(lp) rccEnableAPB1L(RCC_APB1LENR_TIM7EN, lp)
+
+/**
+ * @brief Disables the TIM7 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM7() rccDisableAPB1L(RCC_APB1LENR_TIM7EN)
+
+/**
+ * @brief Resets the TIM7 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM7() rccResetAPB1L(RCC_APB1LRSTR_TIM7RST)
+
+/**
+ * @brief Enables the TIM8 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp)
+
+/**
+ * @brief Disables the TIM8 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN)
+
+/**
+ * @brief Resets the TIM8 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST)
+
+/**
+ * @brief Enables the TIM12 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM12(lp) rccEnableAPB1L(RCC_APB1LENR_TIM12EN, lp)
+
+/**
+ * @brief Disables the TIM12 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM12() rccDisableAPB1L(RCC_APB1LENR_TIM12EN)
+
+/**
+ * @brief Resets the TIM12 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM12() rccResetAPB1L(RCC_APB1LRSTR_TIM12RST)
+
+/**
+ * @brief Enables the TIM13 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM13(lp) rccEnableAPB1L(RCC_APB1LENR_TIM13EN, lp)
+
+/**
+ * @brief Disables the TIM13 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM13() rccDisableAPB1L(RCC_APB1LENR_TIM13EN)
+
+/**
+ * @brief Resets the TIM13 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM13() rccResetAPB1L(RCC_APB1LRSTR_TIM13RST)
+
+/**
+ * @brief Enables the TIM14 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM14(lp) rccEnableAPB1L(RCC_APB1LENR_TIM14EN, lp)
+
+/**
+ * @brief Disables the TIM14 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM14() rccDisableAPB1L(RCC_APB1LENR_TIM14EN)
+
+/**
+ * @brief Resets the TIM14 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM14() rccResetAPB1L(RCC_APB1LRSTR_TIM14RST)
+
+/**
+ * @brief Enables the TIM15 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp)
+
+/**
+ * @brief Disables the TIM15 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN)
+
+/**
+ * @brief Resets the TIM15 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST)
+
+/**
+ * @brief Enables the TIM16 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp)
+
+/**
+ * @brief Disables the TIM16 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN)
+
+/**
+ * @brief Resets the TIM16 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST)
+
+/**
+ * @brief Enables the TIM17 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp)
+
+/**
+ * @brief Disables the TIM17 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN)
+
+/**
+ * @brief Resets the TIM17 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST)
+/** @} */
+
+/**
+ * @name USART/UART peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the USART1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp)
+
+/**
+ * @brief Disables the USART1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN)
+
+/**
+ * @brief Resets the USART1 peripheral.
+ *
+ * @api
+ */
+#define rccResetUSART1() rccResetAPB2(RCC_APB2RSTR_USART1RST)
+
+/**
+ * @brief Enables the USART2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSART2(lp) rccEnableAPB1L(RCC_APB1LENR_USART2EN, lp)
+
+/**
+ * @brief Disables the USART2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUSART2() rccDisableAPB1L(RCC_APB1LENR_USART2EN)
+
+/**
+ * @brief Resets the USART2 peripheral.
+ *
+ * @api
+ */
+#define rccResetUSART2() rccResetAPB1L(RCC_APB1LRSTR_USART2RST)
+
+/**
+ * @brief Enables the USART3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSART3(lp) rccEnableAPB1L(RCC_APB1LENR_USART3EN, lp)
+
+/**
+ * @brief Disables the USART3 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUSART3() rccDisableAPB1L(RCC_APB1LENR_USART3EN)
+
+/**
+ * @brief Resets the USART3 peripheral.
+ *
+ * @api
+ */
+#define rccResetUSART3() rccResetAPB1L(RCC_APB1LRSTR_USART3RST)
+
+/**
+ * @brief Enables the UART4 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUART4(lp) rccEnableAPB1L(RCC_APB1LENR_UART4EN, lp)
+
+/**
+ * @brief Disables the UART4 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUART4() rccDisableAPB1L(RCC_APB1LENR_UART4EN)
+
+/**
+ * @brief Resets the UART4 peripheral.
+ *
+ * @api
+ */
+#define rccResetUART4() rccResetAPB1L(RCC_APB1LRSTR_UART4RST)
+
+/**
+ * @brief Enables the UART5 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUART5(lp) rccEnableAPB1L(RCC_APB1LENR_UART5EN, lp)
+
+/**
+ * @brief Disables the UART5 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUART5() rccDisableAPB1L(RCC_APB1LENR_UART5EN)
+
+/**
+ * @brief Resets the UART5 peripheral.
+ *
+ * @api
+ */
+#define rccResetUART5() rccResetAPB1L(RCC_APB1LRSTR_UART5RST)
+
+/**
+ * @brief Enables the USART6 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSART6(lp) rccEnableAPB2(RCC_APB2ENR_USART6EN, lp)
+
+/**
+ * @brief Disables the USART6 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUSART6() rccDisableAPB2(RCC_APB2ENR_USART6EN)
+
+/**
+ * @brief Resets the USART6 peripheral.
+ *
+ * @api
+ */
+#define rccResetUSART6() rccResetAPB2(RCC_APB2RSTR_USART6RST)
+
+/**
+ * @brief Enables the UART7 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUART7(lp) rccEnableAPB1L(RCC_APB1LENR_UART7EN, lp)
+
+/**
+ * @brief Disables the UART7 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUART7() rccDisableAPB1L(RCC_APB1LENR_UART7EN)
+
+/**
+ * @brief Resets the UART7 peripheral.
+ *
+ * @api
+ */
+#define rccResetUART7() rccResetAPB1L(RCC_APB1LRSTR_UART7RST)
+
+/**
+ * @brief Enables the UART8 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUART8(lp) rccEnableAPB1L(RCC_APB1LENR_UART8EN, lp)
+
+/**
+ * @brief Disables the UART8 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUART8() rccDisableAPB1L(RCC_APB1LENR_UART8EN)
+
+/**
+ * @brief Resets the UART8 peripheral.
+ *
+ * @api
+ */
+#define rccResetUART8() rccResetAPB1L(RCC_APB1LRSTR_UART8RST)
+/** @} */
+
+/**
+ * @brief Enables the LPUART1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableLPUART1(lp) rccEnableAPB4(RCC_APB4ENR_LPUART1EN, lp)
+
+/**
+ * @brief Disables the LPUART1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableLPUART1() rccDisableAPB4(RCC_APB4ENR_LPUART1EN)
+
+/**
+ * @brief Resets the LPUART1 peripheral.
+ *
+ * @api
+ */
+#define rccResetLPUART1() rccResetAPB4(RCC_APB4RSTR_LPUART1RST)
+/** @} */
+
+/**
+ * @name LTDC peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the LTDC peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableLTDC(lp) rccEnableAPB3(RCC_APB3ENR_LTDCEN, lp)
+
+/**
+ * @brief Disables the LTDC peripheral clock.
+. *
+ * @api
+ */
+#define rccDisableLTDC() rccDisableAPB3(RCC_APB3ENR_LTDCEN)
+
+/**
+ * @brief Resets the LTDC peripheral.
+ *
+ * @api
+ */
+#define rccResetLTDC() rccResetAPB3(RCC_APB3RSTR_LTDCRST)
+
+/**
+ * @name DMA2D peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the DMA2D peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableDMA2D(lp) rccEnableAHB3(RCC_AHB3ENR_DMA2DEN, lp)
+
+/**
+ * @brief Disables the DMA2D peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableDMA2D() rccDisableAHB3(RCC_AHB3ENR_DMA2DEN)
+
+/**
+ * @brief Resets the DMA2D peripheral.
+ *
+ * @api
+ */
+#define rccResetDMA2D() rccResetAHB3(RCC_AHB3RSTR_DMA2DRST)
+/** @} */
+
+/**
+ * @name FSMC peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the FSMC peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#if defined(STM32_FSMC_IS_FMC)
+ #define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FMCEN, lp)
+#else
+ #define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FSMCEN, lp)
+#endif
+
+/**
+ * @brief Disables the FSMC peripheral clock.
+ *
+ * @api
+ */
+#if defined(STM32_FSMC_IS_FMC)
+ #define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FMCEN)
+#else
+ #define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FSMCEN)
+#endif
+
+/**
+ * @brief Resets the FSMC peripheral.
+ *
+ * @api
+ */
+#if defined(STM32_FSMC_IS_FMC)
+ #define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FMCRST)
+#else
+ #define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FSMCRST)
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32_RCC_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/stm32_registry.h b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/stm32_registry.h
new file mode 100644
index 0000000..51e88e5
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32H7xx/stm32_registry.h
@@ -0,0 +1,778 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32H7xx/stm32_registry.h
+ * @brief STM32H7xx capabilities registry.
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#ifndef STM32_REGISTRY_H
+#define STM32_REGISTRY_H
+
+/*===========================================================================*/
+/* Platform capabilities. */
+/*===========================================================================*/
+
+/* Cores.*/
+#if defined(STM32H750xx) || defined(STM32H742xx) || \
+ defined(STM32H743xx) || defined(STM32H753xx) || \
+ defined(STM32H723xx)
+#define STM32_HAS_M7 TRUE
+#define STM32_HAS_M4 FALSE
+#else
+#define STM32_HAS_M7 TRUE
+#define STM32_HAS_M4 TRUE
+#endif
+
+/**
+ * @name STM32H7xx capabilities
+ * @{
+ */
+
+/*===========================================================================*/
+/* Common. */
+/*===========================================================================*/
+
+/* RNG attributes.*/
+#define STM32_HAS_RNG1 TRUE
+
+/* I2C attributes.*/
+#define STM32_I2C4_USE_BDMA TRUE
+
+/*===========================================================================*/
+/* STM32H743xx, STM32H753xx, STM32H745xx, STM32H755xx, STM32H747xx, */
+/* STM32H757xx. */
+/*===========================================================================*/
+#if defined(STM32H743xx) || defined(STM32H753xx) || \
+ defined(STM32H745xx) || defined(STM32H755xx) || \
+ defined(STM32H747xx) || defined(STM32H757xx) || \
+ defined(__DOXYGEN__)
+
+/* ADC attributes.*/
+#define STM32_HAS_ADC1 TRUE
+#define STM32_HAS_ADC2 TRUE
+#define STM32_HAS_ADC3 TRUE
+#define STM32_HAS_ADC4 FALSE
+
+#define STM32_HAS_SDADC1 FALSE
+#define STM32_HAS_SDADC2 FALSE
+#define STM32_HAS_SDADC3 FALSE
+
+/* CAN attributes.*/
+#define STM32_HAS_FDCAN1 TRUE
+#define STM32_HAS_FDCAN2 TRUE
+#define STM32_HAS_FDCAN3 FALSE
+#define STM32_FDCAN_FLS_NBR 128U
+#define STM32_FDCAN_FLE_NBR 128U
+#define STM32_FDCAN_RF0_NBR 64U
+#define STM32_FDCAN_RF1_NBR 64U
+#define STM32_FDCAN_RB_NBR 64U
+#define STM32_FDCAN_TEF_NBR 32U
+#define STM32_FDCAN_TB_NBR 32U
+#define STM32_FDCAN_TM_NBR 64U
+
+/* DAC attributes.*/
+#define STM32_HAS_DAC1_CH1 TRUE
+#define STM32_HAS_DAC1_CH2 TRUE
+#define STM32_HAS_DAC2_CH1 FALSE
+#define STM32_HAS_DAC2_CH2 FALSE
+
+/* BDMA attributes.*/
+#define STM32_HAS_BDMA1 TRUE
+
+/* DMA attributes.*/
+#define STM32_ADVANCED_DMA TRUE
+#define STM32_DMA_SUPPORTS_DMAMUX TRUE
+
+#define STM32_HAS_DMA1 TRUE
+#define STM32_HAS_DMA2 TRUE
+
+/* MDMA attributes.*/
+#define STM32_HAS_MDMA1 TRUE
+
+/* ETH attributes.*/
+#define STM32_HAS_ETH TRUE
+
+/* EXTI attributes.*/
+#define STM32_EXTI_ENHANCED
+#define STM32_EXTI_NUM_LINES 34
+#define STM32_EXTI_IMR1_MASK 0x1F800000U
+#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU
+
+/* GPIO attributes.*/
+#define STM32_HAS_GPIOA TRUE
+#define STM32_HAS_GPIOB TRUE
+#define STM32_HAS_GPIOC TRUE
+#define STM32_HAS_GPIOD TRUE
+#define STM32_HAS_GPIOE TRUE
+#define STM32_HAS_GPIOH TRUE
+#define STM32_HAS_GPIOF TRUE
+#define STM32_HAS_GPIOG TRUE
+#define STM32_HAS_GPIOI TRUE
+#define STM32_HAS_GPIOJ TRUE
+#define STM32_HAS_GPIOK TRUE
+#define STM32_GPIO_EN_MASK (RCC_AHB4ENR_GPIOAEN | \
+ RCC_AHB4ENR_GPIOBEN | \
+ RCC_AHB4ENR_GPIOCEN | \
+ RCC_AHB4ENR_GPIODEN | \
+ RCC_AHB4ENR_GPIOEEN | \
+ RCC_AHB4ENR_GPIOFEN | \
+ RCC_AHB4ENR_GPIOGEN | \
+ RCC_AHB4ENR_GPIOHEN | \
+ RCC_AHB4ENR_GPIOIEN | \
+ RCC_AHB4ENR_GPIOJEN | \
+ RCC_AHB4ENR_GPIOKEN)
+
+/* I2C attributes.*/
+#define STM32_HAS_I2C1 TRUE
+#define STM32_HAS_I2C2 TRUE
+#define STM32_HAS_I2C3 TRUE
+#define STM32_HAS_I2C4 TRUE
+
+/* QUADSPI attributes.*/
+#define STM32_HAS_QUADSPI1 TRUE
+#define STM32_HAS_QUADSPI2 FALSE
+
+/* RTC attributes.*/
+#define STM32_HAS_RTC TRUE
+#define STM32_RTC_HAS_SUBSECONDS TRUE
+#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE
+#define STM32_RTC_NUM_ALARMS 2
+#define STM32_RTC_HAS_INTERRUPTS FALSE
+
+/* SDMMC attributes.*/
+#define STM32_HAS_SDMMC1 TRUE
+#define STM32_HAS_SDMMC2 TRUE
+
+/* SPI attributes.*/
+#define STM32_HAS_SPI1 TRUE
+#define STM32_SPI1_SUPPORTS_I2S TRUE
+#define STM32_SPI1_I2S_FULLDUPLEX TRUE
+
+#define STM32_HAS_SPI2 TRUE
+#define STM32_SPI2_SUPPORTS_I2S TRUE
+#define STM32_SPI2_I2S_FULLDUPLEX TRUE
+
+#define STM32_HAS_SPI3 TRUE
+#define STM32_SPI3_SUPPORTS_I2S TRUE
+#define STM32_SPI3_I2S_FULLDUPLEX TRUE
+
+#define STM32_HAS_SPI4 TRUE
+#define STM32_SPI4_SUPPORTS_I2S FALSE
+
+#define STM32_HAS_SPI5 TRUE
+#define STM32_SPI5_SUPPORTS_I2S FALSE
+
+#define STM32_HAS_SPI6 TRUE
+#define STM32_SPI6_SUPPORTS_I2S FALSE
+
+/* TIM attributes.*/
+#define STM32_TIM_MAX_CHANNELS 6
+
+#define STM32_HAS_TIM1 TRUE
+#define STM32_TIM1_IS_32BITS FALSE
+#define STM32_TIM1_CHANNELS 6
+
+#define STM32_HAS_TIM2 TRUE
+#define STM32_TIM2_IS_32BITS TRUE
+#define STM32_TIM2_CHANNELS 4
+
+#define STM32_HAS_TIM3 TRUE
+#define STM32_TIM3_IS_32BITS FALSE
+#define STM32_TIM3_CHANNELS 4
+
+#define STM32_HAS_TIM4 TRUE
+#define STM32_TIM4_IS_32BITS FALSE
+#define STM32_TIM4_CHANNELS 4
+
+#define STM32_HAS_TIM5 TRUE
+#define STM32_TIM5_IS_32BITS TRUE
+#define STM32_TIM5_CHANNELS 4
+
+#define STM32_HAS_TIM6 TRUE
+#define STM32_TIM6_IS_32BITS FALSE
+#define STM32_TIM6_CHANNELS 0
+
+#define STM32_HAS_TIM7 TRUE
+#define STM32_TIM7_IS_32BITS FALSE
+#define STM32_TIM7_CHANNELS 0
+
+#define STM32_HAS_TIM8 TRUE
+#define STM32_TIM8_IS_32BITS FALSE
+#define STM32_TIM8_CHANNELS 6
+
+#define STM32_HAS_TIM12 TRUE
+#define STM32_TIM12_IS_32BITS FALSE
+#define STM32_TIM12_CHANNELS 2
+
+#define STM32_HAS_TIM13 TRUE
+#define STM32_TIM13_IS_32BITS FALSE
+#define STM32_TIM13_CHANNELS 1
+
+#define STM32_HAS_TIM14 TRUE
+#define STM32_TIM14_IS_32BITS FALSE
+#define STM32_TIM14_CHANNELS 1
+
+#define STM32_HAS_TIM15 FALSE
+#define STM32_TIM15_IS_32BITS FALSE
+#define STM32_TIM15_CHANNELS 2
+
+#define STM32_HAS_TIM16 FALSE
+#define STM32_TIM16_IS_32BITS FALSE
+#define STM32_TIM16_CHANNELS 1
+
+#define STM32_HAS_TIM17 FALSE
+#define STM32_TIM17_IS_32BITS FALSE
+#define STM32_TIM17_CHANNELS 1
+
+#define STM32_HAS_TIM9 FALSE
+#define STM32_HAS_TIM10 FALSE
+#define STM32_HAS_TIM11 FALSE
+#define STM32_HAS_TIM18 FALSE
+#define STM32_HAS_TIM19 FALSE
+#define STM32_HAS_TIM20 FALSE
+#define STM32_HAS_TIM21 FALSE
+#define STM32_HAS_TIM22 FALSE
+
+/* USART attributes.*/
+#define STM32_HAS_USART1 TRUE
+#define STM32_HAS_USART2 TRUE
+#define STM32_HAS_USART3 TRUE
+#define STM32_HAS_UART4 TRUE
+#define STM32_HAS_UART5 TRUE
+#define STM32_HAS_USART6 TRUE
+#define STM32_HAS_UART7 TRUE
+#define STM32_HAS_UART8 TRUE
+#define STM32_HAS_LPUART1 TRUE
+
+/* USB attributes.*/
+#define STM32_OTG_STEPPING 2
+#define STM32_HAS_OTG1 TRUE
+#define STM32_OTG1_ENDPOINTS 8
+
+#define STM32_HAS_OTG2 TRUE
+#define STM32_OTG2_ENDPOINTS 8
+
+#define STM32_HAS_USB FALSE
+
+/* IWDG attributes.*/
+#define STM32_HAS_IWDG TRUE
+#define STM32_IWDG_IS_WINDOWED TRUE
+
+/* LTDC attributes.*/
+#define STM32_HAS_LTDC TRUE
+
+/* DMA2D attributes.*/
+#define STM32_HAS_DMA2D TRUE
+
+/* FSMC attributes.*/
+#define STM32_HAS_FSMC TRUE
+#define STM32_FSMC_IS_FMC TRUE
+
+/* CRC attributes.*/
+#define STM32_HAS_CRC TRUE
+#define STM32_CRC_PROGRAMMABLE TRUE
+
+/* DCMI attributes.*/
+#define STM32_HAS_DCMI TRUE
+
+#endif /* defined(STM32H743xx) || defined(STM32H753xx) */
+/** @} */
+
+/*===========================================================================*/
+/* STM32H750xx. */
+/*===========================================================================*/
+#if defined(STM32H750xx) || \
+ defined(__DOXYGEN__)
+
+/* ADC attributes.*/
+#define STM32_HAS_ADC1 TRUE
+#define STM32_HAS_ADC2 TRUE
+#define STM32_HAS_ADC3 FALSE
+#define STM32_HAS_ADC4 FALSE
+
+#define STM32_HAS_SDADC1 FALSE
+#define STM32_HAS_SDADC2 FALSE
+#define STM32_HAS_SDADC3 FALSE
+
+/* CAN attributes.*/
+#define STM32_HAS_FDCAN1 TRUE
+#define STM32_HAS_FDCAN2 TRUE
+
+/* DAC attributes.*/
+#define STM32_HAS_DAC1_CH1 TRUE
+#define STM32_HAS_DAC1_CH2 TRUE
+#define STM32_HAS_DAC2_CH1 FALSE
+#define STM32_HAS_DAC2_CH2 FALSE
+
+/* BDMA attributes.*/
+#define STM32_HAS_BDMA1 TRUE
+
+/* DMA attributes.*/
+#define STM32_ADVANCED_DMA TRUE
+#define STM32_DMA_SUPPORTS_DMAMUX TRUE
+
+#define STM32_HAS_DMA1 TRUE
+#define STM32_HAS_DMA2 TRUE
+
+/* MDMA attributes.*/
+#define STM32_HAS_MDMA1 TRUE
+
+/* ETH attributes.*/
+#define STM32_HAS_ETH TRUE
+
+/* EXTI attributes.*/
+#define STM32_EXTI_ENHANCED
+#define STM32_EXTI_NUM_LINES 34
+#define STM32_EXTI_IMR1_MASK 0x1F800000U
+#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU
+
+/* GPIO attributes.*/
+#define STM32_HAS_GPIOA TRUE
+#define STM32_HAS_GPIOB TRUE
+#define STM32_HAS_GPIOC TRUE
+#define STM32_HAS_GPIOD TRUE
+#define STM32_HAS_GPIOE TRUE
+#define STM32_HAS_GPIOH TRUE
+#define STM32_HAS_GPIOF TRUE
+#define STM32_HAS_GPIOG TRUE
+#define STM32_HAS_GPIOI TRUE
+#define STM32_HAS_GPIOJ TRUE
+#define STM32_HAS_GPIOK TRUE
+#define STM32_GPIO_EN_MASK (RCC_AHB4ENR_GPIOAEN | \
+ RCC_AHB4ENR_GPIOBEN | \
+ RCC_AHB4ENR_GPIOCEN | \
+ RCC_AHB4ENR_GPIODEN | \
+ RCC_AHB4ENR_GPIOEEN | \
+ RCC_AHB4ENR_GPIOFEN | \
+ RCC_AHB4ENR_GPIOGEN | \
+ RCC_AHB4ENR_GPIOHEN | \
+ RCC_AHB4ENR_GPIOIEN | \
+ RCC_AHB4ENR_GPIOJEN | \
+ RCC_AHB4ENR_GPIOKEN)
+
+/* I2C attributes.*/
+#define STM32_HAS_I2C1 TRUE
+#define STM32_HAS_I2C2 TRUE
+#define STM32_HAS_I2C3 TRUE
+#define STM32_HAS_I2C4 TRUE
+
+/* QUADSPI attributes.*/
+#define STM32_HAS_QUADSPI1 TRUE
+#define STM32_HAS_QUADSPI2 FALSE
+
+/* RTC attributes.*/
+#define STM32_HAS_RTC TRUE
+#define STM32_RTC_HAS_SUBSECONDS TRUE
+#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE
+#define STM32_RTC_NUM_ALARMS 2
+#define STM32_RTC_HAS_INTERRUPTS FALSE
+
+/* SDMMC attributes.*/
+#define STM32_HAS_SDMMC1 TRUE
+#define STM32_HAS_SDMMC2 TRUE
+
+/* SPI attributes.*/
+#define STM32_HAS_SPI1 TRUE
+#define STM32_SPI1_SUPPORTS_I2S TRUE
+#define STM32_SPI1_I2S_FULLDUPLEX TRUE
+
+#define STM32_HAS_SPI2 TRUE
+#define STM32_SPI2_SUPPORTS_I2S TRUE
+#define STM32_SPI2_I2S_FULLDUPLEX TRUE
+
+#define STM32_HAS_SPI3 TRUE
+#define STM32_SPI3_SUPPORTS_I2S TRUE
+#define STM32_SPI3_I2S_FULLDUPLEX TRUE
+
+#define STM32_HAS_SPI4 TRUE
+#define STM32_SPI4_SUPPORTS_I2S FALSE
+
+#define STM32_HAS_SPI5 TRUE
+#define STM32_SPI5_SUPPORTS_I2S FALSE
+
+#define STM32_HAS_SPI6 TRUE
+#define STM32_SPI6_SUPPORTS_I2S FALSE
+
+/* TIM attributes.*/
+#define STM32_TIM_MAX_CHANNELS 6
+
+#define STM32_HAS_TIM1 TRUE
+#define STM32_TIM1_IS_32BITS FALSE
+#define STM32_TIM1_CHANNELS 6
+
+#define STM32_HAS_TIM2 TRUE
+#define STM32_TIM2_IS_32BITS TRUE
+#define STM32_TIM2_CHANNELS 4
+
+#define STM32_HAS_TIM3 TRUE
+#define STM32_TIM3_IS_32BITS FALSE
+#define STM32_TIM3_CHANNELS 4
+
+#define STM32_HAS_TIM4 TRUE
+#define STM32_TIM4_IS_32BITS FALSE
+#define STM32_TIM4_CHANNELS 4
+
+#define STM32_HAS_TIM5 TRUE
+#define STM32_TIM5_IS_32BITS TRUE
+#define STM32_TIM5_CHANNELS 4
+
+#define STM32_HAS_TIM6 TRUE
+#define STM32_TIM6_IS_32BITS FALSE
+#define STM32_TIM6_CHANNELS 0
+
+#define STM32_HAS_TIM7 TRUE
+#define STM32_TIM7_IS_32BITS FALSE
+#define STM32_TIM7_CHANNELS 0
+
+#define STM32_HAS_TIM8 TRUE
+#define STM32_TIM8_IS_32BITS FALSE
+#define STM32_TIM8_CHANNELS 6
+
+#define STM32_HAS_TIM12 TRUE
+#define STM32_TIM12_IS_32BITS FALSE
+#define STM32_TIM12_CHANNELS 2
+
+#define STM32_HAS_TIM13 TRUE
+#define STM32_TIM13_IS_32BITS FALSE
+#define STM32_TIM13_CHANNELS 1
+
+#define STM32_HAS_TIM14 TRUE
+#define STM32_TIM14_IS_32BITS FALSE
+#define STM32_TIM14_CHANNELS 1
+
+#define STM32_HAS_TIM15 FALSE
+#define STM32_TIM15_IS_32BITS FALSE
+#define STM32_TIM15_CHANNELS 2
+
+#define STM32_HAS_TIM16 FALSE
+#define STM32_TIM16_IS_32BITS FALSE
+#define STM32_TIM16_CHANNELS 1
+
+#define STM32_HAS_TIM17 FALSE
+#define STM32_TIM17_IS_32BITS FALSE
+#define STM32_TIM17_CHANNELS 1
+
+#define STM32_HAS_TIM9 FALSE
+#define STM32_HAS_TIM10 FALSE
+#define STM32_HAS_TIM11 FALSE
+#define STM32_HAS_TIM18 FALSE
+#define STM32_HAS_TIM19 FALSE
+#define STM32_HAS_TIM20 FALSE
+#define STM32_HAS_TIM21 FALSE
+#define STM32_HAS_TIM22 FALSE
+
+/* USART attributes.*/
+#define STM32_HAS_USART1 TRUE
+#define STM32_HAS_USART2 TRUE
+#define STM32_HAS_USART3 TRUE
+#define STM32_HAS_UART4 TRUE
+#define STM32_HAS_UART5 TRUE
+#define STM32_HAS_USART6 TRUE
+#define STM32_HAS_UART7 TRUE
+#define STM32_HAS_UART8 TRUE
+#define STM32_HAS_LPUART1 TRUE
+
+/* USB attributes.*/
+#define STM32_OTG_STEPPING 2
+#define STM32_HAS_OTG1 TRUE
+#define STM32_OTG1_ENDPOINTS 8
+
+#define STM32_HAS_OTG2 TRUE
+#define STM32_OTG2_ENDPOINTS 8
+
+#define STM32_HAS_USB FALSE
+
+/* IWDG attributes.*/
+#define STM32_HAS_IWDG TRUE
+#define STM32_IWDG_IS_WINDOWED TRUE
+
+/* LTDC attributes.*/
+#define STM32_HAS_LTDC TRUE
+
+/* DMA2D attributes.*/
+#define STM32_HAS_DMA2D TRUE
+
+/* FSMC attributes.*/
+#define STM32_HAS_FSMC TRUE
+#define STM32_FSMC_IS_FMC TRUE
+
+/* CRC attributes.*/
+#define STM32_HAS_CRC TRUE
+#define STM32_CRC_PROGRAMMABLE TRUE
+
+/* DCMI attributes.*/
+#define STM32_HAS_DCMI TRUE
+
+#endif /* defined(STM32H750xx) */
+
+/*===========================================================================*/
+/* STM32H723xx. */
+/*===========================================================================*/
+#if defined(STM32H723xx) || defined(__DOXYGEN__)
+
+/* ADC attributes.*/
+#define STM32_HAS_ADC1 TRUE
+#define STM32_HAS_ADC2 TRUE
+#define STM32_HAS_ADC3 TRUE
+#define STM32_HAS_ADC4 FALSE
+
+#define STM32_HAS_SDADC1 FALSE
+#define STM32_HAS_SDADC2 FALSE
+#define STM32_HAS_SDADC3 FALSE
+
+/* CAN attributes.*/
+#define STM32_HAS_FDCAN1 TRUE
+#define STM32_HAS_FDCAN2 TRUE
+#define STM32_HAS_FDCAN3 FALSE
+#define STM32_FDCAN_FLS_NBR 128U
+#define STM32_FDCAN_FLE_NBR 128U
+#define STM32_FDCAN_RF0_NBR 64U
+#define STM32_FDCAN_RF1_NBR 64U
+#define STM32_FDCAN_RB_NBR 64U
+#define STM32_FDCAN_TEF_NBR 32U
+#define STM32_FDCAN_TB_NBR 32U
+#define STM32_FDCAN_TM_NBR 64U
+
+/* DAC attributes.*/
+#define STM32_HAS_DAC1_CH1 TRUE
+#define STM32_HAS_DAC1_CH2 TRUE
+#define STM32_HAS_DAC2_CH1 FALSE
+#define STM32_HAS_DAC2_CH2 FALSE
+
+/* BDMA attributes.*/
+#define STM32_HAS_BDMA1 TRUE
+
+/* DMA attributes.*/
+#define STM32_ADVANCED_DMA TRUE
+#define STM32_DMA_SUPPORTS_DMAMUX TRUE
+
+#define STM32_HAS_DMA1 TRUE
+#define STM32_HAS_DMA2 TRUE
+
+/* MDMA attributes.*/
+#define STM32_HAS_MDMA1 TRUE
+
+/* ETH attributes.*/
+#define STM32_HAS_ETH TRUE
+
+/* EXTI attributes.*/
+#define STM32_EXTI_ENHANCED
+#define STM32_EXTI_NUM_LINES 34
+#define STM32_EXTI_IMR1_MASK 0x1F800000U
+#define STM32_EXTI_IMR2_MASK 0xFFFFFFFCU
+
+/* GPIO attributes.*/
+#define STM32_HAS_GPIOA TRUE
+#define STM32_HAS_GPIOB TRUE
+#define STM32_HAS_GPIOC TRUE
+#define STM32_HAS_GPIOD TRUE
+#define STM32_HAS_GPIOE TRUE
+#define STM32_HAS_GPIOH TRUE
+#define STM32_HAS_GPIOF TRUE
+#define STM32_HAS_GPIOG TRUE
+#define STM32_HAS_GPIOI FALSE
+#define STM32_HAS_GPIOJ TRUE
+#define STM32_HAS_GPIOK TRUE
+#define STM32_GPIO_EN_MASK (RCC_AHB4ENR_GPIOAEN | \
+ RCC_AHB4ENR_GPIOBEN | \
+ RCC_AHB4ENR_GPIOCEN | \
+ RCC_AHB4ENR_GPIODEN | \
+ RCC_AHB4ENR_GPIOEEN | \
+ RCC_AHB4ENR_GPIOFEN | \
+ RCC_AHB4ENR_GPIOGEN | \
+ RCC_AHB4ENR_GPIOHEN | \
+ RCC_AHB4ENR_GPIOJEN | \
+ RCC_AHB4ENR_GPIOKEN)
+
+/* I2C attributes.*/
+#define STM32_HAS_I2C1 TRUE
+#define STM32_HAS_I2C2 TRUE
+#define STM32_HAS_I2C3 TRUE
+#define STM32_HAS_I2C4 TRUE
+#define STM32_HAS_I2C5 TRUE
+
+/* QUADSPI attributes.*/
+#define STM32_HAS_QUADSPI1 FALSE
+#define STM32_HAS_QUADSPI2 FALSE
+
+/* OCTOSPI attributes.*/
+#define STM32_HAS_OCTOSPI1 TRUE
+#define STM32_HAS_OCTOSPI2 TRUE
+
+/* RTC attributes.*/
+#define STM32_HAS_RTC TRUE
+#define STM32_RTC_HAS_SUBSECONDS TRUE
+#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE
+#define STM32_RTC_NUM_ALARMS 2
+#define STM32_RTC_HAS_INTERRUPTS FALSE
+
+/* SDMMC attributes.*/
+#define STM32_HAS_SDMMC1 TRUE
+#define STM32_HAS_SDMMC2 TRUE
+
+/* SPI attributes.*/
+#define STM32_HAS_SPI1 TRUE
+#define STM32_SPI1_SUPPORTS_I2S TRUE
+#define STM32_SPI1_I2S_FULLDUPLEX TRUE
+
+#define STM32_HAS_SPI2 TRUE
+#define STM32_SPI2_SUPPORTS_I2S TRUE
+#define STM32_SPI2_I2S_FULLDUPLEX TRUE
+
+#define STM32_HAS_SPI3 TRUE
+#define STM32_SPI3_SUPPORTS_I2S TRUE
+#define STM32_SPI3_I2S_FULLDUPLEX TRUE
+
+#define STM32_HAS_SPI4 TRUE
+#define STM32_SPI4_SUPPORTS_I2S FALSE
+
+#define STM32_HAS_SPI5 TRUE
+#define STM32_SPI5_SUPPORTS_I2S FALSE
+
+#define STM32_HAS_SPI6 TRUE
+#define STM32_SPI6_SUPPORTS_I2S TRUE
+#define STM32_SPI6_I2S_FULLDUPLEX TRUE
+
+/* TIM attributes.*/
+#define STM32_TIM_MAX_CHANNELS 6
+
+#define STM32_HAS_TIM1 TRUE
+#define STM32_TIM1_IS_32BITS FALSE
+#define STM32_TIM1_CHANNELS 6
+
+#define STM32_HAS_TIM2 TRUE
+#define STM32_TIM2_IS_32BITS TRUE
+#define STM32_TIM2_CHANNELS 4
+
+#define STM32_HAS_TIM3 TRUE
+#define STM32_TIM3_IS_32BITS FALSE
+#define STM32_TIM3_CHANNELS 4
+
+#define STM32_HAS_TIM4 TRUE
+#define STM32_TIM4_IS_32BITS FALSE
+#define STM32_TIM4_CHANNELS 4
+
+#define STM32_HAS_TIM5 TRUE
+#define STM32_TIM5_IS_32BITS TRUE
+#define STM32_TIM5_CHANNELS 4
+
+#define STM32_HAS_TIM6 TRUE
+#define STM32_TIM6_IS_32BITS FALSE
+#define STM32_TIM6_CHANNELS 0
+
+#define STM32_HAS_TIM7 TRUE
+#define STM32_TIM7_IS_32BITS FALSE
+#define STM32_TIM7_CHANNELS 0
+
+#define STM32_HAS_TIM8 TRUE
+#define STM32_TIM8_IS_32BITS FALSE
+#define STM32_TIM8_CHANNELS 6
+
+#define STM32_HAS_TIM12 TRUE
+#define STM32_TIM12_IS_32BITS FALSE
+#define STM32_TIM12_CHANNELS 2
+
+#define STM32_HAS_TIM13 TRUE
+#define STM32_TIM13_IS_32BITS FALSE
+#define STM32_TIM13_CHANNELS 1
+
+#define STM32_HAS_TIM14 TRUE
+#define STM32_TIM14_IS_32BITS FALSE
+#define STM32_TIM14_CHANNELS 1
+
+#define STM32_HAS_TIM15 TRUE
+#define STM32_TIM15_IS_32BITS FALSE
+#define STM32_TIM15_CHANNELS 2
+
+#define STM32_HAS_TIM16 TRUE
+#define STM32_TIM16_IS_32BITS FALSE
+#define STM32_TIM16_CHANNELS 1
+
+#define STM32_HAS_TIM17 TRUE
+#define STM32_TIM17_IS_32BITS FALSE
+#define STM32_TIM17_CHANNELS 1
+
+#define STM32_HAS_TIM23 TRUE
+#define STM32_TIM23_IS_32BITS TRUE
+#define STM32_TIM23_CHANNELS 4
+
+#define STM32_HAS_TIM24 TRUE
+#define STM32_TIM24_IS_32BITS TRUE
+#define STM32_TIM24_CHANNELS 4
+
+#define STM32_HAS_TIM9 FALSE
+#define STM32_HAS_TIM10 FALSE
+#define STM32_HAS_TIM11 FALSE
+#define STM32_HAS_TIM18 FALSE
+#define STM32_HAS_TIM19 FALSE
+#define STM32_HAS_TIM20 FALSE
+#define STM32_HAS_TIM21 FALSE
+#define STM32_HAS_TIM22 FALSE
+
+/* USART attributes.*/
+#define STM32_HAS_USART1 TRUE
+#define STM32_HAS_USART2 TRUE
+#define STM32_HAS_USART3 TRUE
+#define STM32_HAS_UART4 TRUE
+#define STM32_HAS_UART5 TRUE
+#define STM32_HAS_USART6 TRUE
+#define STM32_HAS_UART7 TRUE
+#define STM32_HAS_UART8 TRUE
+#define STM32_HAS_UART9 TRUE
+#define STM32_HAS_USART10 TRUE
+#define STM32_HAS_LPUART1 TRUE
+
+/* USB attributes.*/
+#define STM32_OTG_STEPPING 2
+#define STM32_HAS_OTG1 TRUE
+#define STM32_OTG1_ENDPOINTS 8
+
+#define STM32_HAS_OTG2 TRUE
+#define STM32_OTG2_ENDPOINTS 8
+
+#define STM32_HAS_USB FALSE
+
+/* IWDG attributes.*/
+#define STM32_HAS_IWDG TRUE
+#define STM32_IWDG_IS_WINDOWED TRUE
+
+/* LTDC attributes.*/
+#define STM32_HAS_LTDC TRUE
+
+/* DMA2D attributes.*/
+#define STM32_HAS_DMA2D TRUE
+
+/* FSMC attributes.*/
+#define STM32_HAS_FSMC TRUE
+#define STM32_FSMC_IS_FMC TRUE
+
+/* CRC attributes.*/
+#define STM32_HAS_CRC TRUE
+#define STM32_CRC_PROGRAMMABLE TRUE
+
+/* DCMI attributes.*/
+#define STM32_HAS_DCMI TRUE
+
+#endif /* defined(STM32H723xx) */
+/** @} */
+
+#endif /* STM32_REGISTRY_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.c
new file mode 100644
index 0000000..6ea46f8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.c
@@ -0,0 +1,542 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_efl_lld.c
+ * @brief STM32L4xx Embedded Flash subsystem low level driver source.
+ *
+ * @addtogroup HAL_EFL
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+
+#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#define STM32_FLASH_SECTOR_SIZE 2048U
+#define STM32_FLASH_LINE_SIZE 8U
+#define STM32_FLASH_LINE_MASK (STM32_FLASH_LINE_SIZE - 1U)
+
+#define FLASH_PDKEY1 0x04152637U
+#define FLASH_PDKEY2 0xFAFBFCFDU
+
+#define FLASH_KEY1 0x45670123U
+#define FLASH_KEY2 0xCDEF89ABU
+
+#define FLASH_OPTKEY1 0x08192A3BU
+#define FLASH_OPTKEY2 0x4C5D6E7FU
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief EFL1 driver identifier.
+ */
+EFlashDriver EFLD1;
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+static const flash_descriptor_t efl_lld_descriptor = {
+ .attributes = FLASH_ATTR_ERASED_IS_ONE |
+ FLASH_ATTR_MEMORY_MAPPED |
+ FLASH_ATTR_ECC_CAPABLE |
+ FLASH_ATTR_ECC_ZERO_LINE_CAPABLE,
+ .page_size = STM32_FLASH_LINE_SIZE,
+ .sectors_count = STM32_FLASH_NUMBER_OF_BANKS *
+ STM32_FLASH_SECTORS_PER_BANK,
+ .sectors = NULL,
+ .sectors_size = STM32_FLASH_SECTOR_SIZE,
+ .address = (uint8_t *)0x08000000U,
+ .size = STM32_FLASH_NUMBER_OF_BANKS *
+ STM32_FLASH_SECTORS_PER_BANK *
+ STM32_FLASH_SECTOR_SIZE
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static inline void stm32_flash_lock(EFlashDriver *eflp) {
+
+ eflp->flash->CR |= FLASH_CR_LOCK;
+}
+
+static inline void stm32_flash_unlock(EFlashDriver *eflp) {
+
+ eflp->flash->KEYR |= FLASH_KEY1;
+ eflp->flash->KEYR |= FLASH_KEY2;
+}
+
+static inline void stm32_flash_enable_pgm(EFlashDriver *eflp) {
+
+ eflp->flash->CR |= FLASH_CR_PG;
+}
+
+static inline void stm32_flash_disable_pgm(EFlashDriver *eflp) {
+
+ eflp->flash->CR &= ~FLASH_CR_PG;
+}
+
+static inline void stm32_flash_clear_status(EFlashDriver *eflp) {
+
+ eflp->flash->SR = 0x0000FFFFU;
+}
+
+static inline void stm32_flash_wait_busy(EFlashDriver *eflp) {
+
+ /* Wait for busy bit clear.*/
+ while ((eflp->flash->SR & FLASH_SR_BSY) != 0U) {
+ }
+}
+
+static inline flash_error_t stm32_flash_check_errors(EFlashDriver *eflp) {
+ uint32_t sr = eflp->flash->SR;
+
+ /* Clearing error conditions.*/
+ eflp->flash->SR = sr & 0x0000FFFFU;
+
+ /* Some errors are only caught by assertion.*/
+ osalDbgAssert((sr & (FLASH_SR_FASTERR |
+ FLASH_SR_MISERR |
+ FLASH_SR_SIZERR)) == 0U, "unexpected flash error");
+
+ /* Decoding relevant errors.*/
+ if ((sr & FLASH_SR_WRPERR) != 0U) {
+ return FLASH_ERROR_HW_FAILURE;
+ }
+
+ if ((sr & (FLASH_SR_PGAERR | FLASH_SR_PROGERR | FLASH_SR_OPERR)) != 0U) {
+ return eflp->state == FLASH_PGM ? FLASH_ERROR_PROGRAM : FLASH_ERROR_ERASE;
+ }
+
+ return FLASH_NO_ERROR;
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level Embedded Flash driver initialization.
+ *
+ * @notapi
+ */
+void efl_lld_init(void) {
+
+ /* Driver initialization.*/
+ eflObjectInit(&EFLD1);
+ EFLD1.flash = FLASH;
+}
+
+/**
+ * @brief Configures and activates the Embedded Flash peripheral.
+ *
+ * @param[in] eflp pointer to a @p EFlashDriver structure
+ *
+ * @notapi
+ */
+void efl_lld_start(EFlashDriver *eflp) {
+
+ stm32_flash_unlock(eflp);
+ FLASH->CR = 0x00000000U;
+}
+
+/**
+ * @brief Deactivates the Embedded Flash peripheral.
+ *
+ * @param[in] eflp pointer to a @p EFlashDriver structure
+ *
+ * @notapi
+ */
+void efl_lld_stop(EFlashDriver *eflp) {
+
+ stm32_flash_lock(eflp);
+}
+
+/**
+ * @brief Gets the flash descriptor structure.
+ *
+ * @param[in] ip pointer to a @p EFlashDriver instance
+ * @return A flash device descriptor.
+ *
+ * @notapi
+ */
+const flash_descriptor_t *efl_lld_get_descriptor(void *instance) {
+
+ (void)instance;
+
+ return &efl_lld_descriptor;
+}
+
+/**
+ * @brief Read operation.
+ *
+ * @param[in] ip pointer to a @p EFlashDriver instance
+ * @param[in] offset flash offset
+ * @param[in] n number of bytes to be read
+ * @param[out] rp pointer to the data buffer
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_READ if the read operation failed.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @notapi
+ */
+flash_error_t efl_lld_read(void *instance, flash_offset_t offset,
+ size_t n, uint8_t *rp) {
+ EFlashDriver *devp = (EFlashDriver *)instance;
+ flash_error_t err = FLASH_NO_ERROR;
+
+ osalDbgCheck((instance != NULL) && (rp != NULL) && (n > 0U));
+ osalDbgCheck((size_t)offset + n <= (size_t)efl_lld_descriptor.size);
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ /* No reading while erasing.*/
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* FLASH_READY state while the operation is performed.*/
+ devp->state = FLASH_READ;
+
+ /* Clearing error status bits.*/
+ stm32_flash_clear_status(devp);
+
+ /* Actual read implementation.*/
+ memcpy((void *)rp, (const void *)efl_lld_descriptor.address + offset, n);
+
+ /* Checking for errors after reading.*/
+ if ((devp->flash->SR & FLASH_SR_RDERR) != 0U) {
+ err = FLASH_ERROR_READ;
+ }
+
+ /* Ready state again.*/
+ devp->state = FLASH_READY;
+
+ return err;
+
+}
+
+/**
+ * @brief Program operation.
+ * @note The device supports ECC, it is only possible to write erased
+ * pages once except when writing all zeroes.
+ *
+ * @param[in] ip pointer to a @p EFlashDriver instance
+ * @param[in] offset flash offset
+ * @param[in] n number of bytes to be programmed
+ * @param[in] pp pointer to the data buffer
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_PROGRAM if the program operation failed.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @notapi
+ */
+flash_error_t efl_lld_program(void *instance, flash_offset_t offset,
+ size_t n, const uint8_t *pp) {
+ EFlashDriver *devp = (EFlashDriver *)instance;
+ flash_error_t err = FLASH_NO_ERROR;
+
+ osalDbgCheck((instance != NULL) && (pp != NULL) && (n > 0U));
+ osalDbgCheck((size_t)offset + n <= (size_t)efl_lld_descriptor.size);
+
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ /* No programming while erasing.*/
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* FLASH_PGM state while the operation is performed.*/
+ devp->state = FLASH_PGM;
+
+ /* Clearing error status bits.*/
+ stm32_flash_clear_status(devp);
+
+ /* Enabling PGM mode in the controller.*/
+ stm32_flash_enable_pgm(devp);
+
+ /* Actual program implementation.*/
+ while (n > 0U) {
+ volatile uint32_t *address;
+
+ union {
+ uint32_t w[STM32_FLASH_LINE_SIZE / sizeof (uint32_t)];
+ uint8_t b[STM32_FLASH_LINE_SIZE / sizeof (uint8_t)];
+ } line;
+
+ /* Unwritten bytes are initialized to all ones.*/
+ line.w[0] = 0xFFFFFFFFU;
+ line.w[1] = 0xFFFFFFFFU;
+
+ /* Programming address aligned to flash lines.*/
+ address = (volatile uint32_t *)(efl_lld_descriptor.address +
+ (offset & ~STM32_FLASH_LINE_MASK));
+
+ /* Copying data inside the prepared line.*/
+ do {
+ line.b[offset & STM32_FLASH_LINE_MASK] = *pp;
+ offset++;
+ n--;
+ pp++;
+ }
+ while ((n > 0U) & ((offset & STM32_FLASH_LINE_MASK) != 0U));
+
+ /* Programming line.*/
+ address[0] = line.w[0];
+ address[1] = line.w[1];
+ stm32_flash_wait_busy(devp);
+ err = stm32_flash_check_errors(devp);
+ if (err != FLASH_NO_ERROR) {
+ break;
+ }
+ }
+
+ /* Disabling PGM mode in the controller.*/
+ stm32_flash_disable_pgm(devp);
+
+ /* Ready state again.*/
+ devp->state = FLASH_READY;
+
+ return err;
+}
+
+/**
+ * @brief Starts a whole-device erase operation.
+ * @note This function only erases bank 2 if it is present. Bank 1 is not
+ * touched because it is where the program is running on.
+ * Pages on bank 1 can be individually erased.
+ *
+ * @param[in] ip pointer to a @p EFlashDriver instance
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @notapi
+ */
+flash_error_t efl_lld_start_erase_all(void *instance) {
+ EFlashDriver *devp = (EFlashDriver *)instance;
+
+ osalDbgCheck(instance != NULL);
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ /* No erasing while erasing.*/
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* FLASH_PGM state while the operation is performed.*/
+ devp->state = FLASH_ERASE;
+
+ /* Clearing error status bits.*/
+ stm32_flash_clear_status(devp);
+
+#if defined(FLASH_CR_MER2)
+ devp->flash->CR |= FLASH_CR_MER2;
+ devp->flash->CR |= FLASH_CR_STRT;
+#endif
+
+ return FLASH_NO_ERROR;
+}
+
+/**
+ * @brief Starts an sector erase operation.
+ *
+ * @param[in] ip pointer to a @p EFlashDriver instance
+ * @param[in] sector sector to be erased
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @notapi
+ */
+flash_error_t efl_lld_start_erase_sector(void *instance,
+ flash_sector_t sector) {
+ EFlashDriver *devp = (EFlashDriver *)instance;
+
+ osalDbgCheck(instance != NULL);
+ osalDbgCheck(sector < efl_lld_descriptor.sectors_count);
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ /* No erasing while erasing.*/
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* FLASH_PGM state while the operation is performed.*/
+ devp->state = FLASH_ERASE;
+
+ /* Clearing error status bits.*/
+ stm32_flash_clear_status(devp);
+
+ /* Enable page erase.*/
+ devp->flash->CR |= FLASH_CR_PER;
+
+#if defined(FLASH_CR_BKER)
+ /* Bank selection.*/
+ if (sector < STM32_FLASH_SECTORS_PER_BANK) {
+ /* First bank.*/
+ devp->flash->CR &= ~FLASH_CR_BKER;
+ }
+ else {
+ /* Second bank.*/
+ devp->flash->CR |= FLASH_CR_BKER;
+ }
+#endif
+
+ /* Mask off the page selection bits.*/
+ devp->flash->CR &= ~FLASH_CR_PNB;
+
+ /* Set the page selection bits.*/
+ devp->flash->CR |= sector << FLASH_CR_PNB_Pos;
+
+ /* Start the erase.*/
+ devp->flash->CR |= FLASH_CR_STRT;
+
+ return FLASH_NO_ERROR;
+}
+
+/**
+ * @brief Queries the driver for erase operation progress.
+ *
+ * @param[in] ip pointer to a @p EFlashDriver instance
+ * @param[out] msec recommended time, in milliseconds, that
+ * should be spent before calling this
+ * function again, can be @p NULL
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_ERASE if the erase operation failed.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @api
+ */
+flash_error_t efl_lld_query_erase(void *instance, uint32_t *msec) {
+ EFlashDriver *devp = (EFlashDriver *)instance;
+ flash_error_t err;
+
+ /* If there is an erase in progress then the device must be checked.*/
+ if (devp->state == FLASH_ERASE) {
+
+ /* Checking for operation in progress.*/
+ if ((devp->flash->SR & FLASH_SR_BSY) == 0U) {
+
+ /* Disabling the various erase control bits.*/
+ devp->flash->CR &= ~(FLASH_CR_MER1 |
+#if defined(FLASH_CR_MER2)
+ FLASH_CR_MER2 |
+#endif
+ FLASH_CR_PER);
+
+ /* No operation in progress, checking for errors.*/
+ err = stm32_flash_check_errors(devp);
+
+ /* Back to ready state.*/
+ devp->state = FLASH_READY;
+ }
+ else {
+ /* Recommended time before polling again, this is a simplified
+ implementation.*/
+ if (msec != NULL) {
+ *msec = (uint32_t)STM32_FLASH_WAIT_TIME_MS;
+ }
+
+ err = FLASH_BUSY_ERASING;
+ }
+ }
+ else {
+ err = FLASH_NO_ERROR;
+ }
+
+ return err;
+}
+
+/**
+ * @brief Returns the erase state of a sector.
+ *
+ * @param[in] ip pointer to a @p EFlashDriver instance
+ * @param[in] sector sector to be verified
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if the sector is erased.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_VERIFY if the verify operation failed.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @notapi
+ */
+flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector) {
+ EFlashDriver *devp = (EFlashDriver *)instance;
+ uint32_t *address;
+ flash_error_t err = FLASH_NO_ERROR;
+ unsigned i;
+
+ osalDbgCheck(instance != NULL);
+ osalDbgCheck(sector < efl_lld_descriptor.sectors_count);
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ /* No verifying while erasing.*/
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* Address of the sector.*/
+ address = (uint32_t *)(efl_lld_descriptor.address +
+ flashGetSectorOffset(getBaseFlash(devp), sector));
+
+ /* FLASH_READY state while the operation is performed.*/
+ devp->state = FLASH_READ;
+
+ /* Scanning the sector space.*/
+ for (i = 0U; i < STM32_FLASH_SECTOR_SIZE / sizeof(uint32_t); i++) {
+ if (*address != 0xFFFFFFFFU) {
+ err = FLASH_ERROR_VERIFY;
+ break;
+ }
+ address++;
+ }
+
+ /* Ready state again.*/
+ devp->state = FLASH_READY;
+
+ return err;
+}
+
+#endif /* HAL_USE_EFL == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.h
new file mode 100644
index 0000000..774e8ae
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.h
@@ -0,0 +1,116 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_efl_lld.h
+ * @brief STM32L4xx Embedded Flash subsystem low level driver header.
+ *
+ * @addtogroup HAL_EFL
+ * @{
+ */
+
+#ifndef HAL_EFL_LLD_H
+#define HAL_EFL_LLD_H
+
+#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name STM32L4xx configuration options
+ * @{
+ */
+/**
+ * @brief Suggested wait time during erase operations polling.
+ */
+#if !defined(STM32_FLASH_WAIT_TIME_MS) || defined(__DOXYGEN__)
+#define STM32_FLASH_WAIT_TIME_MS 5
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !defined(STM32_FLASH_NUMBER_OF_BANKS)
+#error "STM32_FLASH_NUMBER_OF_BANKS not defined in registry"
+#endif
+
+#if !defined(STM32_FLASH_SECTORS_PER_BANK)
+#error "STM32_FLASH_SECTORS_PER_BANK not defined in registry"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the embedded flash driver structure.
+ */
+#define efl_lld_driver_fields \
+ /* Flash registers.*/ \
+ FLASH_TypeDef *flash
+
+/**
+ * @brief Low level fields of the embedded flash configuration structure.
+ */
+#define efl_lld_config_fields \
+ /* Dummy configuration, it is not needed.*/ \
+ uint32_t dummy
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern EFlashDriver EFLD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void efl_lld_init(void);
+ void efl_lld_start(EFlashDriver *eflp);
+ void efl_lld_stop(EFlashDriver *eflp);
+ const flash_descriptor_t *efl_lld_get_descriptor(void *instance);
+ flash_error_t efl_lld_read(void *instance, flash_offset_t offset,
+ size_t n, uint8_t *rp);
+ flash_error_t efl_lld_program(void *instance, flash_offset_t offset,
+ size_t n, const uint8_t *pp);
+ flash_error_t efl_lld_start_erase_all(void *instance);
+ flash_error_t efl_lld_start_erase_sector(void *instance,
+ flash_sector_t sector);
+ flash_error_t efl_lld_query_erase(void *instance, uint32_t *msec);
+ flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_EFL == TRUE */
+
+#endif /* HAL_EFL_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/hal_lld.c b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/hal_lld.c
new file mode 100644
index 0000000..23e9d84
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/hal_lld.c
@@ -0,0 +1,392 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32L4xx/hal_lld.c
+ * @brief STM32L4xx HAL subsystem low level driver source.
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#include "hal.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief CMSIS system core clock variable.
+ * @note It is declared in system_stm32f7xx.h.
+ */
+uint32_t SystemCoreClock = STM32_HCLK;
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes the backup domain.
+ * @note WARNING! Changing RTC clock source impossible without resetting
+ * of the whole BKP domain.
+ */
+static void hal_lld_backup_domain_init(void) {
+
+ /* Reset BKP domain if different clock source selected.*/
+ if ((RCC->BDCR & STM32_RTCSEL_MASK) != STM32_RTCSEL) {
+ /* Backup domain reset.*/
+ RCC->BDCR = RCC_BDCR_BDRST;
+ RCC->BDCR = 0;
+ }
+
+#if STM32_LSE_ENABLED
+ /* LSE activation.*/
+#if defined(STM32_LSE_BYPASS)
+ /* LSE Bypass.*/
+ RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP;
+#else
+ /* No LSE Bypass.*/
+ RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON;
+#endif
+ while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0)
+ ; /* Wait until LSE is stable. */
+#endif
+
+#if STM32_MSIPLL_ENABLED
+ /* MSI PLL activation depends on LSE. Reactivating and checking for
+ MSI stability.*/
+ RCC->CR |= RCC_CR_MSIPLLEN;
+ while ((RCC->CR & RCC_CR_MSIRDY) == 0)
+ ; /* Wait until MSI is stable. */
+#endif
+
+#if HAL_USE_RTC
+ /* If the backup domain hasn't been initialized yet then proceed with
+ initialization.*/
+ if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) {
+ /* Selects clock source.*/
+ RCC->BDCR |= STM32_RTCSEL;
+
+ /* RTC clock enabled.*/
+ RCC->BDCR |= RCC_BDCR_RTCEN;
+ }
+#endif /* HAL_USE_RTC */
+
+ /* Low speed output mode.*/
+ RCC->BDCR |= STM32_LSCOSEL;
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level HAL driver initialization.
+ *
+ * @notapi
+ */
+void hal_lld_init(void) {
+
+ /* Reset of all peripherals.
+ Note, GPIOs are not reset because initialized before this point in
+ board files.*/
+ rccResetAHB1(~0);
+ rccResetAHB2(~STM32_GPIO_EN_MASK);
+ rccResetAHB3(~0);
+ rccResetAPB1R1(~RCC_APB1RSTR1_PWRRST);
+ rccResetAPB1R2(~0);
+ rccResetAPB2(~0);
+
+ /* PWR clock enabled.*/
+ rccEnablePWRInterface(true);
+
+ /* Initializes the backup domain.*/
+ hal_lld_backup_domain_init();
+
+ /* DMA subsystems initialization.*/
+#if defined(STM32_DMA_REQUIRED)
+ dmaInit();
+#endif
+
+ /* IRQ subsystem initialization.*/
+ irqInit();
+
+ /* Programmable voltage detector enable.*/
+#if STM32_PVD_ENABLE
+ PWR->CR2 = PWR_CR2_PVDE | (STM32_PLS & STM32_PLS_MASK);
+#else
+ PWR->CR2 = 0;
+#endif /* STM32_PVD_ENABLE */
+
+ /* Enabling independent VDDUSB.*/
+#if HAL_USE_USB
+ PWR->CR2 |= PWR_CR2_USV;
+#endif /* HAL_USE_USB */
+
+ /* Enabling independent VDDIO2 required by GPIOG.*/
+#if STM32_HAS_GPIOG
+ PWR->CR2 |= PWR_CR2_IOSV;
+#endif /* STM32_HAS_GPIOG */
+}
+
+/**
+ * @brief STM32L4xx clocks and PLL initialization.
+ * @note All the involved constants come from the file @p board.h.
+ * @note This function should be invoked just after the system reset.
+ *
+ * @special
+ */
+void stm32_clock_init(void) {
+
+#if !STM32_NO_INIT
+ /* PWR clock enable.*/
+#if defined(HAL_USE_RTC) && defined(RCC_APB1ENR1_RTCAPBEN)
+ RCC->APB1ENR1 = RCC_APB1ENR1_PWREN | RCC_APB1ENR1_RTCAPBEN;
+#else
+ RCC->APB1ENR1 = RCC_APB1ENR1_PWREN;
+#endif
+
+ /* Initial clocks setup and wait for MSI stabilization, the MSI clock is
+ always enabled because it is the fall back clock when PLL the fails.
+ Trim fields are not altered from reset values.*/
+
+ /* MSIRANGE can be set only when MSI is OFF or READY.*/
+ RCC->CR = RCC_CR_MSION;
+ while ((RCC->CR & RCC_CR_MSIRDY) == 0)
+ ; /* Wait until MSI is stable. */
+
+ /* Clocking from MSI, in case MSI was not the default source.*/
+ RCC->CFGR = 0;
+ while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI)
+ ; /* Wait until MSI is selected. */
+
+ /* Core voltage setup.*/
+ PWR->CR1 = STM32_VOS;
+ while ((PWR->SR2 & PWR_SR2_VOSF) != 0) /* Wait until regulator is */
+ ; /* stable. */
+
+#if STM32_HSI16_ENABLED
+ /* HSI activation.*/
+ RCC->CR |= RCC_CR_HSION;
+ while ((RCC->CR & RCC_CR_HSIRDY) == 0)
+ ; /* Wait until HSI16 is stable. */
+#endif
+
+#if STM32_CLOCK_HAS_HSI48
+#if STM32_HSI48_ENABLED
+ /* HSI activation.*/
+ RCC->CRRCR |= RCC_CRRCR_HSI48ON;
+ while ((RCC->CRRCR & RCC_CRRCR_HSI48RDY) == 0)
+ ; /* Wait until HSI48 is stable. */
+#endif
+#endif
+
+#if STM32_HSE_ENABLED
+#if defined(STM32_HSE_BYPASS)
+ /* HSE Bypass.*/
+ RCC->CR |= RCC_CR_HSEON | RCC_CR_HSEBYP;
+#endif
+ /* HSE activation.*/
+ RCC->CR |= RCC_CR_HSEON;
+ while ((RCC->CR & RCC_CR_HSERDY) == 0)
+ ; /* Wait until HSE is stable. */
+#endif
+
+#if STM32_LSI_ENABLED
+ /* LSI activation.*/
+ RCC->CSR |= RCC_CSR_LSION;
+ while ((RCC->CSR & RCC_CSR_LSIRDY) == 0)
+ ; /* Wait until LSI is stable. */
+#endif
+
+ /* Backup domain access enabled and left open.*/
+ PWR->CR1 |= PWR_CR1_DBP;
+
+#if STM32_LSE_ENABLED
+ /* LSE activation.*/
+#if defined(STM32_LSE_BYPASS)
+ /* LSE Bypass.*/
+ RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON | RCC_BDCR_LSEBYP;
+#else
+ /* No LSE Bypass.*/
+ RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON;
+#endif
+ while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0)
+ ; /* Wait until LSE is stable. */
+#endif
+
+ /* Flash setup for selected MSI speed setting.*/
+ FLASH->ACR = FLASH_ACR_DCEN | FLASH_ACR_ICEN | FLASH_ACR_PRFTEN |
+ STM32_MSI_FLASHBITS;
+
+ /* Changing MSIRANGE to configured value.*/
+ RCC->CR |= STM32_MSIRANGE;
+
+ /* Switching from MSISRANGE to MSIRANGE.*/
+ RCC->CR |= RCC_CR_MSIRGSEL;
+ while ((RCC->CR & RCC_CR_MSIRDY) == 0)
+ ;
+
+ /* MSI is configured SYSCLK source so wait for it to be stable as well.*/
+ while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI)
+ ;
+
+#if STM32_MSIPLL_ENABLED
+ /* MSI PLL (to LSE) activation */
+ RCC->CR |= RCC_CR_MSIPLLEN;
+#endif
+
+ /* Updating MSISRANGE value. MSISRANGE can be set only when MSIRGSEL is high.
+ This range is used exiting the Standby mode until MSIRGSEL is set.*/
+ RCC->CSR |= STM32_MSISRANGE;
+
+#if STM32_ACTIVATE_PLL || STM32_ACTIVATE_PLLSAI1 || STM32_ACTIVATE_PLLSAI2
+ /* PLLM and PLLSRC are common to all PLLs.*/
+#if defined(STM32L496xx) || defined(STM32L4A6xx)
+ RCC->PLLCFGR = STM32_PLLPDIV | STM32_PLLR |
+ STM32_PLLREN | STM32_PLLQ |
+ STM32_PLLQEN | STM32_PLLP |
+ STM32_PLLPEN | STM32_PLLN |
+ STM32_PLLM | STM32_PLLSRC;
+#else
+ RCC->PLLCFGR = STM32_PLLR | STM32_PLLREN |
+ STM32_PLLQ | STM32_PLLQEN |
+ STM32_PLLP | STM32_PLLPEN |
+ STM32_PLLN | STM32_PLLM |
+ STM32_PLLSRC;
+#endif
+#endif
+
+#if STM32_ACTIVATE_PLL
+ /* PLL activation.*/
+ RCC->CR |= RCC_CR_PLLON;
+
+ /* Waiting for PLL lock.*/
+ while ((RCC->CR & RCC_CR_PLLRDY) == 0)
+ ;
+#endif
+
+#if STM32_ACTIVATE_PLLSAI1
+ /* PLLSAI1 activation.*/
+#if defined(STM32L496xx) || defined(STM32L4A6xx)
+ RCC->PLLSAI1CFGR = STM32_PLLSAI1PDIV | STM32_PLLSAI1R |
+ STM32_PLLSAI1REN | STM32_PLLSAI1Q |
+ STM32_PLLSAI1QEN | STM32_PLLSAI1P |
+ STM32_PLLSAI1PEN | STM32_PLLSAI1N;
+#else
+ RCC->PLLSAI1CFGR = STM32_PLLSAI1R | STM32_PLLSAI1REN |
+ STM32_PLLSAI1Q | STM32_PLLSAI1QEN |
+ STM32_PLLSAI1P | STM32_PLLSAI1PEN |
+ STM32_PLLSAI1N;
+#endif
+ RCC->CR |= RCC_CR_PLLSAI1ON;
+
+ /* Waiting for PLL lock.*/
+ while ((RCC->CR & RCC_CR_PLLSAI1RDY) == 0)
+ ;
+#endif
+
+#if STM32_ACTIVATE_PLLSAI2
+ /* PLLSAI2 activation.*/
+#if defined(STM32L496xx) || defined(STM32L4A6xx)
+ RCC->PLLSAI2CFGR = STM32_PLLSAI2PDIV | STM32_PLLSAI2R |
+ STM32_PLLSAI2REN | STM32_PLLSAI2P |
+ STM32_PLLSAI2PEN | STM32_PLLSAI2N;
+#else
+ RCC->PLLSAI2CFGR = STM32_PLLSAI2R | STM32_PLLSAI2REN |
+ STM32_PLLSAI2P | STM32_PLLSAI2PEN |
+ STM32_PLLSAI2N;
+#endif
+ RCC->CR |= RCC_CR_PLLSAI2ON;
+
+ /* Waiting for PLL lock.*/
+ while ((RCC->CR & RCC_CR_PLLSAI2RDY) == 0)
+ ;
+#endif
+
+ /* Other clock-related settings (dividers, MCO etc).*/
+ RCC->CFGR = STM32_MCOPRE | STM32_MCOSEL | STM32_STOPWUCK |
+ STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE;
+
+ /* CCIPR register initialization, note, must take care of the _OFF
+ pseudo settings.*/
+ {
+ uint32_t ccipr = STM32_DFSDMSEL | STM32_SWPMI1SEL | STM32_ADCSEL |
+ STM32_CLK48SEL | STM32_LPTIM2SEL | STM32_LPTIM1SEL |
+ STM32_I2C3SEL | STM32_I2C2SEL | STM32_I2C1SEL |
+ STM32_UART5SEL | STM32_UART4SEL | STM32_USART3SEL |
+ STM32_USART2SEL | STM32_USART1SEL | STM32_LPUART1SEL;
+#if STM32_SAI2SEL != STM32_SAI2SEL_OFF
+ ccipr |= STM32_SAI2SEL;
+#endif
+#if STM32_SAI1SEL != STM32_SAI1SEL_OFF
+ ccipr |= STM32_SAI1SEL;
+#endif
+ RCC->CCIPR = ccipr;
+ }
+
+#if STM32_HAS_I2C4
+ /* CCIPR2 register initialization.*/
+ {
+ uint32_t ccipr2 = STM32_I2C4SEL;
+ RCC->CCIPR2 = ccipr2;
+ }
+#endif
+
+ /* Set flash WS's for SYSCLK source */
+ if (STM32_FLASHBITS > STM32_MSI_FLASHBITS) {
+ FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY_Msk) | STM32_FLASHBITS;
+ while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) !=
+ (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) {
+ }
+ }
+
+ /* Switching to the configured SYSCLK source if it is different from MSI.*/
+#if (STM32_SW != STM32_SW_MSI)
+ RCC->CFGR |= STM32_SW; /* Switches on the selected clock source. */
+ /* Wait until SYSCLK is stable.*/
+ while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2))
+ ;
+#endif
+
+ /* Reduce the flash WS's for SYSCLK source if they are less than MSI WSs */
+ if (STM32_FLASHBITS < STM32_MSI_FLASHBITS) {
+ FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY_Msk) | STM32_FLASHBITS;
+ while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) !=
+ (STM32_FLASHBITS & FLASH_ACR_LATENCY_Msk)) {
+ }
+ }
+
+#endif /* STM32_NO_INIT */
+
+ /* SYSCFG clock enabled here because it is a multi-functional unit shared
+ among multiple drivers.*/
+ rccEnableAPB2(RCC_APB2ENR_SYSCFGEN, true);
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/hal_lld.h b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/hal_lld.h
new file mode 100644
index 0000000..91a0f57
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/hal_lld.h
@@ -0,0 +1,2349 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32L4xx/hal_lld.h
+ * @brief STM32L4xx HAL subsystem low level driver header.
+ * @pre This module requires the following macros to be defined in the
+ * @p board.h file:
+ * - STM32_LSECLK.
+ * - STM32_LSEDRV.
+ * - STM32_LSE_BYPASS (optionally).
+ * - STM32_HSECLK.
+ * - STM32_HSE_BYPASS (optionally).
+ * .
+ * One of the following macros must also be defined:
+ * - STM32L432xx, STM32L433xx, STM32L443xx.
+ * - STM32L471xx, STM32L475xx, STM32L476xx, STM32L496xx.
+ * - STM32L485xx, STM32L486xx, STM32L4A6xx.
+ * .
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#ifndef HAL_LLD_H
+#define HAL_LLD_H
+
+#include "stm32_registry.h"
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Platform identification
+ * @{
+ */
+#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L443xx) || \
+ defined(STM32L452xx) || defined(STM32L471xx) || defined(STM32L475xx) || \
+ defined(STM32L476xx) || defined(STM32L496xx) || defined(__DOXYGEN__)
+#define PLATFORM_NAME "STM32L4xx Ultra Low Power"
+
+#elif defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L4A6xx)
+#define PLATFORM_NAME "STM32L4xx Ultra Low Power with Crypto"
+
+#else
+#error "STM32L4xx device not specified"
+#endif
+
+/**
+ * @brief Sub-family identifier.
+ */
+#if !defined(STM32L4XX) || defined(__DOXYGEN__)
+#define STM32L4XX
+#endif
+/** @} */
+
+/**
+ * @name Internal clock sources
+ * @{
+ */
+#define STM32_HSI16CLK 16000000 /**< 16MHz internal clock. */
+#define STM32_HSI48CLK 48000000 /**< 48MHz internal clock. */
+#define STM32_LSICLK 32000 /**< Low speed internal clock. */
+/** @} */
+
+/**
+ * @name PWR_CR1 register bits definitions
+ * @{
+ */
+#define STM32_VOS_MASK (3 << 9) /**< Core voltage mask. */
+#define STM32_VOS_RANGE1 (1 << 9) /**< Core voltage 1.2 Volts. */
+#define STM32_VOS_RANGE2 (2 << 9) /**< Core voltage 1.0 Volts. */
+/** @} */
+
+/**
+ * @name PWR_CR2 register bits definitions
+ * @{
+ */
+#define STM32_PLS_MASK (7 << 1) /**< PLS bits mask. */
+#define STM32_PLS_LEV0 (0 << 1) /**< PVD level 0. */
+#define STM32_PLS_LEV1 (1 << 1) /**< PVD level 1. */
+#define STM32_PLS_LEV2 (2 << 1) /**< PVD level 2. */
+#define STM32_PLS_LEV3 (3 << 1) /**< PVD level 3. */
+#define STM32_PLS_LEV4 (4 << 1) /**< PVD level 4. */
+#define STM32_PLS_LEV5 (5 << 1) /**< PVD level 5. */
+#define STM32_PLS_LEV6 (6 << 1) /**< PVD level 6. */
+#define STM32_PLS_EXT (7 << 1) /**< PVD level 7. */
+/** @} */
+
+/**
+ * @name RCC_CR register bits definitions
+ * @{
+ */
+#define STM32_MSIRANGE_MASK (15 << 4) /**< MSIRANGE field mask. */
+#define STM32_MSIRANGE_100K (0 << 4) /**< 100kHz nominal. */
+#define STM32_MSIRANGE_200K (1 << 4) /**< 200kHz nominal. */
+#define STM32_MSIRANGE_400K (2 << 4) /**< 400kHz nominal. */
+#define STM32_MSIRANGE_800K (3 << 4) /**< 800kHz nominal. */
+#define STM32_MSIRANGE_1M (4 << 4) /**< 1MHz nominal. */
+#define STM32_MSIRANGE_2M (5 << 4) /**< 2MHz nominal. */
+#define STM32_MSIRANGE_4M (6 << 4) /**< 4MHz nominal. */
+#define STM32_MSIRANGE_8M (7 << 4) /**< 8MHz nominal. */
+#define STM32_MSIRANGE_16M (8 << 4) /**< 16MHz nominal. */
+#define STM32_MSIRANGE_24M (9 << 4) /**< 24MHz nominal. */
+#define STM32_MSIRANGE_32M (10 << 4) /**< 32MHz nominal. */
+#define STM32_MSIRANGE_48M (11 << 4) /**< 48MHz nominal. */
+/** @} */
+
+/**
+ * @name RCC_CFGR register bits definitions
+ * @{
+ */
+#define STM32_SW_MASK (3 << 0) /**< SW field mask. */
+#define STM32_SW_MSI (0 << 0) /**< SYSCLK source is MSI. */
+#define STM32_SW_HSI16 (1 << 0) /**< SYSCLK source is HSI. */
+#define STM32_SW_HSE (2 << 0) /**< SYSCLK source is HSE. */
+#define STM32_SW_PLL (3 << 0) /**< SYSCLK source is PLL. */
+
+#define STM32_HPRE_MASK (15 << 4) /**< HPRE field mask. */
+#define STM32_HPRE_DIV1 (0 << 4) /**< SYSCLK divided by 1. */
+#define STM32_HPRE_DIV2 (8 << 4) /**< SYSCLK divided by 2. */
+#define STM32_HPRE_DIV4 (9 << 4) /**< SYSCLK divided by 4. */
+#define STM32_HPRE_DIV8 (10 << 4) /**< SYSCLK divided by 8. */
+#define STM32_HPRE_DIV16 (11 << 4) /**< SYSCLK divided by 16. */
+#define STM32_HPRE_DIV64 (12 << 4) /**< SYSCLK divided by 64. */
+#define STM32_HPRE_DIV128 (13 << 4) /**< SYSCLK divided by 128. */
+#define STM32_HPRE_DIV256 (14 << 4) /**< SYSCLK divided by 256. */
+#define STM32_HPRE_DIV512 (15 << 4) /**< SYSCLK divided by 512. */
+
+#define STM32_PPRE1_MASK (7 << 8) /**< PPRE1 field mask. */
+#define STM32_PPRE1_DIV1 (0 << 8) /**< HCLK divided by 1. */
+#define STM32_PPRE1_DIV2 (4 << 8) /**< HCLK divided by 2. */
+#define STM32_PPRE1_DIV4 (5 << 8) /**< HCLK divided by 4. */
+#define STM32_PPRE1_DIV8 (6 << 8) /**< HCLK divided by 8. */
+#define STM32_PPRE1_DIV16 (7 << 8) /**< HCLK divided by 16. */
+
+#define STM32_PPRE2_MASK (7 << 11) /**< PPRE2 field mask. */
+#define STM32_PPRE2_DIV1 (0 << 11) /**< HCLK divided by 1. */
+#define STM32_PPRE2_DIV2 (4 << 11) /**< HCLK divided by 2. */
+#define STM32_PPRE2_DIV4 (5 << 11) /**< HCLK divided by 4. */
+#define STM32_PPRE2_DIV8 (6 << 11) /**< HCLK divided by 8. */
+#define STM32_PPRE2_DIV16 (7 << 11) /**< HCLK divided by 16. */
+
+#define STM32_STOPWUCK_MASK (1 << 15) /**< STOPWUCK field mask. */
+#define STM32_STOPWUCK_MSI (0 << 15) /**< Wakeup clock is MSI. */
+#define STM32_STOPWUCK_HSI16 (1 << 15) /**< Wakeup clock is HSI16. */
+
+#define STM32_MCOSEL_MASK (15 << 24) /**< MCOSEL field mask. */
+#define STM32_MCOSEL_NOCLOCK (0 << 24) /**< No clock on MCO pin. */
+#define STM32_MCOSEL_SYSCLK (1 << 24) /**< SYSCLK on MCO pin. */
+#define STM32_MCOSEL_MSI (2 << 24) /**< MSI clock on MCO pin. */
+#define STM32_MCOSEL_HSI16 (3 << 24) /**< HSI16 clock on MCO pin. */
+#define STM32_MCOSEL_HSE (4 << 24) /**< HSE clock on MCO pin. */
+#define STM32_MCOSEL_PLL (5 << 24) /**< PLL clock on MCO pin. */
+#define STM32_MCOSEL_LSI (6 << 24) /**< LSI clock on MCO pin. */
+#define STM32_MCOSEL_LSE (7 << 24) /**< LSE clock on MCO pin. */
+#define STM32_MCOSEL_HSI48 (8 << 24) /**< HSI48 clock on MCO pin. */
+
+#define STM32_MCOPRE_MASK (7 << 28) /**< MCOPRE field mask. */
+#define STM32_MCOPRE_DIV1 (0 << 28) /**< MCO divided by 1. */
+#define STM32_MCOPRE_DIV2 (1 << 28) /**< MCO divided by 2. */
+#define STM32_MCOPRE_DIV4 (2 << 28) /**< MCO divided by 4. */
+#define STM32_MCOPRE_DIV8 (3 << 28) /**< MCO divided by 8. */
+#define STM32_MCOPRE_DIV16 (4 << 28) /**< MCO divided by 16. */
+/** @} */
+
+/**
+ * @name RCC_PLLCFGR register bits definitions
+ * @{
+ */
+#define STM32_PLLSRC_MASK (3 << 0) /**< PLL clock source mask. */
+#define STM32_PLLSRC_NOCLOCK (0 << 0) /**< PLL clock source disabled. */
+#define STM32_PLLSRC_MSI (1 << 0) /**< PLL clock source is MSI. */
+#define STM32_PLLSRC_HSI16 (2 << 0) /**< PLL clock source is HSI16. */
+#define STM32_PLLSRC_HSE (3 << 0) /**< PLL clock source is HSE. */
+/** @} */
+
+/**
+ * @name RCC_CCIPR register bits definitions
+ * @{
+ */
+#define STM32_USART1SEL_MASK (3 << 0) /**< USART1SEL mask. */
+#define STM32_USART1SEL_PCLK2 (0 << 0) /**< USART1 source is PCLK2. */
+#define STM32_USART1SEL_SYSCLK (1 << 0) /**< USART1 source is SYSCLK. */
+#define STM32_USART1SEL_HSI16 (2 << 0) /**< USART1 source is HSI16. */
+#define STM32_USART1SEL_LSE (3 << 0) /**< USART1 source is LSE. */
+
+#define STM32_USART2SEL_MASK (3 << 2) /**< USART2 mask. */
+#define STM32_USART2SEL_PCLK1 (0 << 2) /**< USART2 source is PCLK1. */
+#define STM32_USART2SEL_SYSCLK (1 << 2) /**< USART2 source is SYSCLK. */
+#define STM32_USART2SEL_HSI16 (2 << 2) /**< USART2 source is HSI16. */
+#define STM32_USART2SEL_LSE (3 << 2) /**< USART2 source is LSE. */
+
+#define STM32_USART3SEL_MASK (3 << 4) /**< USART3 mask. */
+#define STM32_USART3SEL_PCLK1 (0 << 4) /**< USART3 source is PCLK1. */
+#define STM32_USART3SEL_SYSCLK (1 << 4) /**< USART3 source is SYSCLK. */
+#define STM32_USART3SEL_HSI16 (2 << 4) /**< USART3 source is HSI16. */
+#define STM32_USART3SEL_LSE (3 << 4) /**< USART3 source is LSE. */
+
+#define STM32_UART4SEL_MASK (3 << 6) /**< UART4 mask. */
+#define STM32_UART4SEL_PCLK1 (0 << 6) /**< UART4 source is PCLK1. */
+#define STM32_UART4SEL_SYSCLK (1 << 6) /**< UART4 source is SYSCLK. */
+#define STM32_UART4SEL_HSI16 (2 << 6) /**< UART4 source is HSI16. */
+#define STM32_UART4SEL_LSE (3 << 6) /**< UART4 source is LSE. */
+
+#define STM32_UART5SEL_MASK (3 << 8) /**< UART5 mask. */
+#define STM32_UART5SEL_PCLK1 (0 << 8) /**< UART5 source is PCLK1. */
+#define STM32_UART5SEL_SYSCLK (1 << 8) /**< UART5 source is SYSCLK. */
+#define STM32_UART5SEL_HSI16 (2 << 8) /**< UART5 source is HSI16. */
+#define STM32_UART5SEL_LSE (3 << 8) /**< UART5 source is LSE. */
+
+#define STM32_LPUART1SEL_MASK (3 << 10) /**< LPUART1 mask. */
+#define STM32_LPUART1SEL_PCLK1 (0 << 10) /**< LPUART1 source is PCLK1. */
+#define STM32_LPUART1SEL_SYSCLK (1 << 10) /**< LPUART1 source is SYSCLK. */
+#define STM32_LPUART1SEL_HSI16 (2 << 10) /**< LPUART1 source is HSI16. */
+#define STM32_LPUART1SEL_LSE (3 << 10) /**< LPUART1 source is LSE. */
+
+#define STM32_I2C1SEL_MASK (3 << 12) /**< I2C1SEL mask. */
+#define STM32_I2C1SEL_PCLK1 (0 << 12) /**< I2C1 source is PCLK1. */
+#define STM32_I2C1SEL_SYSCLK (1 << 12) /**< I2C1 source is SYSCLK. */
+#define STM32_I2C1SEL_HSI16 (2 << 12) /**< I2C1 source is HSI16. */
+
+#define STM32_I2C2SEL_MASK (3 << 14) /**< I2C2SEL mask. */
+#define STM32_I2C2SEL_PCLK1 (0 << 14) /**< I2C2 source is PCLK1. */
+#define STM32_I2C2SEL_SYSCLK (1 << 14) /**< I2C2 source is SYSCLK. */
+#define STM32_I2C2SEL_HSI16 (2 << 14) /**< I2C2 source is HSI16. */
+
+#define STM32_I2C3SEL_MASK (3 << 16) /**< I2C3SEL mask. */
+#define STM32_I2C3SEL_PCLK1 (0 << 16) /**< I2C3 source is PCLK1. */
+#define STM32_I2C3SEL_SYSCLK (1 << 16) /**< I2C3 source is SYSCLK. */
+#define STM32_I2C3SEL_HSI16 (2 << 16) /**< I2C3 source is HSI16. */
+
+#define STM32_LPTIM1SEL_MASK (3 << 18) /**< LPTIM1SEL mask. */
+#define STM32_LPTIM1SEL_PCLK1 (0 << 18) /**< LPTIM1 source is PCLK1. */
+#define STM32_LPTIM1SEL_LSI (1 << 18) /**< LPTIM1 source is LSI. */
+#define STM32_LPTIM1SEL_HSI16 (2 << 18) /**< LPTIM1 source is HSI16. */
+#define STM32_LPTIM1SEL_LSE (3 << 18) /**< LPTIM1 source is LSE. */
+
+#define STM32_LPTIM2SEL_MASK (3 << 20) /**< LPTIM2SEL mask. */
+#define STM32_LPTIM2SEL_PCLK1 (0 << 20) /**< LPTIM2 source is PCLK1. */
+#define STM32_LPTIM2SEL_LSI (1 << 20) /**< LPTIM2 source is LSI. */
+#define STM32_LPTIM2SEL_HSI16 (2 << 20) /**< LPTIM2 source is HSI16. */
+#define STM32_LPTIM2SEL_LSE (3 << 20) /**< LPTIM2 source is LSE. */
+
+#define STM32_SAI1SEL_MASK (3 << 22) /**< SAI1SEL mask. */
+#define STM32_SAI1SEL_PLLSAI1 (0 << 22) /**< SAI1 source is PLLSAI1-P. */
+#define STM32_SAI1SEL_PLLSAI2 (1 << 22) /**< SAI1 source is PLLSAI2-P. */
+#define STM32_SAI1SEL_PLL (2 << 22) /**< SAI1 source is PLL-P. */
+#define STM32_SAI1SEL_EXTCLK (3 << 22) /**< SAI1 source is external. */
+#define STM32_SAI1SEL_OFF 0xFFFFFFFFU /**< SAI1 clock is not required.*/
+
+#define STM32_SAI2SEL_MASK (3 << 24) /**< SAI2SEL mask. */
+#define STM32_SAI2SEL_PLLSAI1 (0 << 24) /**< SAI2 source is PLLSAI1-P. */
+#define STM32_SAI2SEL_PLLSAI2 (1 << 24) /**< SAI2 source is PLLSAI2-P. */
+#define STM32_SAI2SEL_PLL (2 << 24) /**< SAI2 source is PLL-P. */
+#define STM32_SAI2SEL_EXTCLK (3 << 24) /**< SAI2 source is external. */
+#define STM32_SAI2SEL_OFF 0xFFFFFFFFU /**< SAI2 clock is not required.*/
+
+#define STM32_CLK48SEL_MASK (3 << 26) /**< CLK48SEL mask. */
+#if !STM32_CLOCK_HAS_HSI48
+#define STM32_CLK48SEL_NOCLK (0 << 26) /**< CLK48 disabled. */
+#else
+#define STM32_CLK48SEL_HSI48 (0 << 26) /**< CLK48 source is HSI48. */
+#endif
+#define STM32_CLK48SEL_PLLSAI1 (1 << 26) /**< CLK48 source is PLLSAI1-Q. */
+#define STM32_CLK48SEL_PLL (2 << 26) /**< CLK48 source is PLL-Q. */
+#define STM32_CLK48SEL_MSI (3 << 26) /**< CLK48 source is MSI. */
+
+#define STM32_ADCSEL_MASK (3 << 28) /**< ADCSEL mask. */
+#define STM32_ADCSEL_NOCLK (0 << 28) /**< ADC clock disabled. */
+#define STM32_ADCSEL_PLLSAI1 (1 << 28) /**< ADC source is PLLSAI1-R. */
+#define STM32_ADCSEL_PLLSAI2 (2 << 28) /**< ADC source is PLLSAI2-R. */
+#define STM32_ADCSEL_SYSCLK (3 << 28) /**< ADC source is SYSCLK. */
+
+#define STM32_SWPMI1SEL_MASK (1 << 30) /**< SWPMI1SEL mask. */
+#define STM32_SWPMI1SEL_PCLK1 (0 << 30) /**< SWPMI1 source is PCLK1. */
+#define STM32_SWPMI1SEL_HSI16 (1 << 30) /**< SWPMI1 source is HSI16. */
+
+#define STM32_DFSDMSEL_MASK (1 << 31) /**< DFSDMSEL mask. */
+#define STM32_DFSDMSEL_PCLK2 (0 << 31) /**< DFSDM source is PCLK2. */
+#define STM32_DFSDMSEL_SYSCLK (1 << 31) /**< DFSDM source is SYSCLK. */
+/** @} */
+
+/**
+ * @name RCC_CCIPR2 register bits definitions
+ * @{
+ */
+#define STM32_I2C4SEL_MASK (3 << 0) /**< I2C1SEL mask. */
+#define STM32_I2C4SEL_PCLK1 (0 << 0) /**< I2C1 source is PCLK1. */
+#define STM32_I2C4SEL_SYSCLK (1 << 0) /**< I2C1 source is SYSCLK. */
+#define STM32_I2C4SEL_HSI16 (2 << 0) /**< I2C1 source is HSI16. */
+/** @} */
+
+/**
+ * @name RCC_BDCR register bits definitions
+ * @{
+ */
+#define STM32_RTCSEL_MASK (3 << 8) /**< RTC source mask. */
+#define STM32_RTCSEL_NOCLOCK (0 << 8) /**< No RTC source. */
+#define STM32_RTCSEL_LSE (1 << 8) /**< RTC source is LSE. */
+#define STM32_RTCSEL_LSI (2 << 8) /**< RTC source is LSI. */
+#define STM32_RTCSEL_HSEDIV (3 << 8) /**< RTC source is HSE divided. */
+
+#define STM32_LSCOSEL_MASK (3 << 24) /**< LSCO pin clock source. */
+#define STM32_LSCOSEL_NOCLOCK (0 << 24) /**< No clock on LSCO pin. */
+#define STM32_LSCOSEL_LSI (1 << 24) /**< LSI on LSCO pin. */
+#define STM32_LSCOSEL_LSE (3 << 24) /**< LSE on LSCO pin. */
+/** @} */
+
+/**
+ * @name RCC_CSR register bits definitions
+ * @{
+ */
+#define STM32_MSISRANGE_MASK (15 << 8) /**< MSISRANGE field mask. */
+#define STM32_MSISRANGE_1M (4 << 8) /**< 1MHz nominal. */
+#define STM32_MSISRANGE_2M (5 << 8) /**< 2MHz nominal. */
+#define STM32_MSISRANGE_4M (6 << 8) /**< 4MHz nominal. */
+#define STM32_MSISRANGE_8M (7 << 8) /**< 8MHz nominal. */
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief Disables the PWR/RCC initialization in the HAL.
+ */
+#if !defined(STM32_NO_INIT) || defined(__DOXYGEN__)
+#define STM32_NO_INIT FALSE
+#endif
+
+/**
+ * @brief Core voltage selection.
+ * @note This setting affects all the performance and clock related
+ * settings, the maximum performance is only obtainable selecting
+ * the maximum voltage.
+ */
+#if !defined(STM32_VOS) || defined(__DOXYGEN__)
+#define STM32_VOS STM32_VOS_RANGE1
+#endif
+
+/**
+ * @brief Enables or disables the programmable voltage detector.
+ */
+#if !defined(STM32_PVD_ENABLE) || defined(__DOXYGEN__)
+#define STM32_PVD_ENABLE FALSE
+#endif
+
+/**
+ * @brief Sets voltage level for programmable voltage detector.
+ */
+#if !defined(STM32_PLS) || defined(__DOXYGEN__)
+#define STM32_PLS STM32_PLS_LEV0
+#endif
+
+/**
+ * @brief Enables or disables the HSI16 clock source.
+ */
+#if !defined(STM32_HSI16_ENABLED) || defined(__DOXYGEN__)
+#define STM32_HSI16_ENABLED FALSE
+#endif
+
+/**
+ * @brief Enables or disables the HSI48 clock source.
+ */
+#if !defined(STM32_HSI48_ENABLED) || defined(__DOXYGEN__)
+#define STM32_HSI48_ENABLED FALSE
+#endif
+
+/**
+ * @brief Enables or disables the LSI clock source.
+ */
+#if !defined(STM32_LSI_ENABLED) || defined(__DOXYGEN__)
+#define STM32_LSI_ENABLED TRUE
+#endif
+
+/**
+ * @brief Enables or disables the HSE clock source.
+ */
+#if !defined(STM32_HSE_ENABLED) || defined(__DOXYGEN__)
+#define STM32_HSE_ENABLED FALSE
+#endif
+
+/**
+ * @brief Enables or disables the LSE clock source.
+ */
+#if !defined(STM32_LSE_ENABLED) || defined(__DOXYGEN__)
+#define STM32_LSE_ENABLED FALSE
+#endif
+
+/**
+ * @brief Enables or disables the MSI PLL on LSE clock source.
+ */
+#if !defined(STM32_MSIPLL_ENABLED) || defined(__DOXYGEN__)
+#define STM32_MSIPLL_ENABLED FALSE
+#endif
+
+/**
+ * @brief MSI frequency setting.
+ */
+#if !defined(STM32_MSIRANGE) || defined(__DOXYGEN__)
+#define STM32_MSIRANGE STM32_MSIRANGE_4M
+#endif
+
+/**
+ * @brief MSI frequency setting after standby.
+ */
+#if !defined(STM32_MSISRANGE) || defined(__DOXYGEN__)
+#define STM32_MSISRANGE STM32_MSISRANGE_4M
+#endif
+
+/**
+ * @brief Main clock source selection.
+ * @note If the selected clock source is not the PLL then the PLL is not
+ * initialized and started.
+ * @note The default value is calculated for a 80MHz system clock from
+ * the internal 4MHz MSI clock.
+ */
+#if !defined(STM32_SW) || defined(__DOXYGEN__)
+#define STM32_SW STM32_SW_PLL
+#endif
+
+/**
+ * @brief Clock source for the PLL.
+ * @note This setting has only effect if the PLL is selected as the
+ * system clock source.
+ * @note The default value is calculated for a 80MHz system clock from
+ * the internal 4MHz MSI clock.
+ */
+#if !defined(STM32_PLLSRC) || defined(__DOXYGEN__)
+#define STM32_PLLSRC STM32_PLLSRC_MSI
+#endif
+
+/**
+ * @brief PLLM divider value.
+ * @note The allowed values are 1..8.
+ * @note The default value is calculated for a 80MHz system clock from
+ * the internal 4MHz MSI clock.
+ */
+#if !defined(STM32_PLLM_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLM_VALUE 1
+#endif
+
+/**
+ * @brief PLLN multiplier value.
+ * @note The allowed values are 8..86.
+ * @note The default value is calculated for a 80MHz system clock from
+ * the internal 4MHz MSI clock.
+ */
+#if !defined(STM32_PLLN_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLN_VALUE 80
+#endif
+
+/**
+ * @brief PLLPDIV divider value or zero if disabled.
+ * @note The allowed values are 0, 2..31.
+ */
+#if !defined(STM32_PLLPDIV_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLPDIV_VALUE 0
+#endif
+
+/**
+ * @brief PLLP divider value.
+ * @note The allowed values are 7, 17.
+ * @note The default value is calculated for a 80MHz system clock from
+ * the internal 4MHz MSI clock.
+ */
+#if !defined(STM32_PLLP_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLP_VALUE 7
+#endif
+
+/**
+ * @brief PLLQ divider value.
+ * @note The allowed values are 2, 4, 6, 8.
+ * @note The default value is calculated for a 80MHz system clock from
+ * the internal 4MHz MSI clock.
+ */
+#if !defined(STM32_PLLQ_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLQ_VALUE 6
+#endif
+
+/**
+ * @brief PLLR divider value.
+ * @note The allowed values are 2, 4, 6, 8.
+ * @note The default value is calculated for a 80MHz system clock from
+ * the internal 4MHz MSI clock.
+ */
+#if !defined(STM32_PLLR_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLR_VALUE 4
+#endif
+
+/**
+ * @brief AHB prescaler value.
+ * @note The default value is calculated for a 80MHz system clock from
+ * the internal 4MHz MSI clock.
+ */
+#if !defined(STM32_HPRE) || defined(__DOXYGEN__)
+#define STM32_HPRE STM32_HPRE_DIV1
+#endif
+
+/**
+ * @brief APB1 prescaler value.
+ */
+#if !defined(STM32_PPRE1) || defined(__DOXYGEN__)
+#define STM32_PPRE1 STM32_PPRE1_DIV1
+#endif
+
+/**
+ * @brief APB2 prescaler value.
+ */
+#if !defined(STM32_PPRE2) || defined(__DOXYGEN__)
+#define STM32_PPRE2 STM32_PPRE2_DIV1
+#endif
+
+/**
+ * @brief STOPWUCK clock setting.
+ */
+#if !defined(STM32_STOPWUCK) || defined(__DOXYGEN__)
+#define STM32_STOPWUCK STM32_STOPWUCK_MSI
+#endif
+
+/**
+ * @brief MCO clock source.
+ */
+#if !defined(STM32_MCOSEL) || defined(__DOXYGEN__)
+#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK
+#endif
+
+/**
+ * @brief MCO divider setting.
+ */
+#if !defined(STM32_MCOPRE) || defined(__DOXYGEN__)
+#define STM32_MCOPRE STM32_MCOPRE_DIV1
+#endif
+
+/**
+ * @brief LSCO clock source.
+ */
+#if !defined(STM32_LSCOSEL) || defined(__DOXYGEN__)
+#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK
+#endif
+
+/**
+ * @brief PLLSAI1N multiplier value.
+ * @note The allowed values are 8..86.
+ */
+#if !defined(STM32_PLLSAI1N_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLSAI1N_VALUE 80
+#endif
+
+/**
+ * @brief PLLSAI1PDIV divider value or zero if disabled.
+ * @note The allowed values are 0, 2..31.
+ */
+#if !defined(STM32_PLLSAI1PDIV_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLSAI1PDIV_VALUE 0
+#endif
+
+/**
+ * @brief PLLSAI1P divider value.
+ * @note The allowed values are 7, 17.
+ */
+#if !defined(STM32_PLLSAI1P_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLSAI1P_VALUE 7
+#endif
+
+/**
+ * @brief PLLSAI1Q divider value.
+ * @note The allowed values are 2, 4, 6, 8.
+ */
+#if !defined(STM32_PLLSAI1Q_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLSAI1Q_VALUE 6
+#endif
+
+/**
+ * @brief PLLSAI1R divider value.
+ * @note The allowed values are 2, 4, 6, 8.
+ */
+#if !defined(STM32_PLLSAI1R_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLSAI1R_VALUE 4
+#endif
+
+/**
+ * @brief PLLSAI2N multiplier value.
+ * @note The allowed values are 8..86.
+ */
+#if !defined(STM32_PLLSAI2N_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLSAI2N_VALUE 80
+#endif
+
+/**
+ * @brief PLLSAI2PDIV divider value or zero if disabled.
+ * @note The allowed values are 0, 2..31.
+ */
+#if !defined(STM32_PLLSAI2PDIV_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLSAI2PDIV_VALUE 0
+#endif
+
+/**
+ * @brief PLLSAI2P divider value.
+ * @note The allowed values are 7, 17.
+ */
+#if !defined(STM32_PLLSAI2P_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLSAI2P_VALUE 7
+#endif
+
+/**
+ * @brief PLLSAI2R divider value.
+ * @note The allowed values are 2, 4, 6, 8.
+ */
+#if !defined(STM32_PLLSAI2R_VALUE) || defined(__DOXYGEN__)
+#define STM32_PLLSAI2R_VALUE 4
+#endif
+
+/**
+ * @brief USART1 clock source.
+ */
+#if !defined(STM32_USART1SEL) || defined(__DOXYGEN__)
+#define STM32_USART1SEL STM32_USART1SEL_SYSCLK
+#endif
+
+/**
+ * @brief USART2 clock source.
+ */
+#if !defined(STM32_USART2SEL) || defined(__DOXYGEN__)
+#define STM32_USART2SEL STM32_USART2SEL_SYSCLK
+#endif
+
+/**
+ * @brief USART3 clock source.
+ */
+#if !defined(STM32_USART3SEL) || defined(__DOXYGEN__)
+#define STM32_USART3SEL STM32_USART3SEL_SYSCLK
+#endif
+
+/**
+ * @brief UART4 clock source.
+ */
+#if !defined(STM32_UART4SEL) || defined(__DOXYGEN__)
+#define STM32_UART4SEL STM32_UART4SEL_SYSCLK
+#endif
+
+/**
+ * @brief UART5 clock source.
+ */
+#if !defined(STM32_UART5SEL) || defined(__DOXYGEN__)
+#define STM32_UART5SEL STM32_UART5SEL_SYSCLK
+#endif
+
+/**
+ * @brief LPUART1 clock source.
+ */
+#if !defined(STM32_LPUART1SEL) || defined(__DOXYGEN__)
+#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK
+#endif
+
+/**
+ * @brief I2C1 clock source.
+ */
+#if !defined(STM32_I2C1SEL) || defined(__DOXYGEN__)
+#define STM32_I2C1SEL STM32_I2C1SEL_SYSCLK
+#endif
+
+/**
+ * @brief I2C2 clock source.
+ */
+#if !defined(STM32_I2C2SEL) || defined(__DOXYGEN__)
+#define STM32_I2C2SEL STM32_I2C2SEL_SYSCLK
+#endif
+
+/**
+ * @brief I2C3 clock source.
+ */
+#if !defined(STM32_I2C3SEL) || defined(__DOXYGEN__)
+#define STM32_I2C3SEL STM32_I2C3SEL_SYSCLK
+#endif
+
+/**
+ * @brief I2C4 clock source.
+ */
+#if !defined(STM32_I2C4SEL) || defined(__DOXYGEN__)
+#define STM32_I2C4SEL STM32_I2C4SEL_SYSCLK
+#endif
+
+/**
+ * @brief LPTIM1 clock source.
+ */
+#if !defined(STM32_LPTIM1SEL) || defined(__DOXYGEN__)
+#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1
+#endif
+
+/**
+ * @brief LPTIM2 clock source.
+ */
+#if !defined(STM32_LPTIM2SEL) || defined(__DOXYGEN__)
+#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK1
+#endif
+
+/**
+ * @brief SAI1SEL value (SAI1 clock source).
+ */
+#if !defined(STM32_SAI1SEL) || defined(__DOXYGEN__)
+#define STM32_SAI1SEL STM32_SAI1SEL_OFF
+#endif
+
+/**
+ * @brief SAI2SEL value (SAI2 clock source).
+ */
+#if !defined(STM32_SAI2SEL) || defined(__DOXYGEN__)
+#define STM32_SAI2SEL STM32_SAI2SEL_OFF
+#endif
+
+/**
+ * @brief CLK48SEL value (48MHz clock source).
+ */
+#if !defined(STM32_CLK48SEL) || defined(__DOXYGEN__)
+#define STM32_CLK48SEL STM32_CLK48SEL_PLL
+#endif
+
+/**
+ * @brief ADCSEL value (ADCs clock source).
+ */
+#if !defined(STM32_ADCSEL) || defined(__DOXYGEN__)
+#define STM32_ADCSEL STM32_ADCSEL_SYSCLK
+#endif
+
+/**
+ * @brief SWPMI1SEL value (SWPMI clock source).
+ */
+#if !defined(STM32_SWPMI1SEL) || defined(__DOXYGEN__)
+#define STM32_SWPMI1SEL STM32_SWPMI1SEL_PCLK1
+#endif
+
+/**
+ * @brief DFSDMSEL value (DFSDM clock source).
+ */
+#if !defined(STM32_DFSDMSEL) || defined(__DOXYGEN__)
+#define STM32_DFSDMSEL STM32_DFSDMSEL_PCLK2
+#endif
+
+/**
+ * @brief RTC/LCD clock source.
+ */
+#if !defined(STM32_RTCSEL) || defined(__DOXYGEN__)
+#define STM32_RTCSEL STM32_RTCSEL_LSI
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*
+ * Configuration-related checks.
+ */
+#if !defined(STM32L4xx_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32L4xx_MCUCONF not defined"
+#endif
+
+/* Only some devices have strongly checked mcuconf.h files. Others will be
+ added gradually.*/
+#if defined(STM32L432xx) && !defined(STM32L432_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32L432_MCUCONF not defined"
+#endif
+
+#if defined(STM32L433xx) && !defined(STM32L433_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32L433_MCUCONF not defined"
+#endif
+
+#if defined(STM32L476xx) && !defined(STM32L476_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32L476_MCUCONF not defined"
+#endif
+
+#if defined(STM32L486xx) && !defined(STM32L486_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32L486_MCUCONF not defined"
+#endif
+
+#if defined(STM32L496xx) && !defined(STM32L496_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32L496_MCUCONF not defined"
+#endif
+
+#if defined(STM32L4A6xx) && !defined(STM32L4A6_MCUCONF)
+#error "Using a wrong mcuconf.h file, STM32L4A6_MCUCONF not defined"
+#endif
+
+/*
+ * Board files sanity checks.
+ */
+#if !defined(STM32_LSECLK)
+#error "STM32_LSECLK not defined in board.h"
+#endif
+
+#if !defined(STM32_LSEDRV)
+#error "STM32_LSEDRV not defined in board.h"
+#endif
+
+#if !defined(STM32_HSECLK)
+#error "STM32_HSECLK not defined in board.h"
+#endif
+
+/* Voltage related limits.*/
+#if (STM32_VOS == STM32_VOS_RANGE1) || defined(__DOXYGEN__)
+/**
+ * @name System Limits
+ * @{
+ */
+/**
+ * @brief Maximum SYSCLK clock frequency at current voltage setting.
+ */
+#define STM32_SYSCLK_MAX 80000000
+
+/**
+ * @brief Maximum HSE clock frequency at current voltage setting.
+ */
+#define STM32_HSECLK_MAX 48000000
+
+/**
+ * @brief Maximum HSE clock frequency using an external source.
+ */
+#define STM32_HSECLK_BYP_MAX 48000000
+
+/**
+ * @brief Minimum HSE clock frequency.
+ */
+#define STM32_HSECLK_MIN 4000000
+
+/**
+ * @brief Minimum HSE clock frequency using an external source.
+ */
+#define STM32_HSECLK_BYP_MIN 8000000
+
+/**
+ * @brief Maximum LSE clock frequency.
+ */
+#define STM32_LSECLK_MAX 32768
+
+/**
+ * @brief Maximum LSE clock frequency.
+ */
+#define STM32_LSECLK_BYP_MAX 1000000
+
+/**
+ * @brief Minimum LSE clock frequency.
+ */
+#define STM32_LSECLK_MIN 32768
+
+/**
+ * @brief Minimum LSE clock frequency.
+ */
+#define STM32_LSECLK_BYP_MIN 32768
+
+/**
+ * @brief Maximum PLLs input clock frequency.
+ */
+#define STM32_PLLIN_MAX 16000000
+
+/**
+ * @brief Minimum PLLs input clock frequency.
+ */
+#define STM32_PLLIN_MIN 4000000
+
+/**
+ * @brief Maximum VCO clock frequency at current voltage setting.
+ */
+#define STM32_PLLVCO_MAX 344000000
+
+/**
+ * @brief Minimum VCO clock frequency at current voltage setting.
+ */
+#define STM32_PLLVCO_MIN 64000000
+
+/**
+ * @brief Maximum PLL-P output clock frequency.
+ */
+#define STM32_PLLP_MAX 80000000
+
+/**
+ * @brief Minimum PLL-P output clock frequency.
+ */
+#define STM32_PLLP_MIN 2064500
+
+/**
+ * @brief Maximum PLL-Q output clock frequency.
+ */
+#define STM32_PLLQ_MAX 80000000
+
+/**
+ * @brief Minimum PLL-Q output clock frequency.
+ */
+#define STM32_PLLQ_MIN 8000000
+
+/**
+ * @brief Maximum PLL-R output clock frequency.
+ */
+#define STM32_PLLR_MAX 80000000
+
+/**
+ * @brief Minimum PLL-R output clock frequency.
+ */
+#define STM32_PLLR_MIN 8000000
+
+/**
+ * @brief Maximum APB1 clock frequency.
+ */
+#define STM32_PCLK1_MAX 80000000
+
+/**
+ * @brief Maximum APB2 clock frequency.
+ */
+#define STM32_PCLK2_MAX 80000000
+
+/**
+ * @brief Maximum ADC clock frequency.
+ */
+#define STM32_ADCCLK_MAX 80000000
+/** @} */
+
+/**
+ * @name Flash Wait states
+ * @{
+ */
+#define STM32_0WS_THRESHOLD 16000000
+#define STM32_1WS_THRESHOLD 32000000
+#define STM32_2WS_THRESHOLD 48000000
+#define STM32_3WS_THRESHOLD 64000000
+/** @} */
+
+#elif STM32_VOS == STM32_VOS_RANGE2
+#define STM32_SYSCLK_MAX 26000000
+#define STM32_HSECLK_MAX 26000000
+#define STM32_HSECLK_BYP_MAX 26000000
+#define STM32_HSECLK_MIN 8000000
+#define STM32_HSECLK_BYP_MIN 8000000
+#define STM32_LSECLK_MAX 32768
+#define STM32_LSECLK_BYP_MAX 1000000
+#define STM32_LSECLK_MIN 32768
+#define STM32_LSECLK_BYP_MIN 32768
+#define STM32_PLLIN_MAX 16000000
+#define STM32_PLLIN_MIN 4000000
+#define STM32_PLLVCO_MAX 128000000
+#define STM32_PLLVCO_MIN 64000000
+#define STM32_PLLP_MAX 26000000
+#define STM32_PLLP_MIN 2064500
+#define STM32_PLLQ_MAX 26000000
+#define STM32_PLLQ_MIN 8000000
+#define STM32_PLLR_MAX 26000000
+#define STM32_PLLR_MIN 8000000
+#define STM32_PCLK1_MAX 26000000
+#define STM32_PCLK2_MAX 26000000
+#define STM32_ADCCLK_MAX 26000000
+
+#define STM32_0WS_THRESHOLD 6000000
+#define STM32_1WS_THRESHOLD 12000000
+#define STM32_2WS_THRESHOLD 18000000
+#define STM32_3WS_THRESHOLD 26000000
+
+#else
+#error "invalid STM32_VOS value specified"
+#endif
+
+/**
+ * @brief MSI frequency.
+ */
+#if STM32_MSIRANGE == STM32_MSIRANGE_100K
+#define STM32_MSICLK 100000
+#elif STM32_MSIRANGE == STM32_MSIRANGE_200K
+#define STM32_MSICLK 200000
+#elif STM32_MSIRANGE == STM32_MSIRANGE_400K
+#define STM32_MSICLK 400000
+#elif STM32_MSIRANGE == STM32_MSIRANGE_800K
+#define STM32_MSICLK 800000
+#elif STM32_MSIRANGE == STM32_MSIRANGE_1M
+#define STM32_MSICLK 1000000
+#elif STM32_MSIRANGE == STM32_MSIRANGE_2M
+#define STM32_MSICLK 2000000
+#elif STM32_MSIRANGE == STM32_MSIRANGE_4M
+#define STM32_MSICLK 4000000
+#elif STM32_MSIRANGE == STM32_MSIRANGE_8M
+#define STM32_MSICLK 8000000
+#elif STM32_MSIRANGE == STM32_MSIRANGE_16M
+#define STM32_MSICLK 16000000
+#elif STM32_MSIRANGE == STM32_MSIRANGE_24M
+#define STM32_MSICLK 24000000
+#elif STM32_MSIRANGE == STM32_MSIRANGE_32M
+#define STM32_MSICLK 32000000
+#elif STM32_MSIRANGE == STM32_MSIRANGE_48M
+#define STM32_MSICLK 48000000
+#else
+#error "invalid STM32_MSIRANGE value specified"
+#endif
+
+/**
+ * @brief MSIS frequency.
+ */
+#if STM32_MSISRANGE == STM32_MSISRANGE_1M
+#define STM32_MSISCLK 1000000
+#elif STM32_MSISRANGE == STM32_MSISRANGE_2M
+#define STM32_MSISCLK 2000000
+#elif STM32_MSISRANGE == STM32_MSISRANGE_4M
+#define STM32_MSISCLK 4000000
+#elif STM32_MSISRANGE == STM32_MSISRANGE_8M
+#define STM32_MSISCLK 8000000
+#else
+#error "invalid STM32_MSISRANGE value specified"
+#endif
+
+/*
+ * HSI16 related checks.
+ */
+#if STM32_HSI16_ENABLED
+#else /* !STM32_HSI16_ENABLED */
+
+#if STM32_SW == STM32_SW_HSI16
+#error "HSI16 not enabled, required by STM32_SW"
+#endif
+
+#if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSI16)
+#error "HSI16 not enabled, required by STM32_SW and STM32_PLLSRC"
+#endif
+
+#if (STM32_MCOSEL == STM32_MCOSEL_HSI16) || \
+ ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \
+ (STM32_PLLSRC == STM32_PLLSRC_HSI16))
+#error "HSI16 not enabled, required by STM32_MCOSEL"
+#endif
+
+#if ((STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \
+ (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2)) && \
+ (STM32_PLLSRC == STM32_PLLSRC_HSI16)
+#error "HSI16 not enabled, required by STM32_SAI1SEL"
+#endif
+
+#if ((STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \
+ (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2)) && \
+ (STM32_PLLSRC == STM32_PLLSRC_HSI16)
+#error "HSI16 not enabled, required by STM32_SAI2SEL"
+#endif
+
+#if (STM32_USART1SEL == STM32_USART1SEL_HSI16)
+#error "HSI16 not enabled, required by STM32_USART1SEL"
+#endif
+#if (STM32_USART2SEL == STM32_USART2SEL_HSI16)
+#error "HSI16 not enabled, required by STM32_USART2SEL"
+#endif
+#if (STM32_USART3SEL == STM32_USART3SEL_HSI16)
+#error "HSI16 not enabled, required by STM32_USART3SEL"
+#endif
+#if (STM32_UART4SEL == STM32_UART4SEL_HSI16)
+#error "HSI16 not enabled, required by STM32_UART4SEL"
+#endif
+#if (STM32_UART5SEL == STM32_UART5SEL_HSI16)
+#error "HSI16 not enabled, required by STM32_UART5SEL"
+#endif
+#if (STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16)
+#error "HSI16 not enabled, required by STM32_LPUART1SEL"
+#endif
+
+#if (STM32_I2C1SEL == STM32_I2C1SEL_HSI16)
+#error "HSI16 not enabled, required by I2C1SEL"
+#endif
+#if (STM32_I2C2SEL == STM32_I2C2SEL_HSI16)
+#error "HSI16 not enabled, required by I2C2SEL"
+#endif
+#if (STM32_I2C3SEL == STM32_I2C3SEL_HSI16)
+#error "HSI16 not enabled, required by I2C3SEL"
+#endif
+#if (STM32_I2C4SEL == STM32_I2C4SEL_HSI16)
+#error "HSI16 not enabled, required by I2C4SEL"
+#endif
+
+#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16)
+#error "HSI16 not enabled, required by LPTIM1SEL"
+#endif
+#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16)
+#error "HSI16 not enabled, required by LPTIM2SEL"
+#endif
+
+#if (STM32_SWPMI1SEL == STM32_SWPMI1SEL_HSI16)
+#error "HSI16 not enabled, required by SWPMI1SEL"
+#endif
+#if (STM32_STOPWUCK == STM32_STOPWUCK_HSI16)
+#error "HSI16 not enabled, required by STM32_STOPWUCK"
+#endif
+
+#endif /* !STM32_HSI16_ENABLED */
+
+#if STM32_CLOCK_HAS_HSI48
+#if STM32_HSI48_ENABLED
+#else /* !STM32_HSI48_ENABLED */
+
+#if STM32_MCOSEL == STM32_MCOSEL_HSI48
+#error "HSI48 not enabled, required by STM32_MCOSEL"
+#endif
+
+#if STM32_CLK48SEL == STM32_CLK48SEL_HSI48
+#error "HSI48 not enabled, required by STM32_CLK48SEL"
+#endif
+#endif /* !STM32_HSI48_ENABLED */
+#endif /* STM32_CLOCK_HAS_HSI48 */
+
+/*
+ * HSE related checks.
+ */
+#if STM32_HSE_ENABLED
+
+ #if STM32_HSECLK == 0
+ #error "HSE frequency not defined"
+ #else /* STM32_HSECLK != 0 */
+ #if defined(STM32_HSE_BYPASS)
+ #if (STM32_HSECLK < STM32_HSECLK_BYP_MIN) || (STM32_HSECLK > STM32_HSECLK_BYP_MAX)
+ #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_BYP_MIN...STM32_HSECLK_BYP_MAX)"
+ #endif
+ #else /* !defined(STM32_HSE_BYPASS) */
+ #if (STM32_HSECLK < STM32_HSECLK_MIN) || (STM32_HSECLK > STM32_HSECLK_MAX)
+ #error "STM32_HSECLK outside acceptable range (STM32_HSECLK_MIN...STM32_HSECLK_MAX)"
+ #endif
+ #endif /* !defined(STM32_HSE_BYPASS) */
+ #endif /* STM32_HSECLK != 0 */
+
+ #else /* !STM32_HSE_ENABLED */
+
+ #if STM32_SW == STM32_SW_HSE
+ #error "HSE not enabled, required by STM32_SW"
+ #endif
+
+ #if (STM32_SW == STM32_SW_PLL) && (STM32_PLLSRC == STM32_PLLSRC_HSE)
+ #error "HSE not enabled, required by STM32_SW and STM32_PLLSRC"
+ #endif
+
+ #if (STM32_MCOSEL == STM32_MCOSEL_HSE) || \
+ ((STM32_MCOSEL == STM32_MCOSEL_PLL) && \
+ (STM32_PLLSRC == STM32_PLLSRC_HSE))
+ #error "HSE not enabled, required by STM32_MCOSEL"
+ #endif
+
+ #if ((STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) | \
+ (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2)) && \
+ (STM32_PLLSRC == STM32_PLLSRC_HSE)
+ #error "HSE not enabled, required by STM32_SAI1SEL"
+ #endif
+
+ #if ((STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) | \
+ (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2)) && \
+ (STM32_PLLSRC == STM32_PLLSRC_HSE)
+ #error "HSE not enabled, required by STM32_SAI2SEL"
+ #endif
+
+ #if STM32_RTCSEL == STM32_RTCSEL_HSEDIV
+ #error "HSE not enabled, required by STM32_RTCSEL"
+ #endif
+
+#endif /* !STM32_HSE_ENABLED */
+
+/*
+ * LSI related checks.
+ */
+#if STM32_LSI_ENABLED
+#else /* !STM32_LSI_ENABLED */
+
+ #if STM32_RTCSEL == STM32_RTCSEL_LSI
+ #error "LSI not enabled, required by STM32_RTCSEL"
+ #endif
+
+ #if STM32_MCOSEL == STM32_MCOSEL_LSI
+ #error "LSI not enabled, required by STM32_MCOSEL"
+ #endif
+
+ #if STM32_LSCOSEL == STM32_LSCOSEL_LSI
+ #error "LSI not enabled, required by STM32_LSCOSEL"
+ #endif
+
+#endif /* !STM32_LSI_ENABLED */
+
+/*
+ * LSE related checks.
+ */
+#if STM32_LSE_ENABLED
+
+ #if (STM32_LSECLK == 0)
+ #error "LSE frequency not defined"
+ #endif
+
+ #if (STM32_LSECLK < STM32_LSECLK_MIN) || (STM32_LSECLK > STM32_LSECLK_MAX)
+ #error "STM32_LSECLK outside acceptable range (STM32_LSECLK_MIN...STM32_LSECLK_MAX)"
+ #endif
+
+#else /* !STM32_LSE_ENABLED */
+
+ #if STM32_RTCSEL == STM32_RTCSEL_LSE
+ #error "LSE not enabled, required by STM32_RTCSEL"
+ #endif
+
+ #if STM32_MCOSEL == STM32_MCOSEL_LSE
+ #error "LSE not enabled, required by STM32_MCOSEL"
+ #endif
+
+ #if STM32_LSCOSEL == STM32_LSCOSEL_LSE
+ #error "LSE not enabled, required by STM32_LSCOSEL"
+ #endif
+
+ #if STM32_MSIPLL_ENABLED == TRUE
+ #error "LSE not enabled, required by STM32_MSIPLL_ENABLED"
+ #endif
+
+#endif /* !STM32_LSE_ENABLED */
+
+/*
+ * MSI related checks.
+ */
+#if (STM32_MSIRANGE == STM32_MSIRANGE_48M) && !STM32_MSIPLL_ENABLED
+#warning "STM32_MSIRANGE_48M should be used with STM32_MSIPLL_ENABLED"
+#endif
+
+/**
+ * @brief STM32_PLLM field.
+ */
+#if ((STM32_PLLM_VALUE >= 1) && (STM32_PLLM_VALUE <= 8)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLLM ((STM32_PLLM_VALUE - 1) << 4)
+#else
+#error "invalid STM32_PLLM_VALUE value specified"
+#endif
+
+/**
+ * @brief PLLs input clock frequency.
+ */
+#if (STM32_PLLSRC == STM32_PLLSRC_HSE) || defined(__DOXYGEN__)
+#define STM32_PLLCLKIN (STM32_HSECLK / STM32_PLLM_VALUE)
+
+#elif STM32_PLLSRC == STM32_PLLSRC_MSI
+#define STM32_PLLCLKIN (STM32_MSICLK / STM32_PLLM_VALUE)
+
+#elif STM32_PLLSRC == STM32_PLLSRC_HSI16
+#define STM32_PLLCLKIN (STM32_HSI16CLK / STM32_PLLM_VALUE)
+
+#elif STM32_PLLSRC == STM32_PLLSRC_NOCLOCK
+#define STM32_PLLCLKIN 0
+
+#else
+#error "invalid STM32_PLLSRC value specified"
+#endif
+
+/*
+ * PLLs input frequency range check.
+ */
+#if (STM32_PLLCLKIN != 0) && \
+ ((STM32_PLLCLKIN < STM32_PLLIN_MIN) || (STM32_PLLCLKIN > STM32_PLLIN_MAX))
+#error "STM32_PLLCLKIN outside acceptable range (STM32_PLLIN_MIN...STM32_PLLIN_MAX)"
+#endif
+
+/*
+ * PLL enable check.
+ */
+#if (STM32_HSI48_ENABLED && (STM32_CLK48SEL == STM32_CLK48SEL_PLL)) || \
+ (STM32_SW == STM32_SW_PLL) || \
+ (STM32_MCOSEL == STM32_MCOSEL_PLL) || \
+ (STM32_SAI1SEL == STM32_SAI1SEL_PLL) || \
+ (STM32_SAI2SEL == STM32_SAI2SEL_PLL) || \
+ defined(__DOXYGEN__)
+
+#if STM32_PLLCLKIN == 0
+#error "PLL activation required but no PLL clock selected"
+#endif
+
+/**
+ * @brief PLL activation flag.
+ */
+#define STM32_ACTIVATE_PLL TRUE
+#else
+#define STM32_ACTIVATE_PLL FALSE
+#endif
+
+/**
+ * @brief STM32_PLLN field.
+ */
+#if ((STM32_PLLN_VALUE >= 8) && (STM32_PLLN_VALUE <= 86)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLLN (STM32_PLLN_VALUE << 8)
+#else
+#error "invalid STM32_PLLN_VALUE value specified"
+#endif
+
+/**
+ * @brief STM32_PLLP field.
+ */
+#if (STM32_PLLP_VALUE == 7) || defined(__DOXYGEN__)
+#define STM32_PLLP (0 << 17)
+
+#elif STM32_PLLP_VALUE == 17
+#define STM32_PLLP (1 << 17)
+
+#else
+#error "invalid STM32_PLLP_VALUE value specified"
+#endif
+
+/**
+ * @brief STM32_PLLQ field.
+ */
+#if (STM32_PLLQ_VALUE == 2) || defined(__DOXYGEN__)
+#define STM32_PLLQ (0 << 21)
+
+#elif STM32_PLLQ_VALUE == 4
+#define STM32_PLLQ (1 << 21)
+
+#elif STM32_PLLQ_VALUE == 6
+#define STM32_PLLQ (2 << 21)
+
+#elif STM32_PLLQ_VALUE == 8
+#define STM32_PLLQ (3 << 21)
+
+#else
+#error "invalid STM32_PLLQ_VALUE value specified"
+#endif
+
+/**
+ * @brief STM32_PLLR field.
+ */
+#if (STM32_PLLR_VALUE == 2) || defined(__DOXYGEN__)
+#define STM32_PLLR (0 << 25)
+
+#elif STM32_PLLR_VALUE == 4
+#define STM32_PLLR (1 << 25)
+
+#elif STM32_PLLR_VALUE == 6
+#define STM32_PLLR (2 << 25)
+
+#elif STM32_PLLR_VALUE == 8
+#define STM32_PLLR (3 << 25)
+
+#else
+#error "invalid STM32_PLLR_VALUE value specified"
+#endif
+
+#if defined(STM32L496xx) || defined(STM32L4A6xx)
+/**
+ * @brief STM32_PLLPDIV field. (Only for STM32L496xx/4A6xx)
+ */
+#if (STM32_PLLPDIV_VALUE == 0) || \
+ ((STM32_PLLPDIV_VALUE >= 2) && (STM32_PLLPDIV_VALUE <= 31)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLLPDIV (STM32_PLLPDIV_VALUE << 27)
+#else
+#error "invalid STM32_PLLPDIV_VALUE value specified"
+#endif
+#endif
+
+/**
+ * @brief STM32_PLLPEN field.
+ */
+#if (STM32_SAI1SEL == STM32_SAI1SEL_PLL) || \
+ (STM32_SAI2SEL == STM32_SAI2SEL_PLL) || \
+ defined(__DOXYGEN__)
+#define STM32_PLLPEN (1 << 16)
+#else
+#define STM32_PLLPEN (0 << 16)
+#endif
+
+/**
+ * @brief STM32_PLLQEN field.
+ */
+#if (STM32_CLK48SEL == STM32_CLK48SEL_PLL) || defined(__DOXYGEN__)
+#define STM32_PLLQEN (1 << 20)
+#else
+#define STM32_PLLQEN (0 << 20)
+#endif
+
+/**
+ * @brief STM32_PLLREN field.
+ */
+#if (STM32_SW == STM32_SW_PLL) || \
+ (STM32_MCOSEL == STM32_MCOSEL_PLL) || \
+ defined(__DOXYGEN__)
+#define STM32_PLLREN (1 << 24)
+#else
+#define STM32_PLLREN (0 << 24)
+#endif
+
+/**
+ * @brief PLL VCO frequency.
+ */
+#define STM32_PLLVCO (STM32_PLLCLKIN * STM32_PLLN_VALUE)
+
+/*
+ * PLL VCO frequency range check.
+ */
+#if STM32_ACTIVATE_PLL && \
+ ((STM32_PLLVCO < STM32_PLLVCO_MIN) || (STM32_PLLVCO > STM32_PLLVCO_MAX))
+#error "STM32_PLLVCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)"
+#endif
+
+/**
+ * @brief PLL P output clock frequency.
+ */
+#if (STM32_PLLPDIV_VALUE == 0) || defined(__DOXYGEN__)
+#define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLP_VALUE)
+#else
+#define STM32_PLL_P_CLKOUT (STM32_PLLVCO / STM32_PLLPDIV_VALUE)
+#endif
+
+/**
+ * @brief PLL Q output clock frequency.
+ */
+#define STM32_PLL_Q_CLKOUT (STM32_PLLVCO / STM32_PLLQ_VALUE)
+
+/**
+ * @brief PLL R output clock frequency.
+ */
+#define STM32_PLL_R_CLKOUT (STM32_PLLVCO / STM32_PLLR_VALUE)
+
+/*
+ * PLL-P output frequency range check.
+ */
+#if STM32_ACTIVATE_PLL && \
+ ((STM32_PLL_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLL_P_CLKOUT > STM32_PLLP_MAX))
+#error "STM32_PLL_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)"
+#endif
+
+/*
+ * PLL-Q output frequency range check.
+ */
+#if STM32_ACTIVATE_PLL && \
+ ((STM32_PLL_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLL_Q_CLKOUT > STM32_PLLQ_MAX))
+#error "STM32_PLL_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)"
+#endif
+
+/*
+ * PLL-R output frequency range check.
+ */
+#if STM32_ACTIVATE_PLL && \
+ ((STM32_PLL_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLL_R_CLKOUT > STM32_PLLR_MAX))
+#error "STM32_PLL_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)"
+#endif
+
+/**
+ * @brief System clock source.
+ */
+#if STM32_NO_INIT || defined(__DOXYGEN__)
+#define STM32_SYSCLK STM32_MSICLK
+
+#elif (STM32_SW == STM32_SW_MSI)
+#define STM32_SYSCLK STM32_MSICLK
+
+#elif (STM32_SW == STM32_SW_HSI16)
+#define STM32_SYSCLK STM32_HSI16CLK
+
+#elif (STM32_SW == STM32_SW_HSE)
+#define STM32_SYSCLK STM32_HSECLK
+
+#elif (STM32_SW == STM32_SW_PLL)
+#define STM32_SYSCLK STM32_PLL_R_CLKOUT
+
+#else
+#error "invalid STM32_SW value specified"
+#endif
+
+/* Check on the system clock.*/
+#if STM32_SYSCLK > STM32_SYSCLK_MAX
+#error "STM32_SYSCLK above maximum rated frequency (STM32_SYSCLK_MAX)"
+#endif
+
+/**
+ * @brief AHB frequency.
+ */
+#if (STM32_HPRE == STM32_HPRE_DIV1) || defined(__DOXYGEN__)
+#define STM32_HCLK (STM32_SYSCLK / 1)
+
+#elif STM32_HPRE == STM32_HPRE_DIV2
+#define STM32_HCLK (STM32_SYSCLK / 2)
+
+#elif STM32_HPRE == STM32_HPRE_DIV4
+#define STM32_HCLK (STM32_SYSCLK / 4)
+
+#elif STM32_HPRE == STM32_HPRE_DIV8
+#define STM32_HCLK (STM32_SYSCLK / 8)
+
+#elif STM32_HPRE == STM32_HPRE_DIV16
+#define STM32_HCLK (STM32_SYSCLK / 16)
+
+#elif STM32_HPRE == STM32_HPRE_DIV64
+#define STM32_HCLK (STM32_SYSCLK / 64)
+
+#elif STM32_HPRE == STM32_HPRE_DIV128
+#define STM32_HCLK (STM32_SYSCLK / 128)
+
+#elif STM32_HPRE == STM32_HPRE_DIV256
+#define STM32_HCLK (STM32_SYSCLK / 256)
+
+#elif STM32_HPRE == STM32_HPRE_DIV512
+#define STM32_HCLK (STM32_SYSCLK / 512)
+
+#else
+#error "invalid STM32_HPRE value specified"
+#endif
+
+/*
+ * AHB frequency check.
+ */
+#if STM32_HCLK > STM32_SYSCLK_MAX
+#error "STM32_HCLK exceeding maximum frequency (STM32_SYSCLK_MAX)"
+#endif
+
+/**
+ * @brief APB1 frequency.
+ */
+#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__)
+#define STM32_PCLK1 (STM32_HCLK / 1)
+
+#elif STM32_PPRE1 == STM32_PPRE1_DIV2
+#define STM32_PCLK1 (STM32_HCLK / 2)
+
+#elif STM32_PPRE1 == STM32_PPRE1_DIV4
+#define STM32_PCLK1 (STM32_HCLK / 4)
+
+#elif STM32_PPRE1 == STM32_PPRE1_DIV8
+#define STM32_PCLK1 (STM32_HCLK / 8)
+
+#elif STM32_PPRE1 == STM32_PPRE1_DIV16
+#define STM32_PCLK1 (STM32_HCLK / 16)
+
+#else
+#error "invalid STM32_PPRE1 value specified"
+#endif
+
+/*
+ * APB1 frequency check.
+ */
+#if STM32_PCLK1 > STM32_PCLK1_MAX
+#error "STM32_PCLK1 exceeding maximum frequency (STM32_PCLK1_MAX)"
+#endif
+
+/**
+ * @brief APB2 frequency.
+ */
+#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__)
+#define STM32_PCLK2 (STM32_HCLK / 1)
+
+#elif STM32_PPRE2 == STM32_PPRE2_DIV2
+#define STM32_PCLK2 (STM32_HCLK / 2)
+
+#elif STM32_PPRE2 == STM32_PPRE2_DIV4
+#define STM32_PCLK2 (STM32_HCLK / 4)
+
+#elif STM32_PPRE2 == STM32_PPRE2_DIV8
+#define STM32_PCLK2 (STM32_HCLK / 8)
+
+#elif STM32_PPRE2 == STM32_PPRE2_DIV16
+#define STM32_PCLK2 (STM32_HCLK / 16)
+
+#else
+#error "invalid STM32_PPRE2 value specified"
+#endif
+
+/*
+ * APB2 frequency check.
+ */
+#if STM32_PCLK2 > STM32_PCLK2_MAX
+#error "STM32_PCLK2 exceeding maximum frequency (STM32_PCLK2_MAX)"
+#endif
+
+/*
+ * PLLSAI1 enable check.
+ */
+#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \
+ (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \
+ (STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1) || \
+ (STM32_ADCSEL == STM32_ADCSEL_PLLSAI1) || \
+ defined(__DOXYGEN__)
+
+#if STM32_PLLCLKIN == 0
+#error "PLLSAI1 activation required but no PLL clock selected"
+#endif
+
+/**
+ * @brief PLLSAI1 activation flag.
+ */
+#define STM32_ACTIVATE_PLLSAI1 TRUE
+#else
+#define STM32_ACTIVATE_PLLSAI1 FALSE
+#endif
+
+/**
+ * @brief STM32_PLLSAI1N field.
+ */
+#if ((STM32_PLLSAI1N_VALUE >= 8) && (STM32_PLLSAI1N_VALUE <= 86)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLLSAI1N (STM32_PLLSAI1N_VALUE << 8)
+#else
+#error "invalid STM32_PLLSAI1N_VALUE value specified"
+#endif
+
+/**
+ * @brief STM32_PLLSAI1P field.
+ */
+#if (STM32_PLLSAI1P_VALUE == 7) || defined(__DOXYGEN__)
+#define STM32_PLLSAI1P (0 << 17)
+
+#elif STM32_PLLSAI1P_VALUE == 17
+#define STM32_PLLSAI1P (1 << 17)
+
+#else
+#error "invalid STM32_PLLSAI1P_VALUE value specified"
+#endif
+
+/**
+ * @brief STM32_PLLSAI1Q field.
+ */
+#if (STM32_PLLSAI1Q_VALUE == 2) || defined(__DOXYGEN__)
+#define STM32_PLLSAI1Q (0 << 21)
+
+#elif STM32_PLLSAI1Q_VALUE == 4
+#define STM32_PLLSAI1Q (1 << 21)
+
+#elif STM32_PLLSAI1Q_VALUE == 6
+#define STM32_PLLSAI1Q (2 << 21)
+
+#elif STM32_PLLSAI1Q_VALUE == 8
+#define STM32_PLLSAI1Q (3 << 21)
+
+#else
+#error "invalid STM32_PLLSAI1Q_VALUE value specified"
+#endif
+
+/**
+ * @brief STM32_PLLSAI1R field.
+ */
+#if (STM32_PLLSAI1R_VALUE == 2) || defined(__DOXYGEN__)
+#define STM32_PLLSAI1R (0 << 25)
+
+#elif STM32_PLLSAI1R_VALUE == 4
+#define STM32_PLLSAI1R (1 << 25)
+
+#elif STM32_PLLSAI1R_VALUE == 6
+#define STM32_PLLSAI1R (2 << 25)
+
+#elif STM32_PLLSAI1R_VALUE == 8
+#define STM32_PLLSAI1R (3 << 25)
+
+#else
+#error "invalid STM32_PLLSAI1R_VALUE value specified"
+#endif
+
+#if defined(STM32L496xx) || defined(STM32L4A6xx)
+/**
+ * @brief STM32_PLLSAI1PDIV field. (Only for STM32L496xx/4A6xx)
+ */
+#if ((STM32_PLLSAI1PDIV_VALUE != 1) && (STM32_PLLSAI1PDIV_VALUE <= 31)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLLSAI1PDIV (STM32_PLLSAI1PDIV_VALUE << 27)
+#else
+#error "invalid STM32_PLLSAI1PDIV_VALUE value specified"
+#endif
+#endif
+
+/**
+ * @brief STM32_PLLSAI1PEN field.
+ */
+#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || \
+ (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || \
+ defined(__DOXYGEN__)
+#define STM32_PLLSAI1PEN (1 << 16)
+#else
+#define STM32_PLLSAI1PEN (0 << 16)
+#endif
+
+/**
+ * @brief STM32_PLLSAI1QEN field.
+ */
+#if (STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1) || defined(__DOXYGEN__)
+#define STM32_PLLSAI1QEN (1 << 20)
+#else
+#define STM32_PLLSAI1QEN (0 << 20)
+#endif
+
+/**
+ * @brief STM32_PLLSAI1REN field.
+ */
+#if (STM32_ADCSEL == STM32_ADCSEL_PLLSAI1) || defined(__DOXYGEN__)
+#define STM32_PLLSAI1REN (1 << 24)
+#else
+#define STM32_PLLSAI1REN (0 << 24)
+#endif
+
+/**
+ * @brief PLLSAI1 VCO frequency.
+ */
+#define STM32_PLLSAI1VCO (STM32_PLLCLKIN * STM32_PLLSAI1N_VALUE)
+
+/*
+ * PLLSAI1 VCO frequency range check.
+ */
+#if STM32_ACTIVATE_PLLSAI1 && \
+ ((STM32_PLLSAI1VCO < STM32_PLLVCO_MIN) || (STM32_PLLSAI1VCO > STM32_PLLVCO_MAX))
+#error "STM32_PLLSAI1VCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)"
+#endif
+
+/**
+ * @brief PLLSAI1-P output clock frequency.
+ */
+#if (STM32_PLLSAI1PDIV_VALUE == 0) || defined(__DOXYGEN__)
+#define STM32_PLLSAI1_P_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1P_VALUE)
+#else
+#define STM32_PLLSAI1_P_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1PDIV_VALUE)
+#endif
+
+/**
+ * @brief PLLSAI1-Q output clock frequency.
+ */
+#define STM32_PLLSAI1_Q_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1Q_VALUE)
+
+/**
+ * @brief PLLSAI1-R output clock frequency.
+ */
+#define STM32_PLLSAI1_R_CLKOUT (STM32_PLLSAI1VCO / STM32_PLLSAI1R_VALUE)
+
+/*
+ * PLLSAI1-P output frequency range check.
+ */
+#if STM32_ACTIVATE_PLLSAI1 && \
+ ((STM32_PLLSAI1_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLLSAI1_P_CLKOUT > STM32_PLLP_MAX))
+#error "STM32_PLLSAI1_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)"
+#endif
+
+/*
+ * PLLSAI1-Q output frequency range check.
+ */
+#if STM32_ACTIVATE_PLLSAI1 && \
+ ((STM32_PLLSAI1_Q_CLKOUT < STM32_PLLQ_MIN) || (STM32_PLLSAI1_Q_CLKOUT > STM32_PLLQ_MAX))
+#error "STM32_PLLSAI1_Q_CLKOUT outside acceptable range (STM32_PLLQ_MIN...STM32_PLLQ_MAX)"
+#endif
+
+/*
+ * PLLSAI1-R output frequency range check.
+ */
+#if STM32_ACTIVATE_PLLSAI1 && \
+ ((STM32_PLLSAI1_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLLSAI1_R_CLKOUT > STM32_PLLR_MAX))
+#error "STM32_PLLSAI1_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)"
+#endif
+
+/*
+ * PLLSAI2 enable check.
+ */
+#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2) || \
+ (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2) || \
+ (STM32_ADCSEL == STM32_ADCSEL_PLLSAI2) || \
+ defined(__DOXYGEN__)
+
+#if STM32_PLLCLKIN == 0
+#error "PLLSAI2 activation required but no PLL clock selected"
+#endif
+
+/**
+ * @brief PLLSAI2 activation flag.
+ */
+#define STM32_ACTIVATE_PLLSAI2 TRUE
+#else
+#define STM32_ACTIVATE_PLLSAI2 FALSE
+#endif
+
+/**
+ * @brief STM32_PLLSAI2N field.
+ */
+#if ((STM32_PLLSAI2N_VALUE >= 8) && (STM32_PLLSAI2N_VALUE <= 86)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLLSAI2N (STM32_PLLSAI2N_VALUE << 8)
+#else
+#error "invalid STM32_PLLSAI2N_VALUE value specified"
+#endif
+
+/**
+ * @brief STM32_PLLSAI2P field.
+ */
+#if (STM32_PLLSAI2P_VALUE == 7) || defined(__DOXYGEN__)
+#define STM32_PLLSAI2P (0 << 17)
+
+#elif STM32_PLLSAI2P_VALUE == 17
+#define STM32_PLLSAI2P (1 << 17)
+
+#else
+#error "invalid STM32_PLLSAI2P_VALUE value specified"
+#endif
+
+/**
+ * @brief STM32_PLLSAI2R field.
+ */
+#if (STM32_PLLSAI2R_VALUE == 2) || defined(__DOXYGEN__)
+#define STM32_PLLSAI2R (0 << 25)
+
+#elif STM32_PLLSAI2R_VALUE == 4
+#define STM32_PLLSAI2R (1 << 25)
+
+#elif STM32_PLLSAI2R_VALUE == 6
+#define STM32_PLLSAI2R (2 << 25)
+
+#elif STM32_PLLSAI2R_VALUE == 8
+#define STM32_PLLSAI2R (3 << 25)
+
+#else
+#error "invalid STM32_PLLSAI2R_VALUE value specified"
+#endif
+
+#if defined(STM32L496xx) || defined(STM32L4A6xx)
+/**
+ * @brief STM32_PLLSAI2PDIV field. (Only for STM32L496xx/4A6xx)
+ */
+#if ((STM32_PLLSAI2PDIV_VALUE != 1) && (STM32_PLLSAI2PDIV_VALUE <= 31)) || \
+ defined(__DOXYGEN__)
+#define STM32_PLLSAI2PDIV (STM32_PLLSAI2PDIV_VALUE << 27)
+#else
+#error "invalid STM32_PLLSAI2PDIV_VALUE value specified"
+#endif
+#endif
+
+/**
+ * @brief STM32_PLLSAI2PEN field.
+ */
+#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2) || \
+ (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2) || \
+ defined(__DOXYGEN__)
+#define STM32_PLLSAI2PEN (1 << 16)
+#else
+#define STM32_PLLSAI2PEN (0 << 16)
+#endif
+
+/**
+ * @brief STM32_PLLSAI2REN field.
+ */
+#if (STM32_ADCSEL == STM32_ADCSEL_PLLSAI2) || defined(__DOXYGEN__)
+#define STM32_PLLSAI2REN (1 << 24)
+#else
+#define STM32_PLLSAI2REN (0 << 24)
+#endif
+
+/**
+ * @brief PLLSAI2 VCO frequency.
+ */
+#define STM32_PLLSAI2VCO (STM32_PLLCLKIN * STM32_PLLSAI2N_VALUE)
+
+/*
+ * PLLSAI2 VCO frequency range check.
+ */
+#if STM32_ACTIVATE_PLLSAI2 && \
+ ((STM32_PLLSAI2VCO < STM32_PLLVCO_MIN) || (STM32_PLLSAI2VCO > STM32_PLLVCO_MAX))
+#error "STM32_PLLSAI2VCO outside acceptable range (STM32_PLLVCO_MIN...STM32_PLLVCO_MAX)"
+#endif
+
+/**
+ * @brief PLLSAI2-P output clock frequency.
+ */
+#if (STM32_PLLSAI2PDIV_VALUE == 0) || defined(__DOXYGEN__)
+#define STM32_PLLSAI2_P_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2P_VALUE)
+#else
+#define STM32_PLLSAI2_P_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2PDIV_VALUE)
+#endif
+
+/**
+ * @brief PLLSAI2-R output clock frequency.
+ */
+#define STM32_PLLSAI2_R_CLKOUT (STM32_PLLSAI2VCO / STM32_PLLSAI2R_VALUE)
+
+/*
+ * PLLSAI2-P output frequency range check.
+ */
+#if STM32_ACTIVATE_PLLSAI2 && \
+ ((STM32_PLLSAI2_P_CLKOUT < STM32_PLLP_MIN) || (STM32_PLLSAI2_P_CLKOUT > STM32_PLLP_MAX))
+#error "STM32_PLLSAI2_P_CLKOUT outside acceptable range (STM32_PLLP_MIN...STM32_PLLP_MAX)"
+#endif
+
+/*
+ * PLLSAI2-R output frequency range check.
+ */
+#if STM32_ACTIVATE_PLLSAI2 && \
+ ((STM32_PLLSAI2_R_CLKOUT < STM32_PLLR_MIN) || (STM32_PLLSAI2_R_CLKOUT > STM32_PLLR_MAX))
+#error "STM32_PLLSAI2_R_CLKOUT outside acceptable range (STM32_PLLR_MIN...STM32_PLLR_MAX)"
+#endif
+
+/**
+ * @brief MCO divider clock frequency.
+ */
+#if (STM32_MCOSEL == STM32_MCOSEL_NOCLOCK) || defined(__DOXYGEN__)
+#define STM32_MCODIVCLK 0
+
+#elif STM32_MCOSEL == STM32_MCOSEL_SYSCLK
+#define STM32_MCODIVCLK STM32_SYSCLK
+
+#elif STM32_MCOSEL == STM32_MCOSEL_MSI
+#define STM32_MCODIVCLK STM32_MSICLK
+
+#elif STM32_MCOSEL == STM32_MCOSEL_HSI16
+#define STM32_MCODIVCLK STM32_HSI16CLK
+
+#elif STM32_MCOSEL == STM32_MCOSEL_HSE
+#define STM32_MCODIVCLK STM32_HSECLK
+
+#elif STM32_MCOSEL == STM32_MCOSEL_PLL
+#define STM32_MCODIVCLK STM32_PLL_P_CLKOUT
+
+#elif STM32_MCOSEL == STM32_MCOSEL_LSI
+#define STM32_MCODIVCLK STM32_LSICLK
+
+#elif STM32_MCOSEL == STM32_MCOSEL_LSE
+#define STM32_MCODIVCLK STM32_LSECLK
+
+#elif STM32_MCOSEL == STM32_MCOSEL_HSI48
+#define STM32_MCODIVCLK STM32_HSI48CLK
+
+#else
+#error "invalid STM32_MCOSEL value specified"
+#endif
+
+/**
+ * @brief MCO output pin clock frequency.
+ */
+#if (STM32_MCOPRE == STM32_MCOPRE_DIV1) || defined(__DOXYGEN__)
+#define STM32_MCOCLK STM32_MCODIVCLK
+
+#elif STM32_MCOPRE == STM32_MCOPRE_DIV2
+#define STM32_MCOCLK (STM32_MCODIVCLK / 2)
+
+#elif STM32_MCOPRE == STM32_MCOPRE_DIV4
+#define STM32_MCOCLK (STM32_MCODIVCLK / 4)
+
+#elif STM32_MCOPRE == STM32_MCOPRE_DIV8
+#define STM32_MCOCLK (STM32_MCODIVCLK / 8)
+
+#elif STM32_MCOPRE == STM32_MCOPRE_DIV16
+#define STM32_MCOCLK (STM32_MCODIVCLK / 16)
+
+#else
+#error "invalid STM32_MCOPRE value specified"
+#endif
+
+/**
+ * @brief RTC clock frequency.
+ */
+#if (STM32_RTCSEL == STM32_RTCSEL_NOCLOCK) || defined(__DOXYGEN__)
+#define STM32_RTCCLK 0
+
+#elif STM32_RTCSEL == STM32_RTCSEL_LSE
+#define STM32_RTCCLK STM32_LSECLK
+
+#elif STM32_RTCSEL == STM32_RTCSEL_LSI
+#define STM32_RTCCLK STM32_LSICLK
+
+#elif STM32_RTCSEL == STM32_RTCSEL_HSEDIV
+#define STM32_RTCCLK (STM32_HSECLK / 32)
+
+#else
+#error "invalid STM32_RTCSEL value specified"
+#endif
+
+/**
+ * @brief USART1 clock frequency.
+ */
+#if (STM32_USART1SEL == STM32_USART1SEL_PCLK2) || defined(__DOXYGEN__)
+#define STM32_USART1CLK STM32_PCLK2
+#elif STM32_USART1SEL == STM32_USART1SEL_SYSCLK
+#define STM32_USART1CLK STM32_SYSCLK
+#elif STM32_USART1SEL == STM32_USART1SEL_HSI16
+#define STM32_USART1CLK STM32_HSI16CLK
+#elif STM32_USART1SEL == STM32_USART1SEL_LSE
+#define STM32_USART1CLK STM32_LSECLK
+#else
+#error "invalid source selected for USART1 clock"
+#endif
+
+/**
+ * @brief USART2 clock frequency.
+ */
+#if (STM32_USART2SEL == STM32_USART2SEL_PCLK1) || defined(__DOXYGEN__)
+#define STM32_USART2CLK STM32_PCLK1
+#elif STM32_USART2SEL == STM32_USART2SEL_SYSCLK
+#define STM32_USART2CLK STM32_SYSCLK
+#elif STM32_USART2SEL == STM32_USART2SEL_HSI16
+#define STM32_USART2CLK STM32_HSI16CLK
+#elif STM32_USART2SEL == STM32_USART2SEL_LSE
+#define STM32_USART2CLK STM32_LSECLK
+#else
+#error "invalid source selected for USART2 clock"
+#endif
+
+/**
+ * @brief USART3 clock frequency.
+ */
+#if (STM32_USART3SEL == STM32_USART3SEL_PCLK1) || defined(__DOXYGEN__)
+#define STM32_USART3CLK STM32_PCLK1
+#elif STM32_USART3SEL == STM32_USART3SEL_SYSCLK
+#define STM32_USART3CLK STM32_SYSCLK
+#elif STM32_USART3SEL == STM32_USART3SEL_HSI16
+#define STM32_USART3CLK STM32_HSI16CLK
+#elif STM32_USART3SEL == STM32_USART3SEL_LSE
+#define STM32_USART3CLK STM32_LSECLK
+#else
+#error "invalid source selected for USART3 clock"
+#endif
+
+/**
+ * @brief UART4 clock frequency.
+ */
+#if (STM32_UART4SEL == STM32_UART4SEL_PCLK1) || defined(__DOXYGEN__)
+#define STM32_UART4CLK STM32_PCLK1
+#elif STM32_UART4SEL == STM32_UART4SEL_SYSCLK
+#define STM32_UART4CLK STM32_SYSCLK
+#elif STM32_UART4SEL == STM32_UART4SEL_HSI16
+#define STM32_UART4CLK STM32_HSI16CLK
+#elif STM32_UART4SEL == STM32_UART4SEL_LSE
+#define STM32_UART4CLK STM32_LSECLK
+#else
+#error "invalid source selected for UART4 clock"
+#endif
+
+/**
+ * @brief UART5 clock frequency.
+ */
+#if (STM32_UART5SEL == STM32_UART5SEL_PCLK1) || defined(__DOXYGEN__)
+#define STM32_UART5CLK STM32_PCLK1
+#elif STM32_UART5SEL == STM32_UART5SEL_SYSCLK
+#define STM32_UART5CLK STM32_SYSCLK
+#elif STM32_UART5SEL == STM32_UART5SEL_HSI16
+#define STM32_UART5CLK STM32_HSI16CLK
+#elif STM32_UART5SEL == STM32_UART5SEL_LSE
+#define STM32_UART5CLK STM32_LSECLK
+#else
+#error "invalid source selected for UART5 clock"
+#endif
+
+/**
+ * @brief LPUART1 clock frequency.
+ */
+#if (STM32_LPUART1SEL == STM32_LPUART1SEL_PCLK1) || defined(__DOXYGEN__)
+#define STM32_LPUART1CLK STM32_PCLK1
+#elif STM32_LPUART1SEL == STM32_LPUART1SEL_SYSCLK
+#define STM32_LPUART1CLK STM32_SYSCLK
+#elif STM32_LPUART1SEL == STM32_LPUART1SEL_HSI16
+#define STM32_LPUART1CLK STM32_HSI16CLK
+#elif STM32_LPUART1SEL == STM32_LPUART1SEL_LSE
+#define STM32_LPUART1CLK STM32_LSECLK
+#else
+#error "invalid source selected for LPUART1 clock"
+#endif
+
+/**
+ * @brief I2C1 clock frequency.
+ */
+#if (STM32_I2C1SEL == STM32_I2C1SEL_PCLK1) || defined(__DOXYGEN__)
+#define STM32_I2C1CLK STM32_PCLK1
+#elif STM32_I2C1SEL == STM32_I2C1SEL_SYSCLK
+#define STM32_I2C1CLK STM32_SYSCLK
+#elif STM32_I2C1SEL == STM32_I2C1SEL_HSI16
+#define STM32_I2C1CLK STM32_HSI16CLK
+#else
+#error "invalid source selected for I2C1 clock"
+#endif
+
+/**
+ * @brief I2C2 clock frequency.
+ */
+#if (STM32_I2C2SEL == STM32_I2C2SEL_PCLK1) || defined(__DOXYGEN__)
+#define STM32_I2C2CLK STM32_PCLK1
+#elif STM32_I2C2SEL == STM32_I2C2SEL_SYSCLK
+#define STM32_I2C2CLK STM32_SYSCLK
+#elif STM32_I2C2SEL == STM32_I2C2SEL_HSI16
+#define STM32_I2C2CLK STM32_HSI16CLK
+#else
+#error "invalid source selected for I2C2 clock"
+#endif
+
+/**
+ * @brief I2C3 clock frequency.
+ */
+#if (STM32_I2C3SEL == STM32_I2C3SEL_PCLK1) || defined(__DOXYGEN__)
+#define STM32_I2C3CLK STM32_PCLK1
+#elif STM32_I2C3SEL == STM32_I2C3SEL_SYSCLK
+#define STM32_I2C3CLK STM32_SYSCLK
+#elif STM32_I2C3SEL == STM32_I2C3SEL_HSI16
+#define STM32_I2C3CLK STM32_HSI16CLK
+#else
+#error "invalid source selected for I2C3 clock"
+#endif
+
+/**
+ * @brief I2C4 clock frequency.
+ */
+#if (STM32_I2C4SEL == STM32_I2C4SEL_PCLK1) || defined(__DOXYGEN__)
+#define STM32_I2C4CLK STM32_PCLK1
+#elif STM32_I2C4SEL == STM32_I2C4SEL_SYSCLK
+#define STM32_I2C4CLK STM32_SYSCLK
+#elif STM32_I2C4SEL == STM32_I2C4SEL_HSI16
+#define STM32_I2C4CLK STM32_HSI16CLK
+#else
+#error "invalid source selected for I2C4 clock"
+#endif
+
+/**
+ * @brief LPTIM1 clock frequency.
+ */
+#if (STM32_LPTIM1SEL == STM32_LPTIM1SEL_PCLK1) || defined(__DOXYGEN__)
+#define STM32_LPTIM1CLK STM32_PCLK1
+#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSI
+#define STM32_LPTIM1CLK STM32_LSICLK
+#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_HSI16
+#define STM32_LPTIM1CLK STM32_HSI16CLK
+#elif STM32_LPTIM1SEL == STM32_LPTIM1SEL_LSE
+#define STM32_LPTIM1CLK STM32_LSECLK
+#else
+#error "invalid source selected for LPTIM1 clock"
+#endif
+
+/**
+ * @brief LPTIM2 clock frequency.
+ */
+#if (STM32_LPTIM2SEL == STM32_LPTIM2SEL_PCLK1) || defined(__DOXYGEN__)
+#define STM32_LPTIM2CLK STM32_PCLK1
+#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSI
+#define STM32_LPTIM2CLK STM32_LSICLK
+#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_HSI16
+#define STM32_LPTIM2CLK STM32_HSI16CLK
+#elif STM32_LPTIM2SEL == STM32_LPTIM2SEL_LSE
+#define STM32_LPTIM2CLK STM32_LSECLK
+#else
+#error "invalid source selected for LPTIM2 clock"
+#endif
+
+/**
+ * @brief 48MHz clock frequency.
+ */
+#if !STM32_CLOCK_HAS_HSI48 || defined(__DOXYGEN__)
+
+#if (STM32_CLK48SEL == STM32_CLK48SEL_NOCLK) || defined(__DOXYGEN__)
+#define STM32_48CLK 0
+#elif STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1
+#define STM32_48CLK (STM32_PLLSAI1VCO / STM32_PLLSAI1Q_VALUE)
+#elif STM32_CLK48SEL == STM32_CLK48SEL_PLL
+#define STM32_48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE)
+#elif STM32_CLK48SEL == STM32_CLK48SEL_MSI
+#define STM32_48CLK STM32_MSICLK
+#else
+#error "invalid source selected for 48CLK clock"
+#endif
+
+#else /* STM32_CLOCK_HAS_HSI48 */
+
+#if (STM32_CLK48SEL == STM32_CLK48SEL_HSI48) || defined(__DOXYGEN__)
+#define STM32_48CLK STM32_HSI48CLK
+#elif STM32_CLK48SEL == STM32_CLK48SEL_PLLSAI1
+#define STM32_48CLK (STM32_PLLSAI1VCO / STM32_PLLSAI1Q_VALUE)
+#elif STM32_CLK48SEL == STM32_CLK48SEL_PLL
+#define STM32_48CLK (STM32_PLLVCO / STM32_PLLQ_VALUE)
+#elif STM32_CLK48SEL == STM32_CLK48SEL_MSI
+#define STM32_48CLK STM32_MSICLK
+#else
+#error "invalid source selected for 48CLK clock"
+#endif
+
+#endif /* STM32_CLOCK_HAS_HSI48 */
+
+/**
+ * @brief SAI1 clock frequency.
+ */
+#if (STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI1) || defined(__DOXYGEN__)
+#define STM32_SAI1CLK STM32_PLLSAI1_P_CLKOUT
+#elif STM32_SAI1SEL == STM32_SAI1SEL_PLLSAI2
+#define STM32_SAI1CLK STM32_PLLSAI2_P_CLKOUT
+#elif STM32_SAI1SEL == STM32_SAI1SEL_PLL
+#define STM32_SAI1CLK STM32_PLL_P_CLKOUT
+#elif STM32_SAI1SEL == STM32_SAI1SEL_EXTCLK
+#define STM32_SAI1CLK 0 /* Unknown, would require a board value */
+#elif STM32_SAI1SEL == STM32_SAI1SEL_OFF
+#define STM32_SAI1CLK 0
+#else
+#error "invalid source selected for SAI1 clock"
+#endif
+
+/**
+ * @brief SAI2 clock frequency.
+ */
+#if (STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI1) || defined(__DOXYGEN__)
+#define STM32_SAI2CLK STM32_PLLSAI1_P_CLKOUT
+#elif STM32_SAI2SEL == STM32_SAI2SEL_PLLSAI2
+#define STM32_SAI2CLK STM32_PLLSAI2_P_CLKOUT
+#elif STM32_SAI2SEL == STM32_SAI2SEL_PLL
+#define STM32_SAI2CLK STM32_PLL_P_CLKOUT
+#elif STM32_SAI2SEL == STM32_SAI2SEL_EXTCLK
+#define STM32_SAI2CLK 0 /* Unknown, would require a board value */
+#elif STM32_SAI2SEL == STM32_SAI2SEL_OFF
+#define STM32_SAI2CLK 0
+#else
+#error "invalid source selected for SAI2 clock"
+#endif
+
+/**
+ * @brief USB clock point.
+ */
+#define STM32_USBCLK STM32_48CLK
+
+/**
+ * @brief RNG clock point.
+ */
+#define STM32_RNGCLK STM32_48CLK
+
+/**
+ * @brief ADC clock frequency.
+ */
+#if (STM32_ADCSEL == STM32_ADCSEL_NOCLK) || defined(__DOXYGEN__)
+#define STM32_ADCCLK 0
+#elif STM32_ADCSEL == STM32_ADCSEL_PLLSAI1
+#define STM32_ADCCLK STM32_PLLSAI1_R_CLKOUT
+#elif STM32_ADCSEL == STM32_ADCSEL_PLLSAI2
+#define STM32_ADCCLK STM32_PLLSAI2_R_CLKOUT
+#elif STM32_ADCSEL == STM32_ADCSEL_SYSCLK
+#define STM32_ADCCLK STM32_SYSCLK
+#else
+#error "invalid source selected for ADC clock"
+#endif
+
+/**
+ * @brief SWPMI1 clock frequency.
+ */
+#if (STM32_SWPMI1SEL == STM32_SWPMI1SEL_PCLK1) || defined(__DOXYGEN__)
+#define STM32_SWPMI1CLK STM32_PCLK1
+#elif STM32_SWPMI1SEL == STM32_SWPMI1SEL_HSI16
+#define STM32_SWPMI1CLK STM32_HSI16CLK
+#else
+#error "invalid source selected for SWPMI1 clock"
+#endif
+
+/**
+ * @brief DFSDM clock frequency.
+ */
+#if (STM32_DFSDMSEL == STM32_DFSDMSEL_PCLK2) || defined(__DOXYGEN__)
+#define STM32_DFSDMCLK STM32_PCLK2
+#elif STM32_DFSDMSEL == STM32_DFSDMSEL_SYSCLK
+#define STM32_DFSDMCLK STM32_SYSCLK
+#else
+#error "invalid source selected for DFSDM clock"
+#endif
+
+/**
+ * @brief SDMMC frequency.
+ */
+#define STM32_SDMMC1CLK STM32_48CLK
+
+/**
+ * @brief Clock of timers connected to APB1
+ */
+#if (STM32_PPRE1 == STM32_PPRE1_DIV1) || defined(__DOXYGEN__)
+#define STM32_TIMCLK1 (STM32_PCLK1 * 1)
+#else
+#define STM32_TIMCLK1 (STM32_PCLK1 * 2)
+#endif
+
+/**
+ * @brief Clock of timers connected to APB2.
+ */
+#if (STM32_PPRE2 == STM32_PPRE2_DIV1) || defined(__DOXYGEN__)
+#define STM32_TIMCLK2 (STM32_PCLK2 * 1)
+#else
+#define STM32_TIMCLK2 (STM32_PCLK2 * 2)
+#endif
+
+/**
+ * @brief Flash settings.
+ */
+#if (STM32_HCLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__)
+#define STM32_FLASHBITS FLASH_ACR_LATENCY_0WS
+
+#elif STM32_HCLK <= STM32_1WS_THRESHOLD
+#define STM32_FLASHBITS FLASH_ACR_LATENCY_1WS
+
+#elif STM32_HCLK <= STM32_2WS_THRESHOLD
+#define STM32_FLASHBITS FLASH_ACR_LATENCY_2WS
+
+#elif STM32_HCLK <= STM32_3WS_THRESHOLD
+#define STM32_FLASHBITS FLASH_ACR_LATENCY_3WS
+
+#else
+#define STM32_FLASHBITS FLASH_ACR_LATENCY_4WS
+#endif
+
+/**
+ * @brief Flash settings for MSI.
+ */
+#if (STM32_MSICLK <= STM32_0WS_THRESHOLD) || defined(__DOXYGEN__)
+#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_0WS
+
+#elif STM32_MSICLK <= STM32_1WS_THRESHOLD
+#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_1WS
+
+#elif STM32_MSICLK <= STM32_2WS_THRESHOLD
+#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_2WS
+
+#elif STM32_MSICLK <= STM32_3WS_THRESHOLD
+#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_3WS
+
+#else
+#define STM32_MSI_FLASHBITS FLASH_ACR_LATENCY_4WS
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/* Various helpers.*/
+#include "nvic.h"
+#include "cache.h"
+#include "mpu_v7m.h"
+#include "stm32_isr.h"
+#include "stm32_dma.h"
+#include "stm32_exti.h"
+#include "stm32_rcc.h"
+#include "stm32_tim.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void hal_lld_init(void);
+ void stm32_clock_init(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/platform.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/platform.mk
new file mode 100644
index 0000000..5426ea3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/platform.mk
@@ -0,0 +1,49 @@
+# Required platform files.
+PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \
+ $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx/stm32_isr.c \
+ $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx/hal_lld.c \
+ $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx/hal_efl_lld.c
+
+# Required include directories.
+PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \
+ $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx
+
+# Optional platform files.
+ifeq ($(USE_SMART_BUILD),yes)
+
+# Configuration files directory
+ifeq ($(HALCONFDIR),)
+ ifeq ($(CONFDIR),)
+ HALCONFDIR = .
+ else
+ HALCONFDIR := $(CONFDIR)
+ endif
+endif
+
+HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define"))
+
+else
+endif
+
+# Drivers compatible with the platform.
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/CRYPv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv3/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/OTGv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk
+
+# Shared variables
+ALLCSRC += $(PLATFORMSRC)
+ALLINC += $(PLATFORMINC)
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/platform_l432.mk b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/platform_l432.mk
new file mode 100644
index 0000000..ba67f99
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/platform_l432.mk
@@ -0,0 +1,47 @@
+# Required platform files.
+PLATFORMSRC := $(CHIBIOS)/os/hal/ports/common/ARMCMx/nvic.c \
+ $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx/stm32_isr.c \
+ $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx/hal_lld.c
+
+# Required include directories.
+PLATFORMINC := $(CHIBIOS)/os/hal/ports/common/ARMCMx \
+ $(CHIBIOS)/os/hal/ports/STM32/STM32L4xx
+
+# Optional platform files.
+ifeq ($(USE_SMART_BUILD),yes)
+
+# Configuration files directory
+ifeq ($(HALCONFDIR),)
+ ifeq ($(CONFDIR),)
+ HALCONFDIR = .
+ else
+ HALCONFDIR := $(CONFDIR)
+ endif
+endif
+
+HALCONF := $(strip $(shell cat $(HALCONFDIR)/halconf.h | egrep -e "\#define"))
+
+else
+endif
+
+# Drivers compatible with the platform.
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/ADCv3/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/CANv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/DACv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/DMAv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/EXTIv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/GPIOv3/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/QUADSPIv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/RNGv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/RTCv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/SDMMCv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/USARTv2/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/USBv1/driver.mk
+include $(CHIBIOS)/os/hal/ports/STM32/LLD/xWDGv1/driver.mk
+
+# Shared variables
+ALLCSRC += $(PLATFORMSRC)
+ALLINC += $(PLATFORMINC)
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/stm32_isr.c b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/stm32_isr.c
new file mode 100644
index 0000000..291a6c2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/stm32_isr.c
@@ -0,0 +1,159 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32L4xx/stm32_isr.c
+ * @brief STM32L4xx ISR handler code.
+ *
+ * @addtogroup STM32L4xx_ISR
+ * @{
+ */
+
+#include "hal.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#define exti_serve_irq(pr, channel) { \
+ \
+ if ((pr) & (1U << (channel))) { \
+ _pal_isr_code(channel); \
+ } \
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+#include "stm32_exti0.inc"
+#include "stm32_exti1.inc"
+#include "stm32_exti2.inc"
+#include "stm32_exti3.inc"
+#include "stm32_exti4.inc"
+#include "stm32_exti5_9.inc"
+#include "stm32_exti10_15.inc"
+#include "stm32_exti16-35_38.inc"
+#include "stm32_exti18.inc"
+#include "stm32_exti19.inc"
+#include "stm32_exti20.inc"
+#include "stm32_exti21_22.inc"
+
+#include "stm32_usart1.inc"
+#include "stm32_usart2.inc"
+#include "stm32_usart3.inc"
+#include "stm32_uart4.inc"
+#include "stm32_uart5.inc"
+#include "stm32_lpuart1.inc"
+
+#include "stm32_tim1_15_16_17.inc"
+#include "stm32_tim2.inc"
+#include "stm32_tim3.inc"
+#include "stm32_tim4.inc"
+#include "stm32_tim5.inc"
+#include "stm32_tim6.inc"
+#include "stm32_tim7.inc"
+#include "stm32_tim8.inc"
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables IRQ sources.
+ *
+ * @notapi
+ */
+void irqInit(void) {
+
+ exti0_irq_init();
+ exti1_irq_init();
+ exti2_irq_init();
+ exti3_irq_init();
+ exti4_irq_init();
+ exti5_9_irq_init();
+ exti10_15_irq_init();
+ exti16_exti35_38_irq_init();
+ exti18_irq_init();
+ exti19_irq_init();
+ exti21_22_irq_init();
+
+ tim1_tim15_tim16_tim17_irq_init();
+ tim2_irq_init();
+ tim3_irq_init();
+ tim4_irq_init();
+ tim5_irq_init();
+ tim6_irq_init();
+ tim7_irq_init();
+ tim8_irq_init();
+
+ usart1_irq_init();
+ usart2_irq_init();
+ usart3_irq_init();
+ uart4_irq_init();
+ uart5_irq_init();
+ lpuart1_irq_init();
+}
+
+/**
+ * @brief Disables IRQ sources.
+ *
+ * @notapi
+ */
+void irqDeinit(void) {
+
+ exti0_irq_deinit();
+ exti1_irq_deinit();
+ exti2_irq_deinit();
+ exti3_irq_deinit();
+ exti4_irq_deinit();
+ exti5_9_irq_deinit();
+ exti10_15_irq_deinit();
+ exti16_exti35_38_irq_deinit();
+ exti18_irq_deinit();
+ exti19_irq_deinit();
+ exti21_22_irq_deinit();
+
+ tim1_tim15_tim16_tim17_irq_deinit();
+ tim2_irq_deinit();
+ tim3_irq_deinit();
+ tim4_irq_deinit();
+ tim5_irq_deinit();
+ tim6_irq_deinit();
+ tim7_irq_deinit();
+ tim8_irq_deinit();
+
+ usart1_irq_deinit();
+ usart2_irq_deinit();
+ usart3_irq_deinit();
+ uart4_irq_deinit();
+ uart5_irq_deinit();
+ lpuart1_irq_deinit();
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/stm32_isr.h b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/stm32_isr.h
new file mode 100644
index 0000000..f4a6294
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/stm32_isr.h
@@ -0,0 +1,289 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32L4xx/stm32_isr.h
+ * @brief STM32L4xx ISR handler header.
+ *
+ * @addtogroup SRM32L4xx_ISR
+ * @{
+ */
+
+#ifndef STM32_ISR_H
+#define STM32_ISR_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name ISRs suppressed in standard drivers
+ * @{
+ */
+#define STM32_TIM1_SUPPRESS_ISR
+#define STM32_TIM2_SUPPRESS_ISR
+#define STM32_TIM3_SUPPRESS_ISR
+#define STM32_TIM4_SUPPRESS_ISR
+#define STM32_TIM5_SUPPRESS_ISR
+#define STM32_TIM6_SUPPRESS_ISR
+#define STM32_TIM7_SUPPRESS_ISR
+#define STM32_TIM8_SUPPRESS_ISR
+#define STM32_TIM15_SUPPRESS_ISR
+#define STM32_TIM16_SUPPRESS_ISR
+#define STM32_TIM17_SUPPRESS_ISR
+
+#define STM32_USART1_SUPPRESS_ISR
+#define STM32_USART2_SUPPRESS_ISR
+#define STM32_USART3_SUPPRESS_ISR
+#define STM32_UART4_SUPPRESS_ISR
+#define STM32_UART5_SUPPRESS_ISR
+#define STM32_LPUART1_SUPPRESS_ISR
+/** @} */
+
+/**
+ * @name ISR names and numbers
+ * @{
+ */
+/*
+ * ADC unit.
+ */
+#define STM32_ADC1_HANDLER Vector88
+#define STM32_ADC2_HANDLER Vector88
+#define STM32_ADC3_HANDLER VectorFC
+
+#define STM32_ADC1_NUMBER 18
+#define STM32_ADC2_NUMBER 18
+#define STM32_ADC3_NUMBER 47
+
+/*
+ * CAN unit.
+ */
+#define STM32_CAN1_TX_HANDLER Vector8C
+#define STM32_CAN1_RX0_HANDLER Vector90
+#define STM32_CAN1_RX1_HANDLER Vector94
+#define STM32_CAN1_SCE_HANDLER Vector98
+#define STM32_CAN2_TX_HANDLER Vector198
+#define STM32_CAN2_RX0_HANDLER Vector19C
+#define STM32_CAN2_RX1_HANDLER Vector1A0
+#define STM32_CAN2_SCE_HANDLER Vector1A4
+
+#define STM32_CAN1_TX_NUMBER 19
+#define STM32_CAN1_RX0_NUMBER 20
+#define STM32_CAN1_RX1_NUMBER 21
+#define STM32_CAN1_SCE_NUMBER 22
+#define STM32_CAN2_TX_NUMBER 86
+#define STM32_CAN2_RX0_NUMBER 87
+#define STM32_CAN2_RX1_NUMBER 88
+#define STM32_CAN2_SCE_NUMBER 89
+
+/*
+ * DMA unit.
+ */
+#define STM32_DMA1_CH1_HANDLER Vector6C
+#define STM32_DMA1_CH2_HANDLER Vector70
+#define STM32_DMA1_CH3_HANDLER Vector74
+#define STM32_DMA1_CH4_HANDLER Vector78
+#define STM32_DMA1_CH5_HANDLER Vector7C
+#define STM32_DMA1_CH6_HANDLER Vector80
+#define STM32_DMA1_CH7_HANDLER Vector84
+#define STM32_DMA2_CH1_HANDLER Vector120
+#define STM32_DMA2_CH2_HANDLER Vector124
+#define STM32_DMA2_CH3_HANDLER Vector128
+#define STM32_DMA2_CH4_HANDLER Vector12C
+#define STM32_DMA2_CH5_HANDLER Vector130
+#define STM32_DMA2_CH6_HANDLER Vector150
+#define STM32_DMA2_CH7_HANDLER Vector154
+
+#define STM32_DMA1_CH1_NUMBER 11
+#define STM32_DMA1_CH2_NUMBER 12
+#define STM32_DMA1_CH3_NUMBER 13
+#define STM32_DMA1_CH4_NUMBER 14
+#define STM32_DMA1_CH5_NUMBER 15
+#define STM32_DMA1_CH6_NUMBER 16
+#define STM32_DMA1_CH7_NUMBER 17
+#define STM32_DMA2_CH1_NUMBER 56
+#define STM32_DMA2_CH2_NUMBER 57
+#define STM32_DMA2_CH3_NUMBER 58
+#define STM32_DMA2_CH4_NUMBER 59
+#define STM32_DMA2_CH5_NUMBER 60
+#define STM32_DMA2_CH6_NUMBER 68
+#define STM32_DMA2_CH7_NUMBER 69
+
+/*
+ * EXTI unit.
+ */
+#define STM32_EXTI0_HANDLER Vector58
+#define STM32_EXTI1_HANDLER Vector5C
+#define STM32_EXTI2_HANDLER Vector60
+#define STM32_EXTI3_HANDLER Vector64
+#define STM32_EXTI4_HANDLER Vector68
+#define STM32_EXTI5_9_HANDLER Vector9C
+#define STM32_EXTI10_15_HANDLER VectorE0
+#define STM32_EXTI1635_38_HANDLER Vector44 /* PVD PVM1 PVM4 */
+#define STM32_EXTI18_HANDLER VectorE4 /* RTC ALARM */
+#define STM32_EXTI19_HANDLER Vector48 /* RTC TAMP CSS */
+#define STM32_EXTI20_HANDLER Vector4C /* RTC WAKEUP */
+#define STM32_EXTI21_22_HANDLER Vector140 /* COMP1..2 */
+
+#define STM32_EXTI0_NUMBER 6
+#define STM32_EXTI1_NUMBER 7
+#define STM32_EXTI2_NUMBER 8
+#define STM32_EXTI3_NUMBER 9
+#define STM32_EXTI4_NUMBER 10
+#define STM32_EXTI5_9_NUMBER 23
+#define STM32_EXTI10_15_NUMBER 40
+#define STM32_EXTI1635_38_NUMBER 1
+#define STM32_EXTI18_NUMBER 41
+#define STM32_EXTI19_NUMBER 2
+#define STM32_EXTI20_NUMBER 3
+#define STM32_EXTI21_22_NUMBER 64
+
+/*
+ * I2C units.
+ */
+#define STM32_I2C1_EVENT_HANDLER VectorBC
+#define STM32_I2C1_ERROR_HANDLER VectorC0
+#define STM32_I2C2_EVENT_HANDLER VectorC4
+#define STM32_I2C2_ERROR_HANDLER VectorC8
+#define STM32_I2C3_EVENT_HANDLER Vector160
+#define STM32_I2C3_ERROR_HANDLER Vector164
+#define STM32_I2C4_EVENT_HANDLER Vector18C
+#define STM32_I2C4_ERROR_HANDLER Vector190
+
+#define STM32_I2C1_EVENT_NUMBER 31
+#define STM32_I2C1_ERROR_NUMBER 32
+#define STM32_I2C2_EVENT_NUMBER 33
+#define STM32_I2C2_ERROR_NUMBER 34
+#define STM32_I2C3_EVENT_NUMBER 72
+#define STM32_I2C3_ERROR_NUMBER 73
+#define STM32_I2C4_EVENT_NUMBER 83
+#define STM32_I2C4_ERROR_NUMBER 84
+
+/*
+ * QUADSPI unit.
+ */
+#define STM32_QUADSPI1_HANDLER Vector15C
+
+#define STM32_QUADSPI1_NUMBER 71
+
+/*
+ * SDMMC unit.
+ */
+#define STM32_SDMMC1_HANDLER Vector104
+
+#define STM32_SDMMC1_NUMBER 49
+
+/*
+ * TIM units.
+ */
+#define STM32_TIM1_BRK_TIM15_HANDLER VectorA0
+#define STM32_TIM1_UP_TIM16_HANDLER VectorA4
+#define STM32_TIM1_TRGCO_TIM17_HANDLER VectorA8
+#define STM32_TIM1_CC_HANDLER VectorAC
+#define STM32_TIM2_HANDLER VectorB0
+#define STM32_TIM3_HANDLER VectorB4
+#define STM32_TIM4_HANDLER VectorB8
+#define STM32_TIM5_HANDLER Vector108
+#define STM32_TIM6_HANDLER Vector118
+#define STM32_TIM7_HANDLER Vector11C
+#define STM32_TIM8_BRK_HANDLER VectorEC
+#define STM32_TIM8_UP_HANDLER VectorF0
+#define STM32_TIM8_TRGCO_HANDLER VectorF4
+#define STM32_TIM8_CC_HANDLER VectorF8
+
+#define STM32_TIM1_BRK_TIM15_NUMBER 24
+#define STM32_TIM1_UP_TIM16_NUMBER 25
+#define STM32_TIM1_TRGCO_TIM17_NUMBER 26
+#define STM32_TIM1_CC_NUMBER 27
+#define STM32_TIM2_NUMBER 28
+#define STM32_TIM3_NUMBER 29
+#define STM32_TIM4_NUMBER 30
+#define STM32_TIM5_NUMBER 50
+#define STM32_TIM6_NUMBER 54
+#define STM32_TIM7_NUMBER 55
+#define STM32_TIM8_BRK_NUMBER 43
+#define STM32_TIM8_UP_NUMBER 44
+#define STM32_TIM8_TRGCO_NUMBER 45
+#define STM32_TIM8_CC_NUMBER 46
+
+/*
+ * USART/UART units.
+ */
+#define STM32_USART1_HANDLER VectorD4
+#define STM32_USART2_HANDLER VectorD8
+#define STM32_USART3_HANDLER VectorDC
+#define STM32_UART4_HANDLER Vector110
+#define STM32_UART5_HANDLER Vector114
+#define STM32_LPUART1_HANDLER Vector158
+
+#define STM32_USART1_NUMBER 37
+#define STM32_USART2_NUMBER 38
+#define STM32_USART3_NUMBER 39
+#define STM32_UART4_NUMBER 52
+#define STM32_UART5_NUMBER 53
+#define STM32_LPUART1_NUMBER 70
+
+/*
+ * USB/OTG units.
+ */
+#define STM32_USB1_HP_HANDLER Vector14C
+#define STM32_USB1_LP_HANDLER Vector14C
+#define STM32_OTG1_HANDLER Vector14C
+
+#define STM32_USB1_HP_NUMBER 67
+#define STM32_USB1_LP_NUMBER 67
+#define STM32_OTG1_NUMBER 67
+
+/*
+ * DMA2D unit.
+ */
+#define STM32_DMA2D_HANDLER Vector1A8
+
+#define STM32_DMA2D_NUMBER 90
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void irqInit(void);
+ void irqDeinit(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32_ISR_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/stm32_rcc.h b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/stm32_rcc.h
new file mode 100644
index 0000000..de3acfa
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/stm32_rcc.h
@@ -0,0 +1,1279 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32L4xx/stm32_rcc.h
+ * @brief RCC helper driver header.
+ * @note This file requires definitions from the ST header file
+ * @p stm32l4xx.h.
+ *
+ * @addtogroup STM32L4xx_RCC
+ * @{
+ */
+#ifndef STM32_RCC_H
+#define STM32_RCC_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @name Generic RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the clock of one or more peripheral on the APB1 bus (R1).
+ *
+ * @param[in] mask APB1 R1 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAPB1R1(mask, lp) { \
+ RCC->APB1ENR1 |= (mask); \
+ if (lp) \
+ RCC->APB1SMENR1 |= (mask); \
+ else \
+ RCC->APB1SMENR1 &= ~(mask); \
+ (void)RCC->APB1SMENR1; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the APB1 bus (R1).
+ *
+ * @param[in] mask APB1 R1 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAPB1R1(mask) { \
+ RCC->APB1ENR1 &= ~(mask); \
+ RCC->APB1SMENR1 &= ~(mask); \
+ (void)RCC->APB1SMENR1; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the APB1 bus (R1).
+ *
+ * @param[in] mask APB1 R1 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAPB1R1(mask) { \
+ RCC->APB1RSTR1 |= (mask); \
+ RCC->APB1RSTR1 &= ~(mask); \
+ (void)RCC->APB1RSTR1; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the APB1 bus (R2).
+ *
+ * @param[in] mask APB1 R2 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAPB1R2(mask, lp) { \
+ RCC->APB1ENR2 |= (mask); \
+ if (lp) \
+ RCC->APB1SMENR2 |= (mask); \
+ else \
+ RCC->APB1SMENR2 &= ~(mask); \
+ (void)RCC->APB1SMENR2; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the APB1 bus (R2).
+ *
+ * @param[in] mask APB1 R2 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAPB1R2(mask) { \
+ RCC->APB1ENR2 &= ~(mask); \
+ RCC->APB1SMENR2 &= ~(mask); \
+ (void)RCC->APB1SMENR2; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the APB1 bus (R2).
+ *
+ * @param[in] mask APB1 R2 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAPB1R2(mask) { \
+ RCC->APB1RSTR2 |= (mask); \
+ RCC->APB1RSTR2 &= ~(mask); \
+ (void)RCC->APB1RSTR2; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the APB2 bus.
+ *
+ * @param[in] mask APB2 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAPB2(mask, lp) { \
+ RCC->APB2ENR |= (mask); \
+ if (lp) \
+ RCC->APB2SMENR |= (mask); \
+ else \
+ RCC->APB2SMENR &= ~(mask); \
+ (void)RCC->APB2SMENR; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the APB2 bus.
+ *
+ * @param[in] mask APB2 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAPB2(mask) { \
+ RCC->APB2ENR &= ~(mask); \
+ RCC->APB2SMENR &= ~(mask); \
+ (void)RCC->APB2SMENR; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the APB2 bus.
+ *
+ * @param[in] mask APB2 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAPB2(mask) { \
+ RCC->APB2RSTR |= (mask); \
+ RCC->APB2RSTR &= ~(mask); \
+ (void)RCC->APB2RSTR; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the AHB1 bus.
+ *
+ * @param[in] mask AHB1 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAHB1(mask, lp) { \
+ RCC->AHB1ENR |= (mask); \
+ if (lp) \
+ RCC->AHB1SMENR |= (mask); \
+ else \
+ RCC->AHB1SMENR &= ~(mask); \
+ (void)RCC->AHB1SMENR; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the AHB1 bus.
+ *
+ * @param[in] mask AHB1 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAHB1(mask) { \
+ RCC->AHB1ENR &= ~(mask); \
+ RCC->AHB1SMENR &= ~(mask); \
+ (void)RCC->AHB1SMENR; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the AHB1 bus.
+ *
+ * @param[in] mask AHB1 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAHB1(mask) { \
+ RCC->AHB1RSTR |= (mask); \
+ RCC->AHB1RSTR &= ~(mask); \
+ (void)RCC->AHB1RSTR; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the AHB2 bus.
+ *
+ * @param[in] mask AHB2 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAHB2(mask, lp) { \
+ RCC->AHB2ENR |= (mask); \
+ if (lp) \
+ RCC->AHB2SMENR |= (mask); \
+ else \
+ RCC->AHB2SMENR &= ~(mask); \
+ (void)RCC->AHB2SMENR; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the AHB2 bus.
+ *
+ * @param[in] mask AHB2 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAHB2(mask) { \
+ RCC->AHB2ENR &= ~(mask); \
+ RCC->AHB2SMENR &= ~(mask); \
+ (void)RCC->AHB2SMENR; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the AHB2 bus.
+ *
+ * @param[in] mask AHB2 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAHB2(mask) { \
+ RCC->AHB2RSTR |= (mask); \
+ RCC->AHB2RSTR &= ~(mask); \
+ (void)RCC->AHB2RSTR; \
+}
+
+/**
+ * @brief Enables the clock of one or more peripheral on the AHB3 (FSMC) bus.
+ *
+ * @param[in] mask AHB3 peripherals mask
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableAHB3(mask, lp) { \
+ RCC->AHB3ENR |= (mask); \
+ if (lp) \
+ RCC->AHB3SMENR |= (mask); \
+ else \
+ RCC->AHB3SMENR &= ~(mask); \
+ (void)RCC->AHB3SMENR; \
+}
+
+/**
+ * @brief Disables the clock of one or more peripheral on the AHB3 (FSMC) bus.
+ *
+ * @param[in] mask AHB3 peripherals mask
+ *
+ * @api
+ */
+#define rccDisableAHB3(mask) { \
+ RCC->AHB3ENR &= ~(mask); \
+ RCC->AHB3SMENR &= ~(mask); \
+ (void)RCC->AHB3SMENR; \
+}
+
+/**
+ * @brief Resets one or more peripheral on the AHB3 (FSMC) bus.
+ *
+ * @param[in] mask AHB3 peripherals mask
+ *
+ * @api
+ */
+#define rccResetAHB3(mask) { \
+ RCC->AHB3RSTR |= (mask); \
+ RCC->AHB3RSTR &= ~(mask); \
+ (void)RCC->AHB3RSTR; \
+}
+/** @} */
+
+/**
+ * @name ADC peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the ADC1/ADC2/ADC3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableADC123(lp) rccEnableAHB2(RCC_AHB2ENR_ADCEN, lp)
+
+/**
+ * @brief Disables the ADC1/ADC2/ADC3 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableADC123() rccDisableAHB2(RCC_AHB2ENR_ADCEN)
+
+/**
+ * @brief Resets the ADC1/ADC2/ADC3 peripheral.
+ *
+ * @api
+ */
+#define rccResetADC123() rccResetAHB2(RCC_AHB2RSTR_ADCRST)
+/** @} */
+
+/**
+ * @name DAC peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the DAC1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableDAC1(lp) rccEnableAPB1R1(RCC_APB1ENR1_DAC1EN, lp)
+
+/**
+ * @brief Disables the DAC1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableDAC1() rccDisableAPB1R1(RCC_APB1ENR1_DAC1EN)
+
+/**
+ * @brief Resets the DAC1 peripheral.
+ *
+ * @api
+ */
+#define rccResetDAC1() rccResetAPB1R1(RCC_APB1RSTR1_DAC1RST)
+/** @} */
+
+/**
+ * @name DMA peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the DMA1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableDMA1(lp) rccEnableAHB1(RCC_AHB1ENR_DMA1EN, lp)
+
+/**
+ * @brief Disables the DMA1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableDMA1() rccDisableAHB1(RCC_AHB1ENR_DMA1EN)
+
+/**
+ * @brief Resets the DMA1 peripheral.
+ *
+ * @api
+ */
+#define rccResetDMA1() rccResetAHB1(RCC_AHB1RSTR_DMA1RST)
+
+/**
+ * @brief Enables the DMA2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableDMA2(lp) rccEnableAHB1(RCC_AHB1ENR_DMA2EN, lp)
+
+/**
+ * @brief Disables the DMA2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableDMA2() rccDisableAHB1(RCC_AHB1ENR_DMA2EN)
+
+/**
+ * @brief Resets the DMA2 peripheral.
+ *
+ * @api
+ */
+#define rccResetDMA2() rccResetAHB1(RCC_AHB1RSTR_DMA2RST)
+/** @} */
+
+/**
+ * @name PWR interface specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the PWR interface clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnablePWRInterface(lp) rccEnableAPB1R1(RCC_APB1ENR1_PWREN, lp)
+
+/**
+ * @brief Disables PWR interface clock.
+ *
+ * @api
+ */
+#define rccDisablePWRInterface() rccDisableAPB1R1(RCC_APB1ENR1_PWREN)
+
+/**
+ * @brief Resets the PWR interface.
+ *
+ * @api
+ */
+#define rccResetPWRInterface() rccResetAPB1R1(RCC_APB1RSTR1_PWRRST)
+/** @} */
+
+/**
+ * @name CAN peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the CAN1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableCAN1(lp) rccEnableAPB1R1(RCC_APB1ENR1_CAN1EN, lp)
+
+/**
+ * @brief Disables the CAN1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableCAN1() rccDisableAPB1R1(RCC_APB1ENR1_CAN1EN)
+
+/**
+ * @brief Resets the CAN1 peripheral.
+ *
+ * @api
+ */
+#define rccResetCAN1() rccResetAPB1R1(RCC_APB1RSTR1_CAN1RST)
+
+/**
+ * @brief Enables the CAN2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableCAN2(lp) rccEnableAPB1R1(RCC_APB1ENR1_CAN2EN, lp)
+
+/**
+ * @brief Disables the CAN2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableCAN2() rccDisableAPB1R1(RCC_APB1ENR1_CAN2EN)
+
+/**
+ * @brief Resets the CAN2 peripheral.
+ *
+ * @api
+ */
+#define rccResetCAN2() rccResetAPB1R1(RCC_APB1RSTR1_CAN2RST)
+/** @} */
+
+/**
+ * @name I2C peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the I2C1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableI2C1(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C1EN, lp)
+
+/**
+ * @brief Disables the I2C1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableI2C1() rccDisableAPB1R1(RCC_APB1ENR1_I2C1EN)
+
+/**
+ * @brief Resets the I2C1 peripheral.
+ *
+ * @api
+ */
+#define rccResetI2C1() rccResetAPB1R1(RCC_APB1RSTR1_I2C1RST)
+
+/**
+ * @brief Enables the I2C2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableI2C2(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C2EN, lp)
+
+/**
+ * @brief Disables the I2C2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableI2C2() rccDisableAPB1R1(RCC_APB1ENR1_I2C2EN)
+
+/**
+ * @brief Resets the I2C2 peripheral.
+ *
+ * @api
+ */
+#define rccResetI2C2() rccResetAPB1R1(RCC_APB1RSTR1_I2C2RST)
+
+/**
+ * @brief Enables the I2C3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableI2C3(lp) rccEnableAPB1R1(RCC_APB1ENR1_I2C3EN, lp)
+
+/**
+ * @brief Disables the I2C3 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableI2C3() rccDisableAPB1R1(RCC_APB1ENR1_I2C3EN)
+
+/**
+ * @brief Resets the I2C3 peripheral.
+ *
+ * @api
+ */
+#define rccResetI2C3() rccResetAPB1R1(RCC_APB1RSTR1_I2C3RST)
+
+/**
+ * @brief Enables the I2C4 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableI2C4(lp) rccEnableAPB1R2(RCC_APB1ENR2_I2C4EN, lp)
+
+/**
+ * @brief Disables the I2C4 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableI2C4() rccDisableAPB1R1(RCC_APB1ENR2_I2C4EN)
+
+/**
+ * @brief Resets the I2C4 peripheral.
+ *
+ * @api
+ */
+#define rccResetI2C4() rccResetAPB1R1(RCC_APB1RSTR2_I2C4RST)
+/** @} */
+
+/**
+ * @name OTG peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the OTG_FS peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableOTG_FS(lp) rccEnableAHB2(RCC_AHB2ENR_OTGFSEN, lp)
+
+/**
+ * @brief Disables the OTG_FS peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableOTG_FS() rccDisableAHB2(RCC_AHB2ENR_OTGFSEN)
+
+/**
+ * @brief Resets the OTG_FS peripheral.
+ *
+ * @api
+ */
+#define rccResetOTG_FS() rccResetAHB2(RCC_AHB2RSTR_OTGFSRST)
+/** @} */
+
+/**
+ * @name QUADSPI peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the QUADSPI1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableQUADSPI1(lp) rccEnableAHB3(RCC_AHB3ENR_QSPIEN, lp)
+
+/**
+ * @brief Disables the QUADSPI1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableQUADSPI1() rccDisableAHB3(RCC_AHB3ENR_QSPIEN)
+
+/**
+ * @brief Resets the QUADSPI1 peripheral.
+ *
+ * @api
+ */
+#define rccResetQUADSPI1() rccResetAHB3(RCC_AHB3RSTR_QSPIRST)
+/** @} */
+
+/**
+ * @name RNG peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the RNG peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableRNG(lp) rccEnableAHB2(RCC_AHB2ENR_RNGEN, lp)
+
+/**
+ * @brief Disables the RNG peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableRNG() rccDisableAHB2(RCC_AHB2ENR_RNGEN)
+
+/**
+ * @brief Resets the RNG peripheral.
+ *
+ * @api
+ */
+#define rccResetRNG() rccResetAHB2(RCC_AHB2RSTR_RNGRST)
+/** @} */
+
+/**
+ * @name SDMMC peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the SDMMC1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSDMMC1(lp) rccEnableAPB2(RCC_APB2ENR_SDMMC1EN, lp)
+
+/**
+ * @brief Disables the SDMMC1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableSDMMC1() rccDisableAPB2(RCC_APB2ENR_SDMMC1EN)
+
+/**
+ * @brief Resets the SDMMC1 peripheral.
+ *
+ * @api
+ */
+#define rccResetSDMMC1() rccResetAPB2(RCC_APB2RSTR_SDMMC1RST)
+/** @} */
+
+/**
+ * @name SPI peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the SPI1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI1(lp) rccEnableAPB2(RCC_APB2ENR_SPI1EN, lp)
+
+/**
+ * @brief Disables the SPI1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableSPI1() rccDisableAPB2(RCC_APB2ENR_SPI1EN)
+
+/**
+ * @brief Resets the SPI1 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI1() rccResetAPB2(RCC_APB2RSTR_SPI1RST)
+
+/**
+ * @brief Enables the SPI2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI2(lp) rccEnableAPB1R1(RCC_APB1ENR1_SPI2EN, lp)
+
+/**
+ * @brief Disables the SPI2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableSPI2() rccDisableAPB1R1(RCC_APB1ENR1_SPI2EN)
+
+/**
+ * @brief Resets the SPI2 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI2() rccResetAPB1R1(RCC_APB1RSTR1_SPI2RST)
+
+/**
+ * @brief Enables the SPI3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableSPI3(lp) rccEnableAPB1R1(RCC_APB1ENR1_SPI3EN, lp)
+
+/**
+ * @brief Disables the SPI3 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableSPI3() rccDisableAPB1R1(RCC_APB1ENR1_SPI3EN)
+
+/**
+ * @brief Resets the SPI3 peripheral.
+ *
+ * @api
+ */
+#define rccResetSPI3() rccResetAPB1R1(RCC_APB1RSTR1_SPI3RST)
+/** @} */
+
+/**
+ * @name TIM peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the TIM1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM1(lp) rccEnableAPB2(RCC_APB2ENR_TIM1EN, lp)
+
+/**
+ * @brief Disables the TIM1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM1() rccDisableAPB2(RCC_APB2ENR_TIM1EN)
+
+/**
+ * @brief Resets the TIM1 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM1() rccResetAPB2(RCC_APB2RSTR_TIM1RST)
+
+/**
+ * @brief Enables the TIM2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM2(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM2EN, lp)
+
+/**
+ * @brief Disables the TIM2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM2() rccDisableAPB1R1(RCC_APB1ENR1_TIM2EN)
+
+/**
+ * @brief Resets the TIM2 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM2() rccResetAPB1R1(RCC_APB1RSTR1_TIM2RST)
+
+/**
+ * @brief Enables the TIM3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM3(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM3EN, lp)
+
+/**
+ * @brief Disables the TIM3 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM3() rccDisableAPB1R1(RCC_APB1ENR1_TIM3EN)
+
+/**
+ * @brief Resets the TIM3 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM3() rccResetAPB1R1(RCC_APB1RSTR1_TIM3RST)
+
+/**
+ * @brief Enables the TIM4 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM4(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM4EN, lp)
+
+/**
+ * @brief Disables the TIM4 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM4() rccDisableAPB1R1(RCC_APB1ENR1_TIM4EN)
+
+/**
+ * @brief Resets the TIM4 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM4() rccResetAPB1R1(RCC_APB1RSTR1_TIM4RST)
+
+/**
+ * @brief Enables the TIM5 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM5(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM5EN, lp)
+
+/**
+ * @brief Disables the TIM5 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM5() rccDisableAPB1R1(RCC_APB1ENR1_TIM5EN)
+
+/**
+ * @brief Resets the TIM5 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM5() rccResetAPB1R1(RCC_APB1RSTR1_TIM5RST)
+
+/**
+ * @brief Enables the TIM6 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM6(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM6EN, lp)
+
+/**
+ * @brief Disables the TIM6 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM6() rccDisableAPB1R1(RCC_APB1ENR1_TIM6EN)
+
+/**
+ * @brief Resets the TIM6 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM6() rccResetAPB1R1(RCC_APB1RSTR1_TIM6RST)
+
+/**
+ * @brief Enables the TIM7 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM7(lp) rccEnableAPB1R1(RCC_APB1ENR1_TIM7EN, lp)
+
+/**
+ * @brief Disables the TIM7 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM7() rccDisableAPB1R1(RCC_APB1ENR1_TIM7EN)
+
+/**
+ * @brief Resets the TIM7 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM7() rccResetAPB1R1(RCC_APB1RSTR1_TIM7RST)
+
+/**
+ * @brief Enables the TIM8 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM8(lp) rccEnableAPB2(RCC_APB2ENR_TIM8EN, lp)
+
+/**
+ * @brief Disables the TIM8 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM8() rccDisableAPB2(RCC_APB2ENR_TIM8EN)
+
+/**
+ * @brief Resets the TIM8 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM8() rccResetAPB2(RCC_APB2RSTR_TIM8RST)
+
+/**
+ * @brief Enables the TIM15 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM15(lp) rccEnableAPB2(RCC_APB2ENR_TIM15EN, lp)
+
+/**
+ * @brief Disables the TIM15 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM15() rccDisableAPB2(RCC_APB2ENR_TIM15EN)
+
+/**
+ * @brief Resets the TIM15 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM15() rccResetAPB2(RCC_APB2RSTR_TIM15RST)
+
+/**
+ * @brief Enables the TIM16 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM16(lp) rccEnableAPB2(RCC_APB2ENR_TIM16EN, lp)
+
+/**
+ * @brief Disables the TIM16 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM16() rccDisableAPB2(RCC_APB2ENR_TIM16EN)
+
+/**
+ * @brief Resets the TIM16 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM16() rccResetAPB2(RCC_APB2RSTR_TIM16RST)
+
+/**
+ * @brief Enables the TIM17 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableTIM17(lp) rccEnableAPB2(RCC_APB2ENR_TIM17EN, lp)
+
+/**
+ * @brief Disables the TIM17 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableTIM17() rccDisableAPB2(RCC_APB2ENR_TIM17EN)
+
+/**
+ * @brief Resets the TIM17 peripheral.
+ *
+ * @api
+ */
+#define rccResetTIM17() rccResetAPB2(RCC_APB2RSTR_TIM17RST)
+/** @} */
+
+/**
+ * @name USART/UART peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the USART1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSART1(lp) rccEnableAPB2(RCC_APB2ENR_USART1EN, lp)
+
+/**
+ * @brief Disables the USART1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUSART1() rccDisableAPB2(RCC_APB2ENR_USART1EN)
+
+/**
+ * @brief Resets the USART1 peripheral.
+ *
+ * @api
+ */
+#define rccResetUSART1() rccResetAPB2(RCC_APB2RSTR_USART1RST)
+
+/**
+ * @brief Enables the USART2 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSART2(lp) rccEnableAPB1R1(RCC_APB1ENR1_USART2EN, lp)
+
+/**
+ * @brief Disables the USART2 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUSART2() rccDisableAPB1R1(RCC_APB1ENR1_USART2EN)
+
+/**
+ * @brief Resets the USART2 peripheral.
+ *
+ * @api
+ */
+#define rccResetUSART2() rccResetAPB1R1(RCC_APB1RSTR1_USART2RST)
+
+/**
+ * @brief Enables the USART3 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSART3(lp) rccEnableAPB1R1(RCC_APB1ENR1_USART3EN, lp)
+
+/**
+ * @brief Disables the USART3 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUSART3() rccDisableAPB1R1(RCC_APB1ENR1_USART3EN)
+
+/**
+ * @brief Resets the USART3 peripheral.
+ *
+ * @api
+ */
+#define rccResetUSART3() rccResetAPB1R1(RCC_APB1RSTR1_USART3RST)
+
+/**
+ * @brief Enables the UART4 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUART4(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART4EN, lp)
+
+/**
+ * @brief Disables the UART4 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUART4() rccDisableAPB1R1(RCC_APB1ENR1_UART4EN)
+
+/**
+ * @brief Resets the UART4 peripheral.
+ *
+ * @api
+ */
+#define rccResetUART4() rccResetAPB1R1(RCC_APB1RSTR1_UART4RST)
+
+/**
+ * @brief Enables the UART5 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUART5(lp) rccEnableAPB1R1(RCC_APB1ENR1_UART5EN, lp)
+
+/**
+ * @brief Disables the UART5 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUART5() rccDisableAPB1R1(RCC_APB1ENR1_UART5EN)
+
+/**
+ * @brief Resets the UART5 peripheral.
+ *
+ * @api
+ */
+#define rccResetUART5() rccResetAPB1R1(RCC_APB1RSTR1_UART5RST)
+
+/**
+ * @brief Enables the LPUART1 peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableLPUART1(lp) rccEnableAPB1R2(RCC_APB1ENR2_LPUART1EN, lp)
+
+/**
+ * @brief Disables the LPUART1 peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableLPUART1() rccDisableAPB1R2(RCC_APB1ENR2_LPUART1EN)
+
+/**
+ * @brief Resets the USART1 peripheral.
+ *
+ * @api
+ */
+#define rccResetLPUART1() rccResetAPB1R2(RCC_APB1RSTR2_LPUART1RST)
+/** @} */
+
+/**
+ * @name USB peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the USB peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableUSB(lp) rccEnableAPB1R1(RCC_APB1ENR1_USBFSEN, lp)
+
+/**
+ * @brief Disables the USB peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableUSB() rccDisableAPB1R1(RCC_APB1ENR1_USBFSEN)
+
+/**
+ * @brief Resets the USB peripheral.
+ *
+ * @api
+ */
+#define rccResetUSB() rccResetAPB1R1(RCC_APB1RSTR1_USBFSRST)
+/** @} */
+
+/**
+ * @name CRC peripheral specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the CRC peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableCRC(lp) rccEnableAHB1(RCC_AHB1ENR_CRCEN, lp)
+
+/**
+ * @brief Disables the CRC peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableCRC() rccDisableAHB1(RCC_AHB1ENR_CRCEN)
+
+/**
+ * @brief Resets the CRC peripheral.
+ *
+ * @api
+ */
+#define rccResetCRC() rccResetAHB1(RCC_AHB1RSTR_CRCRST)
+/** @} */
+
+/**
+ * @name FSMC peripherals specific RCC operations
+ * @{
+ */
+/**
+ * @brief Enables the FSMC peripheral clock.
+ *
+ * @param[in] lp low power enable flag
+ *
+ * @api
+ */
+#define rccEnableFSMC(lp) rccEnableAHB3(RCC_AHB3ENR_FMCEN, lp)
+
+/**
+ * @brief Disables the FSMC peripheral clock.
+ *
+ * @api
+ */
+#define rccDisableFSMC() rccDisableAHB3(RCC_AHB3ENR_FMCEN)
+
+/**
+ * @brief Resets the FSMC peripheral.
+ *
+ * @api
+ */
+#define rccResetFSMC() rccResetAHB3(RCC_AHB3RSTR_FMCRST)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM32_RCC_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/stm32_registry.h b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/stm32_registry.h
new file mode 100644
index 0000000..fdec353
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/STM32L4xx/stm32_registry.h
@@ -0,0 +1,1347 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file STM32L4xx/stm32_registry.h
+ * @brief STM32L4xx capabilities registry.
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#ifndef STM32_REGISTRY_H
+#define STM32_REGISTRY_H
+
+/*===========================================================================*/
+/* Platform capabilities. */
+/*===========================================================================*/
+
+/**
+ * @name STM32L4xx capabilities
+ * @{
+ */
+
+/*===========================================================================*/
+/* Common. */
+/*===========================================================================*/
+
+/* RNG attributes.*/
+#define STM32_HAS_RNG1 TRUE
+
+/* RTC attributes.*/
+#define STM32_HAS_RTC TRUE
+#define STM32_RTC_HAS_SUBSECONDS TRUE
+#define STM32_RTC_HAS_PERIODIC_WAKEUPS TRUE
+#define STM32_RTC_NUM_ALARMS 2
+#define STM32_RTC_STORAGE_SIZE 128
+#define STM32_RTC_TAMP_STAMP_HANDLER Vector48
+#define STM32_RTC_WKUP_HANDLER Vector4C
+#define STM32_RTC_ALARM_HANDLER VectorE4
+#define STM32_RTC_TAMP_STAMP_NUMBER 2
+#define STM32_RTC_WKUP_NUMBER 3
+#define STM32_RTC_ALARM_NUMBER 41
+#define STM32_RTC_ALARM_EXTI 18
+#define STM32_RTC_TAMP_STAMP_EXTI 19
+#define STM32_RTC_WKUP_EXTI 20
+#define STM32_RTC_IRQ_ENABLE() do { \
+ nvicEnableVector(STM32_RTC_TAMP_STAMP_NUMBER, STM32_IRQ_EXTI19_PRIORITY); \
+ nvicEnableVector(STM32_RTC_WKUP_NUMBER, STM32_IRQ_EXTI20_PRIORITY); \
+ nvicEnableVector(STM32_RTC_ALARM_NUMBER, STM32_IRQ_EXTI18_PRIORITY); \
+} while (false)
+
+#if defined(STM32L486xx) || defined(STM32L4A6xx) || \
+ defined(__DOXYGEN__)
+#define STM32_HAS_HASH1 TRUE
+#define STM32_HAS_CRYP1 TRUE
+#else
+#define STM32_HAS_HASH1 FALSE
+#define STM32_HAS_CRYP1 FALSE
+#endif
+
+/*===========================================================================*/
+/* STM32L432xx, STM32L433xx. */
+/*===========================================================================*/
+
+#if defined(STM32L432xx) || defined(STM32L433xx) || defined(__DOXYGEN__)
+
+/* Clock attributes.*/
+#define STM32_CLOCK_HAS_HSI48 TRUE
+
+/* ADC attributes.*/
+#define STM32_HAS_ADC1 TRUE
+#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\
+ STM32_DMA_STREAM_ID_MSK(2, 3))
+#define STM32_ADC1_DMA_CHN 0x00000000
+
+#define STM32_HAS_ADC2 FALSE
+#define STM32_HAS_ADC3 FALSE
+#define STM32_HAS_ADC4 FALSE
+
+/* CAN attributes.*/
+#define STM32_CAN_MAX_FILTERS 14
+#define STM32_HAS_CAN1 TRUE
+#define STM32_HAS_CAN2 FALSE
+#define STM32_HAS_CAN3 FALSE
+
+/* DAC attributes.*/
+#define STM32_HAS_DAC1_CH1 TRUE
+#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)|\
+ STM32_DMA_STREAM_ID_MSK(2, 4))
+#define STM32_DAC1_CH1_DMA_CHN 0x00003600
+
+#define STM32_HAS_DAC1_CH2 TRUE
+#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)|\
+ STM32_DMA_STREAM_ID_MSK(2, 5))
+#define STM32_DAC1_CH2_DMA_CHN 0x00035000
+
+#define STM32_HAS_DAC2_CH1 FALSE
+#define STM32_HAS_DAC2_CH2 FALSE
+
+/* DMA attributes.*/
+#define STM32_ADVANCED_DMA TRUE
+#define STM32_DMA_SUPPORTS_DMAMUX FALSE
+#define STM32_DMA_SUPPORTS_CSELR TRUE
+#define STM32_DMA1_NUM_CHANNELS 7
+#define STM32_DMA2_NUM_CHANNELS 7
+
+/* ETH attributes.*/
+#define STM32_HAS_ETH FALSE
+
+/* EXTI attributes.*/
+#define STM32_EXTI_NUM_LINES 40
+#define STM32_EXTI_IMR1_MASK 0xFF820000U
+#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U
+
+/* Flash attributes.*/
+#define STM32_FLASH_NUMBER_OF_BANKS 1
+#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__)
+#define STM32_FLASH_SECTORS_PER_BANK 256 /* Maximum, can be redefined.*/
+#endif
+
+/* GPIO attributes.*/
+#define STM32_HAS_GPIOA TRUE
+#define STM32_HAS_GPIOB TRUE
+#define STM32_HAS_GPIOC TRUE
+#define STM32_HAS_GPIOD FALSE
+#define STM32_HAS_GPIOE FALSE
+#define STM32_HAS_GPIOF FALSE
+#define STM32_HAS_GPIOG FALSE
+#define STM32_HAS_GPIOH FALSE
+#define STM32_HAS_GPIOI FALSE
+#define STM32_HAS_GPIOJ FALSE
+#define STM32_HAS_GPIOK FALSE
+#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \
+ RCC_AHB2ENR_GPIOBEN | \
+ RCC_AHB2ENR_GPIOCEN)
+
+/* I2C attributes.*/
+#define STM32_HAS_I2C1 TRUE
+#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\
+ STM32_DMA_STREAM_ID_MSK(2, 6))
+#define STM32_I2C1_RX_DMA_CHN 0x03500000
+#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6) |\
+ STM32_DMA_STREAM_ID_MSK(2, 7))
+#define STM32_I2C1_TX_DMA_CHN 0x05300000
+
+#define STM32_HAS_I2C3 TRUE
+#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3))
+#define STM32_I2C3_RX_DMA_CHN 0x00000300
+#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2))
+#define STM32_I2C3_TX_DMA_CHN 0x00000030
+
+#define STM32_HAS_I2C2 FALSE
+#define STM32_HAS_I2C4 FALSE
+
+/* QUADSPI attributes.*/
+#define STM32_HAS_QUADSPI1 TRUE
+#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\
+ STM32_DMA_STREAM_ID_MSK(2, 7))
+#define STM32_QUADSPI1_DMA_CHN 0x03050000
+
+/* SDMMC attributes.*/
+#define STM32_HAS_SDMMC1 FALSE
+#define STM32_HAS_SDMMC2 FALSE
+
+/* SPI attributes.*/
+#define STM32_HAS_SPI1 TRUE
+#define STM32_SPI1_SUPPORTS_I2S FALSE
+#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\
+ STM32_DMA_STREAM_ID_MSK(2, 3))
+#define STM32_SPI1_RX_DMA_CHN 0x00000410
+#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\
+ STM32_DMA_STREAM_ID_MSK(2, 4))
+#define STM32_SPI1_TX_DMA_CHN 0x00004100
+
+#define STM32_HAS_SPI3 TRUE
+#define STM32_SPI3_SUPPORTS_I2S FALSE
+#define STM32_SPI3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1))
+#define STM32_SPI3_RX_DMA_CHN 0x00000003
+#define STM32_SPI3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2))
+#define STM32_SPI3_TX_DMA_CHN 0x00000030
+
+#define STM32_HAS_SPI2 FALSE
+#define STM32_HAS_SPI4 FALSE
+#define STM32_HAS_SPI5 FALSE
+#define STM32_HAS_SPI6 FALSE
+
+/* TIM attributes.*/
+#define STM32_TIM_MAX_CHANNELS 6
+
+#define STM32_HAS_TIM1 TRUE
+#define STM32_TIM1_IS_32BITS FALSE
+#define STM32_TIM1_CHANNELS 6
+
+#define STM32_HAS_TIM2 TRUE
+#define STM32_TIM2_IS_32BITS TRUE
+#define STM32_TIM2_CHANNELS 4
+
+#define STM32_HAS_TIM6 TRUE
+#define STM32_TIM6_IS_32BITS FALSE
+#define STM32_TIM6_CHANNELS 0
+
+#define STM32_HAS_TIM7 TRUE
+#define STM32_TIM7_IS_32BITS FALSE
+#define STM32_TIM7_CHANNELS 0
+
+#define STM32_HAS_TIM15 TRUE
+#define STM32_TIM15_IS_32BITS FALSE
+#define STM32_TIM15_CHANNELS 2
+
+#define STM32_HAS_TIM16 TRUE
+#define STM32_TIM16_IS_32BITS FALSE
+#define STM32_TIM16_CHANNELS 2
+
+#define STM32_HAS_TIM3 FALSE
+#define STM32_HAS_TIM4 FALSE
+#define STM32_HAS_TIM5 FALSE
+#define STM32_HAS_TIM8 FALSE
+#define STM32_HAS_TIM9 FALSE
+#define STM32_HAS_TIM10 FALSE
+#define STM32_HAS_TIM11 FALSE
+#define STM32_HAS_TIM12 FALSE
+#define STM32_HAS_TIM13 FALSE
+#define STM32_HAS_TIM14 FALSE
+#define STM32_HAS_TIM17 FALSE
+#define STM32_HAS_TIM18 FALSE
+#define STM32_HAS_TIM19 FALSE
+#define STM32_HAS_TIM20 FALSE
+#define STM32_HAS_TIM21 FALSE
+#define STM32_HAS_TIM22 FALSE
+
+/* USART attributes.*/
+#define STM32_HAS_USART1 TRUE
+#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\
+ STM32_DMA_STREAM_ID_MSK(2, 7))
+#define STM32_USART1_RX_DMA_CHN 0x02020000
+#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\
+ STM32_DMA_STREAM_ID_MSK(2, 6))
+#define STM32_USART1_TX_DMA_CHN 0x00202000
+
+#define STM32_HAS_USART2 TRUE
+#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6))
+#define STM32_USART2_RX_DMA_CHN 0x00200000
+#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7))
+#define STM32_USART2_TX_DMA_CHN 0x02000000
+
+#define STM32_HAS_LPUART1 TRUE
+
+#define STM32_HAS_USART3 FALSE
+#define STM32_HAS_UART4 FALSE
+#define STM32_HAS_UART5 FALSE
+#define STM32_HAS_USART6 FALSE
+#define STM32_HAS_UART7 FALSE
+#define STM32_HAS_UART8 FALSE
+
+/* USB attributes.*/
+#define STM32_HAS_USB TRUE
+#define STM32_USB_ACCESS_SCHEME_2x16 TRUE
+#define STM32_USB_PMA_SIZE 1024
+#define STM32_USB_HAS_BCDR TRUE
+
+#define STM32_HAS_OTG1 FALSE
+#define STM32_HAS_OTG2 FALSE
+
+/* IWDG attributes.*/
+#define STM32_HAS_IWDG TRUE
+#define STM32_IWDG_IS_WINDOWED TRUE
+
+/* LTDC attributes.*/
+#define STM32_HAS_LTDC FALSE
+
+/* DMA2D attributes.*/
+#define STM32_HAS_DMA2D FALSE
+
+/* FSMC attributes.*/
+#define STM32_HAS_FSMC TRUE
+
+/* CRC attributes.*/
+#define STM32_HAS_CRC TRUE
+#define STM32_CRC_PROGRAMMABLE TRUE
+
+#endif /* defined(STM32L432xx) */
+
+/*===========================================================================*/
+/* STM32L443xx. */
+/*===========================================================================*/
+
+#if defined(STM32L443xx) || defined(__DOXYGEN__)
+
+/* Clock attributes.*/
+#define STM32_CLOCK_HAS_HSI48 TRUE
+
+/* ADC attributes.*/
+#define STM32_HAS_ADC1 TRUE
+#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\
+ STM32_DMA_STREAM_ID_MSK(2, 3))
+#define STM32_ADC1_DMA_CHN 0x00000000
+
+#define STM32_HAS_ADC2 FALSE
+#define STM32_HAS_ADC3 FALSE
+#define STM32_HAS_ADC4 FALSE
+
+/* CAN attributes.*/
+#define STM32_CAN_MAX_FILTERS 14
+#define STM32_HAS_CAN1 TRUE
+#define STM32_HAS_CAN2 FALSE
+#define STM32_HAS_CAN3 FALSE
+
+/* DAC attributes.*/
+#define STM32_HAS_DAC1_CH1 TRUE
+#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)|\
+ STM32_DMA_STREAM_ID_MSK(2, 4))
+#define STM32_DAC1_CH1_DMA_CHN 0x00003600
+
+#define STM32_HAS_DAC1_CH2 TRUE
+#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)|\
+ STM32_DMA_STREAM_ID_MSK(2, 5))
+#define STM32_DAC1_CH2_DMA_CHN 0x00035000
+
+#define STM32_HAS_DAC2_CH1 FALSE
+#define STM32_HAS_DAC2_CH2 FALSE
+
+/* DMA attributes.*/
+#define STM32_ADVANCED_DMA TRUE
+#define STM32_DMA_SUPPORTS_DMAMUX FALSE
+#define STM32_DMA_SUPPORTS_CSELR TRUE
+#define STM32_DMA1_NUM_CHANNELS 7
+#define STM32_DMA2_NUM_CHANNELS 7
+
+/* ETH attributes.*/
+#define STM32_HAS_ETH FALSE
+
+/* EXTI attributes.*/
+#define STM32_EXTI_NUM_LINES 40
+#define STM32_EXTI_IMR1_MASK 0xFF820000U
+#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U
+
+/* Flash attributes.*/
+#define STM32_FLASH_NUMBER_OF_BANKS 1
+#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__)
+#define STM32_FLASH_SECTORS_PER_BANK 256 /* Maximum, can be redefined.*/
+#endif
+
+/* GPIO attributes.*/
+#define STM32_HAS_GPIOA TRUE
+#define STM32_HAS_GPIOB TRUE
+#define STM32_HAS_GPIOC TRUE
+#define STM32_HAS_GPIOD FALSE
+#define STM32_HAS_GPIOE FALSE
+#define STM32_HAS_GPIOF FALSE
+#define STM32_HAS_GPIOG FALSE
+#define STM32_HAS_GPIOH TRUE
+#define STM32_HAS_GPIOI FALSE
+#define STM32_HAS_GPIOJ FALSE
+#define STM32_HAS_GPIOK FALSE
+#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \
+ RCC_AHB2ENR_GPIOBEN | \
+ RCC_AHB2ENR_GPIOCEN | \
+ RCC_AHB2ENR_GPIOHEN)
+
+/* I2C attributes.*/
+#define STM32_HAS_I2C1 TRUE
+#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\
+ STM32_DMA_STREAM_ID_MSK(2, 6))
+#define STM32_I2C1_RX_DMA_CHN 0x03500000
+#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6) |\
+ STM32_DMA_STREAM_ID_MSK(2, 7))
+#define STM32_I2C1_TX_DMA_CHN 0x05300000
+
+#define STM32_HAS_I2C2 TRUE
+#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5))
+#define STM32_I2C2_RX_DMA_CHN 0x00030000
+#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4))
+#define STM32_I2C2_TX_DMA_CHN 0x00003000
+
+#define STM32_HAS_I2C3 TRUE
+#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3))
+#define STM32_I2C3_RX_DMA_CHN 0x00000300
+#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2))
+#define STM32_I2C3_TX_DMA_CHN 0x00000030
+
+#define STM32_HAS_I2C4 FALSE
+
+/* QUADSPI attributes.*/
+#define STM32_HAS_QUADSPI1 TRUE
+#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\
+ STM32_DMA_STREAM_ID_MSK(2, 7))
+#define STM32_QUADSPI1_DMA_CHN 0x03050000
+
+/* SDMMC attributes.*/
+#define STM32_HAS_SDMMC1 TRUE
+#define STM32_SDC_SDMMC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\
+ STM32_DMA_STREAM_ID_MSK(2, 5))
+#define STM32_SDC_SDMMC1_DMA_CHN 0x00077000
+
+#define STM32_HAS_SDMMC2 FALSE
+
+/* SPI attributes.*/
+#define STM32_HAS_SPI1 TRUE
+#define STM32_SPI1_SUPPORTS_I2S FALSE
+#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\
+ STM32_DMA_STREAM_ID_MSK(2, 3))
+#define STM32_SPI1_RX_DMA_CHN 0x00000410
+#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\
+ STM32_DMA_STREAM_ID_MSK(2, 4))
+#define STM32_SPI1_TX_DMA_CHN 0x00004100
+
+#define STM32_HAS_SPI2 TRUE
+#define STM32_SPI2_SUPPORTS_I2S FALSE
+#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4))
+#define STM32_SPI2_RX_DMA_CHN 0x00001000
+#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5))
+#define STM32_SPI2_TX_DMA_CHN 0x00010000
+
+#define STM32_HAS_SPI3 TRUE
+#define STM32_SPI3_SUPPORTS_I2S FALSE
+#define STM32_SPI3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1))
+#define STM32_SPI3_RX_DMA_CHN 0x00000003
+#define STM32_SPI3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2))
+#define STM32_SPI3_TX_DMA_CHN 0x00000030
+
+#define STM32_HAS_SPI4 FALSE
+#define STM32_HAS_SPI5 FALSE
+#define STM32_HAS_SPI6 FALSE
+
+/* TIM attributes.*/
+#define STM32_TIM_MAX_CHANNELS 6
+
+#define STM32_HAS_TIM1 TRUE
+#define STM32_TIM1_IS_32BITS FALSE
+#define STM32_TIM1_CHANNELS 6
+
+#define STM32_HAS_TIM2 TRUE
+#define STM32_TIM2_IS_32BITS TRUE
+#define STM32_TIM2_CHANNELS 4
+
+#define STM32_HAS_TIM6 TRUE
+#define STM32_TIM6_IS_32BITS FALSE
+#define STM32_TIM6_CHANNELS 0
+
+#define STM32_HAS_TIM7 TRUE
+#define STM32_TIM7_IS_32BITS FALSE
+#define STM32_TIM7_CHANNELS 0
+
+#define STM32_HAS_TIM15 TRUE
+#define STM32_TIM15_IS_32BITS FALSE
+#define STM32_TIM15_CHANNELS 2
+
+#define STM32_HAS_TIM16 TRUE
+#define STM32_TIM16_IS_32BITS FALSE
+#define STM32_TIM16_CHANNELS 2
+
+#define STM32_HAS_TIM3 FALSE
+#define STM32_HAS_TIM4 FALSE
+#define STM32_HAS_TIM5 FALSE
+#define STM32_HAS_TIM8 FALSE
+#define STM32_HAS_TIM9 FALSE
+#define STM32_HAS_TIM10 FALSE
+#define STM32_HAS_TIM11 FALSE
+#define STM32_HAS_TIM12 FALSE
+#define STM32_HAS_TIM13 FALSE
+#define STM32_HAS_TIM14 FALSE
+#define STM32_HAS_TIM17 FALSE
+#define STM32_HAS_TIM18 FALSE
+#define STM32_HAS_TIM19 FALSE
+#define STM32_HAS_TIM20 FALSE
+#define STM32_HAS_TIM21 FALSE
+#define STM32_HAS_TIM22 FALSE
+
+/* USART attributes.*/
+#define STM32_HAS_USART1 TRUE
+#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\
+ STM32_DMA_STREAM_ID_MSK(2, 7))
+#define STM32_USART1_RX_DMA_CHN 0x02020000
+#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\
+ STM32_DMA_STREAM_ID_MSK(2, 6))
+#define STM32_USART1_TX_DMA_CHN 0x00202000
+
+#define STM32_HAS_USART2 TRUE
+#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6))
+#define STM32_USART2_RX_DMA_CHN 0x00200000
+#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7))
+#define STM32_USART2_TX_DMA_CHN 0x02000000
+
+#define STM32_HAS_USART3 TRUE
+#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3))
+#define STM32_USART3_RX_DMA_CHN 0x00000200
+#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2))
+#define STM32_USART3_TX_DMA_CHN 0x00000020
+
+#define STM32_HAS_LPUART1 TRUE
+
+#define STM32_HAS_UART4 FALSE
+#define STM32_HAS_UART5 FALSE
+#define STM32_HAS_USART6 FALSE
+#define STM32_HAS_UART7 FALSE
+#define STM32_HAS_UART8 FALSE
+
+/* USB attributes.*/
+#define STM32_HAS_USB TRUE
+#define STM32_USB_ACCESS_SCHEME_2x16 TRUE
+#define STM32_USB_PMA_SIZE 1024
+#define STM32_USB_HAS_BCDR TRUE
+
+#define STM32_HAS_OTG1 FALSE
+#define STM32_HAS_OTG2 FALSE
+
+/* IWDG attributes.*/
+#define STM32_HAS_IWDG TRUE
+#define STM32_IWDG_IS_WINDOWED TRUE
+
+/* LTDC attributes.*/
+#define STM32_HAS_LTDC FALSE
+
+/* DMA2D attributes.*/
+#define STM32_HAS_DMA2D FALSE
+
+/* FSMC attributes.*/
+#define STM32_HAS_FSMC TRUE
+
+/* CRC attributes.*/
+#define STM32_HAS_CRC TRUE
+#define STM32_CRC_PROGRAMMABLE TRUE
+
+#endif /* defined(STM32L443xx) */
+
+/*===========================================================================*/
+/* STM32L452xx. */
+/*===========================================================================*/
+
+#if defined(STM32L452xx) || defined(__DOXYGEN__)
+
+/* Clock attributes.*/
+#define STM32_CLOCK_HAS_HSI48 TRUE
+
+/* ADC attributes.*/
+#define STM32_HAS_ADC1 TRUE
+#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\
+ STM32_DMA_STREAM_ID_MSK(2, 3))
+#define STM32_ADC1_DMA_CHN 0x00000000
+
+#define STM32_HAS_ADC2 FALSE
+#define STM32_HAS_ADC3 FALSE
+#define STM32_HAS_ADC4 FALSE
+
+/* CAN attributes.*/
+#define STM32_CAN_MAX_FILTERS 14
+#define STM32_HAS_CAN1 TRUE
+#define STM32_HAS_CAN2 FALSE
+#define STM32_HAS_CAN3 FALSE
+
+/* DAC attributes.*/
+#define STM32_HAS_DAC1_CH1 TRUE
+#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)|\
+ STM32_DMA_STREAM_ID_MSK(2, 4))
+#define STM32_DAC1_CH1_DMA_CHN 0x00003600
+
+#define STM32_HAS_DAC1_CH2 FALSE
+#define STM32_HAS_DAC2_CH1 FALSE
+#define STM32_HAS_DAC2_CH2 FALSE
+
+/* DMA attributes.*/
+#define STM32_ADVANCED_DMA TRUE
+#define STM32_DMA_SUPPORTS_DMAMUX FALSE
+#define STM32_DMA_SUPPORTS_CSELR TRUE
+#define STM32_DMA1_NUM_CHANNELS 7
+#define STM32_DMA2_NUM_CHANNELS 7
+
+/* ETH attributes.*/
+#define STM32_HAS_ETH FALSE
+
+/* EXTI attributes.*/
+#define STM32_EXTI_NUM_LINES 40
+#define STM32_EXTI_IMR1_MASK 0xFF820000U
+#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U
+
+/* GPIO attributes.*/
+#define STM32_HAS_GPIOA TRUE
+#define STM32_HAS_GPIOB TRUE
+#define STM32_HAS_GPIOC TRUE
+#define STM32_HAS_GPIOD TRUE
+#define STM32_HAS_GPIOE TRUE
+#define STM32_HAS_GPIOF FALSE
+#define STM32_HAS_GPIOG FALSE
+#define STM32_HAS_GPIOH TRUE
+#define STM32_HAS_GPIOI FALSE
+#define STM32_HAS_GPIOJ FALSE
+#define STM32_HAS_GPIOK FALSE
+#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \
+ RCC_AHB2ENR_GPIOBEN | \
+ RCC_AHB2ENR_GPIOCEN | \
+ RCC_AHB2ENR_GPIODEN | \
+ RCC_AHB2ENR_GPIOEEN | \
+ RCC_AHB2ENR_GPIOHEN)
+
+/* I2C attributes.*/
+#define STM32_HAS_I2C1 TRUE
+#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\
+ STM32_DMA_STREAM_ID_MSK(2, 6))
+#define STM32_I2C1_RX_DMA_CHN 0x03500000
+#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6) |\
+ STM32_DMA_STREAM_ID_MSK(2, 7))
+#define STM32_I2C1_TX_DMA_CHN 0x05300000
+
+#define STM32_HAS_I2C2 TRUE
+#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5))
+#define STM32_I2C2_RX_DMA_CHN 0x00030000
+#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4))
+#define STM32_I2C2_TX_DMA_CHN 0x00003000
+
+#define STM32_HAS_I2C3 TRUE
+#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3))
+#define STM32_I2C3_RX_DMA_CHN 0x00000300
+#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2))
+#define STM32_I2C3_TX_DMA_CHN 0x00000030
+
+#define STM32_HAS_I2C4 TRUE
+#define STM32_I2C4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2))
+#define STM32_I2C4_RX_DMA_CHN 0x00000000
+#define STM32_I2C4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1))
+#define STM32_I2C4_TX_DMA_CHN 0x00000000
+
+/* QUADSPI attributes.*/
+#define STM32_HAS_QUADSPI1 TRUE
+#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\
+ STM32_DMA_STREAM_ID_MSK(2, 7))
+#define STM32_QUADSPI1_DMA_CHN 0x03050000
+
+/* SDMMC attributes.*/
+#define STM32_HAS_SDMMC1 TRUE
+#define STM32_SDC_SDMMC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\
+ STM32_DMA_STREAM_ID_MSK(2, 5))
+#define STM32_SDC_SDMMC1_DMA_CHN 0x00077000
+
+#define STM32_HAS_SDMMC2 FALSE
+
+/* SPI attributes.*/
+#define STM32_HAS_SPI1 TRUE
+#define STM32_SPI1_SUPPORTS_I2S FALSE
+#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\
+ STM32_DMA_STREAM_ID_MSK(2, 3))
+#define STM32_SPI1_RX_DMA_CHN 0x00000410
+#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\
+ STM32_DMA_STREAM_ID_MSK(2, 4))
+#define STM32_SPI1_TX_DMA_CHN 0x00004100
+
+#define STM32_HAS_SPI2 TRUE
+#define STM32_SPI2_SUPPORTS_I2S FALSE
+#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4))
+#define STM32_SPI2_RX_DMA_CHN 0x00001000
+#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5))
+#define STM32_SPI2_TX_DMA_CHN 0x00010000
+
+#define STM32_HAS_SPI3 TRUE
+#define STM32_SPI3_SUPPORTS_I2S FALSE
+#define STM32_SPI3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1))
+#define STM32_SPI3_RX_DMA_CHN 0x00000003
+#define STM32_SPI3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2))
+#define STM32_SPI3_TX_DMA_CHN 0x00000030
+
+#define STM32_HAS_SPI4 FALSE
+#define STM32_HAS_SPI5 FALSE
+#define STM32_HAS_SPI6 FALSE
+
+/* TIM attributes.*/
+#define STM32_TIM_MAX_CHANNELS 6
+
+#define STM32_HAS_TIM1 TRUE
+#define STM32_TIM1_IS_32BITS FALSE
+#define STM32_TIM1_CHANNELS 6
+
+#define STM32_HAS_TIM2 TRUE
+#define STM32_TIM2_IS_32BITS TRUE
+#define STM32_TIM2_CHANNELS 4
+
+#define STM32_HAS_TIM3 TRUE
+#define STM32_TIM3_IS_32BITS FALSE
+#define STM32_TIM3_CHANNELS 4
+
+#define STM32_HAS_TIM6 TRUE
+#define STM32_TIM6_IS_32BITS FALSE
+#define STM32_TIM6_CHANNELS 0
+
+#define STM32_HAS_TIM15 TRUE
+#define STM32_TIM15_IS_32BITS FALSE
+#define STM32_TIM15_CHANNELS 2
+
+#define STM32_HAS_TIM16 TRUE
+#define STM32_TIM16_IS_32BITS FALSE
+#define STM32_TIM16_CHANNELS 2
+
+#define STM32_HAS_TIM4 FALSE
+#define STM32_HAS_TIM5 FALSE
+#define STM32_HAS_TIM7 FALSE
+#define STM32_HAS_TIM8 FALSE
+#define STM32_HAS_TIM9 FALSE
+#define STM32_HAS_TIM10 FALSE
+#define STM32_HAS_TIM11 FALSE
+#define STM32_HAS_TIM12 FALSE
+#define STM32_HAS_TIM13 FALSE
+#define STM32_HAS_TIM14 FALSE
+#define STM32_HAS_TIM17 FALSE
+#define STM32_HAS_TIM18 FALSE
+#define STM32_HAS_TIM19 FALSE
+#define STM32_HAS_TIM20 FALSE
+#define STM32_HAS_TIM21 FALSE
+#define STM32_HAS_TIM22 FALSE
+
+/* USART attributes.*/
+#define STM32_HAS_USART1 TRUE
+#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\
+ STM32_DMA_STREAM_ID_MSK(2, 7))
+#define STM32_USART1_RX_DMA_CHN 0x02020000
+#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\
+ STM32_DMA_STREAM_ID_MSK(2, 6))
+#define STM32_USART1_TX_DMA_CHN 0x00202000
+
+#define STM32_HAS_USART2 TRUE
+#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6))
+#define STM32_USART2_RX_DMA_CHN 0x00200000
+#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7))
+#define STM32_USART2_TX_DMA_CHN 0x02000000
+
+#define STM32_HAS_USART3 TRUE
+#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3))
+#define STM32_USART3_RX_DMA_CHN 0x00000200
+#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2))
+#define STM32_USART3_TX_DMA_CHN 0x00000020
+
+#define STM32_HAS_UART4 TRUE
+#define STM32_UART4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 5))
+#define STM32_UART4_RX_DMA_CHN 0x00020000
+#define STM32_UART4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 3))
+#define STM32_UART4_TX_DMA_CHN 0x00000200
+
+#define STM32_HAS_LPUART1 TRUE
+
+#define STM32_HAS_UART5 FALSE
+#define STM32_HAS_USART6 FALSE
+#define STM32_HAS_UART7 FALSE
+#define STM32_HAS_UART8 FALSE
+
+/* USB attributes.*/
+#define STM32_HAS_USB TRUE
+#define STM32_USB_ACCESS_SCHEME_2x16 TRUE
+#define STM32_USB_PMA_SIZE 1024
+#define STM32_USB_HAS_BCDR TRUE
+
+#define STM32_HAS_OTG1 FALSE
+#define STM32_HAS_OTG2 FALSE
+
+/* IWDG attributes.*/
+#define STM32_HAS_IWDG TRUE
+#define STM32_IWDG_IS_WINDOWED TRUE
+
+/* LTDC attributes.*/
+#define STM32_HAS_LTDC FALSE
+
+/* DMA2D attributes.*/
+#define STM32_HAS_DMA2D FALSE
+
+/* FSMC attributes.*/
+#define STM32_HAS_FSMC TRUE
+
+/* CRC attributes.*/
+#define STM32_HAS_CRC TRUE
+#define STM32_CRC_PROGRAMMABLE TRUE
+
+#endif /* defined(STM32L452xx) */
+
+/*===========================================================================*/
+/* STM32L476xx, STM32L486xx. */
+/*===========================================================================*/
+
+#if defined(STM32L476xx) || defined(STM32L486xx)
+
+/* Clock attributes.*/
+#define STM32_CLOCK_HAS_HSI48 FALSE
+
+/* ADC attributes.*/
+#define STM32_HAS_ADC1 TRUE
+#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\
+ STM32_DMA_STREAM_ID_MSK(2, 3))
+#define STM32_ADC1_DMA_CHN 0x00000000
+
+#define STM32_HAS_ADC2 TRUE
+#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\
+ STM32_DMA_STREAM_ID_MSK(2, 4))
+#define STM32_ADC2_DMA_CHN 0x00000000
+
+#define STM32_HAS_ADC3 TRUE
+#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\
+ STM32_DMA_STREAM_ID_MSK(2, 5))
+#define STM32_ADC3_DMA_CHN 0x00000000
+
+#define STM32_HAS_ADC4 FALSE
+
+/* CAN attributes.*/
+#define STM32_CAN_MAX_FILTERS 14
+#define STM32_HAS_CAN1 TRUE
+#define STM32_HAS_CAN2 FALSE
+#define STM32_HAS_CAN3 FALSE
+
+/* DAC attributes.*/
+#define STM32_HAS_DAC1_CH1 TRUE
+#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)|\
+ STM32_DMA_STREAM_ID_MSK(2, 4))
+#define STM32_DAC1_CH1_DMA_CHN 0x00003600
+
+#define STM32_HAS_DAC1_CH2 TRUE
+#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)|\
+ STM32_DMA_STREAM_ID_MSK(2, 5))
+#define STM32_DAC1_CH2_DMA_CHN 0x00035000
+
+#define STM32_HAS_DAC2_CH1 FALSE
+#define STM32_HAS_DAC2_CH2 FALSE
+
+/* DMA attributes.*/
+#define STM32_ADVANCED_DMA TRUE
+#define STM32_DMA_SUPPORTS_DMAMUX FALSE
+#define STM32_DMA_SUPPORTS_CSELR TRUE
+#define STM32_DMA1_NUM_CHANNELS 7
+#define STM32_DMA2_NUM_CHANNELS 7
+
+/* ETH attributes.*/
+#define STM32_HAS_ETH FALSE
+
+/* EXTI attributes.*/
+#define STM32_EXTI_NUM_LINES 40
+#define STM32_EXTI_IMR1_MASK 0xFF820000U
+#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U
+
+/* Flash attributes.*/
+#define STM32_FLASH_NUMBER_OF_BANKS 2
+#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__)
+#define STM32_FLASH_SECTORS_PER_BANK 256 /* Maximum, can be redefined.*/
+#endif
+
+/* GPIO attributes.*/
+#define STM32_HAS_GPIOA TRUE
+#define STM32_HAS_GPIOB TRUE
+#define STM32_HAS_GPIOC TRUE
+#define STM32_HAS_GPIOD TRUE
+#define STM32_HAS_GPIOE TRUE
+#define STM32_HAS_GPIOF TRUE
+#define STM32_HAS_GPIOG TRUE
+#define STM32_HAS_GPIOH TRUE
+#define STM32_HAS_GPIOI FALSE
+#define STM32_HAS_GPIOJ FALSE
+#define STM32_HAS_GPIOK FALSE
+#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \
+ RCC_AHB2ENR_GPIOBEN | \
+ RCC_AHB2ENR_GPIOCEN | \
+ RCC_AHB2ENR_GPIODEN | \
+ RCC_AHB2ENR_GPIOEEN | \
+ RCC_AHB2ENR_GPIOFEN | \
+ RCC_AHB2ENR_GPIOGEN | \
+ RCC_AHB2ENR_GPIOHEN)
+
+/* I2C attributes.*/
+#define STM32_HAS_I2C1 TRUE
+#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\
+ STM32_DMA_STREAM_ID_MSK(2, 6))
+#define STM32_I2C1_RX_DMA_CHN 0x03500000
+#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6) |\
+ STM32_DMA_STREAM_ID_MSK(2, 7))
+#define STM32_I2C1_TX_DMA_CHN 0x05300000
+
+#define STM32_HAS_I2C2 TRUE
+#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5))
+#define STM32_I2C2_RX_DMA_CHN 0x00030000
+#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4))
+#define STM32_I2C2_TX_DMA_CHN 0x00003000
+
+#define STM32_HAS_I2C3 TRUE
+#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3))
+#define STM32_I2C3_RX_DMA_CHN 0x00000300
+#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2))
+#define STM32_I2C3_TX_DMA_CHN 0x00000030
+
+#define STM32_HAS_I2C4 FALSE
+
+/* QUADSPI attributes.*/
+#define STM32_HAS_QUADSPI1 TRUE
+#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\
+ STM32_DMA_STREAM_ID_MSK(2, 7))
+#define STM32_QUADSPI1_DMA_CHN 0x03050000
+
+/* SDMMC attributes.*/
+#define STM32_HAS_SDMMC1 TRUE
+#define STM32_SDC_SDMMC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\
+ STM32_DMA_STREAM_ID_MSK(2, 5))
+#define STM32_SDC_SDMMC1_DMA_CHN 0x00077000
+
+#define STM32_HAS_SDMMC2 FALSE
+
+/* SPI attributes.*/
+#define STM32_HAS_SPI1 TRUE
+#define STM32_SPI1_SUPPORTS_I2S FALSE
+#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\
+ STM32_DMA_STREAM_ID_MSK(2, 3))
+#define STM32_SPI1_RX_DMA_CHN 0x00000410
+#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\
+ STM32_DMA_STREAM_ID_MSK(2, 4))
+#define STM32_SPI1_TX_DMA_CHN 0x00004100
+
+#define STM32_HAS_SPI2 TRUE
+#define STM32_SPI2_SUPPORTS_I2S FALSE
+#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4))
+#define STM32_SPI2_RX_DMA_CHN 0x00001000
+#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5))
+#define STM32_SPI2_TX_DMA_CHN 0x00010000
+
+#define STM32_HAS_SPI3 TRUE
+#define STM32_SPI3_SUPPORTS_I2S FALSE
+#define STM32_SPI3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1))
+#define STM32_SPI3_RX_DMA_CHN 0x00000003
+#define STM32_SPI3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2))
+#define STM32_SPI3_TX_DMA_CHN 0x00000030
+
+#define STM32_HAS_SPI4 FALSE
+#define STM32_HAS_SPI5 FALSE
+#define STM32_HAS_SPI6 FALSE
+
+/* TIM attributes.*/
+#define STM32_TIM_MAX_CHANNELS 6
+
+#define STM32_HAS_TIM1 TRUE
+#define STM32_TIM1_IS_32BITS FALSE
+#define STM32_TIM1_CHANNELS 6
+
+#define STM32_HAS_TIM2 TRUE
+#define STM32_TIM2_IS_32BITS TRUE
+#define STM32_TIM2_CHANNELS 4
+
+#define STM32_HAS_TIM3 TRUE
+#define STM32_TIM3_IS_32BITS FALSE
+#define STM32_TIM3_CHANNELS 4
+
+#define STM32_HAS_TIM4 TRUE
+#define STM32_TIM4_IS_32BITS FALSE
+#define STM32_TIM4_CHANNELS 4
+
+#define STM32_HAS_TIM5 TRUE
+#define STM32_TIM5_IS_32BITS TRUE
+#define STM32_TIM5_CHANNELS 4
+
+#define STM32_HAS_TIM6 TRUE
+#define STM32_TIM6_IS_32BITS FALSE
+#define STM32_TIM6_CHANNELS 0
+
+#define STM32_HAS_TIM7 TRUE
+#define STM32_TIM7_IS_32BITS FALSE
+#define STM32_TIM7_CHANNELS 0
+
+#define STM32_HAS_TIM8 TRUE
+#define STM32_TIM8_IS_32BITS FALSE
+#define STM32_TIM8_CHANNELS 6
+
+#define STM32_HAS_TIM15 TRUE
+#define STM32_TIM15_IS_32BITS FALSE
+#define STM32_TIM15_CHANNELS 2
+
+#define STM32_HAS_TIM16 TRUE
+#define STM32_TIM16_IS_32BITS FALSE
+#define STM32_TIM16_CHANNELS 2
+
+#define STM32_HAS_TIM17 TRUE
+#define STM32_TIM17_IS_32BITS FALSE
+#define STM32_TIM17_CHANNELS 2
+
+#define STM32_HAS_TIM9 FALSE
+#define STM32_HAS_TIM10 FALSE
+#define STM32_HAS_TIM11 FALSE
+#define STM32_HAS_TIM12 FALSE
+#define STM32_HAS_TIM13 FALSE
+#define STM32_HAS_TIM14 FALSE
+#define STM32_HAS_TIM18 FALSE
+#define STM32_HAS_TIM19 FALSE
+#define STM32_HAS_TIM20 FALSE
+#define STM32_HAS_TIM21 FALSE
+#define STM32_HAS_TIM22 FALSE
+
+/* USART attributes.*/
+#define STM32_HAS_USART1 TRUE
+#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\
+ STM32_DMA_STREAM_ID_MSK(2, 7))
+#define STM32_USART1_RX_DMA_CHN 0x02020000
+#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\
+ STM32_DMA_STREAM_ID_MSK(2, 6))
+#define STM32_USART1_TX_DMA_CHN 0x00202000
+
+#define STM32_HAS_USART2 TRUE
+#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6))
+#define STM32_USART2_RX_DMA_CHN 0x00200000
+#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7))
+#define STM32_USART2_TX_DMA_CHN 0x02000000
+
+#define STM32_HAS_USART3 TRUE
+#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3))
+#define STM32_USART3_RX_DMA_CHN 0x00000200
+#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2))
+#define STM32_USART3_TX_DMA_CHN 0x00000020
+
+#define STM32_HAS_UART4 TRUE
+#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 5)
+#define STM32_UART4_RX_DMA_CHN 0x00020000
+#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 3)
+#define STM32_UART4_TX_DMA_CHN 0x00000200
+
+#define STM32_HAS_UART5 TRUE
+#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 2)
+#define STM32_UART5_RX_DMA_CHN 0x00000020
+#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 1)
+#define STM32_UART5_TX_DMA_CHN 0x00000002
+
+#define STM32_HAS_LPUART1 TRUE
+
+#define STM32_HAS_USART6 FALSE
+#define STM32_HAS_UART7 FALSE
+#define STM32_HAS_UART8 FALSE
+
+/* USB attributes.*/
+#define STM32_OTG_SEQUENCE_WORKAROUND
+#define STM32_OTG_STEPPING 2
+#define STM32_HAS_OTG1 TRUE
+#define STM32_OTG1_ENDPOINTS 5
+
+#define STM32_HAS_OTG2 FALSE
+#define STM32_HAS_USB FALSE
+
+/* IWDG attributes.*/
+#define STM32_HAS_IWDG TRUE
+#define STM32_IWDG_IS_WINDOWED TRUE
+
+/* LTDC attributes.*/
+#define STM32_HAS_LTDC FALSE
+
+/* DMA2D attributes.*/
+#define STM32_HAS_DMA2D FALSE
+
+/* FSMC attributes.*/
+#define STM32_HAS_FSMC TRUE
+
+/* CRC attributes.*/
+#define STM32_HAS_CRC TRUE
+#define STM32_CRC_PROGRAMMABLE TRUE
+
+#endif /* defined(STM32L476xx) */
+
+/*===========================================================================*/
+/* STM32L496xx, STM32L4A6xx. */
+/*===========================================================================*/
+
+#if defined(STM32L496xx) || defined(STM32L4A6xx)
+
+/* Clock attributes.*/
+#define STM32_CLOCK_HAS_HSI48 FALSE
+
+/* ADC attributes.*/
+#define STM32_HAS_ADC1 TRUE
+#define STM32_ADC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 1) |\
+ STM32_DMA_STREAM_ID_MSK(2, 3))
+#define STM32_ADC1_DMA_CHN 0x00000000
+
+#define STM32_HAS_ADC2 TRUE
+#define STM32_ADC2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\
+ STM32_DMA_STREAM_ID_MSK(2, 4))
+#define STM32_ADC2_DMA_CHN 0x00000000
+
+#define STM32_HAS_ADC3 TRUE
+#define STM32_ADC3_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\
+ STM32_DMA_STREAM_ID_MSK(2, 5))
+#define STM32_ADC3_DMA_CHN 0x00000000
+
+#define STM32_HAS_ADC4 FALSE
+
+/* CAN attributes.*/
+#define STM32_CAN_MAX_FILTERS 14
+#define STM32_HAS_CAN1 TRUE
+#define STM32_HAS_CAN2 TRUE
+#define STM32_HAS_CAN3 FALSE
+
+/* DAC attributes.*/
+#define STM32_HAS_DAC1_CH1 TRUE
+#define STM32_DAC1_CH1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3)|\
+ STM32_DMA_STREAM_ID_MSK(2, 4))
+#define STM32_DAC1_CH1_DMA_CHN 0x00003600
+
+#define STM32_HAS_DAC1_CH2 TRUE
+#define STM32_DAC1_CH2_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4)|\
+ STM32_DMA_STREAM_ID_MSK(2, 5))
+#define STM32_DAC1_CH2_DMA_CHN 0x00035000
+
+#define STM32_HAS_DAC2_CH1 FALSE
+#define STM32_HAS_DAC2_CH2 FALSE
+
+/* DMA attributes.*/
+#define STM32_ADVANCED_DMA TRUE
+#define STM32_DMA_SUPPORTS_DMAMUX FALSE
+#define STM32_DMA_SUPPORTS_CSELR TRUE
+#define STM32_DMA1_NUM_CHANNELS 7
+#define STM32_DMA2_NUM_CHANNELS 7
+
+/* ETH attributes.*/
+#define STM32_HAS_ETH FALSE
+
+/* EXTI attributes.*/
+#define STM32_EXTI_NUM_LINES 40
+#define STM32_EXTI_IMR1_MASK 0xFF820000U
+#define STM32_EXTI_IMR2_MASK 0xFFFFFF87U
+
+/* Flash attributes.*/
+#define STM32_FLASH_NUMBER_OF_BANKS 2
+#if !defined(STM32_FLASH_SECTORS_PER_BANK) || defined(__DOXYGEN__)
+#define STM32_FLASH_SECTORS_PER_BANK 256 /* Maximum, can be redefined.*/
+#endif
+
+/* GPIO attributes.*/
+#define STM32_HAS_GPIOA TRUE
+#define STM32_HAS_GPIOB TRUE
+#define STM32_HAS_GPIOC TRUE
+#define STM32_HAS_GPIOD TRUE
+#define STM32_HAS_GPIOE TRUE
+#define STM32_HAS_GPIOF TRUE
+#define STM32_HAS_GPIOG TRUE
+#define STM32_HAS_GPIOH TRUE
+#define STM32_HAS_GPIOI FALSE
+#define STM32_HAS_GPIOJ FALSE
+#define STM32_HAS_GPIOK FALSE
+#define STM32_GPIO_EN_MASK (RCC_AHB2ENR_GPIOAEN | \
+ RCC_AHB2ENR_GPIOBEN | \
+ RCC_AHB2ENR_GPIOCEN | \
+ RCC_AHB2ENR_GPIODEN | \
+ RCC_AHB2ENR_GPIOEEN | \
+ RCC_AHB2ENR_GPIOFEN | \
+ RCC_AHB2ENR_GPIOGEN | \
+ RCC_AHB2ENR_GPIOHEN)
+
+/* I2C attributes.*/
+#define STM32_HAS_I2C1 TRUE
+#define STM32_I2C1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7) |\
+ STM32_DMA_STREAM_ID_MSK(2, 6))
+#define STM32_I2C1_RX_DMA_CHN 0x03500000
+#define STM32_I2C1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6) |\
+ STM32_DMA_STREAM_ID_MSK(2, 7))
+#define STM32_I2C1_TX_DMA_CHN 0x05300000
+
+#define STM32_HAS_I2C2 TRUE
+#define STM32_I2C2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5))
+#define STM32_I2C2_RX_DMA_CHN 0x00030000
+#define STM32_I2C2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4))
+#define STM32_I2C2_TX_DMA_CHN 0x00003000
+
+#define STM32_HAS_I2C3 TRUE
+#define STM32_I2C3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3))
+#define STM32_I2C3_RX_DMA_CHN 0x00000300
+#define STM32_I2C3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2))
+#define STM32_I2C3_TX_DMA_CHN 0x00000030
+
+#define STM32_HAS_I2C4 TRUE
+#define STM32_I2C4_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2))
+#define STM32_I2C4_RX_DMA_CHN 0x00000000
+#define STM32_I2C4_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1))
+#define STM32_I2C4_TX_DMA_CHN 0x00000000
+
+/* QUADSPI attributes.*/
+#define STM32_HAS_QUADSPI1 TRUE
+#define STM32_QUADSPI1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\
+ STM32_DMA_STREAM_ID_MSK(2, 7))
+#define STM32_QUADSPI1_DMA_CHN 0x03050000
+
+/* SDMMC attributes.*/
+#define STM32_HAS_SDMMC1 TRUE
+#define STM32_SDC_SDMMC1_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 4) |\
+ STM32_DMA_STREAM_ID_MSK(2, 5))
+#define STM32_SDC_SDMMC1_DMA_CHN 0x00077000
+
+#define STM32_HAS_SDMMC2 FALSE
+
+/* SPI attributes.*/
+#define STM32_HAS_SPI1 TRUE
+#define STM32_SPI1_SUPPORTS_I2S FALSE
+#define STM32_SPI1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2) |\
+ STM32_DMA_STREAM_ID_MSK(2, 3))
+#define STM32_SPI1_RX_DMA_CHN 0x00000410
+#define STM32_SPI1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3) |\
+ STM32_DMA_STREAM_ID_MSK(2, 4))
+#define STM32_SPI1_TX_DMA_CHN 0x00004100
+
+#define STM32_HAS_SPI2 TRUE
+#define STM32_SPI2_SUPPORTS_I2S FALSE
+#define STM32_SPI2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4))
+#define STM32_SPI2_RX_DMA_CHN 0x00001000
+#define STM32_SPI2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5))
+#define STM32_SPI2_TX_DMA_CHN 0x00010000
+
+#define STM32_HAS_SPI3 TRUE
+#define STM32_SPI3_SUPPORTS_I2S FALSE
+#define STM32_SPI3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 1))
+#define STM32_SPI3_RX_DMA_CHN 0x00000003
+#define STM32_SPI3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(2, 2))
+#define STM32_SPI3_TX_DMA_CHN 0x00000030
+
+#define STM32_HAS_SPI4 FALSE
+#define STM32_HAS_SPI5 FALSE
+#define STM32_HAS_SPI6 FALSE
+
+/* TIM attributes.*/
+#define STM32_TIM_MAX_CHANNELS 6
+
+#define STM32_HAS_TIM1 TRUE
+#define STM32_TIM1_IS_32BITS FALSE
+#define STM32_TIM1_CHANNELS 6
+
+#define STM32_HAS_TIM2 TRUE
+#define STM32_TIM2_IS_32BITS TRUE
+#define STM32_TIM2_CHANNELS 4
+
+#define STM32_HAS_TIM3 TRUE
+#define STM32_TIM3_IS_32BITS FALSE
+#define STM32_TIM3_CHANNELS 4
+
+#define STM32_HAS_TIM4 TRUE
+#define STM32_TIM4_IS_32BITS FALSE
+#define STM32_TIM4_CHANNELS 4
+
+#define STM32_HAS_TIM5 TRUE
+#define STM32_TIM5_IS_32BITS TRUE
+#define STM32_TIM5_CHANNELS 4
+
+#define STM32_HAS_TIM6 TRUE
+#define STM32_TIM6_IS_32BITS FALSE
+#define STM32_TIM6_CHANNELS 0
+
+#define STM32_HAS_TIM7 TRUE
+#define STM32_TIM7_IS_32BITS FALSE
+#define STM32_TIM7_CHANNELS 0
+
+#define STM32_HAS_TIM8 TRUE
+#define STM32_TIM8_IS_32BITS FALSE
+#define STM32_TIM8_CHANNELS 6
+
+#define STM32_HAS_TIM15 TRUE
+#define STM32_TIM15_IS_32BITS FALSE
+
+#define STM32_HAS_TIM16 TRUE
+#define STM32_TIM16_IS_32BITS FALSE
+
+#define STM32_HAS_TIM17 TRUE
+#define STM32_TIM17_IS_32BITS FALSE
+
+#define STM32_HAS_TIM9 FALSE
+#define STM32_HAS_TIM10 FALSE
+#define STM32_HAS_TIM11 FALSE
+#define STM32_HAS_TIM12 FALSE
+#define STM32_HAS_TIM13 FALSE
+#define STM32_HAS_TIM14 FALSE
+#define STM32_HAS_TIM18 FALSE
+#define STM32_HAS_TIM19 FALSE
+#define STM32_HAS_TIM20 FALSE
+#define STM32_HAS_TIM21 FALSE
+#define STM32_HAS_TIM22 FALSE
+
+/* USART attributes.*/
+#define STM32_HAS_USART1 TRUE
+#define STM32_USART1_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 5) |\
+ STM32_DMA_STREAM_ID_MSK(2, 7))
+#define STM32_USART1_RX_DMA_CHN 0x02020000
+#define STM32_USART1_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 4) |\
+ STM32_DMA_STREAM_ID_MSK(2, 6))
+#define STM32_USART1_TX_DMA_CHN 0x00202000
+
+#define STM32_HAS_USART2 TRUE
+#define STM32_USART2_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 6))
+#define STM32_USART2_RX_DMA_CHN 0x00200000
+#define STM32_USART2_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 7))
+#define STM32_USART2_TX_DMA_CHN 0x02000000
+
+#define STM32_HAS_USART3 TRUE
+#define STM32_USART3_RX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 3))
+#define STM32_USART3_RX_DMA_CHN 0x00000200
+#define STM32_USART3_TX_DMA_MSK (STM32_DMA_STREAM_ID_MSK(1, 2))
+#define STM32_USART3_TX_DMA_CHN 0x00000020
+
+#define STM32_HAS_UART4 TRUE
+#define STM32_UART4_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 5)
+#define STM32_UART4_RX_DMA_CHN 0x00020000
+#define STM32_UART4_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 3)
+#define STM32_UART4_TX_DMA_CHN 0x00000200
+
+#define STM32_HAS_UART5 TRUE
+#define STM32_UART5_RX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 2)
+#define STM32_UART5_RX_DMA_CHN 0x00000020
+#define STM32_UART5_TX_DMA_MSK STM32_DMA_STREAM_ID_MSK(2, 1)
+#define STM32_UART5_TX_DMA_CHN 0x00000002
+
+#define STM32_HAS_LPUART1 TRUE
+
+#define STM32_HAS_USART6 FALSE
+#define STM32_HAS_UART7 FALSE
+#define STM32_HAS_UART8 FALSE
+
+/* USB attributes.*/
+#define STM32_OTG_STEPPING 2
+#define STM32_HAS_OTG1 TRUE
+#define STM32_OTG1_ENDPOINTS 5
+
+#define STM32_HAS_OTG2 FALSE
+#define STM32_HAS_USB FALSE
+
+/* IWDG attributes.*/
+#define STM32_HAS_IWDG TRUE
+#define STM32_IWDG_IS_WINDOWED TRUE
+
+/* LTDC attributes.*/
+#define STM32_HAS_LTDC FALSE
+
+/* DMA2D attributes.*/
+#define STM32_HAS_DMA2D TRUE
+
+/* FSMC attributes.*/
+#define STM32_HAS_FSMC TRUE
+
+/* CRC attributes.*/
+#define STM32_HAS_CRC TRUE
+#define STM32_CRC_PROGRAMMABLE TRUE
+
+#endif /* defined(STM32L496xx) */
+
+/** @} */
+
+#endif /* STM32_REGISTRY_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/STM32/todo.txt b/ChibiOS_20.3.2/os/hal/ports/STM32/todo.txt
new file mode 100644
index 0000000..c30cafc
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/STM32/todo.txt
@@ -0,0 +1,4 @@
+- BOFF handling in DACv1.
+- Oversampling support for ADCv1 and ADCv3.
+- Implement missing ICU/PWM/GPT/ST units using shared IRQ handlers.
+- Implement I2S driver over SAI interfaces.
diff --git a/ChibiOS_20.3.2/os/hal/ports/common/ARMCMx/cache.h b/ChibiOS_20.3.2/os/hal/ports/common/ARMCMx/cache.h
new file mode 100644
index 0000000..52a92e7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/common/ARMCMx/cache.h
@@ -0,0 +1,160 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file common/ARMCMx/cache.h
+ * @brief Cortex-Mx cache support macros and structures.
+ *
+ * @addtogroup COMMON_ARMCMx_CACHE
+ * @{
+ */
+
+#ifndef CACHE_H
+#define CACHE_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+#if defined(__DCACHE_PRESENT) || defined(__DOXYGEN__)
+/**
+ * @brief Data cache line size, zero if there is no data cache.
+ */
+#define CACHE_LINE_SIZE 32U
+#else
+#define CACHE_LINE_SIZE 0U
+#endif
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+#if defined(__DCACHE_PRESENT) || defined(__DOXYGEN__)
+#if (__DCACHE_PRESENT != 0) || defined(__DOXYGEN__)
+/**
+ * @brief Aligns the specified size to a multiple of cache line size.
+ * @note This macros assumes that the size of the type @p t is a power of
+ * two and not greater than @p CACHE_LINE_SIZE.
+ *
+ * @param[in] t type of the buffer element
+ * @param[in] n number of buffer elements
+ */
+#define CACHE_SIZE_ALIGN(t, n) \
+ ((((((n) * sizeof (t)) - 1U) | (CACHE_LINE_SIZE - 1U)) + 1U) / sizeof (t))
+
+/**
+ * @brief Invalidates the data cache lines overlapping a memory buffer.
+ * @details This function is meant to make sure that data written in
+ * data cache is invalidated.
+ * @note On devices without data cache this function does nothing.
+ * @note The function does not consider the lower 5 bits of addresses,
+ * the buffers are meant to be aligned to a 32 bytes boundary or
+ * adjacent data can be invalidated as side effect.
+ *
+ * @param[in] saddr start address of the DMA buffer
+ * @param[in] n size of the DMA buffer in bytes
+ *
+ * @api
+ */
+#define cacheBufferInvalidate(saddr, n) { \
+ uint8_t *start = (uint8_t *)(saddr); \
+ uint8_t *end = start + (size_t)(n); \
+ __DSB(); \
+ while (start < end) { \
+ SCB->DCIMVAC = (uint32_t)start; \
+ start += CACHE_LINE_SIZE; \
+ } \
+ __DSB(); \
+ __ISB(); \
+}
+
+/**
+ * @brief Flushes the data cache lines overlapping a DMA buffer.
+ * @details This function is meant to make sure that data written in
+ * data cache is flushed to RAM.
+ * @note On devices without data cache this function does nothing.
+ * @note The function does not consider the lower 5 bits of addresses,
+ * the buffers are meant to be aligned to a 32 bytes boundary or
+ * adjacent data can be flushed as side effect.
+ *
+ * @param[in] saddr start address of the DMA buffer
+ * @param[in] n size of the DMA buffer in bytes
+ *
+ * @api
+ */
+#define cacheBufferFlush(saddr, n) { \
+ uint8_t *start = (uint8_t *)(saddr); \
+ uint8_t *end = start + (size_t)(n); \
+ __DSB(); \
+ while (start < end) { \
+ SCB->DCCIMVAC = (uint32_t)start; \
+ start += CACHE_LINE_SIZE; \
+ } \
+ __DSB(); \
+ __ISB(); \
+}
+
+#else /* __DCACHE_PRESENT == 0 */
+#define cacheBufferInvalidate(addr, size) { \
+ (void)(addr); \
+ (void)(size); \
+}
+#define cacheBufferFlush(addr, size) { \
+ (void)(addr); \
+ (void)(size); \
+}
+#endif
+
+#else /* !defined(__DCACHE_PRESENT) */
+#define CACHE_SIZE_ALIGN(t, n) (n)
+
+#define cacheBufferInvalidate(addr, size) { \
+ (void)(addr); \
+ (void)(size); \
+}
+#define cacheBufferFlush(addr, size) { \
+ (void)(addr); \
+ (void)(size); \
+}
+#endif
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CACHE_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/common/ARMCMx/mpu_v7m.h b/ChibiOS_20.3.2/os/hal/ports/common/ARMCMx/mpu_v7m.h
new file mode 100644
index 0000000..11e691a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/common/ARMCMx/mpu_v7m.h
@@ -0,0 +1,228 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file common/ARMCMx/mpu_v7m.h
+ * @brief ARMv7-M MPU support macros and structures.
+ *
+ * @addtogroup COMMON_ARMCMx_MPUv7M
+ * @{
+ */
+
+#ifndef MPUV7M_H
+#define MPUV7M_H
+
+/* Other layers may include another header named mpu.h which is perfectly
+ compatible, doing a check here to avoid name conflicts.*/
+#ifndef MPU_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name MPU registers definitions
+ * @{
+ */
+#define MPU_TYPE_SEPARATED (1U << 0U)
+#define MPU_TYPE_DREGION(n) (((n) >> 8U) & 255U)
+#define MPU_TYPE_IREGION(n) (((n) >> 16U) & 255U)
+
+#define MPU_CTRL_ENABLE (1U << 0U)
+#define MPU_CTRL_HFNMIENA (1U << 1U)
+#define MPU_CTRL_PRIVDEFENA (1U << 2U)
+
+#define MPU_RNR_REGION_MASK (255U << 0U)
+#define MPU_RNR_REGION(n) ((n) << 0U)
+
+#define MPU_RBAR_REGION_MASK (15U << 0U)
+#define MPU_RBAR_REGION(n) ((n) << 0U)
+#define MPU_RBAR_VALID (1U << 4U)
+#define MPU_RBAR_ADDR_MASK 0xFFFFFFE0U
+#define MPU_RBAR_ADDR(n) ((n) << 5U)
+
+#define MPU_RASR_ENABLE (1U << 0U)
+#define MPU_RASR_SIZE_MASK (31U << 1U)
+#define MPU_RASR_SIZE(n) ((n) << 1U)
+#define MPU_RASR_SIZE_32 MPU_RASR_SIZE(4U)
+#define MPU_RASR_SIZE_64 MPU_RASR_SIZE(5U)
+#define MPU_RASR_SIZE_128 MPU_RASR_SIZE(6U)
+#define MPU_RASR_SIZE_256 MPU_RASR_SIZE(7U)
+#define MPU_RASR_SIZE_512 MPU_RASR_SIZE(8U)
+#define MPU_RASR_SIZE_1K MPU_RASR_SIZE(9U)
+#define MPU_RASR_SIZE_2K MPU_RASR_SIZE(10U)
+#define MPU_RASR_SIZE_4K MPU_RASR_SIZE(11U)
+#define MPU_RASR_SIZE_8K MPU_RASR_SIZE(12U)
+#define MPU_RASR_SIZE_16K MPU_RASR_SIZE(13U)
+#define MPU_RASR_SIZE_32K MPU_RASR_SIZE(14U)
+#define MPU_RASR_SIZE_64K MPU_RASR_SIZE(15U)
+#define MPU_RASR_SIZE_128K MPU_RASR_SIZE(16U)
+#define MPU_RASR_SIZE_256K MPU_RASR_SIZE(17U)
+#define MPU_RASR_SIZE_512K MPU_RASR_SIZE(18U)
+#define MPU_RASR_SIZE_1M MPU_RASR_SIZE(19U)
+#define MPU_RASR_SIZE_2M MPU_RASR_SIZE(20U)
+#define MPU_RASR_SIZE_4M MPU_RASR_SIZE(21U)
+#define MPU_RASR_SIZE_8M MPU_RASR_SIZE(22U)
+#define MPU_RASR_SIZE_16M MPU_RASR_SIZE(23U)
+#define MPU_RASR_SIZE_32M MPU_RASR_SIZE(24U)
+#define MPU_RASR_SIZE_64M MPU_RASR_SIZE(25U)
+#define MPU_RASR_SIZE_128M MPU_RASR_SIZE(26U)
+#define MPU_RASR_SIZE_256M MPU_RASR_SIZE(27U)
+#define MPU_RASR_SIZE_512M MPU_RASR_SIZE(28U)
+#define MPU_RASR_SIZE_1G MPU_RASR_SIZE(29U)
+#define MPU_RASR_SIZE_2G MPU_RASR_SIZE(30U)
+#define MPU_RASR_SIZE_4G MPU_RASR_SIZE(31U)
+#define MPU_RASR_SRD_MASK (255U << 8U)
+#define MPU_RASR_SRD(n) ((n) << 8U)
+#define MPU_RASR_SRD_ALL (0U << 8U)
+#define MPU_RASR_SRD_DISABLE_SUB0 (1U << 8U)
+#define MPU_RASR_SRD_DISABLE_SUB1 (2U << 8U)
+#define MPU_RASR_SRD_DISABLE_SUB2 (4U << 8U)
+#define MPU_RASR_SRD_DISABLE_SUB3 (8U << 8U)
+#define MPU_RASR_SRD_DISABLE_SUB4 (16U << 8U)
+#define MPU_RASR_SRD_DISABLE_SUB5 (32U << 8U)
+#define MPU_RASR_SRD_DISABLE_SUB6 (64U << 8U)
+#define MPU_RASR_SRD_DISABLE_SUB7 (128U << 8U)
+#define MPU_RASR_ATTR_B (1U << 16U)
+#define MPU_RASR_ATTR_C (1U << 17U)
+#define MPU_RASR_ATTR_S (1U << 18U)
+#define MPU_RASR_ATTR_TEX_MASK (7U << 19U)
+#define MPU_RASR_ATTR_TEX(n) ((n) << 19U)
+#define MPU_RASR_ATTR_AP_MASK (7U << 24U)
+#define MPU_RASR_ATTR_AP(n) ((n) << 24U)
+#define MPU_RASR_ATTR_AP_NA_NA (0U << 24U)
+#define MPU_RASR_ATTR_AP_RW_NA (1U << 24U)
+#define MPU_RASR_ATTR_AP_RW_RO (2U << 24U)
+#define MPU_RASR_ATTR_AP_RW_RW (3U << 24U)
+#define MPU_RASR_ATTR_AP_RO_NA (5U << 24U)
+#define MPU_RASR_ATTR_AP_RO_RO (6U << 24U)
+#define MPU_RASR_ATTR_XN (1U << 28U)
+/** @} */
+
+/**
+ * @name Region attributes
+ * @{
+ */
+#define MPU_RASR_ATTR_STRONGLY_ORDERED (MPU_RASR_ATTR_TEX(0))
+#define MPU_RASR_ATTR_SHARED_DEVICE (MPU_RASR_ATTR_TEX(0) | MPU_RASR_ATTR_B)
+#define MPU_RASR_ATTR_CACHEABLE_WT_NWA (MPU_RASR_ATTR_TEX(0) | MPU_RASR_ATTR_C)
+#define MPU_RASR_ATTR_CACHEABLE_WB_NWA (MPU_RASR_ATTR_TEX(0) | MPU_RASR_ATTR_B | MPU_RASR_ATTR_C)
+#define MPU_RASR_ATTR_NON_CACHEABLE (MPU_RASR_ATTR_TEX(1))
+#define MPU_RASR_ATTR_CACHEABLE_WB_WA (MPU_RASR_ATTR_TEX(1) | MPU_RASR_ATTR_B | MPU_RASR_ATTR_C)
+#define MPU_RASR_ATTR_NON_SHARED_DEVICE (MPU_RASR_ATTR_TEX(2))
+/** @} */
+
+/**
+ * @name Region identifiers
+ * @{
+ */
+#define MPU_REGION_0 0U
+#define MPU_REGION_1 1U
+#define MPU_REGION_2 2U
+#define MPU_REGION_3 3U
+#define MPU_REGION_4 4U
+#define MPU_REGION_5 5U
+#define MPU_REGION_6 6U
+#define MPU_REGION_7 7U
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the MPU.
+ * @note MEMFAULENA is enabled in SCB_SHCSR.
+ *
+ * @param[in] ctrl MPU control modes as defined in @p MPU_CTRL register,
+ * the enable bit is enforced
+ *
+ * @api
+ */
+#define mpuEnable(ctrl) { \
+ MPU->CTRL = ((uint32_t)ctrl) | MPU_CTRL_ENABLE; \
+ SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; \
+}
+
+/**
+ * @brief Disables the MPU.
+ * @note MEMFAULENA is disabled in SCB_SHCSR.
+ *
+ * @api
+ */
+#define mpuDisable() { \
+ SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; \
+ MPU->CTRL = 0; \
+}
+
+/**
+ * @brief Configures an MPU region.
+ *
+ * @param[in] region the region number
+ * @param[in] address start address of the region, note, there are alignment
+ * constraints
+ * @param[in] attribs attributes mask as defined in @p MPU_RASR register
+ *
+ * @api
+ */
+#define mpuConfigureRegion(region, addr, attribs) { \
+ MPU->RNR = ((uint32_t)region); \
+ MPU->RBAR = ((uint32_t)addr); \
+ MPU->RASR = ((uint32_t)attribs); \
+}
+
+/**
+ * @brief Changes an MPU region base address.
+ *
+ * @param[in] region the region number
+ * @param[in] address start address of the region, note, there are alignment
+ * constraints
+ *
+ * @api
+ */
+#define mpuSetRegionAddress(region, addr) { \
+ MPU->RNR = ((uint32_t)region); \
+ MPU->RBAR = ((uint32_t)addr); \
+}
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MPU_H */
+
+#endif /* MPUV7M_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/common/ARMCMx/nvic.c b/ChibiOS_20.3.2/os/hal/ports/common/ARMCMx/nvic.c
new file mode 100644
index 0000000..b30c564
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/common/ARMCMx/nvic.c
@@ -0,0 +1,114 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file common/ARMCMx/nvic.c
+ * @brief Cortex-Mx NVIC support code.
+ *
+ * @addtogroup COMMON_ARMCMx_NVIC
+ * @{
+ */
+
+#include "hal.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Sets the priority of an interrupt handler and enables it.
+ *
+ * @param[in] n the interrupt number
+ * @param[in] prio the interrupt priority
+ */
+void nvicEnableVector(uint32_t n, uint32_t prio) {
+
+#if defined(__CORE_CM0_H_GENERIC) || defined(__CORE_CM0PLUS_H_GENERIC)
+ NVIC->IP[_IP_IDX(n)] = (NVIC->IP[_IP_IDX(n)] & ~(0xFFU << _BIT_SHIFT(n))) |
+ (NVIC_PRIORITY_MASK(prio) << _BIT_SHIFT(n));
+#else
+ NVIC->IP[n] = NVIC_PRIORITY_MASK(prio);
+#endif
+ NVIC->ICPR[n >> 5U] = 1U << (n & 0x1FU);
+ NVIC->ISER[n >> 5U] = 1U << (n & 0x1FU);
+}
+
+/**
+ * @brief Disables an interrupt handler.
+ *
+ * @param[in] n the interrupt number
+ */
+void nvicDisableVector(uint32_t n) {
+
+ NVIC->ICER[n >> 5U] = 1U << (n & 0x1FU);
+#if defined(__CORE_CM0_H_GENERIC) || defined(__CORE_CM0PLUS_H_GENERIC)
+ NVIC->IP[_IP_IDX(n)] = NVIC->IP[_IP_IDX(n)] & ~(0xFFU << _BIT_SHIFT(n));
+#else
+ NVIC->IP[n] = 0U;
+#endif
+}
+
+/**
+ * @brief Changes the priority of a system handler.
+ *
+ * @param[in] handler the system handler number
+ * @param[in] prio the system handler priority
+ */
+void nvicSetSystemHandlerPriority(uint32_t handler, uint32_t prio) {
+
+ osalDbgCheck(handler < 12U);
+
+#if defined(__CORE_CM0_H_GENERIC)
+ SCB->SHP[_SHP_IDX(handler)] = (SCB->SHP[_SHP_IDX(handler)] & ~(0xFFU << _BIT_SHIFT(handler))) |
+ (NVIC_PRIORITY_MASK(prio) << _BIT_SHIFT(handler));
+#elif defined(__CORE_CM7_H_GENERIC)
+ SCB->SHPR[handler] = NVIC_PRIORITY_MASK(prio);
+#else
+ SCB->SHP[handler] = NVIC_PRIORITY_MASK(prio);
+#endif
+}
+
+/**
+ * @brief Clears a pending interrupt source.
+ *
+ * @param[in] n the interrupt number
+ */
+void nvicClearPending(uint32_t n) {
+
+ NVIC->ICPR[n >> 5] = 1 << (n & 0x1F);
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/ports/common/ARMCMx/nvic.h b/ChibiOS_20.3.2/os/hal/ports/common/ARMCMx/nvic.h
new file mode 100644
index 0000000..88e32a3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/ports/common/ARMCMx/nvic.h
@@ -0,0 +1,88 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file common/ARMCMx/nvic.h
+ * @brief Cortex-Mx NVIC support macros and structures.
+ *
+ * @addtogroup COMMON_ARMCMx_NVIC
+ * @{
+ */
+
+#ifndef NVIC_H
+#define NVIC_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name System vectors numbers
+ * @{
+ */
+#define HANDLER_MEM_MANAGE 0 /**< MEM MANAGE vector id. */
+#define HANDLER_BUS_FAULT 1 /**< BUS FAULT vector id. */
+#define HANDLER_USAGE_FAULT 2 /**< USAGE FAULT vector id. */
+#define HANDLER_RESERVED_3 3
+#define HANDLER_RESERVED_4 4
+#define HANDLER_RESERVED_5 5
+#define HANDLER_RESERVED_6 6
+#define HANDLER_SVCALL 7 /**< SVCALL vector id. */
+#define HANDLER_DEBUG_MONITOR 8 /**< DEBUG MONITOR vector id. */
+#define HANDLER_RESERVED_9 9
+#define HANDLER_PENDSV 10 /**< PENDSV vector id. */
+#define HANDLER_SYSTICK 11 /**< SYS TCK vector id. */
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Priority level to priority mask conversion macro.
+ */
+#define NVIC_PRIORITY_MASK(prio) ((prio) << (8U - (unsigned)__NVIC_PRIO_BITS))
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void nvicEnableVector(uint32_t n, uint32_t prio);
+ void nvicDisableVector(uint32_t n);
+ void nvicSetSystemHandlerPriority(uint32_t handler, uint32_t prio);
+ void nvicClearPending(uint32_t n);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NVIC_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal.c b/ChibiOS_20.3.2/os/hal/src/hal.c
new file mode 100644
index 0000000..13d7771
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal.c
@@ -0,0 +1,157 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal.c
+ * @brief HAL subsystem code.
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#include "hal.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief HAL initialization.
+ * @details This function invokes the low level initialization code then
+ * initializes all the drivers enabled in the HAL. Finally the
+ * board-specific initialization is performed by invoking
+ * @p boardInit() (usually defined in @p board.c).
+ *
+ * @init
+ */
+void halInit(void) {
+
+ /* Initializes the OS Abstraction Layer.*/
+ osalInit();
+
+ /* Platform low level initializations.*/
+ hal_lld_init();
+
+#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__)
+#if defined(PAL_NEW_INIT)
+ palInit();
+#else
+ palInit(&pal_default_config);
+#endif
+#endif
+#if (HAL_USE_ADC == TRUE) || defined(__DOXYGEN__)
+ adcInit();
+#endif
+#if (HAL_USE_CAN == TRUE) || defined(__DOXYGEN__)
+ canInit();
+#endif
+#if (HAL_USE_CRY == TRUE) || defined(__DOXYGEN__)
+ cryInit();
+#endif
+#if (HAL_USE_DAC == TRUE) || defined(__DOXYGEN__)
+ dacInit();
+#endif
+#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__)
+ eflInit();
+#endif
+#if (HAL_USE_GPT == TRUE) || defined(__DOXYGEN__)
+ gptInit();
+#endif
+#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__)
+ i2cInit();
+#endif
+#if (HAL_USE_I2S == TRUE) || defined(__DOXYGEN__)
+ i2sInit();
+#endif
+#if (HAL_USE_ICU == TRUE) || defined(__DOXYGEN__)
+ icuInit();
+#endif
+#if (HAL_USE_MAC == TRUE) || defined(__DOXYGEN__)
+ macInit();
+#endif
+#if (HAL_USE_PWM == TRUE) || defined(__DOXYGEN__)
+ pwmInit();
+#endif
+#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__)
+ sdInit();
+#endif
+#if (HAL_USE_SDC == TRUE) || defined(__DOXYGEN__)
+ sdcInit();
+#endif
+#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__)
+ spiInit();
+#endif
+#if (HAL_USE_TRNG == TRUE) || defined(__DOXYGEN__)
+ trngInit();
+#endif
+#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__)
+ uartInit();
+#endif
+#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__)
+ usbInit();
+#endif
+#if (HAL_USE_MMC_SPI == TRUE) || defined(__DOXYGEN__)
+ mmcInit();
+#endif
+#if (HAL_USE_SERIAL_USB == TRUE) || defined(__DOXYGEN__)
+ sduInit();
+#endif
+#if (HAL_USE_RTC == TRUE) || defined(__DOXYGEN__)
+ rtcInit();
+#endif
+#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__)
+ wdgInit();
+#endif
+#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__)
+ wspiInit();
+#endif
+
+ /* Community driver overlay initialization.*/
+#if defined(HAL_USE_COMMUNITY) || defined(__DOXYGEN__)
+#if (HAL_USE_COMMUNITY == TRUE) || defined(__DOXYGEN__)
+ halCommunityInit();
+#endif
+#endif
+
+ /* Board specific initialization.*/
+ boardInit();
+
+/*
+ * The ST driver is a special case, it is only initialized if the OSAL is
+ * configured to require it.
+ */
+#if OSAL_ST_MODE != OSAL_ST_MODE_NONE
+ stInit();
+#endif
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_adc.c b/ChibiOS_20.3.2/os/hal/src/hal_adc.c
new file mode 100644
index 0000000..41234ef
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_adc.c
@@ -0,0 +1,324 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_adc.c
+ * @brief ADC Driver code.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_ADC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void adcInit(void) {
+
+ adc_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p ADCDriver structure.
+ *
+ * @param[out] adcp pointer to the @p ADCDriver object
+ *
+ * @init
+ */
+void adcObjectInit(ADCDriver *adcp) {
+
+ adcp->state = ADC_STOP;
+ adcp->config = NULL;
+ adcp->samples = NULL;
+ adcp->depth = 0;
+ adcp->grpp = NULL;
+#if ADC_USE_WAIT == TRUE
+ adcp->thread = NULL;
+#endif
+#if ADC_USE_MUTUAL_EXCLUSION == TRUE
+ osalMutexObjectInit(&adcp->mutex);
+#endif
+#if defined(ADC_DRIVER_EXT_INIT_HOOK)
+ ADC_DRIVER_EXT_INIT_HOOK(adcp);
+#endif
+}
+
+/**
+ * @brief Configures and activates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ * @param[in] config pointer to the @p ADCConfig object. Depending on
+ * the implementation the value can be @p NULL.
+ *
+ * @api
+ */
+void adcStart(ADCDriver *adcp, const ADCConfig *config) {
+
+ osalDbgCheck(adcp != NULL);
+
+ osalSysLock();
+ osalDbgAssert((adcp->state == ADC_STOP) || (adcp->state == ADC_READY),
+ "invalid state");
+ adcp->config = config;
+ adc_lld_start(adcp);
+ adcp->state = ADC_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @api
+ */
+void adcStop(ADCDriver *adcp) {
+
+ osalDbgCheck(adcp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((adcp->state == ADC_STOP) || (adcp->state == ADC_READY),
+ "invalid state");
+
+ adc_lld_stop(adcp);
+ adcp->config = NULL;
+ adcp->state = ADC_STOP;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Starts an ADC conversion.
+ * @details Starts an asynchronous conversion operation.
+ * @note The buffer is organized as a matrix of M*N elements where M is the
+ * channels number configured into the conversion group and N is the
+ * buffer depth. The samples are sequentially written into the buffer
+ * with no gaps.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ * @param[in] grpp pointer to a @p ADCConversionGroup object
+ * @param[out] samples pointer to the samples buffer
+ * @param[in] depth buffer depth (matrix rows number). The buffer depth
+ * must be one or an even number.
+ *
+ * @api
+ */
+void adcStartConversion(ADCDriver *adcp,
+ const ADCConversionGroup *grpp,
+ adcsample_t *samples,
+ size_t depth) {
+
+ osalSysLock();
+ adcStartConversionI(adcp, grpp, samples, depth);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Starts an ADC conversion.
+ * @details Starts an asynchronous conversion operation.
+ * @post The callbacks associated to the conversion group will be invoked
+ * on buffer fill and error events.
+ * @note The buffer is organized as a matrix of M*N elements where M is the
+ * channels number configured into the conversion group and N is the
+ * buffer depth. The samples are sequentially written into the buffer
+ * with no gaps.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ * @param[in] grpp pointer to a @p ADCConversionGroup object
+ * @param[out] samples pointer to the samples buffer
+ * @param[in] depth buffer depth (matrix rows number). The buffer depth
+ * must be one or an even number.
+ *
+ * @iclass
+ */
+void adcStartConversionI(ADCDriver *adcp,
+ const ADCConversionGroup *grpp,
+ adcsample_t *samples,
+ size_t depth) {
+
+ osalDbgCheckClassI();
+ osalDbgCheck((adcp != NULL) && (grpp != NULL) && (samples != NULL) &&
+ (depth > 0U) && ((depth == 1U) || ((depth & 1U) == 0U)));
+ osalDbgAssert((adcp->state == ADC_READY) ||
+ (adcp->state == ADC_ERROR),
+ "not ready");
+
+ adcp->samples = samples;
+ adcp->depth = depth;
+ adcp->grpp = grpp;
+ adcp->state = ADC_ACTIVE;
+ adc_lld_start_conversion(adcp);
+}
+
+/**
+ * @brief Stops an ongoing conversion.
+ * @details This function stops the currently ongoing conversion and returns
+ * the driver in the @p ADC_READY state. If there was no conversion
+ * being processed then the function does nothing.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @api
+ */
+void adcStopConversion(ADCDriver *adcp) {
+
+ osalDbgCheck(adcp != NULL);
+
+ osalSysLock();
+ osalDbgAssert((adcp->state == ADC_READY) || (adcp->state == ADC_ACTIVE),
+ "invalid state");
+ if (adcp->state != ADC_READY) {
+ adc_lld_stop_conversion(adcp);
+ adcp->grpp = NULL;
+ adcp->state = ADC_READY;
+ _adc_reset_s(adcp);
+ }
+ osalSysUnlock();
+}
+
+/**
+ * @brief Stops an ongoing conversion.
+ * @details This function stops the currently ongoing conversion and returns
+ * the driver in the @p ADC_READY state. If there was no conversion
+ * being processed then the function does nothing.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @iclass
+ */
+void adcStopConversionI(ADCDriver *adcp) {
+
+ osalDbgCheckClassI();
+ osalDbgCheck(adcp != NULL);
+ osalDbgAssert((adcp->state == ADC_READY) ||
+ (adcp->state == ADC_ACTIVE) ||
+ (adcp->state == ADC_COMPLETE),
+ "invalid state");
+
+ if (adcp->state != ADC_READY) {
+ adc_lld_stop_conversion(adcp);
+ adcp->grpp = NULL;
+ adcp->state = ADC_READY;
+ _adc_reset_i(adcp);
+ }
+}
+
+#if (ADC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Performs an ADC conversion.
+ * @details Performs a synchronous conversion operation.
+ * @note The buffer is organized as a matrix of M*N elements where M is the
+ * channels number configured into the conversion group and N is the
+ * buffer depth. The samples are sequentially written into the buffer
+ * with no gaps.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ * @param[in] grpp pointer to a @p ADCConversionGroup object
+ * @param[out] samples pointer to the samples buffer
+ * @param[in] depth buffer depth (matrix rows number). The buffer depth
+ * must be one or an even number.
+ * @return The operation result.
+ * @retval MSG_OK Conversion finished.
+ * @retval MSG_RESET The conversion has been stopped using
+ * @p acdStopConversion() or @p acdStopConversionI(),
+ * the result buffer may contain incorrect data.
+ * @retval MSG_TIMEOUT The conversion has been stopped because an hardware
+ * error.
+ *
+ * @api
+ */
+msg_t adcConvert(ADCDriver *adcp,
+ const ADCConversionGroup *grpp,
+ adcsample_t *samples,
+ size_t depth) {
+ msg_t msg;
+
+ osalSysLock();
+ osalDbgAssert(adcp->thread == NULL, "already waiting");
+ adcStartConversionI(adcp, grpp, samples, depth);
+ msg = osalThreadSuspendS(&adcp->thread);
+ osalSysUnlock();
+ return msg;
+}
+#endif /* ADC_USE_WAIT == TRUE */
+
+#if (ADC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Gains exclusive access to the ADC peripheral.
+ * @details This function tries to gain ownership to the ADC bus, if the bus
+ * is already being used then the invoking thread is queued.
+ * @pre In order to use this function the option
+ * @p ADC_USE_MUTUAL_EXCLUSION must be enabled.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @api
+ */
+void adcAcquireBus(ADCDriver *adcp) {
+
+ osalDbgCheck(adcp != NULL);
+
+ osalMutexLock(&adcp->mutex);
+}
+
+/**
+ * @brief Releases exclusive access to the ADC peripheral.
+ * @pre In order to use this function the option
+ * @p ADC_USE_MUTUAL_EXCLUSION must be enabled.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @api
+ */
+void adcReleaseBus(ADCDriver *adcp) {
+
+ osalDbgCheck(adcp != NULL);
+
+ osalMutexUnlock(&adcp->mutex);
+}
+#endif /* ADC_USE_MUTUAL_EXCLUSION == TRUE */
+
+#endif /* HAL_USE_ADC == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_buffers.c b/ChibiOS_20.3.2/os/hal/src/hal_buffers.c
new file mode 100644
index 0000000..1ca880f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_buffers.c
@@ -0,0 +1,847 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_buffers.c
+ * @brief I/O Buffers code.
+ *
+ * @addtogroup HAL_BUFFERS
+ * @details Buffers Queues are used when there is the need to exchange
+ * fixed-length data buffers between ISRs and threads.
+ * On the ISR side data can be exchanged only using buffers,
+ * on the thread side data can be exchanged both using buffers and/or
+ * using an emulation of regular byte queues.
+ * There are several kind of buffers queues:
+ * - Input queue, unidirectional queue where the writer is the
+ * ISR side and the reader is the thread side.
+ * - Output queue, unidirectional queue where the writer is the
+ * thread side and the reader is the ISR side.
+ * - Full duplex queue, bidirectional queue. Full duplex queues
+ * are implemented by pairing an input queue and an output queue
+ * together.
+ * .
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes an input buffers queue object.
+ *
+ * @param[out] ibqp pointer to the @p input_buffers_queue_t object
+ * @param[in] suspended initial state of the queue
+ * @param[in] bp pointer to a memory area allocated for buffers
+ * @param[in] size buffers size
+ * @param[in] n number of buffers
+ * @param[in] infy callback called when a buffer is returned to the queue
+ * @param[in] link application defined pointer
+ *
+ * @init
+ */
+void ibqObjectInit(input_buffers_queue_t *ibqp, bool suspended, uint8_t *bp,
+ size_t size, size_t n, bqnotify_t infy, void *link) {
+
+ osalDbgCheck((ibqp != NULL) && (bp != NULL) && (size >= 2U));
+
+ osalThreadQueueObjectInit(&ibqp->waiting);
+ ibqp->suspended = suspended;
+ ibqp->bcounter = 0;
+ ibqp->brdptr = bp;
+ ibqp->bwrptr = bp;
+ ibqp->btop = bp + ((size + sizeof (size_t)) * n);
+ ibqp->bsize = size + sizeof (size_t);
+ ibqp->bn = n;
+ ibqp->buffers = bp;
+ ibqp->ptr = NULL;
+ ibqp->top = NULL;
+ ibqp->notify = infy;
+ ibqp->link = link;
+}
+
+/**
+ * @brief Resets an input buffers queue.
+ * @details All the data in the input buffers queue is erased and lost, any
+ * waiting thread is resumed with status @p MSG_RESET.
+ * @note A reset operation can be used by a low level driver in order to
+ * obtain immediate attention from the high level layers.
+ *
+ * @param[in] ibqp pointer to the @p input_buffers_queue_t object
+ *
+ * @iclass
+ */
+void ibqResetI(input_buffers_queue_t *ibqp) {
+
+ osalDbgCheckClassI();
+
+ ibqp->bcounter = 0;
+ ibqp->brdptr = ibqp->buffers;
+ ibqp->bwrptr = ibqp->buffers;
+ ibqp->ptr = NULL;
+ ibqp->top = NULL;
+ osalThreadDequeueAllI(&ibqp->waiting, MSG_RESET);
+}
+
+/**
+ * @brief Gets the next empty buffer from the queue.
+ * @note The function always returns the same buffer if called repeatedly.
+ *
+ * @param[in] ibqp pointer to the @p input_buffers_queue_t object
+ * @return A pointer to the next buffer to be filled.
+ * @retval NULL if the queue is full.
+ *
+ * @iclass
+ */
+uint8_t *ibqGetEmptyBufferI(input_buffers_queue_t *ibqp) {
+
+ osalDbgCheckClassI();
+
+ if (ibqIsFullI(ibqp)) {
+ return NULL;
+ }
+
+ return ibqp->bwrptr + sizeof (size_t);
+}
+
+/**
+ * @brief Posts a new filled buffer to the queue.
+ *
+ * @param[in] ibqp pointer to the @p input_buffers_queue_t object
+ * @param[in] size used size of the buffer, cannot be zero
+ *
+ * @iclass
+ */
+void ibqPostFullBufferI(input_buffers_queue_t *ibqp, size_t size) {
+
+ osalDbgCheckClassI();
+
+ osalDbgCheck((size > 0U) && (size <= (ibqp->bsize - sizeof (size_t))));
+ osalDbgAssert(!ibqIsFullI(ibqp), "buffers queue full");
+
+ /* Writing size field in the buffer.*/
+ *((size_t *)ibqp->bwrptr) = size;
+
+ /* Posting the buffer in the queue.*/
+ ibqp->bcounter++;
+ ibqp->bwrptr += ibqp->bsize;
+ if (ibqp->bwrptr >= ibqp->btop) {
+ ibqp->bwrptr = ibqp->buffers;
+ }
+
+ /* Waking up one waiting thread, if any.*/
+ osalThreadDequeueNextI(&ibqp->waiting, MSG_OK);
+}
+
+/**
+ * @brief Gets the next filled buffer from the queue.
+ * @note The function always acquires the same buffer if called repeatedly.
+ * @post After calling the function the fields @p ptr and @p top are set
+ * at beginning and end of the buffer data or @p NULL if the queue
+ * is empty.
+ *
+ * @param[in] ibqp pointer to the @p input_buffers_queue_t object
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if a buffer has been acquired.
+ * @retval MSG_TIMEOUT if the specified time expired.
+ * @retval MSG_RESET if the queue has been reset or has been put in
+ * suspended state.
+ *
+ * @api
+ */
+msg_t ibqGetFullBufferTimeout(input_buffers_queue_t *ibqp,
+ sysinterval_t timeout) {
+ msg_t msg;
+
+ osalSysLock();
+ msg = ibqGetFullBufferTimeoutS(ibqp, timeout);
+ osalSysUnlock();
+
+ return msg;
+}
+
+ /**
+ * @brief Gets the next filled buffer from the queue.
+ * @note The function always acquires the same buffer if called repeatedly.
+ * @post After calling the function the fields @p ptr and @p top are set
+ * at beginning and end of the buffer data or @p NULL if the queue
+ * is empty.
+ *
+ * @param[in] ibqp pointer to the @p input_buffers_queue_t object
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if a buffer has been acquired.
+ * @retval MSG_TIMEOUT if the specified time expired.
+ * @retval MSG_RESET if the queue has been reset or has been put in
+ * suspended state.
+ *
+ * @sclass
+ */
+ msg_t ibqGetFullBufferTimeoutS(input_buffers_queue_t *ibqp,
+ sysinterval_t timeout) {
+
+ osalDbgCheckClassS();
+
+ while (ibqIsEmptyI(ibqp)) {
+ if (ibqp->suspended) {
+ return MSG_RESET;
+ }
+ msg_t msg = osalThreadEnqueueTimeoutS(&ibqp->waiting, timeout);
+ if (msg < MSG_OK) {
+ return msg;
+ }
+ }
+
+ osalDbgAssert(!ibqIsEmptyI(ibqp), "still empty");
+
+ /* Setting up the "current" buffer and its boundary.*/
+ ibqp->ptr = ibqp->brdptr + sizeof (size_t);
+ ibqp->top = ibqp->ptr + *((size_t *)ibqp->brdptr);
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Releases the buffer back in the queue.
+ * @note The object callback is called after releasing the buffer.
+ *
+ * @param[in] ibqp pointer to the @p input_buffers_queue_t object
+ *
+ * @api
+ */
+void ibqReleaseEmptyBuffer(input_buffers_queue_t *ibqp) {
+
+ osalSysLock();
+ ibqReleaseEmptyBufferS(ibqp);
+ osalSysUnlock();
+}
+
+ /**
+ * @brief Releases the buffer back in the queue.
+ * @note The object callback is called after releasing the buffer.
+ *
+ * @param[in] ibqp pointer to the @p input_buffers_queue_t object
+ *
+ * @sclass
+ */
+ void ibqReleaseEmptyBufferS(input_buffers_queue_t *ibqp) {
+
+ osalDbgCheckClassS();
+ osalDbgAssert(!ibqIsEmptyI(ibqp), "buffers queue empty");
+
+ /* Freeing a buffer slot in the queue.*/
+ ibqp->bcounter--;
+ ibqp->brdptr += ibqp->bsize;
+ if (ibqp->brdptr >= ibqp->btop) {
+ ibqp->brdptr = ibqp->buffers;
+ }
+
+ /* No "current" buffer.*/
+ ibqp->ptr = NULL;
+
+ /* Notifying the buffer release.*/
+ if (ibqp->notify != NULL) {
+ ibqp->notify(ibqp);
+ }
+}
+
+/**
+ * @brief Input queue read with timeout.
+ * @details This function reads a byte value from an input queue. If
+ * the queue is empty then the calling thread is suspended until a
+ * new buffer arrives in the queue or a timeout occurs.
+ *
+ * @param[in] ibqp pointer to the @p input_buffers_queue_t object
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A byte value from the queue.
+ * @retval MSG_TIMEOUT if the specified time expired.
+ * @retval MSG_RESET if the queue has been reset or has been put in
+ * suspended state.
+ *
+ * @api
+ */
+msg_t ibqGetTimeout(input_buffers_queue_t *ibqp, sysinterval_t timeout) {
+ msg_t msg;
+
+ osalSysLock();
+
+ /* This condition indicates that a new buffer must be acquired.*/
+ if (ibqp->ptr == NULL) {
+ msg = ibqGetFullBufferTimeoutS(ibqp, timeout);
+ if (msg != MSG_OK) {
+ osalSysUnlock();
+ return msg;
+ }
+ }
+
+ /* Next byte from the buffer.*/
+ msg = (msg_t)*ibqp->ptr;
+ ibqp->ptr++;
+
+ /* If the current buffer has been fully read then it is returned as
+ empty in the queue.*/
+ if (ibqp->ptr >= ibqp->top) {
+ ibqReleaseEmptyBufferS(ibqp);
+ }
+
+ osalSysUnlock();
+ return msg;
+}
+
+/**
+ * @brief Input queue read with timeout.
+ * @details The function reads data from an input queue into a buffer.
+ * The operation completes when the specified amount of data has been
+ * transferred or after the specified timeout or if the queue has
+ * been reset.
+ *
+ * @param[in] ibqp pointer to the @p input_buffers_queue_t object
+ * @param[out] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred, the
+ * value 0 is reserved
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The number of bytes effectively transferred.
+ * @retval 0 if a timeout occurred.
+ *
+ * @api
+ */
+size_t ibqReadTimeout(input_buffers_queue_t *ibqp, uint8_t *bp,
+ size_t n, sysinterval_t timeout) {
+ size_t r = 0;
+
+ osalDbgCheck(n > 0U);
+
+ osalSysLock();
+
+ while (true) {
+ size_t size;
+
+ /* This condition indicates that a new buffer must be acquired.*/
+ if (ibqp->ptr == NULL) {
+ msg_t msg;
+
+ /* Getting a data buffer using the specified timeout.*/
+ msg = ibqGetFullBufferTimeoutS(ibqp, timeout);
+
+ /* Anything except MSG_OK interrupts the operation.*/
+ if (msg != MSG_OK) {
+ osalSysUnlock();
+ return r;
+ }
+ }
+
+ /* Size of the data chunk present in the current buffer.*/
+ size = (size_t)ibqp->top - (size_t)ibqp->ptr;
+ if (size > (n - r)) {
+ size = n - r;
+ }
+
+ /* Smaller chunks in order to not make the critical zone too long,
+ this impacts throughput however.*/
+ if (size > (size_t)BUFFERS_CHUNKS_SIZE) {
+ /* Giving the compiler a chance to optimize for a fixed size move.*/
+ memcpy(bp, ibqp->ptr, BUFFERS_CHUNKS_SIZE);
+ bp += (size_t)BUFFERS_CHUNKS_SIZE;
+ ibqp->ptr += (size_t)BUFFERS_CHUNKS_SIZE;
+ r += (size_t)BUFFERS_CHUNKS_SIZE;
+ }
+ else {
+ memcpy(bp, ibqp->ptr, size);
+ bp += size;
+ ibqp->ptr += size;
+ r += size;
+ }
+
+ /* Has the current data buffer been finished? if so then release it.*/
+ if (ibqp->ptr >= ibqp->top) {
+ ibqReleaseEmptyBufferS(ibqp);
+ }
+
+ /* Giving a preemption chance.*/
+ osalSysUnlock();
+ if (r >= n) {
+ return r;
+ }
+ osalSysLock();
+ }
+}
+
+/**
+ * @brief Initializes an output buffers queue object.
+ *
+ * @param[out] obqp pointer to the @p output_buffers_queue_t object
+ * @param[in] suspended initial state of the queue
+ * @param[in] bp pointer to a memory area allocated for buffers
+ * @param[in] size buffers size
+ * @param[in] n number of buffers
+ * @param[in] onfy callback called when a buffer is posted in the queue
+ * @param[in] link application defined pointer
+ *
+ * @init
+ */
+void obqObjectInit(output_buffers_queue_t *obqp, bool suspended, uint8_t *bp,
+ size_t size, size_t n, bqnotify_t onfy, void *link) {
+
+ osalDbgCheck((obqp != NULL) && (bp != NULL) && (size >= 2U));
+
+ osalThreadQueueObjectInit(&obqp->waiting);
+ obqp->suspended = suspended;
+ obqp->bcounter = n;
+ obqp->brdptr = bp;
+ obqp->bwrptr = bp;
+ obqp->btop = bp + ((size + sizeof (size_t)) * n);
+ obqp->bsize = size + sizeof (size_t);
+ obqp->bn = n;
+ obqp->buffers = bp;
+ obqp->ptr = NULL;
+ obqp->top = NULL;
+ obqp->notify = onfy;
+ obqp->link = link;
+}
+
+/**
+ * @brief Resets an output buffers queue.
+ * @details All the data in the output buffers queue is erased and lost, any
+ * waiting thread is resumed with status @p MSG_RESET.
+ * @note A reset operation can be used by a low level driver in order to
+ * obtain immediate attention from the high level layers.
+ *
+ * @param[in] obqp pointer to the @p output_buffers_queue_t object
+ *
+ * @iclass
+ */
+void obqResetI(output_buffers_queue_t *obqp) {
+
+ osalDbgCheckClassI();
+
+ obqp->bcounter = bqSizeX(obqp);
+ obqp->brdptr = obqp->buffers;
+ obqp->bwrptr = obqp->buffers;
+ obqp->ptr = NULL;
+ obqp->top = NULL;
+ osalThreadDequeueAllI(&obqp->waiting, MSG_RESET);
+}
+
+/**
+ * @brief Gets the next filled buffer from the queue.
+ * @note The function always returns the same buffer if called repeatedly.
+ *
+ * @param[in] obqp pointer to the @p output_buffers_queue_t object
+ * @param[out] sizep pointer to the filled buffer size
+ * @return A pointer to the filled buffer.
+ * @retval NULL if the queue is empty.
+ *
+ * @iclass
+ */
+uint8_t *obqGetFullBufferI(output_buffers_queue_t *obqp,
+ size_t *sizep) {
+
+ osalDbgCheckClassI();
+
+ if (obqIsEmptyI(obqp)) {
+ return NULL;
+ }
+
+ /* Buffer size.*/
+ *sizep = *((size_t *)obqp->brdptr);
+
+ return obqp->brdptr + sizeof (size_t);
+}
+
+/**
+ * @brief Releases the next filled buffer back in the queue.
+ *
+ * @param[in] obqp pointer to the @p output_buffers_queue_t object
+ *
+ * @iclass
+ */
+void obqReleaseEmptyBufferI(output_buffers_queue_t *obqp) {
+
+ osalDbgCheckClassI();
+ osalDbgAssert(!obqIsEmptyI(obqp), "buffers queue empty");
+
+ /* Freeing a buffer slot in the queue.*/
+ obqp->bcounter++;
+ obqp->brdptr += obqp->bsize;
+ if (obqp->brdptr >= obqp->btop) {
+ obqp->brdptr = obqp->buffers;
+ }
+
+ /* Waking up one waiting thread, if any.*/
+ osalThreadDequeueNextI(&obqp->waiting, MSG_OK);
+}
+
+/**
+ * @brief Gets the next empty buffer from the queue.
+ * @note The function always acquires the same buffer if called repeatedly.
+ * @post After calling the function the fields @p ptr and @p top are set
+ * at beginning and end of the buffer data or @p NULL if the queue
+ * is empty.
+ *
+ * @param[in] obqp pointer to the @p output_buffers_queue_t object
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if a buffer has been acquired.
+ * @retval MSG_TIMEOUT if the specified time expired.
+ * @retval MSG_RESET if the queue has been reset or has been put in
+ * suspended state.
+ *
+ * @api
+ */
+msg_t obqGetEmptyBufferTimeout(output_buffers_queue_t *obqp,
+ sysinterval_t timeout) {
+ msg_t msg;
+
+ osalSysLock();
+ msg = obqGetEmptyBufferTimeoutS(obqp, timeout);
+ osalSysUnlock();
+
+ return msg;
+}
+
+/**
+ * @brief Gets the next empty buffer from the queue.
+ * @note The function always acquires the same buffer if called repeatedly.
+ * @post After calling the function the fields @p ptr and @p top are set
+ * at beginning and end of the buffer data or @p NULL if the queue
+ * is empty.
+ *
+ * @param[in] obqp pointer to the @p output_buffers_queue_t object
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if a buffer has been acquired.
+ * @retval MSG_TIMEOUT if the specified time expired.
+ * @retval MSG_RESET if the queue has been reset or has been put in
+ * suspended state.
+ *
+ * @sclass
+ */
+msg_t obqGetEmptyBufferTimeoutS(output_buffers_queue_t *obqp,
+ sysinterval_t timeout) {
+
+ osalDbgCheckClassS();
+
+ while (obqIsFullI(obqp)) {
+ if (obqp->suspended) {
+ return MSG_RESET;
+ }
+ msg_t msg = osalThreadEnqueueTimeoutS(&obqp->waiting, timeout);
+ if (msg < MSG_OK) {
+ return msg;
+ }
+ }
+
+ osalDbgAssert(!obqIsFullI(obqp), "still full");
+
+ /* Setting up the "current" buffer and its boundary.*/
+ obqp->ptr = obqp->bwrptr + sizeof (size_t);
+ obqp->top = obqp->bwrptr + obqp->bsize;
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Posts a new filled buffer to the queue.
+ * @note The object callback is called after releasing the buffer.
+ *
+ * @param[in] obqp pointer to the @p output_buffers_queue_t object
+ * @param[in] size used size of the buffer, cannot be zero
+ *
+ * @api
+ */
+void obqPostFullBuffer(output_buffers_queue_t *obqp, size_t size) {
+
+ osalSysLock();
+ obqPostFullBufferS(obqp, size);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Posts a new filled buffer to the queue.
+ * @note The object callback is called after releasing the buffer.
+ *
+ * @param[in] obqp pointer to the @p output_buffers_queue_t object
+ * @param[in] size used size of the buffer, cannot be zero
+ *
+ * @sclass
+ */
+void obqPostFullBufferS(output_buffers_queue_t *obqp, size_t size) {
+
+ osalDbgCheckClassS();
+ osalDbgCheck((size > 0U) && (size <= (obqp->bsize - sizeof (size_t))));
+ osalDbgAssert(!obqIsFullI(obqp), "buffers queue full");
+
+ /* Writing size field in the buffer.*/
+ *((size_t *)obqp->bwrptr) = size;
+
+ /* Posting the buffer in the queue.*/
+ obqp->bcounter--;
+ obqp->bwrptr += obqp->bsize;
+ if (obqp->bwrptr >= obqp->btop) {
+ obqp->bwrptr = obqp->buffers;
+ }
+
+ /* No "current" buffer.*/
+ obqp->ptr = NULL;
+
+ /* Notifying the buffer release.*/
+ if (obqp->notify != NULL) {
+ obqp->notify(obqp);
+ }
+}
+
+/**
+ * @brief Output queue write with timeout.
+ * @details This function writes a byte value to an output queue. If
+ * the queue is full then the calling thread is suspended until a
+ * new buffer is freed in the queue or a timeout occurs.
+ *
+ * @param[in] obqp pointer to the @p output_buffers_queue_t object
+ * @param[in] b byte value to be transferred
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A byte value from the queue.
+ * @retval MSG_TIMEOUT if the specified time expired.
+ * @retval MSG_RESET if the queue has been reset or has been put in
+ * suspended state.
+ *
+ * @api
+ */
+msg_t obqPutTimeout(output_buffers_queue_t *obqp, uint8_t b,
+ sysinterval_t timeout) {
+ msg_t msg;
+
+ osalSysLock();
+
+ /* This condition indicates that a new buffer must be acquired.*/
+ if (obqp->ptr == NULL) {
+ msg = obqGetEmptyBufferTimeoutS(obqp, timeout);
+ if (msg != MSG_OK) {
+ osalSysUnlock();
+ return msg;
+ }
+ }
+
+ /* Writing the byte to the buffer.*/
+ *obqp->ptr = b;
+ obqp->ptr++;
+
+ /* If the current buffer has been fully written then it is posted as
+ full in the queue.*/
+ if (obqp->ptr >= obqp->top) {
+ obqPostFullBufferS(obqp, obqp->bsize - sizeof (size_t));
+ }
+
+ osalSysUnlock();
+ return MSG_OK;
+}
+
+/**
+ * @brief Output queue write with timeout.
+ * @details The function writes data from a buffer to an output queue. The
+ * operation completes when the specified amount of data has been
+ * transferred or after the specified timeout or if the queue has
+ * been reset.
+ *
+ * @param[in] obqp pointer to the @p output_buffers_queue_t object
+ * @param[in] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred, the
+ * value 0 is reserved
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The number of bytes effectively transferred.
+ * @retval 0 if a timeout occurred.
+ *
+ * @api
+ */
+size_t obqWriteTimeout(output_buffers_queue_t *obqp, const uint8_t *bp,
+ size_t n, sysinterval_t timeout) {
+ size_t w = 0;
+
+ osalDbgCheck(n > 0U);
+
+ osalSysLock();
+
+ while (true) {
+ size_t size;
+
+ /* This condition indicates that a new buffer must be acquired.*/
+ if (obqp->ptr == NULL) {
+ msg_t msg;
+
+ /* Getting an empty buffer using the specified timeout.*/
+ msg = obqGetEmptyBufferTimeoutS(obqp, timeout);
+
+ /* Anything except MSG_OK interrupts the operation.*/
+ if (msg != MSG_OK) {
+ osalSysUnlock();
+ return w;
+ }
+ }
+
+ /* Size of the space available in the current buffer.*/
+ size = (size_t)obqp->top - (size_t)obqp->ptr;
+ if (size > (n - w)) {
+ size = n - w;
+ }
+
+ /* Smaller chunks in order to not make the critical zone too long,
+ this impacts throughput however.*/
+ if (size > (size_t)BUFFERS_CHUNKS_SIZE) {
+ /* Giving the compiler a chance to optimize for a fixed size move.*/
+ memcpy(obqp->ptr, bp, (size_t)BUFFERS_CHUNKS_SIZE);
+ bp += (size_t)BUFFERS_CHUNKS_SIZE;
+ obqp->ptr += (size_t)BUFFERS_CHUNKS_SIZE;
+ w += (size_t)BUFFERS_CHUNKS_SIZE;
+ }
+ else {
+ memcpy(obqp->ptr, bp, size);
+ bp += size;
+ obqp->ptr += size;
+ w += size;
+ }
+
+ /* Has the current data buffer been finished? if so then release it.*/
+ if (obqp->ptr >= obqp->top) {
+ obqPostFullBufferS(obqp, obqp->bsize - sizeof (size_t));
+ }
+
+ /* Giving a preemption chance.*/
+ osalSysUnlock();
+ if (w >= n) {
+ return w;
+ }
+ osalSysLock();
+ }
+}
+
+/**
+ * @brief Flushes the current, partially filled, buffer to the queue.
+ * @note The notification callback is not invoked because the function
+ * is meant to be called from ISR context. An operation status is
+ * returned instead.
+ *
+ * @param[in] obqp pointer to the @p output_buffers_queue_t object
+ * @return The operation status.
+ * @retval false if no new filled buffer has been posted to the queue.
+ * @retval true if a new filled buffer has been posted to the queue.
+ *
+ * @iclass
+ */
+bool obqTryFlushI(output_buffers_queue_t *obqp) {
+
+ osalDbgCheckClassI();
+
+ /* If queue is empty and there is a buffer partially filled and
+ it is not being written.*/
+ if (obqIsEmptyI(obqp) && (obqp->ptr != NULL)) {
+ size_t size = (size_t)obqp->ptr - ((size_t)obqp->bwrptr + sizeof (size_t));
+
+ if (size > 0U) {
+
+ /* Writing size field in the buffer.*/
+ *((size_t *)obqp->bwrptr) = size;
+
+ /* Posting the buffer in the queue.*/
+ obqp->bcounter--;
+ obqp->bwrptr += obqp->bsize;
+ if (obqp->bwrptr >= obqp->btop) {
+ obqp->bwrptr = obqp->buffers;
+ }
+
+ /* No "current" buffer.*/
+ obqp->ptr = NULL;
+
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * @brief Flushes the current, partially filled, buffer to the queue.
+ *
+ * @param[in] obqp pointer to the @p output_buffers_queue_t object
+ *
+ * @api
+ */
+void obqFlush(output_buffers_queue_t *obqp) {
+
+ osalSysLock();
+
+ /* If there is a buffer partially filled and not being written.*/
+ if (obqp->ptr != NULL) {
+ size_t size = ((size_t)obqp->ptr - (size_t)obqp->bwrptr) - sizeof (size_t);
+
+ if (size > 0U) {
+ obqPostFullBufferS(obqp, size);
+ }
+ }
+
+ osalSysUnlock();
+}
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_can.c b/ChibiOS_20.3.2/os/hal/src/hal_can.c
new file mode 100644
index 0000000..f715981
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_can.c
@@ -0,0 +1,394 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_can.c
+ * @brief CAN Driver code.
+ *
+ * @addtogroup CAN
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_CAN == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief CAN Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void canInit(void) {
+
+ can_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p CANDriver structure.
+ *
+ * @param[out] canp pointer to the @p CANDriver object
+ *
+ * @init
+ */
+void canObjectInit(CANDriver *canp) {
+
+ canp->state = CAN_STOP;
+ canp->config = NULL;
+ osalThreadQueueObjectInit(&canp->txqueue);
+ osalThreadQueueObjectInit(&canp->rxqueue);
+#if CAN_ENFORCE_USE_CALLBACKS == FALSE
+ osalEventObjectInit(&canp->rxfull_event);
+ osalEventObjectInit(&canp->txempty_event);
+ osalEventObjectInit(&canp->error_event);
+#if CAN_USE_SLEEP_MODE == TRUE
+ osalEventObjectInit(&canp->sleep_event);
+ osalEventObjectInit(&canp->wakeup_event);
+#endif
+#else /* CAN_ENFORCE_USE_CALLBACKS == TRUE */
+ canp->rxfull_cb = NULL;
+ canp->txempty_cb = NULL;
+ canp->error_cb = NULL;
+#if CAN_USE_SLEEP_MODE == TRUE
+ canp->wakeup_cb = NULL;
+#endif
+#endif /* CAN_ENFORCE_USE_CALLBACKS == TRUE */
+}
+
+/**
+ * @brief Configures and activates the CAN peripheral.
+ * @note Activating the CAN bus can be a slow operation.
+ * @note Unlike other drivers it is not possible to restart the CAN
+ * driver without first stopping it using canStop().
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] config pointer to the @p CANConfig object. Depending on
+ * the implementation the value can be @p NULL.
+ *
+ * @api
+ */
+void canStart(CANDriver *canp, const CANConfig *config) {
+
+ osalDbgCheck(canp != NULL);
+
+ osalSysLock();
+ osalDbgAssert(canp->state == CAN_STOP, "invalid state");
+
+ /* Entering initialization mode. */
+ canp->state = CAN_STARTING;
+ canp->config = config;
+
+ /* Low level initialization, could be a slow process and sleeps could
+ be performed inside.*/
+ can_lld_start(canp);
+
+ /* The driver finally goes into the ready state.*/
+ canp->state = CAN_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the CAN peripheral.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @api
+ */
+void canStop(CANDriver *canp) {
+
+ osalDbgCheck(canp != NULL);
+
+ osalSysLock();
+ osalDbgAssert((canp->state == CAN_STOP) || (canp->state == CAN_READY),
+ "invalid state");
+
+ /* The low level driver is stopped.*/
+ canp->state = CAN_STOPPING;
+ can_lld_stop(canp);
+ canp->config = NULL;
+ canp->state = CAN_STOP;
+
+ /* Threads waiting on CAN APIs are notified that the driver has been
+ stopped in order to not have stuck threads.*/
+ osalThreadDequeueAllI(&canp->rxqueue, MSG_RESET);
+ osalThreadDequeueAllI(&canp->txqueue, MSG_RESET);
+ osalOsRescheduleS();
+ osalSysUnlock();
+}
+
+/**
+ * @brief Can frame transmission attempt.
+ * @details The specified frame is queued for transmission, if the hardware
+ * queue is full then the function fails.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
+ * @param[in] ctfp pointer to the CAN frame to be transmitted
+ * @return The operation result.
+ * @retval false Frame transmitted.
+ * @retval true Mailbox full.
+ *
+ * @iclass
+ */
+bool canTryTransmitI(CANDriver *canp,
+ canmbx_t mailbox,
+ const CANTxFrame *ctfp) {
+
+ osalDbgCheckClassI();
+ osalDbgCheck((canp != NULL) && (ctfp != NULL) &&
+ (mailbox <= (canmbx_t)CAN_TX_MAILBOXES));
+ osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP),
+ "invalid state");
+
+ /* If the RX mailbox is full then the function fails.*/
+ if (!can_lld_is_tx_empty(canp, mailbox)) {
+ return true;
+ }
+
+ /* Transmitting frame.*/
+ can_lld_transmit(canp, mailbox, ctfp);
+
+ return false;
+}
+
+/**
+ * @brief Can frame receive attempt.
+ * @details The function tries to fetch a frame from a mailbox.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
+ * @param[out] crfp pointer to the buffer where the CAN frame is copied
+ * @return The operation result.
+ * @retval false Frame fetched.
+ * @retval true Mailbox empty.
+ *
+ * @iclass
+ */
+bool canTryReceiveI(CANDriver *canp,
+ canmbx_t mailbox,
+ CANRxFrame *crfp) {
+
+ osalDbgCheckClassI();
+ osalDbgCheck((canp != NULL) && (crfp != NULL) &&
+ (mailbox <= (canmbx_t)CAN_RX_MAILBOXES));
+ osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP),
+ "invalid state");
+
+ /* If the RX mailbox is empty then the function fails.*/
+ if (!can_lld_is_rx_nonempty(canp, mailbox)) {
+ return true;
+ }
+
+ /* Fetching the frame.*/
+ can_lld_receive(canp, mailbox, crfp);
+
+ return false;
+}
+
+/**
+ * @brief Tries to abort an ongoing transmission.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] mailbox mailbox number
+ *
+ * @xclass
+ */
+void canTryAbortX(CANDriver *canp,
+ canmbx_t mailbox) {
+
+ osalDbgCheck((canp != NULL) &&
+ (mailbox != CAN_ANY_MAILBOX) &&
+ (mailbox <= (canmbx_t)CAN_TX_MAILBOXES));
+
+ can_lld_abort(canp, mailbox);
+}
+
+/**
+ * @brief Can frame transmission.
+ * @details The specified frame is queued for transmission, if the hardware
+ * queue is full then the invoking thread is queued.
+ * @note Trying to transmit while in sleep mode simply enqueues the thread.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
+ * @param[in] ctfp pointer to the CAN frame to be transmitted
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation result.
+ * @retval MSG_OK the frame has been queued for transmission.
+ * @retval MSG_TIMEOUT The operation has timed out.
+ * @retval MSG_RESET The driver has been stopped while waiting.
+ *
+ * @api
+ */
+msg_t canTransmitTimeout(CANDriver *canp,
+ canmbx_t mailbox,
+ const CANTxFrame *ctfp,
+ sysinterval_t timeout) {
+
+ osalDbgCheck((canp != NULL) && (ctfp != NULL) &&
+ (mailbox <= (canmbx_t)CAN_TX_MAILBOXES));
+
+ osalSysLock();
+ osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP),
+ "invalid state");
+
+ /*lint -save -e9007 [13.5] Right side is supposed to be pure.*/
+ while ((canp->state == CAN_SLEEP) || !can_lld_is_tx_empty(canp, mailbox)) {
+ /*lint -restore*/
+ msg_t msg = osalThreadEnqueueTimeoutS(&canp->txqueue, timeout);
+ if (msg != MSG_OK) {
+ osalSysUnlock();
+ return msg;
+ }
+ }
+ can_lld_transmit(canp, mailbox, ctfp);
+ osalSysUnlock();
+ return MSG_OK;
+}
+
+/**
+ * @brief Can frame receive.
+ * @details The function waits until a frame is received.
+ * @note Trying to receive while in sleep mode simply enqueues the thread.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
+ * @param[out] crfp pointer to the buffer where the CAN frame is copied
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout (useful in an
+ * event driven scenario where a thread never blocks
+ * for I/O).
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation result.
+ * @retval MSG_OK a frame has been received and placed in the buffer.
+ * @retval MSG_TIMEOUT The operation has timed out.
+ * @retval MSG_RESET The driver has been stopped while waiting.
+ *
+ * @api
+ */
+msg_t canReceiveTimeout(CANDriver *canp,
+ canmbx_t mailbox,
+ CANRxFrame *crfp,
+ sysinterval_t timeout) {
+
+ osalDbgCheck((canp != NULL) && (crfp != NULL) &&
+ (mailbox <= (canmbx_t)CAN_RX_MAILBOXES));
+
+ osalSysLock();
+ osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP),
+ "invalid state");
+
+ /*lint -save -e9007 [13.5] Right side is supposed to be pure.*/
+ while ((canp->state == CAN_SLEEP) || !can_lld_is_rx_nonempty(canp, mailbox)) {
+ /*lint -restore*/
+ msg_t msg = osalThreadEnqueueTimeoutS(&canp->rxqueue, timeout);
+ if (msg != MSG_OK) {
+ osalSysUnlock();
+ return msg;
+ }
+ }
+ can_lld_receive(canp, mailbox, crfp);
+ osalSysUnlock();
+ return MSG_OK;
+}
+
+#if (CAN_USE_SLEEP_MODE == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Enters the sleep mode.
+ * @details This function puts the CAN driver in sleep mode and broadcasts
+ * the @p sleep_event event source.
+ * @pre In order to use this function the option @p CAN_USE_SLEEP_MODE must
+ * be enabled and the @p CAN_SUPPORTS_SLEEP mode must be supported
+ * by the low level driver.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @api
+ */
+void canSleep(CANDriver *canp) {
+
+ osalDbgCheck(canp != NULL);
+
+ osalSysLock();
+ osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP),
+ "invalid state");
+ if (canp->state == CAN_READY) {
+ can_lld_sleep(canp);
+ canp->state = CAN_SLEEP;
+#if CAN_ENFORCE_USE_CALLBACKS == FALSE
+ osalEventBroadcastFlagsI(&canp->sleep_event, (eventflags_t)0);
+ osalOsRescheduleS();
+#endif
+ }
+ osalSysUnlock();
+}
+
+/**
+ * @brief Enforces leaving the sleep mode.
+ * @note The sleep mode is supposed to be usually exited automatically by
+ * an hardware event.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ */
+void canWakeup(CANDriver *canp) {
+
+ osalDbgCheck(canp != NULL);
+
+ osalSysLock();
+ osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP),
+ "invalid state");
+ if (canp->state == CAN_SLEEP) {
+ can_lld_wakeup(canp);
+ canp->state = CAN_READY;
+#if CAN_ENFORCE_USE_CALLBACKS == FALSE
+ osalEventBroadcastFlagsI(&canp->wakeup_event, (eventflags_t)0);
+ osalOsRescheduleS();
+#endif
+ }
+ osalSysUnlock();
+}
+#endif /* CAN_USE_SLEEP_MODE == TRUE */
+
+#endif /* HAL_USE_CAN == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_crypto.c b/ChibiOS_20.3.2/os/hal/src/hal_crypto.c
new file mode 100644
index 0000000..4e2914f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_crypto.c
@@ -0,0 +1,1736 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_crypto.c
+ * @brief Cryptographic Driver code.
+ *
+ * @addtogroup CRYPTO
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_CRY == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Cryptographic Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void cryInit(void) {
+
+#if HAL_CRY_ENFORCE_FALLBACK == FALSE
+ cry_lld_init();
+#endif
+}
+
+/**
+ * @brief Initializes the standard part of a @p CRYDriver structure.
+ *
+ * @param[out] cryp pointer to the @p CRYDriver object
+ *
+ * @init
+ */
+void cryObjectInit(CRYDriver *cryp) {
+
+ cryp->state = CRY_STOP;
+ cryp->config = NULL;
+#if defined(CRY_DRIVER_EXT_INIT_HOOK)
+ CRY_DRIVER_EXT_INIT_HOOK(cryp);
+#endif
+}
+
+/**
+ * @brief Configures and activates the cryptographic peripheral.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] config pointer to the @p CRYConfig object. Depending
+ * on the implementation the value can be @p NULL.
+ *
+ * @api
+ */
+void cryStart(CRYDriver *cryp, const CRYConfig *config) {
+
+ osalDbgCheck(cryp != NULL);
+
+ osalSysLock();
+ osalDbgAssert((cryp->state == CRY_STOP) || (cryp->state == CRY_READY),
+ "invalid state");
+ cryp->config = config;
+#if HAL_CRY_ENFORCE_FALLBACK == FALSE
+ cry_lld_start(cryp);
+#endif
+ cryp->state = CRY_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the cryptographic peripheral.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ *
+ * @api
+ */
+void cryStop(CRYDriver *cryp) {
+
+ osalDbgCheck(cryp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((cryp->state == CRY_STOP) || (cryp->state == CRY_READY),
+ "invalid state");
+
+#if HAL_CRY_ENFORCE_FALLBACK == FALSE
+ cry_lld_stop(cryp);
+#endif
+ cryp->config = NULL;
+ cryp->state = CRY_STOP;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Initializes the AES transient key.
+ * @note It is the underlying implementation to decide which key sizes are
+ * allowable.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] size key size in bytes
+ * @param[in] keyp pointer to the key data
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the algorithm is unsupported.
+ * @retval CRY_ERR_INV_KEY_SIZE if the specified key size is invalid for
+ * the specified algorithm.
+ *
+ * @api
+ */
+cryerror_t cryLoadAESTransientKey(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *keyp) {
+
+ osalDbgCheck((cryp != NULL) && (keyp != NULL));
+
+#if CRY_LLD_SUPPORTS_AES == TRUE
+ return cry_lld_aes_loadkey(cryp, size, keyp);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_aes_loadkey(cryp, size, keyp);
+#else
+ (void)cryp;
+ (void)size;
+ (void)keyp;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Encryption of a single block using AES.
+ * @note The implementation of this function must guarantee that it can
+ * be called from any context.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @special
+ */
+cryerror_t cryEncryptAES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ osalDbgCheck((cryp != NULL) && (in != NULL) && (out != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_AES == TRUE
+ return cry_lld_encrypt_AES(cryp, key_id, in, out);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_encrypt_AES(cryp, key_id, in, out);
+#else
+ (void)cryp;
+ (void)key_id;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Decryption of a single block using AES.
+ * @note The implementation of this function must guarantee that it can
+ * be called from any context.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] in buffer containing the input ciphertext
+ * @param[out] out buffer for the output plaintext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @special
+ */
+cryerror_t cryDecryptAES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ osalDbgCheck((cryp != NULL) && (in != NULL) && (out != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_AES == TRUE
+ return cry_lld_decrypt_AES(cryp, key_id, in, out);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_decrypt_AES(cryp, key_id, in, out);
+#else
+ (void)cryp;
+ (void)key_id;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Encryption operation using AES-ECB.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers, this number must be a
+ * multiple of 16
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryEncryptAES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ osalDbgCheck((cryp != NULL) && (in != NULL) && (out != NULL) &&
+ ((size & (size_t)15) == (size_t)0));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_AES_ECB == TRUE
+ return cry_lld_encrypt_AES_ECB(cryp, key_id, size, in, out);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_encrypt_AES_ECB(cryp, key_id, size, in, out);
+#else
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Decryption operation using AES-ECB.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers, this number must be a
+ * multiple of 16
+ * @param[in] in buffer containing the input ciphertext
+ * @param[out] out buffer for the output plaintext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryDecryptAES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ osalDbgCheck((cryp != NULL) && (in != NULL) && (out != NULL) &&
+ ((size & (size_t)15) == (size_t)0));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_AES_ECB == TRUE
+ return cry_lld_decrypt_AES_ECB(cryp, key_id, size, in, out);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_decrypt_AES_ECB(cryp, key_id, size, in, out);
+#else
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Encryption operation using AES-CBC.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers, this number must be a
+ * multiple of 16
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @param[in] iv 128 bits input vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryEncryptAES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ osalDbgCheck((cryp != NULL) && (in != NULL) && (out != NULL) &&
+ (iv != NULL) && ((size & (size_t)15) == (size_t)0));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_AES_CBC == TRUE
+ return cry_lld_encrypt_AES_CBC(cryp, key_id, size, in, out, iv);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_encrypt_AES_CBC(cryp, key_id, size, in, out, iv);
+#else
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Decryption operation using AES-CBC.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers, this number must be a
+ * multiple of 16
+ * @param[in] in buffer containing the input ciphertext
+ * @param[out] out buffer for the output plaintext
+ * @param[in] iv 128 bits input vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryDecryptAES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ osalDbgCheck((cryp != NULL) && (in != NULL) && (out != NULL) &&
+ (iv != NULL) && ((size & (size_t)15) == (size_t)0));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_AES_CBC == TRUE
+ return cry_lld_decrypt_AES_CBC(cryp, key_id, size, in, out, iv);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_decrypt_AES_CBC(cryp, key_id, size, in, out, iv);
+#else
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Encryption operation using AES-CFB.
+ * @note This is a stream cipher, there are no size restrictions.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @param[in] iv 128 bits input vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryEncryptAES_CFB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ osalDbgCheck((cryp != NULL) && (in != NULL) && (out != NULL) &&
+ (iv != NULL) && (size > (size_t)0));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_AES_CFB == TRUE
+ return cry_lld_encrypt_AES_CFB(cryp, key_id, size, in, out, iv);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_encrypt_AES_CFB(cryp, key_id, size, in, out, iv);
+#else
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Decryption operation using AES-CFB.
+ * @note This is a stream cipher, there are no size restrictions.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers
+ * @param[in] in buffer containing the input ciphertext
+ * @param[out] out buffer for the output plaintext
+ * @param[in] iv 128 bits input vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryDecryptAES_CFB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ osalDbgCheck((cryp != NULL) && (in != NULL) && (out != NULL) &&
+ (iv != NULL) && (size > (size_t)0));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_AES_CFB == TRUE
+ return cry_lld_decrypt_AES_CFB(cryp, key_id, size, in, out, iv);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_decrypt_AES_CFB(cryp, key_id, size, in, out, iv);
+#else
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Encryption operation using AES-CTR.
+ * @note This is a stream cipher, there are no size restrictions.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @param[in] iv 128 bits input vector + counter, it contains
+ * a 96 bits IV and a 32 bits counter
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryEncryptAES_CTR(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ osalDbgCheck((cryp != NULL) && (in != NULL) && (out != NULL) &&
+ (iv != NULL) && (size > (size_t)0));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_AES_CTR == TRUE
+ return cry_lld_encrypt_AES_CTR(cryp, key_id, size, in, out, iv);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_encrypt_AES_CTR(cryp, key_id, size, in, out, iv);
+#else
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Decryption operation using AES-CTR.
+ * @note This is a stream cipher, there are no size restrictions.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers
+ * @param[in] in buffer containing the input ciphertext
+ * @param[out] out buffer for the output plaintext
+ * @param[in] iv 128 bits input vector + counter, it contains
+ * a 96 bits IV and a 32 bits counter
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryDecryptAES_CTR(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ osalDbgCheck((cryp != NULL) && (in != NULL) && (out != NULL) &&
+ (iv != NULL) && (size > (size_t)0));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_AES_CTR == TRUE
+ return cry_lld_decrypt_AES_CTR(cryp, key_id, size, in, out, iv);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_decrypt_AES_CTR(cryp, key_id, size, in, out, iv);
+#else
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Encryption operation using AES-GCM.
+ * @note This is a stream cipher, there are no size restrictions.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] auth_size size of the data buffer to be authenticated
+ * @param[in] auth_in buffer containing the data to be authenticated
+ * @param[in] text_size size of the text buffer
+ * @param[in] text_in buffer containing the input plaintext
+ * @param[out] text_out buffer for the output ciphertext
+ * @param[in] iv 128 bits input vector
+ * @param[in] tag_size size of the authentication tag, this number
+ * must be between 1 and 16
+ * @param[out] tag_out buffer for the generated authentication tag
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryEncryptAES_GCM(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t auth_size,
+ const uint8_t *auth_in,
+ size_t text_size,
+ const uint8_t *text_in,
+ uint8_t *text_out,
+ const uint8_t *iv,
+ size_t tag_size,
+ uint8_t *tag_out) {
+
+ osalDbgCheck((cryp != NULL) && (auth_in != NULL) &&
+ (text_size > (size_t)0) &&
+ (text_in != NULL) && (text_out != NULL) && (iv != NULL) &&
+ (tag_size >= (size_t)1) && (tag_size <= (size_t)16) &&
+ (tag_out != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_AES_GCM == TRUE
+ return cry_lld_encrypt_AES_GCM(cryp, key_id, auth_size, auth_in,
+ text_size, text_in, text_out, iv,
+ tag_size, tag_out);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_encrypt_AES_GCM(cryp, key_id, auth_size, auth_in,
+ text_size, text_in, text_out, iv,
+ tag_size, tag_out);
+#else
+ (void)cryp;
+ (void)key_id;
+ (void)auth_size;
+ (void)auth_in;
+ (void)text_size;
+ (void)text_in;
+ (void)text_out;
+ (void)iv;
+ (void)tag_size;
+ (void)tag_out;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Decryption operation using AES-GCM.
+ * @note This is a stream cipher, there are no size restrictions.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] auth_size size of the data buffer to be authenticated
+ * @param[in] auth_in buffer containing the data to be authenticated
+ * @param[in] text_size size of the text buffer
+ * @param[in] text_in buffer containing the input plaintext
+ * @param[out] text_out buffer for the output ciphertext
+ * @param[in] iv 128 bits input vector
+ * @param[in] tag_size size of the authentication tag, this number
+ * must be between 1 and 16
+ * @param[in] tag_in buffer for the generated authentication tag
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_AUTH_FAILED authentication failed
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryDecryptAES_GCM(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t auth_size,
+ const uint8_t *auth_in,
+ size_t text_size,
+ const uint8_t *text_in,
+ uint8_t *text_out,
+ const uint8_t *iv,
+ size_t tag_size,
+ const uint8_t *tag_in) {
+
+ osalDbgCheck((cryp != NULL) && (auth_in != NULL) &&
+ (text_size > (size_t)0) &&
+ (text_in != NULL) && (text_out != NULL) && (iv != NULL) &&
+ (tag_size >= (size_t)1) && (tag_size <= (size_t)16) &&
+ (tag_in != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_AES_GCM == TRUE
+ return cry_lld_decrypt_AES_GCM(cryp, key_id, auth_size, auth_in,
+ text_size, text_in, text_out, iv,
+ tag_size, tag_in);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_decrypt_AES_GCM(cryp, key_id, auth_size, auth_in,
+ text_size, text_in, text_out, iv,
+ tag_size, tag_in);
+#else
+ (void)cryp;
+ (void)key_id;
+ (void)auth_size;
+ (void)auth_in;
+ (void)text_size;
+ (void)text_in;
+ (void)text_out;
+ (void)iv;
+ (void)tag_size;
+ (void)tag_in;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Initializes the DES transient key.
+ * @note It is the underlying implementation to decide which key sizes are
+ * allowable.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] size key size in bytes
+ * @param[in] keyp pointer to the key data
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the algorithm is unsupported.
+ * @retval CRY_ERR_INV_KEY_SIZE if the specified key size is invalid for
+ * the specified algorithm.
+ *
+ * @api
+ */
+cryerror_t cryLoadDESTransientKey(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *keyp) {
+
+ osalDbgCheck((cryp != NULL) && (keyp != NULL));
+
+#if CRY_LLD_SUPPORTS_DES == TRUE
+ return cry_lld_des_loadkey(cryp, size, keyp);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_des_loadkey(cryp, size, keyp);
+#else
+ (void)cryp;
+ (void)size;
+ (void)keyp;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Encryption of a single block using (T)DES.
+ * @note The implementation of this function must guarantee that it can
+ * be called from any context.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @special
+ */
+cryerror_t cryEncryptDES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ osalDbgCheck((cryp != NULL) && (in != NULL) && (out != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_DES == TRUE
+ return cry_lld_encrypt_DES(cryp, key_id, in, out);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_encrypt_DES(cryp, key_id, in, out);
+#else
+ (void)cryp;
+ (void)key_id;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Decryption of a single block using (T)DES.
+ * @note The implementation of this function must guarantee that it can
+ * be called from any context.
+ *
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] in buffer containing the input ciphertext
+ * @param[out] out buffer for the output plaintext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @special
+ */
+cryerror_t cryDecryptDES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ osalDbgCheck((cryp != NULL) && (in != NULL) && (out != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_DES == TRUE
+ return cry_lld_decrypt_DES(cryp, key_id, in, out);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_decrypt_DES(cryp, key_id, in, out);
+#else
+ (void)cryp;
+ (void)key_id;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Encryption operation using (T)DES-ECB.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an DES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers, this number must be a
+ * multiple of 8
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryEncryptDES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ osalDbgCheck((cryp != NULL) && (in != NULL) && (out != NULL) &&
+ ((size & (size_t)7) == (size_t)0));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_DES_ECB == TRUE
+ return cry_lld_encrypt_DES_ECB(cryp, key_id, size, in, out);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_encrypt_DES_ECB(cryp, key_id, size, in, out);
+#else
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Decryption operation using (T)DES-ECB.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an DES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers, this number must be a
+ * multiple of 8
+ * @param[in] in buffer containing the input ciphertext
+ * @param[out] out buffer for the output plaintext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryDecryptDES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ osalDbgCheck((cryp != NULL) && (in != NULL) && (out != NULL) &&
+ ((size & (size_t)7) == (size_t)0));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_DES_ECB == TRUE
+ return cry_lld_decrypt_DES_ECB(cryp, key_id, size, in, out);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_decrypt_DES_ECB(cryp, key_id, size, in, out);
+#else
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Encryption operation using (T)DES-CBC.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an DES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers, this number must be a
+ * multiple of 8
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @param[in] iv 64 bits input vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryEncryptDES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ osalDbgCheck((cryp != NULL) && (in != NULL) && (out != NULL) &&
+ (iv != NULL) && ((size & (size_t)7) == (size_t)0));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_DES_CBC == TRUE
+ return cry_lld_encrypt_DES_CBC(cryp, key_id, size, in, out, iv);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_encrypt_DES_CBC(cryp, key_id, size, in, out, iv);
+#else
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Decryption operation using (T)DES-CBC.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an DES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers, this number must be a
+ * multiple of 8
+ * @param[in] in buffer containing the input ciphertext
+ * @param[out] out buffer for the output plaintext
+ * @param[in] iv 64 bits input vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryDecryptDES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ osalDbgCheck((cryp != NULL) && (in != NULL) && (out != NULL) &&
+ (iv != NULL) && ((size & (size_t)7) == (size_t)0));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_DES_CBC == TRUE
+ return cry_lld_decrypt_DES_CBC(cryp, key_id, size, in, out, iv);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_decrypt_DES_CBC(cryp, key_id, size, in, out, iv);
+#else
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Hash initialization using SHA1.
+ * @note Use of this algorithm is not recommended because proven weak.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[out] sha1ctxp pointer to a SHA1 context to be initialized
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t crySHA1Init(CRYDriver *cryp, SHA1Context *sha1ctxp) {
+
+ osalDbgCheck((cryp != NULL) && (sha1ctxp != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_SHA1 == TRUE
+ return cry_lld_SHA1_init(cryp, sha1ctxp);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_SHA1_init(cryp, sha1ctxp);
+#else
+ (void)cryp;
+ (void)sha1ctxp;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Hash update using SHA1.
+ * @note Use of this algorithm is not recommended because proven weak.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] sha1ctxp pointer to a SHA1 context
+ * @param[in] size size of input buffer
+ * @param[in] in buffer containing the input text
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t crySHA1Update(CRYDriver *cryp, SHA1Context *sha1ctxp,
+ size_t size, const uint8_t *in) {
+
+ osalDbgCheck((cryp != NULL) && (sha1ctxp != NULL) && (in != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_SHA1 == TRUE
+ return cry_lld_SHA1_update(cryp, sha1ctxp, size, in);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_SHA1_update(cryp, sha1ctxp, size, in);
+#else
+ (void)cryp;
+ (void)sha1ctxp;
+ (void)size;
+ (void)in;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Hash finalization using SHA1.
+ * @note Use of this algorithm is not recommended because proven weak.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] sha1ctxp pointer to a SHA1 context
+ * @param[out] out 160 bits output buffer
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t crySHA1Final(CRYDriver *cryp, SHA1Context *sha1ctxp, uint8_t *out) {
+
+ osalDbgCheck((cryp != NULL) && (sha1ctxp != NULL) && (out != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_SHA1 == TRUE
+ return cry_lld_SHA1_final(cryp, sha1ctxp, out);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_SHA1_final(cryp, sha1ctxp, out);
+#else
+ (void)cryp;
+ (void)sha1ctxp;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Hash initialization using SHA256.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[out] sha256ctxp pointer to a SHA256 context to be initialized
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t crySHA256Init(CRYDriver *cryp, SHA256Context *sha256ctxp) {
+
+ osalDbgCheck((cryp != NULL) && (sha256ctxp != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_SHA256 == TRUE
+ return cry_lld_SHA256_init(cryp, sha256ctxp);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_SHA256_init(cryp, sha256ctxp);
+#else
+ (void)cryp;
+ (void)sha256ctxp;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Hash update using SHA256.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] sha256ctxp pointer to a SHA256 context
+ * @param[in] size size of input buffer
+ * @param[in] in buffer containing the input text
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t crySHA256Update(CRYDriver *cryp, SHA256Context *sha256ctxp,
+ size_t size, const uint8_t *in) {
+
+ osalDbgCheck((cryp != NULL) && (sha256ctxp != NULL) && (in != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_SHA256 == TRUE
+ return cry_lld_SHA256_update(cryp, sha256ctxp, size, in);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_SHA256_update(cryp, sha256ctxp, size, in);
+#else
+ (void)cryp;
+ (void)sha256ctxp;
+ (void)size;
+ (void)in;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Hash finalization using SHA256.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] sha256ctxp pointer to a SHA256 context
+ * @param[out] out 256 bits output buffer
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t crySHA256Final(CRYDriver *cryp, SHA256Context *sha256ctxp,
+ uint8_t *out) {
+
+ osalDbgCheck((cryp != NULL) && (sha256ctxp != NULL) && (out != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_SHA256 == TRUE
+ return cry_lld_SHA256_final(cryp, sha256ctxp, out);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_SHA256_final(cryp, sha256ctxp, out);
+#else
+ (void)cryp;
+ (void)sha256ctxp;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Hash initialization using SHA512.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[out] sha512ctxp pointer to a SHA512 context to be initialized
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t crySHA512Init(CRYDriver *cryp, SHA512Context *sha512ctxp) {
+
+ osalDbgCheck((cryp != NULL) && (sha512ctxp != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_SHA512 == TRUE
+ return cry_lld_SHA512_init(cryp, sha512ctxp);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_SHA512_init(cryp, sha512ctxp);
+#else
+ (void)cryp;
+ (void)sha512ctxp;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Hash update using SHA512.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] sha512ctxp pointer to a SHA512 context
+ * @param[in] size size of input buffer
+ * @param[in] in buffer containing the input text
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t crySHA512Update(CRYDriver *cryp, SHA512Context *sha512ctxp,
+ size_t size, const uint8_t *in) {
+
+ osalDbgCheck((cryp != NULL) && (sha512ctxp != NULL) && (in != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_SHA512 == TRUE
+ return cry_lld_SHA512_update(cryp, sha512ctxp, size, in);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_SHA512_update(cryp, sha512ctxp, size, in);
+#else
+ (void)cryp;
+ (void)sha512ctxp;
+ (void)size;
+ (void)in;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Hash finalization using SHA512.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] sha512ctxp pointer to a SHA512 context
+ * @param[out] out 512 bits output buffer
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t crySHA512Final(CRYDriver *cryp, SHA512Context *sha512ctxp,
+ uint8_t *out) {
+
+ osalDbgCheck((cryp != NULL) && (sha512ctxp != NULL) && (out != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_SHA512 == TRUE
+ return cry_lld_SHA512_final(cryp, sha512ctxp, out);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_SHA512_final(cryp, sha512ctxp, out);
+#else
+ (void)cryp;
+ (void)sha512ctxp;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Initializes the HMAC transient key.
+ * @note It is the underlying implementation to decide which key sizes are
+ * allowable.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] size key size in bytes
+ * @param[in] keyp pointer to the key data
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the algorithm is unsupported.
+ * @retval CRY_ERR_INV_KEY_SIZE if the specified key size is invalid for
+ * the specified algorithm.
+ *
+ * @api
+ */
+cryerror_t cryLoadHMACTransientKey(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *keyp) {
+
+ osalDbgCheck((cryp != NULL) && (keyp != NULL));
+
+#if (CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE) || \
+ (CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE)
+ return cry_lld_hmac_loadkey(cryp, size, keyp);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_hmac_loadkey(cryp, size, keyp);
+#else
+ (void)cryp;
+ (void)size;
+ (void)keyp;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Hash initialization using HMAC_SHA256.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[out] hmacsha256ctxp pointer to a HMAC_SHA256 context to be
+ * initialized
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryHMACSHA256Init(CRYDriver *cryp,
+ HMACSHA256Context *hmacsha256ctxp) {
+
+ osalDbgCheck((cryp != NULL) && (hmacsha256ctxp != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE
+ return cry_lld_HMACSHA256_init(cryp, hmacsha256ctxp);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_HMACSHA256_init(cryp, hmacsha256ctxp);
+#else
+ (void)cryp;
+ (void)hmacsha256ctxp;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Hash update using HMAC.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] hmacsha256ctxp pointer to a HMAC_SHA256 context
+ * @param[in] size size of input buffer
+ * @param[in] in buffer containing the input text
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryHMACSHA256Update(CRYDriver *cryp,
+ HMACSHA256Context *hmacsha256ctxp,
+ size_t size,
+ const uint8_t *in) {
+
+ osalDbgCheck((cryp != NULL) && (hmacsha256ctxp != NULL) && (in != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE
+ return cry_lld_HMACSHA256_update(cryp, hmacsha256ctxp, size, in);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_HMACSHA256_update(cryp, hmacsha256ctxp, size, in);
+#else
+ (void)cryp;
+ (void)hmacsha256ctxp;
+ (void)size;
+ (void)in;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Hash finalization using HMAC.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] hmacsha256ctxp pointer to a HMAC_SHA256 context
+ * @param[out] out 256 bits output buffer
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryHMACSHA256Final(CRYDriver *cryp,
+ HMACSHA256Context *hmacsha256ctxp,
+ uint8_t *out) {
+
+ osalDbgCheck((cryp != NULL) && (hmacsha256ctxp != NULL) && (out != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE
+ return cry_lld_HMACSHA256_final(cryp, hmacsha256ctxp, out);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_HMACSHA256_final(cryp, hmacsha256ctxp, out);
+#else
+ (void)cryp;
+ (void)hmacsha256ctxp;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Hash initialization using HMAC_SHA512.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[out] hmacsha512ctxp pointer to a HMAC_SHA512 context to be
+ * initialized
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryHMACSHA512Init(CRYDriver *cryp,
+ HMACSHA512Context *hmacsha512ctxp) {
+
+ osalDbgCheck((cryp != NULL) && (hmacsha512ctxp != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE
+ return cry_lld_HMACSHA512_init(cryp, hmacsha512ctxp);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_HMACSHA512_init(cryp, hmacsha512ctxp);
+#else
+ (void)cryp;
+ (void)hmacsha512ctxp;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Hash update using HMAC.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] hmacsha512ctxp pointer to a HMAC_SHA512 context
+ * @param[in] size size of input buffer
+ * @param[in] in buffer containing the input text
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryHMACSHA512Update(CRYDriver *cryp,
+ HMACSHA512Context *hmacsha512ctxp,
+ size_t size,
+ const uint8_t *in) {
+
+ osalDbgCheck((cryp != NULL) && (hmacsha512ctxp != NULL) && (in != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE
+ return cry_lld_HMACSHA512_update(cryp, hmacsha512ctxp, size, in);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_HMACSHA512_update(cryp, hmacsha512ctxp, size, in);
+#else
+ (void)cryp;
+ (void)hmacsha512ctxp;
+ (void)size;
+ (void)in;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+/**
+ * @brief Hash finalization using HMAC.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] hmacsha512ctxp pointer to a HMAC_SHA512 context
+ * @param[out] out 512 bits output buffer
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @api
+ */
+cryerror_t cryHMACSHA512Final(CRYDriver *cryp,
+ HMACSHA512Context *hmacsha512ctxp,
+ uint8_t *out) {
+
+ osalDbgCheck((cryp != NULL) && (hmacsha512ctxp != NULL) && (out != NULL));
+
+ osalDbgAssert(cryp->state == CRY_READY, "not ready");
+
+#if CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE
+ return cry_lld_HMACSHA512_final(cryp, hmacsha512ctxp, out);
+#elif HAL_CRY_USE_FALLBACK == TRUE
+ return cry_fallback_HMACSHA512_final(cryp, hmacsha512ctxp, out);
+#else
+ (void)cryp;
+ (void)hmacsha512ctxp;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+#endif
+}
+
+#endif /* HAL_USE_CRY == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_dac.c b/ChibiOS_20.3.2/os/hal/src/hal_dac.c
new file mode 100644
index 0000000..80fbdf9
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_dac.c
@@ -0,0 +1,350 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_dac.c
+ * @brief DAC Driver code.
+ *
+ * @addtogroup DAC
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_DAC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief DAC Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void dacInit(void) {
+
+ dac_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p DACDriver structure.
+ *
+ * @param[out] dacp pointer to the @p DACDriver object
+ *
+ * @init
+ */
+void dacObjectInit(DACDriver *dacp) {
+
+ dacp->state = DAC_STOP;
+ dacp->config = NULL;
+#if DAC_USE_WAIT
+ dacp->thread = NULL;
+#endif
+#if DAC_USE_MUTUAL_EXCLUSION
+ osalMutexObjectInit(&dacp->mutex);
+#endif
+#if defined(DAC_DRIVER_EXT_INIT_HOOK)
+ DAC_DRIVER_EXT_INIT_HOOK(dacp);
+#endif
+}
+
+/**
+ * @brief Configures and activates the DAC peripheral.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ * @param[in] config pointer to the @p DACConfig object, it can be
+ * @p NULL if the low level driver implementation
+ * supports a default configuration
+ *
+ * @api
+ */
+void dacStart(DACDriver *dacp, const DACConfig *config) {
+
+ osalDbgCheck(dacp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY),
+ "invalid state");
+
+ dacp->config = config;
+ dac_lld_start(dacp);
+ dacp->state = DAC_READY;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the DAC peripheral.
+ * @note Deactivating the peripheral also enforces a release of the slave
+ * select line.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @api
+ */
+void dacStop(DACDriver *dacp) {
+
+ osalDbgCheck(dacp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY),
+ "invalid state");
+
+ dac_lld_stop(dacp);
+ dacp->config = NULL;
+ dacp->state = DAC_STOP;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Outputs a value directly on a DAC channel.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ * @param[in] channel DAC channel number
+ * @param[in] sample value to be output
+ *
+ * @xclass
+ */
+void dacPutChannelX(DACDriver *dacp, dacchannel_t channel, dacsample_t sample) {
+
+ osalDbgCheck(channel < (dacchannel_t)DAC_MAX_CHANNELS);
+ osalDbgAssert(dacp->state == DAC_READY, "invalid state");
+
+ dac_lld_put_channel(dacp, channel, sample);
+}
+
+/**
+ * @brief Starts a DAC conversion.
+ * @details Starts an asynchronous conversion operation.
+ * @note The buffer is organized as a matrix of M*N elements where M is the
+ * channels number configured into the conversion group and N is the
+ * buffer depth. The samples are sequentially written into the buffer
+ * with no gaps.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ * @param[in] grpp pointer to a @p DACConversionGroup object
+ * @param[in] samples pointer to the samples buffer
+ * @param[in] depth buffer depth (matrix rows number). The buffer depth
+ * must be one or an even number.
+ *
+ * @api
+ */
+void dacStartConversion(DACDriver *dacp,
+ const DACConversionGroup *grpp,
+ dacsample_t *samples,
+ size_t depth) {
+
+ osalSysLock();
+ dacStartConversionI(dacp, grpp, samples, depth);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Starts a DAC conversion.
+ * @details Starts an asynchronous conversion operation.
+ * @post The callbacks associated to the conversion group will be invoked
+ * on buffer fill and error events.
+ * @note The buffer is organized as a matrix of M*N elements where M is the
+ * channels number configured into the conversion group and N is the
+ * buffer depth. The samples are sequentially written into the buffer
+ * with no gaps.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ * @param[in] grpp pointer to a @p DACConversionGroup object
+ * @param[in] samples pointer to the samples buffer
+ * @param[in] depth buffer depth (matrix rows number). The buffer depth
+ * must be one or an even number.
+ *
+ * @iclass
+ */
+void dacStartConversionI(DACDriver *dacp,
+ const DACConversionGroup *grpp,
+ dacsample_t *samples,
+ size_t depth) {
+
+ osalDbgCheckClassI();
+ osalDbgCheck((dacp != NULL) && (grpp != NULL) && (samples != NULL) &&
+ ((depth == 1U) || ((depth & 1U) == 0U)));
+ osalDbgAssert((dacp->state == DAC_READY) ||
+ (dacp->state == DAC_COMPLETE) ||
+ (dacp->state == DAC_ERROR),
+ "not ready");
+
+ dacp->samples = samples;
+ dacp->depth = depth;
+ dacp->grpp = grpp;
+ dacp->state = DAC_ACTIVE;
+ dac_lld_start_conversion(dacp);
+}
+
+/**
+ * @brief Stops an ongoing conversion.
+ * @details This function stops the currently ongoing conversion and returns
+ * the driver in the @p DAC_READY state. If there was no conversion
+ * being processed then the function does nothing.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @api
+ */
+void dacStopConversion(DACDriver *dacp) {
+
+ osalDbgCheck(dacp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((dacp->state == DAC_READY) ||
+ (dacp->state == DAC_ACTIVE),
+ "invalid state");
+
+ if (dacp->state != DAC_READY) {
+ dac_lld_stop_conversion(dacp);
+ dacp->grpp = NULL;
+ dacp->state = DAC_READY;
+ _dac_reset_s(dacp);
+ }
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Stops an ongoing conversion.
+ * @details This function stops the currently ongoing conversion and returns
+ * the driver in the @p DAC_READY state. If there was no conversion
+ * being processed then the function does nothing.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @iclass
+ */
+void dacStopConversionI(DACDriver *dacp) {
+
+ osalDbgCheckClassI();
+ osalDbgCheck(dacp != NULL);
+ osalDbgAssert((dacp->state == DAC_READY) ||
+ (dacp->state == DAC_ACTIVE) ||
+ (dacp->state == DAC_COMPLETE),
+ "invalid state");
+
+ if (dacp->state != DAC_READY) {
+ dac_lld_stop_conversion(dacp);
+ dacp->grpp = NULL;
+ dacp->state = DAC_READY;
+ _dac_reset_i(dacp);
+ }
+}
+
+#if (DAC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Performs a DAC conversion.
+ * @details Performs a synchronous conversion operation.
+ * @note The buffer is organized as a matrix of M*N elements where M is the
+ * channels number configured into the conversion group and N is the
+ * buffer depth. The samples are sequentially written into the buffer
+ * with no gaps.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ * @param[in] grpp pointer to a @p DACConversionGroup object
+ * @param[out] samples pointer to the samples buffer
+ * @param[in] depth buffer depth (matrix rows number). The buffer depth
+ * must be one or an even number.
+ * @return The operation result.
+ * @retval MSG_OK Conversion finished.
+ * @retval MSG_RESET The conversion has been stopped using
+ * @p acdStopConversion() or @p acdStopConversionI(),
+ * the result buffer may contain incorrect data.
+ * @retval MSG_TIMEOUT The conversion has been stopped because an hardware
+ * error.
+ *
+ * @api
+ */
+msg_t dacConvert(DACDriver *dacp,
+ const DACConversionGroup *grpp,
+ dacsample_t *samples,
+ size_t depth) {
+ msg_t msg;
+
+ osalSysLock();
+
+ dacStartConversionI(dacp, grpp, samples, depth);
+ msg = osalThreadSuspendS(&dacp->thread);
+
+ osalSysUnlock();
+ return msg;
+}
+#endif /* DAC_USE_WAIT == TRUE */
+
+#if (DAC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Gains exclusive access to the DAC bus.
+ * @details This function tries to gain ownership to the DAC bus, if the bus
+ * is already being used then the invoking thread is queued.
+ * @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION
+ * must be enabled.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @api
+ */
+void dacAcquireBus(DACDriver *dacp) {
+
+ osalDbgCheck(dacp != NULL);
+
+ osalMutexLock(&dacp->mutex);
+}
+
+/**
+ * @brief Releases exclusive access to the DAC bus.
+ * @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION
+ * must be enabled.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @api
+ */
+void dacReleaseBus(DACDriver *dacp) {
+
+ osalDbgCheck(dacp != NULL);
+
+ osalMutexUnlock(&dacp->mutex);
+}
+#endif /* DAC_USE_MUTUAL_EXCLUSION == TRUE */
+
+#endif /* HAL_USE_DAC == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_efl.c b/ChibiOS_20.3.2/os/hal/src/hal_efl.c
new file mode 100644
index 0000000..fb1c7c3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_efl.c
@@ -0,0 +1,134 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_efl.c
+ * @brief Embedded Flash Driver code.
+ *
+ * @addtogroup HAL_EFL
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static const struct EFlashDriverVMT vmt = {
+ (size_t)0,
+ efl_lld_get_descriptor,
+ efl_lld_read,
+ efl_lld_program,
+ efl_lld_start_erase_all,
+ efl_lld_start_erase_sector,
+ efl_lld_query_erase,
+ efl_lld_verify_erase
+};
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Embedded Flash Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void eflInit(void) {
+
+ efl_lld_init();
+}
+
+/**
+ * @brief Initializes a generic @p EFlashDriver object.
+ *
+ * @param[out] eflp pointer to a @p EFlashDriver structure
+ *
+ * @init
+ */
+void eflObjectInit(EFlashDriver *eflp) {
+
+ eflp->vmt = &vmt;
+ eflp->state = FLASH_STOP;
+}
+
+/**
+ * @brief Configures and starts the driver.
+ *
+ * @param[in] eflp pointer to a @p EFlashDriver structure
+ * @param[in] config pointer to a configuration structure.
+ * If this parameter is set to @p NULL then a default
+ * configuration is used.
+ *
+ * @api
+ */
+void eflStart(EFlashDriver *eflp, const EFlashConfig *config) {
+
+ osalDbgCheck(eflp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((eflp->state == FLASH_STOP) || (eflp->state == FLASH_READY),
+ "invalid state");
+ eflp->config = config;
+ efl_lld_start(eflp);
+ eflp->state = FLASH_READY;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Stops the driver.
+ *
+ * @param[in] eflp pointer to a @p EFlashDriver structure
+ *
+ * @api
+ */
+void eflStop(EFlashDriver *eflp) {
+
+ osalDbgCheck(eflp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((eflp->state == FLASH_STOP) || (eflp->state == FLASH_READY),
+ "invalid state");
+
+ efl_lld_stop(eflp);
+ eflp->state = FLASH_STOP;
+
+ osalSysUnlock();
+}
+
+#endif /* HAL_USE_EFL == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_flash.c b/ChibiOS_20.3.2/os/hal/src/hal_flash.c
new file mode 100644
index 0000000..f3e7a35
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_flash.c
@@ -0,0 +1,125 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_flash.c
+ * @brief Generic flash driver class code.
+ *
+ * @addtogroup HAL_FLASH
+ * @{
+ */
+
+#include "hal.h"
+
+#include "hal_flash.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Waits until the current erase operation is finished.
+ *
+ * @param[in] devp pointer to a @p BaseFlash object
+ *
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_ERROR_ERASE if the erase operation failed.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ */
+flash_error_t flashWaitErase(BaseFlash *devp) {
+
+ while (true) {
+ flash_error_t err;
+ uint32_t msec;
+
+ /* Checking operation state.*/
+ err = flashQueryErase(devp, &msec);
+ if (err != FLASH_BUSY_ERASING) {
+ return err;
+ }
+
+ /* Interval because nice waiting.*/
+ osalThreadSleepMilliseconds(msec);
+ }
+}
+
+/**
+ * @brief Returns the offset of a sector.
+ *
+ * @param[in] devp pointer to a @p BaseFlash object
+ * @param[in] sector flash sector number
+ *
+ * @return the offset of the sector
+ */
+flash_offset_t flashGetSectorOffset(BaseFlash *devp,
+ flash_sector_t sector) {
+ flash_offset_t offset;
+ const flash_descriptor_t *descriptor = flashGetDescriptor(devp);
+
+ osalDbgAssert(sector < descriptor->sectors_count, "invalid sector");
+
+ if (descriptor->sectors != NULL) {
+ offset = descriptor->sectors[sector].offset;
+ }
+ else {
+ offset = (flash_offset_t)sector * (flash_offset_t)descriptor->sectors_size;
+ }
+
+ return offset;
+}
+
+/**
+ * @brief Returns the size of a sector.
+ *
+ * @param[in] devp pointer to a @p BaseFlash object
+ * @param[in] sector flash sector number
+ *
+ * @return the size of the sector
+ */
+uint32_t flashGetSectorSize(BaseFlash *devp,
+ flash_sector_t sector) {
+ uint32_t size;
+ const flash_descriptor_t *descriptor = flashGetDescriptor(devp);
+
+ osalDbgAssert(sector < descriptor->sectors_count, "invalid sector");
+
+ if (descriptor->sectors != NULL) {
+ size = descriptor->sectors[sector].size;
+ }
+ else {
+ size = descriptor->sectors_size;
+ }
+
+ return size;
+}
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_gpt.c b/ChibiOS_20.3.2/os/hal/src/hal_gpt.c
new file mode 100644
index 0000000..dd9145d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_gpt.c
@@ -0,0 +1,266 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_gpt.c
+ * @brief GPT Driver code.
+ *
+ * @addtogroup GPT
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_GPT == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief GPT Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void gptInit(void) {
+
+ gpt_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p GPTDriver structure.
+ *
+ * @param[out] gptp pointer to the @p GPTDriver object
+ *
+ * @init
+ */
+void gptObjectInit(GPTDriver *gptp) {
+
+ gptp->state = GPT_STOP;
+ gptp->config = NULL;
+}
+
+/**
+ * @brief Configures and activates the GPT peripheral.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ * @param[in] config pointer to the @p GPTConfig object
+ *
+ * @api
+ */
+void gptStart(GPTDriver *gptp, const GPTConfig *config) {
+
+ osalDbgCheck((gptp != NULL) && (config != NULL));
+
+ osalSysLock();
+ osalDbgAssert((gptp->state == GPT_STOP) || (gptp->state == GPT_READY),
+ "invalid state");
+ gptp->config = config;
+ gpt_lld_start(gptp);
+ gptp->state = GPT_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the GPT peripheral.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ *
+ * @api
+ */
+void gptStop(GPTDriver *gptp) {
+
+ osalDbgCheck(gptp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((gptp->state == GPT_STOP) || (gptp->state == GPT_READY),
+ "invalid state");
+
+ gpt_lld_stop(gptp);
+ gptp->config = NULL;
+ gptp->state = GPT_STOP;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Changes the interval of GPT peripheral.
+ * @details This function changes the interval of a running GPT unit.
+ * @pre The GPT unit must be running in continuous mode.
+ * @post The GPT unit interval is changed to the new value.
+ *
+ * @param[in] gptp pointer to a @p GPTDriver object
+ * @param[in] interval new cycle time in timer ticks
+ *
+ * @api
+ */
+void gptChangeInterval(GPTDriver *gptp, gptcnt_t interval) {
+
+ osalDbgCheck(gptp != NULL);
+
+ osalSysLock();
+ osalDbgAssert(gptp->state == GPT_CONTINUOUS,
+ "invalid state");
+ gptChangeIntervalI(gptp, interval);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Starts the timer in continuous mode.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ * @param[in] interval period in ticks
+ *
+ * @api
+ */
+void gptStartContinuous(GPTDriver *gptp, gptcnt_t interval) {
+
+ osalSysLock();
+ gptStartContinuousI(gptp, interval);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Starts the timer in continuous mode.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ * @param[in] interval period in ticks
+ *
+ * @iclass
+ */
+void gptStartContinuousI(GPTDriver *gptp, gptcnt_t interval) {
+
+ osalDbgCheckClassI();
+ osalDbgCheck(gptp != NULL);
+ osalDbgAssert(gptp->state == GPT_READY,
+ "invalid state");
+
+ gptp->state = GPT_CONTINUOUS;
+ gpt_lld_start_timer(gptp, interval);
+}
+
+/**
+ * @brief Starts the timer in one shot mode.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ * @param[in] interval time interval in ticks
+ *
+ * @api
+ */
+void gptStartOneShot(GPTDriver *gptp, gptcnt_t interval) {
+
+ osalSysLock();
+ gptStartOneShotI(gptp, interval);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Starts the timer in one shot mode.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ * @param[in] interval time interval in ticks
+ *
+ * @api
+ */
+void gptStartOneShotI(GPTDriver *gptp, gptcnt_t interval) {
+
+ osalDbgCheckClassI();
+ osalDbgCheck(gptp != NULL);
+ osalDbgCheck(gptp->config->callback != NULL);
+ osalDbgAssert(gptp->state == GPT_READY,
+ "invalid state");
+
+ gptp->state = GPT_ONESHOT;
+ gpt_lld_start_timer(gptp, interval);
+}
+
+/**
+ * @brief Stops the timer.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ *
+ * @api
+ */
+void gptStopTimer(GPTDriver *gptp) {
+
+ osalSysLock();
+ gptStopTimerI(gptp);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Stops the timer.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ *
+ * @api
+ */
+void gptStopTimerI(GPTDriver *gptp) {
+
+ osalDbgCheckClassI();
+ osalDbgCheck(gptp != NULL);
+ osalDbgAssert((gptp->state == GPT_READY) || (gptp->state == GPT_CONTINUOUS) ||
+ (gptp->state == GPT_ONESHOT),
+ "invalid state");
+
+ gptp->state = GPT_READY;
+ gpt_lld_stop_timer(gptp);
+}
+
+/**
+ * @brief Starts the timer in one shot mode and waits for completion.
+ * @details This function specifically polls the timer waiting for completion
+ * in order to not have extra delays caused by interrupt servicing,
+ * this function is only recommended for short delays.
+ * @note The configured callback is not invoked when using this function.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ * @param[in] interval time interval in ticks
+ *
+ * @api
+ */
+void gptPolledDelay(GPTDriver *gptp, gptcnt_t interval) {
+
+ osalDbgAssert(gptp->state == GPT_READY,
+ "invalid state");
+
+ gptp->state = GPT_ONESHOT;
+ gpt_lld_polled_delay(gptp, interval);
+ gptp->state = GPT_READY;
+}
+
+#endif /* HAL_USE_GPT == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_i2c.c b/ChibiOS_20.3.2/os/hal/src/hal_i2c.c
new file mode 100644
index 0000000..158cfeb
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_i2c.c
@@ -0,0 +1,287 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file hal_i2c.c
+ * @brief I2C Driver code.
+ *
+ * @addtogroup I2C
+ * @{
+ */
+#include "hal.h"
+
+#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief I2C Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void i2cInit(void) {
+
+ i2c_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p I2CDriver structure.
+ *
+ * @param[out] i2cp pointer to the @p I2CDriver object
+ *
+ * @init
+ */
+void i2cObjectInit(I2CDriver *i2cp) {
+
+ i2cp->state = I2C_STOP;
+ i2cp->config = NULL;
+
+#if I2C_USE_MUTUAL_EXCLUSION == TRUE
+ osalMutexObjectInit(&i2cp->mutex);
+#endif
+
+#if defined(I2C_DRIVER_EXT_INIT_HOOK)
+ I2C_DRIVER_EXT_INIT_HOOK(i2cp);
+#endif
+}
+
+/**
+ * @brief Configures and activates the I2C peripheral.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] config pointer to the @p I2CConfig object
+ *
+ * @api
+ */
+void i2cStart(I2CDriver *i2cp, const I2CConfig *config) {
+
+ osalDbgCheck((i2cp != NULL) && (config != NULL));
+ osalDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY) ||
+ (i2cp->state == I2C_LOCKED), "invalid state");
+
+ osalSysLock();
+ i2cp->config = config;
+ i2c_lld_start(i2cp);
+ i2cp->state = I2C_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the I2C peripheral.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @api
+ */
+void i2cStop(I2CDriver *i2cp) {
+
+ osalDbgCheck(i2cp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY) ||
+ (i2cp->state == I2C_LOCKED), "invalid state");
+
+ i2c_lld_stop(i2cp);
+ i2cp->config = NULL;
+ i2cp->state = I2C_STOP;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Returns the errors mask associated to the previous operation.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @return The errors mask.
+ *
+ * @api
+ */
+i2cflags_t i2cGetErrors(I2CDriver *i2cp) {
+
+ osalDbgCheck(i2cp != NULL);
+
+ return i2c_lld_get_errors(i2cp);
+}
+
+/**
+ * @brief Sends data via the I2C bus.
+ * @details Function designed to realize "read-through-write" transfer
+ * paradigm. If you want transmit data without any further read,
+ * than set @b rxbytes field to 0.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] addr slave device address (7 bits) without R/W bit
+ * @param[in] txbuf pointer to transmit buffer
+ * @param[in] txbytes number of bytes to be transmitted
+ * @param[out] rxbuf pointer to receive buffer
+ * @param[in] rxbytes number of bytes to be received, set it to 0 if
+ * you want transmit only
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp,
+ i2caddr_t addr,
+ const uint8_t *txbuf,
+ size_t txbytes,
+ uint8_t *rxbuf,
+ size_t rxbytes,
+ sysinterval_t timeout) {
+ msg_t rdymsg;
+
+ osalDbgCheck((i2cp != NULL) &&
+ (txbytes > 0U) && (txbuf != NULL) &&
+ ((rxbytes == 0U) || ((rxbytes > 0U) && (rxbuf != NULL))) &&
+ (timeout != TIME_IMMEDIATE));
+
+ osalDbgAssert(i2cp->state == I2C_READY, "not ready");
+
+ osalSysLock();
+ i2cp->errors = I2C_NO_ERROR;
+ i2cp->state = I2C_ACTIVE_TX;
+ rdymsg = i2c_lld_master_transmit_timeout(i2cp, addr, txbuf, txbytes,
+ rxbuf, rxbytes, timeout);
+ if (rdymsg == MSG_TIMEOUT) {
+ i2cp->state = I2C_LOCKED;
+ }
+ else {
+ i2cp->state = I2C_READY;
+ }
+ osalSysUnlock();
+ return rdymsg;
+}
+
+/**
+ * @brief Receives data from the I2C bus.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] addr slave device address (7 bits) without R/W bit
+ * @param[out] rxbuf pointer to receive buffer
+ * @param[in] rxbytes number of bytes to be received
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end.
+ *
+ * @api
+ */
+msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp,
+ i2caddr_t addr,
+ uint8_t *rxbuf,
+ size_t rxbytes,
+ sysinterval_t timeout) {
+
+ msg_t rdymsg;
+
+ osalDbgCheck((i2cp != NULL) && (addr != 0U) &&
+ (rxbytes > 0U) && (rxbuf != NULL) &&
+ (timeout != TIME_IMMEDIATE));
+
+ osalDbgAssert(i2cp->state == I2C_READY, "not ready");
+
+ osalSysLock();
+ i2cp->errors = I2C_NO_ERROR;
+ i2cp->state = I2C_ACTIVE_RX;
+ rdymsg = i2c_lld_master_receive_timeout(i2cp, addr, rxbuf, rxbytes, timeout);
+ if (rdymsg == MSG_TIMEOUT) {
+ i2cp->state = I2C_LOCKED;
+ }
+ else {
+ i2cp->state = I2C_READY;
+ }
+ osalSysUnlock();
+ return rdymsg;
+}
+
+#if (I2C_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Gains exclusive access to the I2C bus.
+ * @details This function tries to gain ownership to the I2C bus, if the bus
+ * is already being used then the invoking thread is queued.
+ * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION
+ * must be enabled.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @api
+ */
+void i2cAcquireBus(I2CDriver *i2cp) {
+
+ osalDbgCheck(i2cp != NULL);
+
+ osalMutexLock(&i2cp->mutex);
+}
+
+/**
+ * @brief Releases exclusive access to the I2C bus.
+ * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION
+ * must be enabled.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @api
+ */
+void i2cReleaseBus(I2CDriver *i2cp) {
+
+ osalDbgCheck(i2cp != NULL);
+
+ osalMutexUnlock(&i2cp->mutex);
+}
+#endif /* I2C_USE_MUTUAL_EXCLUSION == TRUE */
+
+#endif /* HAL_USE_I2C == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_i2s.c b/ChibiOS_20.3.2/os/hal/src/hal_i2s.c
new file mode 100644
index 0000000..13bb13c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_i2s.c
@@ -0,0 +1,159 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_i2s.c
+ * @brief I2S Driver code.
+ *
+ * @addtogroup I2S
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_I2S == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief I2S Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void i2sInit(void) {
+
+ i2s_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p I2SDriver structure.
+ *
+ * @param[out] i2sp pointer to the @p I2SDriver object
+ *
+ * @init
+ */
+void i2sObjectInit(I2SDriver *i2sp) {
+
+ i2sp->state = I2S_STOP;
+ i2sp->config = NULL;
+}
+
+/**
+ * @brief Configures and activates the I2S peripheral.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ * @param[in] config pointer to the @p I2SConfig object
+ *
+ * @api
+ */
+void i2sStart(I2SDriver *i2sp, const I2SConfig *config) {
+
+ osalDbgCheck((i2sp != NULL) && (config != NULL));
+
+ osalSysLock();
+ osalDbgAssert((i2sp->state == I2S_STOP) || (i2sp->state == I2S_READY),
+ "invalid state");
+ i2sp->config = config;
+ i2s_lld_start(i2sp);
+ i2sp->state = I2S_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the I2S peripheral.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @api
+ */
+void i2sStop(I2SDriver *i2sp) {
+
+ osalDbgCheck(i2sp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((i2sp->state == I2S_STOP) || (i2sp->state == I2S_READY),
+ "invalid state");
+
+ i2s_lld_stop(i2sp);
+ i2sp->config = NULL;
+ i2sp->state = I2S_STOP;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Starts a I2S data exchange.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @api
+ */
+void i2sStartExchange(I2SDriver *i2sp) {
+
+ osalDbgCheck(i2sp != NULL);
+
+ osalSysLock();
+ osalDbgAssert(i2sp->state == I2S_READY, "not ready");
+ i2sStartExchangeI(i2sp);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Stops the ongoing data exchange.
+ * @details The ongoing data exchange, if any, is stopped, if the driver
+ * was not active the function does nothing.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @api
+ */
+void i2sStopExchange(I2SDriver *i2sp) {
+
+ osalDbgCheck((i2sp != NULL));
+
+ osalSysLock();
+ osalDbgAssert((i2sp->state == I2S_READY) ||
+ (i2sp->state == I2S_ACTIVE) ||
+ (i2sp->state == I2S_COMPLETE),
+ "invalid state");
+ i2sStopExchangeI(i2sp);
+ osalSysUnlock();
+}
+
+#endif /* HAL_USE_I2S == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_icu.c b/ChibiOS_20.3.2/os/hal/src/hal_icu.c
new file mode 100644
index 0000000..67f9955
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_icu.c
@@ -0,0 +1,231 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_icu.c
+ * @brief ICU Driver code.
+ *
+ * @addtogroup ICU
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_ICU == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief ICU Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void icuInit(void) {
+
+ icu_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p ICUDriver structure.
+ *
+ * @param[out] icup pointer to the @p ICUDriver object
+ *
+ * @init
+ */
+void icuObjectInit(ICUDriver *icup) {
+
+ icup->state = ICU_STOP;
+ icup->config = NULL;
+}
+
+/**
+ * @brief Configures and activates the ICU peripheral.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @param[in] config pointer to the @p ICUConfig object
+ *
+ * @api
+ */
+void icuStart(ICUDriver *icup, const ICUConfig *config) {
+
+ osalDbgCheck((icup != NULL) && (config != NULL));
+
+ osalSysLock();
+ osalDbgAssert((icup->state == ICU_STOP) || (icup->state == ICU_READY),
+ "invalid state");
+ icup->config = config;
+ icu_lld_start(icup);
+ icup->state = ICU_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the ICU peripheral.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @api
+ */
+void icuStop(ICUDriver *icup) {
+
+ osalDbgCheck(icup != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((icup->state == ICU_STOP) || (icup->state == ICU_READY),
+ "invalid state");
+
+ icu_lld_stop(icup);
+ icup->config = NULL;
+ icup->state = ICU_STOP;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Starts the input capture.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @api
+ */
+void icuStartCapture(ICUDriver *icup) {
+
+ osalDbgCheck(icup != NULL);
+
+ osalSysLock();
+ osalDbgAssert(icup->state == ICU_READY, "invalid state");
+ icuStartCaptureI(icup);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Waits for a completed capture.
+ * @note The operation could be performed in polled mode depending on.
+ * @note In order to use this function notifications must be disabled.
+ * @pre The driver must be in @p ICU_WAITING or @p ICU_ACTIVE states.
+ * @post After the capture is available the driver is in @p ICU_ACTIVE
+ * state. If a capture fails then the driver is in @p ICU_WAITING
+ * state.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @return The capture status.
+ * @retval false if the capture is successful.
+ * @retval true if a timer overflow occurred.
+ *
+ * @api
+ */
+bool icuWaitCapture(ICUDriver *icup) {
+ bool result;
+
+ osalDbgCheck(icup != NULL);
+
+ osalSysLock();
+ osalDbgAssert((icup->state == ICU_WAITING) || (icup->state == ICU_ACTIVE),
+ "invalid state");
+ osalDbgAssert(icuAreNotificationsEnabledX(icup) == false,
+ "notifications enabled");
+ result = icu_lld_wait_capture(icup);
+ icup->state = result ? ICU_WAITING : ICU_ACTIVE;
+ osalSysUnlock();
+
+ return result;
+}
+
+/**
+ * @brief Stops the input capture.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @api
+ */
+void icuStopCapture(ICUDriver *icup) {
+
+ osalDbgCheck(icup != NULL);
+
+ osalSysLock();
+ osalDbgAssert((icup->state == ICU_READY) || (icup->state == ICU_WAITING) ||
+ (icup->state == ICU_ACTIVE),
+ "invalid state");
+ icuStopCaptureI(icup);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Enables notifications.
+ * @pre The ICU unit must have been activated using @p icuStart() and the
+ * capture started using @p icuStartCapture().
+ * @note If the notification is already enabled then the call has no effect.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @api
+ */
+void icuEnableNotifications(ICUDriver *icup) {
+
+ osalDbgCheck(icup != NULL);
+
+ osalSysLock();
+ osalDbgAssert((icup->state == ICU_WAITING) || (icup->state == ICU_ACTIVE),
+ "invalid state");
+ icuEnableNotificationsI(icup);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Disables notifications.
+ * @pre The ICU unit must have been activated using @p icuStart() and the
+ * capture started using @p icuStartCapture().
+ * @note If the notification is already disabled then the call has no effect.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @api
+ */
+void icuDisableNotifications(ICUDriver *icup) {
+
+ osalDbgCheck(icup != NULL);
+
+ osalSysLock();
+ osalDbgAssert((icup->state == ICU_WAITING) || (icup->state == ICU_ACTIVE),
+ "invalid state");
+ icuDisableNotificationsI(icup);
+ osalSysUnlock();
+}
+
+#endif /* HAL_USE_ICU == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_mac.c b/ChibiOS_20.3.2/os/hal/src/hal_mac.c
new file mode 100644
index 0000000..e281360
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_mac.c
@@ -0,0 +1,264 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_mac.c
+ * @brief MAC Driver code.
+ *
+ * @addtogroup MAC
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_MAC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#if (MAC_USE_ZERO_COPY == TRUE) && (MAC_SUPPORTS_ZERO_COPY == FALSE)
+#error "MAC_USE_ZERO_COPY not supported by this implementation"
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief MAC Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void macInit(void) {
+
+ mac_lld_init();
+}
+
+/**
+ * @brief Initialize the standard part of a @p MACDriver structure.
+ *
+ * @param[out] macp pointer to the @p MACDriver object
+ *
+ * @init
+ */
+void macObjectInit(MACDriver *macp) {
+
+ macp->state = MAC_STOP;
+ macp->config = NULL;
+ osalThreadQueueObjectInit(&macp->tdqueue);
+ osalThreadQueueObjectInit(&macp->rdqueue);
+#if MAC_USE_EVENTS == TRUE
+ osalEventObjectInit(&macp->rdevent);
+#endif
+}
+
+/**
+ * @brief Configures and activates the MAC peripheral.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ * @param[in] config pointer to the @p MACConfig object
+ *
+ * @api
+ */
+void macStart(MACDriver *macp, const MACConfig *config) {
+
+ osalDbgCheck((macp != NULL) && (config != NULL));
+
+ osalSysLock();
+ osalDbgAssert(macp->state == MAC_STOP,
+ "invalid state");
+ macp->config = config;
+ mac_lld_start(macp);
+ macp->state = MAC_ACTIVE;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the MAC peripheral.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ *
+ * @api
+ */
+void macStop(MACDriver *macp) {
+
+ osalDbgCheck(macp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((macp->state == MAC_STOP) || (macp->state == MAC_ACTIVE),
+ "invalid state");
+
+ mac_lld_stop(macp);
+ macp->config = NULL;
+ macp->state = MAC_STOP;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Allocates a transmission descriptor.
+ * @details One of the available transmission descriptors is locked and
+ * returned. If a descriptor is not currently available then the
+ * invoking thread is queued until one is freed.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ * @param[out] tdp pointer to a @p MACTransmitDescriptor structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK the descriptor was obtained.
+ * @retval MSG_TIMEOUT the operation timed out, descriptor not initialized.
+ *
+ * @api
+ */
+msg_t macWaitTransmitDescriptor(MACDriver *macp,
+ MACTransmitDescriptor *tdp,
+ sysinterval_t timeout) {
+ msg_t msg;
+
+ osalDbgCheck((macp != NULL) && (tdp != NULL));
+ osalDbgAssert(macp->state == MAC_ACTIVE, "not active");
+
+ osalSysLock();
+
+ while ((msg = mac_lld_get_transmit_descriptor(macp, tdp)) != MSG_OK) {
+ msg = osalThreadEnqueueTimeoutS(&macp->tdqueue, timeout);
+ if (msg == MSG_TIMEOUT) {
+ break;
+ }
+ }
+
+ osalSysUnlock();
+
+ return msg;
+}
+
+/**
+ * @brief Releases a transmit descriptor and starts the transmission of the
+ * enqueued data as a single frame.
+ *
+ * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure
+ *
+ * @api
+ */
+void macReleaseTransmitDescriptor(MACTransmitDescriptor *tdp) {
+
+ osalDbgCheck(tdp != NULL);
+
+ mac_lld_release_transmit_descriptor(tdp);
+}
+
+/**
+ * @brief Waits for a received frame.
+ * @details Stops until a frame is received and buffered. If a frame is
+ * not immediately available then the invoking thread is queued
+ * until one is received.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ * @param[out] rdp pointer to a @p MACReceiveDescriptor structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK the descriptor was obtained.
+ * @retval MSG_TIMEOUT the operation timed out, descriptor not initialized.
+ *
+ * @api
+ */
+msg_t macWaitReceiveDescriptor(MACDriver *macp,
+ MACReceiveDescriptor *rdp,
+ sysinterval_t timeout) {
+ msg_t msg;
+
+ osalDbgCheck((macp != NULL) && (rdp != NULL));
+ osalDbgAssert(macp->state == MAC_ACTIVE, "not active");
+
+ osalSysLock();
+
+ while (((msg = mac_lld_get_receive_descriptor(macp, rdp)) != MSG_OK)) {
+ msg = osalThreadEnqueueTimeoutS(&macp->rdqueue, timeout);
+ if (msg == MSG_TIMEOUT) {
+ break;
+ }
+ }
+
+ osalSysUnlock();
+
+ return msg;
+}
+
+/**
+ * @brief Releases a receive descriptor.
+ * @details The descriptor and its buffer are made available for more incoming
+ * frames.
+ *
+ * @param[in] rdp the pointer to the @p MACReceiveDescriptor structure
+ *
+ * @api
+ */
+void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp) {
+
+ osalDbgCheck(rdp != NULL);
+
+ mac_lld_release_receive_descriptor(rdp);
+}
+
+/**
+ * @brief Updates and returns the link status.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ * @return The link status.
+ * @retval true if the link is active.
+ * @retval false if the link is down.
+ *
+ * @api
+ */
+bool macPollLinkStatus(MACDriver *macp) {
+
+ osalDbgCheck(macp != NULL);
+ osalDbgAssert(macp->state == MAC_ACTIVE, "not active");
+
+ return mac_lld_poll_link_status(macp);
+}
+
+#endif /* HAL_USE_MAC == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_mmc_spi.c b/ChibiOS_20.3.2/os/hal/src/hal_mmc_spi.c
new file mode 100644
index 0000000..ab2b8e7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_mmc_spi.c
@@ -0,0 +1,920 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Parts of this file have been contributed by Matthias Blaicher.
+ */
+
+/**
+ * @file hal_mmc_spi.c
+ * @brief MMC over SPI driver code.
+ *
+ * @addtogroup MMC_SPI
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+
+#if (HAL_USE_MMC_SPI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/* Forward declarations required by mmc_vmt.*/
+static bool mmc_read(void *instance, uint32_t startblk,
+ uint8_t *buffer, uint32_t n);
+static bool mmc_write(void *instance, uint32_t startblk,
+ const uint8_t *buffer, uint32_t n);
+
+/**
+ * @brief Virtual methods table.
+ */
+static const struct MMCDriverVMT mmc_vmt = {
+ (size_t)0,
+ (bool (*)(void *))mmc_lld_is_card_inserted,
+ (bool (*)(void *))mmc_lld_is_write_protected,
+ (bool (*)(void *))mmcConnect,
+ (bool (*)(void *))mmcDisconnect,
+ mmc_read,
+ mmc_write,
+ (bool (*)(void *))mmcSync,
+ (bool (*)(void *, BlockDeviceInfo *))mmcGetInfo
+};
+
+/**
+ * @brief Lookup table for CRC-7 ( based on polynomial x^7 + x^3 + 1).
+ */
+static const uint8_t crc7_lookup_table[256] = {
+ 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53,
+ 0x6c, 0x65, 0x7e, 0x77, 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26,
+ 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e, 0x32, 0x3b, 0x20, 0x29,
+ 0x16, 0x1f, 0x04, 0x0d, 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45,
+ 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14, 0x63, 0x6a, 0x71, 0x78,
+ 0x47, 0x4e, 0x55, 0x5c, 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b,
+ 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13, 0x7d, 0x74, 0x6f, 0x66,
+ 0x59, 0x50, 0x4b, 0x42, 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a,
+ 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, 0x1e, 0x17, 0x0c, 0x05,
+ 0x3a, 0x33, 0x28, 0x21, 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70,
+ 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38, 0x41, 0x48, 0x53, 0x5a,
+ 0x65, 0x6c, 0x77, 0x7e, 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36,
+ 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67, 0x10, 0x19, 0x02, 0x0b,
+ 0x34, 0x3d, 0x26, 0x2f, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
+ 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x6a, 0x63, 0x78, 0x71,
+ 0x4e, 0x47, 0x5c, 0x55, 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d,
+ 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a, 0x6d, 0x64, 0x7f, 0x76,
+ 0x49, 0x40, 0x5b, 0x52, 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03,
+ 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b, 0x17, 0x1e, 0x05, 0x0c,
+ 0x33, 0x3a, 0x21, 0x28, 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60,
+ 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31, 0x46, 0x4f, 0x54, 0x5d,
+ 0x62, 0x6b, 0x70, 0x79
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static bool mmc_read(void *instance, uint32_t startblk,
+ uint8_t *buffer, uint32_t n) {
+
+ if (mmcStartSequentialRead((MMCDriver *)instance, startblk)) {
+ return HAL_FAILED;
+ }
+
+ while (n > 0U) {
+ if (mmcSequentialRead((MMCDriver *)instance, buffer)) {
+ return HAL_FAILED;
+ }
+ buffer += MMCSD_BLOCK_SIZE;
+ n--;
+ }
+
+ if (mmcStopSequentialRead((MMCDriver *)instance)) {
+ return HAL_FAILED;
+ }
+ return HAL_SUCCESS;
+}
+
+static bool mmc_write(void *instance, uint32_t startblk,
+ const uint8_t *buffer, uint32_t n) {
+
+ if (mmcStartSequentialWrite((MMCDriver *)instance, startblk)) {
+ return HAL_FAILED;
+ }
+
+ while (n > 0U) {
+ if (mmcSequentialWrite((MMCDriver *)instance, buffer)) {
+ return HAL_FAILED;
+ }
+ buffer += MMCSD_BLOCK_SIZE;
+ n--;
+ }
+
+ if (mmcStopSequentialWrite((MMCDriver *)instance)) {
+ return HAL_FAILED;
+ }
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Calculate the MMC standard CRC-7 based on a lookup table.
+ *
+ * @param[in] crc start value for CRC
+ * @param[in] buffer pointer to data buffer
+ * @param[in] len length of data
+ * @return Calculated CRC
+ */
+static uint8_t crc7(uint8_t crc, const uint8_t *buffer, size_t len) {
+
+ while (len > 0U) {
+ crc = crc7_lookup_table[(crc << 1) ^ (*buffer++)];
+ len--;
+ }
+ return crc;
+}
+
+/**
+ * @brief Waits an idle condition.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ *
+ * @notapi
+ */
+static void wait(MMCDriver *mmcp) {
+ int i;
+ uint8_t buf[4];
+
+ for (i = 0; i < 16; i++) {
+ spiReceive(mmcp->config->spip, 1, buf);
+ if (buf[0] == 0xFFU) {
+ return;
+ }
+ }
+ /* Looks like it is a long wait.*/
+ while (true) {
+ spiReceive(mmcp->config->spip, 1, buf);
+ if (buf[0] == 0xFFU) {
+ break;
+ }
+#if MMC_NICE_WAITING == TRUE
+ /* Trying to be nice with the other threads.*/
+ osalThreadSleepMilliseconds(1);
+#endif
+ }
+}
+
+/**
+ * @brief Sends a command header.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ * @param[in] cmd the command id
+ * @param[in] arg the command argument
+ *
+ * @notapi
+ */
+static void send_hdr(MMCDriver *mmcp, uint8_t cmd, uint32_t arg) {
+ uint8_t buf[6];
+
+ /* Wait for the bus to become idle if a write operation was in progress.*/
+ wait(mmcp);
+
+ buf[0] = (uint8_t)0x40U | cmd;
+ buf[1] = (uint8_t)(arg >> 24U);
+ buf[2] = (uint8_t)(arg >> 16U);
+ buf[3] = (uint8_t)(arg >> 8U);
+ buf[4] = (uint8_t)arg;
+ /* Calculate CRC for command header, shift to right position, add stop bit.*/
+ buf[5] = ((crc7(0, buf, 5U) & 0x7FU) << 1U) | 0x01U;
+
+ spiSend(mmcp->config->spip, 6, buf);
+}
+
+/**
+ * @brief Receives a single byte response.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ * @return The response as an @p uint8_t value.
+ * @retval 0xFF timed out.
+ *
+ * @notapi
+ */
+static uint8_t recvr1(MMCDriver *mmcp) {
+ int i;
+ uint8_t r1[1];
+
+ for (i = 0; i < 9; i++) {
+ spiReceive(mmcp->config->spip, 1, r1);
+ if (r1[0] != 0xFFU) {
+ return r1[0];
+ }
+ }
+ return 0xFFU;
+}
+
+/**
+ * @brief Receives a three byte response.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ * @param[out] buffer pointer to four bytes wide buffer
+ * @return First response byte as an @p uint8_t value.
+ * @retval 0xFF timed out.
+ *
+ * @notapi
+ */
+static uint8_t recvr3(MMCDriver *mmcp, uint8_t* buffer) {
+ uint8_t r1;
+
+ r1 = recvr1(mmcp);
+ spiReceive(mmcp->config->spip, 4, buffer);
+
+ return r1;
+}
+
+/**
+ * @brief Sends a command an returns a single byte response.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ * @param[in] cmd the command id
+ * @param[in] arg the command argument
+ * @return The response as an @p uint8_t value.
+ * @retval 0xFF timed out.
+ *
+ * @notapi
+ */
+static uint8_t send_command_R1(MMCDriver *mmcp, uint8_t cmd, uint32_t arg) {
+ uint8_t r1;
+
+ spiSelect(mmcp->config->spip);
+ send_hdr(mmcp, cmd, arg);
+ r1 = recvr1(mmcp);
+ spiUnselect(mmcp->config->spip);
+ return r1;
+}
+
+/**
+ * @brief Sends a command which returns a five bytes response (R3).
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ * @param[in] cmd the command id
+ * @param[in] arg the command argument
+ * @param[out] response pointer to four bytes wide uint8_t buffer
+ * @return The first byte of the response (R1) as an @p
+ * uint8_t value.
+ * @retval 0xFF timed out.
+ *
+ * @notapi
+ */
+static uint8_t send_command_R3(MMCDriver *mmcp, uint8_t cmd, uint32_t arg,
+ uint8_t *response) {
+ uint8_t r1;
+
+ spiSelect(mmcp->config->spip);
+ send_hdr(mmcp, cmd, arg);
+ r1 = recvr3(mmcp, response);
+ spiUnselect(mmcp->config->spip);
+ return r1;
+}
+
+/**
+ * @brief Reads the CSD.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ * @param[out] cmd command
+ * @param[out] cxd pointer to the CSD/CID buffer
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS the operation succeeded.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @notapi
+ */
+static bool read_CxD(MMCDriver *mmcp, uint8_t cmd, uint32_t cxd[4]) {
+ unsigned i;
+ uint8_t *bp, buf[16];
+
+ spiSelect(mmcp->config->spip);
+ send_hdr(mmcp, cmd, 0);
+ if (recvr1(mmcp) != 0x00U) {
+ spiUnselect(mmcp->config->spip);
+ return HAL_FAILED;
+ }
+
+ /* Wait for data availability.*/
+ for (i = 0U; i < MMC_WAIT_DATA; i++) {
+ spiReceive(mmcp->config->spip, 1, buf);
+ if (buf[0] == 0xFEU) {
+ uint32_t *wp;
+
+ spiReceive(mmcp->config->spip, 16, buf);
+ bp = buf;
+ for (wp = &cxd[3]; wp >= cxd; wp--) {
+ *wp = ((uint32_t)bp[0] << 24U) | ((uint32_t)bp[1] << 16U) |
+ ((uint32_t)bp[2] << 8U) | (uint32_t)bp[3];
+ bp += 4;
+ }
+
+ /* CRC ignored then end of transaction. */
+ spiIgnore(mmcp->config->spip, 2);
+ spiUnselect(mmcp->config->spip);
+
+ return HAL_SUCCESS;
+ }
+ }
+ return HAL_FAILED;
+}
+
+/**
+ * @brief Waits that the card reaches an idle state.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ *
+ * @notapi
+ */
+static void sync(MMCDriver *mmcp) {
+ uint8_t buf[1];
+
+ spiSelect(mmcp->config->spip);
+ while (true) {
+ spiReceive(mmcp->config->spip, 1, buf);
+ if (buf[0] == 0xFFU) {
+ break;
+ }
+#if MMC_NICE_WAITING == TRUE
+ /* Trying to be nice with the other threads.*/
+ osalThreadSleepMilliseconds(1);
+#endif
+ }
+ spiUnselect(mmcp->config->spip);
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief MMC over SPI driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void mmcInit(void) {
+
+}
+
+/**
+ * @brief Initializes an instance.
+ *
+ * @param[out] mmcp pointer to the @p MMCDriver object
+ *
+ * @init
+ */
+void mmcObjectInit(MMCDriver *mmcp) {
+
+ mmcp->vmt = &mmc_vmt;
+ mmcp->state = BLK_STOP;
+ mmcp->config = NULL;
+ mmcp->block_addresses = false;
+}
+
+/**
+ * @brief Configures and activates the MMC peripheral.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ * @param[in] config pointer to the @p MMCConfig object.
+ *
+ * @api
+ */
+void mmcStart(MMCDriver *mmcp, const MMCConfig *config) {
+
+ osalDbgCheck((mmcp != NULL) && (config != NULL));
+ osalDbgAssert((mmcp->state == BLK_STOP) || (mmcp->state == BLK_ACTIVE),
+ "invalid state");
+
+ mmcp->config = config;
+ mmcp->state = BLK_ACTIVE;
+}
+
+/**
+ * @brief Disables the MMC peripheral.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ *
+ * @api
+ */
+void mmcStop(MMCDriver *mmcp) {
+
+ osalDbgCheck(mmcp != NULL);
+ osalDbgAssert((mmcp->state == BLK_STOP) || (mmcp->state == BLK_ACTIVE),
+ "invalid state");
+
+ spiStop(mmcp->config->spip);
+ mmcp->config = NULL;
+ mmcp->state = BLK_STOP;
+}
+
+/**
+ * @brief Performs the initialization procedure on the inserted card.
+ * @details This function should be invoked when a card is inserted and
+ * brings the driver in the @p MMC_READY state where it is possible
+ * to perform read and write operations.
+ * @note It is possible to invoke this function from the insertion event
+ * handler.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS the operation succeeded and the driver is now
+ * in the @p MMC_READY state.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @api
+ */
+bool mmcConnect(MMCDriver *mmcp) {
+ unsigned i;
+ uint8_t r3[4];
+
+ osalDbgCheck(mmcp != NULL);
+
+ osalDbgAssert((mmcp->state == BLK_ACTIVE) || (mmcp->state == BLK_READY),
+ "invalid state");
+
+ /* Connection procedure in progress.*/
+ mmcp->state = BLK_CONNECTING;
+ mmcp->block_addresses = false;
+
+ /* Slow clock mode and 128 clock pulses.*/
+ spiStart(mmcp->config->spip, mmcp->config->lscfg);
+ spiIgnore(mmcp->config->spip, 16);
+
+ /* SPI mode selection.*/
+ i = 0;
+ while (true) {
+ if (send_command_R1(mmcp, MMCSD_CMD_GO_IDLE_STATE, 0) == 0x01U) {
+ break;
+ }
+ if (++i >= MMC_CMD0_RETRY) {
+ goto failed;
+ }
+ osalThreadSleepMilliseconds(10);
+ }
+
+ /* Try to detect if this is a high capacity card and switch to block
+ addresses if possible.
+ This method is based on "How to support SDC Ver2 and high capacity cards"
+ by ElmChan.*/
+ if (send_command_R3(mmcp, MMCSD_CMD_SEND_IF_COND,
+ MMCSD_CMD8_PATTERN, r3) != 0x05U) {
+
+ /* Switch to SDHC mode.*/
+ i = 0;
+ while (true) {
+ /*lint -save -e9007 [13.5] Side effect unimportant.*/
+ if ((send_command_R1(mmcp, MMCSD_CMD_APP_CMD, 0) <= 0x01U) &&
+ (send_command_R3(mmcp, MMCSD_CMD_APP_OP_COND, 0x400001AAU, r3) == 0x00U)) {
+ /*lint -restore*/
+ break;
+ }
+
+ if (++i >= MMC_ACMD41_RETRY) {
+ goto failed;
+ }
+ osalThreadSleepMilliseconds(10);
+ }
+
+ /* Execute dedicated read on OCR register */
+ (void) send_command_R3(mmcp, MMCSD_CMD_READ_OCR, 0, r3);
+
+ /* Check if CCS is set in response. Card operates in block mode if set.*/
+ if ((r3[0] & 0x40U) != 0U) {
+ mmcp->block_addresses = true;
+ }
+ }
+
+ /* Initialization.*/
+ i = 0;
+ while (true) {
+ uint8_t b = send_command_R1(mmcp, MMCSD_CMD_INIT, 0);
+ if (b == 0x00U) {
+ break;
+ }
+ if (b != 0x01U) {
+ goto failed;
+ }
+ if (++i >= MMC_CMD1_RETRY) {
+ goto failed;
+ }
+ osalThreadSleepMilliseconds(10);
+ }
+
+ /* Initialization complete, full speed.*/
+ spiStart(mmcp->config->spip, mmcp->config->hscfg);
+
+ /* Setting block size.*/
+ if (send_command_R1(mmcp, MMCSD_CMD_SET_BLOCKLEN,
+ MMCSD_BLOCK_SIZE) != 0x00U) {
+ goto failed;
+ }
+
+ /* Determine capacity.*/
+ if (read_CxD(mmcp, MMCSD_CMD_SEND_CSD, mmcp->csd)) {
+ goto failed;
+ }
+
+ mmcp->capacity = _mmcsd_get_capacity(mmcp->csd);
+ if (mmcp->capacity == 0U) {
+ goto failed;
+ }
+
+ if (read_CxD(mmcp, MMCSD_CMD_SEND_CID, mmcp->cid)) {
+ goto failed;
+ }
+
+ mmcp->state = BLK_READY;
+ return HAL_SUCCESS;
+
+ /* Connection failed, state reset to BLK_ACTIVE.*/
+failed:
+ spiStop(mmcp->config->spip);
+ mmcp->state = BLK_ACTIVE;
+ return HAL_FAILED;
+}
+
+/**
+ * @brief Brings the driver in a state safe for card removal.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ * @return The operation status.
+ *
+ * @retval HAL_SUCCESS the operation succeeded and the driver is now
+ * in the @p MMC_INSERTED state.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @api
+ */
+bool mmcDisconnect(MMCDriver *mmcp) {
+
+ osalDbgCheck(mmcp != NULL);
+
+ osalSysLock();
+ osalDbgAssert((mmcp->state == BLK_ACTIVE) || (mmcp->state == BLK_READY),
+ "invalid state");
+ if (mmcp->state == BLK_ACTIVE) {
+ osalSysUnlock();
+ return HAL_SUCCESS;
+ }
+ mmcp->state = BLK_DISCONNECTING;
+ osalSysUnlock();
+
+ /* Wait for the pending write operations to complete.*/
+ spiStart(mmcp->config->spip, mmcp->config->hscfg);
+ sync(mmcp);
+
+ spiStop(mmcp->config->spip);
+ mmcp->state = BLK_ACTIVE;
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Starts a sequential read.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ * @param[in] startblk first block to read
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS the operation succeeded.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @api
+ */
+bool mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk) {
+
+ osalDbgCheck(mmcp != NULL);
+ osalDbgAssert(mmcp->state == BLK_READY, "invalid state");
+
+ /* Read operation in progress.*/
+ mmcp->state = BLK_READING;
+
+ /* (Re)starting the SPI in case it has been reprogrammed externally, it can
+ happen if the SPI bus is shared among multiple peripherals.*/
+ spiStart(mmcp->config->spip, mmcp->config->hscfg);
+ spiSelect(mmcp->config->spip);
+
+ if (mmcp->block_addresses) {
+ send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk);
+ }
+ else {
+ send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk * MMCSD_BLOCK_SIZE);
+ }
+
+ if (recvr1(mmcp) != 0x00U) {
+ spiStop(mmcp->config->spip);
+ mmcp->state = BLK_READY;
+ return HAL_FAILED;
+ }
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Reads a block within a sequential read operation.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ * @param[out] buffer pointer to the read buffer
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS the operation succeeded.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @api
+ */
+bool mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer) {
+ unsigned i;
+
+ osalDbgCheck((mmcp != NULL) && (buffer != NULL));
+
+ if (mmcp->state != BLK_READING) {
+ return HAL_FAILED;
+ }
+
+ for (i = 0; i < MMC_WAIT_DATA; i++) {
+ spiReceive(mmcp->config->spip, 1, buffer);
+ if (buffer[0] == 0xFEU) {
+ spiReceive(mmcp->config->spip, MMCSD_BLOCK_SIZE, buffer);
+ /* CRC ignored. */
+ spiIgnore(mmcp->config->spip, 2);
+ return HAL_SUCCESS;
+ }
+ }
+ /* Timeout.*/
+ spiUnselect(mmcp->config->spip);
+ spiStop(mmcp->config->spip);
+ mmcp->state = BLK_READY;
+ return HAL_FAILED;
+}
+
+/**
+ * @brief Stops a sequential read gracefully.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS the operation succeeded.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @api
+ */
+bool mmcStopSequentialRead(MMCDriver *mmcp) {
+ static const uint8_t stopcmd[] = {
+ (uint8_t)(0x40U | MMCSD_CMD_STOP_TRANSMISSION), 0, 0, 0, 0, 1, 0xFF
+ };
+
+ osalDbgCheck(mmcp != NULL);
+
+ if (mmcp->state != BLK_READING) {
+ return HAL_FAILED;
+ }
+
+ spiSend(mmcp->config->spip, sizeof(stopcmd), stopcmd);
+/* result = recvr1(mmcp) != 0x00U;*/
+ /* Note, ignored r1 response, it can be not zero, unknown issue.*/
+ (void) recvr1(mmcp);
+
+ /* Read operation finished.*/
+ spiUnselect(mmcp->config->spip);
+ mmcp->state = BLK_READY;
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Starts a sequential write.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ * @param[in] startblk first block to write
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS the operation succeeded.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @api
+ */
+bool mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk) {
+
+ osalDbgCheck(mmcp != NULL);
+ osalDbgAssert(mmcp->state == BLK_READY, "invalid state");
+
+ /* Write operation in progress.*/
+ mmcp->state = BLK_WRITING;
+
+ spiStart(mmcp->config->spip, mmcp->config->hscfg);
+ spiSelect(mmcp->config->spip);
+ if (mmcp->block_addresses) {
+ send_hdr(mmcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, startblk);
+ }
+ else {
+ send_hdr(mmcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK,
+ startblk * MMCSD_BLOCK_SIZE);
+ }
+
+ if (recvr1(mmcp) != 0x00U) {
+ spiStop(mmcp->config->spip);
+ mmcp->state = BLK_READY;
+ return HAL_FAILED;
+ }
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Writes a block within a sequential write operation.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ * @param[out] buffer pointer to the write buffer
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS the operation succeeded.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @api
+ */
+bool mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer) {
+ static const uint8_t start[] = {0xFF, 0xFC};
+ uint8_t b[1];
+
+ osalDbgCheck((mmcp != NULL) && (buffer != NULL));
+
+ if (mmcp->state != BLK_WRITING) {
+ return HAL_FAILED;
+ }
+
+ spiSend(mmcp->config->spip, sizeof(start), start); /* Data prologue. */
+ spiSend(mmcp->config->spip, MMCSD_BLOCK_SIZE, buffer);/* Data. */
+ spiIgnore(mmcp->config->spip, 2); /* CRC ignored. */
+ spiReceive(mmcp->config->spip, 1, b);
+ if ((b[0] & 0x1FU) == 0x05U) {
+ wait(mmcp);
+ return HAL_SUCCESS;
+ }
+
+ /* Error.*/
+ spiUnselect(mmcp->config->spip);
+ spiStop(mmcp->config->spip);
+ mmcp->state = BLK_READY;
+ return HAL_FAILED;
+}
+
+/**
+ * @brief Stops a sequential write gracefully.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS the operation succeeded.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @api
+ */
+bool mmcStopSequentialWrite(MMCDriver *mmcp) {
+ static const uint8_t stop[] = {0xFD, 0xFF};
+
+ osalDbgCheck(mmcp != NULL);
+
+ if (mmcp->state != BLK_WRITING) {
+ return HAL_FAILED;
+ }
+
+ spiSend(mmcp->config->spip, sizeof(stop), stop);
+ spiUnselect(mmcp->config->spip);
+
+ /* Write operation finished.*/
+ mmcp->state = BLK_READY;
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Waits for card idle condition.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS the operation succeeded.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @api
+ */
+bool mmcSync(MMCDriver *mmcp) {
+
+ osalDbgCheck(mmcp != NULL);
+
+ if (mmcp->state != BLK_READY) {
+ return HAL_FAILED;
+ }
+
+ /* Synchronization operation in progress.*/
+ mmcp->state = BLK_SYNCING;
+
+ spiStart(mmcp->config->spip, mmcp->config->hscfg);
+ sync(mmcp);
+
+ /* Synchronization operation finished.*/
+ mmcp->state = BLK_READY;
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Returns the media info.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ * @param[out] bdip pointer to a @p BlockDeviceInfo structure
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS the operation succeeded.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @api
+ */
+bool mmcGetInfo(MMCDriver *mmcp, BlockDeviceInfo *bdip) {
+
+ osalDbgCheck((mmcp != NULL) && (bdip != NULL));
+
+ if (mmcp->state != BLK_READY) {
+ return HAL_FAILED;
+ }
+
+ bdip->blk_num = mmcp->capacity;
+ bdip->blk_size = MMCSD_BLOCK_SIZE;
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Erases blocks.
+ *
+ * @param[in] mmcp pointer to the @p MMCDriver object
+ * @param[in] startblk starting block number
+ * @param[in] endblk ending block number
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS the operation succeeded.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @api
+ */
+bool mmcErase(MMCDriver *mmcp, uint32_t startblk, uint32_t endblk) {
+
+ osalDbgCheck((mmcp != NULL));
+
+ /* Erase operation in progress.*/
+ mmcp->state = BLK_WRITING;
+
+ /* Handling command differences between HC and normal cards.*/
+ if (!mmcp->block_addresses) {
+ startblk *= MMCSD_BLOCK_SIZE;
+ endblk *= MMCSD_BLOCK_SIZE;
+ }
+
+ if (send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_START, startblk) != 0x00U) {
+ goto failed;
+ }
+
+ if (send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_END, endblk) != 0x00U) {
+ goto failed;
+ }
+
+ if (send_command_R1(mmcp, MMCSD_CMD_ERASE, 0) != 0x00U) {
+ goto failed;
+ }
+
+ mmcp->state = BLK_READY;
+ return HAL_SUCCESS;
+
+ /* Command failed, state reset to BLK_ACTIVE.*/
+failed:
+ spiStop(mmcp->config->spip);
+ mmcp->state = BLK_READY;
+ return HAL_FAILED;
+}
+
+#endif /* HAL_USE_MMC_SPI == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_mmcsd.c b/ChibiOS_20.3.2/os/hal/src/hal_mmcsd.c
new file mode 100644
index 0000000..6c19064
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_mmcsd.c
@@ -0,0 +1,331 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_mmcsd.c
+ * @brief MMC/SD cards common code.
+ *
+ * @addtogroup MMCSD
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_MMC_SPI == TRUE) || (HAL_USE_SDC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Gets a bit field from a words array.
+ * @note The bit zero is the LSb of the first word.
+ *
+ * @param[in] data pointer to the words array
+ * @param[in] end bit offset of the last bit of the field, inclusive
+ * @param[in] start bit offset of the first bit of the field, inclusive
+ *
+ * @return The bits field value, left aligned.
+ *
+ * @notapi
+ */
+uint32_t _mmcsd_get_slice(const uint32_t *data,
+ uint32_t end,
+ uint32_t start) {
+ unsigned startidx, endidx, startoff;
+ uint32_t endmask;
+
+ osalDbgCheck((end >= start) && ((end - start) < 32U));
+
+ startidx = start / 32U;
+ startoff = start % 32U;
+ endidx = end / 32U;
+ endmask = ((uint32_t)1U << ((end % 32U) + 1U)) - 1U;
+
+ /* One or two pieces?*/
+ if (startidx < endidx) {
+ return (data[startidx] >> startoff) | /* Two pieces case. */
+ ((data[endidx] & endmask) << (32U - startoff));
+ }
+ return (data[startidx] & endmask) >> startoff; /* One piece case. */
+}
+
+/**
+ * @brief Extract card capacity from a CSD.
+ * @details The capacity is returned as number of available blocks.
+ *
+ * @param[in] csd the CSD record
+ *
+ * @return The card capacity.
+ * @retval 0 CSD format error
+ *
+ * @notapi
+ */
+uint32_t _mmcsd_get_capacity(const uint32_t *csd) {
+ uint32_t a, b, c;
+
+ osalDbgCheck(NULL != csd);
+
+ switch (_mmcsd_get_slice(csd, MMCSD_CSD_10_CSD_STRUCTURE_SLICE)) {
+ case 0:
+ /* CSD version 1.0 */
+ a = _mmcsd_get_slice(csd, MMCSD_CSD_10_C_SIZE_SLICE);
+ b = _mmcsd_get_slice(csd, MMCSD_CSD_10_C_SIZE_MULT_SLICE);
+ c = _mmcsd_get_slice(csd, MMCSD_CSD_10_READ_BL_LEN_SLICE);
+ return ((a + 1U) << (b + 2U)) << (c - 9U); /* 2^9 == MMCSD_BLOCK_SIZE. */
+ case 1:
+ /* CSD version 2.0.*/
+ return 1024U * (_mmcsd_get_slice(csd, MMCSD_CSD_20_C_SIZE_SLICE) + 1U);
+ default:
+ /* Reserved value detected.*/
+ break;
+ }
+ return 0U;
+}
+
+/**
+ * @brief Extract MMC card capacity from EXT_CSD.
+ * @details The capacity is returned as number of available blocks.
+ *
+ * @param[in] ext_csd the extended CSD record
+ *
+ * @return The card capacity.
+ *
+ * @notapi
+ */
+uint32_t _mmcsd_get_capacity_ext(const uint8_t *ext_csd) {
+
+ osalDbgCheck(NULL != ext_csd);
+
+ return ((uint32_t)ext_csd[215] << 24U) +
+ ((uint32_t)ext_csd[214] << 16U) +
+ ((uint32_t)ext_csd[213] << 8U) +
+ (uint32_t)ext_csd[212];
+}
+
+/**
+ * @brief Unpacks SDC CID array in structure.
+ *
+ * @param[in] sdcp pointer to the @p MMCSDBlockDevice object
+ * @param[out] cidsdc pointer to the @p unpacked_sdc_cid_t object
+ *
+ * @notapi
+ */
+void _mmcsd_unpack_sdc_cid(const MMCSDBlockDevice *sdcp,
+ unpacked_sdc_cid_t *cidsdc) {
+ const uint32_t *cid;
+
+ osalDbgCheck((NULL != sdcp) && (NULL != cidsdc));
+
+ cid = sdcp->cid;
+ cidsdc->crc = (uint8_t) _mmcsd_get_slice(cid, MMCSD_CID_SDC_CRC_SLICE);
+ cidsdc->mdt_y = (uint16_t)_mmcsd_get_slice(cid, MMCSD_CID_SDC_MDT_Y_SLICE) +
+ 2000U;
+ cidsdc->mdt_m = (uint8_t) _mmcsd_get_slice(cid, MMCSD_CID_SDC_MDT_M_SLICE);
+ cidsdc->mid = (uint8_t) _mmcsd_get_slice(cid, MMCSD_CID_SDC_MID_SLICE);
+ cidsdc->oid = (uint16_t)_mmcsd_get_slice(cid, MMCSD_CID_SDC_OID_SLICE);
+ cidsdc->pnm[4] = (char) _mmcsd_get_slice(cid, MMCSD_CID_SDC_PNM0_SLICE);
+ cidsdc->pnm[3] = (char) _mmcsd_get_slice(cid, MMCSD_CID_SDC_PNM1_SLICE);
+ cidsdc->pnm[2] = (char) _mmcsd_get_slice(cid, MMCSD_CID_SDC_PNM2_SLICE);
+ cidsdc->pnm[1] = (char) _mmcsd_get_slice(cid, MMCSD_CID_SDC_PNM3_SLICE);
+ cidsdc->pnm[0] = (char) _mmcsd_get_slice(cid, MMCSD_CID_SDC_PNM4_SLICE);
+ cidsdc->prv_n = (uint8_t) _mmcsd_get_slice(cid, MMCSD_CID_SDC_PRV_N_SLICE);
+ cidsdc->prv_m = (uint8_t) _mmcsd_get_slice(cid, MMCSD_CID_SDC_PRV_M_SLICE);
+ cidsdc->psn = _mmcsd_get_slice(cid, MMCSD_CID_SDC_PSN_SLICE);
+}
+
+/**
+ * @brief Unpacks MMC CID array in structure.
+ *
+ * @param[in] sdcp pointer to the @p MMCSDBlockDevice object
+ * @param[out] cidmmc pointer to the @p unpacked_mmc_cid_t object
+ *
+ * @notapi
+ */
+void _mmcsd_unpack_mmc_cid(const MMCSDBlockDevice *sdcp,
+ unpacked_mmc_cid_t *cidmmc) {
+ const uint32_t *cid;
+
+ osalDbgCheck((NULL != sdcp) && (NULL != cidmmc));
+
+ cid = sdcp->cid;
+ cidmmc->crc = (uint8_t) _mmcsd_get_slice(cid, MMCSD_CID_MMC_CRC_SLICE);
+ cidmmc->mdt_y = (uint16_t)_mmcsd_get_slice(cid, MMCSD_CID_MMC_MDT_Y_SLICE) +
+ 1997U;
+ cidmmc->mdt_m = (uint8_t) _mmcsd_get_slice(cid, MMCSD_CID_MMC_MDT_M_SLICE);
+ cidmmc->mid = (uint8_t) _mmcsd_get_slice(cid, MMCSD_CID_MMC_MID_SLICE);
+ cidmmc->oid = (uint16_t)_mmcsd_get_slice(cid, MMCSD_CID_MMC_OID_SLICE);
+ cidmmc->pnm[5] = (char) _mmcsd_get_slice(cid, MMCSD_CID_MMC_PNM0_SLICE);
+ cidmmc->pnm[4] = (char) _mmcsd_get_slice(cid, MMCSD_CID_MMC_PNM1_SLICE);
+ cidmmc->pnm[3] = (char) _mmcsd_get_slice(cid, MMCSD_CID_MMC_PNM2_SLICE);
+ cidmmc->pnm[2] = (char) _mmcsd_get_slice(cid, MMCSD_CID_MMC_PNM3_SLICE);
+ cidmmc->pnm[1] = (char) _mmcsd_get_slice(cid, MMCSD_CID_MMC_PNM4_SLICE);
+ cidmmc->pnm[0] = (char) _mmcsd_get_slice(cid, MMCSD_CID_MMC_PNM5_SLICE);
+ cidmmc->prv_n = (uint8_t) _mmcsd_get_slice(cid, MMCSD_CID_MMC_PRV_N_SLICE);
+ cidmmc->prv_m = (uint8_t) _mmcsd_get_slice(cid, MMCSD_CID_MMC_PRV_M_SLICE);
+ cidmmc->psn = _mmcsd_get_slice(cid, MMCSD_CID_MMC_PSN_SLICE);
+}
+
+/**
+ * @brief Unpacks MMC CSD array in structure.
+ *
+ * @param[in] sdcp pointer to the @p MMCSDBlockDevice object
+ * @param[out] csdmmc pointer to the @p unpacked_mmc_csd_t object
+ *
+ * @notapi
+ */
+void _mmcsd_unpack_csd_mmc(const MMCSDBlockDevice *sdcp,
+ unpacked_mmc_csd_t *csdmmc) {
+ const uint32_t *csd;
+
+ osalDbgCheck((NULL != sdcp) && (NULL != csdmmc));
+
+ csd = sdcp->csd;
+ csdmmc->c_size = (uint16_t)_mmcsd_get_slice(csd, MMCSD_CSD_MMC_C_SIZE_SLICE);
+ csdmmc->c_size_mult = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_C_SIZE_MULT_SLICE);
+ csdmmc->ccc = (uint16_t)_mmcsd_get_slice(csd, MMCSD_CSD_MMC_CCC_SLICE);
+ csdmmc->copy = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_COPY_SLICE);
+ csdmmc->crc = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_CRC_SLICE);
+ csdmmc->csd_structure = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_CSD_STRUCTURE_SLICE);
+ csdmmc->dsr_imp = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_DSR_IMP_SLICE);
+ csdmmc->ecc = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_ECC_SLICE);
+ csdmmc->erase_grp_mult = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_ERASE_GRP_MULT_SLICE);
+ csdmmc->erase_grp_size = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_ERASE_GRP_SIZE_SLICE);
+ csdmmc->file_format = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_FILE_FORMAT_SLICE);
+ csdmmc->file_format_grp = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_FILE_FORMAT_GRP_SLICE);
+ csdmmc->nsac = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_NSAC_SLICE);
+ csdmmc->perm_write_protect = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_PERM_WRITE_PROTECT_SLICE);
+ csdmmc->r2w_factor = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_R2W_FACTOR_SLICE);
+ csdmmc->read_bl_len = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_READ_BL_LEN_SLICE);
+ csdmmc->read_bl_partial = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_READ_BL_PARTIAL_SLICE);
+ csdmmc->read_blk_misalign = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_READ_BLK_MISALIGN_SLICE);
+ csdmmc->spec_vers = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_SPEC_VERS_SLICE);
+ csdmmc->taac = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_TAAC_SLICE);
+ csdmmc->tmp_write_protect = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_TMP_WRITE_PROTECT_SLICE);
+ csdmmc->tran_speed = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_TRAN_SPEED_SLICE);
+ csdmmc->vdd_r_curr_max = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_VDD_R_CURR_MAX_SLICE);
+ csdmmc->vdd_r_curr_min = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_VDD_R_CURR_MIN_SLICE);
+ csdmmc->vdd_w_curr_max = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_VDD_W_CURR_MAX_SLICE);
+ csdmmc->vdd_w_curr_min = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_VDD_W_CURR_MIN_SLICE);
+ csdmmc->wp_grp_enable = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_WP_GRP_ENABLE_SLICE);
+ csdmmc->wp_grp_size = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_WP_GRP_SIZE_SLICE);
+ csdmmc->write_bl_len = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_WRITE_BL_LEN_SLICE);
+ csdmmc->write_bl_partial = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_WRITE_BL_PARTIAL_SLICE);
+ csdmmc->write_blk_misalign = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_MMC_WRITE_BLK_MISALIGN_SLICE);
+}
+
+/**
+ * @brief Unpacks SDC CSD v1.0 array in structure.
+ *
+ * @param[in] sdcp pointer to the @p MMCSDBlockDevice object
+ * @param[out] csd10 pointer to the @p unpacked_sdc_csd_10_t object
+ *
+ * @notapi
+ */
+void _mmcsd_unpack_csd_v10(const MMCSDBlockDevice *sdcp,
+ unpacked_sdc_csd_10_t *csd10) {
+ const uint32_t *csd;
+
+ osalDbgCheck(NULL != sdcp);
+
+ csd = sdcp->csd;
+ csd10->c_size = (uint16_t)_mmcsd_get_slice(csd, MMCSD_CSD_10_C_SIZE_SLICE);
+ csd10->c_size_mult = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_C_SIZE_MULT_SLICE);
+ csd10->ccc = (uint16_t)_mmcsd_get_slice(csd, MMCSD_CSD_10_CCC_SLICE);
+ csd10->copy = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_COPY_SLICE);
+ csd10->crc = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_CRC_SLICE);
+ csd10->csd_structure = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_CSD_STRUCTURE_SLICE);
+ csd10->dsr_imp = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_DSR_IMP_SLICE);
+ csd10->erase_blk_en = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_ERASE_BLK_EN_SLICE);
+ csd10->erase_sector_size = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_ERASE_SECTOR_SIZE_SLICE);
+ csd10->file_format = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_FILE_FORMAT_SLICE);
+ csd10->file_format_grp = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_FILE_FORMAT_GRP_SLICE);
+ csd10->nsac = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_NSAC_SLICE);
+ csd10->perm_write_protect = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_PERM_WRITE_PROTECT_SLICE);
+ csd10->r2w_factor = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_R2W_FACTOR_SLICE);
+ csd10->read_bl_len = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_READ_BL_LEN_SLICE);
+ csd10->read_bl_partial = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_READ_BL_PARTIAL_SLICE);
+ csd10->read_blk_misalign = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_READ_BLK_MISALIGN_SLICE);
+ csd10->taac = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_TAAC_SLICE);
+ csd10->tmp_write_protect = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_TMP_WRITE_PROTECT_SLICE);
+ csd10->tran_speed = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_TRANS_SPEED_SLICE);
+ csd10->wp_grp_enable = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_WP_GRP_ENABLE_SLICE);
+ csd10->wp_grp_size = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_WP_GRP_SIZE_SLICE);
+ csd10->write_bl_len = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_WRITE_BL_LEN_SLICE);
+ csd10->write_bl_partial = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_WRITE_BL_PARTIAL_SLICE);
+ csd10->write_blk_misalign = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_10_WRITE_BLK_MISALIGN_SLICE);
+}
+
+/**
+ * @brief Unpacks SDC CSD v2.0 array in structure.
+ *
+ * @param[in] sdcp pointer to the @p MMCSDBlockDevice object
+ * @param[out] csd20 pointer to the @p unpacked_sdc_csd_20_t object
+ *
+ * @notapi
+ */
+void _mmcsd_unpack_csd_v20(const MMCSDBlockDevice *sdcp,
+ unpacked_sdc_csd_20_t *csd20) {
+ const uint32_t *csd;
+
+ osalDbgCheck(NULL != sdcp);
+
+ csd = sdcp->csd;
+ csd20->c_size = _mmcsd_get_slice(csd, MMCSD_CSD_20_C_SIZE_SLICE);
+ csd20->crc = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_CRC_SLICE);
+ csd20->ccc = (uint16_t)_mmcsd_get_slice(csd, MMCSD_CSD_20_CCC_SLICE);
+ csd20->copy = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_COPY_SLICE);
+ csd20->csd_structure = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_CSD_STRUCTURE_SLICE);
+ csd20->dsr_imp = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_DSR_IMP_SLICE);
+ csd20->erase_blk_en = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_ERASE_BLK_EN_SLICE);
+ csd20->file_format = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_FILE_FORMAT_SLICE);
+ csd20->file_format_grp = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_FILE_FORMAT_GRP_SLICE);
+ csd20->nsac = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_NSAC_SLICE);
+ csd20->perm_write_protect = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_PERM_WRITE_PROTECT_SLICE);
+ csd20->r2w_factor = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_R2W_FACTOR_SLICE);
+ csd20->read_bl_len = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_READ_BL_LEN_SLICE);
+ csd20->read_bl_partial = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_READ_BL_PARTIAL_SLICE);
+ csd20->read_blk_misalign = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_READ_BLK_MISALIGN_SLICE);
+ csd20->erase_sector_size = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_ERASE_SECTOR_SIZE_SLICE);
+ csd20->taac = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_TAAC_SLICE);
+ csd20->tmp_write_protect = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_TMP_WRITE_PROTECT_SLICE);
+ csd20->tran_speed = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_TRANS_SPEED_SLICE);
+ csd20->wp_grp_enable = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_WP_GRP_ENABLE_SLICE);
+ csd20->wp_grp_size = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_WP_GRP_SIZE_SLICE);
+ csd20->write_bl_len = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_WRITE_BL_LEN_SLICE);
+ csd20->write_bl_partial = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_WRITE_BL_PARTIAL_SLICE);
+ csd20->write_blk_misalign = (uint8_t) _mmcsd_get_slice(csd, MMCSD_CSD_20_WRITE_BLK_MISALIGN_SLICE);
+}
+
+#endif /* (HAL_USE_MMC_SPI == TRUE) || (HAL_USE_SDC == TRUE) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_pal.c b/ChibiOS_20.3.2/os/hal/src/hal_pal.c
new file mode 100644
index 0000000..de64624
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_pal.c
@@ -0,0 +1,257 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_pal.c
+ * @brief I/O Ports Abstraction Layer code.
+ *
+ * @addtogroup PAL
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Read from an I/O bus.
+ * @note The operation is not guaranteed to be atomic on all the
+ * architectures, for atomicity and/or portability reasons you may
+ * need to enclose port I/O operations between @p osalSysLock() and
+ * @p osalSysUnlock().
+ * @note The function internally uses the @p palReadGroup() macro. The use
+ * of this function is preferred when you value code size, readability
+ * and error checking over speed.
+ * @note The function can be called from any context.
+ *
+ * @param[in] bus the I/O bus, pointer to a @p IOBus structure
+ * @return The bus logical states.
+ *
+ * @special
+ */
+ioportmask_t palReadBus(const IOBus *bus) {
+
+ osalDbgCheck((bus != NULL) && (bus->offset < PAL_IOPORTS_WIDTH));
+
+ return palReadGroup(bus->portid, bus->mask, bus->offset);
+}
+
+/**
+ * @brief Write to an I/O bus.
+ * @note The operation is not guaranteed to be atomic on all the
+ * architectures, for atomicity and/or portability reasons you may
+ * need to enclose port I/O operations between @p osalSysLock() and
+ * @p osalSysUnlock().
+ * @note The default implementation is non atomic and not necessarily
+ * optimal. Low level drivers may optimize the function by using
+ * specific hardware or coding.
+ * @note The function can be called from any context.
+ *
+ * @param[in] bus the I/O bus, pointer to a @p IOBus structure
+ * @param[in] bits the bits to be written on the I/O bus. Values exceeding
+ * the bus width are masked so most significant bits are
+ * lost.
+ *
+ * @special
+ */
+void palWriteBus(const IOBus *bus, ioportmask_t bits) {
+
+ osalDbgCheck((bus != NULL) && (bus->offset < PAL_IOPORTS_WIDTH));
+
+ palWriteGroup(bus->portid, bus->mask, bus->offset, bits);
+}
+
+/**
+ * @brief Programs a bus with the specified mode.
+ * @note The operation is not guaranteed to be atomic on all the
+ * architectures, for atomicity and/or portability reasons you may
+ * need to enclose port I/O operations between @p osalSysLock() and
+ * @p osalSysUnlock().
+ * @note The default implementation is non atomic and not necessarily
+ * optimal. Low level drivers may optimize the function by using
+ * specific hardware or coding.
+ * @note The function can be called from any context.
+ *
+ * @param[in] bus the I/O bus, pointer to a @p IOBus structure
+ * @param[in] mode the mode
+ *
+ * @special
+ */
+void palSetBusMode(const IOBus *bus, iomode_t mode) {
+
+ osalDbgCheck((bus != NULL) && (bus->offset < PAL_IOPORTS_WIDTH));
+
+ palSetGroupMode(bus->portid, bus->mask, bus->offset, mode);
+}
+
+#if (PAL_USE_CALLBACKS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Associates a callback to a port/pad.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] cb event callback function
+ * @param[in] arg callback argument
+ *
+ * @iclass
+ */
+void palSetPadCallbackI(ioportid_t port, iopadid_t pad,
+ palcallback_t cb, void *arg) {
+
+ palevent_t *pep = pal_lld_get_pad_event(port, pad);
+ pep->cb = cb;
+ pep->arg = arg;
+}
+
+/**
+ * @brief Associates a callback to a line.
+ *
+ * @param[in] line line identifier
+ * @param[in] cb event callback function
+ * @param[in] arg callback argument
+ *
+ * @iclass
+ */
+void palSetLineCallbackI(ioline_t line, palcallback_t cb, void *arg) {
+
+ palevent_t *pep = pal_lld_get_line_event(line);
+ pep->cb = cb;
+ pep->arg = arg;
+}
+#endif /* PAL_USE_CALLBACKS == TRUE */
+
+#if (PAL_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Waits for an edge on the specified port/pad.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @returns The operation state.
+ * @retval MSG_OK if an edge has been detected.
+ * @retval MSG_TIMEOUT if a timeout occurred before an edge could be detected.
+ * @retval MSG_RESET if the event has been disabled while the thread was
+ * waiting for an edge.
+ *
+ * @sclass
+ */
+msg_t palWaitPadTimeoutS(ioportid_t port,
+ iopadid_t pad,
+ sysinterval_t timeout) {
+
+ palevent_t *pep = pal_lld_get_pad_event(port, pad);
+ return osalThreadEnqueueTimeoutS(&pep->threads, timeout);
+}
+
+/**
+ * @brief Waits for an edge on the specified port/pad.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @returns The operation state.
+ * @retval MSG_OK if an edge has been detected.
+ * @retval MSG_TIMEOUT if a timeout occurred before an edge cound be detected.
+ * @retval MSG_RESET if the event has been disabled while the thread was
+ * waiting for an edge.
+ *
+ * @api
+ */
+msg_t palWaitPadTimeout(ioportid_t port,
+ iopadid_t pad,
+ sysinterval_t timeout) {
+ msg_t msg;
+
+ osalSysLock();
+ msg = palWaitPadTimeoutS(port, pad, timeout);
+ osalSysUnlock();
+ return msg;
+}
+
+/**
+ * @brief Waits for an edge on the specified line.
+ *
+ * @param[in] line line identifier
+ * @param[in] timeout operation timeout
+ * @returns The operation state.
+ * @retval MSG_OK if an edge has been detected.
+ * @retval MSG_TIMEOUT if a timeout occurred before an edge could be detected.
+ * @retval MSG_RESET if the event has been disabled while the thread was
+ * waiting for an edge.
+ *
+ * @sclass
+ */
+msg_t palWaitLineTimeoutS(ioline_t line,
+ sysinterval_t timeout) {
+
+ palevent_t *pep = pal_lld_get_line_event(line);
+ return osalThreadEnqueueTimeoutS(&pep->threads, timeout);
+}
+
+/**
+ * @brief Waits for an edge on the specified line.
+ *
+ * @param[in] line line identifier
+ * @param[in] timeout operation timeout
+ * @returns The operation state.
+ * @retval MSG_OK if an edge has been detected.
+ * @retval MSG_TIMEOUT if a timeout occurred before an edge cound be detected.
+ * @retval MSG_RESET if the event has been disabled while the thread was
+ * waiting for an edge.
+ *
+ * @api
+ */
+msg_t palWaitLineTimeout(ioline_t line, sysinterval_t timeout) {
+ msg_t msg;
+
+ osalSysLock();
+ msg = palWaitLineTimeoutS(line, timeout);
+ osalSysUnlock();
+ return msg;
+}
+#endif /* PAL_USE_WAIT == TRUE */
+
+#endif /* HAL_USE_PAL == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_pwm.c b/ChibiOS_20.3.2/os/hal/src/hal_pwm.c
new file mode 100644
index 0000000..61e81c0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_pwm.c
@@ -0,0 +1,313 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_pwm.c
+ * @brief PWM Driver code.
+ *
+ * @addtogroup PWM
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_PWM == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief PWM Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void pwmInit(void) {
+
+ pwm_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p PWMDriver structure.
+ *
+ * @param[out] pwmp pointer to a @p PWMDriver object
+ *
+ * @init
+ */
+void pwmObjectInit(PWMDriver *pwmp) {
+
+ pwmp->state = PWM_STOP;
+ pwmp->config = NULL;
+ pwmp->enabled = 0;
+ pwmp->channels = 0;
+#if defined(PWM_DRIVER_EXT_INIT_HOOK)
+ PWM_DRIVER_EXT_INIT_HOOK(pwmp);
+#endif
+}
+
+/**
+ * @brief Configures and activates the PWM peripheral.
+ * @note Starting a driver that is already in the @p PWM_READY state
+ * disables all the active channels.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] config pointer to a @p PWMConfig object
+ *
+ * @api
+ */
+void pwmStart(PWMDriver *pwmp, const PWMConfig *config) {
+
+ osalDbgCheck((pwmp != NULL) && (config != NULL));
+
+ osalSysLock();
+ osalDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY),
+ "invalid state");
+ pwmp->config = config;
+ pwmp->period = config->period;
+ pwm_lld_start(pwmp);
+ pwmp->enabled = 0;
+ pwmp->state = PWM_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the PWM peripheral.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ *
+ * @api
+ */
+void pwmStop(PWMDriver *pwmp) {
+
+ osalDbgCheck(pwmp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY),
+ "invalid state");
+
+ pwm_lld_stop(pwmp);
+ pwmp->enabled = 0;
+ pwmp->config = NULL;
+ pwmp->state = PWM_STOP;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Changes the period the PWM peripheral.
+ * @details This function changes the period of a PWM unit that has already
+ * been activated using @p pwmStart().
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @post The PWM unit period is changed to the new value.
+ * @note If a period is specified that is shorter than the pulse width
+ * programmed in one of the channels then the behavior is not
+ * guaranteed.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] period new cycle time in ticks
+ *
+ * @api
+ */
+void pwmChangePeriod(PWMDriver *pwmp, pwmcnt_t period) {
+
+ osalDbgCheck(pwmp != NULL);
+
+ osalSysLock();
+ osalDbgAssert(pwmp->state == PWM_READY, "invalid state");
+ pwmChangePeriodI(pwmp, period);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Enables a PWM channel.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @post The channel is active using the specified configuration.
+ * @note Depending on the hardware implementation this function has
+ * effect starting on the next cycle (recommended implementation)
+ * or immediately (fallback implementation).
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] channel PWM channel identifier (0...channels-1)
+ * @param[in] width PWM pulse width as clock pulses number
+ *
+ * @api
+ */
+void pwmEnableChannel(PWMDriver *pwmp,
+ pwmchannel_t channel,
+ pwmcnt_t width) {
+
+ osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels));
+
+ osalSysLock();
+
+ osalDbgAssert(pwmp->state == PWM_READY, "not ready");
+
+ pwmEnableChannelI(pwmp, channel, width);
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Disables a PWM channel and its notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @post The channel is disabled and its output line returned to the
+ * idle state.
+ * @note Depending on the hardware implementation this function has
+ * effect starting on the next cycle (recommended implementation)
+ * or immediately (fallback implementation).
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] channel PWM channel identifier (0...channels-1)
+ *
+ * @api
+ */
+void pwmDisableChannel(PWMDriver *pwmp, pwmchannel_t channel) {
+
+ osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels));
+
+ osalSysLock();
+
+ osalDbgAssert(pwmp->state == PWM_READY, "not ready");
+
+ pwmDisableChannelI(pwmp, channel);
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Enables the periodic activation edge notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @note If the notification is already enabled then the call has no effect.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ *
+ * @api
+ */
+void pwmEnablePeriodicNotification(PWMDriver *pwmp) {
+
+ osalDbgCheck(pwmp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert(pwmp->state == PWM_READY, "not ready");
+ osalDbgAssert(pwmp->config->callback != NULL, "undefined periodic callback");
+
+ pwmEnablePeriodicNotificationI(pwmp);
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Disables the periodic activation edge notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @note If the notification is already disabled then the call has no effect.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ *
+ * @api
+ */
+void pwmDisablePeriodicNotification(PWMDriver *pwmp) {
+
+ osalDbgCheck(pwmp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert(pwmp->state == PWM_READY, "not ready");
+ osalDbgAssert(pwmp->config->callback != NULL, "undefined periodic callback");
+
+ pwmDisablePeriodicNotificationI(pwmp);
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Enables a channel de-activation edge notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @pre The channel must have been activated using @p pwmEnableChannel().
+ * @note If the notification is already enabled then the call has no effect.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] channel PWM channel identifier (0...channels-1)
+ *
+ * @api
+ */
+void pwmEnableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel) {
+
+ osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels));
+
+ osalSysLock();
+
+ osalDbgAssert(pwmp->state == PWM_READY, "not ready");
+ osalDbgAssert((pwmp->enabled & ((pwmchnmsk_t)1U << (pwmchnmsk_t)channel)) != 0U,
+ "channel not enabled");
+ osalDbgAssert(pwmp->config->channels[channel].callback != NULL,
+ "undefined channel callback");
+
+ pwmEnableChannelNotificationI(pwmp, channel);
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Disables a channel de-activation edge notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @pre The channel must have been activated using @p pwmEnableChannel().
+ * @note If the notification is already disabled then the call has no effect.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] channel PWM channel identifier (0...channels-1)
+ *
+ * @api
+ */
+void pwmDisableChannelNotification(PWMDriver *pwmp, pwmchannel_t channel) {
+
+ osalDbgCheck((pwmp != NULL) && (channel < pwmp->channels));
+
+ osalSysLock();
+
+ osalDbgAssert(pwmp->state == PWM_READY, "not ready");
+ osalDbgAssert((pwmp->enabled & ((pwmchnmsk_t)1U << (pwmchnmsk_t)channel)) != 0U,
+ "channel not enabled");
+ osalDbgAssert(pwmp->config->channels[channel].callback != NULL,
+ "undefined channel callback");
+
+ pwmDisableChannelNotificationI(pwmp, channel);
+
+ osalSysUnlock();
+}
+
+#endif /* HAL_USE_PWM == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_queues.c b/ChibiOS_20.3.2/os/hal/src/hal_queues.c
new file mode 100644
index 0000000..6c58ebb
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_queues.c
@@ -0,0 +1,699 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_queues.c
+ * @brief I/O Queues code.
+ *
+ * @addtogroup HAL_QUEUES
+ * @details Queues are mostly used in serial-like device drivers.
+ * Serial device drivers are usually designed to have a lower side
+ * (lower driver, it is usually an interrupt service routine) and an
+ * upper side (upper driver, accessed by the application threads).
+ * There are several kind of queues:
+ * - Input queue, unidirectional queue where the writer is the
+ * lower side and the reader is the upper side.
+ * - Output queue, unidirectional queue where the writer is the
+ * upper side and the reader is the lower side.
+ * - Full duplex queue, bidirectional queue. Full duplex queues
+ * are implemented by pairing an input queue and an output queue
+ * together.
+ * .
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/**
+ * @brief Non-blocking input queue read.
+ * @details The function reads data from an input queue into a buffer. The
+ * operation completes when the specified amount of data has been
+ * transferred or when the input queue has been emptied.
+ *
+ * @param[in] iqp pointer to an @p input_queue_t structure
+ * @param[out] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred, the
+ * value 0 is reserved
+ * @return The number of bytes effectively transferred.
+ *
+ * @notapi
+ */
+static size_t iq_read(input_queue_t *iqp, uint8_t *bp, size_t n) {
+ size_t s1, s2;
+
+ osalDbgCheck(n > 0U);
+
+ /* Number of bytes that can be read in a single atomic operation.*/
+ if (n > iqGetFullI(iqp)) {
+ n = iqGetFullI(iqp);
+ }
+
+ /* Number of bytes before buffer limit.*/
+ /*lint -save -e9033 [10.8] Checked to be safe.*/
+ s1 = (size_t)(iqp->q_top - iqp->q_rdptr);
+ /*lint -restore*/
+ if (n < s1) {
+ memcpy((void *)bp, (void *)iqp->q_rdptr, n);
+ iqp->q_rdptr += n;
+ }
+ else if (n > s1) {
+ memcpy((void *)bp, (void *)iqp->q_rdptr, s1);
+ bp += s1;
+ s2 = n - s1;
+ memcpy((void *)bp, (void *)iqp->q_buffer, s2);
+ iqp->q_rdptr = iqp->q_buffer + s2;
+ }
+ else {
+ memcpy((void *)bp, (void *)iqp->q_rdptr, n);
+ iqp->q_rdptr = iqp->q_buffer;
+ }
+
+ iqp->q_counter -= n;
+ return n;
+}
+
+/**
+ * @brief Non-blocking output queue write.
+ * @details The function writes data from a buffer to an output queue. The
+ * operation completes when the specified amount of data has been
+ * transferred or when the output queue has been filled.
+ *
+ * @param[in] oqp pointer to an @p output_queue_t structure
+ * @param[in] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred, the
+ * value 0 is reserved
+ * @return The number of bytes effectively transferred.
+ *
+ * @notapi
+ */
+static size_t oq_write(output_queue_t *oqp, const uint8_t *bp, size_t n) {
+ size_t s1, s2;
+
+ osalDbgCheck(n > 0U);
+
+ /* Number of bytes that can be written in a single atomic operation.*/
+ if (n > oqGetEmptyI(oqp)) {
+ n = oqGetEmptyI(oqp);
+ }
+
+ /* Number of bytes before buffer limit.*/
+ /*lint -save -e9033 [10.8] Checked to be safe.*/
+ s1 = (size_t)(oqp->q_top - oqp->q_wrptr);
+ /*lint -restore*/
+ if (n < s1) {
+ memcpy((void *)oqp->q_wrptr, (const void *)bp, n);
+ oqp->q_wrptr += n;
+ }
+ else if (n > s1) {
+ memcpy((void *)oqp->q_wrptr, (const void *)bp, s1);
+ bp += s1;
+ s2 = n - s1;
+ memcpy((void *)oqp->q_buffer, (const void *)bp, s2);
+ oqp->q_wrptr = oqp->q_buffer + s2;
+ }
+ else {
+ memcpy((void *)oqp->q_wrptr, (const void *)bp, n);
+ oqp->q_wrptr = oqp->q_buffer;
+ }
+
+ oqp->q_counter -= n;
+ return n;
+}
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes an input queue.
+ * @details A Semaphore is internally initialized and works as a counter of
+ * the bytes contained in the queue.
+ * @note The callback is invoked from within the S-Locked system state.
+ *
+ * @param[out] iqp pointer to an @p input_queue_t structure
+ * @param[in] bp pointer to a memory area allocated as queue buffer
+ * @param[in] size size of the queue buffer
+ * @param[in] infy pointer to a callback function that is invoked when
+ * data is read from the queue. The value can be @p NULL.
+ * @param[in] link application defined pointer
+ *
+ * @init
+ */
+void iqObjectInit(input_queue_t *iqp, uint8_t *bp, size_t size,
+ qnotify_t infy, void *link) {
+
+ osalThreadQueueObjectInit(&iqp->q_waiting);
+ iqp->q_counter = 0;
+ iqp->q_buffer = bp;
+ iqp->q_rdptr = bp;
+ iqp->q_wrptr = bp;
+ iqp->q_top = bp + size;
+ iqp->q_notify = infy;
+ iqp->q_link = link;
+}
+
+/**
+ * @brief Resets an input queue.
+ * @details All the data in the input queue is erased and lost, any waiting
+ * thread is resumed with status @p MSG_RESET.
+ * @note A reset operation can be used by a low level driver in order to
+ * obtain immediate attention from the high level layers.
+ *
+ * @param[in] iqp pointer to an @p input_queue_t structure
+ *
+ * @iclass
+ */
+void iqResetI(input_queue_t *iqp) {
+
+ osalDbgCheckClassI();
+
+ iqp->q_rdptr = iqp->q_buffer;
+ iqp->q_wrptr = iqp->q_buffer;
+ iqp->q_counter = 0;
+ osalThreadDequeueAllI(&iqp->q_waiting, MSG_RESET);
+}
+
+/**
+ * @brief Input queue write.
+ * @details A byte value is written into the low end of an input queue. The
+ * operation completes immediately.
+ *
+ * @param[in] iqp pointer to an @p input_queue_t structure
+ * @param[in] b the byte value to be written in the queue
+ * @return The operation status.
+ * @retval MSG_OK if the operation has been completed with success.
+ * @retval MSG_TIMEOUT if the queue is full.
+ *
+ * @iclass
+ */
+msg_t iqPutI(input_queue_t *iqp, uint8_t b) {
+
+ osalDbgCheckClassI();
+
+ /* Queue space check.*/
+ if (!iqIsFullI(iqp)) {
+ iqp->q_counter++;
+ *iqp->q_wrptr++ = b;
+ if (iqp->q_wrptr >= iqp->q_top) {
+ iqp->q_wrptr = iqp->q_buffer;
+ }
+
+ osalThreadDequeueNextI(&iqp->q_waiting, MSG_OK);
+
+ return MSG_OK;
+ }
+
+ return MSG_TIMEOUT;
+}
+
+/**
+ * @brief Input queue non-blocking read.
+ * @details This function reads a byte value from an input queue. The
+ * operation completes immediately.
+ * @note The callback is invoked after removing a character from the
+ * queue.
+ *
+ * @param[in] iqp pointer to an @p input_queue_t structure
+ * @return A byte value from the queue.
+ * @retval MSG_TIMEOUT if the queue is empty.
+ * @retval MSG_RESET if the queue has been reset.
+ *
+ * @iclass
+ */
+msg_t iqGetI(input_queue_t *iqp) {
+
+ osalDbgCheckClassI();
+
+ /* Queue data check.*/
+ if (!iqIsEmptyI(iqp)) {
+ uint8_t b;
+
+ /* Getting the character from the queue.*/
+ iqp->q_counter--;
+ b = *iqp->q_rdptr++;
+ if (iqp->q_rdptr >= iqp->q_top) {
+ iqp->q_rdptr = iqp->q_buffer;
+ }
+
+ /* Inform the low side that the queue has at least one slot available.*/
+ if (iqp->q_notify != NULL) {
+ iqp->q_notify(iqp);
+ }
+
+ return (msg_t)b;
+ }
+
+ return MSG_TIMEOUT;
+}
+
+/**
+ * @brief Input queue read with timeout.
+ * @details This function reads a byte value from an input queue. If the queue
+ * is empty then the calling thread is suspended until a byte arrives
+ * in the queue or a timeout occurs.
+ * @note The callback is invoked after removing a character from the
+ * queue.
+ *
+ * @param[in] iqp pointer to an @p input_queue_t structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A byte value from the queue.
+ * @retval MSG_TIMEOUT if the specified time expired.
+ * @retval MSG_RESET if the queue has been reset.
+ *
+ * @api
+ */
+msg_t iqGetTimeout(input_queue_t *iqp, sysinterval_t timeout) {
+ uint8_t b;
+
+ osalSysLock();
+
+ /* Waiting until there is a character available or a timeout occurs.*/
+ while (iqIsEmptyI(iqp)) {
+ msg_t msg = osalThreadEnqueueTimeoutS(&iqp->q_waiting, timeout);
+ if (msg < MSG_OK) {
+ osalSysUnlock();
+ return msg;
+ }
+ }
+
+ /* Getting the character from the queue.*/
+ iqp->q_counter--;
+ b = *iqp->q_rdptr++;
+ if (iqp->q_rdptr >= iqp->q_top) {
+ iqp->q_rdptr = iqp->q_buffer;
+ }
+
+ /* Inform the low side that the queue has at least one slot available.*/
+ if (iqp->q_notify != NULL) {
+ iqp->q_notify(iqp);
+ }
+
+ osalSysUnlock();
+
+ return (msg_t)b;
+}
+
+/**
+ * @brief Input queue non-blocking read.
+ * @details The function reads data from an input queue into a buffer. The
+ * operation completes immediately.
+ *
+ * @param[in] iqp pointer to an @p input_queue_t structure
+ * @param[out] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred, the
+ * value 0 is reserved
+ * @return The number of bytes effectively transferred.
+ *
+ * @iclass
+ */
+size_t iqReadI(input_queue_t *iqp, uint8_t *bp, size_t n) {
+ qnotify_t nfy = iqp->q_notify;
+ size_t rd;
+
+ osalDbgCheckClassI();
+
+ rd = iq_read(iqp, bp, n);
+
+ /* Inform the low side that the queue has at least one character
+ available.*/
+ if ((rd > (size_t)0) && (nfy != NULL)) {
+ nfy(iqp);
+ }
+
+ return rd;
+}
+
+/**
+ * @brief Input queue read with timeout.
+ * @details The function reads data from an input queue into a buffer. The
+ * operation completes when the specified amount of data has been
+ * transferred or after the specified timeout or if the queue has
+ * been reset.
+ * @note The function is not atomic, if you need atomicity it is suggested
+ * to use a semaphore or a mutex for mutual exclusion.
+ * @note The callback is invoked after removing each character from the
+ * queue.
+ *
+ * @param[in] iqp pointer to an @p input_queue_t structure
+ * @param[out] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred, the
+ * value 0 is reserved
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The number of bytes effectively transferred.
+ *
+ * @api
+ */
+size_t iqReadTimeout(input_queue_t *iqp, uint8_t *bp,
+ size_t n, sysinterval_t timeout) {
+ qnotify_t nfy = iqp->q_notify;
+ size_t max = n;
+
+ osalDbgCheck(n > 0U);
+
+ osalSysLock();
+
+ while (n > 0U) {
+ size_t done;
+
+ done = iq_read(iqp, bp, n);
+ if (done == (size_t)0) {
+ msg_t msg = osalThreadEnqueueTimeoutS(&iqp->q_waiting, timeout);
+
+ /* Anything except MSG_OK causes the operation to stop.*/
+ if (msg != MSG_OK) {
+ break;
+ }
+ }
+ else {
+ /* Inform the low side that the queue has at least one empty slot
+ available.*/
+ if (nfy != NULL) {
+ nfy(iqp);
+ }
+
+ /* Giving a preemption chance in a controlled point.*/
+ osalSysUnlock();
+
+ n -= done;
+ bp += done;
+
+ osalSysLock();
+ }
+ }
+
+ osalSysUnlock();
+ return max - n;
+}
+
+/**
+ * @brief Initializes an output queue.
+ * @details A Semaphore is internally initialized and works as a counter of
+ * the free bytes in the queue.
+ * @note The callback is invoked from within the S-Locked system state.
+ *
+ * @param[out] oqp pointer to an @p output_queue_t structure
+ * @param[in] bp pointer to a memory area allocated as queue buffer
+ * @param[in] size size of the queue buffer
+ * @param[in] onfy pointer to a callback function that is invoked when
+ * data is written to the queue. The value can be @p NULL.
+ * @param[in] link application defined pointer
+ *
+ * @init
+ */
+void oqObjectInit(output_queue_t *oqp, uint8_t *bp, size_t size,
+ qnotify_t onfy, void *link) {
+
+ osalThreadQueueObjectInit(&oqp->q_waiting);
+ oqp->q_counter = size;
+ oqp->q_buffer = bp;
+ oqp->q_rdptr = bp;
+ oqp->q_wrptr = bp;
+ oqp->q_top = bp + size;
+ oqp->q_notify = onfy;
+ oqp->q_link = link;
+}
+
+/**
+ * @brief Resets an output queue.
+ * @details All the data in the output queue is erased and lost, any waiting
+ * thread is resumed with status @p MSG_RESET.
+ * @note A reset operation can be used by a low level driver in order to
+ * obtain immediate attention from the high level layers.
+ *
+ * @param[in] oqp pointer to an @p output_queue_t structure
+ *
+ * @iclass
+ */
+void oqResetI(output_queue_t *oqp) {
+
+ osalDbgCheckClassI();
+
+ oqp->q_rdptr = oqp->q_buffer;
+ oqp->q_wrptr = oqp->q_buffer;
+ oqp->q_counter = qSizeX(oqp);
+ osalThreadDequeueAllI(&oqp->q_waiting, MSG_RESET);
+}
+
+/**
+ * @brief Output queue non-blocking write.
+ * @details This function writes a byte value to an output queue. The
+ * operation completes immediately.
+ *
+ * @param[in] oqp pointer to an @p output_queue_t structure
+ * @param[in] b the byte value to be written in the queue
+ * @return The operation status.
+ * @retval MSG_OK if the operation succeeded.
+ * @retval MSG_TIMEOUT if the queue is full.
+ * @retval MSG_RESET if the queue has been reset.
+ *
+ * @iclass
+ */
+msg_t oqPutI(output_queue_t *oqp, uint8_t b) {
+
+ osalDbgCheckClassI();
+
+ /* Queue space check.*/
+ while (!oqIsFullI(oqp)) {
+ /* Putting the character into the queue.*/
+ oqp->q_counter--;
+ *oqp->q_wrptr++ = b;
+ if (oqp->q_wrptr >= oqp->q_top) {
+ oqp->q_wrptr = oqp->q_buffer;
+ }
+
+ /* Inform the low side that the queue has at least one character available.*/
+ if (oqp->q_notify != NULL) {
+ oqp->q_notify(oqp);
+ }
+
+ return MSG_OK;
+ }
+
+ return MSG_TIMEOUT;
+}
+
+/**
+ * @brief Output queue write with timeout.
+ * @details This function writes a byte value to an output queue. If the queue
+ * is full then the calling thread is suspended until there is space
+ * in the queue or a timeout occurs.
+ * @note The callback is invoked after putting the character into the
+ * queue.
+ *
+ * @param[in] oqp pointer to an @p output_queue_t structure
+ * @param[in] b the byte value to be written in the queue
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if the operation succeeded.
+ * @retval MSG_TIMEOUT if the specified time expired.
+ * @retval MSG_RESET if the queue has been reset.
+ *
+ * @api
+ */
+msg_t oqPutTimeout(output_queue_t *oqp, uint8_t b, sysinterval_t timeout) {
+
+ osalSysLock();
+
+ /* Waiting until there is a slot available or a timeout occurs.*/
+ while (oqIsFullI(oqp)) {
+ msg_t msg = osalThreadEnqueueTimeoutS(&oqp->q_waiting, timeout);
+ if (msg < MSG_OK) {
+ osalSysUnlock();
+ return msg;
+ }
+ }
+
+ /* Putting the character into the queue.*/
+ oqp->q_counter--;
+ *oqp->q_wrptr++ = b;
+ if (oqp->q_wrptr >= oqp->q_top) {
+ oqp->q_wrptr = oqp->q_buffer;
+ }
+
+ /* Inform the low side that the queue has at least one character available.*/
+ if (oqp->q_notify != NULL) {
+ oqp->q_notify(oqp);
+ }
+
+ osalSysUnlock();
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Output queue read.
+ * @details A byte value is read from the low end of an output queue. The
+ * operation completes immediately.
+ *
+ * @param[in] oqp pointer to an @p output_queue_t structure
+ * @return The byte value from the queue.
+ * @retval MSG_TIMEOUT if the queue is empty.
+ *
+ * @iclass
+ */
+msg_t oqGetI(output_queue_t *oqp) {
+
+ osalDbgCheckClassI();
+
+ /* Queue data check.*/
+ if (!oqIsEmptyI(oqp)) {
+ uint8_t b;
+
+ oqp->q_counter++;
+ b = *oqp->q_rdptr++;
+ if (oqp->q_rdptr >= oqp->q_top) {
+ oqp->q_rdptr = oqp->q_buffer;
+ }
+
+ osalThreadDequeueNextI(&oqp->q_waiting, MSG_OK);
+
+ return (msg_t)b;
+ }
+
+ return MSG_TIMEOUT;
+}
+
+/**
+ * @brief Output queue non-blocking write.
+ * @details The function writes data from a buffer to an output queue. The
+ * operation completes immediately.
+ *
+ * @param[in] oqp pointer to an @p output_queue_t structure
+ * @param[in] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred, the
+ * value 0 is reserved
+ * @return The number of bytes effectively transferred.
+ *
+ * @iclass
+ */
+size_t oqWriteI(output_queue_t *oqp, const uint8_t *bp, size_t n) {
+ qnotify_t nfy = oqp->q_notify;
+ size_t wr;
+
+ osalDbgCheckClassI();
+
+ wr = oq_write(oqp, bp, n);
+
+ /* Inform the low side that the queue has at least one character
+ available.*/
+ if ((wr > (size_t)0) && (nfy != NULL)) {
+ nfy(oqp);
+ }
+
+ return wr;
+}
+
+/**
+ * @brief Output queue write with timeout.
+ * @details The function writes data from a buffer to an output queue. The
+ * operation completes when the specified amount of data has been
+ * transferred or after the specified timeout or if the queue has
+ * been reset.
+ * @note The function is not atomic, if you need atomicity it is suggested
+ * to use a semaphore or a mutex for mutual exclusion.
+ * @note The callback is invoked after putting each character into the
+ * queue.
+ *
+ * @param[in] oqp pointer to an @p output_queue_t structure
+ * @param[in] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred, the
+ * value 0 is reserved
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The number of bytes effectively transferred.
+ *
+ * @api
+ */
+size_t oqWriteTimeout(output_queue_t *oqp, const uint8_t *bp,
+ size_t n, sysinterval_t timeout) {
+ qnotify_t nfy = oqp->q_notify;
+ size_t max = n;
+
+ osalDbgCheck(n > 0U);
+
+ osalSysLock();
+
+ while (n > 0U) {
+ size_t done;
+
+ done = oq_write(oqp, bp, n);
+ if (done == (size_t)0) {
+ msg_t msg = osalThreadEnqueueTimeoutS(&oqp->q_waiting, timeout);
+
+ /* Anything except MSG_OK causes the operation to stop.*/
+ if (msg != MSG_OK) {
+ break;
+ }
+ }
+ else {
+ /* Inform the low side that the queue has at least one character
+ available.*/
+ if (nfy != NULL) {
+ nfy(oqp);
+ }
+
+ /* Giving a preemption chance in a controlled point.*/
+ osalSysUnlock();
+
+ n -= done;
+ bp += done;
+
+ osalSysLock();
+ }
+ }
+
+ osalSysUnlock();
+ return max - n;
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_rtc.c b/ChibiOS_20.3.2/os/hal/src/hal_rtc.c
new file mode 100644
index 0000000..840e2ec
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_rtc.c
@@ -0,0 +1,321 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file hal_rtc.c
+ * @brief RTC Driver code.
+ *
+ * @addtogroup RTC
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_RTC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*
+ * Lookup table with months' length
+ */
+static const uint8_t month_len[12] = {
+ 31, 30, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief RTC Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void rtcInit(void) {
+
+ rtc_lld_init();
+}
+
+/**
+ * @brief Initializes a generic RTC driver object.
+ * @details The HW dependent part of the initialization has to be performed
+ * outside, usually in the hardware initialization code.
+ *
+ * @param[out] rtcp pointer to RTC driver structure
+ *
+ * @init
+ */
+void rtcObjectInit(RTCDriver *rtcp) {
+
+#if RTC_HAS_STORAGE == TRUE
+ rtcp->vmt = &_rtc_lld_vmt;
+#else
+ (void)rtcp;
+#endif
+}
+
+/**
+ * @brief Set current time.
+ * @note This function can be called from any context but limitations
+ * could be imposed by the low level implementation. It is
+ * guaranteed that the function can be called from thread
+ * context.
+ * @note The function can be reentrant or not reentrant depending on
+ * the low level implementation.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] timespec pointer to a @p RTCDateTime structure
+ *
+ * @special
+ */
+void rtcSetTime(RTCDriver *rtcp, const RTCDateTime *timespec) {
+
+ osalDbgCheck((rtcp != NULL) && (timespec != NULL));
+
+ rtc_lld_set_time(rtcp, timespec);
+}
+
+/**
+ * @brief Get current time.
+ * @note This function can be called from any context but limitations
+ * could be imposed by the low level implementation. It is
+ * guaranteed that the function can be called from thread
+ * context.
+ * @note The function can be reentrant or not reentrant depending on
+ * the low level implementation.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[out] timespec pointer to a @p RTCDateTime structure
+ *
+ * @special
+ */
+void rtcGetTime(RTCDriver *rtcp, RTCDateTime *timespec) {
+
+ osalDbgCheck((rtcp != NULL) && (timespec != NULL));
+
+ rtc_lld_get_time(rtcp, timespec);
+}
+
+#if (RTC_ALARMS > 0) || defined(__DOXYGEN__)
+/**
+ * @brief Set alarm time.
+ * @note This function can be called from any context but limitations
+ * could be imposed by the low level implementation. It is
+ * guaranteed that the function can be called from thread
+ * context.
+ * @note The function can be reentrant or not reentrant depending on
+ * the low level implementation.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] alarm alarm identifier
+ * @param[in] alarmspec pointer to a @p RTCAlarm structure or @p NULL
+ *
+ * @special
+ */
+void rtcSetAlarm(RTCDriver *rtcp,
+ rtcalarm_t alarm,
+ const RTCAlarm *alarmspec) {
+
+ osalDbgCheck((rtcp != NULL) && (alarm < (rtcalarm_t)RTC_ALARMS));
+
+ rtc_lld_set_alarm(rtcp, alarm, alarmspec);
+}
+
+/**
+ * @brief Get current alarm.
+ * @note If an alarm has not been set then the returned alarm specification
+ * is not meaningful.
+ * @note This function can be called from any context but limitations
+ * could be imposed by the low level implementation. It is
+ * guaranteed that the function can be called from thread
+ * context.
+ * @note The function can be reentrant or not reentrant depending on
+ * the low level implementation.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] alarm alarm identifier
+ * @param[out] alarmspec pointer to a @p RTCAlarm structure
+ *
+ * @special
+ */
+void rtcGetAlarm(RTCDriver *rtcp,
+ rtcalarm_t alarm,
+ RTCAlarm *alarmspec) {
+
+ osalDbgCheck((rtcp != NULL) &&
+ (alarm < (rtcalarm_t)RTC_ALARMS) &&
+ (alarmspec != NULL));
+
+ rtc_lld_get_alarm(rtcp, alarm, alarmspec);
+}
+#endif /* RTC_ALARMS > 0 */
+
+#if (RTC_SUPPORTS_CALLBACKS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Enables or disables RTC callbacks.
+ * @details This function enables or disables the callback, use a @p NULL
+ * pointer in order to disable it.
+ * @note This function can be called from any context but limitations
+ * could be imposed by the low level implementation. It is
+ * guaranteed that the function can be called from thread
+ * context.
+ * @note The function can be reentrant or not reentrant depending on
+ * the low level implementation.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] callback callback function pointer or @p NULL
+ *
+ * @special
+ */
+void rtcSetCallback(RTCDriver *rtcp, rtccb_t callback) {
+
+ osalDbgCheck(rtcp != NULL);
+
+ rtc_lld_set_callback(rtcp, callback);
+}
+#endif /* RTC_SUPPORTS_CALLBACKS == TRUE */
+
+/**
+ * @brief Convert @p RTCDateTime to broken-down time structure.
+ *
+ * @param[in] timespec pointer to a @p RTCDateTime structure
+ * @param[out] timp pointer to a broken-down time structure
+ * @param[out] tv_msec pointer to milliseconds value or @p NULL
+ *
+ * @api
+ */
+void rtcConvertDateTimeToStructTm(const RTCDateTime *timespec,
+ struct tm *timp,
+ uint32_t *tv_msec) {
+ int sec;
+
+ timp->tm_year = (int)timespec->year + (int)(RTC_BASE_YEAR - 1900U);
+ timp->tm_mon = (int)timespec->month - 1;
+ timp->tm_mday = (int)timespec->day;
+ timp->tm_isdst = (int)timespec->dstflag;
+ timp->tm_wday = (int)timespec->dayofweek - 1;
+
+ sec = (int)timespec->millisecond / 1000;
+ timp->tm_hour = sec / 3600;
+ sec %= 3600;
+ timp->tm_min = sec / 60;
+ timp->tm_sec = sec % 60;
+
+ if (NULL != tv_msec) {
+ *tv_msec = (uint32_t)timespec->millisecond % 1000U;
+ }
+}
+
+/**
+ * @brief Convert broken-down time structure to @p RTCDateTime.
+ *
+ * @param[in] timp pointer to a broken-down time structure
+ * @param[in] tv_msec milliseconds value
+ * @param[out] timespec pointer to a @p RTCDateTime structure
+ *
+ * @api
+ */
+void rtcConvertStructTmToDateTime(const struct tm *timp,
+ uint32_t tv_msec,
+ RTCDateTime *timespec) {
+
+ /*lint -save -e9034 [10.4] Verified assignments to bit fields.*/
+ timespec->year = (uint32_t)timp->tm_year - (RTC_BASE_YEAR - 1900U);
+ timespec->month = (uint32_t)timp->tm_mon + 1U;
+ timespec->day = (uint32_t)timp->tm_mday;
+ timespec->dayofweek = (uint32_t)timp->tm_wday + 1U;
+ if (-1 == timp->tm_isdst) {
+ timespec->dstflag = 0U; /* Set zero if dst is unknown.*/
+ }
+ else {
+ timespec->dstflag = (uint32_t)timp->tm_isdst;
+ }
+ /*lint -restore*/
+ /*lint -save -e9033 [10.8] Verified assignments to bit fields.*/
+ timespec->millisecond = tv_msec + (uint32_t)(((timp->tm_hour * 3600) +
+ (timp->tm_min * 60) +
+ timp->tm_sec) * 1000);
+ /*lint -restore*/
+}
+
+/**
+ * @brief Get current time in format suitable for usage in FAT file system.
+ * @note The information about day of week and DST is lost in DOS
+ * format, the second field loses its least significant bit.
+ *
+ * @param[out] timespec pointer to a @p RTCDateTime structure
+ * @return FAT date/time value.
+ *
+ * @api
+ */
+uint32_t rtcConvertDateTimeToFAT(const RTCDateTime *timespec) {
+ uint32_t fattime;
+ uint32_t sec, min, hour, day, month;
+
+ sec = timespec->millisecond / 1000U;
+ hour = sec / 3600U;
+ sec %= 3600U;
+ min = sec / 60U;
+ sec %= 60U;
+ day = timespec->day;
+ month = timespec->month;
+
+ /* Handle DST flag.*/
+ if (1U == timespec->dstflag) {
+ hour += 1U;
+ if (hour == 24U) {
+ hour = 0U;
+ day += 1U;
+ if (day > month_len[month - 1U]) {
+ day = 1U;
+ month += 1U;
+ }
+ }
+ }
+
+ fattime = sec >> 1U;
+ fattime |= min << 5U;
+ fattime |= hour << 11U;
+ fattime |= day << 16U;
+ fattime |= month << 21U;
+ fattime |= (uint32_t)timespec->year << 25U;
+
+ return fattime;
+}
+
+#endif /* HAL_USE_RTC == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_sdc.c b/ChibiOS_20.3.2/os/hal/src/hal_sdc.c
new file mode 100644
index 0000000..17995e4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_sdc.c
@@ -0,0 +1,999 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_sdc.c
+ * @brief SDC Driver code.
+ *
+ * @addtogroup SDC
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+
+#if (HAL_USE_SDC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/**
+ * @brief MMC switch mode.
+ */
+typedef enum {
+ MMC_SWITCH_COMMAND_SET = 0,
+ MMC_SWITCH_SET_BITS = 1,
+ MMC_SWITCH_CLEAR_BITS = 2,
+ MMC_SWITCH_WRITE_BYTE = 3
+} mmc_switch_t;
+
+/**
+ * @brief SDC switch mode.
+ */
+typedef enum {
+ SD_SWITCH_CHECK = 0,
+ SD_SWITCH_SET = 1
+} sd_switch_t;
+
+/**
+ * @brief SDC switch function.
+ */
+typedef enum {
+ SD_SWITCH_FUNCTION_SPEED = 0,
+ SD_SWITCH_FUNCTION_CMD_SYSTEM = 1,
+ SD_SWITCH_FUNCTION_DRIVER_STRENGTH = 2,
+ SD_SWITCH_FUNCTION_CURRENT_LIMIT = 3
+} sd_switch_function_t;
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Virtual methods table.
+ */
+static const struct SDCDriverVMT sdc_vmt = {
+ (size_t)0,
+ (bool (*)(void *))sdc_lld_is_card_inserted,
+ (bool (*)(void *))sdc_lld_is_write_protected,
+ (bool (*)(void *))sdcConnect,
+ (bool (*)(void *))sdcDisconnect,
+ (bool (*)(void *, uint32_t, uint8_t *, uint32_t))sdcRead,
+ (bool (*)(void *, uint32_t, const uint8_t *, uint32_t))sdcWrite,
+ (bool (*)(void *))sdcSync,
+ (bool (*)(void *, BlockDeviceInfo *))sdcGetInfo
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+/**
+ * @brief Detects card mode.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+static bool mode_detect(SDCDriver *sdcp) {
+ uint32_t resp[1];
+
+ /* V2.0 cards detection.*/
+ if (!sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEND_IF_COND,
+ MMCSD_CMD8_PATTERN, resp)) {
+ sdcp->cardmode = SDC_MODE_CARDTYPE_SDV20;
+ /* Voltage verification.*/
+ if (((resp[0] >> 8U) & 0xFU) != 1U) {
+ return HAL_FAILED;
+ }
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, 0, resp) ||
+ MMCSD_R1_ERROR(resp[0])) {
+ return HAL_FAILED;
+ }
+ }
+ else {
+ /* MMC or SD V1.1 detection.*/
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, 0, resp) ||
+ MMCSD_R1_ERROR(resp[0])) {
+ sdcp->cardmode = SDC_MODE_CARDTYPE_MMC;
+ }
+ else {
+ sdcp->cardmode = SDC_MODE_CARDTYPE_SDV11;
+
+ /* Reset error flag illegal command.*/
+ sdc_lld_send_cmd_none(sdcp, MMCSD_CMD_GO_IDLE_STATE, 0);
+ }
+ }
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Init procedure for MMC.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+static bool mmc_init(SDCDriver *sdcp) {
+ uint32_t ocr;
+ unsigned i;
+ uint32_t resp[1];
+
+ ocr = 0xC0FF8000U;
+ i = 0;
+ while (true) {
+ if (sdc_lld_send_cmd_short(sdcp, MMCSD_CMD_INIT, ocr, resp)) {
+ return HAL_FAILED;
+ }
+ if ((resp[0] & 0x80000000U) != 0U) {
+ if ((resp[0] & 0x40000000U) != 0U) {
+ sdcp->cardmode |= SDC_MODE_HIGH_CAPACITY;
+ }
+ break;
+ }
+ if (++i >= (unsigned)SDC_INIT_RETRY) {
+ return HAL_FAILED;
+ }
+ osalThreadSleepMilliseconds(10);
+ }
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Init procedure for SDC.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+static bool sdc_init(SDCDriver *sdcp) {
+ unsigned i;
+ uint32_t ocr;
+ uint32_t resp[1];
+
+ if ((sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) == SDC_MODE_CARDTYPE_SDV20) {
+ ocr = SDC_INIT_OCR_V20;
+ }
+ else {
+ ocr = SDC_INIT_OCR;
+ }
+
+ i = 0;
+ while (true) {
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, 0, resp) ||
+ MMCSD_R1_ERROR(resp[0])) {
+ return HAL_FAILED;
+ }
+ if (sdc_lld_send_cmd_short(sdcp, MMCSD_CMD_APP_OP_COND, ocr, resp)) {
+ return HAL_FAILED;
+ }
+ if ((resp[0] & 0x80000000U) != 0U) {
+ if ((resp[0] & 0x40000000U) != 0U) {
+ sdcp->cardmode |= SDC_MODE_HIGH_CAPACITY;
+ }
+ break;
+ }
+ if (++i >= (unsigned)SDC_INIT_RETRY) {
+ return HAL_FAILED;
+ }
+ osalThreadSleepMilliseconds(10);
+ }
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Constructs CMD6 argument for MMC.
+ *
+ * @param[in] access EXT_CSD access mode
+ * @param[in] idx EXT_CSD byte number
+ * @param[in] value value to be written in target field
+ * @param[in] cmd_set switch current command set
+ *
+ * @return CMD6 argument.
+ *
+ * @notapi
+ */
+static uint32_t mmc_cmd6_construct(mmc_switch_t access, uint32_t idx,
+ uint32_t value, uint32_t cmd_set) {
+
+ osalDbgAssert(idx <= 191U, "This field is not writable");
+ osalDbgAssert(cmd_set < 8U, "This field has only 3 bits");
+
+ return ((uint32_t)access << 24U) | (idx << 16U) | (value << 8U) | cmd_set;
+}
+
+/**
+ * @brief Constructs CMD6 argument for SDC.
+ *
+ * @param[in] mode switch/test mode
+ * @param[in] function function number to be switched
+ * @param[in] value value to be written in target function
+ *
+ * @return CMD6 argument.
+ *
+ * @notapi
+ */
+static uint32_t sdc_cmd6_construct(sd_switch_t mode,
+ sd_switch_function_t function,
+ uint32_t value) {
+ uint32_t ret = 0xFFFFFF;
+
+ osalDbgAssert((value < 16U), "This field has only 4 bits");
+
+ ret &= ~((uint32_t)0xFU << ((uint32_t)function * 4U));
+ ret |= value << ((uint32_t)function * 4U);
+ return ret | ((uint32_t)mode << 31U);
+}
+
+/**
+ * @brief Extracts information from CMD6 answer.
+ *
+ * @param[in] function function number to be switched
+ * @param[in] buf buffer with answer
+ *
+ * @return extracted answer.
+ *
+ * @notapi
+ */
+static uint16_t sdc_cmd6_extract_info(sd_switch_function_t function,
+ const uint8_t *buf) {
+
+ unsigned start = 12U - ((unsigned)function * 2U);
+
+ return ((uint16_t)buf[start] << 8U) | (uint16_t)buf[start + 1U];
+}
+
+/**
+ * @brief Checks status after switching using CMD6.
+ *
+ * @param[in] function function number to be switched
+ * @param[in] buf buffer with answer
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+static bool sdc_cmd6_check_status(sd_switch_function_t function,
+ const uint8_t *buf) {
+
+ uint32_t tmp;
+ uint32_t status;
+
+ tmp = ((uint32_t)buf[14] << 16U) |
+ ((uint32_t)buf[15] << 8U) |
+ (uint32_t)buf[16];
+ status = (tmp >> ((uint32_t)function * 4U)) & 0xFU;
+ if (0xFU != status) {
+ return HAL_SUCCESS;
+ }
+ return HAL_FAILED;
+}
+
+/**
+ * @brief Reads supported bus clock and switch SDC to appropriate mode.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[out] clk pointer to clock enum
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+static bool sdc_detect_bus_clk(SDCDriver *sdcp, sdcbusclk_t *clk) {
+ uint32_t cmdarg;
+ const size_t N = 64;
+ uint8_t tmp[N];
+
+ /* Safe default.*/
+ *clk = SDC_CLK_25MHz;
+
+ /* Looks like only "high capacity" cards produce meaningful results during
+ this clock detection procedure.*/
+ if (0U == _mmcsd_get_slice(sdcp->csd, MMCSD_CSD_10_CSD_STRUCTURE_SLICE)) {
+ *clk = SDC_CLK_25MHz;
+ return HAL_SUCCESS;
+ }
+
+ /* Read switch functions' register.*/
+ if (sdc_lld_read_special(sdcp, tmp, N, MMCSD_CMD_SWITCH, 0)) {
+ return HAL_FAILED;
+ }
+
+ /* Check card capabilities parsing acquired data.*/
+ if ((sdc_cmd6_extract_info(SD_SWITCH_FUNCTION_SPEED, tmp) & 2U) == 2U) {
+ /* Construct command to set the bus speed.*/
+ cmdarg = sdc_cmd6_construct(SD_SWITCH_SET, SD_SWITCH_FUNCTION_SPEED, 1);
+
+ /* Write constructed command and read operation status in single call.*/
+ if (sdc_lld_read_special(sdcp, tmp, N, MMCSD_CMD_SWITCH, cmdarg)) {
+ return HAL_FAILED;
+ }
+
+ /* Check card answer for success status bits.*/
+ if (HAL_SUCCESS == sdc_cmd6_check_status(SD_SWITCH_FUNCTION_SPEED, tmp)) {
+ *clk = SDC_CLK_50MHz;
+ }
+ else {
+ *clk = SDC_CLK_25MHz;
+ }
+ }
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Reads supported bus clock and switch MMC to appropriate mode.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[out] clk pointer to clock enum
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+static bool mmc_detect_bus_clk(SDCDriver *sdcp, sdcbusclk_t *clk) {
+ uint32_t cmdarg;
+ uint32_t resp[1];
+
+ /* Safe default.*/
+ *clk = SDC_CLK_25MHz;
+
+ cmdarg = mmc_cmd6_construct(MMC_SWITCH_WRITE_BYTE, 185, 1, 0);
+ if (!(sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SWITCH, cmdarg, resp) ||
+ MMCSD_R1_ERROR(resp[0]))) {
+ *clk = SDC_CLK_50MHz;
+ }
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Reads supported bus clock and switch card to appropriate mode.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[out] clk pointer to clock enum
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+static bool detect_bus_clk(SDCDriver *sdcp, sdcbusclk_t *clk) {
+
+ if (SDC_MODE_CARDTYPE_MMC == (sdcp->cardmode & SDC_MODE_CARDTYPE_MASK)) {
+ return mmc_detect_bus_clk(sdcp, clk);
+ }
+ return sdc_detect_bus_clk(sdcp, clk);
+}
+
+/**
+ * @brief Sets bus width for SDC.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+static bool sdc_set_bus_width(SDCDriver *sdcp) {
+ uint32_t resp[1];
+
+ if (SDC_MODE_1BIT == sdcp->config->bus_width) {
+ /* Nothing to do. Bus is already in 1bit mode.*/
+ return HAL_SUCCESS;
+ }
+ else if (SDC_MODE_4BIT == sdcp->config->bus_width) {
+ sdc_lld_set_bus_mode(sdcp, SDC_MODE_4BIT);
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, sdcp->rca, resp) ||
+ MMCSD_R1_ERROR(resp[0])) {
+ return HAL_FAILED;
+ }
+
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SET_BUS_WIDTH, 2, resp) ||
+ MMCSD_R1_ERROR(resp[0])) {
+ return HAL_FAILED;
+ }
+ }
+ else {
+ /* SD card does not support 8bit bus.*/
+ return HAL_FAILED;
+ }
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Sets bus width for MMC.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+static bool mmc_set_bus_width(SDCDriver *sdcp) {
+ uint32_t resp[1];
+ uint32_t cmdarg = mmc_cmd6_construct(MMC_SWITCH_WRITE_BYTE, 183, 0, 0);
+
+ switch (sdcp->config->bus_width) {
+ case SDC_MODE_1BIT:
+ /* Nothing to do. Bus is already in 1bit mode.*/
+ return HAL_SUCCESS;
+ case SDC_MODE_4BIT:
+ cmdarg = mmc_cmd6_construct(MMC_SWITCH_WRITE_BYTE, 183, 1, 0);
+ break;
+ case SDC_MODE_8BIT:
+ cmdarg = mmc_cmd6_construct(MMC_SWITCH_WRITE_BYTE, 183, 2, 0);
+ break;
+ default:
+ osalDbgAssert(false, "unexpected case");
+ break;
+ }
+
+ sdc_lld_set_bus_mode(sdcp, sdcp->config->bus_width);
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SWITCH, cmdarg, resp) ||
+ MMCSD_R1_ERROR(resp[0])) {
+ return HAL_FAILED;
+ }
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Wait for the card to complete pending operations.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool _sdc_wait_for_transfer_state(SDCDriver *sdcp) {
+ uint32_t resp[1];
+
+ while (true) {
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEND_STATUS,
+ sdcp->rca, resp) ||
+ MMCSD_R1_ERROR(resp[0])) {
+ return HAL_FAILED;
+ }
+
+ switch (MMCSD_R1_STS(resp[0])) {
+ case MMCSD_STS_TRAN:
+ return HAL_SUCCESS;
+ case MMCSD_STS_DATA:
+ case MMCSD_STS_RCV:
+ case MMCSD_STS_PRG:
+#if SDC_NICE_WAITING == TRUE
+ osalThreadSleepMilliseconds(1);
+#endif
+ continue;
+ default:
+ /* The card should have been initialized so any other state is not
+ valid and is reported as an error.*/
+ return HAL_FAILED;
+ }
+ }
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief SDC Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void sdcInit(void) {
+
+ sdc_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p SDCDriver structure.
+ *
+ * @param[out] sdcp pointer to the @p SDCDriver object
+ *
+ * @init
+ */
+void sdcObjectInit(SDCDriver *sdcp) {
+
+ sdcp->vmt = &sdc_vmt;
+ sdcp->state = BLK_STOP;
+ sdcp->errors = SDC_NO_ERROR;
+ sdcp->config = NULL;
+ sdcp->capacity = 0;
+}
+
+/**
+ * @brief Configures and activates the SDC peripheral.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] config pointer to the @p SDCConfig object, can be @p NULL if
+ * the driver supports a default configuration or
+ * requires no configuration
+ *
+ * @api
+ */
+void sdcStart(SDCDriver *sdcp, const SDCConfig *config) {
+
+ osalDbgCheck(sdcp != NULL);
+
+ osalSysLock();
+ osalDbgAssert((sdcp->state == BLK_STOP) || (sdcp->state == BLK_ACTIVE),
+ "invalid state");
+ sdcp->config = config;
+ sdc_lld_start(sdcp);
+ sdcp->state = BLK_ACTIVE;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the SDC peripheral.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @api
+ */
+void sdcStop(SDCDriver *sdcp) {
+
+ osalDbgCheck(sdcp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((sdcp->state == BLK_STOP) || (sdcp->state == BLK_ACTIVE),
+ "invalid state");
+
+ sdc_lld_stop(sdcp);
+ sdcp->config = NULL;
+ sdcp->state = BLK_STOP;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Performs the initialization procedure on the inserted card.
+ * @details This function should be invoked when a card is inserted and
+ * brings the driver in the @p BLK_READY state where it is possible
+ * to perform read and write operations.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @api
+ */
+bool sdcConnect(SDCDriver *sdcp) {
+ uint32_t resp[1];
+ sdcbusclk_t clk = SDC_CLK_25MHz;
+
+ osalDbgCheck(sdcp != NULL);
+ osalDbgAssert((sdcp->state == BLK_ACTIVE) || (sdcp->state == BLK_READY),
+ "invalid state");
+
+ /* Connection procedure in progress.*/
+ sdcp->state = BLK_CONNECTING;
+
+ /* Card clock initialization.*/
+ sdc_lld_start_clk(sdcp);
+
+ /* Enforces the initial card state.*/
+ sdc_lld_send_cmd_none(sdcp, MMCSD_CMD_GO_IDLE_STATE, 0);
+
+ /* Detect card type.*/
+ if (HAL_FAILED == mode_detect(sdcp)) {
+ goto failed;
+ }
+
+ /* Perform specific initialization procedure.*/
+ if ((sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) == SDC_MODE_CARDTYPE_MMC) {
+ if (HAL_FAILED == mmc_init(sdcp)) {
+ goto failed;
+ }
+ }
+ else {
+ if (HAL_FAILED == sdc_init(sdcp)) {
+ goto failed;
+ }
+ }
+
+ /* Reads CID.*/
+ if (sdc_lld_send_cmd_long_crc(sdcp, MMCSD_CMD_ALL_SEND_CID, 0, sdcp->cid)) {
+ goto failed;
+ }
+
+ /* Asks for the RCA.*/
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEND_RELATIVE_ADDR,
+ 0, &sdcp->rca)) {
+ goto failed;
+ }
+
+ /* Reads CSD.*/
+ if (sdc_lld_send_cmd_long_crc(sdcp, MMCSD_CMD_SEND_CSD,
+ sdcp->rca, sdcp->csd)) {
+ goto failed;
+ }
+
+ /* Selects the card for operations.*/
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEL_DESEL_CARD,
+ sdcp->rca, resp)) {
+ goto failed;
+ }
+
+ /* Switches to high speed.*/
+ if (HAL_SUCCESS != detect_bus_clk(sdcp, &clk)) {
+ goto failed;
+ }
+ sdc_lld_set_data_clk(sdcp, clk);
+
+ /* Reads extended CSD if needed and possible.*/
+ if (SDC_MODE_CARDTYPE_MMC == (sdcp->cardmode & SDC_MODE_CARDTYPE_MASK)) {
+
+ /* The card is a MMC, checking if it is a large device.*/
+ if (_mmcsd_get_slice(sdcp->csd, MMCSD_CSD_MMC_CSD_STRUCTURE_SLICE) > 1U) {
+ uint8_t *ext_csd = sdcp->buf;
+
+ if (sdc_lld_read_special(sdcp, ext_csd, 512, MMCSD_CMD_SEND_EXT_CSD, 0)) {
+ goto failed;
+ }
+
+ /* Capacity from the EXT_CSD.*/
+ sdcp->capacity = _mmcsd_get_capacity_ext(ext_csd);
+ }
+ else {
+ /* Capacity from the normal CSD.*/
+ sdcp->capacity = _mmcsd_get_capacity(sdcp->csd);
+ }
+ }
+ else {
+ /* The card is an SDC, capacity from the normal CSD.*/
+ sdcp->capacity = _mmcsd_get_capacity(sdcp->csd);
+ }
+
+ /* Block length fixed at 512 bytes.*/
+ if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SET_BLOCKLEN,
+ MMCSD_BLOCK_SIZE, resp) ||
+ MMCSD_R1_ERROR(resp[0])) {
+ goto failed;
+ }
+
+ /* Switches to wide bus mode.*/
+ switch (sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) {
+ case SDC_MODE_CARDTYPE_SDV11:
+ case SDC_MODE_CARDTYPE_SDV20:
+ if (HAL_FAILED == sdc_set_bus_width(sdcp)) {
+ goto failed;
+ }
+ break;
+ case SDC_MODE_CARDTYPE_MMC:
+ if (HAL_FAILED == mmc_set_bus_width(sdcp)) {
+ goto failed;
+ }
+ break;
+ default:
+ /* Unknown type.*/
+ goto failed;
+ }
+
+ /* Initialization complete.*/
+ sdcp->state = BLK_READY;
+ return HAL_SUCCESS;
+
+ /* Connection failed, state reset to BLK_ACTIVE.*/
+failed:
+ sdc_lld_stop_clk(sdcp);
+ sdcp->state = BLK_ACTIVE;
+ return HAL_FAILED;
+}
+
+/**
+ * @brief Brings the driver in a state safe for card removal.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @api
+ */
+bool sdcDisconnect(SDCDriver *sdcp) {
+
+ osalDbgCheck(sdcp != NULL);
+
+ osalSysLock();
+ osalDbgAssert((sdcp->state == BLK_ACTIVE) || (sdcp->state == BLK_READY),
+ "invalid state");
+ if (sdcp->state == BLK_ACTIVE) {
+ osalSysUnlock();
+ return HAL_SUCCESS;
+ }
+ sdcp->state = BLK_DISCONNECTING;
+ osalSysUnlock();
+
+ /* Waits for eventual pending operations completion.*/
+ if (_sdc_wait_for_transfer_state(sdcp)) {
+ sdc_lld_stop_clk(sdcp);
+ sdcp->state = BLK_ACTIVE;
+ return HAL_FAILED;
+ }
+
+ /* Card clock stopped.*/
+ sdc_lld_stop_clk(sdcp);
+ sdcp->state = BLK_ACTIVE;
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Reads one or more blocks.
+ * @pre The driver must be in the @p BLK_READY state after a successful
+ * sdcConnect() invocation.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to read
+ * @param[out] buf pointer to the read buffer
+ * @param[in] n number of blocks to read
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @api
+ */
+bool sdcRead(SDCDriver *sdcp, uint32_t startblk, uint8_t *buf, uint32_t n) {
+ bool status;
+
+ osalDbgCheck((sdcp != NULL) && (buf != NULL) && (n > 0U));
+ osalDbgAssert(sdcp->state == BLK_READY, "invalid state");
+
+ if ((startblk + n - 1U) > sdcp->capacity) {
+ sdcp->errors |= SDC_OVERFLOW_ERROR;
+ return HAL_FAILED;
+ }
+
+ /* Read operation in progress.*/
+ sdcp->state = BLK_READING;
+
+ status = sdc_lld_read(sdcp, startblk, buf, n);
+
+ /* Read operation finished.*/
+ sdcp->state = BLK_READY;
+ return status;
+}
+
+/**
+ * @brief Writes one or more blocks.
+ * @pre The driver must be in the @p BLK_READY state after a successful
+ * sdcConnect() invocation.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to write
+ * @param[out] buf pointer to the write buffer
+ * @param[in] n number of blocks to write
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @api
+ */
+bool sdcWrite(SDCDriver *sdcp, uint32_t startblk,
+ const uint8_t *buf, uint32_t n) {
+ bool status;
+
+ osalDbgCheck((sdcp != NULL) && (buf != NULL) && (n > 0U));
+ osalDbgAssert(sdcp->state == BLK_READY, "invalid state");
+
+ if ((startblk + n - 1U) > sdcp->capacity) {
+ sdcp->errors |= SDC_OVERFLOW_ERROR;
+ return HAL_FAILED;
+ }
+
+ /* Write operation in progress.*/
+ sdcp->state = BLK_WRITING;
+
+ status = sdc_lld_write(sdcp, startblk, buf, n);
+
+ /* Write operation finished.*/
+ sdcp->state = BLK_READY;
+ return status;
+}
+
+/**
+ * @brief Returns the errors mask associated to the previous operation.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @return The errors mask.
+ *
+ * @api
+ */
+sdcflags_t sdcGetAndClearErrors(SDCDriver *sdcp) {
+ sdcflags_t flags;
+
+ osalDbgCheck(sdcp != NULL);
+ osalDbgAssert(sdcp->state == BLK_READY, "invalid state");
+
+ osalSysLock();
+ flags = sdcp->errors;
+ sdcp->errors = SDC_NO_ERROR;
+ osalSysUnlock();
+ return flags;
+}
+
+/**
+ * @brief Waits for card idle condition.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS the operation succeeded.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @api
+ */
+bool sdcSync(SDCDriver *sdcp) {
+ bool result;
+
+ osalDbgCheck(sdcp != NULL);
+
+ if (sdcp->state != BLK_READY) {
+ return HAL_FAILED;
+ }
+
+ /* Synchronization operation in progress.*/
+ sdcp->state = BLK_SYNCING;
+
+ result = sdc_lld_sync(sdcp);
+
+ /* Synchronization operation finished.*/
+ sdcp->state = BLK_READY;
+ return result;
+}
+
+/**
+ * @brief Returns the media info.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[out] bdip pointer to a @p BlockDeviceInfo structure
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS the operation succeeded.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @api
+ */
+bool sdcGetInfo(SDCDriver *sdcp, BlockDeviceInfo *bdip) {
+
+ osalDbgCheck((sdcp != NULL) && (bdip != NULL));
+
+ if (sdcp->state != BLK_READY) {
+ return HAL_FAILED;
+ }
+
+ bdip->blk_num = sdcp->capacity;
+ bdip->blk_size = MMCSD_BLOCK_SIZE;
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Erases the supplied blocks.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk starting block number
+ * @param[in] endblk ending block number
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS the operation succeeded.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @api
+ */
+bool sdcErase(SDCDriver *sdcp, uint32_t startblk, uint32_t endblk) {
+ uint32_t resp[1];
+
+ osalDbgCheck((sdcp != NULL));
+ osalDbgAssert(sdcp->state == BLK_READY, "invalid state");
+
+ /* Erase operation in progress.*/
+ sdcp->state = BLK_WRITING;
+
+ /* Handling command differences between HC and normal cards.*/
+ if ((sdcp->cardmode & SDC_MODE_HIGH_CAPACITY) != 0U) {
+ startblk *= MMCSD_BLOCK_SIZE;
+ endblk *= MMCSD_BLOCK_SIZE;
+ }
+
+ if (_sdc_wait_for_transfer_state(sdcp)) {
+ goto failed;
+ }
+
+ if ((sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_ERASE_RW_BLK_START,
+ startblk, resp) != HAL_SUCCESS) ||
+ MMCSD_R1_ERROR(resp[0])) {
+ goto failed;
+ }
+
+ if ((sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_ERASE_RW_BLK_END,
+ endblk, resp) != HAL_SUCCESS) ||
+ MMCSD_R1_ERROR(resp[0])) {
+ goto failed;
+ }
+
+ if ((sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_ERASE,
+ 0, resp) != HAL_SUCCESS) ||
+ MMCSD_R1_ERROR(resp[0])) {
+ goto failed;
+ }
+
+ /* Quick sleep to allow it to transition to programming or receiving state */
+ /* CHTODO: ??????????????????????????? */
+
+ /* Wait for it to return to transfer state to indicate it has finished erasing */
+ if (_sdc_wait_for_transfer_state(sdcp)) {
+ goto failed;
+ }
+
+ sdcp->state = BLK_READY;
+ return HAL_SUCCESS;
+
+failed:
+ sdcp->state = BLK_READY;
+ return HAL_FAILED;
+}
+
+#endif /* HAL_USE_SDC == TRUE */
+
+/** @} */
+
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_serial.c b/ChibiOS_20.3.2/os/hal/src/hal_serial.c
new file mode 100644
index 0000000..f4a7472
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_serial.c
@@ -0,0 +1,349 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_serial.c
+ * @brief Serial Driver code.
+ *
+ * @addtogroup SERIAL
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*
+ * Interface implementation, the following functions just invoke the equivalent
+ * queue-level function or macro.
+ */
+
+static size_t _write(void *ip, const uint8_t *bp, size_t n) {
+
+ return oqWriteTimeout(&((SerialDriver *)ip)->oqueue, bp,
+ n, TIME_INFINITE);
+}
+
+static size_t _read(void *ip, uint8_t *bp, size_t n) {
+
+ return iqReadTimeout(&((SerialDriver *)ip)->iqueue, bp,
+ n, TIME_INFINITE);
+}
+
+static msg_t _put(void *ip, uint8_t b) {
+
+ return oqPutTimeout(&((SerialDriver *)ip)->oqueue, b, TIME_INFINITE);
+}
+
+static msg_t _get(void *ip) {
+
+ return iqGetTimeout(&((SerialDriver *)ip)->iqueue, TIME_INFINITE);
+}
+
+static msg_t _putt(void *ip, uint8_t b, sysinterval_t timeout) {
+
+ return oqPutTimeout(&((SerialDriver *)ip)->oqueue, b, timeout);
+}
+
+static msg_t _gett(void *ip, sysinterval_t timeout) {
+
+ return iqGetTimeout(&((SerialDriver *)ip)->iqueue, timeout);
+}
+
+static size_t _writet(void *ip, const uint8_t *bp, size_t n,
+ sysinterval_t timeout) {
+
+ return oqWriteTimeout(&((SerialDriver *)ip)->oqueue, bp, n, timeout);
+}
+
+static size_t _readt(void *ip, uint8_t *bp, size_t n,
+ sysinterval_t timeout) {
+
+ return iqReadTimeout(&((SerialDriver *)ip)->iqueue, bp, n, timeout);
+}
+
+static msg_t _ctl(void *ip, unsigned int operation, void *arg) {
+ SerialDriver *sdp = (SerialDriver *)ip;
+
+ osalDbgCheck(sdp != NULL);
+
+ switch (operation) {
+ case CHN_CTL_NOP:
+ osalDbgCheck(arg == NULL);
+ break;
+ case CHN_CTL_INVALID:
+ osalDbgAssert(false, "invalid CTL operation");
+ break;
+ default:
+#if defined(SD_LLD_IMPLEMENTS_CTL)
+ /* Delegating to the LLD if supported.*/
+ return sd_lld_control(sdp, operation, arg);
+#else
+ break;
+#endif
+ }
+ return MSG_OK;
+}
+
+static const struct SerialDriverVMT vmt = {
+ (size_t)0,
+ _write, _read, _put, _get,
+ _putt, _gett, _writet, _readt,
+ _ctl
+};
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Serial Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void sdInit(void) {
+
+ sd_lld_init();
+}
+
+/**
+ * @brief Initializes a generic serial driver object.
+ * @details The HW dependent part of the initialization has to be performed
+ * outside, usually in the hardware initialization code.
+ *
+ * @param[out] sdp pointer to a @p SerialDriver structure
+ * @param[in] inotify pointer to a callback function that is invoked when
+ * some data is read from the Queue. The value can be
+ * @p NULL.
+ * @param[in] onotify pointer to a callback function that is invoked when
+ * some data is written in the Queue. The value can be
+ * @p NULL.
+ *
+ * @init
+ */
+#if !defined(SERIAL_ADVANCED_BUFFERING_SUPPORT) || \
+ (SERIAL_ADVANCED_BUFFERING_SUPPORT == FALSE) || \
+ defined(__DOXYGEN__)
+void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify) {
+
+ sdp->vmt = &vmt;
+ osalEventObjectInit(&sdp->event);
+ sdp->state = SD_STOP;
+ iqObjectInit(&sdp->iqueue, sdp->ib, SERIAL_BUFFERS_SIZE, inotify, sdp);
+ oqObjectInit(&sdp->oqueue, sdp->ob, SERIAL_BUFFERS_SIZE, onotify, sdp);
+}
+#else
+void sdObjectInit(SerialDriver *sdp) {
+
+ sdp->vmt = &vmt;
+ osalEventObjectInit(&sdp->event);
+ sdp->state = SD_STOP;
+}
+#endif
+
+/**
+ * @brief Configures and starts the driver.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ * @param[in] config the architecture-dependent serial driver configuration.
+ * If this parameter is set to @p NULL then a default
+ * configuration is used.
+ *
+ * @api
+ */
+void sdStart(SerialDriver *sdp, const SerialConfig *config) {
+
+ osalDbgCheck(sdp != NULL);
+
+ osalSysLock();
+ osalDbgAssert((sdp->state == SD_STOP) || (sdp->state == SD_READY),
+ "invalid state");
+ sd_lld_start(sdp, config);
+ sdp->state = SD_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Stops the driver.
+ * @details Any thread waiting on the driver's queues will be awakened with
+ * the message @p MSG_RESET.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ *
+ * @api
+ */
+void sdStop(SerialDriver *sdp) {
+
+ osalDbgCheck(sdp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((sdp->state == SD_STOP) || (sdp->state == SD_READY),
+ "invalid state");
+
+ sd_lld_stop(sdp);
+ sdp->state = SD_STOP;
+ oqResetI(&sdp->oqueue);
+ iqResetI(&sdp->iqueue);
+ osalOsRescheduleS();
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Handles incoming data.
+ * @details This function must be called from the input interrupt service
+ * routine in order to enqueue incoming data and generate the
+ * related events.
+ * @note The incoming data event is only generated when the input queue
+ * becomes non-empty.
+ * @note In order to gain some performance it is suggested to not use
+ * this function directly but copy this code directly into the
+ * interrupt service routine.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver structure
+ * @param[in] b the byte to be written in the driver's Input Queue
+ *
+ * @iclass
+ */
+void sdIncomingDataI(SerialDriver *sdp, uint8_t b) {
+
+ osalDbgCheckClassI();
+ osalDbgCheck(sdp != NULL);
+
+ if (iqIsEmptyI(&sdp->iqueue))
+ chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
+ if (iqPutI(&sdp->iqueue, b) < MSG_OK)
+ chnAddFlagsI(sdp, SD_QUEUE_FULL_ERROR);
+}
+
+/**
+ * @brief Handles outgoing data.
+ * @details Must be called from the output interrupt service routine in order
+ * to get the next byte to be transmitted.
+ * @note In order to gain some performance it is suggested to not use
+ * this function directly but copy this code directly into the
+ * interrupt service routine.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver structure
+ * @return The byte value read from the driver's output queue.
+ * @retval MSG_TIMEOUT if the queue is empty (the lower driver usually
+ * disables the interrupt source when this happens).
+ *
+ * @iclass
+ */
+msg_t sdRequestDataI(SerialDriver *sdp) {
+ msg_t b;
+
+ osalDbgCheckClassI();
+ osalDbgCheck(sdp != NULL);
+
+ b = oqGetI(&sdp->oqueue);
+ if (b < MSG_OK)
+ chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
+ return b;
+}
+
+/**
+ * @brief Direct output check on a @p SerialDriver.
+ * @note This function bypasses the indirect access to the channel and
+ * checks directly the output queue. This is faster but cannot
+ * be used to check different channels implementations.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver structure
+ * @return The queue status.
+ * @retval false if the next write operation would not block.
+ * @retval true if the next write operation would block.
+ *
+ * @deprecated
+ *
+ * @api
+ */
+bool sdPutWouldBlock(SerialDriver *sdp) {
+ bool b;
+
+ osalSysLock();
+ b = oqIsFullI(&sdp->oqueue);
+ osalSysUnlock();
+
+ return b;
+}
+
+/**
+ * @brief Direct input check on a @p SerialDriver.
+ * @note This function bypasses the indirect access to the channel and
+ * checks directly the input queue. This is faster but cannot
+ * be used to check different channels implementations.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver structure
+ * @return The queue status.
+ * @retval false if the next write operation would not block.
+ * @retval true if the next write operation would block.
+ *
+ * @deprecated
+ *
+ * @api
+ */
+bool sdGetWouldBlock(SerialDriver *sdp) {
+ bool b;
+
+ osalSysLock();
+ b = iqIsEmptyI(&sdp->iqueue);
+ osalSysUnlock();
+
+ return b;
+}
+
+/**
+ * @brief Control operation on a serial port.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ * @param[in] operation control operation code
+ * @param[in,out] arg operation argument
+ *
+ * @return The control operation status.
+ * @retval MSG_OK in case of success.
+ * @retval MSG_TIMEOUT in case of operation timeout.
+ * @retval MSG_RESET in case of operation reset.
+ *
+ * @api
+ */
+msg_t sdControl(SerialDriver *sdp, unsigned int operation, void *arg) {
+
+ return _ctl((void *)sdp, operation, arg);
+}
+
+#endif /* HAL_USE_SERIAL == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_serial_usb.c b/ChibiOS_20.3.2/os/hal/src/hal_serial_usb.c
new file mode 100644
index 0000000..9eabb15
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_serial_usb.c
@@ -0,0 +1,553 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_serial_usb.c
+ * @brief Serial over USB Driver code.
+ *
+ * @addtogroup SERIAL_USB
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_SERIAL_USB == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*
+ * Current Line Coding.
+ */
+static cdc_linecoding_t linecoding = {
+ {0x00, 0x96, 0x00, 0x00}, /* 38400. */
+ LC_STOP_1, LC_PARITY_NONE, 8
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static bool sdu_start_receive(SerialUSBDriver *sdup) {
+ uint8_t *buf;
+
+ /* If the USB driver is not in the appropriate state then transactions
+ must not be started.*/
+ if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) ||
+ (sdup->state != SDU_READY)) {
+ return true;
+ }
+
+ /* Checking if there is already a transaction ongoing on the endpoint.*/
+ if (usbGetReceiveStatusI(sdup->config->usbp, sdup->config->bulk_in)) {
+ return true;
+ }
+
+ /* Checking if there is a buffer ready for incoming data.*/
+ buf = ibqGetEmptyBufferI(&sdup->ibqueue);
+ if (buf == NULL) {
+ return true;
+ }
+
+ /* Buffer found, starting a new transaction.*/
+ usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out,
+ buf, SERIAL_USB_BUFFERS_SIZE);
+
+ return false;
+}
+
+/*
+ * Interface implementation.
+ */
+
+static size_t _write(void *ip, const uint8_t *bp, size_t n) {
+
+ return obqWriteTimeout(&((SerialUSBDriver *)ip)->obqueue, bp,
+ n, TIME_INFINITE);
+}
+
+static size_t _read(void *ip, uint8_t *bp, size_t n) {
+
+ return ibqReadTimeout(&((SerialUSBDriver *)ip)->ibqueue, bp,
+ n, TIME_INFINITE);
+}
+
+static msg_t _put(void *ip, uint8_t b) {
+
+ return obqPutTimeout(&((SerialUSBDriver *)ip)->obqueue, b, TIME_INFINITE);
+}
+
+static msg_t _get(void *ip) {
+
+ return ibqGetTimeout(&((SerialUSBDriver *)ip)->ibqueue, TIME_INFINITE);
+}
+
+static msg_t _putt(void *ip, uint8_t b, sysinterval_t timeout) {
+
+ return obqPutTimeout(&((SerialUSBDriver *)ip)->obqueue, b, timeout);
+}
+
+static msg_t _gett(void *ip, sysinterval_t timeout) {
+
+ return ibqGetTimeout(&((SerialUSBDriver *)ip)->ibqueue, timeout);
+}
+
+static size_t _writet(void *ip, const uint8_t *bp, size_t n,
+ sysinterval_t timeout) {
+
+ return obqWriteTimeout(&((SerialUSBDriver *)ip)->obqueue, bp, n, timeout);
+}
+
+static size_t _readt(void *ip, uint8_t *bp, size_t n,
+ sysinterval_t timeout) {
+
+ return ibqReadTimeout(&((SerialUSBDriver *)ip)->ibqueue, bp, n, timeout);
+}
+
+static msg_t _ctl(void *ip, unsigned int operation, void *arg) {
+ SerialUSBDriver *sdup = (SerialUSBDriver *)ip;
+
+ osalDbgCheck(sdup != NULL);
+
+ switch (operation) {
+ case CHN_CTL_NOP:
+ osalDbgCheck(arg == NULL);
+ break;
+ case CHN_CTL_INVALID:
+ osalDbgAssert(false, "invalid CTL operation");
+ break;
+ default:
+#if defined(SDU_LLD_IMPLEMENTS_CTL)
+ /* The SDU driver does not have a LLD but the application can use this
+ hook to implement extra controls by supplying this function.*/
+ extern msg_t sdu_lld_control(SerialUSBDriver *sdup,
+ unsigned int operation,
+ void *arg);
+ return sdu_lld_control(sdup, operation, arg);
+#else
+ break;
+#endif
+ }
+ return MSG_OK;
+}
+
+static const struct SerialUSBDriverVMT vmt = {
+ (size_t)0,
+ _write, _read, _put, _get,
+ _putt, _gett, _writet, _readt,
+ _ctl
+};
+
+/**
+ * @brief Notification of empty buffer released into the input buffers queue.
+ *
+ * @param[in] bqp the buffers queue pointer.
+ */
+static void ibnotify(io_buffers_queue_t *bqp) {
+ SerialUSBDriver *sdup = bqGetLinkX(bqp);
+ (void) sdu_start_receive(sdup);
+}
+
+/**
+ * @brief Notification of filled buffer inserted into the output buffers queue.
+ *
+ * @param[in] bqp the buffers queue pointer.
+ */
+static void obnotify(io_buffers_queue_t *bqp) {
+ size_t n;
+ SerialUSBDriver *sdup = bqGetLinkX(bqp);
+
+ /* If the USB driver is not in the appropriate state then transactions
+ must not be started.*/
+ if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) ||
+ (sdup->state != SDU_READY)) {
+ return;
+ }
+
+ /* Checking if there is already a transaction ongoing on the endpoint.*/
+ if (!usbGetTransmitStatusI(sdup->config->usbp, sdup->config->bulk_in)) {
+ /* Getting a full buffer, a buffer is available for sure because this
+ callback is invoked when one has been inserted.*/
+ uint8_t *buf = obqGetFullBufferI(&sdup->obqueue, &n);
+ osalDbgAssert(buf != NULL, "buffer not found");
+ usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in, buf, n);
+ }
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Serial Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void sduInit(void) {
+}
+
+/**
+ * @brief Initializes a generic full duplex driver object.
+ * @details The HW dependent part of the initialization has to be performed
+ * outside, usually in the hardware initialization code.
+ *
+ * @param[out] sdup pointer to a @p SerialUSBDriver structure
+ *
+ * @init
+ */
+void sduObjectInit(SerialUSBDriver *sdup) {
+
+ sdup->vmt = &vmt;
+ osalEventObjectInit(&sdup->event);
+ sdup->state = SDU_STOP;
+ ibqObjectInit(&sdup->ibqueue, true, sdup->ib,
+ SERIAL_USB_BUFFERS_SIZE, SERIAL_USB_BUFFERS_NUMBER,
+ ibnotify, sdup);
+ obqObjectInit(&sdup->obqueue, true, sdup->ob,
+ SERIAL_USB_BUFFERS_SIZE, SERIAL_USB_BUFFERS_NUMBER,
+ obnotify, sdup);
+}
+
+/**
+ * @brief Configures and starts the driver.
+ *
+ * @param[in] sdup pointer to a @p SerialUSBDriver object
+ * @param[in] config the serial over USB driver configuration
+ *
+ * @api
+ */
+void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config) {
+ USBDriver *usbp = config->usbp;
+
+ osalDbgCheck(sdup != NULL);
+
+ osalSysLock();
+ osalDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY),
+ "invalid state");
+ usbp->in_params[config->bulk_in - 1U] = sdup;
+ usbp->out_params[config->bulk_out - 1U] = sdup;
+ if (config->int_in > 0U) {
+ usbp->in_params[config->int_in - 1U] = sdup;
+ }
+ sdup->config = config;
+ sdup->state = SDU_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Stops the driver.
+ * @details Any thread waiting on the driver's queues will be awakened with
+ * the message @p MSG_RESET.
+ *
+ * @param[in] sdup pointer to a @p SerialUSBDriver object
+ *
+ * @api
+ */
+void sduStop(SerialUSBDriver *sdup) {
+ USBDriver *usbp = sdup->config->usbp;
+
+ osalDbgCheck(sdup != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY),
+ "invalid state");
+
+ /* Driver in stopped state.*/
+ usbp->in_params[sdup->config->bulk_in - 1U] = NULL;
+ usbp->out_params[sdup->config->bulk_out - 1U] = NULL;
+ if (sdup->config->int_in > 0U) {
+ usbp->in_params[sdup->config->int_in - 1U] = NULL;
+ }
+ sdup->config = NULL;
+ sdup->state = SDU_STOP;
+
+ /* Enforces a disconnection.*/
+ chnAddFlagsI(sdup, CHN_DISCONNECTED);
+ ibqResetI(&sdup->ibqueue);
+ obqResetI(&sdup->obqueue);
+ osalOsRescheduleS();
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief USB device suspend handler.
+ * @details Generates a @p CHN_DISCONNECT event and puts queues in
+ * non-blocking mode, this way the application cannot get stuck
+ * in the middle of an I/O operations.
+ * @note If this function is not called from an ISR then an explicit call
+ * to @p osalOsRescheduleS() in necessary afterward.
+ *
+ * @param[in] sdup pointer to a @p SerialUSBDriver object
+ *
+ * @iclass
+ */
+void sduSuspendHookI(SerialUSBDriver *sdup) {
+
+ /* Avoiding events spam.*/
+ if (bqIsSuspendedX(&sdup->ibqueue) && bqIsSuspendedX(&sdup->obqueue)) {
+ return;
+ }
+ chnAddFlagsI(sdup, CHN_DISCONNECTED);
+ bqSuspendI(&sdup->ibqueue);
+ bqSuspendI(&sdup->obqueue);
+}
+
+/**
+ * @brief USB device wakeup handler.
+ * @details Generates a @p CHN_CONNECT event and resumes normal queues
+ * operations.
+ *
+ * @note If this function is not called from an ISR then an explicit call
+ * to @p osalOsRescheduleS() in necessary afterward.
+ *
+ * @param[in] sdup pointer to a @p SerialUSBDriver object
+ *
+ * @iclass
+ */
+void sduWakeupHookI(SerialUSBDriver *sdup) {
+
+ chnAddFlagsI(sdup, CHN_CONNECTED);
+ bqResumeX(&sdup->ibqueue);
+ bqResumeX(&sdup->obqueue);
+}
+
+/**
+ * @brief USB device configured handler.
+ *
+ * @param[in] sdup pointer to a @p SerialUSBDriver object
+ *
+ * @iclass
+ */
+void sduConfigureHookI(SerialUSBDriver *sdup) {
+
+ ibqResetI(&sdup->ibqueue);
+ bqResumeX(&sdup->ibqueue);
+ obqResetI(&sdup->obqueue);
+ bqResumeX(&sdup->obqueue);
+ chnAddFlagsI(sdup, CHN_CONNECTED);
+ (void) sdu_start_receive(sdup);
+}
+
+/**
+ * @brief Default requests hook.
+ * @details Applications wanting to use the Serial over USB driver can use
+ * this function as requests hook in the USB configuration.
+ * The following requests are emulated:
+ * - CDC_GET_LINE_CODING.
+ * - CDC_SET_LINE_CODING.
+ * - CDC_SET_CONTROL_LINE_STATE.
+ * .
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @return The hook status.
+ * @retval true Message handled internally.
+ * @retval false Message not handled.
+ */
+bool sduRequestsHook(USBDriver *usbp) {
+
+ if ((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) {
+ switch (usbp->setup[1]) {
+ case CDC_GET_LINE_CODING:
+ usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding), NULL);
+ return true;
+ case CDC_SET_LINE_CODING:
+ usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding), NULL);
+ return true;
+ case CDC_SET_CONTROL_LINE_STATE:
+ /* Nothing to do, there are no control lines.*/
+ usbSetupTransfer(usbp, NULL, 0, NULL);
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
+/**
+ * @brief SOF handler.
+ * @details The SOF interrupt is used for automatic flushing of incomplete
+ * buffers pending in the output queue.
+ *
+ * @param[in] sdup pointer to a @p SerialUSBDriver object
+ *
+ * @iclass
+ */
+void sduSOFHookI(SerialUSBDriver *sdup) {
+
+ /* If the USB driver is not in the appropriate state then transactions
+ must not be started.*/
+ if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) ||
+ (sdup->state != SDU_READY)) {
+ return;
+ }
+
+ /* If there is already a transaction ongoing then another one cannot be
+ started.*/
+ if (usbGetTransmitStatusI(sdup->config->usbp, sdup->config->bulk_in)) {
+ return;
+ }
+
+ /* Checking if there only a buffer partially filled, if so then it is
+ enforced in the queue and transmitted.*/
+ if (obqTryFlushI(&sdup->obqueue)) {
+ size_t n;
+ uint8_t *buf = obqGetFullBufferI(&sdup->obqueue, &n);
+
+ osalDbgAssert(buf != NULL, "queue is empty");
+
+ usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in, buf, n);
+ }
+}
+
+/**
+ * @brief Default data transmitted callback.
+ * @details The application must use this function as callback for the IN
+ * data endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep IN endpoint number
+ */
+void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
+ uint8_t *buf;
+ size_t n;
+ SerialUSBDriver *sdup = usbp->in_params[ep - 1U];
+
+ if (sdup == NULL) {
+ return;
+ }
+
+ osalSysLockFromISR();
+
+ /* Signaling that space is available in the output queue.*/
+ chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY);
+
+ /* Freeing the buffer just transmitted, if it was not a zero size packet.*/
+ if (usbp->epc[ep]->in_state->txsize > 0U) {
+ obqReleaseEmptyBufferI(&sdup->obqueue);
+ }
+
+ /* Checking if there is a buffer ready for transmission.*/
+ buf = obqGetFullBufferI(&sdup->obqueue, &n);
+
+ if (buf != NULL) {
+ /* The endpoint cannot be busy, we are in the context of the callback,
+ so it is safe to transmit without a check.*/
+ usbStartTransmitI(usbp, ep, buf, n);
+ }
+ else if ((usbp->epc[ep]->in_state->txsize > 0U) &&
+ ((usbp->epc[ep]->in_state->txsize &
+ ((size_t)usbp->epc[ep]->in_maxsize - 1U)) == 0U)) {
+ /* Transmit zero sized packet in case the last one has maximum allowed
+ size. Otherwise the recipient may expect more data coming soon and
+ not return buffered data to app. See section 5.8.3 Bulk Transfer
+ Packet Size Constraints of the USB Specification document.*/
+ usbStartTransmitI(usbp, ep, usbp->setup, 0);
+
+ }
+ else {
+ /* Nothing to transmit.*/
+ }
+
+ osalSysUnlockFromISR();
+}
+
+/**
+ * @brief Default data received callback.
+ * @details The application must use this function as callback for the OUT
+ * data endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep OUT endpoint number
+ */
+void sduDataReceived(USBDriver *usbp, usbep_t ep) {
+ size_t size;
+ SerialUSBDriver *sdup = usbp->out_params[ep - 1U];
+
+ if (sdup == NULL) {
+ return;
+ }
+
+ osalSysLockFromISR();
+
+ /* Checking for zero-size transactions.*/
+ size = usbGetReceiveTransactionSizeX(sdup->config->usbp,
+ sdup->config->bulk_out);
+ if (size > (size_t)0) {
+ /* Signaling that data is available in the input queue.*/
+ chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE);
+
+ /* Posting the filled buffer in the queue.*/
+ ibqPostFullBufferI(&sdup->ibqueue, size);
+ }
+
+ /* The endpoint cannot be busy, we are in the context of the callback,
+ so a packet is in the buffer for sure. Trying to get a free buffer
+ for the next transaction.*/
+ (void) sdu_start_receive(sdup);
+
+ osalSysUnlockFromISR();
+}
+
+/**
+ * @brief Default data received callback.
+ * @details The application must use this function as callback for the IN
+ * interrupt endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ */
+void sduInterruptTransmitted(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+ (void)ep;
+}
+
+/**
+ * @brief Control operation on a serial USB port.
+ *
+ * @param[in] usbp pointer to a @p USBDriver object
+ * @param[in] operation control operation code
+ * @param[in,out] arg operation argument
+ *
+ * @return The control operation status.
+ * @retval MSG_OK in case of success.
+ * @retval MSG_TIMEOUT in case of operation timeout.
+ * @retval MSG_RESET in case of operation reset.
+ *
+ * @api
+ */
+msg_t sduControl(USBDriver *usbp, unsigned int operation, void *arg) {
+
+ return _ctl((void *)usbp, operation, arg);
+}
+
+#endif /* HAL_USE_SERIAL_USB == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_sio.c b/ChibiOS_20.3.2/os/hal/src/hal_sio.c
new file mode 100644
index 0000000..47901e2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_sio.c
@@ -0,0 +1,126 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_sio.c
+ * @brief SIO Driver code.
+ *
+ * @addtogroup SIO
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_SIO == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief SIO Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void sioInit(void) {
+
+ sio_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p SIODriver structure.
+ *
+ * @param[out] siop pointer to the @p SIODriver object
+ *
+ * @init
+ */
+void sioObjectInit(SIODriver *siop) {
+
+ siop->state = SIO_STOP;
+ siop->config = NULL;
+
+ /* Optional, user-defined initializer.*/
+#if defined(SIO_DRIVER_EXT_INIT_HOOK)
+ SIO_DRIVER_EXT_INIT_HOOK(siop);
+#endif
+}
+
+/**
+ * @brief Configures and activates the SIO peripheral.
+ *
+ * @param[in] siop pointer to the @p SIODriver object
+ * @param[in] config pointer to the @p SIOConfig object
+ *
+ * @api
+ */
+void sioStart(SIODriver *siop, const SIOConfig *config) {
+
+ osalDbgCheck((siop != NULL) && (config != NULL));
+
+ osalSysLock();
+ osalDbgAssert((siop->state == SIO_STOP) || (siop->state == SIO_READY),
+ "invalid state");
+
+ siop->config = config;
+ sio_lld_start(siop);
+ siop->state = SIO_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the SIO peripheral.
+ *
+ * @param[in] siop pointer to the @p SIODriver object
+ *
+ * @api
+ */
+void sioStop(SIODriver *siop) {
+
+ osalDbgCheck(siop != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((siop->state == SIO_STOP) || (siop->state == SIO_READY),
+ "invalid state");
+
+ sio_lld_stop(siop);
+ siop->config = NULL;
+ siop->state = SIO_STOP;
+
+ osalSysUnlock();
+}
+
+#endif /* HAL_USE_SIO == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_spi.c b/ChibiOS_20.3.2/os/hal/src/hal_spi.c
new file mode 100644
index 0000000..aae3bd8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_spi.c
@@ -0,0 +1,469 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_spi.c
+ * @brief SPI Driver code.
+ *
+ * @addtogroup SPI
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief SPI Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void spiInit(void) {
+
+ spi_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p SPIDriver structure.
+ *
+ * @param[out] spip pointer to the @p SPIDriver object
+ *
+ * @init
+ */
+void spiObjectInit(SPIDriver *spip) {
+
+ spip->state = SPI_STOP;
+ spip->config = NULL;
+#if SPI_USE_WAIT == TRUE
+ spip->thread = NULL;
+#endif
+#if SPI_USE_MUTUAL_EXCLUSION == TRUE
+ osalMutexObjectInit(&spip->mutex);
+#endif
+#if defined(SPI_DRIVER_EXT_INIT_HOOK)
+ SPI_DRIVER_EXT_INIT_HOOK(spip);
+#endif
+}
+
+/**
+ * @brief Configures and activates the SPI peripheral.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] config pointer to the @p SPIConfig object
+ *
+ * @api
+ */
+void spiStart(SPIDriver *spip, const SPIConfig *config) {
+
+ osalDbgCheck((spip != NULL) && (config != NULL));
+
+ osalSysLock();
+ osalDbgAssert((spip->state == SPI_STOP) || (spip->state == SPI_READY),
+ "invalid state");
+ spip->config = config;
+ spi_lld_start(spip);
+ spip->state = SPI_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the SPI peripheral.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @api
+ */
+void spiStop(SPIDriver *spip) {
+
+ osalDbgCheck(spip != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((spip->state == SPI_STOP) || (spip->state == SPI_READY),
+ "invalid state");
+
+ spi_lld_stop(spip);
+ spip->config = NULL;
+ spip->state = SPI_STOP;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Asserts the slave select signal and prepares for transfers.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @api
+ */
+void spiSelect(SPIDriver *spip) {
+
+ osalDbgCheck(spip != NULL);
+
+ osalSysLock();
+ osalDbgAssert(spip->state == SPI_READY, "not ready");
+ spiSelectI(spip);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deasserts the slave select signal.
+ * @details The previously selected peripheral is unselected.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @api
+ */
+void spiUnselect(SPIDriver *spip) {
+
+ osalDbgCheck(spip != NULL);
+
+ osalSysLock();
+ osalDbgAssert(spip->state == SPI_READY, "not ready");
+ spiUnselectI(spip);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Ignores data on the SPI bus.
+ * @details This asynchronous function starts the transmission of a series of
+ * idle words on the SPI bus and ignores the received data.
+ * @pre A slave must have been selected using @p spiSelect() or
+ * @p spiSelectI().
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be ignored
+ *
+ * @api
+ */
+void spiStartIgnore(SPIDriver *spip, size_t n) {
+
+ osalDbgCheck((spip != NULL) && (n > 0U));
+
+ osalSysLock();
+ osalDbgAssert(spip->state == SPI_READY, "not ready");
+ spiStartIgnoreI(spip, n);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Exchanges data on the SPI bus.
+ * @details This asynchronous function starts a simultaneous transmit/receive
+ * operation.
+ * @pre A slave must have been selected using @p spiSelect() or
+ * @p spiSelectI().
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be exchanged
+ * @param[in] txbuf the pointer to the transmit buffer
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @api
+ */
+void spiStartExchange(SPIDriver *spip, size_t n,
+ const void *txbuf, void *rxbuf) {
+
+ osalDbgCheck((spip != NULL) && (n > 0U) &&
+ (rxbuf != NULL) && (txbuf != NULL));
+
+ osalSysLock();
+ osalDbgAssert(spip->state == SPI_READY, "not ready");
+ spiStartExchangeI(spip, n, txbuf, rxbuf);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Sends data over the SPI bus.
+ * @details This asynchronous function starts a transmit operation.
+ * @pre A slave must have been selected using @p spiSelect() or
+ * @p spiSelectI().
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @api
+ */
+void spiStartSend(SPIDriver *spip, size_t n, const void *txbuf) {
+
+ osalDbgCheck((spip != NULL) && (n > 0U) && (txbuf != NULL));
+
+ osalSysLock();
+ osalDbgAssert(spip->state == SPI_READY, "not ready");
+ spiStartSendI(spip, n, txbuf);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Receives data from the SPI bus.
+ * @details This asynchronous function starts a receive operation.
+ * @pre A slave must have been selected using @p spiSelect() or
+ * @p spiSelectI().
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to receive
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @api
+ */
+void spiStartReceive(SPIDriver *spip, size_t n, void *rxbuf) {
+
+ osalDbgCheck((spip != NULL) && (n > 0U) && (rxbuf != NULL));
+
+ osalSysLock();
+ osalDbgAssert(spip->state == SPI_READY, "not ready");
+ spiStartReceiveI(spip, n, rxbuf);
+ osalSysUnlock();
+}
+
+#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Aborts the ongoing SPI operation.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @iclass
+ */
+void spiAbortI(SPIDriver *spip) {
+
+ osalDbgCheckClassI();
+
+ osalDbgCheck(spip != NULL);
+ osalDbgAssert((spip->state == SPI_ACTIVE) || (spip->state == SPI_COMPLETE),
+ "invalid state");
+
+ spi_lld_abort(spip);
+ spip->state = SPI_READY;
+#if SPI_USE_WAIT == TRUE
+ osalThreadResumeI(&spip->thread, MSG_OK);
+#endif
+}
+
+/**
+ * @brief Aborts the ongoing SPI operation, if any.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @api
+ */
+void spiAbort(SPIDriver *spip) {
+
+ osalSysLock();
+ osalDbgAssert((spip->state == SPI_READY) || (spip->state == SPI_ACTIVE),
+ "invalid state");
+ if (spip->state == SPI_ACTIVE) {
+ spiAbortI(spip);
+ osalOsRescheduleS();
+ }
+ osalSysUnlock();
+}
+#endif
+
+#if (SPI_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Ignores data on the SPI bus.
+ * @details This synchronous function performs the transmission of a series of
+ * idle words on the SPI bus and ignores the received data.
+ * @pre In order to use this function the option @p SPI_USE_WAIT must be
+ * enabled.
+ * @pre In order to use this function the driver must have been configured
+ * without callbacks (@p end_cb = @p NULL).
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be ignored
+ *
+ * @api
+ */
+void spiIgnore(SPIDriver *spip, size_t n) {
+
+ osalDbgCheck((spip != NULL) && (n > 0U));
+#if SPI_SUPPORTS_CIRCULAR
+ osalDbgCheck((spip->config->circular == false) || ((n & 1U) == 0U));
+#endif
+
+ osalSysLock();
+ osalDbgAssert(spip->state == SPI_READY, "not ready");
+ spiStartIgnoreI(spip, n);
+ (void) osalThreadSuspendS(&spip->thread);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Exchanges data on the SPI bus.
+ * @details This synchronous function performs a simultaneous transmit/receive
+ * operation.
+ * @pre In order to use this function the option @p SPI_USE_WAIT must be
+ * enabled.
+ * @pre In order to use this function the driver must have been configured
+ * without callbacks (@p end_cb = @p NULL).
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be exchanged
+ * @param[in] txbuf the pointer to the transmit buffer
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @api
+ */
+void spiExchange(SPIDriver *spip, size_t n,
+ const void *txbuf, void *rxbuf) {
+
+ osalDbgCheck((spip != NULL) && (n > 0U) &&
+ (rxbuf != NULL) && (txbuf != NULL));
+#if SPI_SUPPORTS_CIRCULAR
+ osalDbgCheck((spip->config->circular == false) || ((n & 1U) == 0U));
+#endif
+
+ osalSysLock();
+ osalDbgAssert(spip->state == SPI_READY, "not ready");
+ spiStartExchangeI(spip, n, txbuf, rxbuf);
+ (void) osalThreadSuspendS(&spip->thread);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Sends data over the SPI bus.
+ * @details This synchronous function performs a transmit operation.
+ * @pre In order to use this function the option @p SPI_USE_WAIT must be
+ * enabled.
+ * @pre In order to use this function the driver must have been configured
+ * without callbacks (@p end_cb = @p NULL).
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @api
+ */
+void spiSend(SPIDriver *spip, size_t n, const void *txbuf) {
+
+ osalDbgCheck((spip != NULL) && (n > 0U) && (txbuf != NULL));
+#if SPI_SUPPORTS_CIRCULAR
+ osalDbgCheck((spip->config->circular == false) || ((n & 1U) == 0U));
+#endif
+
+ osalSysLock();
+ osalDbgAssert(spip->state == SPI_READY, "not ready");
+ spiStartSendI(spip, n, txbuf);
+ (void) osalThreadSuspendS(&spip->thread);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Receives data from the SPI bus.
+ * @details This synchronous function performs a receive operation.
+ * @pre In order to use this function the option @p SPI_USE_WAIT must be
+ * enabled.
+ * @pre In order to use this function the driver must have been configured
+ * without callbacks (@p end_cb = @p NULL).
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to receive
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @api
+ */
+void spiReceive(SPIDriver *spip, size_t n, void *rxbuf) {
+
+ osalDbgCheck((spip != NULL) && (n > 0U) && (rxbuf != NULL));
+#if SPI_SUPPORTS_CIRCULAR
+ osalDbgCheck((spip->config->circular == false) || ((n & 1U) == 0U));
+#endif
+
+ osalSysLock();
+ osalDbgAssert(spip->state == SPI_READY, "not ready");
+ spiStartReceiveI(spip, n, rxbuf);
+ (void) osalThreadSuspendS(&spip->thread);
+ osalSysUnlock();
+}
+#endif /* SPI_USE_WAIT == TRUE */
+
+#if (SPI_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Gains exclusive access to the SPI bus.
+ * @details This function tries to gain ownership to the SPI bus, if the bus
+ * is already being used then the invoking thread is queued.
+ * @pre In order to use this function the option @p SPI_USE_MUTUAL_EXCLUSION
+ * must be enabled.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @api
+ */
+void spiAcquireBus(SPIDriver *spip) {
+
+ osalDbgCheck(spip != NULL);
+
+ osalMutexLock(&spip->mutex);
+}
+
+/**
+ * @brief Releases exclusive access to the SPI bus.
+ * @pre In order to use this function the option @p SPI_USE_MUTUAL_EXCLUSION
+ * must be enabled.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @api
+ */
+void spiReleaseBus(SPIDriver *spip) {
+
+ osalDbgCheck(spip != NULL);
+
+ osalMutexUnlock(&spip->mutex);
+}
+#endif /* SPI_USE_MUTUAL_EXCLUSION == TRUE */
+
+#endif /* HAL_USE_SPI == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_st.c b/ChibiOS_20.3.2/os/hal/src/hal_st.c
new file mode 100644
index 0000000..ef60182
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_st.c
@@ -0,0 +1,262 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_st.c
+ * @brief ST Driver code.
+ *
+ * @addtogroup ST
+ * @{
+ */
+
+#include "hal.h"
+
+#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+#if (ST_LLD_NUM_ALARMS > 1) || defined(__DOXYGEN__)
+st_callback_t st_callbacks[ST_LLD_NUM_ALARMS - 1];
+#endif
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief ST Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void stInit(void) {
+#if ST_LLD_NUM_ALARMS > 1
+ unsigned i;
+
+ for (i = 0U; i < (unsigned)ST_LLD_NUM_ALARMS - 1U; i++) {
+ st_callbacks[i] = NULL;
+ }
+#endif
+ st_lld_init();
+}
+
+#if (OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING) || defined(__DOXYGEN__)
+/**
+ * @brief Starts the alarm zero.
+ * @note Makes sure that no spurious alarms are triggered after
+ * this call.
+ * @note This functionality is only available in free running mode, the
+ * behavior in periodic mode is undefined.
+ *
+ * @param[in] abstime the time to be set for the first alarm
+ *
+ * @api
+ */
+void stStartAlarm(systime_t abstime) {
+
+ osalDbgAssert(stIsAlarmActive() == false, "already active");
+
+ st_lld_start_alarm(abstime);
+}
+
+/**
+ * @brief Stops the alarm zero interrupt.
+ * @note This functionality is only available in free running mode, the
+ * behavior in periodic mode is undefined.
+ *
+ * @api
+ */
+void stStopAlarm(void) {
+
+ st_lld_stop_alarm();
+}
+
+/**
+ * @brief Sets the alarm zero time.
+ * @note This functionality is only available in free running mode, the
+ * behavior in periodic mode is undefined.
+ *
+ * @param[in] abstime the time to be set for the next alarm
+ *
+ * @api
+ */
+void stSetAlarm(systime_t abstime) {
+
+ osalDbgAssert(stIsAlarmActive() != false, "not active");
+
+ st_lld_set_alarm(abstime);
+}
+
+/**
+ * @brief Returns the alarm zero current time.
+ * @note This functionality is only available in free running mode, the
+ * behavior in periodic mode is undefined.
+ *
+ * @return The currently set alarm time.
+ *
+ * @api
+ */
+systime_t stGetAlarm(void) {
+
+ osalDbgAssert(stIsAlarmActive() != false, "not active");
+
+ return st_lld_get_alarm();
+}
+
+/**
+ * @brief Returns the time counter value.
+ * @note This functionality is only available in free running mode, the
+ * behaviour in periodic mode is undefined.
+ *
+ * @return The counter value.
+ *
+ * @api
+ */
+systime_t stGetCounter(void) {
+
+ return st_lld_get_counter();
+}
+
+/**
+ * @brief Determines if the alarm zero is active.
+ *
+ * @return The alarm status.
+ * @retval false if the alarm is not active.
+ * @retval true is the alarm is active
+ *
+ * @api
+ */
+bool stIsAlarmActive(void) {
+
+ return st_lld_is_alarm_active();
+}
+
+#if (ST_LLD_NUM_ALARMS > 1) || defined(__DOXYGEN__)
+/**
+ * @brief Determines if the specified alarm is active.
+ *
+ * @param[in] alarm alarm channel number (1..ST_LLD_NUM_ALARMS)
+ * @return The alarm status.
+ * @retval false if the alarm is not active.
+ * @retval true is the alarm is active
+ *
+ * @api
+ */
+bool stIsAlarmActiveN(unsigned alarm) {
+
+ return st_lld_is_alarm_active_n(n);
+}
+
+/**
+ * @brief Starts an additional alarm.
+ * @note Makes sure that no spurious alarms are triggered after
+ * this call.
+ * @note This functionality is only available in free running mode, the
+ * behavior in periodic mode is undefined.
+ *
+ * @param[in] abstime the time to be set for the first alarm
+ * @param[in] alarm alarm channel number (1..ST_LLD_NUM_ALARMS)
+ * @param[in] cb alarm callback
+ *
+ * @api
+ */
+void stStartAlarmN(unsigned alarm, systime_t abstime, st_callback_t cb) {
+
+ osalDbgCheck((alarm > 0U) && (alarm < (unsigned)ST_LLD_NUM_ALARMS));
+ osalDbgAssert(stIsAlarmActiveN(alarm) == false, "already active");
+
+ st_callbacks[alarm - 1U] = cb;
+ st_lld_start_alarm_n(alarm, abstime);
+}
+
+/**
+ * @brief Stops an additional alarm.
+ * @note This functionality is only available in free running mode, the
+ * behavior in periodic mode is undefined.
+ *
+ * @param[in] alarm alarm channel number (1..ST_LLD_NUM_ALARMS)
+ *
+ * @api
+ */
+void stStopAlarmN(unsigned alarm) {
+
+ osalDbgCheck((alarm > 0U) && (alarm < (unsigned)ST_LLD_NUM_ALARMS));
+
+ st_callbacks[alarm - 1U] = NULL;
+ st_lld_stop_alarm_n(alarm);
+}
+
+/**
+ * @brief Sets an additional alarm time.
+ * @note This functionality is only available in free running mode, the
+ * behavior in periodic mode is undefined.
+ *
+ * @param[in] alarm alarm channel number (1..ST_LLD_NUM_ALARMS)
+ * @param[in] abstime the time to be set for the next alarm
+ *
+ * @api
+ */
+void stSetAlarmN(unsigned alarm, systime_t abstime) {
+
+ osalDbgCheck((alarm > 0U) && (alarm < (unsigned)ST_LLD_NUM_ALARMS));
+ osalDbgAssert(stIsAlarmActiveN(alarm) != false, "not active");
+
+ st_lld_set_alarm_n(alarm, abstime);
+}
+
+/**
+ * @brief Returns an additional alarm current time.
+ * @note This functionality is only available in free running mode, the
+ * behavior in periodic mode is undefined.
+ *
+ * @param[in] alarm alarm channel number (1..ST_LLD_NUM_ALARMS)
+ * @return The currently set alarm time.
+ *
+ * @api
+ */
+systime_t stGetAlarmN(unsigned alarm) {
+
+ osalDbgCheck((alarm > 0U) && (alarm < (unsigned)ST_LLD_NUM_ALARMS));
+ osalDbgAssert(stIsAlarmActiveN(alarm) != false, "not active");
+
+ return st_lld_get_alarm_n(alarm);
+}
+#endif /* ST_LLD_NUM_ALARMS > 1 */
+
+#endif /* OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING */
+
+#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_trng.c b/ChibiOS_20.3.2/os/hal/src/hal_trng.c
new file mode 100644
index 0000000..76bba3c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_trng.c
@@ -0,0 +1,151 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_trng.c
+ * @brief TRNG Driver code.
+ *
+ * @addtogroup TRNG
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_TRNG == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief TRNG Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void trngInit(void) {
+
+ trng_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p TRNGDriver structure.
+ *
+ * @param[out] trngp pointer to the @p TRNGDriver object
+ *
+ * @init
+ */
+void trngObjectInit(TRNGDriver *trngp) {
+
+ trngp->state = TRNG_STOP;
+ trngp->config = NULL;
+}
+
+/**
+ * @brief Configures and activates the TRNG peripheral.
+ *
+ * @param[in] trngp pointer to the @p TRNGDriver object
+ * @param[in] config pointer to the @p TRNGConfig object or @p NULL for
+ * default configuration
+ *
+ * @api
+ */
+void trngStart(TRNGDriver *trngp, const TRNGConfig *config) {
+
+ osalDbgCheck(trngp != NULL);
+
+ osalSysLock();
+ osalDbgAssert((trngp->state == TRNG_STOP) || (trngp->state == TRNG_READY),
+ "invalid state");
+ trngp->config = config;
+ trng_lld_start(trngp);
+ trngp->state = TRNG_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the TRNG peripheral.
+ *
+ * @param[in] trngp pointer to the @p TRNGDriver object
+ *
+ * @api
+ */
+void trngStop(TRNGDriver *trngp) {
+
+ osalDbgCheck(trngp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((trngp->state == TRNG_STOP) || (trngp->state == TRNG_READY),
+ "invalid state");
+
+ trng_lld_stop(trngp);
+ trngp->config = NULL;
+ trngp->state = TRNG_STOP;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief True random numbers generator.
+ * @note The function is blocking and likely performs polled waiting
+ * inside the low level implementation.
+ *
+ * @param[in] trngp pointer to the @p TRNGDriver object
+ * @param[in] size size of output buffer
+ * @param[out] out output buffer
+ * @return The operation status.
+ * @retval false if a random number has been generated.
+ * @retval true if an HW error occurred.
+ *
+ * @api
+ */
+bool trngGenerate(TRNGDriver *trngp, size_t size, uint8_t *out) {
+ bool err;
+
+ osalDbgCheck((trngp != NULL) && (out != NULL));
+
+ osalDbgAssert(trngp->state == TRNG_READY, "not ready");
+
+ trngp->state = TRNG_RUNNING;
+
+ err = trng_lld_generate(trngp, size, out);
+
+ trngp->state = TRNG_READY;
+
+ return err;
+}
+
+#endif /* HAL_USE_TRNG == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_uart.c b/ChibiOS_20.3.2/os/hal/src/hal_uart.c
new file mode 100644
index 0000000..42455bd
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_uart.c
@@ -0,0 +1,524 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_uart.c
+ * @brief UART Driver code.
+ *
+ * @addtogroup UART
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief UART Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void uartInit(void) {
+
+ uart_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p UARTDriver structure.
+ *
+ * @param[out] uartp pointer to the @p UARTDriver object
+ *
+ * @init
+ */
+void uartObjectInit(UARTDriver *uartp) {
+
+ uartp->state = UART_STOP;
+ uartp->txstate = UART_TX_IDLE;
+ uartp->rxstate = UART_RX_IDLE;
+ uartp->config = NULL;
+#if UART_USE_WAIT == TRUE
+ uartp->early = false;
+ uartp->threadrx = NULL;
+ uartp->threadtx = NULL;
+#endif /* UART_USE_WAIT */
+#if UART_USE_MUTUAL_EXCLUSION == TRUE
+ osalMutexObjectInit(&uartp->mutex);
+#endif /* UART_USE_MUTUAL_EXCLUSION */
+
+ /* Optional, user-defined initializer.*/
+#if defined(UART_DRIVER_EXT_INIT_HOOK)
+ UART_DRIVER_EXT_INIT_HOOK(uartp);
+#endif
+}
+
+/**
+ * @brief Configures and activates the UART peripheral.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] config pointer to the @p UARTConfig object
+ *
+ * @api
+ */
+void uartStart(UARTDriver *uartp, const UARTConfig *config) {
+
+ osalDbgCheck((uartp != NULL) && (config != NULL));
+
+ osalSysLock();
+ osalDbgAssert((uartp->state == UART_STOP) || (uartp->state == UART_READY),
+ "invalid state");
+
+ uartp->config = config;
+ uart_lld_start(uartp);
+ uartp->state = UART_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the UART peripheral.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @api
+ */
+void uartStop(UARTDriver *uartp) {
+
+ osalDbgCheck(uartp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((uartp->state == UART_STOP) || (uartp->state == UART_READY),
+ "invalid state");
+
+ uart_lld_stop(uartp);
+ uartp->config = NULL;
+ uartp->state = UART_STOP;
+ uartp->txstate = UART_TX_IDLE;
+ uartp->rxstate = UART_RX_IDLE;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Starts a transmission on the UART peripheral.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] n number of data frames to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @api
+ */
+void uartStartSend(UARTDriver *uartp, size_t n, const void *txbuf) {
+
+ osalDbgCheck((uartp != NULL) && (n > 0U) && (txbuf != NULL));
+
+ osalSysLock();
+ osalDbgAssert(uartp->state == UART_READY, "is active");
+ osalDbgAssert(uartp->txstate != UART_TX_ACTIVE, "tx active");
+
+ uart_lld_start_send(uartp, n, txbuf);
+ uartp->txstate = UART_TX_ACTIVE;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Starts a transmission on the UART peripheral.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ * @note This function has to be invoked from a lock zone.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] n number of data frames to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @iclass
+ */
+void uartStartSendI(UARTDriver *uartp, size_t n, const void *txbuf) {
+
+ osalDbgCheckClassI();
+ osalDbgCheck((uartp != NULL) && (n > 0U) && (txbuf != NULL));
+ osalDbgAssert(uartp->state == UART_READY, "is active");
+ osalDbgAssert(uartp->txstate != UART_TX_ACTIVE, "tx active");
+
+ uart_lld_start_send(uartp, n, txbuf);
+ uartp->txstate = UART_TX_ACTIVE;
+}
+
+/**
+ * @brief Stops any ongoing transmission.
+ * @note Stopping a transmission also suppresses the transmission callbacks.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @return The number of data frames not transmitted by the
+ * stopped transmit operation.
+ * @retval UART_ERR_NOT_ACTIVE if there was no transmit operation in progress.
+ *
+ * @api
+ */
+size_t uartStopSend(UARTDriver *uartp) {
+ size_t n;
+
+ osalDbgCheck(uartp != NULL);
+
+ osalSysLock();
+ osalDbgAssert(uartp->state == UART_READY, "not active");
+
+ if (uartp->txstate == UART_TX_ACTIVE) {
+ n = uart_lld_stop_send(uartp);
+ uartp->txstate = UART_TX_IDLE;
+ }
+ else {
+ n = UART_ERR_NOT_ACTIVE;
+ }
+ osalSysUnlock();
+
+ return n;
+}
+
+/**
+ * @brief Stops any ongoing transmission.
+ * @note Stopping a transmission also suppresses the transmission callbacks.
+ * @note This function has to be invoked from a lock zone.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @return The number of data frames not transmitted by the
+ * stopped transmit operation.
+ * @retval UART_ERR_NOT_ACTIVE if there was no transmit operation in progress.
+ *
+ * @iclass
+ */
+size_t uartStopSendI(UARTDriver *uartp) {
+
+ osalDbgCheckClassI();
+ osalDbgCheck(uartp != NULL);
+ osalDbgAssert(uartp->state == UART_READY, "not active");
+
+ if (uartp->txstate == UART_TX_ACTIVE) {
+ size_t n = uart_lld_stop_send(uartp);
+ uartp->txstate = UART_TX_IDLE;
+ return n;
+ }
+ return UART_ERR_NOT_ACTIVE;
+}
+
+/**
+ * @brief Starts a receive operation on the UART peripheral.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] n number of data frames to receive
+ * @param[in] rxbuf the pointer to the receive buffer
+ *
+ * @api
+ */
+void uartStartReceive(UARTDriver *uartp, size_t n, void *rxbuf) {
+
+ osalDbgCheck((uartp != NULL) && (n > 0U) && (rxbuf != NULL));
+
+ osalSysLock();
+ osalDbgAssert(uartp->state == UART_READY, "is active");
+ osalDbgAssert(uartp->rxstate != UART_RX_ACTIVE, "rx active");
+
+ uart_lld_start_receive(uartp, n, rxbuf);
+ uartp->rxstate = UART_RX_ACTIVE;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Starts a receive operation on the UART peripheral.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ * @note This function has to be invoked from a lock zone.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] n number of data frames to receive
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @iclass
+ */
+void uartStartReceiveI(UARTDriver *uartp, size_t n, void *rxbuf) {
+
+ osalDbgCheckClassI();
+ osalDbgCheck((uartp != NULL) && (n > 0U) && (rxbuf != NULL));
+ osalDbgAssert(uartp->state == UART_READY, "is active");
+ osalDbgAssert(uartp->rxstate != UART_RX_ACTIVE, "rx active");
+
+ uart_lld_start_receive(uartp, n, rxbuf);
+ uartp->rxstate = UART_RX_ACTIVE;
+}
+
+/**
+ * @brief Stops any ongoing receive operation.
+ * @note Stopping a receive operation also suppresses the receive callbacks.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @return The number of data frames not received by the
+ * stopped receive operation.
+ * @retval UART_ERR_NOT_ACTIVE if there was no receive operation in progress.
+ *
+ * @api
+ */
+size_t uartStopReceive(UARTDriver *uartp) {
+ size_t n;
+
+ osalDbgCheck(uartp != NULL);
+
+ osalSysLock();
+ osalDbgAssert(uartp->state == UART_READY, "not active");
+
+ if (uartp->rxstate == UART_RX_ACTIVE) {
+ n = uart_lld_stop_receive(uartp);
+ uartp->rxstate = UART_RX_IDLE;
+ }
+ else {
+ n = UART_ERR_NOT_ACTIVE;
+ }
+ osalSysUnlock();
+
+ return n;
+}
+
+/**
+ * @brief Stops any ongoing receive operation.
+ * @note Stopping a receive operation also suppresses the receive callbacks.
+ * @note This function has to be invoked from a lock zone.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @return The number of data frames not received by the
+ * stopped receive operation.
+ * @retval UART_ERR_NOT_ACTIVE if there was no receive operation in progress.
+ *
+ * @iclass
+ */
+size_t uartStopReceiveI(UARTDriver *uartp) {
+
+ osalDbgCheckClassI();
+ osalDbgCheck(uartp != NULL);
+ osalDbgAssert(uartp->state == UART_READY, "not active");
+
+ if (uartp->rxstate == UART_RX_ACTIVE) {
+ size_t n = uart_lld_stop_receive(uartp);
+ uartp->rxstate = UART_RX_IDLE;
+ return n;
+ }
+ return UART_ERR_NOT_ACTIVE;
+}
+
+#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Performs a transmission on the UART peripheral.
+ * @note The function returns when the specified number of frames have been
+ * sent to the UART or on timeout.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ * @note This function implements a software timeout, it does not use
+ * any underlying HW timeout mechanism.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in,out] np number of data frames to transmit, on exit the number
+ * of frames actually transmitted
+ * @param[in] txbuf the pointer to the transmit buffer
+ * @param[in] timeout operation timeout
+ * @return The operation status.
+ * @retval MSG_OK if the operation completed successfully.
+ * @retval MSG_TIMEOUT if the operation timed out.
+ *
+ * @api
+ */
+msg_t uartSendTimeout(UARTDriver *uartp, size_t *np,
+ const void *txbuf, sysinterval_t timeout) {
+ msg_t msg;
+
+ osalDbgCheck((uartp != NULL) && (*np > 0U) && (txbuf != NULL));
+
+ osalSysLock();
+ osalDbgAssert(uartp->state == UART_READY, "is active");
+ osalDbgAssert(uartp->txstate != UART_TX_ACTIVE, "tx active");
+
+ /* Transmission start.*/
+ uartp->early = true;
+ uart_lld_start_send(uartp, *np, txbuf);
+ uartp->txstate = UART_TX_ACTIVE;
+
+ /* Waiting for result.*/
+ msg = osalThreadSuspendTimeoutS(&uartp->threadtx, timeout);
+ if (msg != MSG_OK) {
+ *np -= uartStopSendI(uartp);
+ }
+ osalSysUnlock();
+
+ return msg;
+}
+
+/**
+ * @brief Performs a transmission on the UART peripheral.
+ * @note The function returns when the specified number of frames have been
+ * physically transmitted or on timeout.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ * @note This function implements a software timeout, it does not use
+ * any underlying HW timeout mechanism.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in,out] np number of data frames to transmit, on exit the number
+ * of frames actually transmitted
+ * @param[in] txbuf the pointer to the transmit buffer
+ * @param[in] timeout operation timeout
+ * @return The operation status.
+ * @retval MSG_OK if the operation completed successfully.
+ * @retval MSG_TIMEOUT if the operation timed out.
+ *
+ * @api
+ */
+msg_t uartSendFullTimeout(UARTDriver *uartp, size_t *np,
+ const void *txbuf, sysinterval_t timeout) {
+ msg_t msg;
+
+ osalDbgCheck((uartp != NULL) && (*np > 0U) && (txbuf != NULL));
+
+ osalSysLock();
+ osalDbgAssert(uartp->state == UART_READY, "is active");
+ osalDbgAssert(uartp->txstate != UART_TX_ACTIVE, "tx active");
+
+ /* Transmission start.*/
+ uartp->early = false;
+ uart_lld_start_send(uartp, *np, txbuf);
+ uartp->txstate = UART_TX_ACTIVE;
+
+ /* Waiting for result.*/
+ msg = osalThreadSuspendTimeoutS(&uartp->threadtx, timeout);
+ if (msg != MSG_OK) {
+ *np -= uartStopSendI(uartp);
+ }
+ osalSysUnlock();
+
+ return msg;
+}
+
+/**
+ * @brief Performs a receive operation on the UART peripheral.
+ * @note The function returns when the specified number of frames have been
+ * received or on error/timeout.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ * @note This function implements a software timeout, it does not use
+ * any underlying HW timeout mechanism.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in,out] np number of data frames to receive, on exit the number
+ * of frames actually received
+ * @param[in] rxbuf the pointer to the receive buffer
+ * @param[in] timeout operation timeout
+ *
+ * @return The operation status.
+ * @retval MSG_OK if the operation completed successfully.
+ * @retval MSG_TIMEOUT if the operation timed out.
+ * @retval MSG_RESET in case of a receive error.
+ *
+ * @api
+ */
+msg_t uartReceiveTimeout(UARTDriver *uartp, size_t *np,
+ void *rxbuf, sysinterval_t timeout) {
+ msg_t msg;
+
+ osalDbgCheck((uartp != NULL) && (*np > 0U) && (rxbuf != NULL));
+
+ osalSysLock();
+ osalDbgAssert(uartp->state == UART_READY, "is active");
+ osalDbgAssert(uartp->rxstate != UART_RX_ACTIVE, "rx active");
+
+ /* Receive start.*/
+ uart_lld_start_receive(uartp, *np, rxbuf);
+ uartp->rxstate = UART_RX_ACTIVE;
+
+ /* Waiting for result.*/
+ msg = osalThreadSuspendTimeoutS(&uartp->threadrx, timeout);
+ if (msg != MSG_OK) {
+ *np -= uartStopReceiveI(uartp);
+ }
+ osalSysUnlock();
+
+ return msg;
+}
+#endif
+
+#if (UART_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Gains exclusive access to the UART bus.
+ * @details This function tries to gain ownership to the UART bus, if the bus
+ * is already being used then the invoking thread is queued.
+ * @pre In order to use this function the option @p UART_USE_MUTUAL_EXCLUSION
+ * must be enabled.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @api
+ */
+void uartAcquireBus(UARTDriver *uartp) {
+
+ osalDbgCheck(uartp != NULL);
+
+ osalMutexLock(&uartp->mutex);
+}
+
+/**
+ * @brief Releases exclusive access to the UART bus.
+ * @pre In order to use this function the option @p UART_USE_MUTUAL_EXCLUSION
+ * must be enabled.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @api
+ */
+void uartReleaseBus(UARTDriver *uartp) {
+
+ osalDbgCheck(uartp != NULL);
+
+ osalMutexUnlock(&uartp->mutex);
+}
+#endif
+
+#endif /* HAL_USE_UART == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_usb.c b/ChibiOS_20.3.2/os/hal/src/hal_usb.c
new file mode 100644
index 0000000..caa8d6d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_usb.c
@@ -0,0 +1,1002 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_usb.c
+ * @brief USB Driver code.
+ *
+ * @addtogroup USB
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+
+#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+static const uint8_t zero_status[] = {0x00, 0x00};
+static const uint8_t active_status[] = {0x00, 0x00};
+static const uint8_t halted_status[] = {0x01, 0x00};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+static uint16_t get_hword(uint8_t *p) {
+ uint16_t hw;
+
+ hw = (uint16_t)*p++;
+ hw |= (uint16_t)*p << 8U;
+ return hw;
+}
+
+/**
+ * @brief SET ADDRESS transaction callback.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ */
+static void set_address(USBDriver *usbp) {
+
+ usbp->address = usbp->setup[2];
+ usb_lld_set_address(usbp);
+ _usb_isr_invoke_event_cb(usbp, USB_EVENT_ADDRESS);
+ usbp->state = USB_SELECTED;
+}
+
+/**
+ * @brief Standard requests handler.
+ * @details This is the standard requests default handler, most standard
+ * requests are handled here, the user can override the standard
+ * handling using the @p requests_hook_cb hook in the
+ * @p USBConfig structure.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @return The request handling exit code.
+ * @retval false Request not recognized by the handler or error.
+ * @retval true Request handled.
+ */
+static bool default_handler(USBDriver *usbp) {
+ const USBDescriptor *dp;
+
+ /* Decoding the request.*/
+ switch ((((uint32_t)usbp->setup[0] & (USB_RTYPE_RECIPIENT_MASK |
+ USB_RTYPE_TYPE_MASK)) |
+ ((uint32_t)usbp->setup[1] << 8U))) {
+ case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_GET_STATUS << 8):
+ /* Just returns the current status word.*/
+ usbSetupTransfer(usbp, (uint8_t *)&usbp->status, 2, NULL);
+ return true;
+ case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_CLEAR_FEATURE << 8):
+ /* Only the DEVICE_REMOTE_WAKEUP is handled here, any other feature
+ number is handled as an error.*/
+ if (usbp->setup[2] == USB_FEATURE_DEVICE_REMOTE_WAKEUP) {
+ usbp->status &= ~2U;
+ usbSetupTransfer(usbp, NULL, 0, NULL);
+ return true;
+ }
+ return false;
+ case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_FEATURE << 8):
+ /* Only the DEVICE_REMOTE_WAKEUP is handled here, any other feature
+ number is handled as an error.*/
+ if (usbp->setup[2] == USB_FEATURE_DEVICE_REMOTE_WAKEUP) {
+ usbp->status |= 2U;
+ usbSetupTransfer(usbp, NULL, 0, NULL);
+ return true;
+ }
+ return false;
+ case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_ADDRESS << 8):
+ /* The SET_ADDRESS handling can be performed here or postponed after
+ the status packed depending on the USB_SET_ADDRESS_MODE low
+ driver setting.*/
+#if USB_SET_ADDRESS_MODE == USB_EARLY_SET_ADDRESS
+ if ((usbp->setup[0] == USB_RTYPE_RECIPIENT_DEVICE) &&
+ (usbp->setup[1] == USB_REQ_SET_ADDRESS)) {
+ set_address(usbp);
+ }
+ usbSetupTransfer(usbp, NULL, 0, NULL);
+#else
+ usbSetupTransfer(usbp, NULL, 0, set_address);
+#endif
+ return true;
+ case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_GET_DESCRIPTOR << 8):
+ case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_GET_DESCRIPTOR << 8):
+ /* Handling descriptor requests from the host.*/
+ dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3],
+ usbp->setup[2],
+ get_hword(&usbp->setup[4]));
+ if (dp == NULL) {
+ return false;
+ }
+ /*lint -save -e9005 [11.8] Removing const is fine.*/
+ usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL);
+ /*lint -restore*/
+ return true;
+ case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_GET_CONFIGURATION << 8):
+ /* Returning the last selected configuration.*/
+ usbSetupTransfer(usbp, &usbp->configuration, 1, NULL);
+ return true;
+ case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_CONFIGURATION << 8):
+#if defined(USB_SET_CONFIGURATION_OLD_BEHAVIOR)
+ /* Handling configuration selection from the host only if it is different
+ from the current configuration.*/
+ if (usbp->configuration != usbp->setup[2])
+#endif
+ {
+ /* If the USB device is already active then we have to perform the clear
+ procedure on the current configuration.*/
+ if (usbp->state == USB_ACTIVE) {
+ /* Current configuration cleared.*/
+ osalSysLockFromISR ();
+ usbDisableEndpointsI(usbp);
+ osalSysUnlockFromISR ();
+ usbp->configuration = 0U;
+ usbp->state = USB_SELECTED;
+ _usb_isr_invoke_event_cb(usbp, USB_EVENT_UNCONFIGURED);
+ }
+ if (usbp->setup[2] != 0U) {
+ /* New configuration.*/
+ usbp->configuration = usbp->setup[2];
+ usbp->state = USB_ACTIVE;
+ _usb_isr_invoke_event_cb(usbp, USB_EVENT_CONFIGURED);
+ }
+ }
+ usbSetupTransfer(usbp, NULL, 0, NULL);
+ return true;
+ case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_GET_STATUS << 8):
+ case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_SYNCH_FRAME << 8):
+ /* Just sending two zero bytes, the application can change the behavior
+ using a hook..*/
+ /*lint -save -e9005 [11.8] Removing const is fine.*/
+ usbSetupTransfer(usbp, (uint8_t *)zero_status, 2, NULL);
+ /*lint -restore*/
+ return true;
+ case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_GET_STATUS << 8):
+ /* Sending the EP status.*/
+ if ((usbp->setup[4] & 0x80U) != 0U) {
+ switch (usb_lld_get_status_in(usbp, usbp->setup[4] & 0x0FU)) {
+ case EP_STATUS_STALLED:
+ /*lint -save -e9005 [11.8] Removing const is fine.*/
+ usbSetupTransfer(usbp, (uint8_t *)halted_status, 2, NULL);
+ /*lint -restore*/
+ return true;
+ case EP_STATUS_ACTIVE:
+ /*lint -save -e9005 [11.8] Removing const is fine.*/
+ usbSetupTransfer(usbp, (uint8_t *)active_status, 2, NULL);
+ /*lint -restore*/
+ return true;
+ case EP_STATUS_DISABLED:
+ default:
+ return false;
+ }
+ }
+ else {
+ switch (usb_lld_get_status_out(usbp, usbp->setup[4] & 0x0FU)) {
+ case EP_STATUS_STALLED:
+ /*lint -save -e9005 [11.8] Removing const is fine.*/
+ usbSetupTransfer(usbp, (uint8_t *)halted_status, 2, NULL);
+ /*lint -restore*/
+ return true;
+ case EP_STATUS_ACTIVE:
+ /*lint -save -e9005 [11.8] Removing const is fine.*/
+ usbSetupTransfer(usbp, (uint8_t *)active_status, 2, NULL);
+ /*lint -restore*/
+ return true;
+ case EP_STATUS_DISABLED:
+ default:
+ return false;
+ }
+ }
+ case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_CLEAR_FEATURE << 8):
+ /* Only ENDPOINT_HALT is handled as feature.*/
+ if (usbp->setup[2] != USB_FEATURE_ENDPOINT_HALT) {
+ return false;
+ }
+ /* Clearing the EP status, not valid for EP0, it is ignored in that case.*/
+ if ((usbp->setup[4] & 0x0FU) != 0U) {
+ if ((usbp->setup[4] & 0x80U) != 0U) {
+ usb_lld_clear_in(usbp, usbp->setup[4] & 0x0FU);
+ }
+ else {
+ usb_lld_clear_out(usbp, usbp->setup[4] & 0x0FU);
+ }
+ }
+ usbSetupTransfer(usbp, NULL, 0, NULL);
+ return true;
+ case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_SET_FEATURE << 8):
+ /* Only ENDPOINT_HALT is handled as feature.*/
+ if (usbp->setup[2] != USB_FEATURE_ENDPOINT_HALT) {
+ return false;
+ }
+ /* Stalling the EP, not valid for EP0, it is ignored in that case.*/
+ if ((usbp->setup[4] & 0x0FU) != 0U) {
+ if ((usbp->setup[4] & 0x80U) != 0U) {
+ usb_lld_stall_in(usbp, usbp->setup[4] & 0x0FU);
+ }
+ else {
+ usb_lld_stall_out(usbp, usbp->setup[4] & 0x0FU);
+ }
+ }
+ usbSetupTransfer(usbp, NULL, 0, NULL);
+ return true;
+ case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_DESCRIPTOR << 8):
+ case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_CLEAR_FEATURE << 8):
+ case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_SET_FEATURE << 8):
+ case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_GET_INTERFACE << 8):
+ case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_SET_INTERFACE << 8):
+ /* All the above requests are not handled here, if you need them then
+ use the hook mechanism and provide handling.*/
+ default:
+ return false;
+ }
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief USB Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void usbInit(void) {
+
+ usb_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p USBDriver structure.
+ *
+ * @param[out] usbp pointer to the @p USBDriver object
+ *
+ * @init
+ */
+void usbObjectInit(USBDriver *usbp) {
+ unsigned i;
+
+ usbp->state = USB_STOP;
+ usbp->config = NULL;
+ for (i = 0; i < (unsigned)USB_MAX_ENDPOINTS; i++) {
+ usbp->in_params[i] = NULL;
+ usbp->out_params[i] = NULL;
+ }
+ usbp->transmitting = 0;
+ usbp->receiving = 0;
+}
+
+/**
+ * @brief Configures and activates the USB peripheral.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] config pointer to the @p USBConfig object
+ *
+ * @api
+ */
+void usbStart(USBDriver *usbp, const USBConfig *config) {
+ unsigned i;
+
+ osalDbgCheck((usbp != NULL) && (config != NULL));
+
+ osalSysLock();
+ osalDbgAssert((usbp->state == USB_STOP) || (usbp->state == USB_READY),
+ "invalid state");
+ usbp->config = config;
+ for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
+ usbp->epc[i] = NULL;
+ }
+ usb_lld_start(usbp);
+ usbp->state = USB_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the USB peripheral.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @api
+ */
+void usbStop(USBDriver *usbp) {
+ unsigned i;
+
+ osalDbgCheck(usbp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((usbp->state == USB_STOP) || (usbp->state == USB_READY) ||
+ (usbp->state == USB_SELECTED) || (usbp->state == USB_ACTIVE) ||
+ (usbp->state == USB_SUSPENDED),
+ "invalid state");
+
+ usb_lld_stop(usbp);
+ usbp->config = NULL;
+ usbp->state = USB_STOP;
+
+ /* Resetting all ongoing synchronous operations.*/
+ for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
+#if USB_USE_WAIT == TRUE
+ if (usbp->epc[i] != NULL) {
+ if (usbp->epc[i]->in_state != NULL) {
+ osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET);
+ }
+ if (usbp->epc[i]->out_state != NULL) {
+ osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET);
+ }
+ }
+#endif
+ usbp->epc[i] = NULL;
+ }
+ osalOsRescheduleS();
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Enables an endpoint.
+ * @details This function enables an endpoint, both IN and/or OUT directions
+ * depending on the configuration structure.
+ * @note This function must be invoked in response of a SET_CONFIGURATION
+ * or SET_INTERFACE message.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[in] epcp the endpoint configuration
+ *
+ * @iclass
+ */
+void usbInitEndpointI(USBDriver *usbp, usbep_t ep,
+ const USBEndpointConfig *epcp) {
+
+ osalDbgCheckClassI();
+ osalDbgCheck((usbp != NULL) && (epcp != NULL));
+ osalDbgAssert(usbp->state == USB_ACTIVE,
+ "invalid state");
+ osalDbgAssert(usbp->epc[ep] == NULL, "already initialized");
+
+ /* Logically enabling the endpoint in the USBDriver structure.*/
+ usbp->epc[ep] = epcp;
+
+ /* Clearing the state structures, custom fields as well.*/
+ if (epcp->in_state != NULL) {
+ memset(epcp->in_state, 0, sizeof(USBInEndpointState));
+ }
+ if (epcp->out_state != NULL) {
+ memset(epcp->out_state, 0, sizeof(USBOutEndpointState));
+ }
+
+ /* Low level endpoint activation.*/
+ usb_lld_init_endpoint(usbp, ep);
+}
+
+/**
+ * @brief Disables all the active endpoints.
+ * @details This function disables all the active endpoints except the
+ * endpoint zero.
+ * @note This function must be invoked in response of a SET_CONFIGURATION
+ * message with configuration number zero.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @iclass
+ */
+void usbDisableEndpointsI(USBDriver *usbp) {
+ unsigned i;
+
+ osalDbgCheckClassI();
+ osalDbgCheck(usbp != NULL);
+ osalDbgAssert(usbp->state == USB_ACTIVE, "invalid state");
+
+ usbp->transmitting &= 1U;
+ usbp->receiving &= 1U;
+
+ for (i = 1; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
+#if USB_USE_WAIT == TRUE
+ /* Signaling the event to threads waiting on endpoints.*/
+ if (usbp->epc[i] != NULL) {
+ if (usbp->epc[i]->in_state != NULL) {
+ osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET);
+ }
+ if (usbp->epc[i]->out_state != NULL) {
+ osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET);
+ }
+ }
+#endif
+ usbp->epc[i] = NULL;
+ }
+
+ /* Low level endpoints deactivation.*/
+ usb_lld_disable_endpoints(usbp);
+}
+
+/**
+ * @brief Starts a receive transaction on an OUT endpoint.
+ * @note This function is meant to be called from ISR context outside
+ * critical zones because there is a potentially slow operation
+ * inside.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[out] buf buffer where to copy the received data
+ * @param[in] n transaction size. It is recommended a multiple of
+ * the packet size because the excess is discarded.
+ *
+ * @iclass
+ */
+void usbStartReceiveI(USBDriver *usbp, usbep_t ep,
+ uint8_t *buf, size_t n) {
+ USBOutEndpointState *osp;
+
+ osalDbgCheckClassI();
+ osalDbgCheck((usbp != NULL) && (ep <= (usbep_t)USB_MAX_ENDPOINTS));
+ osalDbgAssert(!usbGetReceiveStatusI(usbp, ep), "already receiving");
+
+ /* Marking the endpoint as active.*/
+ usbp->receiving |= (uint16_t)((unsigned)1U << (unsigned)ep);
+
+ /* Setting up the transfer.*/
+ /*lint -save -e661 [18.1] pclint is confused by the check on ep.*/
+ osp = usbp->epc[ep]->out_state;
+ /*lint -restore*/
+ osp->rxbuf = buf;
+ osp->rxsize = n;
+ osp->rxcnt = 0;
+#if USB_USE_WAIT == TRUE
+ osp->thread = NULL;
+#endif
+
+ /* Starting transfer.*/
+ usb_lld_start_out(usbp, ep);
+}
+
+/**
+ * @brief Starts a transmit transaction on an IN endpoint.
+ * @note This function is meant to be called from ISR context outside
+ * critical zones because there is a potentially slow operation
+ * inside.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[in] buf buffer where to fetch the data to be transmitted
+ * @param[in] n transaction size
+ *
+ * @iclass
+ */
+void usbStartTransmitI(USBDriver *usbp, usbep_t ep,
+ const uint8_t *buf, size_t n) {
+ USBInEndpointState *isp;
+
+ osalDbgCheckClassI();
+ osalDbgCheck((usbp != NULL) && (ep <= (usbep_t)USB_MAX_ENDPOINTS));
+ osalDbgAssert(!usbGetTransmitStatusI(usbp, ep), "already transmitting");
+
+ /* Marking the endpoint as active.*/
+ usbp->transmitting |= (uint16_t)((unsigned)1U << (unsigned)ep);
+
+ /* Setting up the transfer.*/
+ /*lint -save -e661 [18.1] pclint is confused by the check on ep.*/
+ isp = usbp->epc[ep]->in_state;
+ /*lint -restore*/
+ isp->txbuf = buf;
+ isp->txsize = n;
+ isp->txcnt = 0;
+#if USB_USE_WAIT == TRUE
+ isp->thread = NULL;
+#endif
+
+ /* Starting transfer.*/
+ usb_lld_start_in(usbp, ep);
+}
+
+#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Performs a receive transaction on an OUT endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[out] buf buffer where to copy the received data
+ * @param[in] n transaction size. It is recommended a multiple of
+ * the packet size because the excess is discarded.
+ *
+ * @return The received effective data size, it can be less than
+ * the amount specified.
+ * @retval MSG_RESET driver not in @p USB_ACTIVE state or the operation
+ * has been aborted by an USB reset or a transition to
+ * the @p USB_SUSPENDED state.
+ *
+ * @api
+ */
+msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) {
+ msg_t msg;
+
+ osalSysLock();
+
+ if (usbGetDriverStateI(usbp) != USB_ACTIVE) {
+ osalSysUnlock();
+ return MSG_RESET;
+ }
+
+ usbStartReceiveI(usbp, ep, buf, n);
+ msg = osalThreadSuspendS(&usbp->epc[ep]->out_state->thread);
+ osalSysUnlock();
+
+ return msg;
+}
+
+/**
+ * @brief Performs a transmit transaction on an IN endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[in] buf buffer where to fetch the data to be transmitted
+ * @param[in] n transaction size
+ *
+ * @return The operation status.
+ * @retval MSG_OK operation performed successfully.
+ * @retval MSG_RESET driver not in @p USB_ACTIVE state or the operation
+ * has been aborted by an USB reset or a transition to
+ * the @p USB_SUSPENDED state.
+ *
+ * @api
+ */
+msg_t usbTransmit(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n) {
+ msg_t msg;
+
+ osalSysLock();
+
+ if (usbGetDriverStateI(usbp) != USB_ACTIVE) {
+ osalSysUnlock();
+ return MSG_RESET;
+ }
+
+ usbStartTransmitI(usbp, ep, buf, n);
+ msg = osalThreadSuspendS(&usbp->epc[ep]->in_state->thread);
+ osalSysUnlock();
+
+ return msg;
+}
+#endif /* USB_USE_WAIT == TRUE */
+
+/**
+ * @brief Stalls an OUT endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @return The operation status.
+ * @retval false Endpoint stalled.
+ * @retval true Endpoint busy, not stalled.
+ *
+ * @iclass
+ */
+bool usbStallReceiveI(USBDriver *usbp, usbep_t ep) {
+
+ osalDbgCheckClassI();
+ osalDbgCheck(usbp != NULL);
+
+ if (usbGetReceiveStatusI(usbp, ep)) {
+ return true;
+ }
+
+ usb_lld_stall_out(usbp, ep);
+ return false;
+}
+
+/**
+ * @brief Stalls an IN endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @return The operation status.
+ * @retval false Endpoint stalled.
+ * @retval true Endpoint busy, not stalled.
+ *
+ * @iclass
+ */
+bool usbStallTransmitI(USBDriver *usbp, usbep_t ep) {
+
+ osalDbgCheckClassI();
+ osalDbgCheck(usbp != NULL);
+
+ if (usbGetTransmitStatusI(usbp, ep)) {
+ return true;
+ }
+
+ usb_lld_stall_in(usbp, ep);
+ return false;
+}
+
+/**
+ * @brief Host wake-up procedure.
+ * @note It is silently ignored if the USB device is not in the
+ * @p USB_SUSPENDED state.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @api
+ */
+void usbWakeupHost(USBDriver *usbp) {
+
+ if (usbp->state == USB_SUSPENDED) {
+ /* Starting host wakeup procedure.*/
+ usb_lld_wakeup_host(usbp);
+ }
+}
+
+/**
+ * @brief USB reset routine.
+ * @details This function must be invoked when an USB bus reset condition is
+ * detected.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+void _usb_reset(USBDriver *usbp) {
+ unsigned i;
+
+ /* State transition.*/
+ usbp->state = USB_READY;
+
+ /* Resetting internal state.*/
+ usbp->status = 0;
+ usbp->address = 0;
+ usbp->configuration = 0;
+ usbp->transmitting = 0;
+ usbp->receiving = 0;
+
+ /* Invalidates all endpoints into the USBDriver structure.*/
+ for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
+#if USB_USE_WAIT == TRUE
+ /* Signaling the event to threads waiting on endpoints.*/
+ if (usbp->epc[i] != NULL) {
+ osalSysLockFromISR();
+ if (usbp->epc[i]->in_state != NULL) {
+ osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET);
+ }
+ if (usbp->epc[i]->out_state != NULL) {
+ osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET);
+ }
+ osalSysUnlockFromISR();
+ }
+#endif
+ usbp->epc[i] = NULL;
+ }
+
+ /* EP0 state machine initialization.*/
+ usbp->ep0state = USB_EP0_STP_WAITING;
+
+ /* Low level reset.*/
+ usb_lld_reset(usbp);
+
+ /* Notification of reset event.*/
+ _usb_isr_invoke_event_cb(usbp, USB_EVENT_RESET);
+}
+
+/**
+ * @brief USB suspend routine.
+ * @details This function must be invoked when an USB bus suspend condition is
+ * detected.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+void _usb_suspend(USBDriver *usbp) {
+ /* No state change, suspend always returns to previous state. */
+
+ /* State transition.*/
+ usbp->saved_state = usbp->state;
+ usbp->state = USB_SUSPENDED;
+
+ /* Notification of suspend event.*/
+ _usb_isr_invoke_event_cb(usbp, USB_EVENT_SUSPEND);
+
+ /* Terminating all pending transactions.*/
+ usbp->transmitting = 0;
+ usbp->receiving = 0;
+
+ /* Signaling the event to threads waiting on endpoints.*/
+#if USB_USE_WAIT == TRUE
+ {
+ unsigned i;
+
+ for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
+ if (usbp->epc[i] != NULL) {
+ osalSysLockFromISR();
+ if (usbp->epc[i]->in_state != NULL) {
+ osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET);
+ }
+ if (usbp->epc[i]->out_state != NULL) {
+ osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET);
+ }
+ osalSysUnlockFromISR();
+ }
+ }
+ }
+#endif
+}
+
+/**
+ * @brief USB wake-up routine.
+ * @details This function must be invoked when an USB bus wake-up condition is
+ * detected.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+void _usb_wakeup(USBDriver *usbp) {
+
+ /* State transition, returning to the previous state.*/
+ usbp->state = usbp->saved_state;
+
+ /* Notification of suspend event.*/
+ _usb_isr_invoke_event_cb(usbp, USB_EVENT_WAKEUP);
+}
+
+/**
+ * @brief Default EP0 SETUP callback.
+ * @details This function is used by the low level driver as default handler
+ * for EP0 SETUP events.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number, always zero
+ *
+ * @notapi
+ */
+void _usb_ep0setup(USBDriver *usbp, usbep_t ep) {
+ size_t max;
+
+ /* Is the EP0 state machine in the correct state for handling setup
+ packets?*/
+ if (usbp->ep0state != USB_EP0_STP_WAITING) {
+ /* This is unexpected could require handling with a warning event.*/
+ /* CHTODO: handling here.*/
+
+ /* Resetting the EP0 state machine and going ahead.*/
+ usbp->ep0state = USB_EP0_STP_WAITING;
+ }
+
+ /* Reading the setup data into the driver buffer.*/
+ usbReadSetup(usbp, ep, usbp->setup);
+
+ /* First verify if the application has an handler installed for this
+ request.*/
+ /*lint -save -e9007 [13.5] No side effects, it is intentional.*/
+ if ((usbp->config->requests_hook_cb == NULL) ||
+ !(usbp->config->requests_hook_cb(usbp))) {
+ /*lint -restore*/
+ /* Invoking the default handler, if this fails then stalls the
+ endpoint zero as error.*/
+ /*lint -save -e9007 [13.5] No side effects, it is intentional.*/
+ if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) != USB_RTYPE_TYPE_STD) ||
+ !default_handler(usbp)) {
+ /*lint -restore*/
+ /* Error response, the state machine goes into an error state, the low
+ level layer will have to reset it to USB_EP0_WAITING_SETUP after
+ receiving a SETUP packet.*/
+ usb_lld_stall_in(usbp, 0);
+ usb_lld_stall_out(usbp, 0);
+ _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED);
+ usbp->ep0state = USB_EP0_ERROR;
+ return;
+ }
+ }
+#if (USB_SET_ADDRESS_ACK_HANDLING == USB_SET_ADDRESS_ACK_HW)
+ if (usbp->setup[1] == USB_REQ_SET_ADDRESS) {
+ /* Zero-length packet sent by hardware */
+ return;
+ }
+#endif
+ /* Transfer preparation. The request handler must have populated
+ correctly the fields ep0next, ep0n and ep0endcb using the macro
+ usbSetupTransfer().*/
+ max = (size_t)get_hword(&usbp->setup[6]);
+ /* The transfer size cannot exceed the specified amount.*/
+ if (usbp->ep0n > max) {
+ usbp->ep0n = max;
+ }
+ if ((usbp->setup[0] & USB_RTYPE_DIR_MASK) == USB_RTYPE_DIR_DEV2HOST) {
+ /* IN phase.*/
+ if (usbp->ep0n != 0U) {
+ /* Starts the transmit phase.*/
+ usbp->ep0state = USB_EP0_IN_TX;
+ osalSysLockFromISR();
+ usbStartTransmitI(usbp, 0, usbp->ep0next, usbp->ep0n);
+ osalSysUnlockFromISR();
+ }
+ else {
+ /* No transmission phase, directly receiving the zero sized status
+ packet.*/
+ usbp->ep0state = USB_EP0_OUT_WAITING_STS;
+#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
+ osalSysLockFromISR();
+ usbStartReceiveI(usbp, 0, NULL, 0);
+ osalSysUnlockFromISR();
+#else
+ usb_lld_end_setup(usbp, ep);
+#endif
+ }
+ }
+ else {
+ /* OUT phase.*/
+ if (usbp->ep0n != 0U) {
+ /* Starts the receive phase.*/
+ usbp->ep0state = USB_EP0_OUT_RX;
+ osalSysLockFromISR();
+ usbStartReceiveI(usbp, 0, (uint8_t *)usbp->ep0next, usbp->ep0n);
+ osalSysUnlockFromISR();
+ }
+ else {
+ /* No receive phase, directly sending the zero sized status
+ packet.*/
+ usbp->ep0state = USB_EP0_IN_SENDING_STS;
+#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
+ osalSysLockFromISR();
+ usbStartTransmitI(usbp, 0, NULL, 0);
+ osalSysUnlockFromISR();
+#else
+ usb_lld_end_setup(usbp, ep);
+#endif
+ }
+ }
+}
+
+/**
+ * @brief Default EP0 IN callback.
+ * @details This function is used by the low level driver as default handler
+ * for EP0 IN events.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number, always zero
+ *
+ * @notapi
+ */
+void _usb_ep0in(USBDriver *usbp, usbep_t ep) {
+ size_t max;
+
+ (void)ep;
+ switch (usbp->ep0state) {
+ case USB_EP0_IN_TX:
+ max = (size_t)get_hword(&usbp->setup[6]);
+ /* If the transmitted size is less than the requested size and it is a
+ multiple of the maximum packet size then a zero size packet must be
+ transmitted.*/
+ if ((usbp->ep0n < max) &&
+ ((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0U)) {
+ osalSysLockFromISR();
+ usbStartTransmitI(usbp, 0, NULL, 0);
+ osalSysUnlockFromISR();
+ usbp->ep0state = USB_EP0_IN_WAITING_TX0;
+ return;
+ }
+ /* Falls through.*/
+ case USB_EP0_IN_WAITING_TX0:
+ /* Transmit phase over, receiving the zero sized status packet.*/
+ usbp->ep0state = USB_EP0_OUT_WAITING_STS;
+#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
+ osalSysLockFromISR();
+ usbStartReceiveI(usbp, 0, NULL, 0);
+ osalSysUnlockFromISR();
+#else
+ usb_lld_end_setup(usbp, ep);
+#endif
+ return;
+ case USB_EP0_IN_SENDING_STS:
+ /* Status packet sent, invoking the callback if defined.*/
+ if (usbp->ep0endcb != NULL) {
+ usbp->ep0endcb(usbp);
+ }
+ usbp->ep0state = USB_EP0_STP_WAITING;
+ return;
+ case USB_EP0_STP_WAITING:
+ case USB_EP0_OUT_WAITING_STS:
+ case USB_EP0_OUT_RX:
+ /* All the above are invalid states in the IN phase.*/
+ osalDbgAssert(false, "EP0 state machine error");
+ /* Falls through.*/
+ case USB_EP0_ERROR:
+ /* Error response, the state machine goes into an error state, the low
+ level layer will have to reset it to USB_EP0_WAITING_SETUP after
+ receiving a SETUP packet.*/
+ usb_lld_stall_in(usbp, 0);
+ usb_lld_stall_out(usbp, 0);
+ _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED);
+ usbp->ep0state = USB_EP0_ERROR;
+ return;
+ default:
+ osalDbgAssert(false, "EP0 state machine invalid state");
+ }
+}
+
+/**
+ * @brief Default EP0 OUT callback.
+ * @details This function is used by the low level driver as default handler
+ * for EP0 OUT events.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number, always zero
+ *
+ * @notapi
+ */
+void _usb_ep0out(USBDriver *usbp, usbep_t ep) {
+
+ (void)ep;
+ switch (usbp->ep0state) {
+ case USB_EP0_OUT_RX:
+ /* Receive phase over, sending the zero sized status packet.*/
+ usbp->ep0state = USB_EP0_IN_SENDING_STS;
+#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
+ osalSysLockFromISR();
+ usbStartTransmitI(usbp, 0, NULL, 0);
+ osalSysUnlockFromISR();
+#else
+ usb_lld_end_setup(usbp, ep);
+#endif
+ return;
+ case USB_EP0_OUT_WAITING_STS:
+ /* Status packet received, it must be zero sized, invoking the callback
+ if defined.*/
+#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
+ if (usbGetReceiveTransactionSizeX(usbp, 0) != 0U) {
+ break;
+ }
+#endif
+ if (usbp->ep0endcb != NULL) {
+ usbp->ep0endcb(usbp);
+ }
+ usbp->ep0state = USB_EP0_STP_WAITING;
+ return;
+ case USB_EP0_STP_WAITING:
+ case USB_EP0_IN_TX:
+ case USB_EP0_IN_WAITING_TX0:
+ case USB_EP0_IN_SENDING_STS:
+ /* All the above are invalid states in the IN phase.*/
+ osalDbgAssert(false, "EP0 state machine error");
+ /* Falls through.*/
+ case USB_EP0_ERROR:
+ /* Error response, the state machine goes into an error state, the low
+ level layer will have to reset it to USB_EP0_WAITING_SETUP after
+ receiving a SETUP packet.*/
+ usb_lld_stall_in(usbp, 0);
+ usb_lld_stall_out(usbp, 0);
+ _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED);
+ usbp->ep0state = USB_EP0_ERROR;
+ return;
+ default:
+ osalDbgAssert(false, "EP0 state machine invalid state");
+ }
+}
+
+#endif /* HAL_USE_USB == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_wdg.c b/ChibiOS_20.3.2/os/hal/src/hal_wdg.c
new file mode 100644
index 0000000..442b2a2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_wdg.c
@@ -0,0 +1,124 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_wdg.c
+ * @brief WDG Driver code.
+ *
+ * @addtogroup WDG
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief WDG Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void wdgInit(void) {
+
+ wdg_lld_init();
+}
+
+/**
+ * @brief Configures and activates the WDG peripheral.
+ *
+ * @param[in] wdgp pointer to the @p WDGDriver object
+ * @param[in] config pointer to the @p WDGConfig object
+ *
+ * @api
+ */
+void wdgStart(WDGDriver *wdgp, const WDGConfig *config) {
+
+ osalDbgCheck((wdgp != NULL) && (config != NULL));
+
+ osalSysLock();
+ osalDbgAssert((wdgp->state == WDG_STOP) || (wdgp->state == WDG_READY),
+ "invalid state");
+ wdgp->config = config;
+ wdg_lld_start(wdgp);
+ wdgp->state = WDG_READY;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the WDG peripheral.
+ *
+ * @param[in] wdgp pointer to the @p WDGDriver object
+ *
+ * @api
+ */
+void wdgStop(WDGDriver *wdgp) {
+
+ osalDbgCheck(wdgp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((wdgp->state == WDG_STOP) || (wdgp->state == WDG_READY),
+ "invalid state");
+
+ wdg_lld_stop(wdgp);
+ wdgp->config = NULL;
+ wdgp->state = WDG_STOP;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Resets WDG's counter.
+ *
+ * @param[in] wdgp pointer to the @p WDGDriver object
+ *
+ * @api
+ */
+void wdgReset(WDGDriver *wdgp) {
+
+ osalDbgCheck(wdgp != NULL);
+
+ osalSysLock();
+ osalDbgAssert(wdgp->state == WDG_READY, "not ready");
+ wdgResetI(wdgp);
+ osalSysUnlock();
+}
+
+#endif /* HAL_USE_WDG == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/src/hal_wspi.c b/ChibiOS_20.3.2/os/hal/src/hal_wspi.c
new file mode 100644
index 0000000..b4dfe04
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/src/hal_wspi.c
@@ -0,0 +1,410 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_wspi.c
+ * @brief WSPI Driver code.
+ *
+ * @addtogroup WSPI
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief WSPI Driver initialization.
+ * @note This function is implicitly invoked by @p halInit(), there is
+ * no need to explicitly initialize the driver.
+ *
+ * @init
+ */
+void wspiInit(void) {
+
+ wspi_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p WSPIDriver structure.
+ *
+ * @param[out] wspip pointer to the @p WSPIDriver object
+ *
+ * @init
+ */
+void wspiObjectInit(WSPIDriver *wspip) {
+
+ wspip->state = WSPI_STOP;
+ wspip->config = NULL;
+#if WSPI_USE_WAIT == TRUE
+ wspip->thread = NULL;
+#endif
+#if WSPI_USE_MUTUAL_EXCLUSION == TRUE
+ osalMutexObjectInit(&wspip->mutex);
+#endif
+#if defined(WSPI_DRIVER_EXT_INIT_HOOK)
+ WSPI_DRIVER_EXT_INIT_HOOK(wspip);
+#endif
+}
+
+/**
+ * @brief Configures and activates the WSPI peripheral.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] config pointer to the @p WSPIConfig object
+ *
+ * @api
+ */
+void wspiStart(WSPIDriver *wspip, const WSPIConfig *config) {
+
+ osalDbgCheck((wspip != NULL) && (config != NULL));
+
+ osalSysLock();
+
+ osalDbgAssert((wspip->state == WSPI_STOP) || (wspip->state == WSPI_READY),
+ "invalid state");
+
+ wspip->config = config;
+ wspi_lld_start(wspip);
+ wspip->state = WSPI_READY;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the WSPI peripheral.
+ * @note Deactivating the peripheral also enforces a release of the slave
+ * select line.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @api
+ */
+void wspiStop(WSPIDriver *wspip) {
+
+ osalDbgCheck(wspip != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((wspip->state == WSPI_STOP) || (wspip->state == WSPI_READY),
+ "invalid state");
+
+ wspi_lld_stop(wspip);
+ wspip->config = NULL;
+ wspip->state = WSPI_STOP;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Sends a command without data phase.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ *
+ * @api
+ */
+void wspiStartCommand(WSPIDriver *wspip, const wspi_command_t *cmdp) {
+
+ osalDbgCheck((wspip != NULL) && (cmdp != NULL));
+
+ osalSysLock();
+
+ osalDbgAssert(wspip->state == WSPI_READY, "not ready");
+
+ wspiStartCommandI(wspip, cmdp);
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Sends a command with data over the WSPI bus.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[in] n number of bytes to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @api
+ */
+void wspiStartSend(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, const uint8_t *txbuf) {
+
+ osalDbgCheck((wspip != NULL) && (cmdp != NULL));
+ osalDbgCheck((n > 0U) && (txbuf != NULL));
+
+ osalSysLock();
+
+ osalDbgAssert(wspip->state == WSPI_READY, "not ready");
+
+ wspiStartSendI(wspip, cmdp, n, txbuf);
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Sends a command then receives data over the WSPI bus.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[in] n number of bytes to send
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @api
+ */
+void wspiStartReceive(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, uint8_t *rxbuf) {
+
+ osalDbgCheck((wspip != NULL) && (cmdp != NULL));
+ osalDbgCheck((n > 0U) && (rxbuf != NULL));
+
+ osalSysLock();
+
+ osalDbgAssert(wspip->state == WSPI_READY, "not ready");
+
+ wspiStartReceiveI(wspip, cmdp, n, rxbuf);
+
+ osalSysUnlock();
+}
+
+#if (WSPI_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Sends a command without data phase.
+ * @pre In order to use this function the option @p WSPI_USE_WAIT must be
+ * enabled.
+ * @pre In order to use this function the driver must have been configured
+ * without callbacks (@p end_cb = @p NULL).
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @return The operation status.
+ * @retval false if the operation succeeded.
+ * @retval true if the operation failed because HW issues.
+ *
+ * @api
+ */
+bool wspiCommand(WSPIDriver *wspip, const wspi_command_t *cmdp) {
+ msg_t msg;
+
+ osalDbgCheck((wspip != NULL) && (cmdp != NULL));
+ osalDbgCheck((cmdp->cfg & WSPI_CFG_DATA_MODE_MASK) == WSPI_CFG_DATA_MODE_NONE);
+
+ osalSysLock();
+
+ osalDbgAssert(wspip->state == WSPI_READY, "not ready");
+ osalDbgAssert(wspip->config->end_cb == NULL, "has callback");
+
+ wspiStartCommandI(wspip, cmdp);
+ msg = osalThreadSuspendS(&wspip->thread);
+
+ osalSysUnlock();
+
+ return (bool)(msg != MSG_OK);
+}
+
+/**
+ * @brief Sends a command with data over the WSPI bus.
+ * @pre In order to use this function the option @p WSPI_USE_WAIT must be
+ * enabled.
+ * @pre In order to use this function the driver must have been configured
+ * without callbacks (@p end_cb = @p NULL).
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[in] n number of bytes to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ * @return The operation status.
+ * @retval false if the operation succeeded.
+ * @retval true if the operation failed because HW issues.
+ *
+ * @api
+ */
+bool wspiSend(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, const uint8_t *txbuf) {
+ msg_t msg;
+
+ osalDbgCheck((wspip != NULL) && (cmdp != NULL));
+ osalDbgCheck((n > 0U) && (txbuf != NULL));
+ osalDbgCheck((cmdp->cfg & WSPI_CFG_DATA_MODE_MASK) != WSPI_CFG_DATA_MODE_NONE);
+
+ osalSysLock();
+
+ osalDbgAssert(wspip->state == WSPI_READY, "not ready");
+ osalDbgAssert(wspip->config->end_cb == NULL, "has callback");
+
+ wspiStartSendI(wspip, cmdp, n, txbuf);
+ msg = osalThreadSuspendS(&wspip->thread);
+
+ osalSysUnlock();
+
+ return (bool)(msg != MSG_OK);
+}
+
+/**
+ * @brief Sends a command then receives data over the WSPI bus.
+ * @pre In order to use this function the option @p WSPI_USE_WAIT must be
+ * enabled.
+ * @pre In order to use this function the driver must have been configured
+ * without callbacks (@p end_cb = @p NULL).
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[in] n number of bytes to send
+ * @param[out] rxbuf the pointer to the receive buffer
+ * @return The operation status.
+ * @retval false if the operation succeeded.
+ * @retval true if the operation failed because HW issues.
+ *
+ * @api
+ */
+bool wspiReceive(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, uint8_t *rxbuf) {
+ msg_t msg;
+
+ osalDbgCheck((wspip != NULL) && (cmdp != NULL));
+ osalDbgCheck((n > 0U) && (rxbuf != NULL));
+ osalDbgCheck((cmdp->cfg & WSPI_CFG_DATA_MODE_MASK) != WSPI_CFG_DATA_MODE_NONE);
+
+ osalSysLock();
+
+ osalDbgAssert(wspip->state == WSPI_READY, "not ready");
+ osalDbgAssert(wspip->config->end_cb == NULL, "has callback");
+
+ wspiStartReceiveI(wspip, cmdp, n, rxbuf);
+ msg = osalThreadSuspendS(&wspip->thread);
+
+ osalSysUnlock();
+
+ return (bool)(msg != MSG_OK);
+}
+#endif /* WSPI_USE_WAIT == TRUE */
+
+#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Maps in memory space a WSPI flash device.
+ * @pre The memory flash device must be initialized appropriately
+ * before mapping it in memory space.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[out] addrp pointer to the memory start address of the mapped
+ * flash or @p NULL
+ *
+ * @api
+ */
+void wspiMapFlash(WSPIDriver *wspip,
+ const wspi_command_t *cmdp,
+ uint8_t **addrp) {
+
+ osalDbgCheck((wspip != NULL) && (cmdp != NULL));
+ osalDbgCheck((cmdp->cfg & WSPI_CFG_DATA_MODE_MASK) != WSPI_CFG_DATA_MODE_NONE);
+
+ osalSysLock();
+
+ osalDbgAssert(wspip->state == WSPI_READY, "not ready");
+
+ wspiMapFlashI(wspip, cmdp, addrp);
+ wspip->state = WSPI_MEMMAP;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Unmaps from memory space a WSPI flash device.
+ * @post The memory flash device must be re-initialized for normal
+ * commands exchange.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @api
+ */
+void wspiUnmapFlash(WSPIDriver *wspip) {
+
+ osalDbgCheck(wspip != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert(wspip->state == WSPI_MEMMAP, "not ready");
+
+ wspiUnmapFlashI(wspip);
+ wspip->state = WSPI_READY;
+
+ osalSysUnlock();
+}
+#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */
+
+#if (WSPI_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Gains exclusive access to the WSPI bus.
+ * @details This function tries to gain ownership to the WSPI bus, if the bus
+ * is already being used then the invoking thread is queued.
+ * @pre In order to use this function the option @p WSPI_USE_MUTUAL_EXCLUSION
+ * must be enabled.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @api
+ */
+void wspiAcquireBus(WSPIDriver *wspip) {
+
+ osalDbgCheck(wspip != NULL);
+
+ osalMutexLock(&wspip->mutex);
+}
+
+/**
+ * @brief Releases exclusive access to the WSPI bus.
+ * @pre In order to use this function the option @p WSPI_USE_MUTUAL_EXCLUSION
+ * must be enabled.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @api
+ */
+void wspiReleaseBus(WSPIDriver *wspip) {
+
+ osalDbgCheck(wspip != NULL);
+
+ osalMutexUnlock(&wspip->mutex);
+}
+#endif /* WSPI_USE_MUTUAL_EXCLUSION == TRUE */
+
+#endif /* HAL_USE_WSPI == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/board/board.c b/ChibiOS_20.3.2/os/hal/templates/board/board.c
new file mode 100644
index 0000000..2757a5b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/board/board.c
@@ -0,0 +1,24 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#include "hal.h"
+
+/**
+ * @brief Board-specific initialization code.
+ * @note You can add your board-specific code here.
+ */
+void boardInit(void) {
+}
diff --git a/ChibiOS_20.3.2/os/hal/templates/board/board.h b/ChibiOS_20.3.2/os/hal/templates/board/board.h
new file mode 100644
index 0000000..d6186de
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/board/board.h
@@ -0,0 +1,40 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef BOARD_H
+#define BOARD_H
+
+/*
+ * Setup for a generic board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_GENERIC
+#define BOARD_NAME "Generic Board"
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* BOARD_H */
diff --git a/ChibiOS_20.3.2/os/hal/templates/board/board.mk b/ChibiOS_20.3.2/os/hal/templates/board/board.mk
new file mode 100644
index 0000000..a8506ee
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/board/board.mk
@@ -0,0 +1,5 @@
+# List of all the board related files.
+BOARDSRC = $(CHIBIOS)/os/hal/templates/board/board.c
+
+# Required include directories
+BOARDINC = $(CHIBIOS)/os/hal/templates/board
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_adc_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_adc_lld.c
new file mode 100644
index 0000000..48169e0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_adc_lld.c
@@ -0,0 +1,141 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_adc_lld.c
+ * @brief PLATFORM ADC subsystem low level driver source.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_ADC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC1 driver identifier.
+ */
+#if (PLATFORM_ADC_USE_ADC1 == TRUE) || defined(__DOXYGEN__)
+ADCDriver ADCD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level ADC driver initialization.
+ *
+ * @notapi
+ */
+void adc_lld_init(void) {
+
+#if PLATFORM_ADC_USE_ADC1 == TRUE
+ /* Driver initialization.*/
+ adcObjectInit(&ADCD1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start(ADCDriver *adcp) {
+
+ if (adcp->state == ADC_STOP) {
+ /* Enables the peripheral.*/
+#if PLATFORM_ADC_USE_ADC1 == TRUE
+ if (&ADCD1 == adcp) {
+
+ }
+#endif
+ }
+ /* Configures the peripheral.*/
+
+}
+
+/**
+ * @brief Deactivates the ADC peripheral.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop(ADCDriver *adcp) {
+
+ if (adcp->state == ADC_READY) {
+ /* Resets the peripheral.*/
+
+ /* Disables the peripheral.*/
+#if PLATFORM_ADC_USE_ADC1 == TRUE
+ if (&ADCD1 == adcp) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Starts an ADC conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_start_conversion(ADCDriver *adcp) {
+
+ (void)adcp;
+}
+
+/**
+ * @brief Stops an ongoing conversion.
+ *
+ * @param[in] adcp pointer to the @p ADCDriver object
+ *
+ * @notapi
+ */
+void adc_lld_stop_conversion(ADCDriver *adcp) {
+
+ (void)adcp;
+}
+
+#endif /* HAL_USE_ADC == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_adc_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_adc_lld.h
new file mode 100644
index 0000000..4ba9bc0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_adc_lld.h
@@ -0,0 +1,130 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_adc_lld.h
+ * @brief PLATFORM ADC subsystem low level driver header.
+ *
+ * @addtogroup ADC
+ * @{
+ */
+
+#ifndef HAL_ADC_LLD_H
+#define HAL_ADC_LLD_H
+
+#if (HAL_USE_ADC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief ADC1 driver enable switch.
+ * @details If set to @p TRUE the support for ADC1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_ADC_USE_ADC1) || defined(__DOXYGEN__)
+#define PLATFORM_ADC_USE_ADC1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief ADC sample data type.
+ */
+typedef uint16_t adcsample_t;
+
+/**
+ * @brief Channels number in a conversion group.
+ */
+typedef uint16_t adc_channels_num_t;
+
+/**
+ * @brief Possible ADC failure causes.
+ * @note Error codes are architecture dependent and should not relied
+ * upon.
+ */
+typedef enum {
+ ADC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */
+ ADC_ERR_OVERFLOW = 1, /**< ADC overflow condition. */
+ ADC_ERR_AWD = 2 /**< Analog watchdog triggered. */
+} adcerror_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the ADC driver structure.
+ */
+#define adc_lld_driver_fields \
+ /* Dummy field, it is not needed.*/ \
+ uint32_t dummy
+
+/**
+ * @brief Low level fields of the ADC configuration structure.
+ */
+#define adc_lld_config_fields \
+ /* Dummy configuration, it is not needed.*/ \
+ uint32_t dummy
+
+/**
+ * @brief Low level fields of the ADC configuration structure.
+ */
+#define adc_lld_configuration_group_fields \
+ /* Dummy configuration, it is not needed.*/ \
+ uint32_t dummy
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_ADC_USE_ADC1 == TRUE) && !defined(__DOXYGEN__)
+extern ADCDriver ADCD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void adc_lld_init(void);
+ void adc_lld_start(ADCDriver *adcp);
+ void adc_lld_stop(ADCDriver *adcp);
+ void adc_lld_start_conversion(ADCDriver *adcp);
+ void adc_lld_stop_conversion(ADCDriver *adcp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_ADC == TRUE */
+
+#endif /* HAL_ADC_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_can_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_can_lld.c
new file mode 100644
index 0000000..57d62bb
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_can_lld.c
@@ -0,0 +1,257 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_can_lld.c
+ * @brief PLATFORM CAN subsystem low level driver source.
+ *
+ * @addtogroup CAN
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_CAN == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief CAN1 driver identifier.
+ */
+#if (PLATFORM_CAN_USE_CAN1 == TRUE) || defined(__DOXYGEN__)
+CANDriver CAND1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level CAN driver initialization.
+ *
+ * @notapi
+ */
+void can_lld_init(void) {
+
+#if PLATFORM_CAN_USE_CAN1 == TRUE
+ /* Driver initialization.*/
+ canObjectInit(&CAND1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the CAN peripheral.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+void can_lld_start(CANDriver *canp) {
+
+ if (canp->state == CAN_STOP) {
+ /* Enables the peripheral.*/
+#if PLATFORM_CAN_USE_CAN1 == TRUE
+ if (&CAND1 == canp) {
+
+ }
+#endif
+ }
+ /* Configures the peripheral.*/
+
+}
+
+/**
+ * @brief Deactivates the CAN peripheral.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+void can_lld_stop(CANDriver *canp) {
+
+ if (canp->state == CAN_READY) {
+ /* Resets the peripheral.*/
+
+ /* Disables the peripheral.*/
+#if PLATFORM_CAN_USE_CAN1 == TRUE
+ if (&CAND1 == canp) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Determines whether a frame can be transmitted.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
+ *
+ * @return The queue space availability.
+ * @retval false no space in the transmit queue.
+ * @retval true transmit slot available.
+ *
+ * @notapi
+ */
+bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) {
+
+ (void)canp;
+
+ switch (mailbox) {
+ case CAN_ANY_MAILBOX:
+ return false;
+ case 1:
+ return false;
+ case 2:
+ return false;
+ case 3:
+ return false;
+ default:
+ return false;
+ }
+}
+
+/**
+ * @brief Inserts a frame into the transmit queue.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] ctfp pointer to the CAN frame to be transmitted
+ * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
+ *
+ * @notapi
+ */
+void can_lld_transmit(CANDriver *canp,
+ canmbx_t mailbox,
+ const CANTxFrame *ctfp) {
+
+ (void)canp;
+ (void)mailbox;
+ (void)ctfp;
+
+}
+
+/**
+ * @brief Determines whether a frame has been received.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
+ *
+ * @return The queue space availability.
+ * @retval false no space in the transmit queue.
+ * @retval true transmit slot available.
+ *
+ * @notapi
+ */
+bool can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox) {
+
+ (void)canp;
+ (void)mailbox;
+
+ switch (mailbox) {
+ case CAN_ANY_MAILBOX:
+ return false;
+ case 1:
+ return false;
+ case 2:
+ return false;
+ default:
+ return false;
+ }
+}
+
+/**
+ * @brief Receives a frame from the input queue.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
+ * @param[out] crfp pointer to the buffer where the CAN frame is copied
+ *
+ * @notapi
+ */
+void can_lld_receive(CANDriver *canp,
+ canmbx_t mailbox,
+ CANRxFrame *crfp) {
+
+ (void)canp;
+ (void)mailbox;
+ (void)crfp;
+
+}
+
+/**
+ * @brief Tries to abort an ongoing transmission.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ * @param[in] mailbox mailbox number
+ *
+ * @notapi
+ */
+void can_lld_abort(CANDriver *canp,
+ canmbx_t mailbox) {
+
+ (void)canp;
+ (void)mailbox;
+}
+
+#if (CAN_USE_SLEEP_MODE == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Enters the sleep mode.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+void can_lld_sleep(CANDriver *canp) {
+
+ (void)canp;
+
+}
+
+/**
+ * @brief Enforces leaving the sleep mode.
+ *
+ * @param[in] canp pointer to the @p CANDriver object
+ *
+ * @notapi
+ */
+void can_lld_wakeup(CANDriver *canp) {
+
+ (void)canp;
+
+}
+#endif /* CAN_USE_SLEEP_MOD == TRUEE */
+
+#endif /* HAL_USE_CAN == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_can_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_can_lld.h
new file mode 100644
index 0000000..6128f25
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_can_lld.h
@@ -0,0 +1,275 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_can_lld.h
+ * @brief PLATFORM CAN subsystem low level driver header.
+ *
+ * @addtogroup CAN
+ * @{
+ */
+
+#ifndef HAL_CAN_LLD_H
+#define HAL_CAN_LLD_H
+
+#if (HAL_USE_CAN == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of transmit mailboxes.
+ */
+#define CAN_TX_MAILBOXES 1
+
+/**
+ * @brief Number of receive mailboxes.
+ */
+#define CAN_RX_MAILBOXES 1
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief CAN1 driver enable switch.
+ * @details If set to @p TRUE the support for CAN1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_CAN_USE_CAN1) || defined(__DOXYGEN__)
+#define PLATFORM_CAN_USE_CAN1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a structure representing an CAN driver.
+ */
+typedef struct CANDriver CANDriver;
+
+/**
+ * @brief Type of a transmission mailbox index.
+ */
+typedef uint32_t canmbx_t;
+
+#if defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a CAN notification callback.
+ *
+ * @param[in] canp pointer to the @p CANDriver object triggering the
+ * callback
+ * @param[in] flags flags associated to the mailbox callback
+ */
+typedef void (*can_callback_t)(CANDriver *canp, uint32_t flags);
+#endif
+
+/**
+ * @brief CAN transmission frame.
+ * @note Accessing the frame data as word16 or word32 is not portable because
+ * machine data endianness, it can be still useful for a quick filling.
+ */
+typedef struct {
+ /*lint -save -e46 [6.1] Standard types are fine too.*/
+ uint8_t DLC:4; /**< @brief Data length. */
+ uint8_t RTR:1; /**< @brief Frame type. */
+ uint8_t IDE:1; /**< @brief Identifier type. */
+ union {
+ uint32_t SID:11; /**< @brief Standard identifier.*/
+ uint32_t EID:29; /**< @brief Extended identifier.*/
+ uint32_t _align1;
+ };
+ /*lint -restore*/
+ union {
+ uint8_t data8[8]; /**< @brief Frame data. */
+ uint16_t data16[4]; /**< @brief Frame data. */
+ uint32_t data32[2]; /**< @brief Frame data. */
+ };
+} CANTxFrame;
+
+/**
+ * @brief CAN received frame.
+ * @note Accessing the frame data as word16 or word32 is not portable because
+ * machine data endianness, it can be still useful for a quick filling.
+ */
+typedef struct {
+ /*lint -save -e46 [6.1] Standard types are fine too.*/
+ uint8_t FMI; /**< @brief Filter id. */
+ uint16_t TIME; /**< @brief Time stamp. */
+ uint8_t DLC:4; /**< @brief Data length. */
+ uint8_t RTR:1; /**< @brief Frame type. */
+ uint8_t IDE:1; /**< @brief Identifier type. */
+ union {
+ uint32_t SID:11; /**< @brief Standard identifier.*/
+ uint32_t EID:29; /**< @brief Extended identifier.*/
+ uint32_t _align1;
+ };
+ /*lint -restore*/
+ union {
+ uint8_t data8[8]; /**< @brief Frame data. */
+ uint16_t data16[4]; /**< @brief Frame data. */
+ uint32_t data32[2]; /**< @brief Frame data. */
+ };
+} CANRxFrame;
+
+/**
+ * @brief Driver configuration structure.
+ */
+typedef struct {
+ /* End of the mandatory fields.*/
+ uint32_t dummy;
+} CANConfig;
+
+/**
+ * @brief Structure representing an CAN driver.
+ */
+struct CANDriver {
+ /**
+ * @brief Driver state.
+ */
+ canstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const CANConfig *config;
+ /**
+ * @brief Transmission threads queue.
+ */
+ threads_queue_t txqueue;
+ /**
+ * @brief Receive threads queue.
+ */
+ threads_queue_t rxqueue;
+#if (CAN_ENFORCE_USE_CALLBACKS == FALSE) || defined (__DOXYGEN__)
+ /**
+ * @brief One or more frames become available.
+ * @note After broadcasting this event it will not be broadcasted again
+ * until the received frames queue has been completely emptied. It
+ * is not broadcasted for each received frame. It is
+ * responsibility of the application to empty the queue by
+ * repeatedly invoking @p chReceive() when listening to this event.
+ * This behavior minimizes the interrupt served by the system
+ * because CAN traffic.
+ * @note The flags associated to the listeners will indicate which
+ * receive mailboxes become non-empty.
+ */
+ event_source_t rxfull_event;
+ /**
+ * @brief One or more transmission mailbox become available.
+ * @note The flags associated to the listeners will indicate which
+ * transmit mailboxes become empty.
+ */
+ event_source_t txempty_event;
+ /**
+ * @brief A CAN bus error happened.
+ * @note The flags associated to the listeners will indicate the
+ * error(s) that have occurred.
+ */
+ event_source_t error_event;
+#if (CAN_USE_SLEEP_MODE == TRUE) || defined (__DOXYGEN__)
+ /**
+ * @brief Entering sleep state event.
+ */
+ event_source_t sleep_event;
+ /**
+ * @brief Exiting sleep state event.
+ */
+ event_source_t wakeup_event;
+#endif
+#else /* CAN_ENFORCE_USE_CALLBACKS == TRUE */
+ /**
+ * @brief One or more frames become available.
+ * @note After calling this function it will not be called again
+ * until the received frames queue has been completely emptied. It
+ * is not called for each received frame. It is
+ * responsibility of the application to empty the queue by
+ * repeatedly invoking @p chTryReceiveI().
+ * This behavior minimizes the interrupt served by the system
+ * because CAN traffic.
+ */
+ can_callback_t rxfull_cb;
+ /**
+ * @brief One or more transmission mailbox become available.
+ * @note The flags associated to the callback will indicate which
+ * transmit mailboxes become empty.
+ */
+ can_callback_t txempty_cb;
+ /**
+ * @brief A CAN bus error happened.
+ */
+ can_callback_t error_cb;
+#if (CAN_USE_SLEEP_MODE == TRUE) || defined (__DOXYGEN__)
+ /**
+ * @brief Exiting sleep state.
+ */
+ can_callback_t wakeup_cb;
+#endif
+#endif
+ /* End of the mandatory fields.*/
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_CAN_USE_CAN1 == TRUE) && !defined(__DOXYGEN__)
+extern CANDriver CAND1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void can_lld_init(void);
+ void can_lld_start(CANDriver *canp);
+ void can_lld_stop(CANDriver *canp);
+ bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox);
+ void can_lld_transmit(CANDriver *canp,
+ canmbx_t mailbox,
+ const CANTxFrame *ctfp);
+ bool can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox);
+ void can_lld_receive(CANDriver *canp,
+ canmbx_t mailbox,
+ CANRxFrame *crfp);
+ void can_lld_abort(CANDriver *canp,
+ canmbx_t mailbox);
+#if CAN_USE_SLEEP_MODE == TRUE
+ void can_lld_sleep(CANDriver *canp);
+ void can_lld_wakeup(CANDriver *canp);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_CAN == TRUE */
+
+#endif /* HAL_CAN_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_crypto_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_crypto_lld.c
new file mode 100644
index 0000000..c149293
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_crypto_lld.c
@@ -0,0 +1,1346 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_crypto_lld.c
+ * @brief PLATFORM cryptographic subsystem low level driver source.
+ *
+ * @addtogroup CRYPTO
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_CRY == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief CRY1 driver identifier.*/
+#if PLATFORM_CRY_USE_CRY1 || defined(__DOXYGEN__)
+CRYDriver CRYD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level crypto driver initialization.
+ *
+ * @notapi
+ */
+void cry_lld_init(void) {
+
+}
+
+/**
+ * @brief Configures and activates the crypto peripheral.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ *
+ * @notapi
+ */
+void cry_lld_start(CRYDriver *cryp) {
+
+ if (cryp->state == CRY_STOP) {
+
+ }
+}
+
+/**
+ * @brief Deactivates the crypto peripheral.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ *
+ * @notapi
+ */
+void cry_lld_stop(CRYDriver *cryp) {
+
+ if (cryp->state == CRY_READY) {
+
+ }
+}
+
+#if (CRY_LLD_SUPPORTS_AES == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Initializes the AES transient key.
+ * @note It is the underlying implementation to decide which key sizes are
+ * allowable.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] size key size in bytes
+ * @param[in] keyp pointer to the key data
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the algorithm is unsupported.
+ * @retval CRY_ERR_INV_KEY_SIZE if the specified key size is invalid for
+ * the specified algorithm.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_aes_loadkey(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *keyp) {
+
+ (void)cryp;
+ (void)size;
+ (void)keyp;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Encryption of a single block using AES.
+ * @note The implementation of this function must guarantee that it can
+ * be called from any context.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_AES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Decryption of a single block using AES.
+ * @note The implementation of this function must guarantee that it can
+ * be called from any context.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] in buffer containing the input ciphertext
+ * @param[out] out buffer for the output plaintext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_AES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_AES_ECB == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Encryption operation using AES-ECB.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers, this number must be a
+ * multiple of 16
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_AES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Decryption operation using AES-ECB.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers, this number must be a
+ * multiple of 16
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_AES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_AES_CBC == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Encryption operation using AES-CBC.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers, this number must be a
+ * multiple of 16
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @param[in] iv 128 bits initial vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_AES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Decryption operation using AES-CBC.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an AES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers, this number must be a
+ * multiple of 16
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @param[in] iv 128 bits initial vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_AES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_AES_CFB == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Encryption operation using AES-CFB.
+ * @note This is a stream cipher, there are no size restrictions.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @param[in] iv 128 bits initial vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_AES_CFB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Decryption operation using AES-CFB.
+ * @note This is a stream cipher, there are no size restrictions.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @param[in] iv 128 bits initial vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_AES_CFB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_AES_CTR == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Encryption operation using AES-CTR.
+ * @note This is a stream cipher, there are no size restrictions.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @param[in] iv 128 bits initial vector + counter, it contains
+ * a 96 bits IV and a 32 bits counter
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_AES_CTR(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Decryption operation using AES-CTR.
+ * @note This is a stream cipher, there are no size restrictions.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of both buffers
+ * @param[in] in buffer containing the input ciphertext
+ * @param[out] out buffer for the output plaintext
+ * @param[in] iv 128 bits initial vector + counter, it contains
+ * a 96 bits IV and a 32 bits counter
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_AES_CTR(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_AES_GCM == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Encryption operation using AES-GCM.
+ * @note This is a stream cipher, there are no size restrictions.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] auth_size size of the data buffer to be authenticated
+ * @param[in] auth_in buffer containing the data to be authenticated
+ * @param[in] text_size size of the text buffer
+ * @param[in] text_in buffer containing the input plaintext
+ * @param[out] text_out buffer for the output ciphertext
+ * @param[in] iv 128 bits input vector
+ * @param[in] tag_size size of the authentication tag, this number
+ * must be between 1 and 16
+ * @param[out] tag_out buffer for the generated authentication tag
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_AES_GCM(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t auth_size,
+ const uint8_t *auth_in,
+ size_t text_size,
+ const uint8_t *text_in,
+ uint8_t *text_out,
+ const uint8_t *iv,
+ size_t tag_size,
+ uint8_t *tag_out) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)auth_size;
+ (void)auth_in;
+ (void)text_size;
+ (void)text_in;
+ (void)text_out;
+ (void)iv;
+ (void)tag_size;
+ (void)tag_out;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Decryption operation using AES-GCM.
+ * @note This is a stream cipher, there are no size restrictions.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] auth_size size of the data buffer to be authenticated
+ * @param[in] auth_in buffer containing the data to be authenticated
+ * @param[in] text_size size of the text buffer
+ * @param[in] text_in buffer containing the input plaintext
+ * @param[out] text_out buffer for the output ciphertext
+ * @param[in] iv 128 bits input vector
+ * @param[in] tag_size size of the authentication tag, this number
+ * must be between 1 and 16
+ * @param[in] tag_in buffer for the generated authentication tag
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_AUTH_FAILED authentication failed
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_AES_GCM(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t auth_size,
+ const uint8_t *auth_in,
+ size_t text_size,
+ const uint8_t *text_in,
+ uint8_t *text_out,
+ const uint8_t *iv,
+ size_t tag_size,
+ const uint8_t *tag_in) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)auth_size;
+ (void)auth_in;
+ (void)text_size;
+ (void)text_in;
+ (void)text_out;
+ (void)iv;
+ (void)tag_size;
+ (void)tag_in;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_DES == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Initializes the DES transient key.
+ * @note It is the underlying implementation to decide which key sizes are
+ * allowable.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] size key size in bytes
+ * @param[in] keyp pointer to the key data
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the algorithm is unsupported.
+ * @retval CRY_ERR_INV_KEY_SIZE if the specified key size is invalid for
+ * the specified algorithm.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_des_loadkey(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *keyp) {
+
+ (void)cryp;
+ (void)size;
+ (void)keyp;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Encryption of a single block using (T)DES.
+ * @note The implementation of this function must guarantee that it can
+ * be called from any context.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_DES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Decryption of a single block using (T)DES.
+ * @note The implementation of this function must guarantee that it can
+ * be called from any context.
+ *
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] in buffer containing the input ciphertext
+ * @param[out] out buffer for the output plaintext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_DES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_DES_ECB == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Encryption operation using (T)DES-ECB.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an DES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of the plaintext buffer, this number must
+ * be a multiple of 8
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_DES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Decryption operation using (T)DES-ECB.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an DES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of the plaintext buffer, this number must
+ * be a multiple of 8
+ * @param[in] in buffer containing the input ciphertext
+ * @param[out] out buffer for the output plaintext
+ * @return T he operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_DES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_DES_CBC == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Encryption operation using (T)DES-CBC.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an DES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of the plaintext buffer, this number must
+ * be a multiple of 8
+ * @param[in] in buffer containing the input plaintext
+ * @param[out] out buffer for the output ciphertext
+ * @param[in] iv 64 bits input vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_encrypt_DES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Decryption operation using (T)DES-CBC.
+ * @note The function operates on data buffers whose length is a multiple
+ * of an DES block, this means that padding must be done by the
+ * caller.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] key_id the key to be used for the operation, zero is
+ * the transient key, other values are keys stored
+ * in an unspecified way
+ * @param[in] size size of the plaintext buffer, this number must
+ * be a multiple of 8
+ * @param[in] in buffer containing the input ciphertext
+ * @param[out] out buffer for the output plaintext
+ * @param[in] iv 64 bits input vector
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_INV_KEY_TYPE the selected key is invalid for this operation.
+ * @retval CRY_ERR_INV_KEY_ID if the specified key identifier is invalid
+ * or refers to an empty key slot.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_decrypt_DES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv) {
+
+ (void)cryp;
+ (void)key_id;
+ (void)size;
+ (void)in;
+ (void)out;
+ (void)iv;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_SHA1 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Hash initialization using SHA1.
+ * @note Use of this algorithm is not recommended because proven weak.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[out] sha1ctxp pointer to a SHA1 context to be initialized
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_SHA1_init(CRYDriver *cryp, SHA1Context *sha1ctxp) {
+
+ (void)cryp;
+ (void)sha1ctxp;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash update using SHA1.
+ * @note Use of this algorithm is not recommended because proven weak.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] sha1ctxp pointer to a SHA1 context
+ * @param[in] size size of input buffer
+ * @param[in] in buffer containing the input text
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_SHA1_update(CRYDriver *cryp, SHA1Context *sha1ctxp,
+ size_t size, const uint8_t *in) {
+
+ (void)cryp;
+ (void)sha1ctxp;
+ (void)size;
+ (void)in;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash finalization using SHA1.
+ * @note Use of this algorithm is not recommended because proven weak.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] sha1ctxp pointer to a SHA1 context
+ * @param[out] out 160 bits output buffer
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_SHA1_final(CRYDriver *cryp, SHA1Context *sha1ctxp,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)sha1ctxp;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_SHA256 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Hash initialization using SHA256.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[out] sha256ctxp pointer to a SHA256 context to be initialized
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_SHA256_init(CRYDriver *cryp, SHA256Context *sha256ctxp) {
+
+ (void)cryp;
+ (void)sha256ctxp;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash update using SHA256.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] sha256ctxp pointer to a SHA256 context
+ * @param[in] size size of input buffer
+ * @param[in] in buffer containing the input text
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_SHA256_update(CRYDriver *cryp, SHA256Context *sha256ctxp,
+ size_t size, const uint8_t *in) {
+
+ (void)cryp;
+ (void)sha256ctxp;
+ (void)size;
+ (void)in;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash finalization using SHA256.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] sha256ctxp pointer to a SHA256 context
+ * @param[out] out 256 bits output buffer
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_SHA256_final(CRYDriver *cryp, SHA256Context *sha256ctxp,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)sha256ctxp;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_SHA512 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Hash initialization using SHA512.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[out] sha512ctxp pointer to a SHA512 context to be initialized
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_SHA512_init(CRYDriver *cryp, SHA512Context *sha512ctxp) {
+
+ (void)cryp;
+ (void)sha512ctxp;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash update using SHA512.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] sha512ctxp pointer to a SHA512 context
+ * @param[in] size size of input buffer
+ * @param[in] in buffer containing the input text
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_SHA512_update(CRYDriver *cryp, SHA512Context *sha512ctxp,
+ size_t size, const uint8_t *in) {
+
+ (void)cryp;
+ (void)sha512ctxp;
+ (void)size;
+ (void)in;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash finalization using SHA512.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] sha512ctxp pointer to a SHA512 context
+ * @param[out] out 512 bits output buffer
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_SHA512_final(CRYDriver *cryp, SHA512Context *sha512ctxp,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)sha512ctxp;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Initializes the HMAC transient key.
+ * @note It is the underlying implementation to decide which key sizes are
+ * allowable.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] size key size in bytes
+ * @param[in] keyp pointer to the key data
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the algorithm is unsupported.
+ * @retval CRY_ERR_INV_KEY_SIZE if the specified key size is invalid for
+ * the specified algorithm.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_hmac_loadkey(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *keyp) {
+
+ (void)cryp;
+ (void)size;
+ (void)keyp;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash initialization using HMAC_SHA256.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[out] hmacsha256ctxp pointer to a HMAC_SHA256 context to be
+ * initialized
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_HMACSHA256_init(CRYDriver *cryp,
+ HMACSHA256Context *hmacsha256ctxp) {
+
+ (void)cryp;
+ (void)hmacsha256ctxp;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash update using HMAC.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] hmacsha256ctxp pointer to a HMAC_SHA256 context
+ * @param[in] size size of input buffer
+ * @param[in] in buffer containing the input text
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_HMACSHA256_update(CRYDriver *cryp,
+ HMACSHA256Context *hmacsha256ctxp,
+ size_t size,
+ const uint8_t *in) {
+
+ (void)cryp;
+ (void)hmacsha256ctxp;
+ (void)size;
+ (void)in;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash finalization using HMAC.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] hmacsha256ctxp pointer to a HMAC_SHA256 context
+ * @param[out] out 256 bits output buffer
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_HMACSHA256_final(CRYDriver *cryp,
+ HMACSHA256Context *hmacsha256ctxp,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)hmacsha256ctxp;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#if (CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Hash initialization using HMAC_SHA512.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[out] hmacsha512ctxp pointer to a HMAC_SHA512 context to be
+ * initialized
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_HMACSHA512_init(CRYDriver *cryp,
+ HMACSHA512Context *hmacsha512ctxp) {
+
+ (void)cryp;
+ (void)hmacsha512ctxp;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash update using HMAC.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] hmacsha512ctxp pointer to a HMAC_SHA512 context
+ * @param[in] size size of input buffer
+ * @param[in] in buffer containing the input text
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_HMACSHA512_update(CRYDriver *cryp,
+ HMACSHA512Context *hmacsha512ctxp,
+ size_t size,
+ const uint8_t *in) {
+
+ (void)cryp;
+ (void)hmacsha512ctxp;
+ (void)size;
+ (void)in;
+
+ return CRY_ERR_INV_ALGO;
+}
+
+/**
+ * @brief Hash finalization using HMAC.
+ *
+ * @param[in] cryp pointer to the @p CRYDriver object
+ * @param[in] hmacsha512ctxp pointer to a HMAC_SHA512 context
+ * @param[out] out 512 bits output buffer
+ * @return The operation status.
+ * @retval CRY_NOERROR if the operation succeeded.
+ * @retval CRY_ERR_INV_ALGO if the operation is unsupported on this
+ * device instance.
+ * @retval CRY_ERR_OP_FAILURE if the operation failed, implementation
+ * dependent.
+ *
+ * @notapi
+ */
+cryerror_t cry_lld_HMACSHA512_final(CRYDriver *cryp,
+ HMACSHA512Context *hmacsha512ctxp,
+ uint8_t *out) {
+
+ (void)cryp;
+ (void)hmacsha512ctxp;
+ (void)out;
+
+ return CRY_ERR_INV_ALGO;
+}
+#endif
+
+#endif /* HAL_USE_CRY == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_crypto_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_crypto_lld.h
new file mode 100644
index 0000000..4edde5f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_crypto_lld.h
@@ -0,0 +1,376 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_crypto_lld.h
+ * @brief PLATFORM cryptographic subsystem low level driver header.
+ *
+ * @addtogroup CRYPTO
+ * @{
+ */
+
+#ifndef HAL_CRYPTO_LLD_H
+#define HAL_CRYPTO_LLD_H
+
+#if (HAL_USE_CRY == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Driver capability switches
+ * @{
+ */
+#define CRY_LLD_SUPPORTS_AES TRUE
+#define CRY_LLD_SUPPORTS_AES_ECB TRUE
+#define CRY_LLD_SUPPORTS_AES_CBC TRUE
+#define CRY_LLD_SUPPORTS_AES_CFB TRUE
+#define CRY_LLD_SUPPORTS_AES_CTR TRUE
+#define CRY_LLD_SUPPORTS_AES_GCM TRUE
+#define CRY_LLD_SUPPORTS_DES TRUE
+#define CRY_LLD_SUPPORTS_DES_ECB TRUE
+#define CRY_LLD_SUPPORTS_DES_CBC TRUE
+#define CRY_LLD_SUPPORTS_SHA1 TRUE
+#define CRY_LLD_SUPPORTS_SHA256 TRUE
+#define CRY_LLD_SUPPORTS_SHA512 TRUE
+#define CRY_LLD_SUPPORTS_HMAC_SHA256 TRUE
+#define CRY_LLD_SUPPORTS_HMAC_SHA512 TRUE
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief CRY1 driver enable switch.
+ * @details If set to @p TRUE the support for CRY1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_CRY_USE_CRY1) || defined(__DOXYGEN__)
+#define PLATFORM_CRY_USE_CRY1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief CRY key identifier type.
+ */
+typedef uint32_t crykey_t;
+
+/**
+ * @brief Type of a structure representing an CRY driver.
+ */
+typedef struct CRYDriver CRYDriver;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+ uint32_t dummy;
+} CRYConfig;
+
+/**
+ * @brief Structure representing an CRY driver.
+ */
+struct CRYDriver {
+ /**
+ * @brief Driver state.
+ */
+ crystate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const CRYConfig *config;
+#if defined(CRY_DRIVER_EXT_FIELDS)
+ CRY_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+};
+
+#if (CRY_LLD_SUPPORTS_SHA1 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a SHA1 context.
+ */
+typedef struct {
+ uint32_t dummy;
+} SHA1Context;
+#endif
+
+#if (CRY_LLD_SUPPORTS_SHA256 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a SHA256 context.
+ */
+typedef struct {
+ uint32_t dummy;
+} SHA256Context;
+#endif
+
+#if (CRY_LLD_SUPPORTS_SHA512 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a SHA512 context.
+ */
+typedef struct {
+ uint32_t dummy;
+} SHA512Context;
+#endif
+
+#if (CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a HMAC_SHA256 context.
+ */
+typedef struct {
+ uint32_t dummy;
+} HMACSHA256Context;
+#endif
+
+#if (CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a HMAC_SHA512 context.
+ */
+typedef struct {
+ uint32_t dummy;
+} HMACSHA512Context;
+#endif
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_CRY_USE_CRY1 == TRUE) && !defined(__DOXYGEN__)
+extern CRYDriver CRYD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void cry_lld_init(void);
+ void cry_lld_start(CRYDriver *cryp);
+ void cry_lld_stop(CRYDriver *cryp);
+#if (CRY_LLD_SUPPORTS_AES == TRUE) || \
+ (CRY_LLD_SUPPORTS_AES_ECB == TRUE) || \
+ (CRY_LLD_SUPPORTS_AES_CBC == TRUE) || \
+ (CRY_LLD_SUPPORTS_AES_CFB == TRUE) || \
+ (CRY_LLD_SUPPORTS_AES_CTR == TRUE) || \
+ (CRY_LLD_SUPPORTS_AES_GCM == TRUE) || \
+ defined(__DOXYGEN__)
+ cryerror_t cry_lld_aes_loadkey(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *keyp);
+#endif
+#if (CRY_LLD_SUPPORTS_AES == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_encrypt_AES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cry_lld_decrypt_AES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out);
+#endif
+#if (CRY_LLD_SUPPORTS_AES_ECB == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_encrypt_AES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cry_lld_decrypt_AES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out);
+#endif
+#if (CRY_LLD_SUPPORTS_AES_CBC == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_encrypt_AES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cry_lld_decrypt_AES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+#endif
+#if (CRY_LLD_SUPPORTS_AES_CFB == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_encrypt_AES_CFB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cry_lld_decrypt_AES_CFB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+#endif
+#if (CRY_LLD_SUPPORTS_AES_CTR == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_encrypt_AES_CTR(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cry_lld_decrypt_AES_CTR(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+#endif
+#if (CRY_LLD_SUPPORTS_AES_GCM == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_encrypt_AES_GCM(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t auth_size,
+ const uint8_t *auth_in,
+ size_t text_size,
+ const uint8_t *text_in,
+ uint8_t *text_out,
+ const uint8_t *iv,
+ size_t tag_size,
+ uint8_t *tag_out);
+ cryerror_t cry_lld_decrypt_AES_GCM(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t auth_size,
+ const uint8_t *auth_in,
+ size_t text_size,
+ const uint8_t *text_in,
+ uint8_t *text_out,
+ const uint8_t *iv,
+ size_t tag_size,
+ const uint8_t *tag_in);
+#endif
+#if (CRY_LLD_SUPPORTS_DES == TRUE) || \
+ (CRY_LLD_SUPPORTS_DES_ECB == TRUE) || \
+ (CRY_LLD_SUPPORTS_DES_CBC == TRUE) || \
+ defined(__DOXYGEN__)
+ cryerror_t cry_lld_des_loadkey(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *keyp);
+#endif
+#if (CRY_LLD_SUPPORTS_DES == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_encrypt_DES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cry_lld_decrypt_DES(CRYDriver *cryp,
+ crykey_t key_id,
+ const uint8_t *in,
+ uint8_t *out);
+#endif
+#if (CRY_LLD_SUPPORTS_DES_ECB == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_encrypt_DES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out);
+ cryerror_t cry_lld_decrypt_DES_ECB(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out);
+#endif
+#if (CRY_LLD_SUPPORTS_DES_CBC == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_encrypt_DES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+ cryerror_t cry_lld_decrypt_DES_CBC(CRYDriver *cryp,
+ crykey_t key_id,
+ size_t size,
+ const uint8_t *in,
+ uint8_t *out,
+ const uint8_t *iv);
+#endif
+#if (CRY_LLD_SUPPORTS_SHA1 == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_SHA1_init(CRYDriver *cryp, SHA1Context *sha1ctxp);
+ cryerror_t cry_lld_SHA1_update(CRYDriver *cryp, SHA1Context *sha1ctxp,
+ size_t size, const uint8_t *in);
+ cryerror_t cry_lld_SHA1_final(CRYDriver *cryp, SHA1Context *sha1ctxp,
+ uint8_t *out);
+#endif
+#if (CRY_LLD_SUPPORTS_SHA256 == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_SHA256_init(CRYDriver *cryp, SHA256Context *sha256ctxp);
+ cryerror_t cry_lld_SHA256_update(CRYDriver *cryp, SHA256Context *sha256ctxp,
+ size_t size, const uint8_t *in);
+ cryerror_t cry_lld_SHA256_final(CRYDriver *cryp, SHA256Context *sha256ctxp,
+ uint8_t *out);
+#endif
+#if (CRY_LLD_SUPPORTS_SHA512 == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_SHA512_init(CRYDriver *cryp, SHA512Context *sha512ctxp);
+ cryerror_t cry_lld_SHA512_update(CRYDriver *cryp, SHA512Context *sha512ctxp,
+ size_t size, const uint8_t *in);
+ cryerror_t cry_lld_SHA512_final(CRYDriver *cryp, SHA512Context *sha512ctxp,
+ uint8_t *out);
+#endif
+#if (CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE) || \
+ (CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE) || \
+ defined(__DOXYGEN__)
+ cryerror_t cry_lld_hmac_loadkey(CRYDriver *cryp,
+ size_t size,
+ const uint8_t *keyp);
+#endif
+#if (CRY_LLD_SUPPORTS_HMAC_SHA256 == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_HMACSHA256_init(CRYDriver *cryp,
+ HMACSHA256Context *hmacsha256ctxp);
+ cryerror_t cry_lld_HMACSHA256_update(CRYDriver *cryp,
+ HMACSHA256Context *hmacsha256ctxp,
+ size_t size, const uint8_t *in);
+ cryerror_t cry_lld_HMACSHA256_final(CRYDriver *cryp,
+ HMACSHA256Context *hmacsha256ctxp,
+ uint8_t *out);
+#endif
+#if (CRY_LLD_SUPPORTS_HMAC_SHA512 == TRUE) || defined(__DOXYGEN__)
+ cryerror_t cry_lld_HMACSHA512_init(CRYDriver *cryp,
+ HMACSHA512Context *hmacsha512ctxp);
+ cryerror_t cry_lld_HMACSHA512_update(CRYDriver *cryp,
+ HMACSHA512Context *hmacsha512ctxp,
+ size_t size, const uint8_t *in);
+ cryerror_t cry_lld_HMACSHA512_final(CRYDriver *cryp,
+ HMACSHA512Context *hmacsha512ctxp,
+ uint8_t *out);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_CRY == TRUE */
+
+#endif /* HAL_CRYPTO_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_dac_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_dac_lld.c
new file mode 100644
index 0000000..bb52656
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_dac_lld.c
@@ -0,0 +1,167 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_dac_lld.c
+ * @brief PLATFORM DAC subsystem low level driver source.
+ *
+ * @addtogroup DAC
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_DAC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief DAC1 driver identifier.*/
+#if (PLATFORM_DAC_USE_DAC1 == TRUE) || defined(__DOXYGEN__)
+DACDriver DACD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level DAC driver initialization.
+ *
+ * @notapi
+ */
+void dac_lld_init(void) {
+
+#if PLATFORM_DAC_USE_DAC1 == TRUE
+ dacObjectInit(&DACD1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the DAC peripheral.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @notapi
+ */
+void dac_lld_start(DACDriver *dacp) {
+
+ /* If the driver is in DAC_STOP state then a full initialization is
+ required.*/
+ if (dacp->state == DAC_STOP) {
+ /* Enabling the clock source.*/
+#if PLATFORM_DAC_USE_DAC1 == TRUE
+ if (&DACD1 == dacp) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Deactivates the DAC peripheral.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @notapi
+ */
+void dac_lld_stop(DACDriver *dacp) {
+
+ /* If in ready state then disables the DAC clock.*/
+ if (dacp->state == DAC_READY) {
+
+#if PLATFORM_DAC_USE_DAC1 == TRUE
+ if (&DACD1 == dacp) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Outputs a value directly on a DAC channel.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ * @param[in] channel DAC channel number
+ * @param[in] sample value to be output
+ *
+ * @api
+ */
+void dac_lld_put_channel(DACDriver *dacp,
+ dacchannel_t channel,
+ dacsample_t sample) {
+
+ (void)dacp;
+ (void)channel;
+ (void)sample;
+}
+
+/**
+ * @brief Starts a DAC conversion.
+ * @details Starts an asynchronous conversion operation.
+ * @note In @p DAC_DHRM_8BIT_RIGHT mode the parameters passed to the
+ * callback are wrong because two samples are packed in a single
+ * dacsample_t element. This will not be corrected, do not rely
+ * on those parameters.
+ * @note In @p DAC_DHRM_8BIT_RIGHT_DUAL mode two samples are treated
+ * as a single 16 bits sample and packed into a single dacsample_t
+ * element. The num_channels must be set to one in the group
+ * conversion configuration structure.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @notapi
+ */
+void dac_lld_start_conversion(DACDriver *dacp) {
+
+ (void)dacp;
+}
+
+/**
+ * @brief Stops an ongoing conversion.
+ * @details This function stops the currently ongoing conversion and returns
+ * the driver in the @p DAC_READY state. If there was no conversion
+ * being processed then the function does nothing.
+ *
+ * @param[in] dacp pointer to the @p DACDriver object
+ *
+ * @iclass
+ */
+void dac_lld_stop_conversion(DACDriver *dacp) {
+
+ (void)dacp;
+}
+
+#endif /* HAL_USE_DAC == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_dac_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_dac_lld.h
new file mode 100644
index 0000000..9f994e5
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_dac_lld.h
@@ -0,0 +1,137 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_dac_lld.h
+ * @brief PLATFORM DAC subsystem low level driver header.
+ *
+ * @addtogroup DAC
+ * @{
+ */
+
+#ifndef HAL_DAC_LLD_H
+#define HAL_DAC_LLD_H
+
+#if (HAL_USE_DAC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Maximum number of DAC channels per unit.
+ */
+#define DAC_MAX_CHANNELS 2
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief DAC1 CH1 driver enable switch.
+ * @details If set to @p TRUE the support for DAC1 channel 1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_DAC_USE_DAC1) || defined(__DOXYGEN__)
+#define PLATFORM_DAC_USE_DAC1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a DAC channel index.
+ */
+typedef uint32_t dacchannel_t;
+
+/**
+ * @brief Type representing a DAC sample.
+ */
+typedef uint16_t dacsample_t;
+
+/**
+ * @brief Possible DAC failure causes.
+ * @note Error codes are architecture dependent and should not relied
+ * upon.
+ */
+typedef enum {
+ DAC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */
+ DAC_ERR_UNDERFLOW = 1 /**< DAC overflow condition. */
+} dacerror_t;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the DAC driver structure.
+ */
+#define dac_lld_driver_fields \
+ /* Dummy field, it is not needed.*/ \
+ uint32_t dummy
+
+/**
+ * @brief Low level fields of the DAC configuration structure.
+ */
+#define dac_lld_config_fields \
+ /* Dummy configuration, it is not needed.*/ \
+ uint32_t dummy
+
+/**
+ * @brief Low level fields of the DAC group configuration structure.
+ */
+#define dac_lld_conversion_group_fields \
+ /* Dummy configuration, it is not needed.*/ \
+ uint32_t dummy
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_DAC_USE_DAC1 == TRUE) && !defined(__DOXYGEN__)
+extern DACDriver DACD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void dac_lld_init(void);
+ void dac_lld_start(DACDriver *dacp);
+ void dac_lld_stop(DACDriver *dacp);
+ void dac_lld_put_channel(DACDriver *dacp,
+ dacchannel_t channel,
+ dacsample_t sample);
+ void dac_lld_start_conversion(DACDriver *dacp);
+ void dac_lld_stop_conversion(DACDriver *dacp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_DAC == TRUE */
+
+#endif /* HAL_DAC_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_efl_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_efl_lld.c
new file mode 100644
index 0000000..a6e73f4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_efl_lld.c
@@ -0,0 +1,365 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_efl_lld.c
+ * @brief PLATFORM Embedded Flash subsystem low level driver source.
+ *
+ * @addtogroup HAL_EFL
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief EFL1 driver identifier.
+ */
+#if (PLATFORM_EFL_USE_EFL1 == TRUE) || defined(__DOXYGEN__)
+EFlashDriver EFLD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+static const flash_descriptor_t efl_lld_descriptor = {
+ .attributes = FLASH_ATTR_ERASED_IS_ONE |
+ FLASH_ATTR_MEMORY_MAPPED |
+ FLASH_ATTR_ECC_CAPABLE |
+ FLASH_ATTR_ECC_ZERO_LINE_CAPABLE,
+ .page_size = 0,
+ .sectors_count = 0,
+ .sectors = NULL,
+ .sectors_size = 0,
+ .address = (uint8_t *)0,
+ .size = 0
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level Embedded Flash driver initialization.
+ *
+ * @notapi
+ */
+void efl_lld_init(void) {
+
+#if PLATFORM_EFL_USE_EFL1 == TRUE
+ /* Driver initialization.*/
+ eflObjectInit(&EFLD1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the Embedded Flash peripheral.
+ *
+ * @param[in] eflp pointer to a @p EFlashDriver structure
+ *
+ * @notapi
+ */
+void efl_lld_start(EFlashDriver *eflp) {
+
+ if (eflp->state == FLASH_STOP) {
+ /* Enables the peripheral.*/
+#if PLATFORM_EFL_USE_EFL1 == TRUE
+ if (&EFLD1 == eflp) {
+
+ }
+#endif
+ }
+ /* Configures the peripheral.*/
+
+}
+
+/**
+ * @brief Deactivates the Embedded Flash peripheral.
+ *
+ * @param[in] eflp pointer to a @p EFlashDriver structure
+ *
+ * @notapi
+ */
+void efl_lld_stop(EFlashDriver *eflp) {
+
+ if (eflp->state == FLASH_READY) {
+ /* Resets the peripheral.*/
+
+ /* Disables the peripheral.*/
+#if PLATFORM_EFL_USE_EFL1 == TRUE
+ if (&EFLD1 == eflp) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Gets the flash descriptor structure.
+ *
+ * @param[in] instance pointer to a @p EFlashDriver instance
+ * @return A flash device descriptor.
+ *
+ * @notapi
+ */
+const flash_descriptor_t *efl_lld_get_descriptor(void *instance) {
+
+ (void)instance;
+
+ return &efl_lld_descriptor;
+}
+
+/**
+ * @brief Read operation.
+ *
+ * @param[in] instance pointer to a @p EFlashDriver instance
+ * @param[in] offset flash offset
+ * @param[in] n number of bytes to be read
+ * @param[out] rp pointer to the data buffer
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_READ if the read operation failed.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @notapi
+ */
+flash_error_t efl_lld_read(void *instance, flash_offset_t offset,
+ size_t n, uint8_t *rp) {
+ EFlashDriver *devp = (EFlashDriver *)instance;
+ flash_error_t err = FLASH_NO_ERROR;
+
+ osalDbgCheck((instance != NULL) && (rp != NULL) && (n > 0U));
+ osalDbgCheck(((size_t)offset + n) <= (size_t)efl_lld_descriptor.size);
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ /* No reading while erasing.*/
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* FLASH_READY state while the operation is performed.*/
+ devp->state = FLASH_READ;
+
+ /* IMPLEMENT */
+
+ /* Ready state again.*/
+ devp->state = FLASH_READY;
+
+ return err;
+
+}
+
+/**
+ * @brief Program operation.
+ * @note The device supports ECC, it is only possible to write erased
+ * pages once except when writing all zeroes.
+ *
+ * @param[in] instance pointer to a @p EFlashDriver instance
+ * @param[in] offset flash offset
+ * @param[in] n number of bytes to be programmed
+ * @param[in] pp pointer to the data buffer
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_PROGRAM if the program operation failed.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @notapi
+ */
+flash_error_t efl_lld_program(void *instance, flash_offset_t offset,
+ size_t n, const uint8_t *pp) {
+ EFlashDriver *devp = (EFlashDriver *)instance;
+ flash_error_t err = FLASH_NO_ERROR;
+
+ osalDbgCheck((instance != NULL) && (pp != NULL) && (n > 0U));
+ osalDbgCheck(((size_t)offset + n) <= (size_t)efl_lld_descriptor.size);
+
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ /* No programming while erasing.*/
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* FLASH_PGM state while the operation is performed.*/
+ devp->state = FLASH_PGM;
+
+ /* IMPLEMENT */
+
+ /* Ready state again.*/
+ devp->state = FLASH_READY;
+
+ return err;
+}
+
+/**
+ * @brief Starts a whole-device erase operation.
+ * @note This function only erases bank 2 if it is present. Bank 1 is not
+ * touched because it is where the program is running on.
+ * Pages on bank 1 can be individually erased.
+ *
+ * @param[in] instance pointer to a @p EFlashDriver instance
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @notapi
+ */
+flash_error_t efl_lld_start_erase_all(void *instance) {
+ EFlashDriver *devp = (EFlashDriver *)instance;
+
+ osalDbgCheck(instance != NULL);
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ /* No erasing while erasing.*/
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* FLASH_PGM state while the operation is performed.*/
+ devp->state = FLASH_ERASE;
+
+ /* IMPLEMENT */
+
+ return FLASH_NO_ERROR;
+}
+
+/**
+ * @brief Starts an sector erase operation.
+ *
+ * @param[in] instance pointer to a @p EFlashDriver instance
+ * @param[in] sector sector to be erased
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @notapi
+ */
+flash_error_t efl_lld_start_erase_sector(void *instance,
+ flash_sector_t sector) {
+ EFlashDriver *devp = (EFlashDriver *)instance;
+
+ osalDbgCheck(instance != NULL);
+ osalDbgCheck(sector < efl_lld_descriptor.sectors_count);
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ /* No erasing while erasing.*/
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* FLASH_PGM state while the operation is performed.*/
+ devp->state = FLASH_ERASE;
+
+ /* IMPLEMENT */
+
+ return FLASH_NO_ERROR;
+}
+
+/**
+ * @brief Queries the driver for erase operation progress.
+ *
+ * @param[in] instance pointer to a @p EFlashDriver instance
+ * @param[out] msec recommended time, in milliseconds, that
+ * should be spent before calling this
+ * function again, can be @p NULL
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if there is no erase operation in progress.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_ERASE if the erase operation failed.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @api
+ */
+flash_error_t efl_lld_query_erase(void *instance, uint32_t *msec) {
+ EFlashDriver *devp = (EFlashDriver *)instance;
+ flash_error_t err = FLASH_NO_ERROR;
+
+ (void)msec;
+
+ /* If there is an erase in progress then the device must be checked.*/
+ if (devp->state == FLASH_ERASE) {
+
+ /* IMPLEMENT */
+
+ }
+
+ return err;
+}
+
+/**
+ * @brief Returns the erase state of a sector.
+ *
+ * @param[in] instance pointer to a @p EFlashDriver instance
+ * @param[in] sector sector to be verified
+ * @return An error code.
+ * @retval FLASH_NO_ERROR if the sector is erased.
+ * @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
+ * @retval FLASH_ERROR_VERIFY if the verify operation failed.
+ * @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
+ *
+ * @notapi
+ */
+flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector) {
+ EFlashDriver *devp = (EFlashDriver *)instance;
+ flash_error_t err = FLASH_NO_ERROR;
+
+ osalDbgCheck(instance != NULL);
+ osalDbgCheck(sector < efl_lld_descriptor.sectors_count);
+ osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
+ "invalid state");
+
+ /* No verifying while erasing.*/
+ if (devp->state == FLASH_ERASE) {
+ return FLASH_BUSY_ERASING;
+ }
+
+ /* IMPLEMENT */
+
+ /* Ready state again.*/
+ devp->state = FLASH_READY;
+
+ return err;
+}
+
+#endif /* HAL_USE_EFL == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_efl_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_efl_lld.h
new file mode 100644
index 0000000..a65ee3b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_efl_lld.h
@@ -0,0 +1,110 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_efl_lld.h
+ * @brief PLATFORM Embedded Flash subsystem low level driver header.
+ *
+ * @addtogroup HAL_EFL
+ * @{
+ */
+
+#ifndef HAL_EFL_LLD_H
+#define HAL_EFL_LLD_H
+
+#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief EFL1 driver enable switch.
+ * @details If set to @p TRUE the support for EFL1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_EFL_USE_EFL1) || defined(__DOXYGEN__)
+#define PLATFORM_EFL_USE_EFL1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the embedded flash driver structure.
+ */
+#define efl_lld_driver_fields \
+ /* Dummy field, it is not needed.*/ \
+ uint32_t dummy
+
+/**
+ * @brief Low level fields of the embedded flash configuration structure.
+ */
+#define efl_lld_config_fields \
+ /* Dummy configuration, it is not needed.*/ \
+ uint32_t dummy
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_EFL_USE_EFL1 == TRUE) && !defined(__DOXYGEN__)
+extern EFlashDriver EFLD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void efl_lld_init(void);
+ void efl_lld_start(EFlashDriver *eflp);
+ void efl_lld_stop(EFlashDriver *eflp);
+ const flash_descriptor_t *efl_lld_get_descriptor(void *instance);
+ flash_error_t efl_lld_read(void *instance, flash_offset_t offset,
+ size_t n, uint8_t *rp);
+ flash_error_t efl_lld_program(void *instance, flash_offset_t offset,
+ size_t n, const uint8_t *pp);
+ flash_error_t efl_lld_start_erase_all(void *instance);
+ flash_error_t efl_lld_start_erase_sector(void *instance,
+ flash_sector_t sector);
+ flash_error_t efl_lld_query_erase(void *instance, uint32_t *msec);
+ flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_EFL == TRUE */
+
+#endif /* HAL_EFL_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_gpt_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_gpt_lld.c
new file mode 100644
index 0000000..e22edbd
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_gpt_lld.c
@@ -0,0 +1,163 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_gpt_lld.c
+ * @brief PLATFORM GPT subsystem low level driver source.
+ *
+ * @addtogroup GPT
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_GPT == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief GPTD1 driver identifier.
+ */
+#if (PLATFORM_GPT_USE_GPT1 == TRUE) || defined(__DOXYGEN__)
+GPTDriver GPTD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level GPT driver initialization.
+ *
+ * @notapi
+ */
+void gpt_lld_init(void) {
+
+#if PLATFORM_GPT_USE_GPT1 == TRUE
+ /* Driver initialization.*/
+ gptObjectInit(&GPTD1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the GPT peripheral.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ *
+ * @notapi
+ */
+void gpt_lld_start(GPTDriver *gptp) {
+
+ if (gptp->state == GPT_STOP) {
+ /* Enables the peripheral.*/
+#if PLATFORM_GPT_USE_GPT1 == TRUE
+ if (&GPTD1 == gptp) {
+
+ }
+#endif
+ }
+ /* Configures the peripheral.*/
+
+}
+
+/**
+ * @brief Deactivates the GPT peripheral.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ *
+ * @notapi
+ */
+void gpt_lld_stop(GPTDriver *gptp) {
+
+ if (gptp->state == GPT_READY) {
+ /* Resets the peripheral.*/
+
+ /* Disables the peripheral.*/
+#if PLATFORM_GPT_USE_GPT1 == TRUE
+ if (&GPTD1 == gptp) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Starts the timer in continuous mode.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ * @param[in] interval period in ticks
+ *
+ * @notapi
+ */
+void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval) {
+
+ (void)gptp;
+ (void)interval;
+
+}
+
+/**
+ * @brief Stops the timer.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ *
+ * @notapi
+ */
+void gpt_lld_stop_timer(GPTDriver *gptp) {
+
+ (void)gptp;
+
+}
+
+/**
+ * @brief Starts the timer in one shot mode and waits for completion.
+ * @details This function specifically polls the timer waiting for completion
+ * in order to not have extra delays caused by interrupt servicing,
+ * this function is only recommended for short delays.
+ *
+ * @param[in] gptp pointer to the @p GPTDriver object
+ * @param[in] interval time interval in ticks
+ *
+ * @notapi
+ */
+void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval) {
+
+ (void)gptp;
+ (void)interval;
+
+}
+
+#endif /* HAL_USE_GPT == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_gpt_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_gpt_lld.h
new file mode 100644
index 0000000..10cd5c0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_gpt_lld.h
@@ -0,0 +1,154 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_gpt_lld.h
+ * @brief PLATFORM GPT subsystem low level driver header.
+ *
+ * @addtogroup GPT
+ * @{
+ */
+
+#ifndef HAL_GPT_LLD_H
+#define HAL_GPT_LLD_H
+
+#if (HAL_USE_GPT == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief GPTD1 driver enable switch.
+ * @details If set to @p TRUE the support for GPTD1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_GPT_USE_GPT1) || defined(__DOXYGEN__)
+#define PLATFORM_GPT_USE_GPT1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief GPT frequency type.
+ */
+typedef uint32_t gptfreq_t;
+
+/**
+ * @brief GPT counter type.
+ */
+typedef uint16_t gptcnt_t;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+ /**
+ * @brief Timer clock in Hz.
+ * @note The low level can use assertions in order to catch invalid
+ * frequency specifications.
+ */
+ gptfreq_t frequency;
+ /**
+ * @brief Timer callback pointer.
+ * @note This callback is invoked on GPT counter events.
+ */
+ gptcallback_t callback;
+ /* End of the mandatory fields.*/
+} GPTConfig;
+
+/**
+ * @brief Structure representing a GPT driver.
+ */
+struct GPTDriver {
+ /**
+ * @brief Driver state.
+ */
+ gptstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const GPTConfig *config;
+#if defined(GPT_DRIVER_EXT_FIELDS)
+ GPT_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Changes the interval of GPT peripheral.
+ * @details This function changes the interval of a running GPT unit.
+ * @pre The GPT unit must have been activated using @p gptStart().
+ * @pre The GPT unit must have been running in continuous mode using
+ * @p gptStartContinuous().
+ * @post The GPT unit interval is changed to the new value.
+ * @note The function has effect at the next cycle start.
+ *
+ * @param[in] gptp pointer to a @p GPTDriver object
+ * @param[in] interval new cycle time in timer ticks
+ * @notapi
+ */
+#define gpt_lld_change_interval(gptp, interval) { \
+ (void)gptp; \
+ (void)interval; \
+}
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_GPT_USE_GPT1 == TRUE) && !defined(__DOXYGEN__)
+extern GPTDriver GPTD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void gpt_lld_init(void);
+ void gpt_lld_start(GPTDriver *gptp);
+ void gpt_lld_stop(GPTDriver *gptp);
+ void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval);
+ void gpt_lld_stop_timer(GPTDriver *gptp);
+ void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_GPT == TRUE */
+
+#endif /* HAL_GPT_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_i2c_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_i2c_lld.c
new file mode 100644
index 0000000..b7f2e99
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_i2c_lld.c
@@ -0,0 +1,187 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_i2c_lld.c
+ * @brief PLATFORM I2C subsystem low level driver source.
+ *
+ * @addtogroup I2C
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief I2C1 driver identifier.
+ */
+#if (PLATFORM_I2C_USE_I2C1 == TRUE) || defined(__DOXYGEN__)
+I2CDriver I2CD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level I2C driver initialization.
+ *
+ * @notapi
+ */
+void i2c_lld_init(void) {
+
+#if PLATFORM_I2C_USE_I2C1 == TRUE
+ i2cObjectInit(&I2CD1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the I2C peripheral.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+void i2c_lld_start(I2CDriver *i2cp) {
+
+ if (i2cp->state == I2C_STOP) {
+ /* Enables the peripheral.*/
+#if PLATFORM_I2C_USE_I2C1 == TRUE
+ if (&I2CD1 == i2cp) {
+
+ }
+#endif
+ }
+
+}
+
+/**
+ * @brief Deactivates the I2C peripheral.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+void i2c_lld_stop(I2CDriver *i2cp) {
+
+ if (i2cp->state != I2C_STOP) {
+
+ /* Disables the peripheral.*/
+#if PLATFORM_I2C_USE_I2C1 == TRUE
+ if (&I2CD1 == i2cp) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Receives data via the I2C bus as master.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] addr slave device address
+ * @param[out] rxbuf pointer to the receive buffer
+ * @param[in] rxbytes number of bytes to be received
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a
+ * timeout the driver must be stopped and restarted
+ * because the bus is in an uncertain state.
+ *
+ * @notapi
+ */
+msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout) {
+
+ (void)i2cp;
+ (void)addr;
+ (void)rxbuf;
+ (void)rxbytes;
+ (void)timeout;
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Transmits data via the I2C bus as master.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] addr slave device address
+ * @param[in] txbuf pointer to the transmit buffer
+ * @param[in] txbytes number of bytes to be transmitted
+ * @param[out] rxbuf pointer to the receive buffer
+ * @param[in] rxbytes number of bytes to be received
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if the function succeeded.
+ * @retval MSG_RESET if one or more I2C errors occurred, the errors can
+ * be retrieved using @p i2cGetErrors().
+ * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a
+ * timeout the driver must be stopped and restarted
+ * because the bus is in an uncertain state.
+ *
+ * @notapi
+ */
+msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ const uint8_t *txbuf, size_t txbytes,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout) {
+
+ (void)i2cp;
+ (void)addr;
+ (void)txbuf;
+ (void)txbytes;
+ (void)rxbuf;
+ (void)rxbytes;
+ (void)timeout;
+
+ return MSG_OK;
+}
+
+#endif /* HAL_USE_I2C == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_i2c_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_i2c_lld.h
new file mode 100644
index 0000000..a114806
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_i2c_lld.h
@@ -0,0 +1,152 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_i2c_lld.h
+ * @brief PLATFORM I2C subsystem low level driver header.
+ *
+ * @addtogroup I2C
+ * @{
+ */
+
+#ifndef HAL_I2C_LLD_H
+#define HAL_I2C_LLD_H
+
+#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief I2C1 driver enable switch.
+ * @details If set to @p TRUE the support for I2C1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_I2C_USE_I2C1) || defined(__DOXYGEN__)
+#define PLATFORM_I2C_USE_I2C1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type representing an I2C address.
+ */
+typedef uint16_t i2caddr_t;
+
+/**
+ * @brief Type of I2C Driver condition flags.
+ */
+typedef uint32_t i2cflags_t;
+
+/**
+ * @brief Type of I2C driver configuration structure.
+ * @note Implementations may extend this structure to contain more,
+ * architecture dependent, fields.
+ */
+typedef struct {
+ /* End of the mandatory fields.*/
+ uint32_t dummy;
+} I2CConfig;
+
+/**
+ * @brief Type of a structure representing an I2C driver.
+ */
+typedef struct I2CDriver I2CDriver;
+
+/**
+ * @brief Structure representing an I2C driver.
+ */
+struct I2CDriver {
+ /**
+ * @brief Driver state.
+ */
+ i2cstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const I2CConfig *config;
+ /**
+ * @brief Error flags.
+ */
+ i2cflags_t errors;
+#if (I2C_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
+ mutex_t mutex;
+#endif
+#if defined(I2C_DRIVER_EXT_FIELDS)
+ I2C_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Get errors from I2C driver.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ *
+ * @notapi
+ */
+#define i2c_lld_get_errors(i2cp) ((i2cp)->errors)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_I2C_USE_I2C1 == TRUE) && !defined(__DOXYGEN__)
+extern I2CDriver I2CD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void i2c_lld_init(void);
+ void i2c_lld_start(I2CDriver *i2cp);
+ void i2c_lld_stop(I2CDriver *i2cp);
+ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ const uint8_t *txbuf, size_t txbytes,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout);
+ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
+ uint8_t *rxbuf, size_t rxbytes,
+ sysinterval_t timeout);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_I2C == TRUE */
+
+#endif /* HAL_I2C_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_i2s_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_i2s_lld.c
new file mode 100644
index 0000000..2b6bff4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_i2s_lld.c
@@ -0,0 +1,137 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_i2s_lld.c
+ * @brief PLATFORM I2S subsystem low level driver source.
+ *
+ * @addtogroup I2S
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_I2S == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief I2S2 driver identifier.*/
+#if (PLATFORM_I2S_USE_I2S1 == TRUE) || defined(__DOXYGEN__)
+I2SDriver I2SD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level I2S driver initialization.
+ *
+ * @notapi
+ */
+void i2s_lld_init(void) {
+
+#if PLATFORM_I2S_USE_I2S1
+ i2sObjectInit(&I2SD1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the I2S peripheral.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @notapi
+ */
+void i2s_lld_start(I2SDriver *i2sp) {
+
+ /* If in stopped state then enables the SPI and DMA clocks.*/
+ if (i2sp->state == I2S_STOP) {
+
+#if PLATFORM_I2S_USE_I2S1
+ if (&I2SD1 == i2sp) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Deactivates the I2S peripheral.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @notapi
+ */
+void i2s_lld_stop(I2SDriver *i2sp) {
+
+ /* If in ready state then disables the SPI clock.*/
+ if (i2sp->state == I2S_READY) {
+#if PLATFORM_I2S_USE_I2S1
+ if (&I2SD1 == i2sp) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Starts a I2S data exchange.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @notapi
+ */
+void i2s_lld_start_exchange(I2SDriver *i2sp) {
+
+ (void)i2sp;
+}
+
+/**
+ * @brief Stops the ongoing data exchange.
+ * @details The ongoing data exchange, if any, is stopped, if the driver
+ * was not active the function does nothing.
+ *
+ * @param[in] i2sp pointer to the @p I2SDriver object
+ *
+ * @notapi
+ */
+void i2s_lld_stop_exchange(I2SDriver *i2sp) {
+
+ (void)i2sp;
+}
+
+#endif /* HAL_USE_I2S */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_i2s_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_i2s_lld.h
new file mode 100644
index 0000000..2bd1a62
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_i2s_lld.h
@@ -0,0 +1,102 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_i2s_lld.h
+ * @brief PLATFORM I2S subsystem low level driver header.
+ *
+ * @addtogroup I2S
+ * @{
+ */
+
+#ifndef HAL_I2S_LLD_H
+#define HAL_I2S_LLD_H
+
+#if (HAL_USE_I2S == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief I2SD1 driver enable switch.
+ * @details If set to @p TRUE the support for I2S1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_I2S_USE_I2S1) || defined(__DOXYGEN__)
+#define PLATFORM_I2S_USE_I2S1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the I2S driver structure.
+ */
+#define i2s_lld_driver_fields \
+ /* Dummy field, it is not needed.*/ \
+ uint32_t dummy
+
+/**
+ * @brief Low level fields of the I2S configuration structure.
+ */
+#define i2s_lld_config_fields \
+ /* Dummy configuration, it is not needed.*/ \
+ uint32_t dummy
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_I2S_USE_I2S1 == TRUE) && !defined(__DOXYGEN__)
+extern I2SDriver I2SD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void i2s_lld_init(void);
+ void i2s_lld_start(I2SDriver *i2sp);
+ void i2s_lld_stop(I2SDriver *i2sp);
+ void i2s_lld_start_exchange(I2SDriver *i2sp);
+ void i2s_lld_stop_exchange(I2SDriver *i2sp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_I2S == TRUE */
+
+#endif /* HAL_I2S_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_icu_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_icu_lld.c
new file mode 100644
index 0000000..4fd2d78
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_icu_lld.c
@@ -0,0 +1,187 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_icu_lld.c
+ * @brief PLATFORM ADC subsystem low level driver source.
+ *
+ * @addtogroup ICU
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_ICU == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief ICUD1 driver identifier.
+ * @note The driver ICUD1 allocates the complex timer TIM1 when enabled.
+ */
+#if (PLATFORM_ICU_USE_ICU1 == TRUE) || defined(__DOXYGEN__)
+ICUDriver ICUD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level ICU driver initialization.
+ *
+ * @notapi
+ */
+void icu_lld_init(void) {
+
+#if PLATFORM_ICU_USE_ICU1 == TRUE
+ /* Driver initialization.*/
+ icuObjectInit(&ICUD1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the ICU peripheral.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @notapi
+ */
+void icu_lld_start(ICUDriver *icup) {
+
+ if (icup->state == ICU_STOP) {
+ /* Clock activation and timer reset.*/
+#if PLATFORM_ICU_USE_ICU1 == TRUE
+ if (&ICUD1 == icup) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Deactivates the ICU peripheral.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @notapi
+ */
+void icu_lld_stop(ICUDriver *icup) {
+
+ if (icup->state == ICU_READY) {
+ /* Clock deactivation.*/
+#if PLATFORM_ICU_USE_ICU1 == TRUE
+ if (&ICUD1 == icup) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Starts the input capture.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @notapi
+ */
+void icu_lld_start_capture(ICUDriver *icup) {
+
+ (void)icup;
+}
+
+/**
+ * @brief Waits for a completed capture.
+ * @note The operation is performed in polled mode.
+ * @note In order to use this function notifications must be disabled.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @return The capture status.
+ * @retval false if the capture is successful.
+ * @retval true if a timer overflow occurred.
+ *
+ * @notapi
+ */
+bool icu_lld_wait_capture(ICUDriver *icup) {
+
+ (void)icup;
+
+ return false;
+}
+
+/**
+ * @brief Stops the input capture.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @notapi
+ */
+void icu_lld_stop_capture(ICUDriver *icup) {
+
+ (void)icup;
+}
+
+/**
+ * @brief Enables notifications.
+ * @pre The ICU unit must have been activated using @p icuStart() and the
+ * capture started using @p icuStartCapture().
+ * @note If the notification is already enabled then the call has no effect.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @api
+ */
+void icu_lld_enable_notifications(ICUDriver *icup) {
+
+ (void)icup;
+}
+
+/**
+ * @brief Disables notifications.
+ * @pre The ICU unit must have been activated using @p icuStart() and the
+ * capture started using @p icuStartCapture().
+ * @note If the notification is already disabled then the call has no effect.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ *
+ * @api
+ */
+void icu_lld_disable_notifications(ICUDriver *icup) {
+
+ (void)icup;
+}
+
+#endif /* HAL_USE_ICU == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_icu_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_icu_lld.h
new file mode 100644
index 0000000..6983e0f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_icu_lld.h
@@ -0,0 +1,193 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_icu_lld.h
+ * @brief PLATFORM ICU subsystem low level driver header.
+ *
+ * @addtogroup ICU
+ * @{
+ */
+
+#ifndef HAL_ICU_LLD_H
+#define HAL_ICU_LLD_H
+
+#if (HAL_USE_ICU == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief ICUD1 driver enable switch.
+ * @details If set to @p TRUE the support for ICUD1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_ICU_USE_ICU1) || defined(__DOXYGEN__)
+#define PLATFORM_ICU_USE_ICU1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief ICU driver mode.
+ */
+typedef enum {
+ ICU_INPUT_ACTIVE_HIGH = 0, /**< Trigger on rising edge. */
+ ICU_INPUT_ACTIVE_LOW = 1 /**< Trigger on falling edge. */
+} icumode_t;
+
+/**
+ * @brief ICU frequency type.
+ */
+typedef uint32_t icufreq_t;
+
+/**
+ * @brief ICU counter type.
+ */
+typedef uint32_t icucnt_t;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+ /**
+ * @brief Driver mode.
+ */
+ icumode_t mode;
+ /**
+ * @brief Timer clock in Hz.
+ * @note The low level can use assertions in order to catch invalid
+ * frequency specifications.
+ */
+ icufreq_t frequency;
+ /**
+ * @brief Callback for pulse width measurement.
+ */
+ icucallback_t width_cb;
+ /**
+ * @brief Callback for cycle period measurement.
+ */
+ icucallback_t period_cb;
+ /**
+ * @brief Callback for timer overflow.
+ */
+ icucallback_t overflow_cb;
+ /* End of the mandatory fields.*/
+} ICUConfig;
+
+/**
+ * @brief Structure representing an ICU driver.
+ */
+struct ICUDriver {
+ /**
+ * @brief Driver state.
+ */
+ icustate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const ICUConfig *config;
+#if defined(ICU_DRIVER_EXT_FIELDS)
+ ICU_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Returns the width of the latest pulse.
+ * @details The pulse width is defined as number of ticks between the start
+ * edge and the stop edge.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @return The number of ticks.
+ *
+ * @notapi
+ */
+#define icu_lld_get_width(icup) 0
+
+/**
+ * @brief Returns the width of the latest cycle.
+ * @details The cycle width is defined as number of ticks between a start
+ * edge and the next start edge.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @return The number of ticks.
+ *
+ * @notapi
+ */
+#define icu_lld_get_period(icup) 0
+
+/**
+ * @brief Check on notifications status.
+ *
+ * @param[in] icup pointer to the @p ICUDriver object
+ * @return The notifications status.
+ * @retval false if notifications are not enabled.
+ * @retval true if notifications are enabled.
+ *
+ * @notapi
+ */
+#define icu_lld_are_notifications_enabled(icup) false
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_ICU_USE_ICU1 == TRUE) && !defined(__DOXYGEN__)
+extern ICUDriver ICUD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void icu_lld_init(void);
+ void icu_lld_start(ICUDriver *icup);
+ void icu_lld_stop(ICUDriver *icup);
+ void icu_lld_start_capture(ICUDriver *icup);
+ bool icu_lld_wait_capture(ICUDriver *icup);
+ void icu_lld_stop_capture(ICUDriver *icup);
+ void icu_lld_enable_notifications(ICUDriver *icup);
+ void icu_lld_disable_notifications(ICUDriver *icup);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_ICU == TRUE */
+
+#endif /* HAL_ICU_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_lld.c
new file mode 100644
index 0000000..84a7680
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_lld.c
@@ -0,0 +1,60 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_lld.c
+ * @brief PLATFORM HAL subsystem low level driver source.
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#include "hal.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level HAL driver initialization.
+ *
+ * @notapi
+ */
+void hal_lld_init(void) {
+
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_lld.h
new file mode 100644
index 0000000..3dfe041
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_lld.h
@@ -0,0 +1,82 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_lld.h
+ * @brief PLATFORM HAL subsystem low level driver header.
+ *
+ * @addtogroup HAL
+ * @{
+ */
+
+#ifndef _HAL_LLD_H_
+#define _HAL_LLD_H_
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Platform identification macros
+ * @{
+ */
+#define PLATFORM_NAME "templates"
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*
+ * Configuration-related checks.
+ */
+#if !defined(PLATFORM_MCUCONF)
+#error "Using a wrong mcuconf.h file, PLATFORM_MCUCONF not defined"
+#endif
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void hal_lld_init(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HAL_LLD_H_ */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_mac_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_mac_lld.c
new file mode 100644
index 0000000..4fb16a4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_mac_lld.c
@@ -0,0 +1,313 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_mac_lld.c
+ * @brief PLATFORM MAC subsystem low level driver source.
+ *
+ * @addtogroup MAC
+ * @{
+ */
+
+#include
+
+#include "hal.h"
+
+#if (HAL_USE_MAC == TRUE) || defined(__DOXYGEN__)
+
+#include "hal_mii.h"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief MAC1 driver identifier.
+ */
+#if (PLATFORM_MAC_USE_MAC1 == TRUE) || defined(__DOXYGEN__)
+MACDriver ETHD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level MAC initialization.
+ *
+ * @notapi
+ */
+void mac_lld_init(void) {
+
+#if PLATFORM_MAC_USE_MAC1 == TRUE
+ /* Driver initialization.*/
+ macObjectInit(&MACD1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the MAC peripheral.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ *
+ * @notapi
+ */
+void mac_lld_start(MACDriver *macp) {
+
+ if (macp->state == MAC_STOP) {
+ /* Enables the peripheral.*/
+#if PLATFORM_MAC_USE_MAC1 == TRUE
+ if (&MACD1 == macp) {
+
+ }
+#endif
+ }
+ /* Configures the peripheral.*/
+
+}
+
+/**
+ * @brief Deactivates the MAC peripheral.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ *
+ * @notapi
+ */
+void mac_lld_stop(MACDriver *macp) {
+
+ if (macp->state != MAC_STOP) {
+ /* Resets the peripheral.*/
+
+ /* Disables the peripheral.*/
+#if PLATFORM_MAC_USE_MAC1 == TRUE
+ if (&MACD1 == macp) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Returns a transmission descriptor.
+ * @details One of the available transmission descriptors is locked and
+ * returned.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ * @param[out] tdp pointer to a @p MACTransmitDescriptor structure
+ * @return The operation status.
+ * @retval MSG_OK the descriptor has been obtained.
+ * @retval MSG_TIMEOUT descriptor not available.
+ *
+ * @notapi
+ */
+msg_t mac_lld_get_transmit_descriptor(MACDriver *macp,
+ MACTransmitDescriptor *tdp) {
+
+ (void)macp;
+ (void)tdp;
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Releases a transmit descriptor and starts the transmission of the
+ * enqueued data as a single frame.
+ *
+ * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure
+ *
+ * @notapi
+ */
+void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp) {
+
+ (void)tdp;
+
+}
+
+/**
+ * @brief Returns a receive descriptor.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ * @param[out] rdp pointer to a @p MACReceiveDescriptor structure
+ * @return The operation status.
+ * @retval MSG_OK the descriptor has been obtained.
+ * @retval MSG_TIMEOUT descriptor not available.
+ *
+ * @notapi
+ */
+msg_t mac_lld_get_receive_descriptor(MACDriver *macp,
+ MACReceiveDescriptor *rdp) {
+
+ (void)macp;
+ (void)rdp;
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Releases a receive descriptor.
+ * @details The descriptor and its buffer are made available for more incoming
+ * frames.
+ *
+ * @param[in] rdp the pointer to the @p MACReceiveDescriptor structure
+ *
+ * @notapi
+ */
+void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp) {
+
+ (void)rdp;
+
+}
+
+/**
+ * @brief Updates and returns the link status.
+ *
+ * @param[in] macp pointer to the @p MACDriver object
+ * @return The link status.
+ * @retval true if the link is active.
+ * @retval false if the link is down.
+ *
+ * @notapi
+ */
+bool mac_lld_poll_link_status(MACDriver *macp) {
+
+ (void)macp;
+
+ return false;
+}
+
+/**
+ * @brief Writes to a transmit descriptor's stream.
+ *
+ * @param[in] tdp pointer to a @p MACTransmitDescriptor structure
+ * @param[in] buf pointer to the buffer containing the data to be
+ * written
+ * @param[in] size number of bytes to be written
+ * @return The number of bytes written into the descriptor's
+ * stream, this value can be less than the amount
+ * specified in the parameter @p size if the maximum
+ * frame size is reached.
+ *
+ * @notapi
+ */
+size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp,
+ uint8_t *buf,
+ size_t size) {
+
+ (void)tdp;
+ (void)buf;
+
+ return size;
+}
+
+/**
+ * @brief Reads from a receive descriptor's stream.
+ *
+ * @param[in] rdp pointer to a @p MACReceiveDescriptor structure
+ * @param[in] buf pointer to the buffer that will receive the read data
+ * @param[in] size number of bytes to be read
+ * @return The number of bytes read from the descriptor's
+ * stream, this value can be less than the amount
+ * specified in the parameter @p size if there are
+ * no more bytes to read.
+ *
+ * @notapi
+ */
+size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp,
+ uint8_t *buf,
+ size_t size) {
+
+ (void)rdp;
+ (void)buf;
+
+ return size;
+}
+
+#if (MAC_USE_ZERO_COPY == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Returns a pointer to the next transmit buffer in the descriptor
+ * chain.
+ * @note The API guarantees that enough buffers can be requested to fill
+ * a whole frame.
+ *
+ * @param[in] tdp pointer to a @p MACTransmitDescriptor structure
+ * @param[in] size size of the requested buffer. Specify the frame size
+ * on the first call then scale the value down subtracting
+ * the amount of data already copied into the previous
+ * buffers.
+ * @param[out] sizep pointer to variable receiving the buffer size, it is
+ * zero when the last buffer has already been returned.
+ * Note that a returned size lower than the amount
+ * requested means that more buffers must be requested
+ * in order to fill the frame data entirely.
+ * @return Pointer to the returned buffer.
+ * @retval NULL if the buffer chain has been entirely scanned.
+ *
+ * @notapi
+ */
+uint8_t *mac_lld_get_next_transmit_buffer(MACTransmitDescriptor *tdp,
+ size_t size,
+ size_t *sizep) {
+
+ (void)tdp;
+ (void)size;
+ (void)sizep;
+
+ return NULL;
+}
+
+/**
+ * @brief Returns a pointer to the next receive buffer in the descriptor
+ * chain.
+ * @note The API guarantees that the descriptor chain contains a whole
+ * frame.
+ *
+ * @param[in] rdp pointer to a @p MACReceiveDescriptor structure
+ * @param[out] sizep pointer to variable receiving the buffer size, it is
+ * zero when the last buffer has already been returned.
+ * @return Pointer to the returned buffer.
+ * @retval NULL if the buffer chain has been entirely scanned.
+ *
+ * @notapi
+ */
+const uint8_t *mac_lld_get_next_receive_buffer(MACReceiveDescriptor *rdp,
+ size_t *sizep) {
+
+ (void)rdp;
+ (void)sizep;
+
+ return NULL;
+}
+#endif /* MAC_USE_ZERO_COPY == TRUE */
+
+#endif /* HAL_USE_MAC == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_mac_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_mac_lld.h
new file mode 100644
index 0000000..c9b930f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_mac_lld.h
@@ -0,0 +1,181 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_mac_lld.h
+ * @brief PLATFORM MAC subsystem low level driver header.
+ *
+ * @addtogroup MAC
+ * @{
+ */
+
+#ifndef HAL_MAC_LLD_H
+#define HAL_MAC_LLD_H
+
+#if (HAL_USE_MAC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief This implementation supports the zero-copy mode API.
+ */
+#define MAC_SUPPORTS_ZERO_COPY TRUE
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief MAC driver enable switch.
+ * @details If set to @p TRUE the support for MAC1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_MAC_USE_MAC1) || defined(__DOXYGEN__)
+#define PLATFORM_MAC_USE_MAC1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief MAC address.
+ */
+ uint8_t *mac_address;
+ /* End of the mandatory fields.*/
+} MACConfig;
+
+/**
+ * @brief Structure representing a MAC driver.
+ */
+struct MACDriver {
+ /**
+ * @brief Driver state.
+ */
+ macstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const MACConfig *config;
+ /**
+ * @brief Transmit semaphore.
+ */
+ threads_queue_t tdqueue;
+ /**
+ * @brief Receive semaphore.
+ */
+ threads_queue_t rdqueue;
+#if (MAC_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Receive event.
+ */
+ event_source_t rdevent;
+#endif
+ /* End of the mandatory fields.*/
+};
+
+/**
+ * @brief Structure representing a transmit descriptor.
+ */
+typedef struct {
+ /**
+ * @brief Current write offset.
+ */
+ size_t offset;
+ /**
+ * @brief Available space size.
+ */
+ size_t size;
+ /* End of the mandatory fields.*/
+} MACTransmitDescriptor;
+
+/**
+ * @brief Structure representing a receive descriptor.
+ */
+typedef struct {
+ /**
+ * @brief Current read offset.
+ */
+ size_t offset;
+ /**
+ * @brief Available data size.
+ */
+ size_t size;
+ /* End of the mandatory fields.*/
+} MACReceiveDescriptor;
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_MAC_USE_MAC1 == TRUE) && !defined(__DOXYGEN__)
+extern MACDriver ETHD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void mac_lld_init(void);
+ void mac_lld_start(MACDriver *macp);
+ void mac_lld_stop(MACDriver *macp);
+ msg_t mac_lld_get_transmit_descriptor(MACDriver *macp,
+ MACTransmitDescriptor *tdp);
+ void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp);
+ msg_t mac_lld_get_receive_descriptor(MACDriver *macp,
+ MACReceiveDescriptor *rdp);
+ void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp);
+ bool mac_lld_poll_link_status(MACDriver *macp);
+ size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp,
+ uint8_t *buf,
+ size_t size);
+ size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp,
+ uint8_t *buf,
+ size_t size);
+#if MAC_USE_ZERO_COPY == TRUE
+ uint8_t *mac_lld_get_next_transmit_buffer(MACTransmitDescriptor *tdp,
+ size_t size,
+ size_t *sizep);
+ const uint8_t *mac_lld_get_next_receive_buffer(MACReceiveDescriptor *rdp,
+ size_t *sizep);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_MAC == TRUE */
+
+#endif /* HAL_MAC_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_pal_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_pal_lld.c
new file mode 100644
index 0000000..6cf2194
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_pal_lld.c
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_pal_lld.c
+ * @brief PLATFORM PAL subsystem low level driver source.
+ *
+ * @addtogroup PAL
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief STM32 I/O ports configuration.
+ *
+ * @notapi
+ */
+void _pal_lld_init(void) {
+
+}
+
+/**
+ * @brief Pads mode setup.
+ * @details This function programs a pads group belonging to the same port
+ * with the specified mode.
+ *
+ * @param[in] port the port identifier
+ * @param[in] mask the group mask
+ * @param[in] mode the mode
+ *
+ * @notapi
+ */
+void _pal_lld_setgroupmode(ioportid_t port,
+ ioportmask_t mask,
+ iomode_t mode) {
+
+ (void)port;
+ (void)mask;
+ (void)mode;
+
+}
+
+#endif /* HAL_USE_PAL == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_pal_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_pal_lld.h
new file mode 100644
index 0000000..7aff47a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_pal_lld.h
@@ -0,0 +1,444 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_pal_lld.h
+ * @brief PLATFORM PAL subsystem low level driver header.
+ *
+ * @addtogroup PAL
+ * @{
+ */
+
+#ifndef HAL_PAL_LLD_H
+#define HAL_PAL_LLD_H
+
+#if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Unsupported modes and specific modes */
+/*===========================================================================*/
+
+/* Specifies palInit() without parameter, required until all platforms will
+ be updated to the new style.*/
+#define PAL_NEW_INIT
+
+/*===========================================================================*/
+/* I/O Ports Types and constants. */
+/*===========================================================================*/
+
+/**
+ * @name Port related definitions
+ * @{
+ */
+/**
+ * @brief Width, in bits, of an I/O port.
+ */
+#define PAL_IOPORTS_WIDTH 16U
+
+/**
+ * @brief Whole port mask.
+ * @details This macro specifies all the valid bits into a port.
+ */
+#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFFU)
+/** @} */
+
+/**
+ * @name Line handling macros
+ * @{
+ */
+/**
+ * @brief Forms a line identifier.
+ * @details A port/pad pair are encoded into an @p ioline_t type. The encoding
+ * of this type is platform-dependent.
+ */
+#define PAL_LINE(port, pad) \
+ ((ioline_t)((uint32_t)(port)) | ((uint32_t)(pad)))
+
+/**
+ * @brief Decodes a port identifier from a line identifier.
+ */
+#define PAL_PORT(line) \
+ ((stm32_gpio_t *)(((uint32_t)(line)) & 0xFFFFFFF0U))
+
+/**
+ * @brief Decodes a pad identifier from a line identifier.
+ */
+#define PAL_PAD(line) \
+ ((uint32_t)((uint32_t)(line) & 0x0000000FU))
+
+/**
+ * @brief Value identifying an invalid line.
+ */
+#define PAL_NOLINE 0U
+/** @} */
+
+/**
+ * @brief Generic I/O ports static initializer.
+ * @details An instance of this structure must be passed to @p palInit() at
+ * system startup time in order to initialized the digital I/O
+ * subsystem. This represents only the initial setup, specific pads
+ * or whole ports can be reprogrammed at later time.
+ * @note Implementations may extend this structure to contain more,
+ * architecture dependent, fields.
+ */
+typedef struct {
+
+} PALConfig;
+
+/**
+ * @brief Digital I/O port sized unsigned type.
+ */
+typedef uint32_t ioportmask_t;
+
+/**
+ * @brief Digital I/O modes.
+ */
+typedef uint32_t iomode_t;
+
+/**
+ * @brief Type of an I/O line.
+ */
+typedef uint32_t ioline_t;
+
+/**
+ * @brief Port Identifier.
+ * @details This type can be a scalar or some kind of pointer, do not make
+ * any assumption about it, use the provided macros when populating
+ * variables of this type.
+ */
+typedef uint32_t ioportid_t;
+
+/**
+ * @brief Type of an pad identifier.
+ */
+typedef uint32_t iopadid_t;
+
+/*===========================================================================*/
+/* I/O Ports Identifiers. */
+/*===========================================================================*/
+
+/**
+ * @brief First I/O port identifier.
+ * @details Low level drivers can define multiple ports, it is suggested to
+ * use this naming convention.
+ */
+#define IOPORT1 0
+
+/*===========================================================================*/
+/* Implementation, some of the following macros could be implemented as */
+/* functions, if so please put them in pal_lld.c. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level PAL subsystem initialization.
+ *
+ * @notapi
+ */
+#define pal_lld_init() _pal_lld_init()
+
+/**
+ * @brief Reads the physical I/O port states.
+ *
+ * @param[in] port port identifier
+ * @return The port bits.
+ *
+ * @notapi
+ */
+#define pal_lld_readport(port) 0U
+
+/**
+ * @brief Reads the output latch.
+ * @details The purpose of this function is to read back the latched output
+ * value.
+ *
+ * @param[in] port port identifier
+ * @return The latched logical states.
+ *
+ * @notapi
+ */
+#define pal_lld_readlatch(port) 0U
+
+/**
+ * @brief Writes a bits mask on a I/O port.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be written on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_writeport(port, bits) \
+ do { \
+ (void)port; \
+ (void)bits; \
+ } while (false)
+
+/**
+ * @brief Sets a bits mask on a I/O port.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be ORed on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_setport(port, bits) \
+ do { \
+ (void)port; \
+ (void)bits; \
+ } while (false)
+
+/**
+ * @brief Clears a bits mask on a I/O port.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be cleared on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_clearport(port, bits) \
+ do { \
+ (void)port; \
+ (void)bits; \
+ } while (false)
+
+/**
+ * @brief Toggles a bits mask on a I/O port.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] bits bits to be XORed on the specified port
+ *
+ * @notapi
+ */
+#define pal_lld_toggleport(port, bits) \
+ do { \
+ (void)port; \
+ (void)bits; \
+ } while (false)
+
+/**
+ * @brief Reads a group of bits.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask
+ * @param[in] offset group bit offset within the port
+ * @return The group logical states.
+ *
+ * @notapi
+ */
+#define pal_lld_readgroup(port, mask, offset) 0U
+
+/**
+ * @brief Writes a group of bits.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask
+ * @param[in] offset group bit offset within the port
+ * @param[in] bits bits to be written. Values exceeding the group width
+ * are masked.
+ *
+ * @notapi
+ */
+#define pal_lld_writegroup(port, mask, offset, bits) \
+ do { \
+ (void)port; \
+ (void)mask; \
+ (void)offset; \
+ (void)bits; \
+ } while (false)
+
+/**
+ * @brief Pads group mode setup.
+ * @details This function programs a pads group belonging to the same port
+ * with the specified mode.
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @param[in] port port identifier
+ * @param[in] mask group mask
+ * @param[in] offset group bit offset within the port
+ * @param[in] mode group mode
+ *
+ * @notapi
+ */
+#define pal_lld_setgroupmode(port, mask, offset, mode) \
+ _pal_lld_setgroupmode(port, mask << offset, mode)
+
+/**
+ * @brief Reads a logical state from an I/O pad.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @return The logical state.
+ * @retval PAL_LOW low logical state.
+ * @retval PAL_HIGH high logical state.
+ *
+ * @notapi
+ */
+#define pal_lld_readpad(port, pad) PAL_LOW
+
+/**
+ * @brief Writes a logical state on an output pad.
+ * @note This function is not meant to be invoked directly by the
+ * application code.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] bit logical value, the value must be @p PAL_LOW or
+ * @p PAL_HIGH
+ *
+ * @notapi
+ */
+#define pal_lld_writepad(port, pad, bit) \
+ do { \
+ (void)port; \
+ (void)pad; \
+ (void)bit; \
+ } while (false)
+
+/**
+ * @brief Sets a pad logical state to @p PAL_HIGH.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+#define pal_lld_setpad(port, pad) \
+ do { \
+ (void)port; \
+ (void)pad; \
+ } while (false)
+
+/**
+ * @brief Clears a pad logical state to @p PAL_LOW.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+#define pal_lld_clearpad(port, pad) \
+ do { \
+ (void)port; \
+ (void)pad; \
+ } while (false)
+
+/**
+ * @brief Toggles a pad logical state.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+#define pal_lld_togglepad(port, pad) \
+ do { \
+ (void)port; \
+ (void)pad; \
+ } while (false)
+
+/**
+ * @brief Pad mode setup.
+ * @details This function programs a pad with the specified mode.
+ * @note The @ref PAL provides a default software implementation of this
+ * functionality, implement this function if can optimize it by using
+ * special hardware functionalities or special coding.
+ * @note Programming an unknown or unsupported mode is silently ignored.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ * @param[in] mode pad mode
+ *
+ * @notapi
+ */
+#define pal_lld_setpadmode(port, pad, mode) \
+ do { \
+ (void)port; \
+ (void)pad; \
+ (void)mode; \
+ } while (false)
+
+/**
+ * @brief Returns a PAL event structure associated to a pad.
+ *
+ * @param[in] port port identifier
+ * @param[in] pad pad number within the port
+ *
+ * @notapi
+ */
+#define pal_lld_get_pad_event(port, pad) \
+ &_pal_events[0]; (void)(port); (void)pad
+
+/**
+ * @brief Returns a PAL event structure associated to a line.
+ *
+ * @param[in] line line identifier
+ *
+ * @notapi
+ */
+#define pal_lld_get_line_event(line) \
+ &_pal_events[0]; (void)line
+
+#if !defined(__DOXYGEN__)
+#if (PAL_USE_WAIT == TRUE) || (PAL_USE_CALLBACKS == TRUE)
+extern palevent_t _pal_events[1];
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void _pal_lld_init(void);
+ void _pal_lld_setgroupmode(ioportid_t port,
+ ioportmask_t mask,
+ iomode_t mode);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_PAL == TRUE */
+
+#endif /* HAL_PAL_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_pwm_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_pwm_lld.c
new file mode 100644
index 0000000..49e752f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_pwm_lld.c
@@ -0,0 +1,220 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_pwm_lld.c
+ * @brief PLATFORM PWM subsystem low level driver source.
+ *
+ * @addtogroup PWM
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_PWM == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief PWMD1 driver identifier.
+ * @note The driver PWMD1 allocates the complex timer TIM1 when enabled.
+ */
+#if (PLATFORM_PWM_USE_PWM1 == TRUE) || defined(__DOXYGEN__)
+PWMDriver PWMD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level PWM driver initialization.
+ *
+ * @notapi
+ */
+void pwm_lld_init(void) {
+
+#if PLATFORM_PWM_USE_PWM1 == TRUE
+ /* Driver initialization.*/
+ pwmObjectInit(&PWMD1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the PWM peripheral.
+ * @note Starting a driver that is already in the @p PWM_READY state
+ * disables all the active channels.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ *
+ * @notapi
+ */
+void pwm_lld_start(PWMDriver *pwmp) {
+
+ if (pwmp->state == PWM_STOP) {
+ /* Clock activation and timer reset.*/
+#if PLATFORM_PWM_USE_PWM1 == TRUE
+ if (&PWMD1 == pwmp) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Deactivates the PWM peripheral.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ *
+ * @notapi
+ */
+void pwm_lld_stop(PWMDriver *pwmp) {
+
+ /* If in ready state then disables the PWM clock.*/
+ if (pwmp->state == PWM_READY) {
+#if PLATFORM_PWM_USE_PWM1 == TRUE
+ if (&PWMD1 == pwmp) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Enables a PWM channel.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @post The channel is active using the specified configuration.
+ * @note The function has effect at the next cycle start.
+ * @note Channel notification is not enabled.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] channel PWM channel identifier (0...channels-1)
+ * @param[in] width PWM pulse width as clock pulses number
+ *
+ * @notapi
+ */
+void pwm_lld_enable_channel(PWMDriver *pwmp,
+ pwmchannel_t channel,
+ pwmcnt_t width) {
+
+ (void)pwmp;
+ (void)channel;
+ (void)width;
+}
+
+/**
+ * @brief Disables a PWM channel and its notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @post The channel is disabled and its output line returned to the
+ * idle state.
+ * @note The function has effect at the next cycle start.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] channel PWM channel identifier (0...channels-1)
+ *
+ * @notapi
+ */
+void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) {
+
+ (void)pwmp;
+ (void)channel;
+}
+
+/**
+ * @brief Enables the periodic activation edge notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @note If the notification is already enabled then the call has no effect.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ *
+ * @notapi
+ */
+void pwm_lld_enable_periodic_notification(PWMDriver *pwmp) {
+
+ (void)pwmp;
+}
+
+/**
+ * @brief Disables the periodic activation edge notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @note If the notification is already disabled then the call has no effect.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ *
+ * @notapi
+ */
+void pwm_lld_disable_periodic_notification(PWMDriver *pwmp) {
+
+ (void)pwmp;
+}
+
+/**
+ * @brief Enables a channel de-activation edge notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @pre The channel must have been activated using @p pwmEnableChannel().
+ * @note If the notification is already enabled then the call has no effect.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] channel PWM channel identifier (0...channels-1)
+ *
+ * @notapi
+ */
+void pwm_lld_enable_channel_notification(PWMDriver *pwmp,
+ pwmchannel_t channel) {
+
+ (void)pwmp;
+ (void)channel;
+}
+
+/**
+ * @brief Disables a channel de-activation edge notification.
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @pre The channel must have been activated using @p pwmEnableChannel().
+ * @note If the notification is already disabled then the call has no effect.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] channel PWM channel identifier (0...channels-1)
+ *
+ * @notapi
+ */
+void pwm_lld_disable_channel_notification(PWMDriver *pwmp,
+ pwmchannel_t channel) {
+
+ (void)pwmp;
+ (void)channel;
+}
+
+#endif /* HAL_USE_PWM == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_pwm_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_pwm_lld.h
new file mode 100644
index 0000000..5c4183c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_pwm_lld.h
@@ -0,0 +1,215 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_pwm_lld.h
+ * @brief PLATFORM PWM subsystem low level driver header.
+ *
+ * @addtogroup PWM
+ * @{
+ */
+
+#ifndef HAL_PWM_LLD_H
+#define HAL_PWM_LLD_H
+
+#if (HAL_USE_PWM == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of PWM channels per PWM driver.
+ */
+#define PWM_CHANNELS 4
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief PWMD1 driver enable switch.
+ * @details If set to @p TRUE the support for PWM1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_PWM_USE_PWM1) || defined(__DOXYGEN__)
+#define PLATFORM_PWM_USE_PWM1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Configuration checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a PWM mode.
+ */
+typedef uint32_t pwmmode_t;
+
+/**
+ * @brief Type of a PWM channel.
+ */
+typedef uint8_t pwmchannel_t;
+
+/**
+ * @brief Type of a channels mask.
+ */
+typedef uint32_t pwmchnmsk_t;
+
+/**
+ * @brief Type of a PWM counter.
+ */
+typedef uint32_t pwmcnt_t;
+
+/**
+ * @brief Type of a PWM driver channel configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief Channel active logic level.
+ */
+ pwmmode_t mode;
+ /**
+ * @brief Channel callback pointer.
+ * @note This callback is invoked on the channel compare event. If set to
+ * @p NULL then the callback is disabled.
+ */
+ pwmcallback_t callback;
+ /* End of the mandatory fields.*/
+} PWMChannelConfig;
+
+/**
+ * @brief Type of a PWM driver configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief Timer clock in Hz.
+ * @note The low level can use assertions in order to catch invalid
+ * frequency specifications.
+ */
+ uint32_t frequency;
+ /**
+ * @brief PWM period in ticks.
+ * @note The low level can use assertions in order to catch invalid
+ * period specifications.
+ */
+ pwmcnt_t period;
+ /**
+ * @brief Periodic callback pointer.
+ * @note This callback is invoked on PWM counter reset. If set to
+ * @p NULL then the callback is disabled.
+ */
+ pwmcallback_t callback;
+ /**
+ * @brief Channels configurations.
+ */
+ PWMChannelConfig channels[PWM_CHANNELS];
+ /* End of the mandatory fields.*/
+} PWMConfig;
+
+/**
+ * @brief Structure representing a PWM driver.
+ */
+struct PWMDriver {
+ /**
+ * @brief Driver state.
+ */
+ pwmstate_t state;
+ /**
+ * @brief Current driver configuration data.
+ */
+ const PWMConfig *config;
+ /**
+ * @brief Current PWM period in ticks.
+ */
+ pwmcnt_t period;
+ /**
+ * @brief Mask of the enabled channels.
+ */
+ pwmchnmsk_t enabled;
+ /**
+ * @brief Number of channels in this instance.
+ */
+ pwmchannel_t channels;
+#if defined(PWM_DRIVER_EXT_FIELDS)
+ PWM_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Changes the period the PWM peripheral.
+ * @details This function changes the period of a PWM unit that has already
+ * been activated using @p pwmStart().
+ * @pre The PWM unit must have been activated using @p pwmStart().
+ * @post The PWM unit period is changed to the new value.
+ * @note The function has effect at the next cycle start.
+ * @note If a period is specified that is shorter than the pulse width
+ * programmed in one of the channels then the behavior is not
+ * guaranteed.
+ *
+ * @param[in] pwmp pointer to a @p PWMDriver object
+ * @param[in] period new cycle time in ticks
+ *
+ * @notapi
+ */
+#define pwm_lld_change_period(pwmp, period)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_PWM_USE_PWM1 == TRUE) && !defined(__DOXYGEN__)
+extern PWMDriver PWMD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void pwm_lld_init(void);
+ void pwm_lld_start(PWMDriver *pwmp);
+ void pwm_lld_stop(PWMDriver *pwmp);
+ void pwm_lld_enable_channel(PWMDriver *pwmp,
+ pwmchannel_t channel,
+ pwmcnt_t width);
+ void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel);
+ void pwm_lld_enable_periodic_notification(PWMDriver *pwmp);
+ void pwm_lld_disable_periodic_notification(PWMDriver *pwmp);
+ void pwm_lld_enable_channel_notification(PWMDriver *pwmp,
+ pwmchannel_t channel);
+ void pwm_lld_disable_channel_notification(PWMDriver *pwmp,
+ pwmchannel_t channel);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_PWM == TRUE */
+
+#endif /* HAL_PWM_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_rtc_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_rtc_lld.c
new file mode 100644
index 0000000..cac5f2a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_rtc_lld.c
@@ -0,0 +1,153 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file hal_rtc_lld.c
+ * @brief PLATFORM RTC subsystem low level driver source.
+ *
+ * @addtogroup RTC
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_RTC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief RTC driver identifier.
+ */
+#if (PLATFORM_RTC_USE_RTC1 == TRUE) && !defined(__DOXYGEN__)
+RTCDriver RTCD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Enable access to registers.
+ *
+ * @notapi
+ */
+void rtc_lld_init(void) {
+
+ /* RTC object initialization.*/
+#if PLATFORM_RTC_USE_RTC1 == TRUE
+ rtcObjectInit(&RTCD1);
+#endif
+}
+
+/**
+ * @brief Set current time.
+ * @note Fractional part will be silently ignored. There is no possibility
+ * to set it on PLATFORM platform.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] timespec pointer to a @p RTCDateTime structure
+ *
+ * @notapi
+ */
+void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec) {
+
+ (void)rtcp;
+ (void)timespec;
+}
+
+/**
+ * @brief Get current time.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[out] timespec pointer to a @p RTCDateTime structure
+ *
+ * @notapi
+ */
+void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec) {
+
+ (void)rtcp;
+ (void)timespec;
+}
+
+#if (RTC_ALARMS > 0) || defined(__DOXYGEN__)
+/**
+ * @brief Set alarm time.
+ * @note Default value after BKP domain reset for both comparators is 0.
+ * @note Function does not performs any checks of alarm time validity.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure.
+ * @param[in] alarm alarm identifier. Can be 1 or 2.
+ * @param[in] alarmspec pointer to a @p RTCAlarm structure.
+ *
+ * @notapi
+ */
+void rtc_lld_set_alarm(RTCDriver *rtcp,
+ rtcalarm_t alarm,
+ const RTCAlarm *alarmspec) {
+
+ (void)rtcp;
+ (void)alarm;
+ (void)alarmspec;
+}
+
+/**
+ * @brief Get alarm time.
+ * @note The function can be called from any context.
+ *
+ * @param[in] rtcp pointer to RTC driver structure
+ * @param[in] alarm alarm identifier
+ * @param[out] alarmspec pointer to a @p RTCAlarm structure
+ *
+ * @notapi
+ */
+void rtc_lld_get_alarm(RTCDriver *rtcp,
+ rtcalarm_t alarm,
+ RTCAlarm *alarmspec) {
+
+ (void)rtcp;
+ (void)alarm;
+ (void)alarmspec;
+}
+#endif /* RTC_ALARMS > 0 */
+
+#endif /* HAL_USE_RTC */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_rtc_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_rtc_lld.h
new file mode 100644
index 0000000..be988cf
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_rtc_lld.h
@@ -0,0 +1,148 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ Concepts and parts of this file have been contributed by Uladzimir Pylinsky
+ aka barthess.
+ */
+
+/**
+ * @file hal_rtc_lld.h
+ * @brief PLATFORM RTC subsystem low level driver header.
+ *
+ * @addtogroup RTC
+ * @{
+ */
+
+#ifndef HAL_RTC_LLD_H
+#define HAL_RTC_LLD_H
+
+#if (HAL_USE_RTC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name Implementation capabilities
+ */
+/**
+ * @brief Callback support int the driver.
+ */
+#define RTC_SUPPORTS_CALLBACKS TRUE
+
+/**
+ * @brief Number of alarms available.
+ */
+#define RTC_ALARMS 2
+
+/**
+ * @brief Presence of a local persistent storage.
+ */
+#define RTC_HAS_STORAGE FALSE
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief RTCD1 driver enable switch.
+ * @details If set to @p TRUE the support for RTC1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_RTC_USE_RTC1) || defined(__DOXYGEN__)
+#define PLATFORM_RTC_USE_RTC1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+#if (RTC_SUPPORTS_CALLBACKS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of an RTC event.
+ */
+typedef enum {
+ RTC_EVENT_SECOND = 0 /** Triggered every second. */
+} rtcevent_t;
+
+/**
+ * @brief Type of a generic RTC callback.
+ */
+typedef void (*rtccb_t)(RTCDriver *rtcp, rtcevent_t event);
+#endif
+
+/**
+ * @brief Type of a structure representing an RTC alarm time stamp.
+ */
+typedef struct {
+ /* End of the mandatory fields.*/
+ uint32_t dummy;
+} RTCAlarm;
+
+/**
+ * @brief Implementation-specific @p RTCDriver fields.
+ */
+#define rtc_lld_driver_fields \
+ uint32_t dummy
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_RTC_USE_RTC1 == TRUE) && !defined(__DOXYGEN__)
+extern RTCDriver RTCD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void rtc_lld_init(void);
+ void rtc_lld_set_time(RTCDriver *rtcp, const RTCDateTime *timespec);
+ void rtc_lld_get_time(RTCDriver *rtcp, RTCDateTime *timespec);
+#if RTC_ALARMS > 0
+ void rtc_lld_set_alarm(RTCDriver *rtcp,
+ rtcalarm_t alarm,
+ const RTCAlarm *alarmspec);
+ void rtc_lld_get_alarm(RTCDriver *rtcp,
+ rtcalarm_t alarm,
+ RTCAlarm *alarmspec);
+#endif
+#if RTC_SUPPORTS_CALLBACKS == TRUE
+ void rtc_lld_set_callback(RTCDriver *rtcp, rtccb_t callback);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_RTC == TRUE */
+
+#endif /* HAL_RTC_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_sdc_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_sdc_lld.c
new file mode 100644
index 0000000..cb20ed7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_sdc_lld.c
@@ -0,0 +1,328 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_sdc_lld.c
+ * @brief PLATFORM SDC subsystem low level driver source.
+ *
+ * @addtogroup SDC
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_SDC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief SDCD1 driver identifier.
+ */
+#if (PLATFORM_SDC_USE_SDC1 == TRUE) || defined(__DOXYGEN__)
+SDCDriver SDCD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level SDC driver initialization.
+ *
+ * @notapi
+ */
+void sdc_lld_init(void) {
+
+#if PLATFORM_SDC_USE_SDC1 == TRUE
+ sdcObjectInit(&SDCD1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the SDC peripheral.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_start(SDCDriver *sdcp) {
+
+ if (sdcp->state == BLK_STOP) {
+
+ }
+}
+
+/**
+ * @brief Deactivates the SDC peripheral.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_stop(SDCDriver *sdcp) {
+
+ if (sdcp->state != BLK_STOP) {
+
+ }
+}
+
+/**
+ * @brief Starts the SDIO clock and sets it to init mode (400kHz or less).
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_start_clk(SDCDriver *sdcp) {
+
+ (void)sdcp;
+}
+
+/**
+ * @brief Sets the SDIO clock to data mode (25MHz or less).
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] clk the clock mode
+ *
+ * @notapi
+ */
+void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk) {
+
+ (void)sdcp;
+ (void)clk;
+}
+
+/**
+ * @brief Stops the SDIO clock.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_stop_clk(SDCDriver *sdcp) {
+
+ (void)sdcp;
+}
+
+/**
+ * @brief Switches the bus to 4 bits mode.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] mode bus mode
+ *
+ * @notapi
+ */
+void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) {
+
+ (void)sdcp;
+
+ switch (mode) {
+ case SDC_MODE_1BIT:
+
+ break;
+ case SDC_MODE_4BIT:
+
+ break;
+ case SDC_MODE_8BIT:
+
+ break;
+ default:
+ osalDbgAssert(false, "invalid bus mode");
+ break;
+ }
+}
+
+/**
+ * @brief Sends an SDIO command with no response expected.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] cmd card command
+ * @param[in] arg command argument
+ *
+ * @notapi
+ */
+void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg) {
+
+ (void)sdcp;
+ (void)cmd;
+ (void)arg;
+}
+
+/**
+ * @brief Sends an SDIO command with a short response expected.
+ * @note The CRC is not verified.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] cmd card command
+ * @param[in] arg command argument
+ * @param[out] resp pointer to the response buffer (one word)
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp) {
+
+ (void)sdcp;
+ (void)cmd;
+ (void)arg;
+ (void)resp;
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Sends an SDIO command with a short response expected and CRC.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] cmd card command
+ * @param[in] arg command argument
+ * @param[out] resp pointer to the response buffer (one word)
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp) {
+
+ (void)sdcp;
+ (void)cmd;
+ (void)arg;
+ (void)resp;
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Sends an SDIO command with a long response expected and CRC.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] cmd card command
+ * @param[in] arg command argument
+ * @param[out] resp pointer to the response buffer (four words)
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp) {
+
+ (void)sdcp;
+ (void)cmd;
+ (void)arg;
+ (void)resp;
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Reads one or more blocks.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to read
+ * @param[out] buf pointer to the read buffer
+ * @param[in] n number of blocks to read
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk,
+ uint8_t *buf, uint32_t n) {
+
+ (void)sdcp;
+ (void)startblk;
+ (void)buf;
+ (void)n;
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Writes one or more blocks.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ * @param[in] startblk first block to write
+ * @param[out] buf pointer to the write buffer
+ * @param[in] n number of blocks to write
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS operation succeeded.
+ * @retval HAL_FAILED operation failed.
+ *
+ * @notapi
+ */
+bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk,
+ const uint8_t *buf, uint32_t n) {
+
+ (void)sdcp;
+ (void)startblk;
+ (void)buf;
+ (void)n;
+
+ return HAL_SUCCESS;
+}
+
+/**
+ * @brief Waits for card idle condition.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @return The operation status.
+ * @retval HAL_SUCCESS the operation succeeded.
+ * @retval HAL_FAILED the operation failed.
+ *
+ * @api
+ */
+bool sdc_lld_sync(SDCDriver *sdcp) {
+
+ (void)sdcp;
+
+ return HAL_SUCCESS;
+}
+
+#endif /* HAL_USE_SDC == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_sdc_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_sdc_lld.h
new file mode 100644
index 0000000..61ee84b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_sdc_lld.h
@@ -0,0 +1,180 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_sdc_lld.h
+ * @brief PLATFORM SDC subsystem low level driver header.
+ *
+ * @addtogroup SDC
+ * @{
+ */
+
+#ifndef HAL_SDC_LLD_H
+#define HAL_SDC_LLD_H
+
+#if (HAL_USE_SDC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief PWMD1 driver enable switch.
+ * @details If set to @p TRUE the support for PWM1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_SDC_USE_SDC1) || defined(__DOXYGEN__)
+#define PLATFORM_SDC_USE_SDC1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of card flags.
+ */
+typedef uint32_t sdcmode_t;
+
+/**
+ * @brief SDC Driver condition flags type.
+ */
+typedef uint32_t sdcflags_t;
+
+/**
+ * @brief Type of a structure representing an SDC driver.
+ */
+typedef struct SDCDriver SDCDriver;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+ /**
+ * @brief Bus width.
+ */
+ sdcbusmode_t bus_width;
+ /* End of the mandatory fields.*/
+} SDCConfig;
+
+/**
+ * @brief @p SDCDriver specific methods.
+ */
+#define _sdc_driver_methods \
+ _mmcsd_block_device_methods
+
+/**
+ * @extends MMCSDBlockDeviceVMT
+ *
+ * @brief @p SDCDriver virtual methods table.
+ */
+struct SDCDriverVMT {
+ _sdc_driver_methods
+};
+
+/**
+ * @brief Structure representing an SDC driver.
+ */
+struct SDCDriver {
+ /**
+ * @brief Virtual Methods Table.
+ */
+ const struct SDCDriverVMT *vmt;
+ _mmcsd_block_device_data
+ /**
+ * @brief Current configuration data.
+ */
+ const SDCConfig *config;
+ /**
+ * @brief Various flags regarding the mounted card.
+ */
+ sdcmode_t cardmode;
+ /**
+ * @brief Errors flags.
+ */
+ sdcflags_t errors;
+ /**
+ * @brief Card RCA.
+ */
+ uint32_t rca;
+ /**
+ * @brief Buffer for internal operations.
+ */
+ uint8_t buf[MMCSD_BLOCK_SIZE];
+ /* End of the mandatory fields.*/
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_SDC_USE_SDC1 == TRUE) && !defined(__DOXYGEN__)
+extern SDCDriver SDCD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void sdc_lld_init(void);
+ void sdc_lld_start(SDCDriver *sdcp);
+ void sdc_lld_stop(SDCDriver *sdcp);
+ void sdc_lld_start_clk(SDCDriver *sdcp);
+ void sdc_lld_set_data_clk(SDCDriver *sdcp, sdcbusclk_t clk);
+ void sdc_lld_stop_clk(SDCDriver *sdcp);
+ void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode);
+ void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg);
+ bool sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp);
+ bool sdc_lld_send_cmd_short_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp);
+ bool sdc_lld_send_cmd_long_crc(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
+ uint32_t *resp);
+ bool sdc_lld_read_special(SDCDriver *sdcp, uint8_t *buf, size_t bytes,
+ uint8_t cmd, uint32_t argument);
+ bool sdc_lld_read(SDCDriver *sdcp, uint32_t startblk,
+ uint8_t *buf, uint32_t n);
+ bool sdc_lld_write(SDCDriver *sdcp, uint32_t startblk,
+ const uint8_t *buf, uint32_t n);
+ bool sdc_lld_sync(SDCDriver *sdcp);
+ bool sdc_lld_is_card_inserted(SDCDriver *sdcp);
+ bool sdc_lld_is_write_protected(SDCDriver *sdcp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SDC == TRUE */
+
+#endif /* HAL_SDC_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_serial_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_serial_lld.c
new file mode 100644
index 0000000..cdec15c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_serial_lld.c
@@ -0,0 +1,126 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_serial_lld.c
+ * @brief PLATFORM serial subsystem low level driver source.
+ *
+ * @addtogroup SERIAL
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief USART1 serial driver identifier.*/
+#if (PLATFORM_SERIAL_USE_USART1 == TRUE) || defined(__DOXYGEN__)
+SerialDriver SD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Driver default configuration.
+ */
+static const SerialConfig default_config = {
+ 38400
+};
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level serial driver initialization.
+ *
+ * @notapi
+ */
+void sd_lld_init(void) {
+
+#if PLATFORM_SERIAL_USE_USART1 == TRUE
+ sdObjectInit(&SD1, NULL, notify1);
+#endif
+}
+
+/**
+ * @brief Low level serial driver configuration and (re)start.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ * @param[in] config the architecture-dependent serial driver configuration.
+ * If this parameter is set to @p NULL then a default
+ * configuration is used.
+ *
+ * @notapi
+ */
+void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
+
+ if (config == NULL) {
+ config = &default_config;
+ }
+
+ if (sdp->state == SD_STOP) {
+#if PLATFORM_SERIAL_USE_USART1 == TRUE
+ if (&SD1 == sdp) {
+
+ }
+#endif
+ }
+ /* Configures the peripheral.*/
+ (void)config; /* Warning suppression, remove this.*/
+}
+
+/**
+ * @brief Low level serial driver stop.
+ * @details De-initializes the USART, stops the associated clock, resets the
+ * interrupt vector.
+ *
+ * @param[in] sdp pointer to a @p SerialDriver object
+ *
+ * @notapi
+ */
+void sd_lld_stop(SerialDriver *sdp) {
+
+ if (sdp->state == SD_READY) {
+#if PLATFORM_SERIAL_USE_USART1 == TRUE
+ if (&SD1 == sdp) {
+
+ }
+#endif
+ }
+}
+
+#endif /* HAL_USE_SERIAL == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_serial_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_serial_lld.h
new file mode 100644
index 0000000..4d6b2cb
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_serial_lld.h
@@ -0,0 +1,119 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_serial_lld.h
+ * @brief PLATFORM serial subsystem low level driver header.
+ *
+ * @addtogroup SERIAL
+ * @{
+ */
+
+#ifndef HAL_SERIAL_LLD_H
+#define HAL_SERIAL_LLD_H
+
+#if (HAL_USE_SERIAL == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief USART1 driver enable switch.
+ * @details If set to @p TRUE the support for USART1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_SERIAL_USE_USART1) || defined(__DOXYGEN__)
+#define PLATFORM_SERIAL_USE_USART1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief PLATFORM Serial Driver configuration structure.
+ * @details An instance of this structure must be passed to @p sdStart()
+ * in order to configure and start a serial driver operations.
+ * @note This structure content is architecture dependent, each driver
+ * implementation defines its own version and the custom static
+ * initializers.
+ */
+typedef struct {
+ /**
+ * @brief Bit rate.
+ */
+ uint32_t speed;
+ /* End of the mandatory fields.*/
+} SerialConfig;
+
+/**
+ * @brief @p SerialDriver specific data.
+ */
+#define _serial_driver_data \
+ _base_asynchronous_channel_data \
+ /* Driver state.*/ \
+ sdstate_t state; \
+ /* Input queue.*/ \
+ input_queue_t iqueue; \
+ /* Output queue.*/ \
+ output_queue_t oqueue; \
+ /* Input circular buffer.*/ \
+ uint8_t ib[SERIAL_BUFFERS_SIZE]; \
+ /* Output circular buffer.*/ \
+ uint8_t ob[SERIAL_BUFFERS_SIZE]; \
+ /* End of the mandatory fields.*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_SERIAL_USE_USART1 == TRUE) && !defined(__DOXYGEN__)
+extern SerialDriver SD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void sd_lld_init(void);
+ void sd_lld_start(SerialDriver *sdp, const SerialConfig *config);
+ void sd_lld_stop(SerialDriver *sdp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SERIAL == TRUE */
+
+#endif /* HAL_SERIAL_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_sio_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_sio_lld.c
new file mode 100644
index 0000000..96b2291
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_sio_lld.c
@@ -0,0 +1,140 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_sio_lld.c
+ * @brief PLATFORM SIO subsystem low level driver source.
+ *
+ * @addtogroup SIO
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_SIO == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief SIO1 driver identifier.
+ */
+#if (PLATFORM_SIO_USE_SIO1 == TRUE) || defined(__DOXYGEN__)
+SIODriver SIOD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level SIO driver initialization.
+ *
+ * @notapi
+ */
+void sio_lld_init(void) {
+
+#if PLATFORM_SIO_USE_SIO1 == TRUE
+ /* Driver initialization.*/
+ sioObjectInit(&SIOD1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the SIO peripheral.
+ *
+ * @param[in] siop pointer to the @p SIODriver object
+ *
+ * @notapi
+ */
+void sio_lld_start(SIODriver *siop) {
+
+ if (siop->state == SIO_STOP) {
+ /* Enables the peripheral.*/
+#if PLATFORM_SIO_USE_SIO1 == TRUE
+ if (&SIOD1 == siop) {
+
+ }
+#endif
+ }
+ /* Configures the peripheral.*/
+
+}
+
+/**
+ * @brief Deactivates the SIO peripheral.
+ *
+ * @param[in] siop pointer to the @p SIODriver object
+ *
+ * @notapi
+ */
+void sio_lld_stop(SIODriver *siop) {
+
+ if (siop->state == SIO_READY) {
+ /* Resets the peripheral.*/
+
+ /* Disables the peripheral.*/
+#if PLATFORM_SIO_USE_SIO1 == TRUE
+ if (&SIOD1 == siop) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Control operation on a serial port.
+ *
+ * @param[in] siop pointer to the @p SIODriver object
+ * @param[in] operation control operation code
+ * @param[in,out] arg operation argument
+ *
+ * @return The control operation status.
+ * @retval MSG_OK in case of success.
+ * @retval MSG_TIMEOUT in case of operation timeout.
+ * @retval MSG_RESET in case of operation reset.
+ *
+ * @notapi
+ */
+msg_t sio_lld_control(SIODriver *siop, unsigned int operation, void *arg) {
+
+ (void)siop;
+ (void)operation;
+ (void)arg;
+
+ return MSG_OK;
+}
+
+#endif /* HAL_USE_SIO == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_sio_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_sio_lld.h
new file mode 100644
index 0000000..7b4761c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_sio_lld.h
@@ -0,0 +1,205 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_sio_lld.h
+ * @brief PLATFORM SIO subsystem low level driver header.
+ *
+ * @addtogroup SIO
+ * @{
+ */
+
+#ifndef HAL_SIO_LLD_H
+#define HAL_SIO_LLD_H
+
+#if (HAL_USE_SIO == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief SIO driver enable switch.
+ * @details If set to @p TRUE the support for SIO1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_SIO_USE_SIO1) || defined(__DOXYGEN__)
+#define PLATFORM_SIO_USE_SIO1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief SIO driver condition flags type.
+ */
+typedef uint32_t sioflags_t;
+
+/**
+ * @brief Generic SIO notification callback type.
+ *
+ * @param[in] siop pointer to the @p SIODriver object
+ */
+typedef void (*siocb_t)(SIODriver *siop);
+
+/**
+ * @brief Receive error SIO notification callback type.
+ *
+ * @param[in] siop pointer to the @p SIODriver object triggering the
+ * callback
+ * @param[in] e receive error mask
+ */
+typedef void (*sioecb_t)(SIODriver *siop, sioflags_t e);
+
+/**
+ * @brief Driver configuration structure.
+ * @note Implementations may extend this structure to contain more,
+ * architecture dependent, fields.
+ */
+struct hal_sio_config {
+ /**
+ * @brief Receive buffer filled callback.
+ * @note Can be @p NULL.
+ */
+ siocb_t rxne_cb;
+ /**
+ * @brief End of transmission buffer callback.
+ * @note Can be @p NULL.
+ */
+ siocb_t txnf_cb;
+ /**
+ * @brief Physical end of transmission callback.
+ * @note Can be @p NULL.
+ */
+ siocb_t txend_cb;
+ /**
+ * @brief Receive event callback.
+ * @note Can be @p NULL.
+ */
+ sioecb_t rxevt_cb;
+ /* End of the mandatory fields.*/
+};
+
+/**
+ * @brief Structure representing a SIO driver.
+ * @note Implementations may extend this structure to contain more,
+ * architecture dependent, fields.
+ */
+struct hal_sio_driver {
+ /**
+ * @brief Driver state.
+ */
+ siostate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const SIOConfig *config;
+#if defined(SIO_DRIVER_EXT_FIELDS)
+ SIO_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Determines the state of the RX FIFO.
+ *
+ * @param[in] siop pointer to the @p SIODriver object
+ * @return The RX FIFO state.
+ * @retval false if RX FIFO is not empty
+ * @retval true if RX FIFO is empty
+ *
+ * @notapi
+ */
+#define sio_lld_rx_is_empty(siop) true
+
+/**
+ * @brief Determines the state of the TX FIFO.
+ *
+ * @param[in] siop pointer to the @p SIODriver object
+ * @return The TX FIFO state.
+ * @retval false if TX FIFO is not full
+ * @retval true if TX FIFO is full
+ *
+ * @notapi
+ */
+#define sio_lld_tx_is_full(siop) true
+
+/**
+ * @brief Returns one frame from the RX FIFO.
+ * @note If the FIFO is empty then the returned value is unpredictable.
+ *
+ * @param[in] siop pointer to the @p SIODriver object
+ * @return The frame from RX FIFO.
+ *
+ * @notapi
+ */
+#define sio_lld_rx_get(siop)
+
+/**
+ * @brief Pushes one frame into the TX FIFO.
+ * @note If the FIFO is full then the behavior is unpredictable.
+ *
+ * @param[in] siop pointer to the @p SIODriver object
+ * @param[in] data frame to be written
+ *
+ * @notapi
+ */
+#define sio_lld_tx_put(siop, data)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_SIO_USE_SIO1 == TRUE) && !defined(__DOXYGEN__)
+extern SIODriver SIOD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void sio_lld_init(void);
+ void sio_lld_start(SIODriver *siop);
+ void sio_lld_stop(SIODriver *siop);
+ size_t sio_lld_read(SIODriver *siop, void *buffer, size_t size);
+ size_t sio_lld_write(SIODriver *siop, const void *buffer, size_t size);
+ msg_t sio_lld_control(SIODriver *siop, unsigned int operation, void *arg);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SIO == TRUE */
+
+#endif /* HAL_SIO_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_spi_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_spi_lld.c
new file mode 100644
index 0000000..557342d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_spi_lld.c
@@ -0,0 +1,263 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_spi_lld.c
+ * @brief PLATFORM SPI subsystem low level driver source.
+ *
+ * @addtogroup SPI
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief SPI1 driver identifier.
+ */
+#if (PLATFORM_SPI_USE_SPI1 == TRUE) || defined(__DOXYGEN__)
+SPIDriver SPID1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level SPI driver initialization.
+ *
+ * @notapi
+ */
+void spi_lld_init(void) {
+
+#if PLATFORM_SPI_USE_SPI1 == TRUE
+ /* Driver initialization.*/
+ spiObjectInit(&SPID1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the SPI peripheral.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_start(SPIDriver *spip) {
+
+ if (spip->state == SPI_STOP) {
+ /* Enables the peripheral.*/
+#if PLATFORM_SPI_USE_SPI1 == TRUE
+ if (&SPID1 == spip) {
+
+ }
+#endif
+ }
+ /* Configures the peripheral.*/
+
+}
+
+/**
+ * @brief Deactivates the SPI peripheral.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_stop(SPIDriver *spip) {
+
+ if (spip->state == SPI_READY) {
+ /* Disables the peripheral.*/
+#if PLATFORM_SPI_USE_SPI1 == TRUE
+ if (&SPID1 == spip) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Asserts the slave select signal and prepares for transfers.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_select(SPIDriver *spip) {
+
+ (void)spip;
+
+}
+
+/**
+ * @brief Deasserts the slave select signal.
+ * @details The previously selected peripheral is unselected.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_unselect(SPIDriver *spip) {
+
+ (void)spip;
+
+}
+
+/**
+ * @brief Ignores data on the SPI bus.
+ * @details This asynchronous function starts the transmission of a series of
+ * idle words on the SPI bus and ignores the received data.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be ignored
+ *
+ * @notapi
+ */
+void spi_lld_ignore(SPIDriver *spip, size_t n) {
+
+ (void)spip;
+ (void)n;
+
+}
+
+/**
+ * @brief Exchanges data on the SPI bus.
+ * @details This asynchronous function starts a simultaneous transmit/receive
+ * operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to be exchanged
+ * @param[in] txbuf the pointer to the transmit buffer
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void spi_lld_exchange(SPIDriver *spip, size_t n,
+ const void *txbuf, void *rxbuf) {
+
+ (void)spip;
+ (void)n;
+ (void)txbuf;
+ (void)rxbuf;
+
+}
+
+/**
+ * @brief Sends data over the SPI bus.
+ * @details This asynchronous function starts a transmit operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @notapi
+ */
+void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
+
+ (void)spip;
+ (void)n;
+ (void)txbuf;
+
+}
+
+/**
+ * @brief Receives data from the SPI bus.
+ * @details This asynchronous function starts a receive operation.
+ * @post At the end of the operation the configured callback is invoked.
+ * @note The buffers are organized as uint8_t arrays for data sizes below or
+ * equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] n number of words to receive
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
+
+ (void)spip;
+ (void)n;
+ (void)rxbuf;
+
+}
+
+#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Aborts the ongoing SPI operation, if any.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ *
+ * @notapi
+ */
+void spi_lld_abort(SPIDriver *spip) {
+
+ (void)spip;
+}
+#endif /* SPI_SUPPORTS_CIRCULAR == TRUE */
+
+/**
+ * @brief Exchanges one frame using a polled wait.
+ * @details This synchronous function exchanges one frame using a polled
+ * synchronization method. This function is useful when exchanging
+ * small amount of data on high speed channels, usually in this
+ * situation is much more efficient just wait for completion using
+ * polling than suspending the thread waiting for an interrupt.
+ *
+ * @param[in] spip pointer to the @p SPIDriver object
+ * @param[in] frame the data frame to send over the SPI bus
+ * @return The received data frame from the SPI bus.
+ *
+ * @notapi
+ */
+uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) {
+
+ (void)spip;
+ (void)frame;
+
+ return 0;
+}
+
+#endif /* HAL_USE_SPI == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_spi_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_spi_lld.h
new file mode 100644
index 0000000..b3f180a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_spi_lld.h
@@ -0,0 +1,120 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_spi_lld.h
+ * @brief PLATFORM SPI subsystem low level driver header.
+ *
+ * @addtogroup SPI
+ * @{
+ */
+
+#ifndef HAL_SPI_LLD_H
+#define HAL_SPI_LLD_H
+
+#if (HAL_USE_SPI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Circular mode support flag.
+ */
+#define SPI_SUPPORTS_CIRCULAR TRUE
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief SPI1 driver enable switch.
+ * @details If set to @p TRUE the support for SPI1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_SPI_USE_SPI1) || defined(__DOXYGEN__)
+#define PLATFORM_SPI_USE_SPI1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the SPI driver structure.
+ */
+#define spi_lld_driver_fields \
+ /* Dummy field, it is not needed.*/ \
+ uint32_t dummy
+
+/**
+ * @brief Low level fields of the SPI configuration structure.
+ */
+#define spi_lld_config_fields \
+ /* Dummy configuration, it is not needed.*/ \
+ uint32_t dummy
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_SPI_USE_SPI1 == TRUE) && !defined(__DOXYGEN__)
+extern SPIDriver SPID1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void spi_lld_init(void);
+ void spi_lld_start(SPIDriver *spip);
+ void spi_lld_stop(SPIDriver *spip);
+#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__)
+ void spi_lld_select(SPIDriver *spip);
+ void spi_lld_unselect(SPIDriver *spip);
+#endif
+ void spi_lld_select(SPIDriver *spip);
+ void spi_lld_unselect(SPIDriver *spip);
+ void spi_lld_ignore(SPIDriver *spip, size_t n);
+ void spi_lld_exchange(SPIDriver *spip, size_t n,
+ const void *txbuf, void *rxbuf);
+ void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
+ void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
+#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__)
+ void spi_lld_abort(SPIDriver *spip);
+#endif
+ uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_SPI == TRUE */
+
+#endif /* HAL_SPI_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_st_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_st_lld.c
new file mode 100644
index 0000000..5e7e2f1
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_st_lld.c
@@ -0,0 +1,67 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_st_lld.c
+ * @brief PLATFORM ST subsystem low level driver source.
+ *
+ * @addtogroup ST
+ * @{
+ */
+
+#include "hal.h"
+
+#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level ST driver initialization.
+ *
+ * @notapi
+ */
+void st_lld_init(void) {
+}
+
+#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_st_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_st_lld.h
new file mode 100644
index 0000000..a99bf81
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_st_lld.h
@@ -0,0 +1,141 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_st_lld.h
+ * @brief PLATFORM ST subsystem low level driver header.
+ * @details This header is designed to be include-able without having to
+ * include other files from the HAL.
+ *
+ * @addtogroup ST
+ * @{
+ */
+
+#ifndef HAL_ST_LLD_H
+#define HAL_ST_LLD_H
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void st_lld_init(void);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Driver inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Returns the time counter value.
+ *
+ * @return The counter value.
+ *
+ * @notapi
+ */
+static inline systime_t st_lld_get_counter(void) {
+
+ return (systime_t)0;
+}
+
+/**
+ * @brief Starts the alarm.
+ * @note Makes sure that no spurious alarms are triggered after
+ * this call.
+ *
+ * @param[in] abstime the time to be set for the first alarm
+ *
+ * @notapi
+ */
+static inline void st_lld_start_alarm(systime_t abstime) {
+
+ (void)abstime;
+}
+
+/**
+ * @brief Stops the alarm interrupt.
+ *
+ * @notapi
+ */
+static inline void st_lld_stop_alarm(void) {
+
+}
+
+/**
+ * @brief Sets the alarm time.
+ *
+ * @param[in] abstime the time to be set for the next alarm
+ *
+ * @notapi
+ */
+static inline void st_lld_set_alarm(systime_t abstime) {
+
+ (void)abstime;
+}
+
+/**
+ * @brief Returns the current alarm time.
+ *
+ * @return The currently set alarm time.
+ *
+ * @notapi
+ */
+static inline systime_t st_lld_get_alarm(void) {
+
+ return (systime_t)0;
+}
+
+/**
+ * @brief Determines if the alarm is active.
+ *
+ * @return The alarm status.
+ * @retval false if the alarm is not active.
+ * @retval true is the alarm is active
+ *
+ * @notapi
+ */
+static inline bool st_lld_is_alarm_active(void) {
+
+ return false;
+}
+
+#endif /* HAL_ST_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_trng_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_trng_lld.c
new file mode 100644
index 0000000..68965fc
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_trng_lld.c
@@ -0,0 +1,140 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_trng_lld.c
+ * @brief PLATFORM TRNG subsystem low level driver source.
+ *
+ * @addtogroup TRNG
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_TRNG == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief TRNGD1 driver identifier.
+ */
+#if (PLATFORM_TRNG_USE_TRNG1 == TRUE) || defined(__DOXYGEN__)
+TRNGDriver TRNGD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level TRNG driver initialization.
+ *
+ * @notapi
+ */
+void trng_lld_init(void) {
+
+#if PLATFORM_TRNG_USE_TRNG1 == TRUE
+ /* Driver initialization.*/
+ trngObjectInit(&TRNGD1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the TRNG peripheral.
+ *
+ * @param[in] trngp pointer to the @p TRNGDriver object
+ *
+ * @notapi
+ */
+void trng_lld_start(TRNGDriver *trngp) {
+
+ if (trngp->state == TRNG_STOP) {
+ /* Enables the peripheral.*/
+#if PLATFORM_TRNG_USE_TRNG1 == TRUE
+ if (&TRNGD1 == trngp) {
+
+ }
+#endif
+ }
+ /* Configures the peripheral.*/
+
+}
+
+/**
+ * @brief Deactivates the TRNG peripheral.
+ *
+ * @param[in] trngp pointer to the @p TRNGDriver object
+ *
+ * @notapi
+ */
+void trng_lld_stop(TRNGDriver *trngp) {
+
+ if (trngp->state == TRNG_READY) {
+ /* Resets the peripheral.*/
+
+ /* Disables the peripheral.*/
+#if PLATFORM_TRNG_USE_TRNG1 == TRUE
+ if (&TRNGD1 == trngp) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief True random numbers generator.
+ * @note The function is blocking and likely performs polled waiting
+ * inside the low level implementation.
+ *
+ * @param[in] trngp pointer to the @p TRNGDriver object
+ * @param[in] size size of output buffer
+ * @param[out] out output buffer
+ * @return The operation status.
+ * @retval false if a random number has been generated.
+ * @retval true if an HW error occurred.
+ *
+ * @api
+ */
+bool trng_lld_generate(TRNGDriver *trngp, size_t size, uint8_t *out) {
+
+ (void)trngp;
+ (void)size;
+ (void)out;
+
+ return true;
+}
+
+#endif /* HAL_USE_TRNG == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_trng_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_trng_lld.h
new file mode 100644
index 0000000..c43d09b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_trng_lld.h
@@ -0,0 +1,101 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_trng_lld.h
+ * @brief PLATFORM TRNG subsystem low level driver header.
+ *
+ * @addtogroup TRNG
+ * @{
+ */
+
+#ifndef HAL_TRNG_LLD_H
+#define HAL_TRNG_LLD_H
+
+#if (HAL_USE_TRNG == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief TRNGD1 driver enable switch.
+ * @details If set to @p TRUE the support for TRNGD1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_TRNG_USE_TRNG1) || defined(__DOXYGEN__)
+#define PLATFORM_TRNG_USE_TRNG1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the TRNG driver structure.
+ */
+#define trng_lld_driver_fields \
+ /* Dummy field, it is not needed.*/ \
+ uint32_t dummy
+
+/**
+ * @brief Low level fields of the TRNG configuration structure.
+ */
+#define trng_lld_config_fields \
+ /* Dummy configuration, it is not needed.*/ \
+ uint32_t dummy
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_TRNG_USE_TRNG1 == TRUE) && !defined(__DOXYGEN__)
+extern TRNGDriver TRNGD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void trng_lld_init(void);
+ void trng_lld_start(TRNGDriver *trngp);
+ void trng_lld_stop(TRNGDriver *trngp);
+ bool trng_lld_generate(TRNGDriver *trngp, size_t size, uint8_t *out);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_TRNG == TRUE */
+
+#endif /* HAL_TRNG_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_uart_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_uart_lld.c
new file mode 100644
index 0000000..be42912
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_uart_lld.c
@@ -0,0 +1,191 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_uart_lld.c
+ * @brief PLATFORM UART subsystem low level driver source.
+ *
+ * @addtogroup UART
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief UART1 driver identifier.
+ */
+#if (PLATFORM_UART_USE_UART1 == TRUE) || defined(__DOXYGEN__)
+UARTDriver UARTD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level UART driver initialization.
+ *
+ * @notapi
+ */
+void uart_lld_init(void) {
+
+#if PLATFORM_UART_USE_UART1 == TRUE
+ /* Driver initialization.*/
+ uartObjectInit(&UARTD1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the UART peripheral.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+void uart_lld_start(UARTDriver *uartp) {
+
+ if (uartp->state == UART_STOP) {
+ /* Enables the peripheral.*/
+#if PLATFORM_UART_USE_UART1 == TRUE
+ if (&UARTD1 == uartp) {
+
+ }
+#endif
+ }
+ /* Configures the peripheral.*/
+
+}
+
+/**
+ * @brief Deactivates the UART peripheral.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @notapi
+ */
+void uart_lld_stop(UARTDriver *uartp) {
+
+ if (uartp->state == UART_READY) {
+ /* Resets the peripheral.*/
+
+ /* Disables the peripheral.*/
+#if PLATFORM_UART_USE_UART1 == TRUE
+ if (&UARTD1 == uartp) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Starts a transmission on the UART peripheral.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] n number of data frames to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @notapi
+ */
+void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) {
+
+ (void)uartp;
+ (void)n;
+ (void)txbuf;
+
+}
+
+/**
+ * @brief Stops any ongoing transmission.
+ * @note Stopping a transmission also suppresses the transmission callbacks.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @return The number of data frames not transmitted by the
+ * stopped transmit operation.
+ *
+ * @notapi
+ */
+size_t uart_lld_stop_send(UARTDriver *uartp) {
+
+ (void)uartp;
+
+ return 0;
+}
+
+/**
+ * @brief Starts a receive operation on the UART peripheral.
+ * @note The buffers are organized as uint8_t arrays for data sizes below
+ * or equal to 8 bits else it is organized as uint16_t arrays.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ * @param[in] n number of data frames to send
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) {
+
+ (void)uartp;
+ (void)n;
+ (void)rxbuf;
+
+}
+
+/**
+ * @brief Stops any ongoing receive operation.
+ * @note Stopping a receive operation also suppresses the receive callbacks.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ *
+ * @return The number of data frames not received by the
+ * stopped receive operation.
+ *
+ * @notapi
+ */
+size_t uart_lld_stop_receive(UARTDriver *uartp) {
+
+ (void)uartp;
+
+ return 0;
+}
+
+#endif /* HAL_USE_UART == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_uart_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_uart_lld.h
new file mode 100644
index 0000000..781a0ad
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_uart_lld.h
@@ -0,0 +1,202 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_uart_lld.h
+ * @brief PLATFORM UART subsystem low level driver header.
+ *
+ * @addtogroup UART
+ * @{
+ */
+
+#ifndef HAL_UART_LLD_H
+#define HAL_UART_LLD_H
+
+#if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief UART driver enable switch.
+ * @details If set to @p TRUE the support for UART1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_UART_USE_UART1) || defined(__DOXYGEN__)
+#define PLATFORM_UART_USE_UART1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief UART driver condition flags type.
+ */
+typedef uint32_t uartflags_t;
+
+/**
+ * @brief Type of structure representing an UART driver.
+ */
+typedef struct UARTDriver UARTDriver;
+
+/**
+ * @brief Generic UART notification callback type.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object
+ */
+typedef void (*uartcb_t)(UARTDriver *uartp);
+
+/**
+ * @brief Character received UART notification callback type.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object triggering the
+ * callback
+ * @param[in] c received character
+ */
+typedef void (*uartccb_t)(UARTDriver *uartp, uint16_t c);
+
+/**
+ * @brief Receive error UART notification callback type.
+ *
+ * @param[in] uartp pointer to the @p UARTDriver object triggering the
+ * callback
+ * @param[in] e receive error mask
+ */
+typedef void (*uartecb_t)(UARTDriver *uartp, uartflags_t e);
+
+/**
+ * @brief Driver configuration structure.
+ * @note Implementations may extend this structure to contain more,
+ * architecture dependent, fields.
+ */
+typedef struct {
+ /**
+ * @brief End of transmission buffer callback.
+ */
+ uartcb_t txend1_cb;
+ /**
+ * @brief Physical end of transmission callback.
+ */
+ uartcb_t txend2_cb;
+ /**
+ * @brief Receive buffer filled callback.
+ */
+ uartcb_t rxend_cb;
+ /**
+ * @brief Character received while out if the @p UART_RECEIVE state.
+ */
+ uartccb_t rxchar_cb;
+ /**
+ * @brief Receive error callback.
+ */
+ uartecb_t rxerr_cb;
+ /* End of the mandatory fields.*/
+} UARTConfig;
+
+/**
+ * @brief Structure representing an UART driver.
+ * @note Implementations may extend this structure to contain more,
+ * architecture dependent, fields.
+ */
+struct UARTDriver {
+ /**
+ * @brief Driver state.
+ */
+ uartstate_t state;
+ /**
+ * @brief Transmitter state.
+ */
+ uarttxstate_t txstate;
+ /**
+ * @brief Receiver state.
+ */
+ uartrxstate_t rxstate;
+ /**
+ * @brief Current configuration data.
+ */
+ const UARTConfig *config;
+#if (UART_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Synchronization flag for transmit operations.
+ */
+ bool early;
+ /**
+ * @brief Waiting thread on RX.
+ */
+ thread_reference_t threadrx;
+ /**
+ * @brief Waiting thread on TX.
+ */
+ thread_reference_t threadtx;
+#endif /* UART_USE_WAIT */
+#if (UART_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Mutex protecting the peripheral.
+ */
+ mutex_t mutex;
+#endif /* UART_USE_MUTUAL_EXCLUSION */
+#if defined(UART_DRIVER_EXT_FIELDS)
+ UART_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_UART_USE_UART1 == TRUE) && !defined(__DOXYGEN__)
+extern UARTDriver UARTD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void uart_lld_init(void);
+ void uart_lld_start(UARTDriver *uartp);
+ void uart_lld_stop(UARTDriver *uartp);
+ void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf);
+ size_t uart_lld_stop_send(UARTDriver *uartp);
+ void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf);
+ size_t uart_lld_stop_receive(UARTDriver *uartp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_UART == TRUE */
+
+#endif /* HAL_UART_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_usb_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_usb_lld.c
new file mode 100644
index 0000000..a361716
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_usb_lld.c
@@ -0,0 +1,390 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_usb_lld.c
+ * @brief PLATFORM USB subsystem low level driver source.
+ *
+ * @addtogroup USB
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief USB1 driver identifier.
+ */
+#if (PLATFORM_USB_USE_USB1 == TRUE) || defined(__DOXYGEN__)
+USBDriver USBD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/**
+ * @brief EP0 state.
+ * @note It is an union because IN and OUT endpoints are never used at the
+ * same time for EP0.
+ */
+static union {
+ /**
+ * @brief IN EP0 state.
+ */
+ USBInEndpointState in;
+ /**
+ * @brief OUT EP0 state.
+ */
+ USBOutEndpointState out;
+} ep0_state;
+
+/**
+ * @brief EP0 initialization structure.
+ */
+static const USBEndpointConfig ep0config = {
+ USB_EP_MODE_TYPE_CTRL,
+ _usb_ep0setup,
+ _usb_ep0in,
+ _usb_ep0out,
+ 0x40,
+ 0x40,
+ &ep0_state.in,
+ &ep0_state.out
+};
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers and threads. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level USB driver initialization.
+ *
+ * @notapi
+ */
+void usb_lld_init(void) {
+
+#if PLATFORM_USB_USE_USB1 == TRUE
+ /* Driver initialization.*/
+ usbObjectInit(&USBD1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the USB peripheral.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+void usb_lld_start(USBDriver *usbp) {
+
+ if (usbp->state == USB_STOP) {
+ /* Enables the peripheral.*/
+#if PLATFORM_USB_USE_USB1 == TRUE
+ if (&USBD1 == usbp) {
+
+ }
+#endif
+ }
+ /* Configures the peripheral.*/
+
+}
+
+/**
+ * @brief Deactivates the USB peripheral.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+void usb_lld_stop(USBDriver *usbp) {
+
+ if (usbp->state == USB_READY) {
+ /* Resets the peripheral.*/
+
+ /* Disables the peripheral.*/
+#if PLATFORM_USB_USE_USB1 == TRUE
+ if (&USBD1 == usbp) {
+
+ }
+#endif
+ }
+}
+
+/**
+ * @brief USB low level reset routine.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+void usb_lld_reset(USBDriver *usbp) {
+
+ /* Post reset initialization.*/
+
+ /* EP0 initialization.*/
+ usbp->epc[0] = &ep0config;
+ usb_lld_init_endpoint(usbp, 0);
+}
+
+/**
+ * @brief Sets the USB address.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+void usb_lld_set_address(USBDriver *usbp) {
+
+ (void)usbp;
+
+}
+
+/**
+ * @brief Enables an endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+ (void)ep;
+
+}
+
+/**
+ * @brief Disables all the active endpoints except the endpoint zero.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @notapi
+ */
+void usb_lld_disable_endpoints(USBDriver *usbp) {
+
+ (void)usbp;
+
+}
+
+/**
+ * @brief Returns the status of an OUT endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @return The endpoint status.
+ * @retval EP_STATUS_DISABLED The endpoint is not active.
+ * @retval EP_STATUS_STALLED The endpoint is stalled.
+ * @retval EP_STATUS_ACTIVE The endpoint is active.
+ *
+ * @notapi
+ */
+usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+ (void)ep;
+
+ return EP_STATUS_DISABLED;
+}
+
+/**
+ * @brief Returns the status of an IN endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @return The endpoint status.
+ * @retval EP_STATUS_DISABLED The endpoint is not active.
+ * @retval EP_STATUS_STALLED The endpoint is stalled.
+ * @retval EP_STATUS_ACTIVE The endpoint is active.
+ *
+ * @notapi
+ */
+usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+ (void)ep;
+
+ return EP_STATUS_DISABLED;
+}
+
+/**
+ * @brief Reads a setup packet from the dedicated packet buffer.
+ * @details This function must be invoked in the context of the @p setup_cb
+ * callback in order to read the received setup packet.
+ * @pre In order to use this function the endpoint must have been
+ * initialized as a control endpoint.
+ * @post The endpoint is ready to accept another packet.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[out] buf buffer where to copy the packet data
+ *
+ * @notapi
+ */
+void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) {
+
+ (void)usbp;
+ (void)ep;
+ (void)buf;
+
+}
+
+/**
+ * @brief Prepares for a receive operation.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+ (void)ep;
+
+}
+
+/**
+ * @brief Prepares for a transmit operation.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+ (void)ep;
+
+}
+
+/**
+ * @brief Starts a receive operation on an OUT endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+ (void)ep;
+
+}
+
+/**
+ * @brief Starts a transmit operation on an IN endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+ (void)ep;
+
+}
+
+/**
+ * @brief Brings an OUT endpoint in the stalled state.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+ (void)ep;
+
+}
+
+/**
+ * @brief Brings an IN endpoint in the stalled state.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+ (void)ep;
+
+}
+
+/**
+ * @brief Brings an OUT endpoint in the active state.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+ (void)ep;
+
+}
+
+/**
+ * @brief Brings an IN endpoint in the active state.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+ (void)ep;
+
+}
+
+#endif /* HAL_USE_USB == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_usb_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_usb_lld.h
new file mode 100644
index 0000000..276ce73
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_usb_lld.h
@@ -0,0 +1,383 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_usb_lld.h
+ * @brief PLATFORM USB subsystem low level driver header.
+ *
+ * @addtogroup USB
+ * @{
+ */
+
+#ifndef HAL_USB_LLD_H
+#define HAL_USB_LLD_H
+
+#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Maximum endpoint address.
+ */
+#define USB_MAX_ENDPOINTS 4
+
+/**
+ * @brief Status stage handling method.
+ */
+#define USB_EP0_STATUS_STAGE USB_EP0_STATUS_STAGE_SW
+
+/**
+ * @brief The address can be changed immediately upon packet reception.
+ */
+#define USB_SET_ADDRESS_MODE USB_LATE_SET_ADDRESS
+
+/**
+ * @brief Method for set address acknowledge.
+ */
+#define USB_SET_ADDRESS_ACK_HANDLING USB_SET_ADDRESS_ACK_SW
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name PLATFORM configuration options
+ * @{
+ */
+/**
+ * @brief USB driver enable switch.
+ * @details If set to @p TRUE the support for USB1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_USB_USE_USB1) || defined(__DOXYGEN__)
+#define PLATFORM_USB_USE_USB1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of an IN endpoint state structure.
+ */
+typedef struct {
+ /**
+ * @brief Requested transmit transfer size.
+ */
+ size_t txsize;
+ /**
+ * @brief Transmitted bytes so far.
+ */
+ size_t txcnt;
+ /**
+ * @brief Pointer to the transmission linear buffer.
+ */
+ const uint8_t *txbuf;
+#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Waiting thread.
+ */
+ thread_reference_t thread;
+#endif
+ /* End of the mandatory fields.*/
+} USBInEndpointState;
+
+/**
+ * @brief Type of an OUT endpoint state structure.
+ */
+typedef struct {
+ /**
+ * @brief Requested receive transfer size.
+ */
+ size_t rxsize;
+ /**
+ * @brief Received bytes so far.
+ */
+ size_t rxcnt;
+ /**
+ * @brief Pointer to the receive linear buffer.
+ */
+ uint8_t *rxbuf;
+#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Waiting thread.
+ */
+ thread_reference_t thread;
+#endif
+ /* End of the mandatory fields.*/
+} USBOutEndpointState;
+
+/**
+ * @brief Type of an USB endpoint configuration structure.
+ * @note Platform specific restrictions may apply to endpoints.
+ */
+typedef struct {
+ /**
+ * @brief Type and mode of the endpoint.
+ */
+ uint32_t ep_mode;
+ /**
+ * @brief Setup packet notification callback.
+ * @details This callback is invoked when a setup packet has been
+ * received.
+ * @post The application must immediately call @p usbReadPacket() in
+ * order to access the received packet.
+ * @note This field is only valid for @p USB_EP_MODE_TYPE_CTRL
+ * endpoints, it should be set to @p NULL for other endpoint
+ * types.
+ */
+ usbepcallback_t setup_cb;
+ /**
+ * @brief IN endpoint notification callback.
+ * @details This field must be set to @p NULL if the IN endpoint is not
+ * used.
+ */
+ usbepcallback_t in_cb;
+ /**
+ * @brief OUT endpoint notification callback.
+ * @details This field must be set to @p NULL if the OUT endpoint is not
+ * used.
+ */
+ usbepcallback_t out_cb;
+ /**
+ * @brief IN endpoint maximum packet size.
+ * @details This field must be set to zero if the IN endpoint is not
+ * used.
+ */
+ uint16_t in_maxsize;
+ /**
+ * @brief OUT endpoint maximum packet size.
+ * @details This field must be set to zero if the OUT endpoint is not
+ * used.
+ */
+ uint16_t out_maxsize;
+ /**
+ * @brief @p USBEndpointState associated to the IN endpoint.
+ * @details This structure maintains the state of the IN endpoint.
+ */
+ USBInEndpointState *in_state;
+ /**
+ * @brief @p USBEndpointState associated to the OUT endpoint.
+ * @details This structure maintains the state of the OUT endpoint.
+ */
+ USBOutEndpointState *out_state;
+ /* End of the mandatory fields.*/
+} USBEndpointConfig;
+
+/**
+ * @brief Type of an USB driver configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief USB events callback.
+ * @details This callback is invoked when an USB driver event is registered.
+ */
+ usbeventcb_t event_cb;
+ /**
+ * @brief Device GET_DESCRIPTOR request callback.
+ * @note This callback is mandatory and cannot be set to @p NULL.
+ */
+ usbgetdescriptor_t get_descriptor_cb;
+ /**
+ * @brief Requests hook callback.
+ * @details This hook allows to be notified of standard requests or to
+ * handle non standard requests.
+ */
+ usbreqhandler_t requests_hook_cb;
+ /**
+ * @brief Start Of Frame callback.
+ */
+ usbcallback_t sof_cb;
+ /* End of the mandatory fields.*/
+} USBConfig;
+
+/**
+ * @brief Structure representing an USB driver.
+ */
+struct USBDriver {
+ /**
+ * @brief Driver state.
+ */
+ usbstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const USBConfig *config;
+ /**
+ * @brief Bit map of the transmitting IN endpoints.
+ */
+ uint16_t transmitting;
+ /**
+ * @brief Bit map of the receiving OUT endpoints.
+ */
+ uint16_t receiving;
+ /**
+ * @brief Active endpoints configurations.
+ */
+ const USBEndpointConfig *epc[USB_MAX_ENDPOINTS + 1];
+ /**
+ * @brief Fields available to user, it can be used to associate an
+ * application-defined handler to an IN endpoint.
+ * @note The base index is one, the endpoint zero does not have a
+ * reserved element in this array.
+ */
+ void *in_params[USB_MAX_ENDPOINTS];
+ /**
+ * @brief Fields available to user, it can be used to associate an
+ * application-defined handler to an OUT endpoint.
+ * @note The base index is one, the endpoint zero does not have a
+ * reserved element in this array.
+ */
+ void *out_params[USB_MAX_ENDPOINTS];
+ /**
+ * @brief Endpoint 0 state.
+ */
+ usbep0state_t ep0state;
+ /**
+ * @brief Next position in the buffer to be transferred through endpoint 0.
+ */
+ uint8_t *ep0next;
+ /**
+ * @brief Number of bytes yet to be transferred through endpoint 0.
+ */
+ size_t ep0n;
+ /**
+ * @brief Endpoint 0 end transaction callback.
+ */
+ usbcallback_t ep0endcb;
+ /**
+ * @brief Setup packet buffer.
+ */
+ uint8_t setup[8];
+ /**
+ * @brief Current USB device status.
+ */
+ uint16_t status;
+ /**
+ * @brief Assigned USB address.
+ */
+ uint8_t address;
+ /**
+ * @brief Current USB device configuration.
+ */
+ uint8_t configuration;
+ /**
+ * @brief State of the driver when a suspend happened.
+ */
+ usbstate_t saved_state;
+#if defined(USB_DRIVER_EXT_FIELDS)
+ USB_DRIVER_EXT_FIELDS
+#endif
+ /* End of the mandatory fields.*/
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Returns the current frame number.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @return The current frame number.
+ *
+ * @notapi
+ */
+#define usb_lld_get_frame_number(usbp) 0
+
+/**
+ * @brief Returns the exact size of a receive transaction.
+ * @details The received size can be different from the size specified in
+ * @p usbStartReceiveI() because the last packet could have a size
+ * different from the expected one.
+ * @pre The OUT endpoint must have been configured in transaction mode
+ * in order to use this function.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @return Received data size.
+ *
+ * @notapi
+ */
+#define usb_lld_get_transaction_size(usbp, ep) \
+ ((usbp)->epc[ep]->out_state->rxcnt)
+
+/**
+ * @brief Connects the USB device.
+ *
+ * @api
+ */
+#define usb_lld_connect_bus(usbp)
+
+/**
+ * @brief Disconnect the USB device.
+ *
+ * @api
+ */
+#define usb_lld_disconnect_bus(usbp)
+
+/**
+ * @brief Start of host wake-up procedure.
+ *
+ * @notapi
+ */
+#define usb_lld_wakeup_host(usbp)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_USB_USE_USB1 == TRUE) && !defined(__DOXYGEN__)
+extern USBDriver USBD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void usb_lld_init(void);
+ void usb_lld_start(USBDriver *usbp);
+ void usb_lld_stop(USBDriver *usbp);
+ void usb_lld_reset(USBDriver *usbp);
+ void usb_lld_set_address(USBDriver *usbp);
+ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep);
+ void usb_lld_disable_endpoints(USBDriver *usbp);
+ usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep);
+ usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep);
+ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf);
+ void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep);
+ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep);
+ void usb_lld_start_out(USBDriver *usbp, usbep_t ep);
+ void usb_lld_start_in(USBDriver *usbp, usbep_t ep);
+ void usb_lld_stall_out(USBDriver *usbp, usbep_t ep);
+ void usb_lld_stall_in(USBDriver *usbp, usbep_t ep);
+ void usb_lld_clear_out(USBDriver *usbp, usbep_t ep);
+ void usb_lld_clear_in(USBDriver *usbp, usbep_t ep);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_USB == TRUE */
+
+#endif /* HAL_USB_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_wdg_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_wdg_lld.c
new file mode 100644
index 0000000..0ec0e2d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_wdg_lld.c
@@ -0,0 +1,104 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_wdg_lld.c
+ * @brief WDG Driver subsystem low level driver source template.
+ *
+ * @addtogroup WDG
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+#if (PLATFORM_WDG_USE_WDG1 == TRUE) || defined(__DOXYGEN__)
+WDGDriver WDGD1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level WDG driver initialization.
+ *
+ * @notapi
+ */
+void wdg_lld_init(void) {
+
+}
+
+/**
+ * @brief Configures and activates the WDG peripheral.
+ *
+ * @param[in] wdgp pointer to the @p WDGDriver object
+ *
+ * @notapi
+ */
+void wdg_lld_start(WDGDriver *wdgp) {
+
+ (void)wdgp;
+}
+
+/**
+ * @brief Deactivates the WDG peripheral.
+ *
+ * @param[in] wdgp pointer to the @p WDGDriver object
+ *
+ * @notapi
+ */
+void wdg_lld_stop(WDGDriver *wdgp) {
+
+ (void)wdgp;
+}
+
+/**
+ * @brief Reloads WDG's counter.
+ *
+ * @param[in] wdgp pointer to the @p WDGDriver object
+ *
+ * @notapi
+ */
+void wdg_lld_reset(WDGDriver * wdgp) {
+
+ (void)wdgp;
+}
+
+#endif /* HAL_USE_WDG */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_wdg_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_wdg_lld.h
new file mode 100644
index 0000000..5db2647
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_wdg_lld.h
@@ -0,0 +1,113 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_wdg_lld.h
+ * @brief WDG Driver subsystem low level driver header template.
+ *
+ * @addtogroup WDG
+ * @{
+ */
+
+#ifndef HAL_WDG_LLD_H
+#define HAL_WDG_LLD_H
+
+#if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief WDG1 driver enable switch.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_WDG_USE_WDG1) || defined(__DOXYGEN__)
+#define PLATFORM_WDG_USE_WDG1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a structure representing an WDG driver.
+ */
+typedef struct WDGDriver WDGDriver;
+
+/**
+ * @brief Driver configuration structure.
+ * @note It could be empty on some architectures.
+ */
+typedef struct {
+} WDGConfig;
+
+/**
+ * @brief Structure representing an WDG driver.
+ */
+struct WDGDriver {
+ /**
+ * @brief Driver state.
+ */
+ wdgstate_t state;
+ /**
+ * @brief Current configuration data.
+ */
+ const WDGConfig *config;
+ /* End of the mandatory fields.*/
+};
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_WDG_USE_WDG1 == TRUE) && !defined(__DOXYGEN__)
+extern WDGDriver WDGD1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void wdg_lld_init(void);
+ void wdg_lld_start(WDGDriver *wdgp);
+ void wdg_lld_stop(WDGDriver *wdgp);
+ void wdg_lld_reset(WDGDriver *wdgp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_WDG == TRUE */
+
+#endif /* HAL_WDG_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_wspi_lld.c b/ChibiOS_20.3.2/os/hal/templates/hal_wspi_lld.c
new file mode 100644
index 0000000..233caa6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_wspi_lld.c
@@ -0,0 +1,208 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_wspi_lld.c
+ * @brief PLATFORM WSPI subsystem low level driver source.
+ *
+ * @addtogroup WSPI
+ * @{
+ */
+
+#include "hal.h"
+
+#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+
+/** @brief WSPID1 driver identifier.*/
+#if (PLATFORM_WSPI_USE_WSPI1 == TRUE) || defined(__DOXYGEN__)
+WSPIDriver WSPID1;
+#endif
+
+/*===========================================================================*/
+/* Driver local variables and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level WSPI driver initialization.
+ *
+ * @notapi
+ */
+void wspi_lld_init(void) {
+
+#if PLATFORM_WSPI_USE_WSPI1
+ wspiObjectInit(&WSPID1);
+#endif
+}
+
+/**
+ * @brief Configures and activates the WSPI peripheral.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @notapi
+ */
+void wspi_lld_start(WSPIDriver *wspip) {
+
+ /* If in stopped state then full initialization.*/
+ if (wspip->state == WSPI_STOP) {
+#if PLATFORM_WSPI_USE_WSPI1
+ if (&WSPID1 == wspip) {
+ }
+#endif
+
+ /* Common initializations.*/
+ }
+
+ /* WSPI setup and enable.*/
+}
+
+/**
+ * @brief Deactivates the WSPI peripheral.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @notapi
+ */
+void wspi_lld_stop(WSPIDriver *wspip) {
+
+ /* If in ready state then disables WSPI.*/
+ if (wspip->state == WSPI_READY) {
+
+ /* WSPI disable.*/
+
+ /* Stopping involved clocks.*/
+#if PLATFORM_WSPI_USE_WSPI1
+ if (&WSPID1 == wspip) {
+ }
+#endif
+ }
+}
+
+/**
+ * @brief Sends a command without data phase.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ *
+ * @notapi
+ */
+void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp) {
+
+ (void)wspip;
+ (void)cmdp;
+}
+
+/**
+ * @brief Sends a command with data over the WSPI bus.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[in] n number of bytes to send
+ * @param[in] txbuf the pointer to the transmit buffer
+ *
+ * @notapi
+ */
+void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, const uint8_t *txbuf) {
+
+ (void)wspip;
+ (void)cmdp;
+ (void)n;
+ (void)txbuf;
+}
+
+/**
+ * @brief Sends a command then receives data over the WSPI bus.
+ * @post At the end of the operation the configured callback is invoked.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[in] n number of bytes to send
+ * @param[out] rxbuf the pointer to the receive buffer
+ *
+ * @notapi
+ */
+void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, uint8_t *rxbuf) {
+
+ (void)wspip;
+ (void)cmdp;
+ (void)n;
+ (void)rxbuf;
+}
+
+#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Maps in memory space a WSPI flash device.
+ * @pre The memory flash device must be initialized appropriately
+ * before mapping it in memory space.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ * @param[in] cmdp pointer to the command descriptor
+ * @param[out] addrp pointer to the memory start address of the mapped
+ * flash or @p NULL
+ *
+ * @notapi
+ */
+void wspi_lld_map_flash(WSPIDriver *wspip,
+ const wspi_command_t *cmdp,
+ uint8_t **addrp) {
+
+ (void)wspip;
+ (void)cmdp;
+ (void)addrp;
+}
+
+/**
+ * @brief Unmaps from memory space a WSPI flash device.
+ * @post The memory flash device must be re-initialized for normal
+ * commands exchange.
+ *
+ * @param[in] wspip pointer to the @p WSPIDriver object
+ *
+ * @notapi
+ */
+void wspi_lld_unmap_flash(WSPIDriver *wspip) {
+
+ (void)wspip;
+}
+#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */
+
+#endif /* HAL_USE_WSPI */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/hal_wspi_lld.h b/ChibiOS_20.3.2/os/hal/templates/hal_wspi_lld.h
new file mode 100644
index 0000000..6df16d0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/hal_wspi_lld.h
@@ -0,0 +1,119 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file hal_wspi_lld.h
+ * @brief PLATFORM WSPI subsystem low level driver header.
+ *
+ * @addtogroup WSPI
+ * @{
+ */
+
+#ifndef HAL_WSPI_LLD_H
+#define HAL_WSPI_LLD_H
+
+#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver constants. */
+/*===========================================================================*/
+
+/**
+ * @name WSPI implementation capabilities
+ * @{
+ */
+#define WSPI_SUPPORTS_MEMMAP TRUE
+#define WSPI_DEFAULT_CFG_MASKS TRUE
+/** @} */
+
+/*===========================================================================*/
+/* Driver pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief WSPID1 driver enable switch.
+ * @details If set to @p TRUE the support for WSPID1 is included.
+ * @note The default is @p FALSE.
+ */
+#if !defined(PLATFORM_WSPI_USE_WSPI1) || defined(__DOXYGEN__)
+#define PLATFORM_WSPI_USE_WSPI1 FALSE
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level fields of the WSPI driver structure.
+ */
+#define wspi_lld_driver_fields \
+ /* Dummy field, it is not needed.*/ \
+ uint32_t dummy
+
+/**
+ * @brief Low level fields of the WSPI configuration structure.
+ */
+#define wspi_lld_config_fields \
+ /* Dummy configuration, it is not needed.*/ \
+ uint32_t dummy
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if (PLATFORM_WSPI_USE_WSPI1 == TRUE) && !defined(__DOXYGEN__)
+extern WSPIDriver WSPID1;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void wspi_lld_init(void);
+ void wspi_lld_start(WSPIDriver *wspip);
+ void wspi_lld_stop(WSPIDriver *wspip);
+ void wspi_lld_command(WSPIDriver *wspip, const wspi_command_t *cmdp);
+ void wspi_lld_send(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, const uint8_t *txbuf);
+ void wspi_lld_receive(WSPIDriver *wspip, const wspi_command_t *cmdp,
+ size_t n, uint8_t *rxbuf);
+#if WSPI_SUPPORTS_MEMMAP == TRUE
+ void wspi_lld_map_flash(WSPIDriver *wspip,
+ const wspi_command_t *cmdp,
+ uint8_t **addrp);
+ void wspi_lld_unmap_flash(WSPIDriver *wspip);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_USE_WSPI */
+
+#endif /* HAL_WSPI_LLD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/halconf.h b/ChibiOS_20.3.2/os/hal/templates/halconf.h
new file mode 100644
index 0000000..8ffc930
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/halconf.h
@@ -0,0 +1,531 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/halconf.h
+ * @brief HAL configuration header.
+ * @details HAL configuration file, this file allows to enable or disable the
+ * various device drivers from your application. You may also use
+ * this file in order to override the device drivers default settings.
+ *
+ * @addtogroup HAL_CONF
+ * @{
+ */
+
+#ifndef HALCONF_H
+#define HALCONF_H
+
+#define _CHIBIOS_HAL_CONF_
+#define _CHIBIOS_HAL_CONF_VER_7_1_
+
+#include "mcuconf.h"
+
+/**
+ * @brief Enables the PAL subsystem.
+ */
+#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
+#define HAL_USE_PAL TRUE
+#endif
+
+/**
+ * @brief Enables the ADC subsystem.
+ */
+#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
+#define HAL_USE_ADC TRUE
+#endif
+
+/**
+ * @brief Enables the CAN subsystem.
+ */
+#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
+#define HAL_USE_CAN TRUE
+#endif
+
+/**
+ * @brief Enables the cryptographic subsystem.
+ */
+#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__)
+#define HAL_USE_CRY TRUE
+#endif
+
+/**
+ * @brief Enables the DAC subsystem.
+ */
+#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
+#define HAL_USE_DAC TRUE
+#endif
+
+/**
+ * @brief Enables the EFlash subsystem.
+ */
+#if !defined(HAL_USE_EFL) || defined(__DOXYGEN__)
+#define HAL_USE_EFL TRUE
+#endif
+
+/**
+ * @brief Enables the GPT subsystem.
+ */
+#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
+#define HAL_USE_GPT TRUE
+#endif
+
+/**
+ * @brief Enables the I2C subsystem.
+ */
+#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
+#define HAL_USE_I2C TRUE
+#endif
+
+/**
+ * @brief Enables the I2S subsystem.
+ */
+#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
+#define HAL_USE_I2S TRUE
+#endif
+
+/**
+ * @brief Enables the ICU subsystem.
+ */
+#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
+#define HAL_USE_ICU TRUE
+#endif
+
+/**
+ * @brief Enables the MAC subsystem.
+ */
+#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
+#define HAL_USE_MAC TRUE
+#endif
+
+/**
+ * @brief Enables the MMC_SPI subsystem.
+ */
+#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_MMC_SPI TRUE
+#endif
+
+/**
+ * @brief Enables the PWM subsystem.
+ */
+#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
+#define HAL_USE_PWM TRUE
+#endif
+
+/**
+ * @brief Enables the RTC subsystem.
+ */
+#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
+#define HAL_USE_RTC TRUE
+#endif
+
+/**
+ * @brief Enables the SDC subsystem.
+ */
+#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
+#define HAL_USE_SDC TRUE
+#endif
+
+/**
+ * @brief Enables the SERIAL subsystem.
+ */
+#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL TRUE
+#endif
+
+/**
+ * @brief Enables the SERIAL over USB subsystem.
+ */
+#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL_USB TRUE
+#endif
+
+/**
+ * @brief Enables the SIO subsystem.
+ */
+#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__)
+#define HAL_USE_SIO TRUE
+#endif
+
+/**
+ * @brief Enables the SPI subsystem.
+ */
+#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_SPI TRUE
+#endif
+
+/**
+ * @brief Enables the TRNG subsystem.
+ */
+#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__)
+#define HAL_USE_TRNG TRUE
+#endif
+
+/**
+ * @brief Enables the UART subsystem.
+ */
+#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
+#define HAL_USE_UART TRUE
+#endif
+
+/**
+ * @brief Enables the USB subsystem.
+ */
+#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
+#define HAL_USE_USB TRUE
+#endif
+
+/**
+ * @brief Enables the WDG subsystem.
+ */
+#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
+#define HAL_USE_WDG TRUE
+#endif
+
+/**
+ * @brief Enables the WSPI subsystem.
+ */
+#if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__)
+#define HAL_USE_WSPI TRUE
+#endif
+
+/*===========================================================================*/
+/* PAL driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__)
+#define PAL_USE_CALLBACKS FALSE
+#endif
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__)
+#define PAL_USE_WAIT FALSE
+#endif
+
+/*===========================================================================*/
+/* ADC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
+#define ADC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define ADC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* CAN driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Sleep mode related APIs inclusion switch.
+ */
+#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
+#define CAN_USE_SLEEP_MODE TRUE
+#endif
+
+/**
+ * @brief Enforces the driver to use direct callbacks rather than OSAL events.
+ */
+#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__)
+#define CAN_ENFORCE_USE_CALLBACKS FALSE
+#endif
+
+/*===========================================================================*/
+/* CRY driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the SW fall-back of the cryptographic driver.
+ * @details When enabled, this option, activates a fall-back software
+ * implementation for algorithms not supported by the underlying
+ * hardware.
+ * @note Fall-back implementations may not be present for all algorithms.
+ */
+#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__)
+#define HAL_CRY_USE_FALLBACK FALSE
+#endif
+
+/**
+ * @brief Makes the driver forcibly use the fall-back implementations.
+ */
+#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__)
+#define HAL_CRY_ENFORCE_FALLBACK FALSE
+#endif
+
+/*===========================================================================*/
+/* DAC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__)
+#define DAC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define DAC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* I2C driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the mutual exclusion APIs on the I2C bus.
+ */
+#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define I2C_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* MAC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the zero-copy API.
+ */
+#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
+#define MAC_USE_ZERO_COPY TRUE
+#endif
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
+#define MAC_USE_EVENTS TRUE
+#endif
+
+/*===========================================================================*/
+/* MMC_SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ * This option is recommended also if the SPI driver does not
+ * use a DMA channel and heavily loads the CPU.
+ */
+#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
+#define MMC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SDC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of initialization attempts before rejecting the card.
+ * @note Attempts are performed at 10mS intervals.
+ */
+#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
+#define SDC_INIT_RETRY 100
+#endif
+
+/**
+ * @brief Include support for MMC cards.
+ * @note MMC support is not yet implemented so this option must be kept
+ * at @p FALSE.
+ */
+#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
+#define SDC_MMC_SUPPORT TRUE
+#endif
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ */
+#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
+#define SDC_NICE_WAITING TRUE
+#endif
+
+/**
+ * @brief OCR initialization constant for V20 cards.
+ */
+#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__)
+#define SDC_INIT_OCR_V20 0x50FF8000U
+#endif
+
+/**
+ * @brief OCR initialization constant for non-V20 cards.
+ */
+#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__)
+#define SDC_INIT_OCR 0x80100000U
+#endif
+
+/*===========================================================================*/
+/* SERIAL driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, this is the baud rate selected for the
+ * default configuration.
+ */
+#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
+#define SERIAL_DEFAULT_BITRATE 38400
+#endif
+
+/**
+ * @brief Serial buffers size.
+ * @details Configuration parameter, you can change the depth of the queue
+ * buffers depending on the requirements of your application.
+ * @note The default is 16 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_BUFFERS_SIZE 16
+#endif
+
+/*===========================================================================*/
+/* SERIAL_USB driver related setting. */
+/*===========================================================================*/
+
+/**
+ * @brief Serial over USB buffers size.
+ * @details Configuration parameter, the buffer size must be a multiple of
+ * the USB data endpoint maximum packet size.
+ * @note The default is 256 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_SIZE 256
+#endif
+
+/**
+ * @brief Serial over USB number of buffers.
+ * @note The default is 2 buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_NUMBER 2
+#endif
+
+/*===========================================================================*/
+/* SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
+#define SPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables circular transfers APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__)
+#define SPI_USE_CIRCULAR FALSE
+#endif
+
+/**
+ * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define SPI_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/**
+ * @brief Handling method for SPI CS line.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__)
+#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD
+#endif
+
+/*===========================================================================*/
+/* UART driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__)
+#define UART_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define UART_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* USB driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
+#define USB_USE_WAIT TRUE
+#endif
+
+/*===========================================================================*/
+/* WSPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__)
+#define WSPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define WSPI_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+#endif /* HALCONF_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/mcuconf.h b/ChibiOS_20.3.2/os/hal/templates/mcuconf.h
new file mode 100644
index 0000000..d020f9f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/mcuconf.h
@@ -0,0 +1,30 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef MCUCONF_H
+#define MCUCONF_H
+
+/*
+ * Platform drivers configuration.
+ * The following settings override the default settings present in
+ * the various device driver implementation headers.
+ * Note that the settings for each driver only have effect if the whole
+ * driver is enabled in halconf.h.
+ */
+
+#define PLATFORM_MCUCONF
+
+#endif /* MCUCONF_H */
diff --git a/ChibiOS_20.3.2/os/hal/templates/osal/osal.c b/ChibiOS_20.3.2/os/hal/templates/osal/osal.c
new file mode 100644
index 0000000..5ec0bae
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/osal/osal.c
@@ -0,0 +1,411 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file osal.c
+ * @brief OSAL module code.
+ *
+ * @addtogroup OSAL
+ * @{
+ */
+
+#include "osal.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief Pointer to a halt error message.
+ * @note The message is meant to be retrieved by the debugger after the
+ * system halt caused by an unexpected error.
+ */
+const char *osal_halt_msg;
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief OSAL module initialization.
+ *
+ * @api
+ */
+void osalInit(void) {
+
+}
+
+/**
+ * @brief System halt with error message.
+ *
+ * @param[in] reason the halt message pointer
+ *
+ * @api
+ */
+#if !defined(__DOXYGEN__)
+__attribute__((weak, noreturn))
+#endif
+void osalSysHalt(const char *reason) {
+
+ osalSysDisable();
+ osal_halt_msg = reason;
+ while (true) {
+ }
+}
+
+/**
+ * @brief Polled delay.
+ * @note The real delay is always few cycles in excess of the specified
+ * value.
+ *
+ * @param[in] cycles number of cycles
+ *
+ * @xclass
+ */
+void osalSysPolledDelayX(rtcnt_t cycles) {
+
+ (void)cycles;
+}
+
+/**
+ * @brief System timer handler.
+ * @details The handler is used for scheduling and Virtual Timers management.
+ *
+ * @iclass
+ */
+void osalOsTimerHandlerI(void) {
+
+ osalDbgCheckClassI();
+}
+
+/**
+ * @brief Checks if a reschedule is required and performs it.
+ * @note I-Class functions invoked from thread context must not reschedule
+ * by themselves, an explicit reschedule using this function is
+ * required in this scenario.
+ * @note Not implemented in this simplified OSAL.
+ *
+ * @sclass
+ */
+void osalOsRescheduleS(void) {
+
+}
+
+/**
+ * @brief Current system time.
+ * @details Returns the number of system ticks since the @p osalInit()
+ * invocation.
+ * @note The counter can reach its maximum and then restart from zero.
+ * @note This function can be called from any context but its atomicity
+ * is not guaranteed on architectures whose word size is less than
+ * @p systime_t size.
+ *
+ * @return The system time in ticks.
+ *
+ * @xclass
+ */
+systime_t osalOsGetSystemTimeX(void) {
+
+ return (systime_t)0;
+}
+
+/**
+ * @brief Suspends the invoking thread for the specified time.
+ *
+ * @param[in] time the delay in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE is allowed but interpreted as a
+ * normal time specification.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ *
+ * @sclass
+ */
+void osalThreadSleepS(sysinterval_t time) {
+
+ (void)time;
+}
+
+/**
+ * @brief Suspends the invoking thread for the specified time.
+ *
+ * @param[in] time the delay in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE is allowed but interpreted as a
+ * normal time specification.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ *
+ * @api
+ */
+void osalThreadSleep(sysinterval_t time) {
+
+ (void)time;
+}
+
+/**
+ * @brief Sends the current thread sleeping and sets a reference variable.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @return The wake up message.
+ *
+ * @sclass
+ */
+msg_t osalThreadSuspendS(thread_reference_t *trp) {
+
+ osalDbgCheck(trp != NULL);
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Sends the current thread sleeping and sets a reference variable.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] timeout the timeout in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE the thread enters an infinite sleep
+ * state.
+ * - @a TIME_IMMEDIATE the thread is not enqueued and
+ * the function returns @p MSG_TIMEOUT as if a timeout
+ * occurred.
+ * .
+ * @return The wake up message.
+ * @retval MSG_TIMEOUT if the operation timed out.
+ *
+ * @sclass
+ */
+msg_t osalThreadSuspendTimeoutS(thread_reference_t *trp, sysinterval_t timeout) {
+
+ osalDbgCheck(trp != NULL);
+
+ (void)timeout;
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Wakes up a thread waiting on a thread reference object.
+ * @note This function must not reschedule because it can be called from
+ * ISR context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void osalThreadResumeI(thread_reference_t *trp, msg_t msg) {
+
+ osalDbgCheck(trp != NULL);
+
+ (void)msg;
+}
+
+/**
+ * @brief Wakes up a thread waiting on a thread reference object.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void osalThreadResumeS(thread_reference_t *trp, msg_t msg) {
+
+ osalDbgCheck(trp != NULL);
+
+ (void)msg;
+}
+
+/**
+ * @brief Enqueues the caller thread.
+ * @details The caller thread is enqueued and put to sleep until it is
+ * dequeued or the specified timeouts expires.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] timeout the timeout in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE the thread enters an infinite sleep
+ * state.
+ * - @a TIME_IMMEDIATE the thread is not enqueued and
+ * the function returns @p MSG_TIMEOUT as if a timeout
+ * occurred.
+ * .
+ * @return The message from @p osalQueueWakeupOneI() or
+ * @p osalQueueWakeupAllI() functions.
+ * @retval MSG_TIMEOUT if the thread has not been dequeued within the
+ * specified timeout or if the function has been
+ * invoked with @p TIME_IMMEDIATE as timeout
+ * specification.
+ *
+ * @sclass
+ */
+msg_t osalThreadEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout) {
+
+ osalDbgCheck(tqp != NULL);
+
+ (void)timeout;
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Dequeues and wakes up one thread from the queue, if any.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg) {
+
+ osalDbgCheck(tqp != NULL);
+
+ (void)msg;
+}
+
+/**
+ * @brief Dequeues and wakes up all threads from the queue.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg) {
+
+ (void)tqp;
+ (void)msg;
+}
+
+/**
+ * @brief Add flags to an event source object.
+ *
+ * @param[in] esp pointer to the event flags object
+ * @param[in] flags flags to be ORed to the flags mask
+ *
+ * @iclass
+ */
+void osalEventBroadcastFlagsI(event_source_t *esp, eventflags_t flags) {
+
+ osalDbgCheck(esp != NULL);
+
+ esp->flags |= flags;
+ if (esp->cb != NULL) {
+ esp->cb(esp);
+ }
+}
+
+/**
+ * @brief Add flags to an event source object.
+ *
+ * @param[in] esp pointer to the event flags object
+ * @param[in] flags flags to be ORed to the flags mask
+ *
+ * @iclass
+ */
+void osalEventBroadcastFlags(event_source_t *esp, eventflags_t flags) {
+
+ osalDbgCheck(esp != NULL);
+
+ osalSysLock();
+ osalEventBroadcastFlagsI(esp, flags);
+ osalSysUnlock();
+}
+
+/**
+ * @brief Event callback setup.
+ * @note The callback is invoked from ISR context and can
+ * only invoke I-Class functions. The callback is meant
+ * to wakeup the task that will handle the event by
+ * calling @p osalEventGetAndClearFlagsI().
+ * @note This function is not part of the OSAL API and is provided
+ * exclusively as an example and for convenience.
+ *
+ * @param[in] esp pointer to the event flags object
+ * @param[in] cb pointer to the callback function
+ * @param[in] param parameter to be passed to the callback function
+ *
+ * @api
+ */
+void osalEventSetCallback(event_source_t *esp,
+ eventcallback_t cb,
+ void *param) {
+
+ osalDbgCheck(esp != NULL);
+
+ esp->cb = cb;
+ esp->param = param;
+}
+
+/**
+ * @brief Locks the specified mutex.
+ * @post The mutex is locked and inserted in the per-thread stack of owned
+ * mutexes.
+ *
+ * @param[in,out] mp pointer to the @p mutex_t object
+ *
+ * @api
+ */
+void osalMutexLock(mutex_t *mp) {
+
+ osalDbgCheck(mp != NULL);
+
+ *mp = 1;
+}
+
+/**
+ * @brief Unlocks the specified mutex.
+ * @note The HAL guarantees to release mutex in reverse lock order. The
+ * mutex being unlocked is guaranteed to be the last locked mutex
+ * by the invoking thread.
+ * The implementation can rely on this behavior and eventually
+ * ignore the @p mp parameter which is supplied in order to support
+ * those OSes not supporting a stack of the owned mutexes.
+ *
+ * @param[in,out] mp pointer to the @p mutex_t object
+ *
+ * @api
+ */
+void osalMutexUnlock(mutex_t *mp) {
+
+ osalDbgCheck(mp != NULL);
+
+ *mp = 0;
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/osal/osal.h b/ChibiOS_20.3.2/os/hal/templates/osal/osal.h
new file mode 100644
index 0000000..5c38c21
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/osal/osal.h
@@ -0,0 +1,690 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file osal.h
+ * @brief OSAL module header.
+ *
+ * @addtogroup OSAL
+ * @{
+ */
+
+#ifndef OSAL_H
+#define OSAL_H
+
+#include
+#include
+#include
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Common constants
+ * @{
+ */
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+
+#define OSAL_SUCCESS false
+#define OSAL_FAILED true
+/** @} */
+
+/**
+ * @name Messages
+ * @{
+ */
+#define MSG_OK (msg_t)0
+#define MSG_TIMEOUT (msg_t)-1
+#define MSG_RESET (msg_t)-2
+/** @} */
+
+/**
+ * @name Special time constants
+ * @{
+ */
+#define TIME_IMMEDIATE ((sysinterval_t)0)
+#define TIME_INFINITE ((sysinterval_t)-1)
+/** @} */
+
+/**
+ * @name Systick modes.
+ * @{
+ */
+#define OSAL_ST_MODE_NONE 0
+#define OSAL_ST_MODE_PERIODIC 1
+#define OSAL_ST_MODE_FREERUNNING 2
+/** @} */
+
+/**
+ * @name Systick parameters.
+ * @{
+ */
+/**
+ * @brief Size in bits of the @p systick_t type.
+ */
+#define OSAL_ST_RESOLUTION 32
+
+/**
+ * @brief Required systick frequency or resolution.
+ */
+#define OSAL_ST_FREQUENCY 1000
+
+/**
+ * @brief Systick mode required by the underlying OS.
+ */
+#define OSAL_ST_MODE OSAL_ST_MODE_PERIODIC
+/** @} */
+
+/**
+ * @name IRQ-related constants
+ * @{
+ */
+/**
+ * @brief Total priority levels.
+ * @brief Implementation not mandatory.
+ */
+#define OSAL_IRQ_PRIORITY_LEVELS 16U
+
+/**
+ * @brief Highest IRQ priority for HAL drivers.
+ * @brief Implementation not mandatory.
+ */
+#define OSAL_IRQ_MAXIMUM_PRIORITY 0U
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables OSAL assertions.
+ */
+#if !defined(OSAL_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)
+#define OSAL_DBG_ENABLE_ASSERTS FALSE
+#endif
+
+/**
+ * @brief Enables OSAL functions parameters checks.
+ */
+#if !defined(OSAL_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)
+#define OSAL_DBG_ENABLE_CHECKS FALSE
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if !(OSAL_ST_MODE == OSAL_ST_MODE_NONE) && \
+ !(OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) && \
+ !(OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING)
+#error "invalid OSAL_ST_MODE setting in osal.h"
+#endif
+
+#if (OSAL_ST_RESOLUTION != 16) && (OSAL_ST_RESOLUTION != 32)
+#error "invalid OSAL_ST_RESOLUTION, must be 16 or 32"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a system status word.
+ */
+typedef uint32_t syssts_t;
+
+/**
+ * @brief Type of a message.
+ */
+typedef int32_t msg_t;
+
+/**
+ * @brief Type of system time counter.
+ */
+typedef uint32_t systime_t;
+
+/**
+ * @brief Type of system time interval.
+ */
+typedef uint32_t sysinterval_t;
+
+/**
+ * @brief Type of realtime counter.
+ */
+typedef uint32_t rtcnt_t;
+
+/**
+ * @brief Type of a thread reference.
+ */
+typedef void * thread_reference_t;
+
+/**
+ * @brief Type of an event flags mask.
+ */
+typedef uint32_t eventflags_t;
+
+/**
+ * @brief Type of an event flags object.
+ * @note The content of this structure is not part of the API and should
+ * not be relied upon. Implementers may define this structure in
+ * an entirely different way.
+ * @note Retrieval and clearing of the flags are not defined in this
+ * API and are implementation-dependent.
+ */
+typedef struct event_source event_source_t;
+
+/**
+ * @brief Type of an event source callback.
+ * @note This type is not part of the OSAL API and is provided
+ * exclusively as an example and for convenience.
+ */
+typedef void (*eventcallback_t)(event_source_t *esp);
+
+/**
+ * @brief Events source object.
+ * @note The content of this structure is not part of the API and should
+ * not be relied upon. Implementers may define this structure in
+ * an entirely different way.
+ * @note Retrieval and clearing of the flags are not defined in this
+ * API and are implementation-dependent.
+ */
+struct event_source {
+ volatile eventflags_t flags; /**< @brief Stored event flags. */
+ eventcallback_t cb; /**< @brief Event source callback. */
+ void *param; /**< @brief User defined field. */
+};
+
+/**
+ * @brief Type of a mutex.
+ * @note If the OS does not support mutexes or there is no OS then them
+ * mechanism can be simulated.
+ */
+typedef uint32_t mutex_t;
+
+/**
+ * @brief Type of a thread queue.
+ * @details A thread queue is a queue of sleeping threads, queued threads
+ * can be dequeued one at time or all together.
+ * @note If the OSAL is implemented on a bare metal machine without RTOS
+ * then the queue can be implemented as a single thread reference.
+ */
+typedef struct {
+ thread_reference_t tr;
+} threads_queue_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @name Debug related macros
+ * @{
+ */
+/**
+ * @brief Condition assertion.
+ * @details If the condition check fails then the OSAL panics with a
+ * message and halts.
+ * @note The condition is tested only if the @p OSAL_ENABLE_ASSERTIONS
+ * switch is enabled.
+ * @note The remark string is not currently used except for putting a
+ * comment in the code about the assertion.
+ *
+ * @param[in] c the condition to be verified to be true
+ * @param[in] remark a remark string
+ *
+ * @api
+ */
+#define osalDbgAssert(c, remark) do { \
+ /*lint -save -e506 -e774 [2.1, 14.3] Can be a constant by design.*/ \
+ if (OSAL_DBG_ENABLE_ASSERTS != FALSE) { \
+ if (!(c)) { \
+ /*lint -restore*/ \
+ osalSysHalt(__func__); \
+ } \
+ } \
+} while (false)
+
+/**
+ * @brief Function parameters check.
+ * @details If the condition check fails then the OSAL panics and halts.
+ * @note The condition is tested only if the @p OSAL_ENABLE_CHECKS switch
+ * is enabled.
+ *
+ * @param[in] c the condition to be verified to be true
+ *
+ * @api
+ */
+#define osalDbgCheck(c) do { \
+ /*lint -save -e506 -e774 [2.1, 14.3] Can be a constant by design.*/ \
+ if (OSAL_DBG_ENABLE_CHECKS != FALSE) { \
+ if (!(c)) { \
+ /*lint -restore*/ \
+ osalSysHalt(__func__); \
+ } \
+ } \
+} while (false)
+
+/**
+ * @brief I-Class state check.
+ * @note Implementation is optional.
+ */
+#define osalDbgCheckClassI()
+
+/**
+ * @brief S-Class state check.
+ * @note Implementation is optional.
+ */
+#define osalDbgCheckClassS()
+/** @} */
+
+/**
+ * @name IRQ service routines wrappers
+ * @{
+ */
+/**
+ * @brief Priority level verification macro.
+ */
+#define OSAL_IRQ_IS_VALID_PRIORITY(n) \
+ (((n) >= OSAL_IRQ_MAXIMUM_PRIORITY) && ((n) < OSAL_IRQ_PRIORITY_LEVELS))
+
+/**
+ * @brief IRQ prologue code.
+ * @details This macro must be inserted at the start of all IRQ handlers.
+ */
+#define OSAL_IRQ_PROLOGUE()
+
+/**
+ * @brief IRQ epilogue code.
+ * @details This macro must be inserted at the end of all IRQ handlers.
+ */
+#define OSAL_IRQ_EPILOGUE()
+
+/**
+ * @brief IRQ handler function declaration.
+ * @details This macro hides the details of an ISR function declaration.
+ *
+ * @param[in] id a vector name as defined in @p vectors.s
+ */
+#define OSAL_IRQ_HANDLER(id) void id(void)
+/** @} */
+
+/**
+ * @name Time conversion utilities
+ * @{
+ */
+/**
+ * @brief Seconds to system ticks.
+ * @details Converts from seconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ *
+ * @param[in] secs number of seconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define OSAL_S2I(secs) \
+ ((sysinterval_t)((uint32_t)(secs) * (uint32_t)OSAL_ST_FREQUENCY))
+
+/**
+ * @brief Milliseconds to system ticks.
+ * @details Converts from milliseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ *
+ * @param[in] msecs number of milliseconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define OSAL_MS2I(msecs) \
+ ((sysinterval_t)((((((uint32_t)(msecs)) * \
+ ((uint32_t)OSAL_ST_FREQUENCY)) - 1UL) / 1000UL) + 1UL))
+
+/**
+ * @brief Microseconds to system ticks.
+ * @details Converts from microseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ *
+ * @param[in] usecs number of microseconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define OSAL_US2I(usecs) \
+ ((sysinterval_t)((((((uint32_t)(usecs)) * \
+ ((uint32_t)OSAL_ST_FREQUENCY)) - 1UL) / 1000000UL) + 1UL))
+/** @} */
+
+/**
+ * @name Time conversion utilities for the realtime counter
+ * @{
+ */
+/**
+ * @brief Seconds to realtime counter.
+ * @details Converts from seconds to realtime counter cycles.
+ * @note The macro assumes that @p freq >= @p 1.
+ *
+ * @param[in] freq clock frequency, in Hz, of the realtime counter
+ * @param[in] sec number of seconds
+ * @return The number of cycles.
+ *
+ * @api
+ */
+#define OSAL_S2RTC(freq, sec) ((freq) * (sec))
+
+/**
+ * @brief Milliseconds to realtime counter.
+ * @details Converts from milliseconds to realtime counter cycles.
+ * @note The result is rounded upward to the next millisecond boundary.
+ * @note The macro assumes that @p freq >= @p 1000.
+ *
+ * @param[in] freq clock frequency, in Hz, of the realtime counter
+ * @param[in] msec number of milliseconds
+ * @return The number of cycles.
+ *
+ * @api
+ */
+#define OSAL_MS2RTC(freq, msec) (rtcnt_t)((((freq) + 999UL) / 1000UL) * (msec))
+
+/**
+ * @brief Microseconds to realtime counter.
+ * @details Converts from microseconds to realtime counter cycles.
+ * @note The result is rounded upward to the next microsecond boundary.
+ * @note The macro assumes that @p freq >= @p 1000000.
+ *
+ * @param[in] freq clock frequency, in Hz, of the realtime counter
+ * @param[in] usec number of microseconds
+ * @return The number of cycles.
+ *
+ * @api
+ */
+#define OSAL_US2RTC(freq, usec) (rtcnt_t)((((freq) + 999999UL) / 1000000UL) * (usec))
+/** @} */
+
+/**
+ * @name Sleep macros using absolute time
+ * @{
+ */
+/**
+ * @brief Delays the invoking thread for the specified number of seconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system tick clock.
+ * @note The maximum specifiable value is implementation dependent.
+ *
+ * @param[in] secs time in seconds, must be different from zero
+ *
+ * @api
+ */
+#define osalThreadSleepSeconds(secs) osalThreadSleep(OSAL_S2I(secs))
+
+/**
+ * @brief Delays the invoking thread for the specified number of
+ * milliseconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system tick clock.
+ * @note The maximum specifiable value is implementation dependent.
+ *
+ * @param[in] msecs time in milliseconds, must be different from zero
+ *
+ * @api
+ */
+#define osalThreadSleepMilliseconds(msecs) osalThreadSleep(OSAL_MS2I(msecs))
+
+/**
+ * @brief Delays the invoking thread for the specified number of
+ * microseconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system tick clock.
+ * @note The maximum specifiable value is implementation dependent.
+ *
+ * @param[in] usecs time in microseconds, must be different from zero
+ *
+ * @api
+ */
+#define osalThreadSleepMicroseconds(usecs) osalThreadSleep(OSAL_US2I(usecs))
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+extern const char *osal_halt_msg;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void osalInit(void);
+ void osalSysHalt(const char *reason);
+ void osalSysPolledDelayX(rtcnt_t cycles);
+ void osalOsTimerHandlerI(void);
+ void osalOsRescheduleS(void);
+ systime_t osalOsGetSystemTimeX(void);
+ void osalThreadSleepS(sysinterval_t time);
+ void osalThreadSleep(sysinterval_t time);
+ msg_t osalThreadSuspendS(thread_reference_t *trp);
+ msg_t osalThreadSuspendTimeoutS(thread_reference_t *trp, sysinterval_t timeout);
+ void osalThreadResumeI(thread_reference_t *trp, msg_t msg);
+ void osalThreadResumeS(thread_reference_t *trp, msg_t msg);
+ msg_t osalThreadEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout);
+ void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg);
+ void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg);
+ void osalEventBroadcastFlagsI(event_source_t *esp, eventflags_t flags);
+ void osalEventBroadcastFlags(event_source_t *esp, eventflags_t flags);
+ void osalEventSetCallback(event_source_t *esp,
+ eventcallback_t cb,
+ void *param);
+ void osalMutexLock(mutex_t *mp);
+ void osalMutexUnlock(mutex_t *mp);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Disables interrupts globally.
+ *
+ * @special
+ */
+static inline void osalSysDisable(void) {
+
+}
+
+/**
+ * @brief Enables interrupts globally.
+ *
+ * @special
+ */
+static inline void osalSysEnable(void) {
+
+}
+
+/**
+ * @brief Enters a critical zone from thread context.
+ * @note This function cannot be used for reentrant critical zones.
+ *
+ * @special
+ */
+static inline void osalSysLock(void) {
+
+}
+
+/**
+ * @brief Leaves a critical zone from thread context.
+ * @note This function cannot be used for reentrant critical zones.
+ *
+ * @special
+ */
+static inline void osalSysUnlock(void) {
+
+}
+
+/**
+ * @brief Enters a critical zone from ISR context.
+ * @note This function cannot be used for reentrant critical zones.
+ *
+ * @special
+ */
+static inline void osalSysLockFromISR(void) {
+
+}
+
+/**
+ * @brief Leaves a critical zone from ISR context.
+ * @note This function cannot be used for reentrant critical zones.
+ *
+ * @special
+ */
+static inline void osalSysUnlockFromISR(void) {
+
+}
+
+/**
+ * @brief Returns the execution status and enters a critical zone.
+ * @details This functions enters into a critical zone and can be called
+ * from any context. Because its flexibility it is less efficient
+ * than @p chSysLock() which is preferable when the calling context
+ * is known.
+ * @post The system is in a critical zone.
+ *
+ * @return The previous system status, the encoding of this
+ * status word is architecture-dependent and opaque.
+ *
+ * @xclass
+ */
+static inline syssts_t osalSysGetStatusAndLockX(void) {
+
+ return (syssts_t)0;
+}
+
+/**
+ * @brief Restores the specified execution status and leaves a critical zone.
+ * @note A call to @p chSchRescheduleS() is automatically performed
+ * if exiting the critical zone and if not in ISR context.
+ *
+ * @param[in] sts the system status to be restored.
+ *
+ * @xclass
+ */
+static inline void osalSysRestoreStatusX(syssts_t sts) {
+
+ (void)sts;
+}
+
+/**
+ * @brief Adds an interval to a system time returning a system time.
+ *
+ * @param[in] systime base system time
+ * @param[in] interval interval to be added
+ * @return The new system time.
+ *
+ * @xclass
+ */
+static inline systime_t osalTimeAddX(systime_t systime,
+ sysinterval_t interval) {
+
+ return systime + (systime_t)interval;
+}
+
+/**
+ * @brief Subtracts two system times returning an interval.
+ *
+ * @param[in] start first system time
+ * @param[in] end second system time
+ * @return The interval representing the time difference.
+ *
+ * @xclass
+ */
+static inline sysinterval_t osalTimeDiffX(systime_t start, systime_t end) {
+
+ return (sysinterval_t)((systime_t)(end - start));
+}
+
+/**
+ * @brief Checks if the specified time is within the specified time window.
+ * @note When start==end then the function returns always false because the
+ * time window has zero size.
+ * @note This function can be called from any context.
+ *
+ * @param[in] time the time to be verified
+ * @param[in] start the start of the time window (inclusive)
+ * @param[in] end the end of the time window (non inclusive)
+ * @retval true current time within the specified time window.
+ * @retval false current time not within the specified time window.
+ *
+ * @xclass
+ */
+static inline bool osalTimeIsInRangeX(systime_t time,
+ systime_t start,
+ systime_t end) {
+
+ return (bool)((systime_t)((systime_t)time - (systime_t)start) <
+ (systime_t)((systime_t)end - (systime_t)start));
+}
+
+/**
+ * @brief Initializes a threads queue object.
+ *
+ * @param[out] tqp pointer to the threads queue object
+ *
+ * @init
+ */
+static inline void osalThreadQueueObjectInit(threads_queue_t *tqp) {
+
+ osalDbgCheck(tqp != NULL);
+}
+
+/**
+ * @brief Initializes an event source object.
+ *
+ * @param[out] esp pointer to the event source object
+ *
+ * @init
+ */
+static inline void osalEventObjectInit(event_source_t *esp) {
+
+ osalDbgCheck(esp != NULL);
+
+ esp->flags = (eventflags_t)0;
+ esp->cb = NULL;
+ esp->param = NULL;
+}
+
+/**
+ * @brief Initializes s @p mutex_t object.
+ *
+ * @param[out] mp pointer to the @p mutex_t object
+ *
+ * @init
+ */
+static inline void osalMutexObjectInit(mutex_t *mp) {
+
+ osalDbgCheck(mp != NULL);
+
+ *mp = 0;
+}
+
+#endif /* OSAL_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/hal/templates/osal/osal.mk b/ChibiOS_20.3.2/os/hal/templates/osal/osal.mk
new file mode 100644
index 0000000..623811f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/osal/osal.mk
@@ -0,0 +1,9 @@
+# OSAL files.
+OSALSRC += ${CHIBIOS}/os/hal/templates/osal/osal.c
+
+# Required include directories
+OSALINC += ${CHIBIOS}/os/hal/templates/osal
+
+# Shared variables
+ALLCSRC += $(OSALSRC)
+ALLINC += $(OSALINC)
diff --git a/ChibiOS_20.3.2/os/hal/templates/platform.mk b/ChibiOS_20.3.2/os/hal/templates/platform.mk
new file mode 100644
index 0000000..32cf64e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/hal/templates/platform.mk
@@ -0,0 +1,111 @@
+# List of all the template platform files.
+ifeq ($(USE_SMART_BUILD),yes)
+
+# Configuration files directory
+ifeq ($(CONFDIR),)
+ CONFDIR = .
+endif
+
+HALCONF := $(strip $(shell cat $(CONFDIR)/halconf.h | egrep -e "\#define"))
+
+PLATFORMSRC := ${CHIBIOS}/os/hal/templates/hal_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_st_lld.c
+ifneq ($(findstring HAL_USE_ADC TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_adc_lld.c
+endif
+ifneq ($(findstring HAL_USE_CAN TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_can_lld.c
+endif
+ifneq ($(findstring HAL_USE_CRY TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_crypto_lld.c
+endif
+ifneq ($(findstring HAL_USE_DAC TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_dac_lld.c
+endif
+ifneq ($(findstring HAL_USE_EFL TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_efl_lld.c
+endif
+ifneq ($(findstring HAL_USE_GPT TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_gpt_lld.c
+endif
+ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_i2c_lld.c
+endif
+ifneq ($(findstring HAL_USE_I2S TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_i2s_lld.c
+endif
+ifneq ($(findstring HAL_USE_ICU TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_icu_lld.c
+endif
+ifneq ($(findstring HAL_USE_MAC TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_mac_lld.c
+endif
+ifneq ($(findstring HAL_USE_PAL TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_pal_lld.c
+endif
+ifneq ($(findstring HAL_USE_PWM TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_pwm_lld.c
+endif
+ifneq ($(findstring HAL_USE_RTC TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_rtc_lld.c
+endif
+ifneq ($(findstring HAL_USE_SDC TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_sdc_lld.c
+endif
+ifneq ($(findstring HAL_USE_SERIAL TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_serial_lld.c
+endif
+ifneq ($(findstring HAL_USE_SIO TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_sio_lld.c
+endif
+ifneq ($(findstring HAL_USE_SPI TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_spi_lld.c
+endif
+ifneq ($(findstring HAL_USE_TRNG TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_trng_lld.c
+endif
+ifneq ($(findstring HAL_USE_UART TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_uart_lld.c
+endif
+ifneq ($(findstring HAL_USE_USB TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_usb_lld.c
+endif
+ifneq ($(findstring HAL_USE_WDG TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_wdg_lld.c
+endif
+ifneq ($(findstring HAL_USE_WSPI TRUE,$(HALCONF)),)
+PLATFORMSRC += ${CHIBIOS}/os/hal/templates/hal_wspi_lld.c
+endif
+else
+PLATFORMSRC = ${CHIBIOS}/os/hal/templates/hal_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_adc_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_can_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_crypto_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_dac_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_efl_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_gpt_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_i2c_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_i2s_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_icu_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_mac_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_pal_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_pwm_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_rtc_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_sdc_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_serial_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_sio_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_spi_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_st_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_trng_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_uart_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_usb_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_wdg_lld.c \
+ ${CHIBIOS}/os/hal/templates/hal_wspi_lld.c
+endif
+
+# Required include directories
+PLATFORMINC = ${CHIBIOS}/os/hal/templates
+
+# Shared variables
+ALLCSRC += $(PLATFORMSRC)
+ALLINC += $(PLATFORMINC)
diff --git a/ChibiOS_20.3.2/os/license/chcustomer.h b/ChibiOS_20.3.2/os/license/chcustomer.h
new file mode 100644
index 0000000..c5ca3aa
--- /dev/null
+++ b/ChibiOS_20.3.2/os/license/chcustomer.h
@@ -0,0 +1,103 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file chcustomer.h
+ * @brief Customer-related info.
+ *
+ * @addtogroup chibios_customer
+ * @details This module incapsulates licensee information, this is only
+ * meaningful for commercial licenses. It is a stub for public
+ * releases.
+ * @{
+ */
+
+#ifndef CHCUSTOMER_H
+#define CHCUSTOMER_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Customer readable identifier.
+ */
+#define CH_CUSTOMER_ID_STRING "Santa, North Pole"
+
+/**
+ * @brief Customer code.
+ */
+#define CH_CUSTOMER_ID_CODE "xxxx-yyyy"
+
+/**
+ * @brief Current license.
+ * @note This setting is reserved to the copyright owner.
+ * @note Changing this setting invalidates the license.
+ * @note The license statement in the source headers is valid, applicable
+ * and binding regardless this setting.
+ */
+#define CH_LICENSE CH_LICENSE_GPL
+
+/**
+ * @name Licensed Products
+ * @{
+ */
+#define CH_CUSTOMER_LIC_RT TRUE
+#define CH_CUSTOMER_LIC_NIL TRUE
+#define CH_CUSTOMER_LIC_OSLIB TRUE
+#define CH_CUSTOMER_LIC_EX TRUE
+#define CH_CUSTOMER_LIC_SB TRUE
+#define CH_CUSTOMER_LIC_PORT_CM0 TRUE
+#define CH_CUSTOMER_LIC_PORT_CM3 TRUE
+#define CH_CUSTOMER_LIC_PORT_CM4 TRUE
+#define CH_CUSTOMER_LIC_PORT_CM7 TRUE
+#define CH_CUSTOMER_LIC_PORT_ARM79 TRUE
+#define CH_CUSTOMER_LIC_PORT_E200Z0 TRUE
+#define CH_CUSTOMER_LIC_PORT_E200Z2 TRUE
+#define CH_CUSTOMER_LIC_PORT_E200Z3 TRUE
+#define CH_CUSTOMER_LIC_PORT_E200Z4 TRUE
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* CHCUSTOMER_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/license/chlicense.h b/ChibiOS_20.3.2/os/license/chlicense.h
new file mode 100644
index 0000000..9a956de
--- /dev/null
+++ b/ChibiOS_20.3.2/os/license/chlicense.h
@@ -0,0 +1,199 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file chlicense.h
+ * @brief License Module macros and structures.
+ *
+ * @addtogroup chibios_license
+ * @details This module contains all the definitions required for defining
+ * a licensing scheme for customers or public releases.
+ * @{
+ */
+
+#ifndef CHLICENSE_H
+#define CHLICENSE_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Allowed Features Levels
+ * @{
+ */
+#define CH_FEATURES_BASIC 0
+#define CH_FEATURES_INTERMEDIATE 1
+#define CH_FEATURES_FULL 2
+/** @} */
+
+/**
+ * @name Deployment Options
+ */
+#define CH_DEPLOY_UNLIMITED -1
+#define CH_DEPLOY_NONE 0
+/** @} */
+
+/**
+ * @name Licensing Options
+ * @{
+ */
+#define CH_LICENSE_GPL 0
+#define CH_LICENSE_GPL_EXCEPTION 1
+#define CH_LICENSE_COMMERCIAL_FREE 2
+#define CH_LICENSE_COMMERCIAL_DEV_1000 3
+#define CH_LICENSE_COMMERCIAL_DEV_5000 4
+#define CH_LICENSE_COMMERCIAL_FULL 5
+#define CH_LICENSE_COMMERCIAL_RUNTIME 6
+#define CH_LICENSE_PARTNER 7
+/** @} */
+
+#include "chcustomer.h"
+#if CH_LICENSE == CH_LICENSE_PARTNER
+#include "chpartner.h"
+#endif
+#if CH_LICENSE == CH_LICENSE_COMMERCIAL_RUNTIME
+#include "chruntime.h"
+#endif
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if (CH_LICENSE == CH_LICENSE_GPL) || defined(__DOXYGEN__)
+/**
+ * @brief License identification string.
+ * @details This string identifies the license in a machine-readable
+ * format.
+ */
+#define CH_LICENSE_TYPE_STRING "GNU General Public License 3 (GPL3)"
+
+/**
+ * @brief Customer identification string.
+ * @details This information is only available for registered commercial users.
+ */
+#define CH_LICENSE_ID_STRING "N/A"
+
+/**
+ * @brief Customer code.
+ * @details This information is only available for registered commercial users.
+ */
+#define CH_LICENSE_ID_CODE "N/A"
+
+/**
+ * @brief Code modifiability restrictions.
+ * @details This setting defines if the source code is user-modifiable or not.
+ */
+#define CH_LICENSE_MODIFIABLE_CODE TRUE
+
+/**
+ * @brief Code functionality restrictions.
+ */
+#define CH_LICENSE_FEATURES CH_FEATURES_FULL
+
+/**
+ * @brief Code deploy restrictions.
+ * @details This is the per-core deploy limit allowed under the current
+ * license scheme.
+ */
+#define CH_LICENSE_MAX_DEPLOY CH_DEPLOY_UNLIMITED
+
+#elif CH_LICENSE == CH_LICENSE_GPL_EXCEPTION
+#define CH_LICENSE_TYPE_STRING "GNU General Public License 3 (GPL3) + Exception"
+#define CH_LICENSE_ID_STRING "N/A"
+#define CH_LICENSE_ID_CODE "N/A"
+#define CH_LICENSE_MODIFIABLE_CODE FALSE
+#define CH_LICENSE_FEATURES CH_FEATURES_BASIC
+#define CH_LICENSE_MAX_DEPLOY CH_DEPLOY_UNLIMITED
+
+#elif CH_LICENSE == CH_LICENSE_COMMERCIAL_FREE
+#define CH_LICENSE_TYPE_STRING "Zero Cost Registered License for 500 Cores"
+#define CH_LICENSE_ID_STRING "N/A"
+#define CH_LICENSE_ID_CODE "2017-0000"
+#define CH_LICENSE_MODIFIABLE_CODE FALSE
+#define CH_LICENSE_FEATURES CH_FEATURES_INTERMEDIATE
+#define CH_LICENSE_MAX_DEPLOY 500
+
+#elif CH_LICENSE == CH_LICENSE_COMMERCIAL_DEV_1000
+#define CH_LICENSE_TYPE_STRING "Developer Commercial License for 1000 Cores"
+#define CH_LICENSE_ID_STRING CH_CUSTOMER_ID_STRING
+#define CH_LICENSE_ID_CODE CH_CUSTOMER_ID_CODE
+#define CH_LICENSE_MODIFIABLE_CODE TRUE
+#define CH_LICENSE_FEATURES CH_FEATURES_FULL
+#define CH_LICENSE_DEPLOY_LIMIT 1000
+
+#elif CH_LICENSE == CH_LICENSE_COMMERCIAL_DEV_5000
+#define CH_LICENSE_TYPE_STRING "Developer Commercial License for 5000 Cores"
+#define CH_LICENSE_ID_STRING CH_CUSTOMER_ID_STRING
+#define CH_LICENSE_ID_CODE CH_CUSTOMER_ID_CODE
+#define CH_LICENSE_MODIFIABLE_CODE TRUE
+#define CH_LICENSE_FEATURES CH_FEATURES_FULL
+#define CH_LICENSE_DEPLOY_LIMIT 5000
+
+#elif CH_LICENSE == CH_LICENSE_COMMERCIAL_FULL
+#define CH_LICENSE_TYPE_STRING "Full Commercial License for Unlimited Deployment"
+#define CH_LICENSE_ID_STRING CH_CUSTOMER_ID_STRING
+#define CH_LICENSE_ID_CODE CH_CUSTOMER_ID_CODE
+#define CH_LICENSE_MODIFIABLE_CODE TRUE
+#define CH_LICENSE_FEATURES CH_FEATURES_FULL
+#define CH_LICENSE_MAX_DEPLOY CH_DEPLOY_UNLIMITED
+
+#elif CH_LICENSE == CH_LICENSE_COMMERCIAL_RUNTIME
+#define CH_LICENSE_TYPE_STRING "Runtime Commercial License"
+#define CH_LICENSE_ID_STRING CH_CUSTOMER_ID_STRING
+#define CH_LICENSE_ID_CODE CH_CUSTOMER_ID_CODE
+#define CH_LICENSE_MODIFIABLE_CODE TRUE
+#define CH_LICENSE_FEATURES CH_FEATURES_FULL
+#define CH_LICENSE_MAX_DEPLOY CH_RUNTIME_MAX_DEPLOY
+
+#elif CH_LICENSE == CH_LICENSE_PARTNER
+#define CH_LICENSE_TYPE_STRING "Partners Special Commercial License"
+#define CH_LICENSE_ID_STRING CH_CUSTOMER_ID_STRING
+#define CH_LICENSE_ID_CODE CH_CUSTOMER_ID_CODE
+#define CH_LICENSE_MODIFIABLE_CODE CH_PARTNER_MODIFIABLE_CODE
+#define CH_LICENSE_FEATURES CH_PARTNER_FEATURES
+#define CH_LICENSE_MAX_DEPLOY CH_PARTNER_MAX_DEPLOY
+
+#else
+#error "invalid licensing option"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* CHLICENSE_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/license/chversion.h b/ChibiOS_20.3.2/os/license/chversion.h
new file mode 100644
index 0000000..1e3ace4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/license/chversion.h
@@ -0,0 +1,103 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file chversion.h
+ * @brief Version Module macros and structures.
+ *
+ * @addtogroup chibios_version
+ * @details This module contains information about the ChibiOS release, it
+ * is common to all subsystems.
+ * @{
+ */
+
+#ifndef CHVERSION_H
+#define CHVERSION_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @brief ChibiOS product identification macro.
+ */
+#define _CHIBIOS_
+
+/**
+ * @brief Stable release flag.
+ */
+#define CH_VERSION_STABLE 1
+
+/**
+ * @name ChibiOS version identification
+ * @{
+ */
+/**
+ * @brief ChibiOS version string.
+ */
+#define CH_VERSION "20.3.2"
+
+/**
+ * @brief ChibiOS version release year.
+ */
+#define CH_VERSION_YEAR 20
+
+/**
+ * @brief ChibiOS version release month.
+ */
+#define CH_VERSION_MONTH 3
+
+/**
+ * @brief ChibiOS version patch number.
+ */
+#define CH_VERSION_PATCH 2
+
+/**
+ * @brief ChibiOS version nickname.
+ */
+#define CH_VERSION_NICKNAME "Praiano"
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* CHVERSION_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/license/license.dox b/ChibiOS_20.3.2/os/license/license.dox
new file mode 100644
index 0000000..b240e15
--- /dev/null
+++ b/ChibiOS_20.3.2/os/license/license.dox
@@ -0,0 +1,37 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @defgroup licensing Release and Licensing
+ */
+
+/**
+ * @defgroup chibios_version Release Information
+ * @ingroup licensing
+ */
+
+/**
+ * @defgroup chibios_customer Customer Information
+ * @ingroup licensing
+ */
+
+/**
+ * @defgroup chibios_license License Settings
+ * @ingroup licensing
+ */
diff --git a/ChibiOS_20.3.2/os/license/license.mk b/ChibiOS_20.3.2/os/license/license.mk
new file mode 100644
index 0000000..3781727
--- /dev/null
+++ b/ChibiOS_20.3.2/os/license/license.mk
@@ -0,0 +1,9 @@
+# List of all the licensing subsystem files.
+LICSRC :=
+
+# Required include directories
+LICINC := $(CHIBIOS)/os/license
+
+# Shared variables
+ALLCSRC += $(LICSRC)
+ALLINC += $(LICINC)
diff --git a/ChibiOS_20.3.2/os/nil/dox/nil.dox b/ChibiOS_20.3.2/os/nil/dox/nil.dox
new file mode 100644
index 0000000..9fd3af5
--- /dev/null
+++ b/ChibiOS_20.3.2/os/nil/dox/nil.dox
@@ -0,0 +1,65 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @defgroup NIL NIL Kernel
+ * @details The kernel is the portable part of ChibiOS/NIL, this section
+ * documents the various kernel subsystems.
+ */
+
+/**
+ * @defgroup NIL_CONFIG Configuration
+ * @ingroup NIL
+ */
+
+/*-*
+ * @defgroup NIL_TYPES Kernel Types
+ * @ingroup NIL
+ */
+
+/**
+ * @defgroup NIL_KERNEL Base API
+ * @ingroup NIL
+ */
+
+/**
+ * @defgroup NIL_SEMAPHORES Semaphores
+ * @ingroup NIL
+ */
+
+/**
+ * @defgroup NIL_EVENTS Events
+ * @ingroup NIL
+ */
+
+/**
+ * @defgroup NIL_MESSAGES Synchronous Messages
+ * @ingroup NIL
+ */
+
+/*-*
+ * @defgroup NIL_CORE Port Layer
+ * @ingroup NIL
+ */
+
+/*-*
+ * @defgroup NIL_TIMER Timer Interface
+ * @ingroup NIL
+ */
+
diff --git a/ChibiOS_20.3.2/os/nil/include/ch.h b/ChibiOS_20.3.2/os/nil/include/ch.h
new file mode 100644
index 0000000..0e407bf
--- /dev/null
+++ b/ChibiOS_20.3.2/os/nil/include/ch.h
@@ -0,0 +1,1419 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file nil/include/ch.h
+ * @brief Nil RTOS main header file.
+ * @details This header includes all the required kernel headers so it is the
+ * only header you usually need to include in your application.
+ *
+ * @addtogroup NIL_KERNEL
+ * @{
+ */
+
+#ifndef CH_H
+#define CH_H
+
+#include "chtypes.h"
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @brief ChibiOS/NIL identification macro.
+ */
+#define _CHIBIOS_NIL_
+
+/**
+ * @brief Stable release flag.
+ */
+#define CH_KERNEL_STABLE 1
+
+/**
+ * @name ChibiOS/NIL version identification
+ * @{
+ */
+/**
+ * @brief Kernel version string.
+ */
+#define CH_KERNEL_VERSION "4.0.0"
+
+/**
+ * @brief Kernel version major number.
+ */
+#define CH_KERNEL_MAJOR 4
+
+/**
+ * @brief Kernel version minor number.
+ */
+#define CH_KERNEL_MINOR 0
+
+/**
+ * @brief Kernel version patch number.
+ */
+#define CH_KERNEL_PATCH 0
+/** @} */
+
+/**
+ * @name Constants for configuration options
+ */
+/**
+ * @brief Generic 'false' preprocessor boolean constant.
+ * @note It is meant to be used in configuration files as switch.
+ */
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+/**
+ * @brief Generic 'true' preprocessor boolean constant.
+ * @note It is meant to be used in configuration files as switch.
+ */
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+/** @} */
+
+/**
+ * @name Wakeup messages
+ * @{
+ */
+#define MSG_OK (msg_t)0 /**< @brief OK wakeup message. */
+#define MSG_TIMEOUT (msg_t)-1 /**< @brief Wake-up caused by
+ a timeout condition. */
+#define MSG_RESET (msg_t)-2 /**< @brief Wake-up caused by
+ a reset condition. */
+/** @} */
+
+/**
+ * @name Special time constants
+ * @{
+ */
+/**
+ * @brief Zero time specification for some functions with a timeout
+ * specification.
+ * @note Not all functions accept @p TIME_IMMEDIATE as timeout parameter,
+ * see the specific function documentation.
+ */
+#define TIME_IMMEDIATE ((sysinterval_t)-1)
+
+/**
+ * @brief Infinite time specification for all functions with a timeout
+ * specification.
+ */
+#define TIME_INFINITE ((sysinterval_t)0)
+
+/**
+ * @brief Maximum interval constant usable as timeout.
+ */
+#define TIME_MAX_INTERVAL ((sysinterval_t)-2)
+
+/**
+ * @brief Maximum system of system time before it wraps.
+ */
+#define TIME_MAX_SYSTIME ((systime_t)-1)
+/** @} */
+
+/**
+ * @name Thread state related macros
+ * @{
+ */
+#define NIL_STATE_WTSTART (tstate_t)0 /**< @brief Thread not yet
+ started or terminated. */
+#define NIL_STATE_READY (tstate_t)1 /**< @brief Thread ready or
+ executing. */
+#define NIL_STATE_SLEEPING (tstate_t)2 /**< @brief Thread sleeping. */
+#define NIL_STATE_SUSPENDED (tstate_t)3 /**< @brief Thread suspended. */
+#define NIL_STATE_WTEXIT (tstate_t)4 /**< @brief Waiting a thread. */
+#define NIL_STATE_WTQUEUE (tstate_t)5 /**< @brief On queue or semaph. */
+#define NIL_STATE_WTOREVT (tstate_t)6 /**< @brief Waiting for events. */
+#define NIL_STATE_WTANDEVT (tstate_t)7 /**< @brief Waiting for events. */
+#define NIL_STATE_SNDMSGQ (tstate_t)8 /**< @brief Sending a message,
+ in queue. */
+#define NIL_STATE_WTMSG (tstate_t)10/**< @brief Waiting for a
+ message. */
+#define NIL_STATE_FINAL (tstate_t)11/**< @brief Thread terminated. */
+
+#define NIL_THD_IS_WTSTART(tp) ((tp)->state == NIL_STATE_WTSTART)
+#define NIL_THD_IS_READY(tp) ((tp)->state == NIL_STATE_READY)
+#define NIL_THD_IS_SLEEPING(tp) ((tp)->state == NIL_STATE_SLEEPING)
+#define NIL_THD_IS_SUSPENDED(tp) ((tp)->state == NIL_STATE_SUSPENDED)
+#define NIL_THD_IS_WTEXIT(tp) ((tp)->state == NIL_STATE_WTEXIT)
+#define NIL_THD_IS_WTQUEUE(tp) ((tp)->state == NIL_STATE_WTQUEUE)
+#define NIL_THD_IS_WTOREVT(tp) ((tp)->state == NIL_STATE_WTOREVT)
+#define NIL_THD_IS_WTANDEVT(tp) ((tp)->state == NIL_STATE_WTANDEVT)
+#define NIL_THD_IS_SNDMSGQ(tp) ((tp)->state == NIL_STATE_SNDMSGQ)
+#define NIL_THD_IS_WTMSG(tp) ((tp)->state == NIL_STATE_WTMSG)
+#define NIL_THD_IS_FINAL(tp) ((tp)->state == NIL_STATE_FINAL)
+
+#define CH_STATE_NAMES \
+ "WTSTART", "READY", "SLEEPING", "SUSPENDED", "WTEXIT", "WTQUEUE", \
+ "WTOREVT", "WTANDEVT", "SNDMSGQ", "SNDMSG", "WTMSG", "FINAL"
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+#include "chconf.h"
+#include "chlicense.h"
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Checks on configuration options.*/
+#if !defined(CH_CFG_MAX_THREADS) || defined(__DOXYGEN__)
+#error "CH_CFG_MAX_THREADS not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_AUTOSTART_THREADS) || defined(__DOXYGEN__)
+#error "CH_CFG_AUTOSTART_THREADS not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_ST_RESOLUTION) || defined(__DOXYGEN__)
+#error "CH_CFG_ST_RESOLUTION not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_ST_FREQUENCY) || defined(__DOXYGEN__)
+#error "CH_CFG_ST_FREQUENCY not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_ST_TIMEDELTA) || defined(__DOXYGEN__)
+#error "CH_CFG_ST_TIMEDELTA not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_WAITEXIT)
+#error "CH_CFG_USE_WAITEXIT not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__)
+#error "CH_CFG_USE_MESSAGES not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
+#error "CH_CFG_USE_SEMAPHORES not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_EVENTS)
+#error "CH_CFG_USE_EVENTS not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_MUTEXES) || defined(__DOXYGEN__)
+#error "CH_CFG_USE_MUTEXES not defined in chconf.h"
+#endif
+
+#if !defined(CH_DBG_STATISTICS) || defined(__DOXYGEN__)
+#error "CH_DBG_STATISTICS not defined in chconf.h"
+#endif
+
+#if !defined(CH_DBG_SYSTEM_STATE_CHECK) || defined(__DOXYGEN__)
+#error "CH_DBG_SYSTEM_STATE_CHECK not defined in chconf.h"
+#endif
+
+#if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)
+#error "CH_DBG_ENABLE_CHECKS not defined in chconf.h"
+#endif
+
+#if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)
+#error "CH_DBG_ENABLE_ASSERTS not defined in chconf.h"
+#endif
+
+#if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__)
+#error "CH_DBG_ENABLE_STACK_CHECK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_SYSTEM_INIT_HOOK) || defined(__DOXYGEN__)
+#error "CH_CFG_SYSTEM_INIT_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_THREAD_EXT_FIELDS) || defined(__DOXYGEN__)
+#error "CH_CFG_THREAD_EXT_FIELDS not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_THREAD_EXT_INIT_HOOK) || defined(__DOXYGEN__)
+#error "CH_CFG_THREAD_EXT_INIT_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_THREAD_EXIT_HOOK) || defined(__DOXYGEN__)
+#error "CH_CFG_THREAD_EXIT_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_IDLE_ENTER_HOOK) || defined(__DOXYGEN__)
+#error "CH_CFG_IDLE_ENTER_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_IDLE_LEAVE_HOOK) || defined(__DOXYGEN__)
+#error "CH_CFG_IDLE_LEAVE_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_SYSTEM_HALT_HOOK) || defined(__DOXYGEN__)
+#error "CH_CFG_SYSTEM_HALT_HOOK not defined in chconf.h"
+#endif
+
+/* License checks.*/
+#if !defined(CH_CUSTOMER_LIC_NIL) || !defined(CH_LICENSE_FEATURES)
+#error "malformed chlicense.h"
+#endif
+
+#if CH_CUSTOMER_LIC_NIL == FALSE
+#error "ChibiOS/NIL not licensed"
+#endif
+
+#if (CH_LICENSE_FEATURES != CH_FEATURES_FULL) && \
+ (CH_LICENSE_FEATURES != CH_FEATURES_INTERMEDIATE) && \
+ (CH_LICENSE_FEATURES != CH_FEATURES_BASIC)
+#error "invalid CH_LICENSE_FEATURES setting"
+#endif
+
+/* Restrictions in basic and intermediate modes.*/
+#if (CH_LICENSE_FEATURES == CH_FEATURES_INTERMEDIATE) || \
+ (CH_LICENSE_FEATURES == CH_FEATURES_BASIC)
+
+/* System tick limited to 1000hz.*/
+#if CH_CFG_ST_FREQUENCY > 1000
+#undef CH_CFG_ST_FREQUENCY
+#define CH_CFG_ST_FREQUENCY 1000
+#endif
+
+#endif /* (CH_LICENSE_FEATURES == CH_FEATURES_INTERMEDIATE) ||
+ (CH_LICENSE_FEATURES == CH_FEATURES_BASIC) */
+
+/* Restrictions in basic mode.*/
+#if CH_LICENSE_FEATURES == CH_FEATURES_BASIC
+
+/* Tick-Less mode restricted.*/
+#undef CH_CFG_ST_TIMEDELTA
+#define CH_CFG_ST_TIMEDELTA 0
+
+/* Messages restricted.*/
+#undef CH_CFG_USE_MESSAGES
+#define CH_CFG_USE_MESSAGES FALSE
+
+#endif /* CH_LICENSE_FEATURES == CH_FEATURES_BASIC */
+
+#if !defined(_CHIBIOS_NIL_CONF_)
+#error "missing or wrong configuration file"
+#endif
+
+#if !defined(_CHIBIOS_NIL_CONF_VER_4_0_)
+#error "obsolete or unknown configuration file"
+#endif
+
+#if CH_CFG_MAX_THREADS < 1
+#error "at least one thread must be defined"
+#endif
+
+#if CH_CFG_MAX_THREADS > 16
+#error "ChibiOS/NIL is not recommended for thread-intensive applications," \
+ "consider ChibiOS/RT instead"
+#endif
+
+#if (CH_CFG_ST_RESOLUTION != 16) && (CH_CFG_ST_RESOLUTION != 32)
+#error "invalid CH_CFG_ST_RESOLUTION specified, must be 16 or 32"
+#endif
+
+#if CH_CFG_ST_FREQUENCY <= 0
+#error "invalid CH_CFG_ST_FREQUENCY specified, must be greater than zero"
+#endif
+
+#if (CH_CFG_ST_TIMEDELTA < 0) || (CH_CFG_ST_TIMEDELTA == 1)
+#error "invalid CH_CFG_ST_TIMEDELTA specified, must " \
+ "be zero or greater than one"
+#endif
+
+#if CH_CFG_USE_MUTEXES == TRUE
+#error "mutexes not yet supported"
+#endif
+
+#if CH_DBG_STATISTICS == TRUE
+#error "statistics not yet supported"
+#endif
+
+#if (CH_DBG_SYSTEM_STATE_CHECK == TRUE) || \
+ (CH_DBG_ENABLE_CHECKS == TRUE) || \
+ (CH_DBG_ENABLE_ASSERTS == TRUE) || \
+ (CH_DBG_ENABLE_STACK_CHECK == TRUE)
+#define NIL_DBG_ENABLED TRUE
+#else
+#define NIL_DBG_ENABLED FALSE
+#endif
+
+/** Boundaries of the idle thread boundaries, only required if stack checking
+ is enabled.*/
+#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || defined(__DOXYGEN__)
+#define THD_IDLE_BASE (&__main_thread_stack_base__)
+#define THD_IDLE_END (&__main_thread_stack_end__)
+#else
+#define THD_IDLE_BASE NULL
+#define THD_IDLE_END NULL
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+#if (CH_CFG_ST_RESOLUTION == 32) || defined(__DOXYGEN__)
+/**
+ * @brief Type of system time.
+ * @note It is selectable in configuration between 16 or 32 bits.
+ */
+typedef uint32_t systime_t;
+
+/**
+ * @brief Type of time interval.
+ * @note It is selectable in configuration between 16 or 32 bits.
+ */
+typedef uint32_t sysinterval_t;
+
+/**
+ * @brief Type of time conversion variable.
+ * @note This type must have double width than other time types, it is
+ * only used internally for conversions.
+ */
+typedef uint64_t time_conv_t;
+
+#else
+typedef uint16_t systime_t;
+typedef uint16_t sysinterval_t;
+typedef uint32_t time_conv_t;
+#endif
+
+/**
+ * @brief Type of a structure representing the system.
+ */
+typedef struct nil_system nil_system_t;
+
+/**
+ * @brief Thread function.
+ */
+typedef void (*tfunc_t)(void *p);
+
+/**
+ * @brief Type of a thread descriptor.
+ */
+typedef struct nil_thread_descriptor thread_descriptor_t;
+
+/**
+ * @brief Type of a structure representing a thread.
+ * @note It is required as an early definition.
+ */
+typedef struct nil_thread thread_t;
+
+/**
+ * @brief Type of a thread reference.
+ */
+typedef thread_t * thread_reference_t;
+
+/**
+ * @brief Type of a queue of threads.
+ */
+typedef struct nil_threads_queue threads_queue_t;
+
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a structure representing a semaphore.
+ * @note Semaphores are implemented on thread queues, the object is the
+ * same, the behavior is slightly different.
+ */
+typedef threads_queue_t semaphore_t;
+#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
+
+/* Late inclusion of port core layer.*/
+#include "chcore.h"
+
+/**
+ * @brief Structure representing a queue of threads.
+ */
+struct nil_threads_queue {
+ volatile cnt_t cnt; /**< @brief Threads Queue counter. */
+};
+
+/**
+ * @brief Structure representing a thread descriptor.
+ */
+struct nil_thread_descriptor {
+ const char *name; /**< @brief Thread name, for debugging. */
+ stkalign_t *wbase; /**< @brief Thread working area base. */
+ stkalign_t *wend; /**< @brief Thread working area end. */
+ tprio_t prio; /**< @brief Thread priority slot. */
+ tfunc_t funcp; /**< @brief Thread function. */
+ void *arg; /**< @brief Thread function argument. */
+};
+
+/**
+ * @brief Structure representing a thread.
+ */
+struct nil_thread {
+ struct port_context ctx; /**< @brief Processor context. */
+ tstate_t state; /**< @brief Thread state. */
+ /* Note, the following union contains a pointer/value while the thread is
+ in a sleeping state or a wake-up message when the thread is made ready.*/
+ union {
+ msg_t msg; /**< @brief Wake-up/exit message. */
+ void *p; /**< @brief Generic pointer. */
+ nil_system_t *nsp; /**< @brief Pointer to nil base struct. */
+ thread_reference_t *trp; /**< @brief Pointer to thread reference.*/
+ threads_queue_t *tqp; /**< @brief Pointer to thread queue. */
+ thread_t *tp; /**< @brief Pointer to thread. */
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+ semaphore_t *semp; /**< @brief Pointer to semaphore. */
+#endif
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+ eventmask_t ewmask; /**< @brief Enabled events mask. */
+#endif
+ } u1;
+ volatile sysinterval_t timeout; /**< @brief Timeout counter, zero
+ if disabled. */
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+ eventmask_t epmask; /**< @brief Pending events mask. */
+#endif
+#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
+ msg_t sntmsg; /**< @brief Sent message. */
+#endif
+#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || defined(__DOXYGEN__)
+ stkalign_t *wabase; /**< @brief Thread stack boundary. */
+#endif
+ /* Optional extra fields.*/
+ CH_CFG_THREAD_EXT_FIELDS
+};
+
+/**
+ * @brief System data structure.
+ * @note This structure contain all the data areas used by the OS except
+ * stacks.
+ */
+struct nil_system {
+ /**
+ * @brief Pointer to the running thread.
+ */
+ thread_t *current;
+ /**
+ * @brief Pointer to the next thread to be executed.
+ * @note This pointer must point at the same thread pointed by @p current
+ * or to an higher priority thread if a switch is required.
+ */
+ thread_t *next;
+#if (CH_CFG_ST_TIMEDELTA == 0) || defined(__DOXYGEN__)
+ /**
+ * @brief System time.
+ */
+ volatile systime_t systime;
+#endif
+#if (CH_CFG_ST_TIMEDELTA > 0) || defined(__DOXYGEN__)
+ /**
+ * @brief System time of the last tick event.
+ */
+ systime_t lasttime;
+ /**
+ * @brief Time of the next scheduled tick event.
+ */
+ systime_t nexttime;
+#endif
+#if (CH_DBG_SYSTEM_STATE_CHECK == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief ISR nesting level.
+ */
+ cnt_t isr_cnt;
+ /**
+ * @brief Lock nesting level.
+ */
+ cnt_t lock_cnt;
+#endif
+#if (NIL_DBG_ENABLED == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Panic message.
+ * @note This field is only present if some debug options have been
+ * activated.
+ * @note Accesses to this pointer must never be optimized out so the
+ * field itself is declared volatile.
+ */
+ const char * volatile dbg_panic_msg;
+#endif
+ /**
+ * @brief Thread structures for all the defined threads.
+ */
+ thread_t threads[CH_CFG_MAX_THREADS + 1];
+};
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+#if CH_DBG_SYSTEM_STATE_CHECK == TRUE
+#define _dbg_enter_lock() (nil.lock_cnt = (cnt_t)1)
+#define _dbg_leave_lock() (nil.lock_cnt = (cnt_t)0)
+#endif
+
+/**
+ * @brief Utility to make the parameter a quoted string.
+ */
+#define __CH_STRINGIFY(a) #a
+
+/**
+ * @name Threads tables definition macros
+ * @{
+ */
+/**
+ * @brief Start of user threads table.
+ */
+#define THD_TABLE_BEGIN \
+ const thread_descriptor_t nil_thd_configs[] = {
+
+/**
+ * @brief Entry of user threads table
+ */
+#define THD_TABLE_THREAD(_prio, _name, _wap, _funcp, _arg) \
+ { \
+ .name = (_name), \
+ .wbase = (_wap), \
+ .wend = THD_WORKING_AREA_END(_wap), \
+ .prio = (_prio), \
+ .funcp = (_funcp), \
+ .arg = (_arg) \
+ },
+
+/**
+ * @brief End of user threads table.
+ */
+#define THD_TABLE_END \
+ { \
+ .name = "idle", \
+ .wbase = THD_IDLE_BASE, \
+ .wend = THD_IDLE_END, \
+ .prio = CH_CFG_MAX_THREADS, \
+ .funcp = NULL, \
+ .arg = NULL \
+ } \
+};
+/** @} */
+
+/**
+ * @name Memory alignment support macros
+ */
+/**
+ * @brief Alignment mask constant.
+ *
+ * @param[in] a alignment, must be a power of two
+ */
+#define MEM_ALIGN_MASK(a) ((size_t)(a) - 1U)
+
+/**
+ * @brief Aligns to the previous aligned memory address.
+ *
+ * @param[in] p variable to be aligned
+ * @param[in] a alignment, must be a power of two
+ */
+#define MEM_ALIGN_PREV(p, a) ((size_t)(p) & ~MEM_ALIGN_MASK(a))
+
+/**
+ * @brief Aligns to the new aligned memory address.
+ *
+ * @param[in] p variable to be aligned
+ * @param[in] a alignment, must be a power of two
+ */
+#define MEM_ALIGN_NEXT(p, a) MEM_ALIGN_PREV((size_t)(p) + \
+ MEM_ALIGN_MASK(a), (a))
+
+/**
+ * @brief Returns whatever a pointer or memory size is aligned.
+ *
+ * @param[in] p variable to be aligned
+ * @param[in] a alignment, must be a power of two
+ */
+#define MEM_IS_ALIGNED(p, a) (((size_t)(p) & MEM_ALIGN_MASK(a)) == 0U)
+
+/**
+ * @brief Returns whatever a constant is a valid alignment.
+ * @details Valid alignments are powers of two.
+ *
+ * @param[in] a alignment to be checked, must be a constant
+ */
+#define MEM_IS_VALID_ALIGNMENT(a) \
+ (((size_t)(a) != 0U) && (((size_t)(a) & ((size_t)(a) - 1U)) == 0U))
+/** @} */
+
+/**
+ * @name Working Areas
+ */
+/**
+ * @brief Calculates the total Working Area size.
+ *
+ * @param[in] n the stack size to be assigned to the thread
+ * @return The total used memory in bytes.
+ *
+ * @api
+ */
+#define THD_WORKING_AREA_SIZE(n) MEM_ALIGN_NEXT(PORT_WA_SIZE(n), \
+ PORT_STACK_ALIGN)
+
+/**
+ * @brief Static working area allocation.
+ * @details This macro is used to allocate a static thread working area
+ * aligned as both position and size.
+ *
+ * @param[in] s the name to be assigned to the stack array
+ * @param[in] n the stack size to be assigned to the thread
+ *
+ * @api
+ */
+#define THD_WORKING_AREA(s, n) PORT_WORKING_AREA(s, n)
+/** @} */
+
+/**
+ * @brief Returns the top address of a working area.
+ * @note The parameter is assumed to be an array of @p stkalign_t. The
+ * macros is invalid for anything else.
+ *
+ * @param[in] wa working area array
+ *
+ * @api
+ */
+#define THD_WORKING_AREA_END(wa) \
+ ((wa) + ((sizeof wa) / sizeof (stkalign_t)))
+
+/**
+ * @name Threads abstraction macros
+ */
+/**
+ * @brief Thread declaration macro.
+ * @note Thread declarations should be performed using this macro because
+ * the port layer could define optimizations for thread functions.
+ */
+#define THD_FUNCTION(tname, arg) PORT_THD_FUNCTION(tname, arg)
+/** @} */
+
+/**
+ * @name ISRs abstraction macros
+ */
+/**
+ * @brief Priority level validation macro.
+ * @details This macro determines if the passed value is a valid priority
+ * level for the underlying architecture.
+ *
+ * @param[in] prio the priority level
+ * @return Priority range result.
+ * @retval false if the priority is invalid or if the architecture
+ * does not support priorities.
+ * @retval true if the priority is valid.
+ */
+#if defined(PORT_IRQ_IS_VALID_PRIORITY) || defined(__DOXYGEN__)
+#define CH_IRQ_IS_VALID_PRIORITY(prio) \
+ PORT_IRQ_IS_VALID_PRIORITY(prio)
+#else
+#define CH_IRQ_IS_VALID_PRIORITY(prio) false
+#endif
+
+/**
+ * @brief Priority level validation macro.
+ * @details This macro determines if the passed value is a valid priority
+ * level that cannot preempt the kernel critical zone.
+ *
+ * @param[in] prio the priority level
+ * @return Priority range result.
+ * @retval false if the priority is invalid or if the architecture
+ * does not support priorities.
+ * @retval true if the priority is valid.
+ */
+#if defined(PORT_IRQ_IS_VALID_KERNEL_PRIORITY) || defined(__DOXYGEN__)
+#define CH_IRQ_IS_VALID_KERNEL_PRIORITY(prio) \
+ PORT_IRQ_IS_VALID_KERNEL_PRIORITY(prio)
+#else
+#define CH_IRQ_IS_VALID_KERNEL_PRIORITY(prio) false
+#endif
+
+/**
+ * @brief IRQ handler enter code.
+ * @note Usually IRQ handlers functions are also declared naked.
+ * @note On some architectures this macro can be empty.
+ *
+ * @special
+ */
+#define CH_IRQ_PROLOGUE() \
+ PORT_IRQ_PROLOGUE(); \
+ _dbg_check_enter_isr()
+
+/**
+ * @brief IRQ handler exit code.
+ * @note Usually IRQ handlers function are also declared naked.
+ *
+ * @special
+ */
+#define CH_IRQ_EPILOGUE() \
+ _dbg_check_leave_isr(); \
+ PORT_IRQ_EPILOGUE()
+
+/**
+ * @brief Standard normal IRQ handler declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ *
+ * @special
+ */
+#define CH_IRQ_HANDLER(id) PORT_IRQ_HANDLER(id)
+/** @} */
+
+/**
+ * @name Fast ISRs abstraction macros
+ */
+/**
+ * @brief Standard fast IRQ handler declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ * @note Not all architectures support fast interrupts.
+ *
+ * @special
+ */
+#define CH_FAST_IRQ_HANDLER(id) PORT_FAST_IRQ_HANDLER(id)
+/** @} */
+
+/**
+ * @name Time conversion utilities
+ * @{
+ */
+/**
+ * @brief Seconds to time interval.
+ * @details Converts from seconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] secs number of seconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define TIME_S2I(secs) \
+ ((sysinterval_t)((time_conv_t)(secs) * (time_conv_t)CH_CFG_ST_FREQUENCY))
+
+/**
+ * @brief Milliseconds to time interval.
+ * @details Converts from milliseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] msecs number of milliseconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define TIME_MS2I(msecs) \
+ ((sysinterval_t)((((time_conv_t)(msecs) * \
+ (time_conv_t)CH_CFG_ST_FREQUENCY) + \
+ (time_conv_t)999) / (time_conv_t)1000))
+
+/**
+ * @brief Microseconds to time interval.
+ * @details Converts from microseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] usecs number of microseconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define TIME_US2I(usecs) \
+ ((sysinterval_t)((((time_conv_t)(usecs) * \
+ (time_conv_t)CH_CFG_ST_FREQUENCY) + \
+ (time_conv_t)999999) / (time_conv_t)1000000))
+
+/**
+ * @brief Time interval to seconds.
+ * @details Converts from system ticks number to seconds.
+ * @note The result is rounded up to the next second boundary.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] interval interval in ticks
+ * @return The number of seconds.
+ *
+ * @api
+ */
+#define TIME_I2S(interval) \
+ (time_secs_t)(((time_conv_t)(interval) + \
+ (time_conv_t)CH_CFG_ST_FREQUENCY - \
+ (time_conv_t)1) / (time_conv_t)CH_CFG_ST_FREQUENCY)
+
+/**
+ * @brief Time interval to milliseconds.
+ * @details Converts from system ticks number to milliseconds.
+ * @note The result is rounded up to the next millisecond boundary.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] interval interval in ticks
+ * @return The number of milliseconds.
+ *
+ * @api
+ */
+#define TIME_I2MS(interval) \
+ (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000) + \
+ (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) / \
+ (time_conv_t)CH_CFG_ST_FREQUENCY)
+
+/**
+ * @brief Time interval to microseconds.
+ * @details Converts from system ticks number to microseconds.
+ * @note The result is rounded up to the next microsecond boundary.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] interval interval in ticks
+ * @return The number of microseconds.
+ *
+ * @api
+ */
+#define TIME_I2US(interval) \
+ (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000000) + \
+ (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) / \
+ (time_conv_t)CH_CFG_ST_FREQUENCY)
+/** @} */
+
+/**
+ * @name Threads queues
+ */
+/**
+ * @brief Data part of a static threads queue object initializer.
+ * @details This macro should be used when statically initializing a threads
+ * queue that is part of a bigger structure.
+ *
+ * @param[in] name the name of the threads queue variable
+ */
+#define _THREADS_QUEUE_DATA(name) {(cnt_t)0}
+
+/**
+ * @brief Static threads queue object initializer.
+ * @details Statically initialized threads queues require no explicit
+ * initialization using @p queue_init().
+ *
+ * @param[in] name the name of the threads queue variable
+ */
+#define _THREADS_QUEUE_DECL(name) \
+ threads_queue_t name = _THREADS_QUEUE_DATA(name)
+/** @} */
+
+/**
+ * @name Semaphores macros
+ * @{
+ */
+/**
+ * @brief Data part of a static semaphore initializer.
+ * @details This macro should be used when statically initializing a semaphore
+ * that is part of a bigger structure.
+ *
+ * @param[in] name the name of the semaphore variable
+ * @param[in] n the counter initial value, this value must be
+ * non-negative
+ */
+#define _SEMAPHORE_DATA(name, n) {n}
+
+/**
+ * @brief Static semaphore initializer.
+ * @details Statically initialized semaphores require no explicit
+ * initialization using @p chSemInit().
+ *
+ * @param[in] name the name of the semaphore variable
+ * @param[in] n the counter initial value, this value must be
+ * non-negative
+ */
+#define SEMAPHORE_DECL(name, n) semaphore_t name = _SEMAPHORE_DATA(name, n)
+/** @} */
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Returns the current value of the system real time counter.
+ * @note This function is only available if the port layer supports the
+ * option @p PORT_SUPPORTS_RT.
+ *
+ * @return The value of the system realtime counter of
+ * type rtcnt_t.
+ *
+ * @xclass
+ */
+#if (PORT_SUPPORTS_RT == TRUE) || defined(__DOXYGEN__)
+#define chSysGetRealtimeCounterX() (rtcnt_t)port_rt_get_counter_value()
+#endif
+
+/**
+ * @brief Raises the system interrupt priority mask to the maximum level.
+ * @details All the maskable interrupt sources are disabled regardless their
+ * hardware priority.
+ * @note Do not invoke this API from within a kernel lock.
+ *
+ * @special
+ */
+#define chSysDisable() { \
+ port_disable(); \
+ _dbg_check_disable(); \
+}
+
+/**
+ * @brief Raises the system interrupt priority mask to system level.
+ * @details The interrupt sources that should not be able to preempt the kernel
+ * are disabled, interrupt sources with higher priority are still
+ * enabled.
+ * @note Do not invoke this API from within a kernel lock.
+ * @note This API is no replacement for @p chSysLock(), the @p chSysLock()
+ * could do more than just disable the interrupts.
+ *
+ * @special
+ */
+#define chSysSuspend() { \
+ port_suspend(); \
+ _dbg_check_suspend(); \
+}
+
+/**
+ * @brief Lowers the system interrupt priority mask to user level.
+ * @details All the interrupt sources are enabled.
+ * @note Do not invoke this API from within a kernel lock.
+ * @note This API is no replacement for @p chSysUnlock(), the
+ * @p chSysUnlock() could do more than just enable the interrupts.
+ *
+ * @special
+ */
+#define chSysEnable() { \
+ _dbg_check_enable(); \
+ port_enable(); \
+}
+
+/**
+ * @brief Enters the kernel lock state.
+ *
+ * @special
+ */
+#define chSysLock() { \
+ port_lock(); \
+ _dbg_check_lock(); \
+}
+
+/**
+ * @brief Leaves the kernel lock state.
+ *
+ * @special
+ */
+#define chSysUnlock() { \
+ _dbg_check_unlock(); \
+ port_unlock(); \
+}
+
+/**
+ * @brief Enters the kernel lock state from within an interrupt handler.
+ * @note This API may do nothing on some architectures, it is required
+ * because on ports that support preemptable interrupt handlers
+ * it is required to raise the interrupt mask to the same level of
+ * the system mutual exclusion zone.
+ * It is good practice to invoke this API before invoking any I-class
+ * syscall from an interrupt handler.
+ * @note This API must be invoked exclusively from interrupt handlers.
+ *
+ * @special
+ */
+#define chSysLockFromISR() { \
+ port_lock_from_isr(); \
+ _dbg_check_lock_from_isr(); \
+}
+
+/**
+ * @brief Leaves the kernel lock state from within an interrupt handler.
+ *
+ * @note This API may do nothing on some architectures, it is required
+ * because on ports that support preemptable interrupt handlers
+ * it is required to raise the interrupt mask to the same level of
+ * the system mutual exclusion zone.
+ * It is good practice to invoke this API after invoking any I-class
+ * syscall from an interrupt handler.
+ * @note This API must be invoked exclusively from interrupt handlers.
+ *
+ * @special
+ */
+#define chSysUnlockFromISR() { \
+ _dbg_check_unlock_from_isr(); \
+ port_unlock_from_isr(); \
+}
+
+/**
+ * @brief Puts the current thread to sleep into the specified state.
+ *
+ * @param[in] newstate the new thread state or a semaphore pointer
+ * @return The wakeup message.
+ *
+ * @sclass
+ */
+#define chSchGoSleepS(newstate) chSchGoSleepTimeoutS(newstate, TIME_INFINITE)
+
+/**
+ * @brief Wakes up a thread.
+ *
+ * @param[in] ntp the thread to be made ready
+ * @param[in] msg the wakeup message
+ *
+ * @sclass
+ */
+#define chSchWakeupS(ntp, msg) do { \
+ chSchReadyI(ntp, msg); \
+ chSchRescheduleS(); \
+} while (false)
+
+/**
+ * @brief Evaluates if a reschedule is required.
+ *
+ * @retval true if there is a thread that must go in running state
+ * immediately.
+ * @retval false if preemption is not required.
+ *
+ * @iclass
+ */
+#define chSchIsRescRequiredI() ((bool)(nil.current != nil.next))
+
+/**
+ * @brief Returns a pointer to the current @p thread_t.
+ *
+ * @xclass
+ */
+#define chThdGetSelfX() nil.current
+
+/**
+ * @brief Returns the current thread priority.
+ * @note Can be invoked in any context.
+ *
+ * @return The current thread priority.
+ *
+ * @xclass
+ */
+#define chThdGetPriorityX(void) (tprio_t)(nil.current - &nil.threads[0])
+
+/**
+ * @brief Wakes up a thread waiting on a thread reference object.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] msg the message code
+ *
+ * @sclass
+ */
+#define chThdResumeS(trp, msg) do { \
+ chThdResumeI(trp, msg); \
+ chSchRescheduleS(); \
+} while (false)
+
+/**
+ * @brief Delays the invoking thread for the specified number of seconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system clock.
+ * @note The maximum specified value is implementation dependent.
+ *
+ * @param[in] secs time in seconds, must be different from zero
+ *
+ * @api
+ */
+#define chThdSleepSeconds(secs) chThdSleep(TIME_S2I(secs))
+
+/**
+ * @brief Delays the invoking thread for the specified number of
+ * milliseconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system clock.
+ * @note The maximum specified value is implementation dependent.
+ *
+ * @param[in] msecs time in milliseconds, must be different from zero
+ *
+ * @api
+ */
+#define chThdSleepMilliseconds(msecs) chThdSleep(TIME_MS2I(msecs))
+
+/**
+ * @brief Delays the invoking thread for the specified number of
+ * microseconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system clock.
+ * @note The maximum specified value is implementation dependent.
+ *
+ * @param[in] usecs time in microseconds, must be different from zero
+ *
+ * @api
+ */
+#define chThdSleepMicroseconds(usecs) chThdSleep(TIME_US2I(usecs))
+
+/**
+ * @brief Suspends the invoking thread for the specified time.
+ *
+ * @param[in] timeout the delay in system ticks
+ *
+ * @sclass
+ */
+#define chThdSleepS(timeout) \
+ (void) chSchGoSleepTimeoutS(NIL_STATE_SLEEPING, timeout)
+
+/**
+ * @brief Suspends the invoking thread until the system time arrives to the
+ * specified value.
+ *
+ * @param[in] abstime absolute system time
+ *
+ * @sclass
+ */
+#define chThdSleepUntilS(abstime) \
+ (void) chSchGoSleepTimeoutS(NIL_STATE_SLEEPING, \
+ chTimeDiffX(chVTGetSystemTimeX(), (abstime)))
+
+/**
+ * @brief Initializes a threads queue object.
+ *
+ * @param[out] tqp pointer to the threads queue object
+ *
+ * @init
+ */
+#define chThdQueueObjectInit(tqp) ((tqp)->cnt = (cnt_t)0)
+
+/**
+ * @brief Evaluates to @p true if the specified queue is empty.
+ *
+ * @param[out] tqp pointer to the threads queue object
+ * @return The queue status.
+ * @retval false if the queue is not empty.
+ * @retval true if the queue is empty.
+ *
+ * @iclass
+ */
+#define chThdQueueIsEmptyI(tqp) ((bool)(tqp->cnt >= (cnt_t)0))
+
+/**
+ * @brief Current system time.
+ * @details Returns the number of system ticks since the @p chSysInit()
+ * invocation.
+ * @note The counter can reach its maximum and then restart from zero.
+ * @note This function can be called from any context but its atomicity
+ * is not guaranteed on architectures whose word size is less than
+ * @p systime_t size.
+ *
+ * @return The system time in ticks.
+ *
+ * @xclass
+ */
+#if (CH_CFG_ST_TIMEDELTA == 0) || defined(__DOXYGEN__)
+#define chVTGetSystemTimeX() (nil.systime)
+#else
+#define chVTGetSystemTimeX() port_timer_get_time()
+#endif
+
+/**
+ * @brief Returns the elapsed time since the specified start time.
+ *
+ * @param[in] start start time
+ * @return The elapsed time.
+ *
+ * @xclass
+ */
+#define chVTTimeElapsedSinceX(start) \
+ chTimeDiffX((start), chVTGetSystemTimeX())
+
+/**
+ * @brief Checks if the current system time is within the specified time
+ * window.
+ * @note When start==end then the function returns always false because the
+ * time window has zero size.
+ *
+ * @param[in] start the start of the time window (inclusive)
+ * @param[in] end the end of the time window (non inclusive)
+ * @retval true current time within the specified time window.
+ * @retval false current time not within the specified time window.
+ *
+ * @xclass
+ */
+#define chVTIsSystemTimeWithinX(start, end) \
+ chTimeIsInRangeX(chVTGetSystemTimeX(), start, end)
+
+/**
+ * @brief Adds an interval to a system time returning a system time.
+ *
+ * @param[in] systime base system time
+ * @param[in] interval interval to be added
+ * @return The new system time.
+ *
+ * @xclass
+ */
+#define chTimeAddX(systime, interval) \
+ ((systime_t)(systime) + (systime_t)(interval))
+
+/**
+ * @brief Subtracts two system times returning an interval.
+ *
+ * @param[in] start first system time
+ * @param[in] end second system time
+ * @return The interval representing the time difference.
+ *
+ * @xclass
+ */
+#define chTimeDiffX(start, end) \
+ ((sysinterval_t)((systime_t)((systime_t)(end) - (systime_t)(start))))
+
+/**
+ * @brief Function parameters check.
+ * @details If the condition check fails then the kernel panics and halts.
+ * @note The condition is tested only if the @p CH_DBG_ENABLE_CHECKS switch
+ * is specified in @p chconf.h else the macro does nothing.
+ *
+ * @param[in] c the condition to be verified to be true
+ *
+ * @api
+ */
+#if !defined(chDbgCheck)
+#define chDbgCheck(c) do { \
+ /*lint -save -e506 -e774 [2.1, 14.3] Can be a constant by design.*/ \
+ if (CH_DBG_ENABLE_CHECKS != FALSE) { \
+ if (!(c)) { \
+ /*lint -restore*/ \
+ chSysHalt(__func__); \
+ } \
+ } \
+} while (false)
+#endif /* !defined(chDbgCheck) */
+
+/**
+ * @brief Condition assertion.
+ * @details If the condition check fails then the kernel panics with a
+ * message and halts.
+ * @note The condition is tested only if the @p CH_DBG_ENABLE_ASSERTS
+ * switch is specified in @p chconf.h else the macro does nothing.
+ * @note The remark string is not currently used except for putting a
+ * comment in the code about the assertion.
+ *
+ * @param[in] c the condition to be verified to be true
+ * @param[in] r a remark string
+ *
+ * @api
+ */
+#if !defined(chDbgAssert)
+#define chDbgAssert(c, r) do { \
+ /*lint -save -e506 -e774 [2.1, 14.3] Can be a constant by design.*/ \
+ if (CH_DBG_ENABLE_ASSERTS != FALSE) { \
+ if (!(c)) { \
+ /*lint -restore*/ \
+ chSysHalt(__func__); \
+ } \
+ } \
+} while (false)
+#endif /* !defined(chDbgAssert) */
+/** @} */
+
+/* Empty macros if the state checker is not enabled.*/
+#if CH_DBG_SYSTEM_STATE_CHECK == FALSE
+#define _dbg_enter_lock()
+#define _dbg_leave_lock()
+#define _dbg_check_disable()
+#define _dbg_check_suspend()
+#define _dbg_check_enable()
+#define _dbg_check_lock()
+#define _dbg_check_unlock()
+#define _dbg_check_lock_from_isr()
+#define _dbg_check_unlock_from_isr()
+#define _dbg_check_enter_isr()
+#define _dbg_check_leave_isr()
+#define chDbgCheckClassI()
+#define chDbgCheckClassS()
+#endif
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || defined(__DOXYGEN__)
+extern stkalign_t __main_thread_stack_base__, __main_thread_stack_end__;
+#endif
+extern nil_system_t nil;
+extern const thread_descriptor_t nil_thd_configs[];
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ thread_t *nil_find_thread(tstate_t state, void *p);
+ cnt_t nil_ready_all(void *p, cnt_t cnt, msg_t msg);
+ void chSysInit(void);
+ void chSysHalt(const char *reason);
+ void chSysTimerHandlerI(void);
+ void chSysUnconditionalLock(void);
+ void chSysUnconditionalUnlock(void);
+ syssts_t chSysGetStatusAndLockX(void);
+ bool chSysIsCounterWithinX(rtcnt_t cnt, rtcnt_t start, rtcnt_t end);
+ void chSysPolledDelayX(rtcnt_t cycles);
+ void chSysRestoreStatusX(syssts_t sts);
+ thread_t *chSchReadyI(thread_t *tp, msg_t msg);
+ bool chSchIsPreemptionRequired(void);
+ void chSchDoReschedule(void);
+ void chSchRescheduleS(void);
+ msg_t chSchGoSleepTimeoutS(tstate_t newstate, sysinterval_t timeout);
+ bool chTimeIsInRangeX(systime_t time, systime_t start, systime_t end);
+ thread_t *chThdCreateI(const thread_descriptor_t *tdp);
+ thread_t *chThdCreate(const thread_descriptor_t *tdp);
+ void chThdExit(msg_t msg);
+#if CH_CFG_USE_WAITEXIT == TRUE
+ msg_t chThdWait(thread_t *tp);
+#endif
+ msg_t chThdSuspendTimeoutS(thread_reference_t *trp, sysinterval_t timeout);
+ void chThdResumeI(thread_reference_t *trp, msg_t msg);
+ void chThdResume(thread_reference_t *trp, msg_t msg);
+ void chThdSleep(sysinterval_t timeout);
+ void chThdSleepUntil(systime_t abstime);
+ msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout);
+ void chThdDoDequeueNextI(threads_queue_t *tqp, msg_t msg);
+ void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg);
+ void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg);
+#if CH_DBG_SYSTEM_STATE_CHECK == TRUE
+ void _dbg_check_disable(void);
+ void _dbg_check_suspend(void);
+ void _dbg_check_enable(void);
+ void _dbg_check_lock(void);
+ void _dbg_check_unlock(void);
+ void _dbg_check_lock_from_isr(void);
+ void _dbg_check_unlock_from_isr(void);
+ void _dbg_check_enter_isr(void);
+ void _dbg_check_leave_isr(void);
+ void chDbgCheckClassI(void);
+ void chDbgCheckClassS(void);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* Optional modules.*/
+#include "chsem.h"
+#include "chevt.h"
+#include "chmsg.h"
+#include "chlib.h"
+
+#endif /* CH_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/nil/include/chevt.h b/ChibiOS_20.3.2/os/nil/include/chevt.h
new file mode 100644
index 0000000..7d74461
--- /dev/null
+++ b/ChibiOS_20.3.2/os/nil/include/chevt.h
@@ -0,0 +1,301 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file nil/include/chevt.h
+ * @brief Nil RTOS events header file.
+ *
+ * @addtogroup NIL_EVENTS
+ * @{
+ */
+
+#ifndef CHEVT_H
+#define CHEVT_H
+
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+typedef struct event_listener event_listener_t;
+
+/**
+ * @brief Event Listener structure.
+ */
+struct event_listener {
+ event_listener_t *next; /**< @brief Next Event Listener
+ registered on the event
+ source. */
+ thread_t *listener; /**< @brief Thread interested in the
+ event source. */
+ eventmask_t events; /**< @brief Events to be set in
+ the listening thread. */
+ eventflags_t flags; /**< @brief Flags added to the listener
+ by the event source. */
+ eventflags_t wflags; /**< @brief Flags that this listener
+ interested in. */
+};
+
+/**
+ * @brief Event Source structure.
+ */
+typedef struct event_source {
+ event_listener_t *next; /**< @brief First Event Listener
+ registered on the Event
+ Source. */
+} event_source_t;
+
+/**
+ * @brief Event Handler callback function.
+ */
+typedef void (*evhandler_t)(eventid_t id);
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief All events allowed mask.
+ */
+#define ALL_EVENTS ((eventmask_t)-1)
+
+/**
+ * @brief Returns an event mask from an event identifier.
+ */
+#define EVENT_MASK(eid) ((eventmask_t)1 << (eventmask_t)(eid))
+
+/**
+ * @brief Data part of a static event source initializer.
+ * @details This macro should be used when statically initializing an event
+ * source that is part of a bigger structure.
+ * @param name the name of the event source variable
+ */
+#define _EVENTSOURCE_DATA(name) {(event_listener_t *)(&name)}
+
+/**
+ * @brief Static event source initializer.
+ * @details Statically initialized event sources require no explicit
+ * initialization using @p chEvtInit().
+ *
+ * @param name the name of the event source variable
+ */
+#define EVENTSOURCE_DECL(name) event_source_t name = _EVENTSOURCE_DATA(name)
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Initializes an Event Source.
+ * @note This function can be invoked before the kernel is initialized
+ * because it just prepares a @p event_source_t structure.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ *
+ * @init
+ */
+#define chEvtObjectInit(esp) do { \
+ (esp)->next = (event_listener_t *)(esp); \
+} while (0)
+
+/**
+ * @brief Registers an Event Listener on an Event Source.
+ * @details Once a thread has registered as listener on an event source it
+ * will be notified of all events broadcasted there.
+ * @note Multiple Event Listeners can specify the same bits to be ORed to
+ * different threads.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ * @param[out] elp pointer to the @p event_listener_t structure
+ * @param[in] events the mask of events to be ORed to the thread when
+ * the event source is broadcasted
+ *
+ * @api
+ */
+#define chEvtRegisterMask(esp, elp, events) \
+ chEvtRegisterMaskWithFlags(esp, elp, events, (eventflags_t)-1)
+
+/**
+ * @brief Registers an Event Listener on an Event Source.
+ * @note Multiple Event Listeners can use the same event identifier, the
+ * listener will share the callback function.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ * @param[out] elp pointer to the @p event_listener_t structure
+ * @param[in] event numeric identifier assigned to the Event Listener.
+ * The value must range between zero and the size, in bit,
+ * of the @p eventmask_t type minus one.
+ *
+ * @api
+ */
+#define chEvtRegister(esp, elp, event) \
+ chEvtRegisterMask(esp, elp, EVENT_MASK(event))
+
+/**
+ * @brief Verifies if there is at least one @p event_listener_t registered.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ * @return The event source status.
+ *
+ * @iclass
+ */
+#define chEvtIsListeningI(esp) (bool)((esp) != (event_source_t *)(esp)->next)
+
+/**
+ * @brief Signals all the Event Listeners registered on the specified Event
+ * Source.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ *
+ * @api
+ */
+#define chEvtBroadcast(esp) chEvtBroadcastFlags(esp, (eventflags_t)0)
+
+/**
+ * @brief Signals all the Event Listeners registered on the specified Event
+ * Source.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ *
+ * @iclass
+ */
+#define chEvtBroadcastI(esp) chEvtBroadcastFlagsI(esp, (eventflags_t)0)
+
+/**
+ * @brief Adds (OR) a set of events to the current thread, this is
+ * @b much faster than using @p chEvtBroadcast() or @p chEvtSignal().
+ *
+ * @param[in] events the events to be added
+ * @return The mask of currently pending events.
+ *
+ * @iclass
+ */
+#define chEvtAddEventsI(events) (nil.current->epmask |= events)
+
+/**
+ * @brief Returns the events mask.
+ * @details The pending events mask is returned but not altered in any way.
+ *
+ * @return The pending events mask.
+ *
+ * @api
+ */
+#define chEvtGetEventsX(void) (nil.current->epmask)
+
+/**
+ * @brief Waits for exactly one of the specified events.
+ * @details The function waits for one event among those specified in
+ * @p events to become pending then the event is cleared and returned.
+ * @note One and only one event is served in the function, the one with the
+ * lowest event id. The function is meant to be invoked into a loop
+ * in order to serve all the pending events.
+ * This means that Event Listeners with a lower event identifier have
+ * an higher priority.
+ *
+ * @param[in] events events that the function should wait
+ * for, @p ALL_EVENTS enables all the events
+ * @return The mask of the lowest event id served and cleared.
+ * @retval 0 if the operation has timed out.
+ *
+ * @api
+ */
+#define chEvtWaitOne(events) chEvtWaitOneTimeout(events, TIME_INFINITE)
+
+/**
+ * @brief Waits for any of the specified events.
+ * @details The function waits for any event among those specified in
+ * @p mask to become pending then the events are cleared and
+ * returned.
+ *
+ * @param[in] events events that the function should wait
+ * for, @p ALL_EVENTS enables all the events
+ * @return The mask of the served and cleared events.
+ * @retval 0 if the operation has timed out.
+ *
+ * @api
+ */
+#define chEvtWaitAny(events) chEvtWaitAnyTimeout(events, TIME_INFINITE)
+
+/**
+ * @brief Waits for all the specified events.
+ * @details The function waits for all the events specified in @p mask to
+ * become pending then the events are cleared and returned.
+ *
+ * @param[in] events events that the function should wait
+ * for, @p ALL_EVENTS enables all the events
+ * @return The mask of the served and cleared events.
+ * @retval 0 if the operation has timed out.
+ *
+ * @api
+ */
+#define chEvtWaitAll(events) chEvtWaitAllTimeout(events, TIME_INFINITE)
+
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chEvtRegisterMaskWithFlags(event_source_t *esp,
+ event_listener_t *elp,
+ eventmask_t events,
+ eventflags_t wflags);
+ void chEvtUnregister(event_source_t *esp, event_listener_t *elp);
+ eventmask_t chEvtGetAndClearEventsI(eventmask_t events);
+ eventmask_t chEvtGetAndClearEvents(eventmask_t events);
+ eventmask_t chEvtAddEvents(eventmask_t events);
+ eventflags_t chEvtGetAndClearFlags(event_listener_t *elp);
+ eventflags_t chEvtGetAndClearFlagsI(event_listener_t *elp);
+ void chEvtSignal(thread_t *tp, eventmask_t events);
+ void chEvtSignalI(thread_t *tp, eventmask_t events);
+ void chEvtBroadcastFlags(event_source_t *esp, eventflags_t flags);
+ void chEvtBroadcastFlagsI(event_source_t *esp, eventflags_t flags);
+ void chEvtDispatch(const evhandler_t *handlers, eventmask_t events);
+ eventmask_t chEvtWaitOneTimeout(eventmask_t events, sysinterval_t timeout);
+ eventmask_t chEvtWaitAnyTimeout(eventmask_t mask, sysinterval_t timeout);
+ eventmask_t chEvtWaitAllTimeout(eventmask_t mask, sysinterval_t timeout);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CH_CFG_USE_EVENTS == TRUE */
+
+#endif /* CHEVT_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/nil/include/chmsg.h b/ChibiOS_20.3.2/os/nil/include/chmsg.h
new file mode 100644
index 0000000..abe1de7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/nil/include/chmsg.h
@@ -0,0 +1,123 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file nil/include/chmsg.h
+ * @brief Nil RTOS synchronous messages header file.
+ *
+ * @addtogroup NIL_MESSAGES
+ * @{
+ */
+
+#ifndef CHMSG_H
+#define CHMSG_H
+
+#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Suspends the thread and waits for an incoming message.
+ * @post After receiving a message the function @p chMsgGet() must be
+ * called in order to retrieve the message and then @p chMsgRelease()
+ * must be invoked in order to acknowledge the reception and send
+ * the answer.
+ * @note If the message is a pointer then you can assume that the data
+ * pointed by the message is stable until you invoke @p chMsgRelease()
+ * because the sending thread is suspended until then.
+ * @note The reference counter of the sender thread is not increased, the
+ * returned pointer is a temporary reference.
+ *
+ * @return A pointer to the thread carrying the message.
+ *
+ * @sclass
+ */
+#define chMsgWaitS() chMsgWaitTimeoutS(TIME_INFINITE)
+
+/**
+ * @brief Returns the message carried by the specified thread.
+ * @pre This function must be invoked immediately after exiting a call
+ * to @p chMsgWait().
+ *
+ * @param[in] tp pointer to the thread
+ * @return The message carried by the sender.
+ *
+ * @api
+ */
+#define chMsgGet(tp) ((tp)->sntmsg)
+
+/**
+ * @brief Releases the thread waiting on top of the messages queue.
+ * @pre Invoke this function only after a message has been received
+ * using @p chMsgWait().
+ *
+ * @param[in] tp pointer to the thread
+ * @param[in] msg message to be returned to the sender
+ *
+ * @sclass
+ */
+#define chMsgReleaseS(tp, msg) do { \
+ (void) chSchReadyI(tp, msg); \
+ chSchRescheduleS(); \
+ } while (false)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ msg_t chMsgSend(thread_t *tp, msg_t msg);
+ thread_t *chMsgWait(void);
+ thread_t *chMsgWaitTimeout(sysinterval_t timeout);
+ thread_t *chMsgWaitTimeoutS(sysinterval_t timeout);
+ void chMsgRelease(thread_t *tp, msg_t msg);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CH_CFG_USE_MESSAGES == TRUE */
+
+#endif /* CHMSG_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/nil/include/chsem.h b/ChibiOS_20.3.2/os/nil/include/chsem.h
new file mode 100644
index 0000000..7caad00
--- /dev/null
+++ b/ChibiOS_20.3.2/os/nil/include/chsem.h
@@ -0,0 +1,180 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file nil/include/chsem.h
+ * @brief Nil RTOS semaphores header file.
+ *
+ * @addtogroup NIL_SEMAPHORES
+ * @{
+ */
+
+#ifndef CHSEM_H
+#define CHSEM_H
+
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Initializes a semaphore with the specified counter value.
+ *
+ * @param[out] sp pointer to a @p semaphore_t structure
+ * @param[in] n initial value of the semaphore counter. Must be
+ * non-negative.
+ *
+ * @init
+ */
+#define chSemObjectInit(sp, n) ((sp)->cnt = (n))
+
+/**
+ * @brief Performs a reset operation on the semaphore.
+ * @post After invoking this function all the threads waiting on the
+ * semaphore, if any, are released and the semaphore counter is set
+ * to the specified, non negative, value.
+ * @note This function implicitly sends @p MSG_RESET as message.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @param[in] n the new value of the semaphore counter. The value must
+ * be non-negative.
+ *
+ * @api
+ */
+#define chSemReset(sp, n) chSemResetWithMessage(sp, n, MSG_RESET)
+
+/**
+ * @brief Performs a reset operation on the semaphore.
+ * @post After invoking this function all the threads waiting on the
+ * semaphore, if any, are released and the semaphore counter is set
+ * to the specified, non negative, value.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ * @note This function implicitly sends @p MSG_RESET as message.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @param[in] n the new value of the semaphore counter. The value must
+ * be non-negative.
+ *
+ * @iclass
+ */
+#define chSemResetI(sp, n) chSemResetWithMessageI(sp, n, MSG_RESET)
+
+/**
+ * @brief Performs a wait operation on a semaphore.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @return A message specifying how the invoking thread has been
+ * released from the semaphore.
+ * @retval CH_MSG_OK if the thread has not stopped on the semaphore or the
+ * semaphore has been signaled.
+ * @retval CH_MSG_RST if the semaphore has been reset using @p chSemReset().
+ *
+ * @api
+ */
+#define chSemWait(sp) chSemWaitTimeout(sp, TIME_INFINITE)
+
+/**
+ * @brief Performs a wait operation on a semaphore.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @return A message specifying how the invoking thread has been
+ * released from the semaphore.
+ * @retval CH_MSG_OK if the thread has not stopped on the semaphore or the
+ * semaphore has been signaled.
+ * @retval CH_MSG_RST if the semaphore has been reset using @p chSemReset().
+ *
+ * @sclass
+ */
+#define chSemWaitS(sp) chSemWaitTimeoutS(sp, TIME_INFINITE)
+
+/**
+ * @brief Decreases the semaphore counter.
+ * @details This macro can be used when the counter is known to be positive.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ *
+ * @iclass
+ */
+#define chSemFastWaitI(sp) ((sp)->cnt--)
+
+/**
+ * @brief Increases the semaphore counter.
+ * @details This macro can be used when the counter is known to be not
+ * negative.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ *
+ * @iclass
+ */
+#define chSemFastSignalI(sp) ((sp)->cnt++)
+
+/**
+ * @brief Returns the semaphore counter current value.
+ *
+ * @iclass
+ */
+#define chSemGetCounterI(sp) ((sp)->cnt)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ msg_t chSemWaitTimeout(semaphore_t *sp, sysinterval_t timeout);
+ msg_t chSemWaitTimeoutS(semaphore_t *sp, sysinterval_t timeout);
+ void chSemSignal(semaphore_t *sp);
+ void chSemSignalI(semaphore_t *sp);
+ void chSemResetWithMessage(semaphore_t *sp, cnt_t n, msg_t msg);
+ void chSemResetWithMessageI(semaphore_t *sp, cnt_t n, msg_t msg);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
+
+#endif /* CHSEM_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/nil/nil.mk b/ChibiOS_20.3.2/os/nil/nil.mk
new file mode 100644
index 0000000..165b0e5
--- /dev/null
+++ b/ChibiOS_20.3.2/os/nil/nil.mk
@@ -0,0 +1,42 @@
+# List of all the ChibiOS/NIL kernel files, there is no need to remove the files
+# from this list, you can disable parts of the kernel by editing chconf.h.
+ifeq ($(USE_SMART_BUILD),yes)
+
+# Configuration files directory
+ifeq ($(CHCONFDIR),)
+ ifeq ($(CONFDIR),)
+ CHCONFDIR = .
+ else
+ CHCONFDIR := $(CONFDIR)
+ endif
+endif
+
+CHCONF := $(strip $(shell cat $(CHCONFDIR)/chconf.h | egrep -e "\#define"))
+
+KERNSRC := ${CHIBIOS}/os/nil/src/ch.c
+ifneq ($(findstring CH_CFG_USE_EVENTS TRUE,$(CHCONF)),)
+KERNSRC += $(CHIBIOS)/os/nil/src/chevt.c
+endif
+ifneq ($(findstring CH_CFG_USE_MESSAGES TRUE,$(CHCONF)),)
+KERNSRC += $(CHIBIOS)/os/nil/src/chmsg.c
+endif
+ifneq ($(findstring CH_CFG_USE_SEMAPHORES TRUE,$(CHCONF)),)
+KERNSRC += $(CHIBIOS)/os/nil/src/chsem.c
+endif
+
+else
+KERNSRC := ${CHIBIOS}/os/nil/src/ch.c \
+ ${CHIBIOS}/os/nil/src/chevt.c
+ ${CHIBIOS}/os/nil/src/chmsg.c \
+ ${CHIBIOS}/os/nil/src/chsem.c
+endif
+
+# Required include directories
+KERNINC := ${CHIBIOS}/os/nil/include
+
+# Shared variables
+ALLCSRC += $(KERNSRC)
+ALLINC += $(KERNINC)
+
+# OS Library
+include $(CHIBIOS)/os/oslib/oslib.mk
diff --git a/ChibiOS_20.3.2/os/nil/src/ch.c b/ChibiOS_20.3.2/os/nil/src/ch.c
new file mode 100644
index 0000000..35df8b6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/nil/src/ch.c
@@ -0,0 +1,1080 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file nil/src/ch.c
+ * @brief Nil RTOS main source file.
+ *
+ * @addtogroup NIL_KERNEL
+ * @{
+ */
+
+#include "ch.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief System data structures.
+ */
+nil_system_t nil;
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Retrieves the highest priority thread in the specified state and
+ * associated to the specified object.
+ *
+ * @param[in] state thread state
+ * @param[in] p object pointer
+ * @return The pointer to the found thread.
+ * @retval NULL if the thread is not found.
+ *
+ * @notapi
+ */
+thread_t *nil_find_thread(tstate_t state, void *p) {
+ thread_t *tp = nil.threads;
+
+ while (tp < &nil.threads[CH_CFG_MAX_THREADS]) {
+ /* Is this thread matching?*/
+ if ((tp->state == state) && (tp->u1.p == p)) {
+ return tp;
+ }
+ tp++;
+ }
+ return NULL;
+}
+
+/**
+ * @brief Puts in ready state all thread matching the specified status and
+ * associated object.
+ *
+ * @param[in] p object pointer
+ * @param[in] cnt number of threads to be readied as a negative number,
+ * non negative numbers are ignored
+ * @param[in] msg the wakeup message
+ * @return The number of readied threads.
+ *
+ * @notapi
+ */
+cnt_t nil_ready_all(void *p, cnt_t cnt, msg_t msg) {
+ thread_t *tp = nil.threads;;
+
+ while (cnt < (cnt_t)0) {
+
+ chDbgAssert(tp < &nil.threads[CH_CFG_MAX_THREADS],
+ "pointer out of range");
+
+ /* Is this thread waiting on this queue?*/
+ if ((tp->state == NIL_STATE_WTQUEUE) && (tp->u1.p == p)) {
+ cnt++;
+ (void) chSchReadyI(tp, msg);
+ }
+ tp++;
+ }
+
+ return cnt;
+}
+
+#if (CH_DBG_SYSTEM_STATE_CHECK == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Guard code for @p chSysDisable().
+ *
+ * @notapi
+ */
+void _dbg_check_disable(void) {
+
+ if ((nil.isr_cnt != (cnt_t)0) || (nil.lock_cnt != (cnt_t)0)) {
+ chSysHalt("SV#1");
+ }
+}
+
+/**
+ * @brief Guard code for @p chSysSuspend().
+ *
+ * @notapi
+ */
+void _dbg_check_suspend(void) {
+
+ if ((nil.isr_cnt != (cnt_t)0) || (nil.lock_cnt != (cnt_t)0)) {
+ chSysHalt("SV#2");
+ }
+}
+
+/**
+ * @brief Guard code for @p chSysEnable().
+ *
+ * @notapi
+ */
+void _dbg_check_enable(void) {
+
+ if ((nil.isr_cnt != (cnt_t)0) || (nil.lock_cnt != (cnt_t)0)) {
+ chSysHalt("SV#3");
+ }
+}
+
+/**
+ * @brief Guard code for @p chSysLock().
+ *
+ * @notapi
+ */
+void _dbg_check_lock(void) {
+
+ if ((nil.isr_cnt != (cnt_t)0) || (nil.lock_cnt != (cnt_t)0)) {
+ chSysHalt("SV#4");
+ }
+ _dbg_enter_lock();
+}
+
+/**
+ * @brief Guard code for @p chSysUnlock().
+ *
+ * @notapi
+ */
+void _dbg_check_unlock(void) {
+
+ if ((nil.isr_cnt != (cnt_t)0) || (nil.lock_cnt <= (cnt_t)0)) {
+ chSysHalt("SV#5");
+ }
+ _dbg_leave_lock();
+}
+
+/**
+ * @brief Guard code for @p chSysLockFromIsr().
+ *
+ * @notapi
+ */
+void _dbg_check_lock_from_isr(void) {
+
+ if ((nil.isr_cnt <= (cnt_t)0) || (nil.lock_cnt != (cnt_t)0)) {
+ chSysHalt("SV#6");
+ }
+ _dbg_enter_lock();
+}
+
+/**
+ * @brief Guard code for @p chSysUnlockFromIsr().
+ *
+ * @notapi
+ */
+void _dbg_check_unlock_from_isr(void) {
+
+ if ((nil.isr_cnt <= (cnt_t)0) || (nil.lock_cnt <= (cnt_t)0)) {
+ chSysHalt("SV#7");
+ }
+ _dbg_leave_lock();
+}
+
+/**
+ * @brief Guard code for @p CH_IRQ_PROLOGUE().
+ *
+ * @notapi
+ */
+void _dbg_check_enter_isr(void) {
+
+ port_lock_from_isr();
+ if ((nil.isr_cnt < (cnt_t)0) || (nil.lock_cnt != (cnt_t)0)) {
+ chSysHalt("SV#8");
+ }
+ nil.isr_cnt++;
+ port_unlock_from_isr();
+}
+
+/**
+ * @brief Guard code for @p CH_IRQ_EPILOGUE().
+ *
+ * @notapi
+ */
+void _dbg_check_leave_isr(void) {
+
+ port_lock_from_isr();
+ if ((nil.isr_cnt <= (cnt_t)0) || (nil.lock_cnt != (cnt_t)0)) {
+ chSysHalt("SV#9");
+ }
+ nil.isr_cnt--;
+ port_unlock_from_isr();
+}
+
+/**
+ * @brief I-class functions context check.
+ * @details Verifies that the system is in an appropriate state for invoking
+ * an I-class API function. A panic is generated if the state is
+ * not compatible.
+ *
+ * @api
+ */
+void chDbgCheckClassI(void) {
+
+ if ((nil.isr_cnt < (cnt_t)0) || (nil.lock_cnt <= (cnt_t)0)) {
+ chSysHalt("SV#10");
+ }
+}
+
+/**
+ * @brief S-class functions context check.
+ * @details Verifies that the system is in an appropriate state for invoking
+ * an S-class API function. A panic is generated if the state is
+ * not compatible.
+ *
+ * @api
+ */
+void chDbgCheckClassS(void) {
+
+ if ((nil.isr_cnt != (cnt_t)0) || (nil.lock_cnt <= (cnt_t)0)) {
+ chSysHalt("SV#11");
+ }
+}
+#endif /* CH_DBG_SYSTEM_STATE_CHECK == TRUE */
+
+/**
+ * @brief Initializes the kernel.
+ * @details Initializes the kernel structures, the current instructions flow
+ * becomes the idle thread upon return. The idle thread must not
+ * invoke any kernel primitive able to change state to not runnable.
+ * @note This function assumes that the @p nil global variable has been
+ * zeroed by the runtime environment. If this is not the case then
+ * make sure to clear it before calling this function.
+ *
+ * @special
+ */
+void chSysInit(void) {
+ const thread_descriptor_t *tdp;
+
+ /* Optional library modules.*/
+ _oslib_init();
+
+ /* Architecture layer initialization.*/
+ port_init();
+
+ /* System initialization hook.*/
+ CH_CFG_SYSTEM_INIT_HOOK();
+
+ /* Making idle the current thread, this may change after rescheduling.*/
+ nil.next = nil.current = &nil.threads[CH_CFG_MAX_THREADS];
+ nil.current->state = NIL_STATE_READY;
+
+#if CH_DBG_ENABLE_STACK_CHECK == TRUE
+ /* The idle thread is a special case because its stack is set up by the
+ runtime environment.*/
+ nil.threads[CH_CFG_MAX_THREADS].wabase = THD_IDLE_BASE;
+#endif
+
+ /* Interrupts partially enabled. It is equivalent to entering the
+ kernel critical zone.*/
+ chSysSuspend();
+#if CH_DBG_SYSTEM_STATE_CHECK == TRUE
+ nil.lock_cnt = (cnt_t)1;
+#endif
+
+#if CH_CFG_AUTOSTART_THREADS == TRUE
+ /* Iterates through the list of threads to be auto-started.*/
+ tdp = nil_thd_configs;
+ do {
+ (void) chThdCreateI(tdp);
+ tdp++;
+ } while (tdp->funcp != NULL);
+#endif
+
+ /* Starting the dance.*/
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+/**
+ * @brief Halts the system.
+ * @details This function is invoked by the operating system when an
+ * unrecoverable error is detected, for example because a programming
+ * error in the application code that triggers an assertion while
+ * in debug mode.
+ * @note Can be invoked from any system state.
+ *
+ * @param[in] reason pointer to an error string
+ *
+ * @special
+ */
+void chSysHalt(const char *reason) {
+
+ port_disable();
+
+#if NIL_DBG_ENABLED
+ nil.dbg_panic_msg = reason;
+#else
+ (void)reason;
+#endif
+
+ /* Halt hook code, usually empty.*/
+ CH_CFG_SYSTEM_HALT_HOOK(reason);
+
+ /* Harmless infinite loop.*/
+ while (true) {
+ }
+}
+
+/**
+ * @brief Time management handler.
+ * @note This handler has to be invoked by a periodic ISR in order to
+ * reschedule the waiting threads.
+ *
+ * @iclass
+ */
+void chSysTimerHandlerI(void) {
+
+ chDbgCheckClassI();
+
+#if CH_CFG_ST_TIMEDELTA == 0
+ thread_t *tp = &nil.threads[0];
+ nil.systime++;
+ do {
+ /* Is the thread in a wait state with timeout?.*/
+ if (tp->timeout > (sysinterval_t)0) {
+
+ chDbgAssert(!NIL_THD_IS_READY(tp), "is ready");
+
+ /* Did the timer reach zero?*/
+ if (--tp->timeout == (sysinterval_t)0) {
+ /* Timeout on queues/semaphores requires a special handling because
+ the counter must be incremented.*/
+ /*lint -save -e9013 [15.7] There is no else because it is not needed.*/
+#if CH_CFG_USE_SEMAPHORES == TRUE
+ if (NIL_THD_IS_WTQUEUE(tp)) {
+ tp->u1.semp->cnt++;
+ }
+ else
+#endif
+ if (NIL_THD_IS_SUSPENDED(tp)) {
+ *tp->u1.trp = NULL;
+ }
+ /*lint -restore*/
+ (void) chSchReadyI(tp, MSG_TIMEOUT);
+ }
+ }
+ /* Lock released in order to give a preemption chance on those
+ architectures supporting IRQ preemption.*/
+ chSysUnlockFromISR();
+ tp++;
+ chSysLockFromISR();
+ } while (tp < &nil.threads[CH_CFG_MAX_THREADS]);
+#else
+ thread_t *tp = &nil.threads[0];
+ sysinterval_t next = (sysinterval_t)0;
+
+ chDbgAssert(nil.nexttime == port_timer_get_alarm(), "time mismatch");
+
+ do {
+ sysinterval_t timeout = tp->timeout;
+
+ /* Is the thread in a wait state with timeout?.*/
+ if (timeout > (sysinterval_t)0) {
+
+ chDbgAssert(!NIL_THD_IS_READY(tp), "is ready");
+ chDbgAssert(timeout >= chTimeDiffX(nil.lasttime, nil.nexttime),
+ "skipped one");
+
+ /* The volatile field is updated once, here.*/
+ timeout -= chTimeDiffX(nil.lasttime, nil.nexttime);
+ tp->timeout = timeout;
+
+ if (timeout == (sysinterval_t)0) {
+ /* Timeout on thread queues requires a special handling because the
+ counter must be incremented.*/
+ if (NIL_THD_IS_WTQUEUE(tp)) {
+ tp->u1.tqp->cnt++;
+ }
+ else {
+ if (NIL_THD_IS_SUSPENDED(tp)) {
+ *tp->u1.trp = NULL;
+ }
+ }
+ (void) chSchReadyI(tp, MSG_TIMEOUT);
+ }
+ else {
+ if (timeout <= (sysinterval_t)(next - (sysinterval_t)1)) {
+ next = timeout;
+ }
+ }
+ }
+
+ /* Lock released in order to give a preemption chance on those
+ architectures supporting IRQ preemption.*/
+ chSysUnlockFromISR();
+ tp++;
+ chSysLockFromISR();
+ } while (tp < &nil.threads[CH_CFG_MAX_THREADS]);
+
+ nil.lasttime = nil.nexttime;
+ if (next > (sysinterval_t)0) {
+ nil.nexttime = chTimeAddX(nil.nexttime, next);
+ port_timer_set_alarm(nil.nexttime);
+ }
+ else {
+ /* No tick event needed.*/
+ port_timer_stop_alarm();
+ }
+#endif
+}
+
+/**
+ * @brief Unconditionally enters the kernel lock state.
+ * @note Can be called without previous knowledge of the current lock state.
+ * The final state is "s-locked".
+ *
+ * @special
+ */
+void chSysUnconditionalLock(void) {
+
+ if (port_irq_enabled(port_get_irq_status())) {
+ chSysLock();
+ }
+}
+
+/**
+ * @brief Unconditionally leaves the kernel lock state.
+ * @note Can be called without previous knowledge of the current lock state.
+ * The final state is "normal".
+ *
+ * @special
+ */
+void chSysUnconditionalUnlock(void) {
+
+ if (!port_irq_enabled(port_get_irq_status())) {
+ chSysUnlock();
+ }
+}
+
+/**
+ * @brief Returns the execution status and enters a critical zone.
+ * @details This functions enters into a critical zone and can be called
+ * from any context. Because its flexibility it is less efficient
+ * than @p chSysLock() which is preferable when the calling context
+ * is known.
+ * @post The system is in a critical zone.
+ *
+ * @return The previous system status, the encoding of this
+ * status word is architecture-dependent and opaque.
+ *
+ * @xclass
+ */
+syssts_t chSysGetStatusAndLockX(void) {
+
+ syssts_t sts = port_get_irq_status();
+ if (port_irq_enabled(sts)) {
+ if (port_is_isr_context()) {
+ chSysLockFromISR();
+ }
+ else {
+ chSysLock();
+ }
+ }
+ return sts;
+}
+
+/**
+ * @brief Restores the specified execution status and leaves a critical zone.
+ * @note A call to @p chSchRescheduleS() is automatically performed
+ * if exiting the critical zone and if not in ISR context.
+ *
+ * @param[in] sts the system status to be restored.
+ *
+ * @xclass
+ */
+void chSysRestoreStatusX(syssts_t sts) {
+
+ if (port_irq_enabled(sts)) {
+ if (port_is_isr_context()) {
+ chSysUnlockFromISR();
+ }
+ else {
+ chSchRescheduleS();
+ chSysUnlock();
+ }
+ }
+}
+
+#if (PORT_SUPPORTS_RT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Realtime window test.
+ * @details This function verifies if the current realtime counter value
+ * lies within the specified range or not. The test takes care
+ * of the realtime counter wrapping to zero on overflow.
+ * @note When start==end then the function returns always false because a
+ * null time range is specified.
+ * @note This function is only available if the port layer supports the
+ * option @p PORT_SUPPORTS_RT.
+ *
+ * @param[in] cnt the counter value to be tested
+ * @param[in] start the start of the time window (inclusive)
+ * @param[in] end the end of the time window (non inclusive)
+ * @retval true current time within the specified time window.
+ * @retval false current time not within the specified time window.
+ *
+ * @xclass
+ */
+bool chSysIsCounterWithinX(rtcnt_t cnt, rtcnt_t start, rtcnt_t end) {
+
+ return (bool)(((rtcnt_t)cnt - (rtcnt_t)start) <
+ ((rtcnt_t)end - (rtcnt_t)start));
+}
+
+/**
+ * @brief Polled delay.
+ * @note The real delay is always few cycles in excess of the specified
+ * value.
+ * @note This function is only available if the port layer supports the
+ * option @p PORT_SUPPORTS_RT.
+ *
+ * @param[in] cycles number of cycles
+ *
+ * @xclass
+ */
+void chSysPolledDelayX(rtcnt_t cycles) {
+ rtcnt_t start = chSysGetRealtimeCounterX();
+ rtcnt_t end = start + cycles;
+
+ while (chSysIsCounterWithinX(chSysGetRealtimeCounterX(), start, end)) {
+ }
+}
+#endif /* PORT_SUPPORTS_RT == TRUE */
+
+/**
+ * @brief Makes the specified thread ready for execution.
+ *
+ * @param[in] tp pointer to the @p thread_t object
+ * @param[in] msg the wakeup message
+ *
+ * @return The same reference passed as parameter.
+ */
+thread_t *chSchReadyI(thread_t *tp, msg_t msg) {
+
+ chDbgCheckClassI();
+ chDbgCheck((tp >= nil.threads) && (tp < &nil.threads[CH_CFG_MAX_THREADS]));
+ chDbgAssert(!NIL_THD_IS_READY(tp), "already ready");
+ chDbgAssert(nil.next <= nil.current, "priority ordering");
+
+ tp->u1.msg = msg;
+ tp->state = NIL_STATE_READY;
+ tp->timeout = (sysinterval_t)0;
+ if (tp < nil.next) {
+ nil.next = tp;
+ }
+ return tp;
+}
+
+/**
+ * @brief Evaluates if preemption is required.
+ * @details The decision is taken by comparing the relative priorities and
+ * depending on the state of the round robin timeout counter.
+ * @note Not a user function, it is meant to be invoked by the scheduler
+ * itself or from within the port layer.
+ *
+ * @retval true if there is a thread that must go in running state
+ * immediately.
+ * @retval false if preemption is not required.
+ *
+ * @special
+ */
+bool chSchIsPreemptionRequired(void) {
+
+ return chSchIsRescRequiredI();
+}
+
+/**
+ * @brief Switches to the first thread on the runnable queue.
+ * @note Not a user function, it is meant to be invoked by the scheduler
+ * itself or from within the port layer.
+ *
+ * @special
+ */
+void chSchDoReschedule(void) {
+ thread_t *otp = nil.current;
+
+ nil.current = nil.next;
+ if (otp == &nil.threads[CH_CFG_MAX_THREADS]) {
+ CH_CFG_IDLE_LEAVE_HOOK();
+ }
+ port_switch(nil.next, otp);
+}
+
+/**
+ * @brief Reschedules if needed.
+ *
+ * @sclass
+ */
+void chSchRescheduleS(void) {
+
+ chDbgCheckClassS();
+
+ if (chSchIsRescRequiredI()) {
+ chSchDoReschedule();
+ }
+}
+
+/**
+ * @brief Puts the current thread to sleep into the specified state with
+ * timeout specification.
+ * @details The thread goes into a sleeping state, if it is not awakened
+ * explicitly within the specified system time then it is forcibly
+ * awakened with a @p MSG_TIMEOUT low level message.
+ *
+ * @param[in] newstate the new thread state or a semaphore pointer
+ * @param[in] timeout the number of ticks before the operation timeouts.
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The wakeup message.
+ * @retval MSG_TIMEOUT if a timeout occurred.
+ *
+ * @sclass
+ */
+msg_t chSchGoSleepTimeoutS(tstate_t newstate, sysinterval_t timeout) {
+ thread_t *ntp, *otp = nil.current;
+
+ chDbgCheckClassS();
+
+ chDbgAssert(otp != &nil.threads[CH_CFG_MAX_THREADS],
+ "idle cannot sleep");
+
+ /* Storing the wait object for the current thread.*/
+ otp->state = newstate;
+
+#if CH_CFG_ST_TIMEDELTA > 0
+ if (timeout != TIME_INFINITE) {
+ systime_t abstime;
+
+ /* TIMEDELTA makes sure to have enough time to reprogram the timer
+ before the free-running timer counter reaches the selected timeout.*/
+ if (timeout < (sysinterval_t)CH_CFG_ST_TIMEDELTA) {
+ timeout = (sysinterval_t)CH_CFG_ST_TIMEDELTA;
+ }
+
+ /* Absolute time of the timeout event.*/
+ abstime = chTimeAddX(chVTGetSystemTimeX(), timeout);
+
+ if (nil.lasttime == nil.nexttime) {
+ /* Special case, first thread asking for a timeout.*/
+ port_timer_start_alarm(abstime);
+ nil.nexttime = abstime;
+ }
+ else {
+ /* Special case, there are already other threads with a timeout
+ activated, evaluating the order.*/
+ if (chTimeIsInRangeX(abstime, nil.lasttime, nil.nexttime)) {
+ port_timer_set_alarm(abstime);
+ nil.nexttime = abstime;
+ }
+ }
+
+ /* Timeout settings.*/
+ otp->timeout = abstime - nil.lasttime;
+ }
+#else
+
+ /* Timeout settings.*/
+ otp->timeout = timeout;
+#endif
+
+ /* Scanning the whole threads array.*/
+ ntp = nil.threads;
+ while (true) {
+ /* Is this thread ready to execute?*/
+ if (NIL_THD_IS_READY(ntp)) {
+ nil.current = nil.next = ntp;
+ if (ntp == &nil.threads[CH_CFG_MAX_THREADS]) {
+ CH_CFG_IDLE_ENTER_HOOK();
+ }
+ port_switch(ntp, otp);
+ return nil.current->u1.msg;
+ }
+
+ /* Points to the next thread in lowering priority order.*/
+ ntp++;
+ chDbgAssert(ntp <= &nil.threads[CH_CFG_MAX_THREADS],
+ "pointer out of range");
+ }
+}
+
+/**
+ * @brief Checks if the specified time is within the specified time range.
+ * @note When start==end then the function returns always false because the
+ * time window has zero size.
+ *
+ * @param[in] time the time to be verified
+ * @param[in] start the start of the time window (inclusive)
+ * @param[in] end the end of the time window (non inclusive)
+ * @retval true current time within the specified time window.
+ * @retval false current time not within the specified time window.
+ *
+ * @xclass
+ */
+bool chTimeIsInRangeX(systime_t time, systime_t start, systime_t end) {
+
+ return (bool)((systime_t)((systime_t)(time) - (systime_t)(start)) <
+ (systime_t)((systime_t)(end) - (systime_t)(start)));
+}
+
+/**
+ * @brief Creates a new thread into a static memory area.
+ * @details The new thread is initialized and make ready to execute.
+ * @note A thread can terminate by calling @p chThdExit() or by simply
+ * returning from its main function.
+ *
+ * @param[out] tdp pointer to the thread descriptor structure
+ * @return The pointer to the @p thread_t structure allocated for
+ * the thread.
+ *
+ * @iclass
+ */
+thread_t *chThdCreateI(const thread_descriptor_t *tdp) {
+ thread_t *tp;
+
+ chDbgCheck((tdp->prio < (tprio_t)CH_CFG_MAX_THREADS) &&
+ (tdp->wbase != NULL) &&
+ MEM_IS_ALIGNED(tdp->wbase, PORT_WORKING_AREA_ALIGN) &&
+ (tdp->wend > tdp->wbase) &&
+ MEM_IS_ALIGNED(tdp->wbase, PORT_STACK_ALIGN) &&
+ (tdp->funcp != NULL));
+
+ chDbgCheckClassI();
+
+ /* Pointer to the thread slot to be used.*/
+ tp = &nil.threads[tdp->prio];
+ chDbgAssert(NIL_THD_IS_WTSTART(tp) || NIL_THD_IS_FINAL(tp),
+ "priority slot taken");
+
+#if CH_CFG_USE_EVENTS == TRUE
+ tp->epmask = (eventmask_t)0;
+#endif
+#if CH_DBG_ENABLE_STACK_CHECK == TRUE
+ tp->wabase = (stkalign_t *)tdp->wbase;
+#endif
+
+ /* Port dependent thread initialization.*/
+ PORT_SETUP_CONTEXT(tp, tdp->wbase, tdp->wend, tdp->funcp, tdp->arg);
+
+ /* Initialization hook.*/
+ CH_CFG_THREAD_EXT_INIT_HOOK(tp);
+
+ /* Readying up thread.*/
+ return chSchReadyI(tp, MSG_OK);
+}
+
+/**
+ * @brief Creates a new thread into a static memory area.
+ * @details The new thread is initialized and make ready to execute.
+ * @note A thread can terminate by calling @p chThdExit() or by simply
+ * returning from its main function.
+ *
+ * @param[out] tdp pointer to the thread descriptor structure
+ * @return The pointer to the @p thread_t structure allocated for
+ * the thread.
+ *
+ * @api
+ */
+thread_t *chThdCreate(const thread_descriptor_t *tdp) {
+ thread_t *tp;
+
+ chSysLock();
+ tp = chThdCreateI(tdp);
+ chSchRescheduleS();
+ chSysUnlock();
+
+ return tp;
+}
+
+/**
+ * @brief Terminates the current thread.
+ * @details The thread goes in the @p CH_STATE_FINAL state holding the
+ * specified exit status code, other threads can retrieve the
+ * exit status code by invoking the function @p chThdWait().
+ * @post Exiting a non-static thread that does not have references
+ * (detached) causes the thread to remain in the registry.
+ * It can only be removed by performing a registry scan operation.
+ * @post Eventual code after this function will never be executed,
+ * this function never returns. The compiler has no way to
+ * know this so do not assume that the compiler would remove
+ * the dead code.
+ *
+ * @param[in] msg thread exit code
+ *
+ * @api
+ */
+void chThdExit(msg_t msg) {
+
+ chSysLock();
+
+ /* Exit handler hook.*/
+ CH_CFG_THREAD_EXIT_HOOK(tp);
+
+#if CH_CFG_USE_WAITEXIT == TRUE
+ {
+ /* Waking up any waiting thread.*/
+ thread_t *tp = nil.threads;
+ while (tp < &nil.threads[CH_CFG_MAX_THREADS]) {
+ /* Is this thread waiting for current thread termination?*/
+ if ((tp->state == NIL_STATE_WTEXIT) && (tp->u1.tp == nil.current)) {
+ (void) chSchReadyI(tp, msg);
+ }
+ tp++;
+ }
+ }
+#endif
+
+ /* Going into final state with exit message stored.*/
+ nil.current->u1.msg = msg;
+ (void) chSchGoSleepTimeoutS(NIL_STATE_FINAL, TIME_INFINITE);
+
+ /* The thread never returns here.*/
+ chDbgAssert(false, "zombies apocalypse");
+}
+
+/**
+ * @brief Blocks the execution of the invoking thread until the specified
+ * thread terminates then the exit code is returned.
+ *
+ * @param[in] tp pointer to the thread
+ * @return The exit code from the terminated thread.
+ *
+ * @api
+ */
+msg_t chThdWait(thread_t *tp) {
+ msg_t msg;
+
+ chSysLock();
+ if (NIL_THD_IS_FINAL(tp)) {
+ msg = tp->u1.msg;
+ }
+ else {
+ nil.current->u1.tp = tp;
+ msg = chSchGoSleepTimeoutS(NIL_STATE_WTEXIT, TIME_INFINITE);
+ }
+ chSysUnlock();
+
+ return msg;
+}
+
+/**
+ * @brief Sends the current thread sleeping and sets a reference variable.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The wake up message.
+ *
+ * @sclass
+ */
+msg_t chThdSuspendTimeoutS(thread_reference_t *trp, sysinterval_t timeout) {
+
+ chDbgAssert(*trp == NULL, "not NULL");
+
+ if (TIME_IMMEDIATE == timeout) {
+ return MSG_TIMEOUT;
+ }
+
+ *trp = nil.current;
+ nil.current->u1.trp = trp;
+ return chSchGoSleepTimeoutS(NIL_STATE_SUSPENDED, timeout);
+}
+
+/**
+ * @brief Wakes up a thread waiting on a thread reference object.
+ * @note This function must not reschedule because it can be called from
+ * ISR context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void chThdResumeI(thread_reference_t *trp, msg_t msg) {
+
+ if (*trp != NULL) {
+ thread_reference_t tr = *trp;
+
+ chDbgAssert(NIL_THD_IS_SUSPENDED(tr), "not suspended");
+
+ *trp = NULL;
+ (void) chSchReadyI(tr, msg);
+ }
+}
+
+/**
+ * @brief Wakes up a thread waiting on a thread reference object.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] msg the message code
+ *
+ * @api
+ */
+void chThdResume(thread_reference_t *trp, msg_t msg) {
+
+ chSysLock();
+ chThdResumeS(trp, msg);
+ chSysUnlock();
+}
+
+/**
+ * @brief Suspends the invoking thread for the specified time.
+ *
+ * @param[in] timeout the delay in system ticks
+ *
+ * @api
+ */
+void chThdSleep(sysinterval_t timeout) {
+
+ chSysLock();
+ chThdSleepS(timeout);
+ chSysUnlock();
+}
+
+/**
+ * @brief Suspends the invoking thread until the system time arrives to the
+ * specified value.
+ *
+ * @param[in] abstime absolute system time
+ *
+ * @api
+ */
+void chThdSleepUntil(systime_t abstime) {
+
+ chSysLock();
+ chThdSleepUntilS(abstime);
+ chSysUnlock();
+}
+
+/**
+ * @brief Enqueues the caller thread on a threads queue object.
+ * @details The caller thread is enqueued and put to sleep until it is
+ * dequeued or the specified timeouts expires.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] timeout the timeout in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The message from @p osalQueueWakeupOneI() or
+ * @p osalQueueWakeupAllI() functions.
+ * @retval MSG_TIMEOUT if the thread has not been dequeued within the
+ * specified timeout or if the function has been
+ * invoked with @p TIME_IMMEDIATE as timeout
+ * specification.
+ *
+ * @sclass
+ */
+msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout) {
+
+ chDbgCheckClassS();
+ chDbgCheck(tqp != NULL);
+
+ chDbgAssert(tqp->cnt <= (cnt_t)0, "invalid counter");
+
+ if (TIME_IMMEDIATE == timeout) {
+ return MSG_TIMEOUT;
+ }
+
+ tqp->cnt--;
+ nil.current->u1.tqp = tqp;
+ return chSchGoSleepTimeoutS(NIL_STATE_WTQUEUE, timeout);
+}
+
+/**
+ * @brief Dequeues and wakes up one thread from the threads queue object.
+ * @details Dequeues one thread from the queue without checking if the queue
+ * is empty.
+ * @pre The queue must contain at least an object.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void chThdDoDequeueNextI(threads_queue_t *tqp, msg_t msg) {
+ thread_t *tp;
+
+ chDbgAssert(tqp->cnt < (cnt_t)0, "empty queue");
+
+ tqp->cnt++;
+ tp = nil_find_thread(NIL_STATE_WTQUEUE, (void *)tqp);
+
+ chDbgAssert(tp != NULL, "thread not found");
+
+ (void) chSchReadyI(tp, msg);
+}
+
+/**
+ * @brief Dequeues and wakes up one thread from the threads queue object,
+ * if any.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg) {
+
+ chDbgCheckClassI();
+ chDbgCheck(tqp != NULL);
+
+ if (tqp->cnt < (cnt_t)0) {
+ chThdDoDequeueNextI(tqp, msg);
+ }
+}
+
+/**
+ * @brief Dequeues and wakes up all threads from the threads queue object.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg) {
+
+ chDbgCheckClassI();
+ chDbgCheck(tqp != NULL);
+
+ tqp->cnt = nil_ready_all((void *)tqp, tqp->cnt, msg);
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/nil/src/chevt.c b/ChibiOS_20.3.2/os/nil/src/chevt.c
new file mode 100644
index 0000000..ed33af4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/nil/src/chevt.c
@@ -0,0 +1,478 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file nil/src/chevt.c
+ * @brief Nil RTOS events source file.
+ *
+ * @addtogroup NIL_EVENTS
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Registers an Event Listener on an Event Source.
+ * @details Once a thread has registered as listener on an event source it
+ * will be notified of all events broadcasted there.
+ * @note Multiple Event Listeners can specify the same bits to be ORed to
+ * different threads.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ * @param[in] elp pointer to the @p event_listener_t structure
+ * @param[in] events events to be ORed to the thread when
+ * the event source is broadcasted
+ * @param[in] wflags mask of flags the listening thread is interested in
+ *
+ * @api
+ */
+void chEvtRegisterMaskWithFlags(event_source_t *esp,
+ event_listener_t *elp,
+ eventmask_t events,
+ eventflags_t wflags) {
+
+ chDbgCheck((esp != NULL) && (elp != NULL));
+
+ chSysLock();
+ elp->next = esp->next;
+ esp->next = elp;
+ elp->listener = chThdGetSelfX();
+ elp->events = events;
+ elp->flags = (eventflags_t)0;
+ elp->wflags = wflags;
+ chSysUnlock();
+}
+
+/**
+ * @brief Unregisters an Event Listener from its Event Source.
+ * @note If the event listener is not registered on the specified event
+ * source then the function does nothing.
+ * @note For optimal performance it is better to perform the unregister
+ * operations in inverse order of the register operations (elements
+ * are found on top of the list).
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ * @param[in] elp pointer to the @p event_listener_t structure
+ *
+ * @api
+ */
+void chEvtUnregister(event_source_t *esp, event_listener_t *elp) {
+ event_listener_t *p;
+
+ chDbgCheck((esp != NULL) && (elp != NULL));
+
+ /*lint -save -e9087 -e740 [11.3, 1.3] Cast required by list handling.*/
+ p = (event_listener_t *)esp;
+ /*lint -restore*/
+ chSysLock();
+ /*lint -save -e9087 -e740 [11.3, 1.3] Cast required by list handling.*/
+ while (p->next != (event_listener_t *)esp) {
+ /*lint -restore*/
+ if (p->next == elp) {
+ p->next = elp->next;
+ break;
+ }
+ p = p->next;
+ }
+ chSysUnlock();
+}
+
+/**
+ * @brief Clears the pending events specified in the events mask.
+ *
+ * @param[in] events the events to be cleared
+ * @return The mask of pending events that were cleared.
+ *
+ * @iclass
+ */
+eventmask_t chEvtGetAndClearEventsI(eventmask_t events) {
+ eventmask_t m;
+
+ m = chThdGetSelfX()->epmask & events;
+ chThdGetSelfX()->epmask &= ~events;
+
+ return m;
+}
+
+/**
+ * @brief Clears the pending events specified in the events mask.
+ *
+ * @param[in] events the events to be cleared
+ * @return The mask of pending events that were cleared.
+ *
+ * @api
+ */
+eventmask_t chEvtGetAndClearEvents(eventmask_t events) {
+ eventmask_t m;
+
+ chSysLock();
+ m = chEvtGetAndClearEventsI(events);
+ chSysUnlock();
+
+ return m;
+}
+
+/**
+ * @brief Adds (OR) a set of events to the current thread, this is
+ * @b much faster than using @p chEvtBroadcast() or @p chEvtSignal().
+ *
+ * @param[in] events the events to be added
+ * @return The mask of currently pending events.
+ *
+ * @api
+ */
+eventmask_t chEvtAddEvents(eventmask_t events) {
+ eventmask_t newevt;
+
+ chSysLock();
+ newevt = chEvtAddEventsI(events);
+ chSysUnlock();
+
+ return newevt;
+}
+
+/**
+ * @brief Signals all the Event Listeners registered on the specified Event
+ * Source.
+ * @details This function variants ORs the specified event flags to all the
+ * threads registered on the @p event_source_t in addition to the
+ * event flags specified by the threads themselves in the
+ * @p event_listener_t objects.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ * @param[in] flags the flags set to be added to the listener flags mask
+ *
+ * @iclass
+ */
+void chEvtBroadcastFlagsI(event_source_t *esp, eventflags_t flags) {
+ event_listener_t *elp;
+
+ chDbgCheckClassI();
+ chDbgCheck(esp != NULL);
+
+ elp = esp->next;
+ /*lint -save -e9087 -e740 [11.3, 1.3] Cast required by list handling.*/
+ while (elp != (event_listener_t *)esp) {
+ /*lint -restore*/
+ elp->flags |= flags;
+ /* When flags == 0 the thread will always be signaled because the
+ source does not emit any flag.*/
+ if ((flags == (eventflags_t)0) ||
+ ((flags & elp->wflags) != (eventflags_t)0)) {
+ chEvtSignalI(elp->listener, elp->events);
+ }
+ elp = elp->next;
+ }
+}
+
+/**
+ * @brief Returns the flags associated to an @p event_listener_t.
+ * @details The flags are returned and the @p event_listener_t flags mask is
+ * cleared.
+ *
+ * @param[in] elp pointer to the @p event_listener_t structure
+ * @return The flags added to the listener by the associated
+ * event source.
+ *
+ * @api
+ */
+eventflags_t chEvtGetAndClearFlags(event_listener_t *elp) {
+ eventflags_t flags;
+
+ chSysLock();
+ flags = elp->flags;
+ elp->flags = (eventflags_t)0;
+ chSysUnlock();
+
+ return flags & elp->wflags;
+}
+
+/**
+ * @brief Adds a set of event flags directly to the specified @p thread_t.
+ *
+ * @param[in] tp the thread to be signaled
+ * @param[in] events the event flags set to be ORed
+ *
+ * @api
+ */
+void chEvtSignal(thread_t *tp, eventmask_t events) {
+
+ chSysLock();
+ chEvtSignalI(tp, events);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+/**
+ * @brief Adds a set of event flags directly to the specified @p thread_t.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] tp the thread to be signaled
+ * @param[in] events the event flags set to be ORed
+ *
+ * @iclass
+ */
+void chEvtSignalI(thread_t *tp, eventmask_t events) {
+
+ chDbgCheckClassI();
+ chDbgCheck(tp != NULL);
+
+ tp->epmask |= events;
+ if ((NIL_THD_IS_WTOREVT(tp) &&
+ ((tp->epmask & tp->u1.ewmask) != (eventmask_t)0)) ||
+ (NIL_THD_IS_WTANDEVT(tp) &&
+ ((tp->epmask & tp->u1.ewmask) == tp->u1.ewmask))) {
+ (void) chSchReadyI(tp, MSG_OK);
+ }
+}
+
+/**
+ * @brief Signals all the Event Listeners registered on the specified Event
+ * Source.
+ * @details This function variants ORs the specified event flags to all the
+ * threads registered on the @p event_source_t in addition to the
+ * event flags specified by the threads themselves in the
+ * @p event_listener_t objects.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ * @param[in] flags the flags set to be added to the listener flags mask
+ *
+ * @api
+ */
+void chEvtBroadcastFlags(event_source_t *esp, eventflags_t flags) {
+
+ chSysLock();
+ chEvtBroadcastFlagsI(esp, flags);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+/**
+ * @brief Returns the unmasked flags associated to an @p event_listener_t.
+ * @details The flags are returned and the @p event_listener_t flags mask is
+ * cleared.
+ *
+ * @param[in] elp pointer to the @p event_listener_t structure
+ * @return The flags added to the listener by the associated
+ * event source.
+ *
+ * @iclass
+ */
+eventflags_t chEvtGetAndClearFlagsI(event_listener_t *elp) {
+ eventflags_t flags;
+
+ flags = elp->flags;
+ elp->flags = (eventflags_t)0;
+
+ return flags & elp->wflags;
+}
+
+/**
+ * @brief Invokes the event handlers associated to an event flags mask.
+ *
+ * @param[in] events mask of events to be dispatched
+ * @param[in] handlers an array of @p evhandler_t. The array must have size
+ * equal to the number of bits in eventmask_t.
+ *
+ * @api
+ */
+void chEvtDispatch(const evhandler_t *handlers, eventmask_t events) {
+ eventid_t eid;
+
+ chDbgCheck(handlers != NULL);
+
+ eid = (eventid_t)0;
+ while (events != (eventmask_t)0) {
+ if ((events & EVENT_MASK(eid)) != (eventmask_t)0) {
+ chDbgAssert(handlers[eid] != NULL, "null handler");
+ events &= ~EVENT_MASK(eid);
+ handlers[eid](eid);
+ }
+ eid++;
+ }
+}
+
+/**
+ * @brief Waits for exactly one of the specified events.
+ * @details The function waits for one event among those specified in
+ * @p events to become pending then the event is cleared and returned.
+ * @note One and only one event is served in the function, the one with the
+ * lowest event id. The function is meant to be invoked into a loop
+ * in order to serve all the pending events.
+ * This means that Event Listeners with a lower event identifier have
+ * an higher priority.
+ *
+ * @param[in] events events that the function should wait
+ * for, @p ALL_EVENTS enables all the events
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The mask of the lowest event id served and cleared.
+ * @retval 0 if the operation has timed out.
+ *
+ * @api
+ */
+eventmask_t chEvtWaitOneTimeout(eventmask_t events, sysinterval_t timeout) {
+ thread_t *ctp = nil.current;
+ eventmask_t m;
+
+ chSysLock();
+ m = ctp->epmask & events;
+ if (m == (eventmask_t)0) {
+ if (TIME_IMMEDIATE == timeout) {
+ chSysUnlock();
+
+ return (eventmask_t)0;
+ }
+ ctp->u1.ewmask = events;
+ if (chSchGoSleepTimeoutS(NIL_STATE_WTOREVT, timeout) < MSG_OK) {
+ chSysUnlock();
+
+ return (eventmask_t)0;
+ }
+ m = ctp->epmask & events;
+ }
+ m ^= m & (m - (eventmask_t)1);
+ ctp->epmask &= ~m;
+ chSysUnlock();
+
+ return m;
+}
+
+/**
+ * @brief Waits for any of the specified events.
+ * @details The function waits for any event among those specified in
+ * @p mask to become pending then the events are cleared and
+ * returned.
+ *
+ * @param[in] mask mask of the event flags that the function should wait
+ * for, @p ALL_EVENTS enables all the events
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The mask of the served and cleared events.
+ * @retval 0 if the operation has timed out.
+ *
+ * @api
+ */
+eventmask_t chEvtWaitAnyTimeout(eventmask_t mask, sysinterval_t timeout) {
+ thread_t *ctp = nil.current;
+ eventmask_t m;
+
+ chSysLock();
+ if ((m = (ctp->epmask & mask)) == (eventmask_t)0) {
+ if (TIME_IMMEDIATE == timeout) {
+ chSysUnlock();
+
+ return (eventmask_t)0;
+ }
+ ctp->u1.ewmask = mask;
+ if (chSchGoSleepTimeoutS(NIL_STATE_WTOREVT, timeout) < MSG_OK) {
+ chSysUnlock();
+
+ return (eventmask_t)0;
+ }
+ m = ctp->epmask & mask;
+ }
+ ctp->epmask &= ~m;
+ chSysUnlock();
+
+ return m;
+}
+
+/**
+ * @brief Waits for all the specified events.
+ * @details The function waits for all the events specified in @p mask to
+ * become pending then the events are cleared and returned.
+ *
+ * @param[in] mask mask of the event flags that the function should wait
+ * for, @p ALL_EVENTS enables all the events
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The mask of the served and cleared events.
+ * @retval 0 if the operation has timed out.
+ *
+ * @api
+ */
+eventmask_t chEvtWaitAllTimeout(eventmask_t mask, sysinterval_t timeout) {
+ thread_t *ctp = nil.current;
+
+ chSysLock();
+ if ((ctp->epmask & mask) != mask) {
+ if (TIME_IMMEDIATE == timeout) {
+ chSysUnlock();
+
+ return (eventmask_t)0;
+ }
+ ctp->u1.ewmask = mask;
+ if (chSchGoSleepTimeoutS(NIL_STATE_WTANDEVT, timeout) < MSG_OK) {
+ chSysUnlock();
+
+ return (eventmask_t)0;
+ }
+ }
+ ctp->epmask &= ~mask;
+ chSysUnlock();
+
+ return mask;
+}
+
+#endif /* CH_CFG_USE_EVENTS == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/nil/src/chmsg.c b/ChibiOS_20.3.2/os/nil/src/chmsg.c
new file mode 100644
index 0000000..ccefcc5
--- /dev/null
+++ b/ChibiOS_20.3.2/os/nil/src/chmsg.c
@@ -0,0 +1,201 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file nil/src/chmsg.c
+ * @brief Nil RTOS synchronous messages source file.
+ *
+ * @addtogroup NIL_MESSAGES
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Sends a message to the specified thread.
+ * @details The sender is stopped until the receiver executes a
+ * @p chMsgRelease()after receiving the message.
+ *
+ * @param[in] tp the pointer to the thread
+ * @param[in] msg the message
+ * @return The answer message from @p chMsgRelease().
+ *
+ * @api
+ */
+msg_t chMsgSend(thread_t *tp, msg_t msg) {
+ thread_t *ctp = nil.current;
+
+ chDbgCheck(tp != NULL);
+
+ chSysLock();
+ ctp->sntmsg = msg;
+ ctp->u1.tp = tp;
+ if (NIL_THD_IS_WTMSG(tp)) {
+ (void) chSchReadyI(tp, (msg_t)ctp);
+ }
+ msg = chSchGoSleepTimeoutS(NIL_STATE_SNDMSGQ, TIME_INFINITE);
+ chSysUnlock();
+
+ return msg;
+}
+
+/**
+ * @brief Suspends the thread and waits for an incoming message.
+ * @post After receiving a message the function @p chMsgGet() must be
+ * called in order to retrieve the message and then @p chMsgRelease()
+ * must be invoked in order to acknowledge the reception and send
+ * the answer.
+ * @note If the message is a pointer then you can assume that the data
+ * pointed by the message is stable until you invoke @p chMsgRelease()
+ * because the sending thread is suspended until then.
+ * @note The reference counter of the sender thread is not increased, the
+ * returned pointer is a temporary reference.
+ *
+ * @return A pointer to the thread carrying the message.
+ *
+ * @api
+ */
+thread_t *chMsgWait(void) {
+ thread_t *tp;
+
+ chSysLock();
+ tp = chMsgWaitS();
+ chSysUnlock();
+
+ return tp;
+}
+
+/**
+ * @brief Suspends the thread and waits for an incoming message or a
+ * timeout to occur.
+ * @post After receiving a message the function @p chMsgGet() must be
+ * called in order to retrieve the message and then @p chMsgRelease()
+ * must be invoked in order to acknowledge the reception and send
+ * the answer.
+ * @note If the message is a pointer then you can assume that the data
+ * pointed by the message is stable until you invoke @p chMsgRelease()
+ * because the sending thread is suspended until then.
+ * @note The reference counter of the sender thread is not increased, the
+ * returned pointer is a temporary reference.
+ *
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A pointer to the thread carrying the message.
+ * @retval NULL if a timeout occurred.
+ *
+ * @api
+ */
+thread_t *chMsgWaitTimeout(sysinterval_t timeout) {
+ thread_t *tp;
+
+ chSysLock();
+ tp = chMsgWaitTimeoutS(timeout);
+ chSysUnlock();
+
+ return tp;
+}
+
+/**
+ * @brief Suspends the thread and waits for an incoming message or a
+ * timeout to occur.
+ * @post After receiving a message the function @p chMsgGet() must be
+ * called in order to retrieve the message and then @p chMsgRelease()
+ * must be invoked in order to acknowledge the reception and send
+ * the answer.
+ * @note If the message is a pointer then you can assume that the data
+ * pointed by the message is stable until you invoke @p chMsgRelease()
+ * because the sending thread is suspended until then.
+ * @note The reference counter of the sender thread is not increased, the
+ * returned pointer is a temporary reference.
+ *
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A pointer to the thread carrying the message.
+ * @retval NULL if a timeout occurred.
+ *
+ * @sclass
+ */
+thread_t *chMsgWaitTimeoutS(sysinterval_t timeout) {
+ thread_t *tp;
+
+ chDbgCheckClassS();
+
+ tp = nil_find_thread(NIL_STATE_SNDMSGQ, nil.current);
+ if (tp == NULL) {
+ msg_t msg = chSchGoSleepTimeoutS(NIL_STATE_WTMSG, timeout);
+ if (msg != MSG_TIMEOUT) {
+ return (thread_t *)msg;
+ }
+ }
+
+ return tp;
+}
+
+/**
+ * @brief Releases a sender thread specifying a response message.
+ * @pre Invoke this function only after a message has been received
+ * using @p chMsgWait().
+ *
+ * @param[in] tp pointer to the thread
+ * @param[in] msg message to be returned to the sender
+ *
+ * @api
+ */
+void chMsgRelease(thread_t *tp, msg_t msg) {
+
+ chSysLock();
+ chDbgAssert(tp->state == NIL_STATE_SNDMSGQ, "invalid state");
+ chMsgReleaseS(tp, msg);
+ chSysUnlock();
+}
+
+#endif /* CH_CFG_USE_MESSAGES == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/nil/src/chsem.c b/ChibiOS_20.3.2/os/nil/src/chsem.c
new file mode 100644
index 0000000..c97eb3a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/nil/src/chsem.c
@@ -0,0 +1,224 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file nil/src/chsem.c
+ * @brief Nil RTOS semaphores source file.
+ *
+ * @addtogroup NIL_SEMAPHORES
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Performs a wait operation on a semaphore with timeout specification.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A message specifying how the invoking thread has been
+ * released from the semaphore.
+ * @retval NIL_MSG_OK if the thread has not stopped on the semaphore or the
+ * semaphore has been signaled.
+ * @retval NIL_MSG_RST if the semaphore has been reset using @p chSemReset().
+ * @retval NIL_MSG_TMO if the semaphore has not been signaled or reset within
+ * the specified timeout.
+ *
+ * @api
+ */
+msg_t chSemWaitTimeout(semaphore_t *sp, sysinterval_t timeout) {
+ msg_t msg;
+
+ chSysLock();
+ msg = chSemWaitTimeoutS(sp, timeout);
+ chSysUnlock();
+
+ return msg;
+}
+
+/**
+ * @brief Performs a wait operation on a semaphore with timeout specification.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A message specifying how the invoking thread has been
+ * released from the semaphore.
+ * @retval NIL_MSG_OK if the thread has not stopped on the semaphore or the
+ * semaphore has been signaled.
+ * @retval NIL_MSG_RST if the semaphore has been reset using @p chSemReset().
+ * @retval NIL_MSG_TMO if the semaphore has not been signaled or reset within
+ * the specified timeout.
+ *
+ * @sclass
+ */
+msg_t chSemWaitTimeoutS(semaphore_t *sp, sysinterval_t timeout) {
+
+ chDbgCheckClassS();
+ chDbgCheck(sp != NULL);
+
+ /* Note, the semaphore counter is a volatile variable so accesses are
+ manually optimized.*/
+ cnt_t cnt = sp->cnt;
+ if (cnt <= (cnt_t)0) {
+ if (TIME_IMMEDIATE == timeout) {
+
+ return MSG_TIMEOUT;
+ }
+ sp->cnt = cnt - (cnt_t)1;
+ nil.current->u1.semp = sp;
+
+ return chSchGoSleepTimeoutS(NIL_STATE_WTQUEUE, timeout);
+ }
+ sp->cnt = cnt - (cnt_t)1;
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Performs a signal operation on a semaphore.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ *
+ * @api
+ */
+void chSemSignal(semaphore_t *sp) {
+
+ chSysLock();
+ chSemSignalI(sp);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+/**
+ * @brief Performs a signal operation on a semaphore.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ *
+ * @iclass
+ */
+void chSemSignalI(semaphore_t *sp) {
+
+ chDbgCheckClassI();
+ chDbgCheck(sp != NULL);
+
+ if (++sp->cnt <= (cnt_t)0) {
+ thread_t *tp = nil_find_thread(NIL_STATE_WTQUEUE, (void *)sp);
+
+ chDbgAssert(tp != NULL, "thread not found");
+
+ (void) chSchReadyI(tp, MSG_OK);
+ }
+}
+
+/**
+ * @brief Performs a reset operation on the semaphore.
+ * @post After invoking this function all the threads waiting on the
+ * semaphore, if any, are released and the semaphore counter is set
+ * to the specified, non negative, value.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @param[in] n the new value of the semaphore counter. The value must
+ * be non-negative.
+ * @param[in] msg message to be sent
+ *
+ * @api
+ */
+void chSemResetWithMessage(semaphore_t *sp, cnt_t n, msg_t msg) {
+
+ chSysLock();
+ chSemResetWithMessageI(sp, n, msg);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+/**
+ * @brief Performs a reset operation on the semaphore.
+ * @post After invoking this function all the threads waiting on the
+ * semaphore, if any, are released and the semaphore counter is set
+ * to the specified, non negative, value.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @param[in] n the new value of the semaphore counter. The value must
+ * be non-negative.
+ * @param[in] msg message to be sent
+ *
+ * @iclass
+ */
+void chSemResetWithMessageI(semaphore_t *sp, cnt_t n, msg_t msg) {
+ cnt_t cnt;
+
+ chDbgCheckClassI();
+ chDbgCheck((sp != NULL) && (n >= (cnt_t)0));
+
+ cnt = sp->cnt;
+ sp->cnt = n;
+
+ /* Does nothing for cnt >= 0, calling anyway.*/
+ (void) nil_ready_all((void *)sp, cnt, msg);
+}
+
+#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/nil/templates/chconf.h b/ChibiOS_20.3.2/os/nil/templates/chconf.h
new file mode 100644
index 0000000..3f0c953
--- /dev/null
+++ b/ChibiOS_20.3.2/os/nil/templates/chconf.h
@@ -0,0 +1,479 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file nil/templates/chconf.h
+ * @brief Configuration file template.
+ * @details A copy of this file must be placed in each project directory, it
+ * contains the application specific kernel settings.
+ *
+ * @addtogroup NIL_CONFIG
+ * @details Kernel related settings and hooks.
+ * @{
+ */
+
+#ifndef CHCONF_H
+#define CHCONF_H
+
+#define _CHIBIOS_NIL_CONF_
+#define _CHIBIOS_NIL_CONF_VER_4_0_
+
+/*===========================================================================*/
+/**
+ * @name Kernel parameters and options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Maximum number of user threads in the application.
+ * @note This number is not inclusive of the idle thread which is
+ * implicitly handled.
+ * @note Set this value to be exactly equal to the number of threads you
+ * will use or you would be wasting RAM and cycles.
+ * @note This values also defines the number of available priorities
+ * (0..CH_CFG_MAX_THREADS-1).
+ */
+#if !defined(CH_CFG_MAX_THREADS)
+#define CH_CFG_MAX_THREADS 4
+#endif
+
+/**
+ * @brief Auto starts threads when @p chSysInit() is invoked.
+ */
+#if !defined(CH_CFG_AUTOSTART_THREADS)
+#define CH_CFG_AUTOSTART_THREADS TRUE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name System timer settings
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System time counter resolution.
+ * @note Allowed values are 16 or 32 bits.
+ */
+#if !defined(CH_CFG_ST_RESOLUTION)
+#define CH_CFG_ST_RESOLUTION 32
+#endif
+
+/**
+ * @brief System tick frequency.
+ * @note This value together with the @p CH_CFG_ST_RESOLUTION
+ * option defines the maximum amount of time allowed for
+ * timeouts.
+ */
+#if !defined(CH_CFG_ST_FREQUENCY)
+#define CH_CFG_ST_FREQUENCY 1000
+#endif
+
+/**
+ * @brief Time delta constant for the tick-less mode.
+ * @note If this value is zero then the system uses the classic
+ * periodic tick. This value represents the minimum number
+ * of ticks that is safe to specify in a timeout directive.
+ * The value one is not valid, timeouts are rounded up to
+ * this value.
+ */
+#if !defined(CH_CFG_ST_TIMEDELTA)
+#define CH_CFG_ST_TIMEDELTA 0
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Subsystem options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Threads synchronization APIs.
+ * @details If enabled then the @p chThdWait() function is included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_WAITEXIT)
+#define CH_CFG_USE_WAITEXIT TRUE
+#endif
+
+/**
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_SEMAPHORES)
+#define CH_CFG_USE_SEMAPHORES TRUE
+#endif
+
+/**
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
+ * @note Feature not currently implemented.
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_CFG_USE_MUTEXES)
+#define CH_CFG_USE_MUTEXES FALSE
+#endif
+
+/**
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_EVENTS)
+#define CH_CFG_USE_EVENTS TRUE
+#endif
+
+/**
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_MESSAGES)
+#define CH_CFG_USE_MESSAGES TRUE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name OSLIB options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#if !defined(CH_CFG_USE_MAILBOXES)
+#define CH_CFG_USE_MAILBOXES TRUE
+#endif
+
+/**
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_MEMCORE)
+#define CH_CFG_USE_MEMCORE TRUE
+#endif
+
+/**
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
+ * provide the @p __heap_base__ and @p __heap_end__ symbols.
+ * @note Requires @p CH_CFG_USE_MEMCORE.
+ */
+#if !defined(CH_CFG_MEMCORE_SIZE)
+#define CH_CFG_MEMCORE_SIZE 0
+#endif
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_HEAP)
+#define CH_CFG_USE_HEAP TRUE
+#endif
+
+/**
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_MEMPOOLS)
+#define CH_CFG_USE_MEMPOOLS TRUE
+#endif
+
+/**
+ * @brief Objects FIFOs APIs.
+ * @details If enabled then the objects FIFOs APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_OBJ_FIFOS)
+#define CH_CFG_USE_OBJ_FIFOS TRUE
+#endif
+
+/**
+ * @brief Pipes APIs.
+ * @details If enabled then the pipes APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_PIPES)
+#define CH_CFG_USE_PIPES TRUE
+#endif
+
+/**
+ * @brief Objects Caches APIs.
+ * @details If enabled then the objects caches APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_OBJ_CACHES)
+#define CH_CFG_USE_OBJ_CACHES TRUE
+#endif
+
+/**
+ * @brief Delegate threads APIs.
+ * @details If enabled then the delegate threads APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_DELEGATES)
+#define CH_CFG_USE_DELEGATES TRUE
+#endif
+
+/**
+ * @brief Jobs Queues APIs.
+ * @details If enabled then the jobs queues APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_JOBS)
+#define CH_CFG_USE_JOBS TRUE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Objects factory options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Objects Factory APIs.
+ * @details If enabled then the objects factory APIs are included in the
+ * kernel.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_CFG_USE_FACTORY)
+#define CH_CFG_USE_FACTORY TRUE
+#endif
+
+/**
+ * @brief Maximum length for object names.
+ * @details If the specified length is zero then the name is stored by
+ * pointer but this could have unintended side effects.
+ */
+#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH)
+#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8
+#endif
+
+/**
+ * @brief Enables the registry of generic objects.
+ */
+#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY)
+#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE
+#endif
+
+/**
+ * @brief Enables factory for generic buffers.
+ */
+#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS)
+#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE
+#endif
+
+/**
+ * @brief Enables factory for semaphores.
+ */
+#if !defined(CH_CFG_FACTORY_SEMAPHORES)
+#define CH_CFG_FACTORY_SEMAPHORES TRUE
+#endif
+
+/**
+ * @brief Enables factory for mailboxes.
+ */
+#if !defined(CH_CFG_FACTORY_MAILBOXES)
+#define CH_CFG_FACTORY_MAILBOXES TRUE
+#endif
+
+/**
+ * @brief Enables factory for objects FIFOs.
+ */
+#if !defined(CH_CFG_FACTORY_OBJ_FIFOS)
+#define CH_CFG_FACTORY_OBJ_FIFOS TRUE
+#endif
+
+/**
+ * @brief Enables factory for Pipes.
+ */
+#if !defined(CH_CFG_FACTORY_PIPES)
+#define CH_CFG_FACTORY_PIPES TRUE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Debug options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Debug option, kernel statistics.
+ *
+ * @note Feature not currently implemented.
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_STATISTICS)
+#define CH_DBG_STATISTICS FALSE
+#endif
+
+/**
+ * @brief Debug option, system state check.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_SYSTEM_STATE_CHECK)
+#define CH_DBG_SYSTEM_STATE_CHECK TRUE
+#endif
+
+/**
+ * @brief Debug option, parameters checks.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_ENABLE_CHECKS)
+#define CH_DBG_ENABLE_CHECKS TRUE
+#endif
+
+/**
+ * @brief System assertions.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_ENABLE_ASSERTS)
+#define CH_DBG_ENABLE_ASSERTS TRUE
+#endif
+
+/**
+ * @brief Stack check.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_ENABLE_STACK_CHECK)
+#define CH_DBG_ENABLE_STACK_CHECK TRUE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel hooks
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System initialization hook.
+ */
+#define CH_CFG_SYSTEM_INIT_HOOK() { \
+}
+
+/**
+ * @brief Threads descriptor structure extension.
+ * @details User fields added to the end of the @p thread_t structure.
+ */
+#define CH_CFG_THREAD_EXT_FIELDS \
+ /* Add threads custom fields here.*/
+
+/**
+ * @brief Threads initialization hook.
+ */
+#define CH_CFG_THREAD_EXT_INIT_HOOK(tr) { \
+ /* Add custom threads initialization code here.*/ \
+}
+
+/**
+ * @brief Threads finalization hook.
+ * @details User finalization code added to the @p chThdExit() API.
+ */
+#define CH_CFG_THREAD_EXIT_HOOK(tp) {}
+
+/**
+ * @brief Idle thread enter hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to activate a power saving mode.
+ */
+#define CH_CFG_IDLE_ENTER_HOOK() { \
+}
+
+/**
+ * @brief Idle thread leave hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to deactivate a power saving mode.
+ */
+#define CH_CFG_IDLE_LEAVE_HOOK() { \
+}
+
+/**
+ * @brief System halt hook.
+ */
+#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
+}
+
+/** @} */
+
+/*===========================================================================*/
+/* Port-specific settings (override port settings defaulted in nilcore.h). */
+/*===========================================================================*/
+
+#endif /* CHCONF_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/dox/lib.dox b/ChibiOS_20.3.2/os/oslib/dox/lib.dox
new file mode 100644
index 0000000..362a608
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/dox/lib.dox
@@ -0,0 +1,100 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+/**
+ * @defgroup oslib OS Library
+ * @details The OS Library is a set of RTOS extensions compatible with both
+ * the RT and NIL RTOSes.
+ */
+
+/**
+ * @defgroup oslib_info Version Numbers and Identification
+ * @ingroup oslib
+ */
+
+/**
+ * @defgroup oslib_synchronization Synchronization
+ * @details Synchronization services.
+ * @ingroup oslib
+ */
+
+/**
+ * @defgroup oslib_binary_semaphores Binary Semaphores
+ * @ingroup oslib_synchronization
+ */
+
+/**
+ * @defgroup oslib_mailboxes Mailboxes
+ * @ingroup oslib_synchronization
+ */
+
+/**
+ * @defgroup oslib_pipes Pipes
+ * @ingroup oslib_synchronization
+ */
+
+/**
+ * @defgroup oslib_delegates Delegate Threads
+ * @ingroup oslib_synchronization
+ */
+
+/**
+ * @defgroup oslib_jobs_queues Jobs Queues
+ * @ingroup oslib_synchronization
+ */
+
+/**
+ * @defgroup oslib_memory Memory Management
+ * @details Memory Management services.
+ * @ingroup oslib
+ */
+
+/**
+ * @defgroup oslib_memcore Core Memory Manager
+ * @ingroup oslib_memory
+ */
+
+/**
+ * @defgroup oslib_memheaps Memory Heaps
+ * @ingroup oslib_memory
+ */
+
+/**
+ * @defgroup oslib_mempools Memory Pools
+ * @ingroup oslib_memory
+ */
+
+/**
+ * @defgroup oslib_complex Complex Services
+ * @ingroup oslib
+ */
+
+/**
+ * @defgroup oslib_objects_fifos Objects FIFOs
+ * @ingroup oslib_complex
+ */
+
+/**
+ * @defgroup oslib_objchaches Objects Caches
+ * @ingroup oslib_complex
+ */
+
+/**
+ * @defgroup oslib_objects_factory Dynamic Objects Factory
+ * @ingroup oslib_complex
+ */
diff --git a/ChibiOS_20.3.2/os/oslib/include/chbsem.h b/ChibiOS_20.3.2/os/oslib/include/chbsem.h
new file mode 100644
index 0000000..ed5a703
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/include/chbsem.h
@@ -0,0 +1,311 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/include/chbsem.h
+ * @brief Binary semaphores structures and macros.
+ * @details Binary semaphores related APIs and services.
+ * Operation mode
+ * Binary semaphores are implemented as a set of inline functions
+ * that use the existing counting semaphores primitives. The
+ * difference between counting and binary semaphores is that the
+ * counter of binary semaphores is not allowed to grow above the
+ * value 1. Repeated signal operation are ignored. A binary
+ * semaphore can thus have only two defined states:
+ * - Taken, when its counter has a value of zero or lower
+ * than zero. A negative number represent the number of threads
+ * queued on the binary semaphore.
+ * - Not taken, when its counter has a value of one.
+ * .
+ * Binary semaphores are different from mutexes because there is no
+ * concept of ownership, a binary semaphore can be taken by a
+ * thread and signaled by another thread or an interrupt handler,
+ * mutexes can only be taken and released by the same thread. Another
+ * difference is that binary semaphores, unlike mutexes, do not
+ * implement the priority inheritance protocol.
+ * In order to use the binary semaphores APIs the
+ * @p CH_CFG_USE_SEMAPHORES option must be enabled in @p chconf.h.
+ *
+ * @addtogroup oslib_binary_semaphores
+ * @{
+ */
+
+#ifndef CHBSEM_H
+#define CHBSEM_H
+
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @extends semaphore_t
+ *
+ * @brief Binary semaphore type.
+ */
+typedef struct ch_binary_semaphore {
+ semaphore_t sem;
+} binary_semaphore_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Data part of a static semaphore initializer.
+ * @details This macro should be used when statically initializing a semaphore
+ * that is part of a bigger structure.
+ *
+ * @param[in] name the name of the semaphore variable
+ * @param[in] taken the semaphore initial state
+ */
+#define _BSEMAPHORE_DATA(name, taken) \
+ {_SEMAPHORE_DATA(name.sem, ((taken) ? 0 : 1))}
+
+/**
+ * @brief Static semaphore initializer.
+ * @details Statically initialized semaphores require no explicit
+ * initialization using @p chBSemInit().
+ *
+ * @param[in] name the name of the semaphore variable
+ * @param[in] taken the semaphore initial state
+ */
+#define BSEMAPHORE_DECL(name, taken) \
+ binary_semaphore_t name = _BSEMAPHORE_DATA(name, taken)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes a binary semaphore.
+ *
+ * @param[out] bsp pointer to a @p binary_semaphore_t structure
+ * @param[in] taken initial state of the binary semaphore:
+ * - @a false, the initial state is not taken.
+ * - @a true, the initial state is taken.
+ * .
+ *
+ * @init
+ */
+static inline void chBSemObjectInit(binary_semaphore_t *bsp, bool taken) {
+
+ chSemObjectInit(&bsp->sem, taken ? (cnt_t)0 : (cnt_t)1);
+}
+
+/**
+ * @brief Wait operation on the binary semaphore.
+ *
+ * @param[in] bsp pointer to a @p binary_semaphore_t structure
+ * @return A message specifying how the invoking thread has been
+ * released from the semaphore.
+ * @retval MSG_OK if the binary semaphore has been successfully taken.
+ * @retval MSG_RESET if the binary semaphore has been reset using
+ * @p bsemReset().
+ *
+ * @api
+ */
+static inline msg_t chBSemWait(binary_semaphore_t *bsp) {
+
+ return chSemWait(&bsp->sem);
+}
+
+/**
+ * @brief Wait operation on the binary semaphore.
+ *
+ * @param[in] bsp pointer to a @p binary_semaphore_t structure
+ * @return A message specifying how the invoking thread has been
+ * released from the semaphore.
+ * @retval MSG_OK if the binary semaphore has been successfully taken.
+ * @retval MSG_RESET if the binary semaphore has been reset using
+ * @p bsemReset().
+ *
+ * @sclass
+ */
+static inline msg_t chBSemWaitS(binary_semaphore_t *bsp) {
+
+ chDbgCheckClassS();
+
+ return chSemWaitS(&bsp->sem);
+}
+
+/**
+ * @brief Wait operation on the binary semaphore.
+ *
+ * @param[in] bsp pointer to a @p binary_semaphore_t structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A message specifying how the invoking thread has been
+ * released from the semaphore.
+ * @retval MSG_OK if the binary semaphore has been successfully taken.
+ * @retval MSG_RESET if the binary semaphore has been reset using
+ * @p bsemReset().
+ * @retval MSG_TIMEOUT if the binary semaphore has not been signaled or reset
+ * within the specified timeout.
+ *
+ * @sclass
+ */
+static inline msg_t chBSemWaitTimeoutS(binary_semaphore_t *bsp,
+ sysinterval_t timeout) {
+
+ chDbgCheckClassS();
+
+ return chSemWaitTimeoutS(&bsp->sem, timeout);
+}
+
+/**
+ * @brief Wait operation on the binary semaphore.
+ *
+ * @param[in] bsp pointer to a @p binary_semaphore_t structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A message specifying how the invoking thread has been
+ * released from the semaphore.
+ * @retval MSG_OK if the binary semaphore has been successfully taken.
+ * @retval MSG_RESET if the binary semaphore has been reset using
+ * @p bsemReset().
+ * @retval MSG_TIMEOUT if the binary semaphore has not been signaled or reset
+ * within the specified timeout.
+ *
+ * @api
+ */
+static inline msg_t chBSemWaitTimeout(binary_semaphore_t *bsp,
+ sysinterval_t timeout) {
+
+ return chSemWaitTimeout(&bsp->sem, timeout);
+}
+
+/**
+ * @brief Reset operation on the binary semaphore.
+ * @note The released threads can recognize they were waked up by a reset
+ * rather than a signal because the @p bsemWait() will return
+ * @p MSG_RESET instead of @p MSG_OK.
+ * @note This function does not reschedule.
+ *
+ * @param[in] bsp pointer to a @p binary_semaphore_t structure
+ * @param[in] taken new state of the binary semaphore
+ * - @a false, the new state is not taken.
+ * - @a true, the new state is taken.
+ * .
+ *
+ * @iclass
+ */
+static inline void chBSemResetI(binary_semaphore_t *bsp, bool taken) {
+
+ chDbgCheckClassI();
+
+ chSemResetI(&bsp->sem, taken ? (cnt_t)0 : (cnt_t)1);
+}
+
+/**
+ * @brief Reset operation on the binary semaphore.
+ * @note The released threads can recognize they were waked up by a reset
+ * rather than a signal because the @p bsemWait() will return
+ * @p MSG_RESET instead of @p MSG_OK.
+ *
+ * @param[in] bsp pointer to a @p binary_semaphore_t structure
+ * @param[in] taken new state of the binary semaphore
+ * - @a false, the new state is not taken.
+ * - @a true, the new state is taken.
+ * .
+ *
+ * @api
+ */
+static inline void chBSemReset(binary_semaphore_t *bsp, bool taken) {
+
+ chSemReset(&bsp->sem, taken ? (cnt_t)0 : (cnt_t)1);
+}
+
+/**
+ * @brief Performs a signal operation on a binary semaphore.
+ * @note This function does not reschedule.
+ *
+ * @param[in] bsp pointer to a @p binary_semaphore_t structure
+ *
+ * @iclass
+ */
+static inline void chBSemSignalI(binary_semaphore_t *bsp) {
+
+ chDbgCheckClassI();
+
+ if (bsp->sem.cnt < (cnt_t)1) {
+ chSemSignalI(&bsp->sem);
+ }
+}
+
+/**
+ * @brief Performs a signal operation on a binary semaphore.
+ *
+ * @param[in] bsp pointer to a @p binary_semaphore_t structure
+ *
+ * @api
+ */
+static inline void chBSemSignal(binary_semaphore_t *bsp) {
+
+ chSysLock();
+ chBSemSignalI(bsp);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+/**
+ * @brief Returns the binary semaphore current state.
+ *
+ * @param[in] bsp pointer to a @p binary_semaphore_t structure
+ * @return The binary semaphore current state.
+ * @retval false if the binary semaphore is not taken.
+ * @retval true if the binary semaphore is taken.
+ *
+ * @iclass
+ */
+static inline bool chBSemGetStateI(const binary_semaphore_t *bsp) {
+
+ chDbgCheckClassI();
+
+ return (bsp->sem.cnt > (cnt_t)0) ? false : true;
+}
+
+#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
+
+#endif /* CHBSEM_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/include/chdelegates.h b/ChibiOS_20.3.2/os/oslib/include/chdelegates.h
new file mode 100644
index 0000000..4b4679d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/include/chdelegates.h
@@ -0,0 +1,208 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/include/chdelegates.h
+ * @brief Delegate threads macros and structures.
+ *
+ * @addtogroup oslib_delegates
+ * @{
+ */
+
+#ifndef CHDELEGATES_H
+#define CHDELEGATES_H
+
+#if (CH_CFG_USE_DELEGATES == TRUE) || defined(__DOXYGEN__)
+
+/*lint -save -e829 [17.1] Required by design.*/
+#include
+/*lint -restore*/
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if CH_CFG_USE_MESSAGES == FALSE
+#error "CH_CFG_USE_DELEGATES requires CH_CFG_USE_MESSAGES"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a delegate veneer function.
+ */
+typedef msg_t (*delegate_veneer_t)(va_list *argsp);
+
+/**
+ * @brief Type of a delegate function with no parameters.
+ */
+typedef msg_t (*delegate_fn0_t)(void);
+
+/**
+ * @brief Type of a delegate function with one parameter.
+ */
+typedef msg_t (*delegate_fn1_t)(msg_t p1);
+
+/**
+ * @brief Type of a delegate function with two parameters.
+ */
+typedef msg_t (*delegate_fn2_t)(msg_t p1, msg_t p2);
+
+/**
+ * @brief Type of a delegate function with three parameters.
+ */
+typedef msg_t (*delegate_fn3_t)(msg_t p1, msg_t p2, msg_t p3);
+
+/**
+ * @brief Type of a delegate function with four parameters.
+ */
+typedef msg_t (*delegate_fn4_t)(msg_t p1, msg_t p2, msg_t p3, msg_t p4);
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ msg_t __ch_delegate_fn0(va_list *argsp);
+ msg_t __ch_delegate_fn1(va_list *argsp);
+ msg_t __ch_delegate_fn2(va_list *argsp);
+ msg_t __ch_delegate_fn3(va_list *argsp);
+ msg_t __ch_delegate_fn4(va_list *argsp);
+ void chDelegateDispatch(void);
+ msg_t chDelegateDispatchTimeout(sysinterval_t timeout);
+ msg_t chDelegateCallVeneer(thread_t *tp, delegate_veneer_t veneer, ...);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Direct call to a function with no parameters.
+ * @note The return value is assumed to be not larger than a data
+ * pointer type. If you need a portable function then use
+ * @p chDelegateCallVeneer() instead.
+ *
+ * @param[in] tp pointer to the delegate thread
+ * @param[in] func pointer to the function to be called
+ * @return The function return value as a @p msg_t.
+ */
+static inline msg_t chDelegateCallDirect0(thread_t *tp, delegate_fn0_t func) {
+
+ return chDelegateCallVeneer(tp, __ch_delegate_fn0, func);
+}
+
+/**
+ * @brief Direct call to a function with one parameter.
+ * @note The return value and parameters are assumed to be not larger
+ * than a data pointer type. If you need a portable function then use
+ * @p chDelegateCallVeneer() instead.
+ *
+ * @param[in] tp pointer to the delegate thread
+ * @param[in] func pointer to the function to be called
+ * @param[in] p1 parameter 1 passed as a @p msg_t
+ * @return The function return value as a @p msg_t.
+ */
+static inline msg_t chDelegateCallDirect1(thread_t *tp, delegate_fn1_t func,
+ msg_t p1) {
+
+ return chDelegateCallVeneer(tp, __ch_delegate_fn1, func, p1);
+}
+
+/**
+ * @brief Direct call to a function with two parameters.
+ * @note The return value and parameters are assumed to be not larger
+ * than a data pointer type. If you need a portable function then use
+ * @p chDelegateCallVeneer() instead.
+ *
+ * @param[in] tp pointer to the delegate thread
+ * @param[in] func pointer to the function to be called
+ * @param[in] p1 parameter 1 passed as a @p msg_t
+ * @param[in] p2 parameter 2 passed as a @p msg_t
+ * @return The function return value as a @p msg_t.
+ */
+static inline msg_t chDelegateCallDirect2(thread_t *tp, delegate_fn2_t func,
+ msg_t p1, msg_t p2) {
+
+ return chDelegateCallVeneer(tp, __ch_delegate_fn2, func, p1, p2);
+}
+
+/**
+ * @brief Direct call to a function with three parameters.
+ * @note The return value and parameters are assumed to be not larger
+ * than a data pointer type. If you need a portable function then use
+ * @p chDelegateCallVeneer() instead.
+ *
+ * @param[in] tp pointer to the delegate thread
+ * @param[in] func pointer to the function to be called
+ * @param[in] p1 parameter 1 passed as a @p msg_t
+ * @param[in] p2 parameter 2 passed as a @p msg_t
+ * @param[in] p3 parameter 3 passed as a @p msg_t
+ * @return The function return value as a @p msg_t.
+ */
+static inline msg_t chDelegateCallDirect3(thread_t *tp, delegate_fn3_t func,
+ msg_t p1, msg_t p2, msg_t p3) {
+
+ return chDelegateCallVeneer(tp, __ch_delegate_fn3, func, p1, p2, p3);
+}
+
+/**
+ * @brief Direct call to a function with four parameters.
+ * @note The return value and parameters are assumed to be not larger
+ * than a data pointer type. If you need a portable function then use
+ * @p chDelegateCallVeneer() instead.
+ *
+ * @param[in] tp pointer to the delegate thread
+ * @param[in] func pointer to the function to be called
+ * @param[in] p1 parameter 1 passed as a @p msg_t
+ * @param[in] p2 parameter 2 passed as a @p msg_t
+ * @param[in] p3 parameter 3 passed as a @p msg_t
+ * @param[in] p4 parameter 4 passed as a @p msg_t
+ * @return The function return value as a @p msg_t.
+ */
+static inline msg_t chDelegateCallDirect4(thread_t *tp, delegate_fn4_t func,
+ msg_t p1, msg_t p2, msg_t p3,
+ msg_t p4) {
+
+ return chDelegateCallVeneer(tp, __ch_delegate_fn4, func, p1, p2, p3, p4);
+}
+
+#endif /* CH_CFG_USE_DELEGATES == TRUE */
+
+#endif /* CHDELEGATES_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/include/chfactory.h b/ChibiOS_20.3.2/os/oslib/include/chfactory.h
new file mode 100644
index 0000000..e056914
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/include/chfactory.h
@@ -0,0 +1,523 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/include/chfactory.h
+ * @brief ChibiOS objects factory structures and macros.
+ *
+ * @addtogroup oslib_objects_factory
+ * @{
+ */
+
+#ifndef CHFACTORY_H
+#define CHFACTORY_H
+
+#if (CH_CFG_USE_FACTORY == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Maximum length for object names.
+ * @details If the specified length is zero then the name is stored by
+ * pointer but this could have unintended side effects.
+ */
+#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) || defined(__DOXYGEN__)
+#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8
+#endif
+
+/**
+ * @brief Enables the registry of generic objects.
+ */
+#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) || defined(__DOXYGEN__)
+#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE
+#endif
+
+/**
+ * @brief Enables factory for generic buffers.
+ */
+#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) || defined(__DOXYGEN__)
+#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE
+#endif
+
+/**
+ * @brief Enables factory for semaphores.
+ */
+#if !defined(CH_CFG_FACTORY_SEMAPHORES) || defined(__DOXYGEN__)
+#define CH_CFG_FACTORY_SEMAPHORES TRUE
+#endif
+
+/**
+ * @brief Enables factory for mailboxes.
+ */
+#if !defined(CH_CFG_FACTORY_MAILBOXES) || defined(__DOXYGEN__)
+#define CH_CFG_FACTORY_MAILBOXES TRUE
+#endif
+
+/**
+ * @brief Enables factory for objects FIFOs.
+ */
+#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) || defined(__DOXYGEN__)
+#define CH_CFG_FACTORY_OBJ_FIFOS TRUE
+#endif
+
+/**
+ * @brief Enables factory for objects FIFOs.
+ */
+#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) || defined(__DOXYGEN__)
+#define CH_CFG_FACTORY_OBJ_FIFOS TRUE
+#endif
+
+/**
+ * @brief Enables factory for Pipes.
+ */
+#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__)
+#define CH_CFG_FACTORY_PIPES TRUE
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) && (CH_CFG_USE_SEMAPHORES == FALSE)
+/*lint -save -e767 [20.5] Valid because the #undef.*/
+#undef CH_CFG_FACTORY_SEMAPHORES
+#define CH_CFG_FACTORY_SEMAPHORES FALSE
+/*lint restore*/
+#endif
+
+#if (CH_CFG_FACTORY_MAILBOXES == TRUE) && (CH_CFG_USE_MAILBOXES == FALSE)
+/*lint -save -e767 [20.5] Valid because the #undef.*/
+#undef CH_CFG_FACTORY_MAILBOXES
+#define CH_CFG_FACTORY_MAILBOXES FALSE
+/*lint restore*/
+#endif
+
+#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) && (CH_CFG_USE_OBJ_FIFOS == FALSE)
+/*lint -save -e767 [20.5] Valid because the #undef.*/
+#undef CH_CFG_FACTORY_OBJ_FIFOS
+#define CH_CFG_FACTORY_OBJ_FIFOS FALSE
+/*lint restore*/
+#endif
+
+#if (CH_CFG_FACTORY_PIPES == TRUE) && (CH_CFG_USE_PIPES == FALSE)
+/*lint -save -e767 [20.5] Valid because the #undef.*/
+#undef CH_CFG_FACTORY_PIPES
+#define CH_CFG_FACTORY_PIPES FALSE
+/*lint restore*/
+#endif
+
+#define CH_FACTORY_REQUIRES_POOLS \
+ ((CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || \
+ (CH_CFG_FACTORY_SEMAPHORES == TRUE))
+
+#define CH_FACTORY_REQUIRES_HEAP \
+ ((CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || \
+ (CH_CFG_FACTORY_MAILBOXES == TRUE) || \
+ (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || \
+ (CH_CFG_FACTORY_PIPES == TRUE))
+
+#if (CH_CFG_FACTORY_MAX_NAMES_LENGTH < 0) || \
+ (CH_CFG_FACTORY_MAX_NAMES_LENGTH > 32)
+#error "invalid CH_CFG_FACTORY_MAX_NAMES_LENGTH value"
+#endif
+
+#if (CH_CFG_USE_MUTEXES == FALSE) && (CH_CFG_USE_SEMAPHORES == FALSE)
+#error "CH_CFG_USE_FACTORY requires CH_CFG_USE_MUTEXES and/or CH_CFG_USE_SEMAPHORES"
+#endif
+
+#if CH_CFG_USE_MEMCORE == FALSE
+#error "CH_CFG_USE_FACTORY requires CH_CFG_USE_MEMCORE"
+#endif
+
+#if CH_FACTORY_REQUIRES_POOLS && (CH_CFG_USE_MEMPOOLS == FALSE)
+#error "CH_CFG_USE_MEMPOOLS is required"
+#endif
+
+#if CH_FACTORY_REQUIRES_HEAP && (CH_CFG_USE_HEAP == FALSE)
+#error "CH_CFG_USE_HEAP is required"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a dynamic object list element.
+ */
+typedef struct ch_dyn_element {
+ /**
+ * @brief Next dynamic object in the list.
+ */
+ struct ch_dyn_element *next;
+ /**
+ * @brief Number of references to this object.
+ */
+ ucnt_t refs;
+#if (CH_CFG_FACTORY_MAX_NAMES_LENGTH > 0) || defined(__DOXYGEN__)
+ char name[CH_CFG_FACTORY_MAX_NAMES_LENGTH];
+#else
+ const char *name;
+#endif
+} dyn_element_t;
+
+/**
+ * @brief Type of a dynamic object list.
+ */
+typedef struct ch_dyn_list {
+ dyn_element_t *next;
+} dyn_list_t;
+
+#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a registered object.
+ */
+typedef struct ch_registered_static_object {
+ /**
+ * @brief List element of the registered object.
+ */
+ dyn_element_t element;
+ /**
+ * @brief Pointer to the object.
+ * @note The type of the object is not stored in anyway.
+ */
+ void *objp;
+} registered_object_t;
+#endif
+
+#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a dynamic buffer object.
+ */
+typedef struct ch_dyn_object {
+ /**
+ * @brief List element of the dynamic buffer object.
+ */
+ dyn_element_t element;
+} dyn_buffer_t;
+#endif
+
+#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a dynamic semaphore.
+ */
+typedef struct ch_dyn_semaphore {
+ /**
+ * @brief List element of the dynamic semaphore.
+ */
+ dyn_element_t element;
+ /**
+ * @brief The semaphore.
+ */
+ semaphore_t sem;
+} dyn_semaphore_t;
+#endif
+
+#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a dynamic buffer object.
+ */
+typedef struct ch_dyn_mailbox {
+ /**
+ * @brief List element of the dynamic buffer object.
+ */
+ dyn_element_t element;
+ /**
+ * @brief The mailbox.
+ */
+ mailbox_t mbx;
+} dyn_mailbox_t;
+#endif
+
+#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a dynamic buffer object.
+ */
+typedef struct ch_dyn_objects_fifo {
+ /**
+ * @brief List element of the dynamic buffer object.
+ */
+ dyn_element_t element;
+ /**
+ * @brief The objects FIFO.
+ */
+ objects_fifo_t fifo;
+} dyn_objects_fifo_t;
+#endif
+
+#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a dynamic pipe object.
+ */
+typedef struct ch_dyn_pipe {
+ /**
+ * @brief List element of the dynamic pipe object.
+ */
+ dyn_element_t element;
+ /**
+ * @brief The pipe.
+ */
+ pipe_t pipe;
+} dyn_pipe_t;
+#endif
+
+/**
+ * @brief Type of the factory main object.
+ */
+typedef struct ch_objects_factory {
+ /**
+ * @brief Factory access mutex or semaphore.
+ */
+#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
+ mutex_t mtx;
+#else
+ semaphore_t sem;
+#endif
+ /**
+ * @brief List of the registered objects.
+ */
+ dyn_list_t obj_list;
+ /**
+ * @brief Pool of the available registered objects.
+ */
+ memory_pool_t obj_pool;
+#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief List of the allocated buffer objects.
+ */
+ dyn_list_t buf_list;
+#endif /* CH_CFG_FACTORY_GENERIC_BUFFERS = TRUE */
+#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief List of the allocated semaphores.
+ */
+ dyn_list_t sem_list;
+ /**
+ * @brief Pool of the available semaphores.
+ */
+ memory_pool_t sem_pool;
+#endif /* CH_CFG_FACTORY_SEMAPHORES = TRUE */
+#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief List of the allocated buffer objects.
+ */
+ dyn_list_t mbx_list;
+#endif /* CH_CFG_FACTORY_MAILBOXES = TRUE */
+#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief List of the allocated "objects FIFO" objects.
+ */
+ dyn_list_t fifo_list;
+#endif /* CH_CFG_FACTORY_OBJ_FIFOS = TRUE */
+#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief List of the allocated pipe objects.
+ */
+ dyn_list_t pipe_list;
+#endif /* CH_CFG_FACTORY_PIPES = TRUE */
+} objects_factory_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern objects_factory_t ch_factory;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void _factory_init(void);
+#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__)
+ registered_object_t *chFactoryRegisterObject(const char *name,
+ void *objp);
+ registered_object_t *chFactoryFindObject(const char *name);
+ registered_object_t *chFactoryFindObjectByPointer(void *objp);
+ void chFactoryReleaseObject(registered_object_t *rop);
+#endif
+#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__)
+ dyn_buffer_t *chFactoryCreateBuffer(const char *name, size_t size);
+ dyn_buffer_t *chFactoryFindBuffer(const char *name);
+ void chFactoryReleaseBuffer(dyn_buffer_t *dbp);
+#endif
+#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+ dyn_semaphore_t *chFactoryCreateSemaphore(const char *name, cnt_t n);
+ dyn_semaphore_t *chFactoryFindSemaphore(const char *name);
+ void chFactoryReleaseSemaphore(dyn_semaphore_t *dsp);
+#endif
+#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__)
+ dyn_mailbox_t *chFactoryCreateMailbox(const char *name, size_t n);
+ dyn_mailbox_t *chFactoryFindMailbox(const char *name);
+ void chFactoryReleaseMailbox(dyn_mailbox_t *dmp);
+#endif
+#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__)
+ dyn_objects_fifo_t *chFactoryCreateObjectsFIFO(const char *name,
+ size_t objsize,
+ size_t objn,
+ unsigned objalign);
+ dyn_objects_fifo_t *chFactoryFindObjectsFIFO(const char *name);
+ void chFactoryReleaseObjectsFIFO(dyn_objects_fifo_t *dofp);
+#endif
+#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__)
+ dyn_pipe_t *chFactoryCreatePipe(const char *name, size_t size);
+ dyn_pipe_t *chFactoryFindPipe(const char *name);
+ void chFactoryReleasePipe(dyn_pipe_t *dpp);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Duplicates an object reference.
+ * @note This function can be used on any kind of dynamic object.
+ *
+ * @param[in] dep pointer to the element field of the object
+ * @return The duplicated object reference.
+ *
+ * @api
+ */
+static inline dyn_element_t *chFactoryDuplicateReference(dyn_element_t *dep) {
+
+ dep->refs++;
+
+ return dep;
+}
+
+#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Returns the pointer to the inner registered object.
+ *
+ * @param[in] rop registered object reference
+ * @return The pointer to the registered object.
+ *
+ * @api
+ */
+static inline void *chFactoryGetObject(registered_object_t *rop) {
+
+ return rop->objp;
+}
+#endif /* CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE */
+
+#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Returns the size of a generic dynamic buffer object.
+ *
+ * @param[in] dbp dynamic buffer object reference
+ * @return The size of the buffer object in bytes.
+ *
+ * @api
+ */
+static inline size_t chFactoryGetBufferSize(dyn_buffer_t *dbp) {
+
+ return chHeapGetSize(dbp) - sizeof (dyn_element_t);
+}
+
+/**
+ * @brief Returns the pointer to the inner buffer.
+ *
+ * @param[in] dbp dynamic buffer object reference
+ * @return The pointer to the dynamic buffer.
+ *
+ * @api
+ */
+static inline uint8_t *chFactoryGetBuffer(dyn_buffer_t *dbp) {
+
+ return (uint8_t *)(dbp + 1);
+}
+#endif /* CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE */
+
+#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Returns the pointer to the inner semaphore.
+ *
+ * @param[in] dsp dynamic semaphore object reference
+ * @return The pointer to the semaphore.
+ *
+ * @api
+ */
+static inline semaphore_t *chFactoryGetSemaphore(dyn_semaphore_t *dsp) {
+
+ return &dsp->sem;
+}
+#endif /* CH_CFG_FACTORY_SEMAPHORES == TRUE */
+
+#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Returns the pointer to the inner mailbox.
+ *
+ * @param[in] dmp dynamic mailbox object reference
+ * @return The pointer to the mailbox.
+ *
+ * @api
+ */
+static inline mailbox_t *chFactoryGetMailbox(dyn_mailbox_t *dmp) {
+
+ return &dmp->mbx;
+}
+#endif /* CH_CFG_FACTORY_MAILBOXES == TRUE */
+
+#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Returns the pointer to the inner objects FIFO.
+ *
+ * @param[in] dofp dynamic "objects FIFO" object reference
+ * @return The pointer to the objects FIFO.
+ *
+ * @api
+ */
+static inline objects_fifo_t *chFactoryGetObjectsFIFO(dyn_objects_fifo_t *dofp) {
+
+ return &dofp->fifo;
+}
+#endif /* CH_CFG_FACTORY_OBJ_FIFOS == TRUE */
+
+#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Returns the pointer to the inner pipe.
+ *
+ * @param[in] dpp dynamic pipe object reference
+ * @return The pointer to the pipe.
+ *
+ * @api
+ */
+static inline pipe_t *chFactoryGetPipe(dyn_pipe_t *dpp) {
+
+ return &dpp->pipe;
+}
+#endif /* CH_CFG_FACTORY_PIPES == TRUE */
+
+#endif /* CH_CFG_USE_FACTORY == TRUE */
+
+#endif /* CHFACTORY_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/include/chjobs.h b/ChibiOS_20.3.2/os/oslib/include/chjobs.h
new file mode 100644
index 0000000..46a8edc
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/include/chjobs.h
@@ -0,0 +1,397 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/include/chjobs.h
+ * @brief Jobs Queues structures and macros.
+ * @details This module implements queues of generic jobs to be delegated
+ * asynchronously to a pool of dedicated threads.
+ * Operations defined for Jobs Queues
+ * - Get: An job object is taken from the pool of the
+ * available jobs.
+ * - Post: A job is posted to the queue, it will be
+ * returned to the pool after execution.
+ * .
+ *
+ * @addtogroup oslib_jobs_queues
+ * @{
+ */
+
+#ifndef CHJOBS_H
+#define CHJOBS_H
+
+#if (CH_CFG_USE_JOBS == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Dispatcher return code in case of a @p JOB_NUL has been received.
+ */
+#define MSG_JOB_NULL ((msg_t)-2)
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if CH_CFG_USE_MEMPOOLS == FALSE
+#error "CH_CFG_USE_JOBS requires CH_CFG_USE_MEMPOOLS"
+#endif
+
+#if CH_CFG_USE_SEMAPHORES == FALSE
+#error "CH_CFG_USE_JOBS requires CH_CFG_USE_SEMAPHORES"
+#endif
+
+#if CH_CFG_USE_MAILBOXES == FALSE
+#error "CH_CFG_USE_JOBS requires CH_CFG_USE_MAILBOXES"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a jobs queue.
+ */
+typedef struct ch_jobs_queue {
+ /**
+ * @brief Pool of the free jobs.
+ */
+ guarded_memory_pool_t free;
+ /**
+ * @brief Mailbox of the sent jobs.
+ */
+ mailbox_t mbx;
+} jobs_queue_t;
+
+/**
+ * @brief Type of a job function.
+ */
+typedef void (*job_function_t)(void *arg);
+
+/**
+ * @brief Type of a job descriptor.
+ */
+typedef struct ch_job_descriptor {
+ /**
+ * @brief Job function.
+ */
+ job_function_t jobfunc;
+ /**
+ * @brief Argument to be passed to the job function.
+ */
+ void *jobarg;
+} job_descriptor_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes a jobs queue object.
+ *
+ * @param[out] jqp pointer to a @p jobs_queue_t structure
+ * @param[in] jobsn number of jobs available
+ * @param[in] jobsbuf pointer to the buffer of jobs, it must be able
+ * to hold @p jobsn @p job_descriptor_t structures
+ * @param[in] msgbuf pointer to the buffer of messages, it must be able
+ * to hold @p jobsn @p msg_t messages
+ *
+ * @init
+ */
+static inline void chJobObjectInit(jobs_queue_t *jqp,
+ size_t jobsn,
+ job_descriptor_t *jobsbuf,
+ msg_t *msgbuf) {
+
+ chDbgCheck((jobsn > 0U) && (jobsbuf != NULL) && (msgbuf != NULL));
+
+ chGuardedPoolObjectInit(&jqp->free, sizeof (job_descriptor_t));
+ chGuardedPoolLoadArray(&jqp->free, (void *)jobsbuf, jobsn);
+ chMBObjectInit(&jqp->mbx, msgbuf, jobsn);
+}
+
+/**
+ * @brief Allocates a free job object.
+ *
+ * @param[in] jqp pointer to a @p jobs_queue_t structure
+ * @return The pointer to the allocated job object.
+ *
+ * @api
+ */
+static inline job_descriptor_t *chJobGet(jobs_queue_t *jqp) {
+
+ return (job_descriptor_t *)chGuardedPoolAllocTimeout(&jqp->free, TIME_INFINITE);
+}
+
+/**
+ * @brief Allocates a free job object.
+ *
+ * @param[in] jqp pointer to a @p jobs_queue_t structure
+ * @return The pointer to the allocated job object.
+ * @retval NULL if a job object is not immediately available.
+ *
+ * @iclass
+ */
+static inline job_descriptor_t *chJobGetI(jobs_queue_t *jqp) {
+
+ return (job_descriptor_t *)chGuardedPoolAllocI(&jqp->free);
+}
+
+/**
+ * @brief Allocates a free job object.
+ *
+ * @param[in] jqp pointer to a @p jobs_queue_t structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The pointer to the allocated job object.
+ * @retval NULL if a job object is not available within the specified
+ * timeout.
+ *
+ * @sclass
+ */
+static inline job_descriptor_t *chJobGetTimeoutS(jobs_queue_t *jqp,
+ sysinterval_t timeout) {
+
+ return (job_descriptor_t *)chGuardedPoolAllocTimeoutS(&jqp->free, timeout);
+}
+
+/**
+ * @brief Allocates a free job object.
+ *
+ * @param[in] jqp pointer to a @p jobs_queue_t structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The pointer to the allocated job object.
+ * @retval NULL if a job object is not available within the specified
+ * timeout.
+ *
+ * @api
+ */
+static inline job_descriptor_t *chJobGetTimeout(jobs_queue_t *jqp,
+ sysinterval_t timeout) {
+
+ return (job_descriptor_t *)chGuardedPoolAllocTimeout(&jqp->free, timeout);
+}
+
+/**
+ * @brief Posts a job object.
+ * @note By design the object can be always immediately posted.
+ *
+ * @param[in] jqp pointer to a @p jobs_queue_t structure
+ * @param[in] jp pointer to the job object to be posted
+ *
+ * @iclass
+ */
+static inline void chJobPostI(jobs_queue_t *jqp, job_descriptor_t *jp) {
+ msg_t msg;
+
+ msg = chMBPostI(&jqp->mbx, (msg_t)jp);
+ chDbgAssert(msg == MSG_OK, "post failed");
+}
+
+/**
+ * @brief Posts a job object.
+ * @note By design the object can be always immediately posted.
+ *
+ * @param[in] jqp pointer to a @p jobs_queue_t structure
+ * @param[in] jp pointer to the job object to be posted
+ *
+ * @sclass
+ */
+static inline void chJobPostS(jobs_queue_t *jqp, job_descriptor_t *jp) {
+ msg_t msg;
+
+ msg = chMBPostTimeoutS(&jqp->mbx, (msg_t)jp, TIME_IMMEDIATE);
+ chDbgAssert(msg == MSG_OK, "post failed");
+}
+
+/**
+ * @brief Posts a job object.
+ * @note By design the object can be always immediately posted.
+ *
+ * @param[in] jqp pointer to a @p jobs_queue_t structure
+ * @param[in] jp pointer to the job object to be posted
+ *
+ * @api
+ */
+static inline void chJobPost(jobs_queue_t *jqp, job_descriptor_t *jp) {
+ msg_t msg;
+
+ msg = chMBPostTimeout(&jqp->mbx, (msg_t)jp, TIME_IMMEDIATE);
+ chDbgAssert(msg == MSG_OK, "post failed");
+}
+
+/**
+ * @brief Posts an high priority job object.
+ * @note By design the object can be always immediately posted.
+ *
+ * @param[in] jqp pointer to a @p jobs_queue_t structure
+ * @param[in] jp pointer to the job object to be posted
+ *
+ * @iclass
+ */
+static inline void chJobPostAheadI(jobs_queue_t *jqp, job_descriptor_t *jp) {
+ msg_t msg;
+
+ msg = chMBPostAheadI(&jqp->mbx, (msg_t)jp);
+ chDbgAssert(msg == MSG_OK, "post failed");
+}
+
+/**
+ * @brief Posts an high priority job object.
+ * @note By design the object can be always immediately posted.
+ *
+ * @param[in] jqp pointer to a @p jobs_queue_t structure
+ * @param[in] jp pointer to the job object to be posted
+ *
+ * @sclass
+ */
+static inline void chJobPostAheadS(jobs_queue_t *jqp, job_descriptor_t *jp) {
+ msg_t msg;
+
+ msg = chMBPostAheadTimeoutS(&jqp->mbx, (msg_t)jp, TIME_IMMEDIATE);
+ chDbgAssert(msg == MSG_OK, "post failed");
+}
+
+/**
+ * @brief Posts an high priority job object.
+ * @note By design the object can be always immediately posted.
+ *
+ * @param[in] jqp pointer to a @p jobs_queue_t structure
+ * @param[in] jp pointer to the job object to be posted
+ *
+ * @api
+ */
+static inline void chJobPostAhead(jobs_queue_t *jqp, job_descriptor_t *jp) {
+ msg_t msg;
+
+ msg = chMBPostAheadTimeout(&jqp->mbx, (msg_t)jp, TIME_IMMEDIATE);
+ chDbgAssert(msg == MSG_OK, "post failed");
+}
+
+/**
+ * @brief Waits for a job then executes it.
+ *
+ * @param[in] jqp pointer to a @p jobs_queue_t structure
+ * @return The function outcome.
+ * @retval MSG_OK if a job has been executed.
+ * @retval MSG_RESET if the internal mailbox has been reset.
+ * @retval MSG_JOB_NULL if a @p JOB_NULL has been received.
+ */
+static inline msg_t chJobDispatch(jobs_queue_t *jqp) {
+ msg_t msg, jmsg;
+
+ /* Waiting for a job.*/
+ msg = chMBFetchTimeout(&jqp->mbx, &jmsg, TIME_INFINITE);
+ if (msg == MSG_OK) {
+ job_descriptor_t *jp = (job_descriptor_t *)jmsg;
+
+ chDbgAssert(jp != NULL, "is NULL");
+
+ if (jp->jobfunc != NULL) {
+
+ /* Invoking the job function.*/
+ jp->jobfunc(jp->jobarg);
+
+ /* Returning the job descriptor object.*/
+ chGuardedPoolFree(&jqp->free, (void *)jp);
+ }
+ else {
+ msg = MSG_JOB_NULL;
+ }
+ }
+
+ return msg;
+}
+
+/**
+ * @brief Waits for a job then executes it.
+ *
+ * @param[in] jqp pointer to a @p jobs_queue_t structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The function outcome.
+ * @retval MSG_OK if a job has been executed.
+ * @retval MSG_TIMEOUT if a timeout occurred.
+ * @retval MSG_RESET if the internal mailbox has been reset.
+ * @retval MSG_JOB_NULL if a @p JOB_NULL has been received.
+ */
+static inline msg_t chJobDispatchTimeout(jobs_queue_t *jqp,
+ sysinterval_t timeout) {
+ msg_t msg, jmsg;
+
+ /* Waiting for a job or a timeout.*/
+ msg = chMBFetchTimeout(&jqp->mbx, &jmsg, timeout);
+ if (msg == MSG_OK) {
+ job_descriptor_t *jp = (job_descriptor_t *)jmsg;
+
+ chDbgAssert(jp != NULL, "is NULL");
+
+ if (jp->jobfunc != NULL) {
+
+ /* Invoking the job function.*/
+ jp->jobfunc(jp->jobarg);
+
+ /* Returning the job descriptor object.*/
+ chGuardedPoolFree(&jqp->free, (void *)jp);
+ }
+ else {
+ msg = MSG_JOB_NULL;
+ }
+ }
+
+ return msg;
+}
+
+#endif /* CH_CFG_USE_JOBS == TRUE */
+
+#endif /* CHJOBS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/include/chlib.h b/ChibiOS_20.3.2/os/oslib/include/chlib.h
new file mode 100644
index 0000000..d47efb2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/include/chlib.h
@@ -0,0 +1,264 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/include/chlib.h
+ * @brief ChibiOS/LIB main include file.
+ * @details This header includes all the required library headers. This file
+ * is meant do be included by @p ch.h not directly by user.
+ *
+ * @addtogroup oslib_info
+ * @details OS Library related info.
+ * @{
+ */
+
+#ifndef CHLIB_H
+#define CHLIB_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @brief ChibiOS/LIB identification macro.
+ */
+#define _CHIBIOS_OSLIB_
+
+/**
+ * @brief Stable release flag.
+ */
+#define CH_OSLIB_STABLE 1
+
+/**
+ * @name ChibiOS/LIB version identification
+ * @{
+ */
+/**
+ * @brief OS Library version string.
+ */
+#define CH_OSLIB_VERSION "1.2.0"
+
+/**
+ * @brief OS Library version major number.
+ */
+#define CH_OSLIB_MAJOR 1
+
+/**
+ * @brief OS Library version minor number.
+ */
+#define CH_OSLIB_MINOR 2
+
+/**
+ * @brief OS Library version patch number.
+ */
+#define CH_OSLIB_PATCH 0
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Host OS checks.*/
+#if !defined(_CHIBIOS_RT_) && !defined(_CHIBIOS_NIL_)
+#error "OS check failed, must be included after ch.h"
+#endif
+
+/* Configuration file checks.*/
+#if !defined(CH_CFG_USE_MAILBOXES)
+#error "CH_CFG_USE_MAILBOXES not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_MEMCORE)
+#error "CH_CFG_USE_MEMCORE not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_HEAP)
+#error "CH_CFG_USE_HEAP not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_MEMPOOLS)
+#error "CH_CFG_USE_MEMPOOLS not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_OBJ_FIFOS)
+#error "CH_CFG_USE_OBJ_FIFOS not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_PIPES)
+#error "CH_CFG_USE_PIPES not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_OBJ_CACHES)
+#error "CH_CFG_USE_OBJ_CACHES not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_DELEGATES)
+#error "CH_CFG_USE_DELEGATES not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_JOBS)
+#error "CH_CFG_USE_JOBS not defined in chconf.h"
+#endif
+
+/* Objects factory options checks.*/
+#if !defined(CH_CFG_USE_FACTORY)
+#error "CH_CFG_USE_FACTORY not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH)
+#error "CH_CFG_FACTORY_MAX_NAMES_LENGTH not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY)
+#error "CH_CFG_FACTORY_OBJECTS_REGISTRY not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS)
+#error "CH_CFG_FACTORY_GENERIC_BUFFERS not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_FACTORY_SEMAPHORES)
+#error "CH_CFG_FACTORY_SEMAPHORES not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_FACTORY_MAILBOXES)
+#error "CH_CFG_FACTORY_MAILBOXES not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_FACTORY_OBJ_FIFOS)
+#error "CH_CFG_FACTORY_OBJ_FIFOS not defined in chconf.h"
+#endif
+
+/* License checks.*/
+#if !defined(CH_CUSTOMER_LIC_OSLIB) || !defined(CH_LICENSE_FEATURES)
+#error "malformed chlicense.h"
+#endif
+
+#if (CH_LICENSE_FEATURES != CH_FEATURES_FULL) && \
+ (CH_LICENSE_FEATURES != CH_FEATURES_INTERMEDIATE) && \
+ (CH_LICENSE_FEATURES != CH_FEATURES_BASIC)
+#error "invalid CH_LICENSE_FEATURES setting"
+#endif
+
+/* Restrictions in basic and intermediate modes.*/
+#if (CH_CUSTOMER_LIC_OSLIB == FALSE) || \
+ (CH_LICENSE_FEATURES == CH_FEATURES_INTERMEDIATE) || \
+ (CH_LICENSE_FEATURES == CH_FEATURES_BASIC)
+
+/* Restricted subsystems.*/
+#undef CH_CFG_USE_FACTORY
+
+#define CH_CFG_USE_FACTORY FALSE
+
+#endif /* (CH_CUSTOMER_LIC_OSLIB == FALSE) ||
+ (CH_LICENSE_FEATURES == CH_FEATURES_INTERMEDIATE) ||
+ (CH_LICENSE_FEATURES == CH_FEATURES_BASIC) */
+
+/* Restrictions in basic mode.*/
+#if (CH_CUSTOMER_LIC_OSLIB == FALSE) || \
+ (CH_LICENSE_FEATURES == CH_FEATURES_BASIC)
+
+/* Restricted subsystems.*/
+#undef CH_CFG_USE_HEAP
+#undef CH_CFG_USE_MEMPOOLS
+#undef CH_CFG_USE_OBJ_FIFOS
+#undef CH_CFG_USE_PIPES
+#undef CH_CFG_USE_OBJ_CACHES
+#undef CH_CFG_USE_DELEGATES
+#undef CH_CFG_USE_JOBS
+
+#define CH_CFG_USE_HEAP FALSE
+#define CH_CFG_USE_MEMPOOLS FALSE
+#define CH_CFG_USE_OBJ_FIFOS FALSE
+#define CH_CFG_USE_PIPES FALSE
+#define CH_CFG_USE_OBJ_CACHES FALSE
+#define CH_CFG_USE_DELEGATES FALSE
+#define CH_CFG_USE_JOBS FALSE
+
+#endif /* (CH_CUSTOMER_LIC_OSLIB == FALSE) ||
+ (CH_LICENSE_FEATURES == CH_FEATURES_BASIC) */
+
+/* Restrictions in unlicensed mode.*/
+#if (CH_CUSTOMER_LIC_OSLIB == FALSE)
+
+/* Restricted subsystems.*/
+#undef CH_CFG_USE_MAILBOXES
+
+#define CH_CFG_USE_MAILBOXES FALSE
+
+#endif /* CH_CUSTOMER_LIC_OSLIB == FALSE */
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Late inclusions. */
+/*===========================================================================*/
+
+/* OS Library headers.*/
+#include "chbsem.h"
+#include "chmboxes.h"
+#include "chmemcore.h"
+#include "chmemheaps.h"
+#include "chmempools.h"
+#include "chobjfifos.h"
+#include "chpipes.h"
+#include "chobjcaches.h"
+#include "chdelegates.h"
+#include "chjobs.h"
+#include "chfactory.h"
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initialization of all library modules.
+ *
+ * @notapi
+ */
+static inline void _oslib_init(void) {
+
+#if CH_CFG_USE_MEMCORE == TRUE
+ _core_init();
+#endif
+#if CH_CFG_USE_HEAP == TRUE
+ _heap_init();
+#endif
+#if CH_CFG_USE_FACTORY == TRUE
+ _factory_init();
+#endif
+}
+
+#endif /* CHLIB_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/include/chmboxes.h b/ChibiOS_20.3.2/os/oslib/include/chmboxes.h
new file mode 100644
index 0000000..4f7882b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/include/chmboxes.h
@@ -0,0 +1,209 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/include/chmboxes.h
+ * @brief Mailboxes macros and structures.
+ *
+ * @addtogroup oslib_mailboxes
+ * @{
+ */
+
+#ifndef CHMBOXES_H
+#define CHMBOXES_H
+
+#if (CH_CFG_USE_MAILBOXES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Structure representing a mailbox object.
+ */
+typedef struct {
+ msg_t *buffer; /**< @brief Pointer to the mailbox
+ buffer. */
+ msg_t *top; /**< @brief Pointer to the location
+ after the buffer. */
+ msg_t *wrptr; /**< @brief Write pointer. */
+ msg_t *rdptr; /**< @brief Read pointer. */
+ size_t cnt; /**< @brief Messages in queue. */
+ bool reset; /**< @brief True in reset state. */
+ threads_queue_t qw; /**< @brief Queued writers. */
+ threads_queue_t qr; /**< @brief Queued readers. */
+} mailbox_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Data part of a static mailbox initializer.
+ * @details This macro should be used when statically initializing a
+ * mailbox that is part of a bigger structure.
+ *
+ * @param[in] name the name of the mailbox variable
+ * @param[in] buffer pointer to the mailbox buffer array of @p msg_t
+ * @param[in] size number of @p msg_t elements in the buffer array
+ */
+#define _MAILBOX_DATA(name, buffer, size) { \
+ (msg_t *)(buffer), \
+ (msg_t *)(buffer) + size, \
+ (msg_t *)(buffer), \
+ (msg_t *)(buffer), \
+ (size_t)0, \
+ false, \
+ _THREADS_QUEUE_DATA(name.qw), \
+ _THREADS_QUEUE_DATA(name.qr), \
+}
+
+/**
+ * @brief Static mailbox initializer.
+ * @details Statically initialized mailboxes require no explicit
+ * initialization using @p chMBObjectInit().
+ *
+ * @param[in] name the name of the mailbox variable
+ * @param[in] buffer pointer to the mailbox buffer array of @p msg_t
+ * @param[in] size number of @p msg_t elements in the buffer array
+ */
+#define MAILBOX_DECL(name, buffer, size) \
+ mailbox_t name = _MAILBOX_DATA(name, buffer, size)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chMBObjectInit(mailbox_t *mbp, msg_t *buf, size_t n);
+ void chMBReset(mailbox_t *mbp);
+ void chMBResetI(mailbox_t *mbp);
+ msg_t chMBPostTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout);
+ msg_t chMBPostTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout);
+ msg_t chMBPostI(mailbox_t *mbp, msg_t msg);
+ msg_t chMBPostAheadTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout);
+ msg_t chMBPostAheadTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout);
+ msg_t chMBPostAheadI(mailbox_t *mbp, msg_t msg);
+ msg_t chMBFetchTimeout(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout);
+ msg_t chMBFetchTimeoutS(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout);
+ msg_t chMBFetchI(mailbox_t *mbp, msg_t *msgp);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Returns the mailbox buffer size as number of messages.
+ *
+ * @param[in] mbp the pointer to an initialized @p mailbox_t object
+ * @return The size of the mailbox.
+ *
+ * @iclass
+ */
+static inline size_t chMBGetSizeI(const mailbox_t *mbp) {
+
+ /*lint -save -e9033 [10.8] Perfectly safe pointers
+ arithmetic.*/
+ return (size_t)(mbp->top - mbp->buffer);
+ /*lint -restore*/
+}
+
+/**
+ * @brief Returns the number of used message slots into a mailbox.
+ *
+ * @param[in] mbp the pointer to an initialized @p mailbox_t object
+ * @return The number of queued messages.
+ *
+ * @iclass
+ */
+static inline size_t chMBGetUsedCountI(const mailbox_t *mbp) {
+
+ chDbgCheckClassI();
+
+ return mbp->cnt;
+}
+
+/**
+ * @brief Returns the number of free message slots into a mailbox.
+ *
+ * @param[in] mbp the pointer to an initialized @p mailbox_t object
+ * @return The number of empty message slots.
+ *
+ * @iclass
+ */
+static inline size_t chMBGetFreeCountI(const mailbox_t *mbp) {
+
+ chDbgCheckClassI();
+
+ return chMBGetSizeI(mbp) - chMBGetUsedCountI(mbp);
+}
+
+/**
+ * @brief Returns the next message in the queue without removing it.
+ * @pre A message must be waiting in the queue for this function to work
+ * or it would return garbage. The correct way to use this macro is
+ * to use @p chMBGetUsedCountI() and then use this macro, all within
+ * a lock state.
+ *
+ * @param[in] mbp the pointer to an initialized @p mailbox_t object
+ * @return The next message in queue.
+ *
+ * @iclass
+ */
+static inline msg_t chMBPeekI(const mailbox_t *mbp) {
+
+ chDbgCheckClassI();
+
+ return *mbp->rdptr;
+}
+
+/**
+ * @brief Terminates the reset state.
+ *
+ * @param[in] mbp the pointer to an initialized @p mailbox_t object
+ *
+ * @xclass
+ */
+static inline void chMBResumeX(mailbox_t *mbp) {
+
+ mbp->reset = false;
+}
+
+#endif /* CH_CFG_USE_MAILBOXES == TRUE */
+
+#endif /* CHMBOXES_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/include/chmemcore.h b/ChibiOS_20.3.2/os/oslib/include/chmemcore.h
new file mode 100644
index 0000000..1b86154
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/include/chmemcore.h
@@ -0,0 +1,211 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/include/chmemcore.h
+ * @brief Core memory manager macros and structures.
+ *
+ * @addtogroup oslib_memcore
+ * @{
+ */
+
+#ifndef CHMEMCORE_H
+#define CHMEMCORE_H
+
+#if (CH_CFG_USE_MEMCORE == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
+ * provide the @p __heap_base__ and @p __heap_end__ symbols.
+ * @note Requires @p CH_CFG_USE_MEMCORE.
+ */
+#if !defined(CH_CFG_MEMCORE_SIZE) || defined(__DOXYGEN__)
+#define CH_CFG_MEMCORE_SIZE 0
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if CH_CFG_MEMCORE_SIZE < 0
+#error "invalid CH_CFG_MEMCORE_SIZE value specified"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Memory get function.
+ */
+typedef void *(*memgetfunc_t)(size_t size, unsigned align);
+
+/**
+ * @brief Enhanced memory get function.
+ */
+typedef void *(*memgetfunc2_t)(size_t size, unsigned align, size_t offset);
+
+/**
+ * @brief Type of memory core object.
+ */
+typedef struct {
+ /**
+ * @brief Next free address.
+ */
+ uint8_t *basemem;
+ /**
+ * @brief Final address.
+ */
+ uint8_t *topmem;
+} memcore_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Allocates a memory block.
+ * @note This is a generic form with unspecified allocation position.
+ *
+ * @iclass
+ */
+#define chCoreAllocAlignedWithOffsetI chCoreAllocFromTopI
+
+/**
+ * @brief Allocates a memory block.
+ * @note This is a generic form with unspecified allocation position.
+ *
+ * @api
+ */
+#define chCoreAllocAlignedWithOffset chCoreAllocFromTop
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern memcore_t ch_memcore;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void _core_init(void);
+ void *chCoreAllocFromBaseI(size_t size, unsigned align, size_t offset);
+ void *chCoreAllocFromTopI(size_t size, unsigned align, size_t offset);
+ void *chCoreAllocFromBase(size_t size, unsigned align, size_t offset);
+ void *chCoreAllocFromTop(size_t size, unsigned align, size_t offset);
+ size_t chCoreGetStatusX(void);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Allocates a memory block.
+ * @details The allocated block is guaranteed to be properly aligned to the
+ * specified alignment.
+ * @note This is a generic form with unspecified allocation position.
+ *
+ * @param[in] size the size of the block to be allocated.
+ * @param[in] align desired memory alignment
+ * @return A pointer to the allocated memory block.
+ * @retval NULL allocation failed, core memory exhausted.
+ *
+ * @iclass
+ */
+static inline void *chCoreAllocAlignedI(size_t size, unsigned align) {
+
+ return chCoreAllocAlignedWithOffsetI(size, align, 0U);
+}
+
+/**
+ * @brief Allocates a memory block.
+ * @details The allocated block is guaranteed to be properly aligned to the
+ * specified alignment.
+ * @note This is a generic form with unspecified allocation position.
+ *
+ * @param[in] size the size of the block to be allocated
+ * @param[in] align desired memory alignment
+ * @return A pointer to the allocated memory block.
+ * @retval NULL allocation failed, core memory exhausted.
+ *
+ * @api
+ */
+static inline void *chCoreAllocAligned(size_t size, unsigned align) {
+
+ return chCoreAllocAlignedWithOffset(size, align, 0U);
+}
+
+/**
+ * @brief Allocates a memory block.
+ * @details The allocated block is guaranteed to be properly aligned for a
+ * pointer data type.
+ * @note This is a generic form with unspecified allocation position.
+ *
+ * @param[in] size the size of the block to be allocated.
+ * @return A pointer to the allocated memory block.
+ * @retval NULL allocation failed, core memory exhausted.
+ *
+ * @iclass
+ */
+static inline void *chCoreAllocI(size_t size) {
+
+ return chCoreAllocAlignedWithOffsetI(size, PORT_NATURAL_ALIGN, 0U);
+}
+
+/**
+ * @brief Allocates a memory block.
+ * @details The allocated block is guaranteed to be properly aligned for a
+ * pointer data type.
+ * @note This is a generic form with unspecified allocation position.
+ *
+ * @param[in] size the size of the block to be allocated.
+ * @return A pointer to the allocated memory block.
+ * @retval NULL allocation failed, core memory exhausted.
+ *
+ * @api
+ */
+static inline void *chCoreAlloc(size_t size) {
+
+ return chCoreAllocAlignedWithOffset(size, PORT_NATURAL_ALIGN, 0U);
+}
+
+#endif /* CH_CFG_USE_MEMCORE == TRUE */
+
+#endif /* CHMEMCORE_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/include/chmemheaps.h b/ChibiOS_20.3.2/os/oslib/include/chmemheaps.h
new file mode 100644
index 0000000..3c6daf9
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/include/chmemheaps.h
@@ -0,0 +1,178 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/include/chmemheaps.h
+ * @brief Memory heaps macros and structures.
+ *
+ * @addtogroup oslib_memheaps
+ * @{
+ */
+
+#ifndef CHMEMHEAPS_H
+#define CHMEMHEAPS_H
+
+#if (CH_CFG_USE_HEAP == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Minimum alignment used for heap.
+ * @note Cannot use the sizeof operator in this macro.
+ */
+#if (SIZEOF_PTR == 4) || defined(__DOXYGEN__)
+#define CH_HEAP_ALIGNMENT 8U
+#elif (SIZEOF_PTR == 2)
+#define CH_HEAP_ALIGNMENT 4U
+#else
+#error "unsupported pointer size"
+#endif
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if CH_CFG_USE_MEMCORE == FALSE
+#error "CH_CFG_USE_HEAP requires CH_CFG_USE_MEMCORE"
+#endif
+
+#if (CH_CFG_USE_MUTEXES == FALSE) && (CH_CFG_USE_SEMAPHORES == FALSE)
+#error "CH_CFG_USE_HEAP requires CH_CFG_USE_MUTEXES and/or CH_CFG_USE_SEMAPHORES"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a memory heap.
+ */
+typedef struct memory_heap memory_heap_t;
+
+/**
+ * @brief Type of a memory heap header.
+ */
+typedef union heap_header heap_header_t;
+
+/**
+ * @brief Memory heap block header.
+ */
+union heap_header {
+ struct {
+ heap_header_t *next; /**< @brief Next block in free list. */
+ size_t pages; /**< @brief Size of the area in pages. */
+ } free;
+ struct {
+ memory_heap_t *heap; /**< @brief Block owner heap. */
+ size_t size; /**< @brief Size of the area in bytes. */
+ } used;
+};
+
+/**
+ * @brief Structure describing a memory heap.
+ */
+struct memory_heap {
+ memgetfunc2_t provider; /**< @brief Memory blocks provider for
+ this heap. */
+ heap_header_t header; /**< @brief Free blocks list header. */
+#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
+ mutex_t mtx; /**< @brief Heap access mutex. */
+#else
+ semaphore_t sem; /**< @brief Heap access semaphore. */
+#endif
+};
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Allocation of an aligned static heap buffer.
+ */
+#define CH_HEAP_AREA(name, size) \
+ ALIGNED_VAR(CH_HEAP_ALIGNMENT) \
+ uint8_t name[MEM_ALIGN_NEXT((size), CH_HEAP_ALIGNMENT)]
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void _heap_init(void);
+ void chHeapObjectInit(memory_heap_t *heapp, void *buf, size_t size);
+ void *chHeapAllocAligned(memory_heap_t *heapp, size_t size, unsigned align);
+ void chHeapFree(void *p);
+ size_t chHeapStatus(memory_heap_t *heapp, size_t *totalp, size_t *largestp);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Allocates a block of memory from the heap by using the first-fit
+ * algorithm.
+ * @details The allocated block is guaranteed to be properly aligned for a
+ * pointer data type.
+ *
+ * @param[in] heapp pointer to a heap descriptor or @p NULL in order to
+ * access the default heap.
+ * @param[in] size the size of the block to be allocated. Note that the
+ * allocated block may be a bit bigger than the requested
+ * size for alignment and fragmentation reasons.
+ * @return A pointer to the allocated block.
+ * @retval NULL if the block cannot be allocated.
+ *
+ * @api
+ */
+static inline void *chHeapAlloc(memory_heap_t *heapp, size_t size) {
+
+ return chHeapAllocAligned(heapp, size, CH_HEAP_ALIGNMENT);
+}
+
+/**
+ * @brief Returns the size of an allocated block.
+ * @note The returned value is the requested size, the real size is the
+ * same value aligned to the next @p CH_HEAP_ALIGNMENT multiple.
+ *
+ * @param[in] p pointer to the memory block
+ * @return Size of the block.
+ *
+ * @api
+ */
+static inline size_t chHeapGetSize(const void *p) {
+
+ return ((heap_header_t *)p - 1U)->used.size;
+}
+
+#endif /* CH_CFG_USE_HEAP == TRUE */
+
+#endif /* CHMEMHEAPS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/include/chmempools.h b/ChibiOS_20.3.2/os/oslib/include/chmempools.h
new file mode 100644
index 0000000..2760e01
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/include/chmempools.h
@@ -0,0 +1,385 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/include/chmempools.h
+ * @brief Memory Pools macros and structures.
+ *
+ * @addtogroup oslib_mempools
+ * @{
+ */
+
+#ifndef CHMEMPOOLS_H
+#define CHMEMPOOLS_H
+
+#if (CH_CFG_USE_MEMPOOLS == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if CH_CFG_USE_MEMCORE == FALSE
+#error "CH_CFG_USE_MEMPOOLS requires CH_CFG_USE_MEMCORE"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Memory pool free object header.
+ */
+struct pool_header {
+ struct pool_header *next; /**< @brief Pointer to the next pool
+ header in the list. */
+};
+
+/**
+ * @brief Memory pool descriptor.
+ */
+typedef struct {
+ struct pool_header *next; /**< @brief Pointer to the header. */
+ size_t object_size; /**< @brief Memory pool objects
+ size. */
+ unsigned align; /**< @brief Required alignment. */
+ memgetfunc_t provider; /**< @brief Memory blocks provider
+ for this pool. */
+} memory_pool_t;
+
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Guarded memory pool descriptor.
+ */
+typedef struct {
+ semaphore_t sem; /**< @brief Counter semaphore guarding
+ the memory pool. */
+ memory_pool_t pool; /**< @brief The memory pool itself. */
+} guarded_memory_pool_t;
+#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Data part of a static memory pool initializer.
+ * @details This macro should be used when statically initializing a
+ * memory pool that is part of a bigger structure.
+ *
+ * @param[in] name the name of the memory pool variable
+ * @param[in] size size of the memory pool contained objects
+ * @param[in] align required memory alignment
+ * @param[in] provider memory provider function for the memory pool
+ */
+#define _MEMORYPOOL_DATA(name, size, align, provider) \
+ {NULL, size, align, provider}
+
+/**
+ * @brief Static memory pool initializer.
+ * @details Statically initialized memory pools require no explicit
+ * initialization using @p chPoolInit().
+ *
+ * @param[in] name the name of the memory pool variable
+ * @param[in] size size of the memory pool contained objects
+ * @param[in] align required memory alignment
+ * @param[in] provider memory provider function for the memory pool or @p NULL
+ * if the pool is not allowed to grow automatically
+ */
+#define MEMORYPOOL_DECL(name, size, align, provider) \
+ memory_pool_t name = _MEMORYPOOL_DATA(name, size, align, provider)
+
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Data part of a static guarded memory pool initializer.
+ * @details This macro should be used when statically initializing a
+ * memory pool that is part of a bigger structure.
+ *
+ * @param[in] name the name of the memory pool variable
+ * @param[in] size size of the memory pool contained objects
+ * @param[in] align required memory alignment
+ */
+#define _GUARDEDMEMORYPOOL_DATA(name, size, align) { \
+ _SEMAPHORE_DATA(name.sem, (cnt_t)0), \
+ _MEMORYPOOL_DATA(NULL, size, align, NULL) \
+}
+
+/**
+ * @brief Static guarded memory pool initializer.
+ * @details Statically initialized guarded memory pools require no explicit
+ * initialization using @p chGuardedPoolInit().
+ *
+ * @param[in] name the name of the guarded memory pool variable
+ * @param[in] size size of the memory pool contained objects
+ * @param[in] align required memory alignment
+ */
+#define GUARDEDMEMORYPOOL_DECL(name, size, align) \
+ guarded_memory_pool_t name = _GUARDEDMEMORYPOOL_DATA(name, size, align)
+#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chPoolObjectInitAligned(memory_pool_t *mp, size_t size,
+ unsigned align, memgetfunc_t provider);
+ void chPoolLoadArray(memory_pool_t *mp, void *p, size_t n);
+ void *chPoolAllocI(memory_pool_t *mp);
+ void *chPoolAlloc(memory_pool_t *mp);
+ void chPoolFreeI(memory_pool_t *mp, void *objp);
+ void chPoolFree(memory_pool_t *mp, void *objp);
+#if CH_CFG_USE_SEMAPHORES == TRUE
+ void chGuardedPoolObjectInitAligned(guarded_memory_pool_t *gmp,
+ size_t size,
+ unsigned align);
+ void chGuardedPoolLoadArray(guarded_memory_pool_t *gmp, void *p, size_t n);
+ void *chGuardedPoolAllocTimeoutS(guarded_memory_pool_t *gmp,
+ sysinterval_t timeout);
+ void *chGuardedPoolAllocTimeout(guarded_memory_pool_t *gmp,
+ sysinterval_t timeout);
+ void chGuardedPoolFree(guarded_memory_pool_t *gmp, void *objp);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes an empty memory pool.
+ *
+ * @param[out] mp pointer to a @p memory_pool_t structure
+ * @param[in] size the size of the objects contained in this memory pool,
+ * the minimum accepted size is the size of a pointer to
+ * void.
+ * @param[in] provider memory provider function for the memory pool or
+ * @p NULL if the pool is not allowed to grow
+ * automatically
+ *
+ * @init
+ */
+static inline void chPoolObjectInit(memory_pool_t *mp,
+ size_t size,
+ memgetfunc_t provider) {
+
+ chPoolObjectInitAligned(mp, size, PORT_NATURAL_ALIGN, provider);
+}
+
+/**
+ * @brief Adds an object to a memory pool.
+ * @pre The memory pool must be already been initialized.
+ * @pre The added object must be of the right size for the specified
+ * memory pool.
+ * @pre The added object must be properly aligned.
+ * @note This function is just an alias for @p chPoolFree() and has been
+ * added for clarity.
+ *
+ * @param[in] mp pointer to a @p memory_pool_t structure
+ * @param[in] objp the pointer to the object to be added
+ *
+ * @api
+ */
+static inline void chPoolAdd(memory_pool_t *mp, void *objp) {
+
+ chPoolFree(mp, objp);
+}
+
+/**
+ * @brief Adds an object to a memory pool.
+ * @pre The memory pool must be already been initialized.
+ * @pre The added object must be of the right size for the specified
+ * memory pool.
+ * @pre The added object must be properly aligned.
+ * @note This function is just an alias for @p chPoolFreeI() and has been
+ * added for clarity.
+ *
+ * @param[in] mp pointer to a @p memory_pool_t structure
+ * @param[in] objp the pointer to the object to be added
+ *
+ * @iclass
+ */
+static inline void chPoolAddI(memory_pool_t *mp, void *objp) {
+
+ chPoolFreeI(mp, objp);
+}
+
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Initializes an empty guarded memory pool.
+ *
+ * @param[out] gmp pointer to a @p guarded_memory_pool_t structure
+ * @param[in] size the size of the objects contained in this guarded
+ * memory pool, the minimum accepted size is the size
+ * of a pointer to void.
+ *
+ * @init
+ */
+static inline void chGuardedPoolObjectInit(guarded_memory_pool_t *gmp,
+ size_t size) {
+
+ chGuardedPoolObjectInitAligned(gmp, size, PORT_NATURAL_ALIGN);
+}
+
+/**
+ * @brief Gets the count of objects in a guarded memory pool.
+ * @pre The guarded memory pool must be already been initialized.
+ *
+ * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
+ * @return The counter of the guard semaphore.
+ *
+ * @iclass
+ */
+static inline cnt_t chGuardedPoolGetCounterI(guarded_memory_pool_t *gmp) {
+
+ return chSemGetCounterI(&gmp->sem);
+}
+
+/**
+ * @brief Allocates an object from a guarded memory pool.
+ * @pre The guarded memory pool must be already been initialized.
+ *
+ * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
+ * @return The pointer to the allocated object.
+ * @retval NULL if the pool is empty.
+ *
+ * @iclass
+ */
+static inline void *chGuardedPoolAllocI(guarded_memory_pool_t *gmp) {
+ void *p;
+
+ p = chPoolAllocI(&gmp->pool);
+ if (p != NULL) {
+ chSemFastWaitI(&gmp->sem);
+ chDbgAssert(chSemGetCounterI(&gmp->sem) >= (cnt_t)0,
+ "semaphore out of sync");
+ }
+ return p;
+}
+
+/**
+ * @brief Releases an object into a guarded memory pool.
+ * @pre The guarded memory pool must already be initialized.
+ * @pre The freed object must be of the right size for the specified
+ * guarded memory pool.
+ * @pre The added object must be properly aligned.
+ *
+ * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
+ * @param[in] objp the pointer to the object to be released
+ *
+ * @iclass
+ */
+static inline void chGuardedPoolFreeI(guarded_memory_pool_t *gmp, void *objp) {
+
+ chPoolFreeI(&gmp->pool, objp);
+ chSemSignalI(&gmp->sem);
+}
+
+/**
+ * @brief Releases an object into a guarded memory pool.
+ * @pre The guarded memory pool must already be initialized.
+ * @pre The freed object must be of the right size for the specified
+ * guarded memory pool.
+ * @pre The added object must be properly aligned.
+ *
+ * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
+ * @param[in] objp the pointer to the object to be released
+ *
+ * @sclass
+ */
+static inline void chGuardedPoolFreeS(guarded_memory_pool_t *gmp, void *objp) {
+
+ chGuardedPoolFreeI(gmp, objp);
+ chSchRescheduleS();
+}
+
+/**
+ * @brief Adds an object to a guarded memory pool.
+ * @pre The guarded memory pool must be already been initialized.
+ * @pre The added object must be of the right size for the specified
+ * guarded memory pool.
+ * @pre The added object must be properly aligned.
+ * @note This function is just an alias for @p chGuardedPoolFree() and
+ * has been added for clarity.
+ *
+ * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
+ * @param[in] objp the pointer to the object to be added
+ *
+ * @api
+ */
+static inline void chGuardedPoolAdd(guarded_memory_pool_t *gmp, void *objp) {
+
+ chGuardedPoolFree(gmp, objp);
+}
+
+/**
+ * @brief Adds an object to a guarded memory pool.
+ * @pre The guarded memory pool must be already been initialized.
+ * @pre The added object must be of the right size for the specified
+ * guarded memory pool.
+ * @pre The added object must be properly aligned.
+ * @note This function is just an alias for @p chGuardedPoolFreeI() and
+ * has been added for clarity.
+ *
+ * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
+ * @param[in] objp the pointer to the object to be added
+ *
+ * @iclass
+ */
+static inline void chGuardedPoolAddI(guarded_memory_pool_t *gmp, void *objp) {
+
+ chGuardedPoolFreeI(gmp, objp);
+}
+
+/**
+ * @brief Adds an object to a guarded memory pool.
+ * @pre The guarded memory pool must be already been initialized.
+ * @pre The added object must be of the right size for the specified
+ * guarded memory pool.
+ * @pre The added object must be properly aligned.
+ * @note This function is just an alias for @p chGuardedPoolFreeI() and
+ * has been added for clarity.
+ *
+ * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
+ * @param[in] objp the pointer to the object to be added
+ *
+ * @sclass
+ */
+static inline void chGuardedPoolAddS(guarded_memory_pool_t *gmp, void *objp) {
+
+ chGuardedPoolFreeS(gmp, objp);
+}
+#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
+
+#endif /* CH_CFG_USE_MEMPOOLS == TRUE */
+
+#endif /* CHMEMPOOLS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/include/chobjcaches.h b/ChibiOS_20.3.2/os/oslib/include/chobjcaches.h
new file mode 100644
index 0000000..db69576
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/include/chobjcaches.h
@@ -0,0 +1,304 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/include/chobjcaches.h
+ * @brief Objects Caches macros and structures.
+ *
+ * @addtogroup oslib_objchaches
+ * @{
+ */
+
+#ifndef CHOBJCACHES_H
+#define CHOBJCACHES_H
+
+#if (CH_CFG_USE_OBJ_CACHES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Cached objects flags
+ * @{
+ */
+#define OC_FLAG_INLRU 0x00000001U
+#define OC_FLAG_INHASH 0x00000002U
+#define OC_FLAG_SHARED 0x00000004U
+#define OC_FLAG_NOTSYNC 0x00000008U
+#define OC_FLAG_LAZYWRITE 0x00000010U
+#define OC_FLAG_FORGET 0x00000020U
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Flags of cached objects.
+ */
+typedef uint32_t oc_flags_t;
+
+/**
+ * @brief Type of an hash element header.
+ */
+typedef struct ch_oc_hash_header oc_hash_header_t;
+
+/**
+ * @brief Type of an LRU element header.
+ */
+typedef struct ch_oc_lru_header oc_lru_header_t;
+
+/**
+ * @brief Type of a cached object.
+ */
+typedef struct ch_oc_object oc_object_t;
+
+/**
+ * @brief Type of a cache object.
+ */
+typedef struct ch_objects_cache objects_cache_t;
+
+/**
+ * @brief Object read function.
+ *
+ * @param[in] ocp pointer to the @p objects_cache_t structure
+ * @param[in] async requests an asynchronous operation if supported, the
+ * function is then responsible for releasing the
+ * object
+ */
+typedef bool (*oc_readf_t)(objects_cache_t *ocp,
+ oc_object_t *objp,
+ bool async);
+
+/**
+ * @brief Object write function.
+ *
+ * @param[in] ocp pointer to the @p objects_cache_t structure
+ * @param[in] async requests an asynchronous operation if supported, the
+ * function is then responsible for releasing the
+ * object
+ */
+typedef bool (*oc_writef_t)(objects_cache_t *ocp,
+ oc_object_t *objp,
+ bool async);
+
+/**
+ * @brief Structure representing an hash table element.
+ */
+struct ch_oc_hash_header {
+ /**
+ * @brief Next in the collisions list.
+ */
+ oc_object_t *hash_next;
+ /**
+ * @brief Previous in the collisions list.
+ */
+ oc_object_t *hash_prev;
+};
+
+/**
+ * @brief Structure representing an hash table element.
+ */
+struct ch_oc_lru_header {
+ /**
+ * @brief Next in the collisions list.
+ */
+ oc_object_t *hash_next;
+ /**
+ * @brief Previous in the collisions list.
+ */
+ oc_object_t *hash_prev;
+ /**
+ * @brief Next in the LRU list.
+ */
+ oc_object_t *lru_next;
+ /**
+ * @brief Previous in the LRU list.
+ */
+ oc_object_t *lru_prev;
+};
+
+/**
+ * @brief Structure representing a cached object.
+ */
+struct ch_oc_object {
+ /**
+ * @brief Next in the collisions list.
+ */
+ oc_object_t *hash_next;
+ /**
+ * @brief Previous in the collisions list.
+ */
+ oc_object_t *hash_prev;
+ /**
+ * @brief Next in the LRU list.
+ */
+ oc_object_t *lru_next;
+ /**
+ * @brief Previous in the LRU list.
+ */
+ oc_object_t *lru_prev;
+ /**
+ * @brief Object group.
+ */
+ uint32_t obj_group;
+ /**
+ * @brief Object key.
+ */
+ uint32_t obj_key;
+ /**
+ * @brief Semaphore for object access.
+ */
+ semaphore_t obj_sem;
+ /**
+ * @brief Object flags.
+ */
+ oc_flags_t obj_flags;
+ /**
+ * @brief User pointer.
+ * @note This pointer can be used to refer to external buffers,
+ * @p chCacheObjectInit() initializes it to @p NULL.
+ */
+ void *dptr;
+};
+
+/**
+ * @brief Structure representing a cache object.
+ */
+struct ch_objects_cache {
+ /**
+ * @brief Number of elements in the hash table.
+ */
+ ucnt_t hashn;
+ /**
+ * @brief Pointer to the hash table.
+ */
+ oc_hash_header_t *hashp;
+ /**
+ * @brief Number of elements in the objects table.
+ */
+ ucnt_t objn;
+ /**
+ * @brief Size of elements in the objects table.
+ */
+ size_t objsz;
+ /**
+ * @brief Pointer to the objects table.
+ */
+ void *objvp;
+ /**
+ * @brief LRU list header.
+ */
+ oc_lru_header_t lru;
+ /**
+ * @brief Semaphore for cache access.
+ */
+ semaphore_t cache_sem;
+ /**
+ * @brief Semaphore for LRU access.
+ */
+ semaphore_t lru_sem;
+ /**
+ * @brief Reader functions for cached objects.
+ */
+ oc_readf_t readf;
+ /**
+ * @brief Writer functions for cached objects.
+ */
+ oc_writef_t writef;
+};
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chCacheObjectInit(objects_cache_t *ocp,
+ ucnt_t hashn,
+ oc_hash_header_t *hashp,
+ ucnt_t objn,
+ size_t objsz,
+ void *objvp,
+ oc_readf_t readf,
+ oc_writef_t writef);
+ oc_object_t *chCacheGetObject(objects_cache_t *ocp,
+ uint32_t group,
+ uint32_t key);
+ void chCacheReleaseObjectI(objects_cache_t *ocp,
+ oc_object_t *objp);
+ bool chCacheReadObject(objects_cache_t *ocp,
+ oc_object_t *objp,
+ bool async);
+ bool chCacheWriteObject(objects_cache_t *ocp,
+ oc_object_t *objp,
+ bool async);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Releases an object into the cache.
+ * @note This function gives a meaning to the following flags:
+ * - @p OC_FLAG_INLRU must be cleared.
+ * - @p OC_FLAG_INHASH must be set.
+ * - @p OC_FLAG_SHARED must be cleared.
+ * - @p OC_FLAG_NOTSYNC invalidates the object and queues it on
+ * the LRU tail.
+ * - @p OC_FLAG_LAZYWRITE is ignored and kept, a write will occur
+ * when the object is removed from the LRU list (lazy write).
+ * .
+ *
+ * @param[in] ocp pointer to the @p objects_cache_t structure
+ * @param[in] objp pointer to the @p oc_object_t structure
+ *
+ * @api
+ */
+static inline void chCacheReleaseObject(objects_cache_t *ocp,
+ oc_object_t *objp) {
+
+ chSysLock();
+ chCacheReleaseObjectI(ocp, objp);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+#endif /* CH_CFG_USE_OBJ_CACHES == TRUE */
+
+#endif /* CHOBJCACHES_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/include/chobjfifos.h b/ChibiOS_20.3.2/os/oslib/include/chobjfifos.h
new file mode 100644
index 0000000..52c2279
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/include/chobjfifos.h
@@ -0,0 +1,430 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/include/chobjfifos.h
+ * @brief Objects FIFO structures and macros.
+ * @details This module implements a generic FIFO queue of objects by
+ * coupling a Guarded Memory Pool (for objects storage) and
+ * a MailBox.
+ * On the sender side free objects are taken from the pool, filled
+ * and then sent to the receiver, on the receiver side objects are
+ * fetched, used and then returned to the pool.
+ * Operations defined for object FIFOs:
+ * - Take: An object is taken from the pool of the free
+ * objects, can be blocking.
+ * - Return: An object is returned to the pool of the
+ * free objects, it is guaranteed to be non-blocking.
+ * - Send: An object is sent through the mailbox, it is
+ * guaranteed to be non-blocking
+ * - Receive: An object is received from the mailbox,
+ * can be blocking.
+ * .
+ *
+ * @addtogroup oslib_objects_fifos
+ * @{
+ */
+
+#ifndef CHOBJFIFOS_H
+#define CHOBJFIFOS_H
+
+#if (CH_CFG_USE_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if CH_CFG_USE_MEMPOOLS == FALSE
+#error "CH_CFG_USE_OBJ_FIFOS requires CH_CFG_USE_MEMPOOLS"
+#endif
+
+#if CH_CFG_USE_SEMAPHORES == FALSE
+#error "CH_CFG_USE_OBJ_FIFOS requires CH_CFG_USE_SEMAPHORES"
+#endif
+
+#if CH_CFG_USE_MAILBOXES == FALSE
+#error "CH_CFG_USE_OBJ_FIFOS requires CH_CFG_USE_MAILBOXES"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of an objects FIFO.
+ */
+typedef struct ch_objects_fifo {
+ /**
+ * @brief Pool of the free objects.
+ */
+ guarded_memory_pool_t free;
+ /**
+ * @brief Mailbox of the sent objects.
+ */
+ mailbox_t mbx;
+} objects_fifo_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes a FIFO object.
+ * @pre The messages size must be a multiple of the alignment
+ * requirement.
+ *
+ * @param[out] ofp pointer to a @p objects_fifo_t structure
+ * @param[in] objsize size of objects
+ * @param[in] objn number of objects available
+ * @param[in] objalign required objects alignment
+ * @param[in] objbuf pointer to the buffer of objects, it must be able
+ * to hold @p objn objects of @p objsize size with
+ * @p objalign alignment
+ * @param[in] msgbuf pointer to the buffer of messages, it must be able
+ * to hold @p objn messages
+ *
+ * @init
+ */
+static inline void chFifoObjectInitAligned(objects_fifo_t *ofp, size_t objsize,
+ size_t objn, unsigned objalign,
+ void *objbuf, msg_t *msgbuf) {
+
+ chDbgCheck((objsize >= objalign) && ((objsize % objalign) == 0U));
+
+ chGuardedPoolObjectInitAligned(&ofp->free, objsize, objalign);
+ chGuardedPoolLoadArray(&ofp->free, objbuf, objn);
+ chMBObjectInit(&ofp->mbx, msgbuf, objn);
+}
+
+/**
+ * @brief Initializes a FIFO object.
+ * @pre The messages size must be a multiple of the alignment
+ * requirement.
+ *
+ * @param[out] ofp pointer to a @p objects_fifo_t structure
+ * @param[in] objsize size of objects
+ * @param[in] objn number of objects available
+ * @param[in] objbuf pointer to the buffer of objects, it must be able
+ * to hold @p objn objects of @p objsize size
+ * @param[in] msgbuf pointer to the buffer of messages, it must be able
+ * to hold @p objn messages
+ *
+ * @init
+ */
+static inline void chFifoObjectInit(objects_fifo_t *ofp, size_t objsize,
+ size_t objn, void *objbuf,
+ msg_t *msgbuf) {
+
+ chFifoObjectInitAligned(ofp, objsize, objn,
+ PORT_NATURAL_ALIGN,
+ objbuf, msgbuf);
+}
+
+/**
+ * @brief Allocates a free object.
+ *
+ * @param[in] ofp pointer to a @p objects_fifo_t structure
+ * @return The pointer to the allocated object.
+ * @retval NULL if an object is not immediately available.
+ *
+ * @iclass
+ */
+static inline void *chFifoTakeObjectI(objects_fifo_t *ofp) {
+
+ return chGuardedPoolAllocI(&ofp->free);
+}
+
+/**
+ * @brief Allocates a free object.
+ *
+ * @param[in] ofp pointer to a @p objects_fifo_t structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The pointer to the allocated object.
+ * @retval NULL if an object is not available within the specified
+ * timeout.
+ *
+ * @sclass
+ */
+static inline void *chFifoTakeObjectTimeoutS(objects_fifo_t *ofp,
+ sysinterval_t timeout) {
+
+ return chGuardedPoolAllocTimeoutS(&ofp->free, timeout);
+}
+
+/**
+ * @brief Allocates a free object.
+ *
+ * @param[in] ofp pointer to a @p objects_fifo_t structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The pointer to the allocated object.
+ * @retval NULL if an object is not available within the specified
+ * timeout.
+ *
+ * @api
+ */
+static inline void *chFifoTakeObjectTimeout(objects_fifo_t *ofp,
+ sysinterval_t timeout) {
+
+ return chGuardedPoolAllocTimeout(&ofp->free, timeout);
+}
+
+/**
+ * @brief Releases a fetched object.
+ *
+ * @param[in] ofp pointer to a @p objects_fifo_t structure
+ * @param[in] objp pointer to the object to be released
+ *
+ * @iclass
+ */
+static inline void chFifoReturnObjectI(objects_fifo_t *ofp,
+ void *objp) {
+
+ chGuardedPoolFreeI(&ofp->free, objp);
+}
+
+/**
+ * @brief Releases a fetched object.
+ *
+ * @param[in] ofp pointer to a @p objects_fifo_t structure
+ * @param[in] objp pointer to the object to be released
+ *
+ * @sclass
+ */
+static inline void chFifoReturnObjectS(objects_fifo_t *ofp,
+ void *objp) {
+
+ chGuardedPoolFreeS(&ofp->free, objp);
+}
+
+/**
+ * @brief Releases a fetched object.
+ *
+ * @param[in] ofp pointer to a @p objects_fifo_t structure
+ * @param[in] objp pointer to the object to be released
+ *
+ * @api
+ */
+static inline void chFifoReturnObject(objects_fifo_t *ofp,
+ void *objp) {
+
+ chGuardedPoolFree(&ofp->free, objp);
+}
+
+/**
+ * @brief Posts an object.
+ * @note By design the object can be always immediately posted.
+ *
+ * @param[in] ofp pointer to a @p objects_fifo_t structure
+ * @param[in] objp pointer to the object to be posted
+ *
+ * @iclass
+ */
+static inline void chFifoSendObjectI(objects_fifo_t *ofp,
+ void *objp) {
+ msg_t msg;
+
+ msg = chMBPostI(&ofp->mbx, (msg_t)objp);
+ chDbgAssert(msg == MSG_OK, "post failed");
+}
+
+/**
+ * @brief Posts an object.
+ * @note By design the object can be always immediately posted.
+ *
+ * @param[in] ofp pointer to a @p objects_fifo_t structure
+ * @param[in] objp pointer to the object to be posted
+ *
+ * @sclass
+ */
+static inline void chFifoSendObjectS(objects_fifo_t *ofp,
+ void *objp) {
+ msg_t msg;
+
+ msg = chMBPostTimeoutS(&ofp->mbx, (msg_t)objp, TIME_IMMEDIATE);
+ chDbgAssert(msg == MSG_OK, "post failed");
+}
+
+/**
+ * @brief Posts an object.
+ * @note By design the object can be always immediately posted.
+ *
+ * @param[in] ofp pointer to a @p objects_fifo_t structure
+ * @param[in] objp pointer to the object to be released
+ *
+ * @api
+ */
+static inline void chFifoSendObject(objects_fifo_t *ofp, void *objp) {
+
+ msg_t msg;
+
+ msg = chMBPostTimeout(&ofp->mbx, (msg_t)objp, TIME_IMMEDIATE);
+ chDbgAssert(msg == MSG_OK, "post failed");
+}
+
+/**
+ * @brief Posts an high priority object.
+ * @note By design the object can be always immediately posted.
+ *
+ * @param[in] ofp pointer to a @p objects_fifo_t structure
+ * @param[in] objp pointer to the object to be posted
+ *
+ * @iclass
+ */
+static inline void chFifoSendObjectAheadI(objects_fifo_t *ofp,
+ void *objp) {
+ msg_t msg;
+
+ msg = chMBPostAheadI(&ofp->mbx, (msg_t)objp);
+ chDbgAssert(msg == MSG_OK, "post failed");
+}
+
+/**
+ * @brief Posts an high priority object.
+ * @note By design the object can be always immediately posted.
+ *
+ * @param[in] ofp pointer to a @p objects_fifo_t structure
+ * @param[in] objp pointer to the object to be posted
+ *
+ * @sclass
+ */
+static inline void chFifoSendObjectAheadS(objects_fifo_t *ofp,
+ void *objp) {
+ msg_t msg;
+
+ msg = chMBPostAheadTimeoutS(&ofp->mbx, (msg_t)objp, TIME_IMMEDIATE);
+ chDbgAssert(msg == MSG_OK, "post failed");
+}
+
+/**
+ * @brief Posts an high priority object.
+ * @note By design the object can be always immediately posted.
+ *
+ * @param[in] ofp pointer to a @p objects_fifo_t structure
+ * @param[in] objp pointer to the object to be released
+ *
+ * @api
+ */
+static inline void chFifoSendObjectAhead(objects_fifo_t *ofp, void *objp) {
+
+ msg_t msg;
+
+ msg = chMBPostAheadTimeout(&ofp->mbx, (msg_t)objp, TIME_IMMEDIATE);
+ chDbgAssert(msg == MSG_OK, "post failed");
+}
+
+/**
+ * @brief Fetches an object.
+ *
+ * @param[in] ofp pointer to a @p objects_fifo_t structure
+ * @param[in] objpp pointer to the fetched object reference
+ * @return The operation status.
+ * @retval MSG_OK if an object has been correctly fetched.
+ * @retval MSG_TIMEOUT if the FIFO is empty and a message cannot be fetched.
+ *
+ * @iclass
+ */
+static inline msg_t chFifoReceiveObjectI(objects_fifo_t *ofp,
+ void **objpp) {
+
+ return chMBFetchI(&ofp->mbx, (msg_t *)objpp);
+}
+
+/**
+ * @brief Fetches an object.
+ *
+ * @param[in] ofp pointer to a @p objects_fifo_t structure
+ * @param[in] objpp pointer to the fetched object reference
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if an object has been correctly fetched.
+ * @retval MSG_TIMEOUT if the operation has timed out.
+ *
+ * @sclass
+ */
+static inline msg_t chFifoReceiveObjectTimeoutS(objects_fifo_t *ofp,
+ void **objpp,
+ sysinterval_t timeout) {
+
+ return chMBFetchTimeoutS(&ofp->mbx, (msg_t *)objpp, timeout);
+}
+
+/**
+ * @brief Fetches an object.
+ *
+ * @param[in] ofp pointer to a @p objects_fifo_t structure
+ * @param[in] objpp pointer to the fetched object reference
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if an object has been correctly fetched.
+ * @retval MSG_TIMEOUT if the operation has timed out.
+ *
+ * @api
+ */
+static inline msg_t chFifoReceiveObjectTimeout(objects_fifo_t *ofp,
+ void **objpp,
+ sysinterval_t timeout) {
+
+ return chMBFetchTimeout(&ofp->mbx, (msg_t *)objpp, timeout);
+}
+
+#endif /* CH_CFG_USE_OBJ_FIFOS == TRUE */
+
+#endif /* CHOBJFIFOS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/include/chpipes.h b/ChibiOS_20.3.2/os/oslib/include/chpipes.h
new file mode 100644
index 0000000..98576b6
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/include/chpipes.h
@@ -0,0 +1,208 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/include/chpipes.h
+ * @brief Pipes macros and structures.
+ *
+ * @addtogroup oslib_pipes
+ * @{
+ */
+
+#ifndef CHPIPES_H
+#define CHPIPES_H
+
+#if (CH_CFG_USE_PIPES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Structure representing a pipe object.
+ */
+typedef struct {
+ uint8_t *buffer; /**< @brief Pointer to the pipe
+ buffer. */
+ uint8_t *top; /**< @brief Pointer to the location
+ after the buffer. */
+ uint8_t *wrptr; /**< @brief Write pointer. */
+ uint8_t *rdptr; /**< @brief Read pointer. */
+ size_t cnt; /**< @brief Bytes in the pipe. */
+ bool reset; /**< @brief True if in reset state. */
+ thread_reference_t wtr; /**< @brief Waiting writer. */
+ thread_reference_t rtr; /**< @brief Waiting reader. */
+#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
+ mutex_t cmtx; /**< @brief Common access mutex. */
+ mutex_t wmtx; /**< @brief Write access mutex. */
+ mutex_t rmtx; /**< @brief Read access mutex. */
+#else
+ semaphore_t csem; /**< @brief Common access semaphore.*/
+ semaphore_t wsem; /**< @brief Write access semaphore. */
+ semaphore_t rsem; /**< @brief Read access semaphore. */
+#endif
+} pipe_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Data part of a static pipe initializer.
+ * @details This macro should be used when statically initializing a
+ * pipe that is part of a bigger structure.
+ *
+ * @param[in] name the name of the pipe variable
+ * @param[in] buffer pointer to the pipe buffer array of @p uint8_t
+ * @param[in] size number of @p uint8_t elements in the buffer array
+ */
+#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
+#define _PIPE_DATA(name, buffer, size) { \
+ (uint8_t *)(buffer), \
+ (uint8_t *)(buffer) + size, \
+ (uint8_t *)(buffer), \
+ (uint8_t *)(buffer), \
+ (size_t)0, \
+ false, \
+ NULL, \
+ NULL, \
+ _MUTEX_DATA(name.cmtx), \
+ _MUTEX_DATA(name.wmtx), \
+ _MUTEX_DATA(name.rmtx), \
+}
+#else /* CH_CFG_USE_MUTEXES == FALSE */
+#define _PIPE_DATA(name, buffer, size) { \
+ (uint8_t *)(buffer), \
+ (uint8_t *)(buffer) + size, \
+ (uint8_t *)(buffer), \
+ (uint8_t *)(buffer), \
+ (size_t)0, \
+ false, \
+ NULL, \
+ NULL, \
+ _SEMAPHORE_DATA(name.csem, (cnt_t)1), \
+ _SEMAPHORE_DATA(name.wsem, (cnt_t)1), \
+ _SEMAPHORE_DATA(name.rsem, (cnt_t)1), \
+}
+#endif /* CH_CFG_USE_MUTEXES == FALSE */
+
+/**
+ * @brief Static pipe initializer.
+ * @details Statically initialized pipes require no explicit
+ * initialization using @p chPipeObjectInit().
+ *
+ * @param[in] name the name of the pipe variable
+ * @param[in] buffer pointer to the pipe buffer array of @p uint8_t
+ * @param[in] size number of @p uint8_t elements in the buffer array
+ */
+#define PIPE_DECL(name, buffer, size) \
+ pipe_t name = _PIPE_DATA(name, buffer, size)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chPipeObjectInit(pipe_t *pp, uint8_t *buf, size_t n);
+ void chPipeReset(pipe_t *pp);
+ size_t chPipeWriteTimeout(pipe_t *pp, const uint8_t *bp,
+ size_t n, sysinterval_t timeout);
+ size_t chPipeReadTimeout(pipe_t *pp, uint8_t *bp,
+ size_t n, sysinterval_t timeout);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Returns the pipe buffer size as number of bytes.
+ *
+ * @param[in] pp the pointer to an initialized @p pipe_t object
+ * @return The size of the pipe.
+ *
+ * @api
+ */
+static inline size_t chPipeGetSize(const pipe_t *pp) {
+
+ /*lint -save -e9033 [10.8] Perfectly safe pointers
+ arithmetic.*/
+ return (size_t)(pp->top - pp->buffer);
+ /*lint -restore*/
+}
+
+/**
+ * @brief Returns the number of used byte slots into a pipe.
+ *
+ * @param[in] pp the pointer to an initialized @p pipe_t object
+ * @return The number of queued bytes.
+ *
+ * @api
+ */
+static inline size_t chPipeGetUsedCount(const pipe_t *pp) {
+
+ return pp->cnt;
+}
+
+/**
+ * @brief Returns the number of free byte slots into a pipe.
+ *
+ * @param[in] pp the pointer to an initialized @p pipe_t object
+ * @return The number of empty byte slots.
+ *
+ * @api
+ */
+static inline size_t chPipeGetFreeCount(const pipe_t *pp) {
+
+ return chPipeGetSize(pp) - chPipeGetUsedCount(pp);
+}
+
+/**
+ * @brief Terminates the reset state.
+ *
+ * @param[in] pp the pointer to an initialized @p pipe_t object
+ *
+ * @api
+ */
+static inline void chPipeResume(pipe_t *pp) {
+
+ pp->reset = false;
+}
+
+#endif /* CH_CFG_USE_PIPES == TRUE */
+
+#endif /* CHPIPES_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/oslib.mk b/ChibiOS_20.3.2/os/oslib/oslib.mk
new file mode 100644
index 0000000..c0b95a8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/oslib.mk
@@ -0,0 +1,57 @@
+# List of all the ChibiOS/LIB files, there is no need to remove the files
+# from this list, you can disable parts of the kernel by editing chlibconf.h.
+ifeq ($(USE_SMART_BUILD),yes)
+
+# Configuration files directory
+ifeq ($(CHCONFDIR),)
+ ifeq ($(CONFDIR),)
+ CHCONFDIR = .
+ else
+ CHCONFDIR := $(CONFDIR)
+ endif
+endif
+
+CHLIBCONF := $(strip $(shell cat $(CHCONFDIR)/chconf.h | egrep -e "\#define"))
+
+LIBSRC :=
+ifneq ($(findstring CH_CFG_USE_MAILBOXES TRUE,$(CHLIBCONF)),)
+LIBSRC += $(CHIBIOS)/os/oslib/src/chmboxes.c
+endif
+ifneq ($(findstring CH_CFG_USE_MEMCORE TRUE,$(CHLIBCONF)),)
+LIBSRC += $(CHIBIOS)/os/oslib/src/chmemcore.c
+endif
+ifneq ($(findstring CH_CFG_USE_HEAP TRUE,$(CHLIBCONF)),)
+LIBSRC += $(CHIBIOS)/os/oslib/src/chmemheaps.c
+endif
+ifneq ($(findstring CH_CFG_USE_MEMPOOLS TRUE,$(CHLIBCONF)),)
+LIBSRC += $(CHIBIOS)/os/oslib/src/chmempools.c
+endif
+ifneq ($(findstring CH_CFG_USE_PIPES TRUE,$(CHLIBCONF)),)
+LIBSRC += $(CHIBIOS)/os/oslib/src/chpipes.c
+endif
+ifneq ($(findstring CH_CFG_USE_OBJ_CACHES TRUE,$(CHLIBCONF)),)
+LIBSRC += $(CHIBIOS)/os/oslib/src/chobjcaches.c
+endif
+ifneq ($(findstring CH_CFG_USE_DELEGATES TRUE,$(CHLIBCONF)),)
+LIBSRC += $(CHIBIOS)/os/oslib/src/chdelegates.c
+endif
+ifneq ($(findstring CH_CFG_USE_FACTORY TRUE,$(CHLIBCONF)),)
+LIBSRC += $(CHIBIOS)/os/oslib/src/chfactory.c
+endif
+else
+LIBSRC := $(CHIBIOS)/os/oslib/src/chmboxes.c \
+ $(CHIBIOS)/os/oslib/src/chmemcore.c \
+ $(CHIBIOS)/os/oslib/src/chmemheaps.c \
+ $(CHIBIOS)/os/oslib/src/chmempools.c \
+ $(CHIBIOS)/os/oslib/src/chpipes.c \
+ $(CHIBIOS)/os/oslib/src/chobjcaches.c \
+ $(CHIBIOS)/os/oslib/src/chdelegates.c \
+ $(CHIBIOS)/os/oslib/src/chfactory.c
+endif
+
+# Required include directories
+LIBINC := $(CHIBIOS)/os/oslib/include
+
+# Shared variables
+ALLCSRC += $(LIBSRC)
+ALLINC += $(LIBINC)
diff --git a/ChibiOS_20.3.2/os/oslib/readme.txt b/ChibiOS_20.3.2/os/oslib/readme.txt
new file mode 100644
index 0000000..d2e0e72
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/readme.txt
@@ -0,0 +1,2 @@
+All the code contained under ./os/lib are high level RTOS extension modules
+compatible with both RT and NIL.
\ No newline at end of file
diff --git a/ChibiOS_20.3.2/os/oslib/src/chdelegates.c b/ChibiOS_20.3.2/os/oslib/src/chdelegates.c
new file mode 100644
index 0000000..d1c2453
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/src/chdelegates.c
@@ -0,0 +1,239 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/src/chdelegates.c
+ * @brief Delegate threads code.
+ * @details Delegate threads.
+ * Operation mode
+ * A delegate thread is a thread performing function calls triggered
+ * by other threads. This functionality is especially useful when
+ * encapsulating a library not designed for threading into a
+ * delegate thread. Other threads have access to the library without
+ * having to worry about mutual exclusion.
+ * @pre In order to use the pipes APIs the @p CH_CFG_USE_DELEGATES
+ * option must be enabled in @p chconf.h.
+ * @note Compatible with RT and NIL.
+ *
+ * @addtogroup oslib_delegates
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_DELEGATES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a structure representing a delegate call.
+ */
+typedef struct {
+ /**
+ * @brief The delegate veneer function.
+ */
+ delegate_veneer_t veneer;
+ /**
+ * @brief Pointer to the caller @p va_list object.
+ */
+ va_list *argsp;
+} call_message_t;
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/*lint -save -e586 [17.1] Required by design.*/
+
+/**
+ * @brief Veneer for functions with no parameters.
+ *
+ * @param[in] argsp the list of arguments
+ * @return The function return value.
+ */
+msg_t __ch_delegate_fn0(va_list *argsp) {
+ delegate_fn0_t fn0 = (delegate_fn0_t)va_arg(*argsp, delegate_fn0_t);
+ return fn0();
+}
+
+/**
+ * @brief Veneer for functions with one parameter.
+ *
+ * @param[in] argsp the list of arguments
+ * @return The function return value.
+ */
+msg_t __ch_delegate_fn1(va_list *argsp) {
+ delegate_fn1_t fn1 = (delegate_fn1_t)va_arg(*argsp, delegate_fn1_t);
+ msg_t p1 = (msg_t)va_arg(*argsp, msg_t);
+ return fn1(p1);
+}
+
+/**
+ * @brief Veneer for functions with two parameters.
+ *
+ * @param[in] argsp the list of arguments
+ * @return The function return value.
+ */
+msg_t __ch_delegate_fn2(va_list *argsp) {
+ delegate_fn2_t fn2 = (delegate_fn2_t)va_arg(*argsp, delegate_fn2_t);
+ msg_t p1 = (msg_t)va_arg(*argsp, msg_t);
+ msg_t p2 = (msg_t)va_arg(*argsp, msg_t);
+ return fn2(p1, p2);
+}
+
+/**
+ * @brief Veneer for functions with three parameters.
+ *
+ * @param[in] argsp the list of arguments
+ * @return The function return value.
+ */
+msg_t __ch_delegate_fn3(va_list *argsp) {
+ delegate_fn3_t fn3 = (delegate_fn3_t)va_arg(*argsp, delegate_fn3_t);
+ msg_t p1 = (msg_t)va_arg(*argsp, msg_t);
+ msg_t p2 = (msg_t)va_arg(*argsp, msg_t);
+ msg_t p3 = (msg_t)va_arg(*argsp, msg_t);
+ return fn3(p1, p2, p3);
+}
+
+/**
+ * @brief Veneer for functions with four parameters.
+ *
+ * @param[in] argsp the list of arguments
+ * @return The function return value.
+ */
+msg_t __ch_delegate_fn4(va_list *argsp) {
+ delegate_fn4_t fn4 = (delegate_fn4_t)va_arg(*argsp, delegate_fn4_t);
+ msg_t p1 = (msg_t)va_arg(*argsp, msg_t);
+ msg_t p2 = (msg_t)va_arg(*argsp, msg_t);
+ msg_t p3 = (msg_t)va_arg(*argsp, msg_t);
+ msg_t p4 = (msg_t)va_arg(*argsp, msg_t);
+ return fn4(p1, p2, p3, p4);
+}
+
+/**
+ * @brief Triggers a function call on a delegate thread.
+ * @note The thread must be executing @p chDelegateDispatchTimeout() in
+ * order to have the functions called.
+ *
+ * @param[in] tp pointer to the delegate thread
+ * @param[in] veneer pointer to the veneer function to be called
+ * @param[in] ... variable number of parameters
+ * @return The function return value casted to msg_t. It is
+ * garbage for functions returning @p void.
+ */
+msg_t chDelegateCallVeneer(thread_t *tp, delegate_veneer_t veneer, ...) {
+ va_list args;
+ call_message_t cm;
+ msg_t msg;
+
+ va_start(args, veneer);
+
+ /* Preparing the call message.*/
+ cm.veneer = veneer;
+ cm.argsp = &args;
+ (void)cm; /* Suppresses a lint warning.*/
+
+ /* Sending the message to the dispatcher thread, the return value is
+ contained in the returned message.*/
+ msg = chMsgSend(tp, (msg_t)&cm);
+
+ va_end(args);
+
+ return msg;
+}
+
+/*lint -restore*/
+
+/**
+ * @brief Call messages dispatching.
+ * @details The function awaits for an incoming call messages and calls the
+ * specified functions, then it returns. In case multiple threads
+ * are sending messages then the requests are served in priority
+ * order.
+ *
+ * @api
+ */
+void chDelegateDispatch(void) {
+ thread_t *tp;
+ const call_message_t *cmp;
+ msg_t ret;
+
+ tp = chMsgWait();
+ cmp = (const call_message_t *)chMsgGet(tp);
+ ret = cmp->veneer(cmp->argsp);
+
+ chMsgRelease(tp, ret);
+}
+
+/**
+ * @brief Call messages dispatching with timeout.
+ * @details The function awaits for an incoming call messages and calls the
+ * specified functions, then it returns. In case multiple threads
+ * are sending messages then the requests are served in priority
+ * order.
+ *
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The function outcome.
+ * @retval MSG_OK if a function has been called.
+ * @retval MSG_TIMEOUT if a timeout occurred.
+ *
+ * @api
+ */
+msg_t chDelegateDispatchTimeout(sysinterval_t timeout) {
+ thread_t *tp;
+ const call_message_t *cmp;
+ msg_t ret;
+
+ tp = chMsgWaitTimeout(timeout);
+ if (tp == NULL) {
+ return MSG_TIMEOUT;
+ }
+
+ cmp = (const call_message_t *)chMsgGet(tp);
+ ret = cmp->veneer(cmp->argsp);
+
+ chMsgRelease(tp, ret);
+
+ return MSG_OK;
+}
+
+#endif /* CH_CFG_USE_DELEGATES == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/src/chfactory.c b/ChibiOS_20.3.2/os/oslib/src/chfactory.c
new file mode 100644
index 0000000..aaad90b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/src/chfactory.c
@@ -0,0 +1,811 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/src/chfactory.c
+ * @brief ChibiOS objects factory and registry code.
+ *
+ * @addtogroup oslib_objects_factory
+ * @details The object factory is a subsystem that allows to:
+ * - Register static objects by name.
+ * - Dynamically create objects and assign them a name.
+ * - Retrieve existing objects by name.
+ * - Free objects by reference.
+ * .
+ * Allocated OS objects are handled using a reference counter, only
+ * when all references have been released then the object memory is
+ * freed in a pool.
+ * @pre This subsystem requires the @p CH_CFG_USE_MEMCORE and
+ * @p CH_CFG_USE_MEMPOOLS options to be set to @p TRUE. The
+ * option @p CH_CFG_USE_HEAP is also required if the support
+ * for variable length objects is enabled.
+ * @note Compatible with RT and NIL.
+ * @{
+ */
+
+#include
+
+#include "ch.h"
+
+#if (CH_CFG_USE_FACTORY == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*
+ * Defaults on the best synchronization mechanism available.
+ */
+#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
+#define F_LOCK() chMtxLock(&ch_factory.mtx)
+#define F_UNLOCK() chMtxUnlock(&ch_factory.mtx)
+#else
+#define F_LOCK() (void) chSemWait(&ch_factory.sem)
+#define F_UNLOCK() chSemSignal(&ch_factory.sem)
+#endif
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief Factory object static instance.
+ * @note It is a global object because it could be accessed through
+ * a specific debugger plugin.
+ */
+objects_factory_t ch_factory;
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+static inline void dyn_list_init(dyn_list_t *dlp) {
+
+ dlp->next = (dyn_element_t *)dlp;
+}
+
+static dyn_element_t *dyn_list_find(const char *name, dyn_list_t *dlp) {
+ dyn_element_t *p = dlp->next;
+
+ while (p != (dyn_element_t *)dlp) {
+ if (strncmp(p->name, name, CH_CFG_FACTORY_MAX_NAMES_LENGTH) == 0) {
+ return p;
+ }
+ p = p->next;
+ }
+
+ return NULL;
+}
+
+static dyn_element_t *dyn_list_unlink(dyn_element_t *element,
+ dyn_list_t *dlp) {
+ dyn_element_t *prev = (dyn_element_t *)dlp;
+
+ /* Scanning the list.*/
+ while (prev->next != (dyn_element_t *)dlp) {
+ if (prev->next == element) {
+ /* Found.*/
+ prev->next = element->next;
+ return element;
+ }
+
+ /* Next element in the list.*/
+ prev = prev->next;
+ }
+
+ return NULL;
+}
+
+#if CH_FACTORY_REQUIRES_HEAP || defined(__DOXYGEN__)
+static dyn_element_t *dyn_create_object_heap(const char *name,
+ dyn_list_t *dlp,
+ size_t size) {
+ dyn_element_t *dep;
+
+ chDbgCheck(name != NULL);
+
+ /* Checking if an object with this name has already been created.*/
+ dep = dyn_list_find(name, dlp);
+ if (dep != NULL) {
+ return NULL;
+ }
+
+ /* Allocating space for the new buffer object.*/
+ /*lint -save -e668 [] Lint is confused by the above chDbgCheck() and
+ incorrectly assumes that strncpy() could receive a NULL pointer.*/
+ dep = (dyn_element_t *)chHeapAlloc(NULL, size);
+ if (dep == NULL) {
+ return NULL;
+ }
+
+ /* Initializing object list element.*/
+ strncpy(dep->name, name, CH_CFG_FACTORY_MAX_NAMES_LENGTH);
+ /*lint -restore*/
+ dep->refs = (ucnt_t)1;
+ dep->next = dlp->next;
+
+ /* Updating factory list.*/
+ dlp->next = dep;
+
+ return dep;
+}
+
+static void dyn_release_object_heap(dyn_element_t *dep,
+ dyn_list_t *dlp) {
+
+ chDbgCheck(dep != NULL);
+ chDbgAssert(dep->refs > (ucnt_t)0, "invalid references number");
+
+ dep->refs--;
+ if (dep->refs == (ucnt_t)0) {
+ dep = dyn_list_unlink(dep, dlp);
+ chHeapFree((void *)dep);
+ }
+}
+#endif /* CH_FACTORY_REQUIRES_HEAP */
+
+#if CH_FACTORY_REQUIRES_POOLS || defined(__DOXYGEN__)
+static dyn_element_t *dyn_create_object_pool(const char *name,
+ dyn_list_t *dlp,
+ memory_pool_t *mp) {
+ dyn_element_t *dep;
+
+ chDbgCheck(name != NULL);
+
+ /* Checking if an object object with this name has already been created.*/
+ dep = dyn_list_find(name, dlp);
+ if (dep != NULL) {
+ return NULL;
+ }
+
+ /* Allocating space for the new object.*/
+ dep = (dyn_element_t *)chPoolAlloc(mp);
+ if (dep == NULL) {
+ return NULL;
+ }
+
+ /* Initializing object list element.*/
+ /*lint -save -e668 [] Lint is confused by the above chDbgCheck() and
+ incorrectly assumes that strncpy() could receive a NULL pointer.*/
+ strncpy(dep->name, name, CH_CFG_FACTORY_MAX_NAMES_LENGTH);
+ /*lint -restore*/
+ dep->refs = (ucnt_t)1;
+ dep->next = dlp->next;
+
+ /* Updating factory list.*/
+ dlp->next = (dyn_element_t *)dep;
+
+ return dep;
+}
+
+static void dyn_release_object_pool(dyn_element_t *dep,
+ dyn_list_t *dlp,
+ memory_pool_t *mp) {
+
+ chDbgCheck(dep != NULL);
+ chDbgAssert(dep->refs > (ucnt_t)0, "invalid references number");
+
+ dep->refs--;
+ if (dep->refs == (ucnt_t)0) {
+ dep = dyn_list_unlink(dep, dlp);
+ chPoolFree(mp, (void *)dep);
+ }
+}
+#endif /* CH_FACTORY_REQUIRES_POOLS */
+
+static dyn_element_t *dyn_find_object(const char *name, dyn_list_t *dlp) {
+ dyn_element_t *dep;
+
+ chDbgCheck(name != NULL);
+
+ /* Checking if an object with this name has already been created.*/
+ dep = dyn_list_find(name, dlp);
+ if (dep != NULL) {
+ /* Increasing references counter.*/
+ dep->refs++;
+ }
+
+ return dep;
+}
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes the objects factory.
+ *
+ * @init
+ */
+void _factory_init(void) {
+
+#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
+ chMtxObjectInit(&ch_factory.mtx);
+#else
+ chSemObjectInit(&ch_factory.sem, (cnt_t)1);
+#endif
+
+#if CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE
+ dyn_list_init(&ch_factory.obj_list);
+ chPoolObjectInit(&ch_factory.obj_pool,
+ sizeof (registered_object_t),
+ chCoreAllocAlignedI);
+#endif
+#if CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE
+ dyn_list_init(&ch_factory.buf_list);
+#endif
+#if CH_CFG_FACTORY_SEMAPHORES == TRUE
+ dyn_list_init(&ch_factory.sem_list);
+ chPoolObjectInit(&ch_factory.sem_pool,
+ sizeof (dyn_semaphore_t),
+ chCoreAllocAlignedI);
+#endif
+#if CH_CFG_FACTORY_MAILBOXES == TRUE
+ dyn_list_init(&ch_factory.mbx_list);
+#endif
+#if CH_CFG_FACTORY_OBJ_FIFOS == TRUE
+ dyn_list_init(&ch_factory.fifo_list);
+#endif
+#if CH_CFG_FACTORY_PIPES == TRUE
+ dyn_list_init(&ch_factory.pipe_list);
+#endif
+}
+
+#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXIGEN__)
+/**
+ * @brief Registers a generic object.
+ * @post A reference to the registered object is returned and the
+ * reference counter is initialized to one.
+ *
+ * @param[in] name name to be assigned to the registered object
+ * @param[in] objp pointer to the object to be registered
+ *
+ * @return The reference to the registered object.
+ * @retval NULL if the object to be registered cannot be allocated or
+ * a registered object with the same name exists.
+ *
+ * @api
+ */
+registered_object_t *chFactoryRegisterObject(const char *name,
+ void *objp) {
+ registered_object_t *rop;
+
+ F_LOCK();
+
+ rop = (registered_object_t *)dyn_create_object_pool(name,
+ &ch_factory.obj_list,
+ &ch_factory.obj_pool);
+ if (rop != NULL) {
+ /* Initializing registered object data.*/
+ rop->objp = objp;
+ }
+
+ F_UNLOCK();
+
+ return rop;
+}
+
+/**
+ * @brief Retrieves a registered object.
+ * @post A reference to the registered object is returned with the
+ * reference counter increased by one.
+ *
+ * @param[in] name name of the registered object
+ *
+ * @return The reference to the found registered object.
+ * @retval NULL if a registered object with the specified name
+ * does not exist.
+ *
+ * @api
+ */
+registered_object_t *chFactoryFindObject(const char *name) {
+ registered_object_t *rop;
+
+ F_LOCK();
+
+ rop = (registered_object_t *)dyn_find_object(name, &ch_factory.obj_list);
+
+ F_UNLOCK();
+
+ return rop;
+}
+
+/**
+ * @brief Retrieves a registered object by pointer.
+ * @post A reference to the registered object is returned with the
+ * reference counter increased by one.
+ *
+ * @param[in] objp pointer to the object to be retrieved
+ *
+ * @return The reference to the found registered object.
+ * @retval NULL if a registered object with the specified pointer
+ * does not exist.
+ *
+ * @api
+ */
+registered_object_t *chFactoryFindObjectByPointer(void *objp) {
+ registered_object_t *rop = (registered_object_t *)ch_factory.obj_list.next;
+
+ F_LOCK();
+
+ while ((void *)rop != (void *)&ch_factory.obj_list) {
+ if (rop->objp == objp) {
+ rop->element.refs++;
+
+ F_UNLOCK();
+
+ return rop;
+ }
+ rop = (registered_object_t *)rop->element.next;
+ }
+
+ F_UNLOCK();
+
+ return NULL;
+}
+
+/**
+ * @brief Releases a registered object.
+ * @details The reference counter of the registered object is decreased
+ * by one, if reaches zero then the registered object memory
+ * is freed.
+ * @note The object itself is not freed, it could be static, only the
+ * allocated list element is freed.
+ *
+ * @param[in] rop registered object reference
+ *
+ * @api
+ */
+void chFactoryReleaseObject(registered_object_t *rop) {
+
+ F_LOCK();
+
+ dyn_release_object_pool(&rop->element,
+ &ch_factory.obj_list,
+ &ch_factory.obj_pool);
+
+ F_UNLOCK();
+}
+#endif /* CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE */
+
+#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXIGEN__)
+/**
+ * @brief Creates a generic dynamic buffer object.
+ * @post A reference to the dynamic buffer object is returned and the
+ * reference counter is initialized to one.
+ * @post The dynamic buffer object is filled with zeros.
+ *
+ * @param[in] name name to be assigned to the new dynamic buffer object
+ * @param[in] size payload size of the dynamic buffer object to be created
+ *
+ * @return The reference to the created dynamic buffer object.
+ * @retval NULL if the dynamic buffer object cannot be allocated or
+ * a dynamic buffer object with the same name exists.
+ *
+ * @api
+ */
+dyn_buffer_t *chFactoryCreateBuffer(const char *name, size_t size) {
+ dyn_buffer_t *dbp;
+
+ F_LOCK();
+
+ dbp = (dyn_buffer_t *)dyn_create_object_heap(name,
+ &ch_factory.buf_list,
+ size);
+ if (dbp != NULL) {
+ /* Initializing buffer object data.*/
+ memset((void *)(dbp + 1), 0, size);
+ }
+
+ F_UNLOCK();
+
+ return dbp;
+}
+
+/**
+ * @brief Retrieves a dynamic buffer object.
+ * @post A reference to the dynamic buffer object is returned with the
+ * reference counter increased by one.
+ *
+ * @param[in] name name of the dynamic buffer object
+ *
+ * @return The reference to the found dynamic buffer object.
+ * @retval NULL if a dynamic buffer object with the specified name
+ * does not exist.
+ *
+ * @api
+ */
+dyn_buffer_t *chFactoryFindBuffer(const char *name) {
+ dyn_buffer_t *dbp;
+
+ F_LOCK();
+
+ dbp = (dyn_buffer_t *)dyn_find_object(name, &ch_factory.buf_list);
+
+ F_UNLOCK();
+
+ return dbp;
+}
+
+/**
+ * @brief Releases a dynamic buffer object.
+ * @details The reference counter of the dynamic buffer object is decreased
+ * by one, if reaches zero then the dynamic buffer object memory
+ * is freed.
+ *
+ * @param[in] dbp dynamic buffer object reference
+ *
+ * @api
+ */
+void chFactoryReleaseBuffer(dyn_buffer_t *dbp) {
+
+ F_LOCK();
+
+ dyn_release_object_heap(&dbp->element, &ch_factory.buf_list);
+
+ F_UNLOCK();
+}
+#endif /* CH_CFG_FACTORY_GENERIC_BUFFERS = TRUE */
+
+#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXIGEN__)
+/**
+ * @brief Creates a dynamic semaphore object.
+ * @post A reference to the dynamic semaphore object is returned and the
+ * reference counter is initialized to one.
+ * @post The dynamic semaphore object is initialized and ready to use.
+ *
+ * @param[in] name name to be assigned to the new dynamic semaphore object
+ * @param[in] n dynamic semaphore object counter initialization value
+ *
+ * @return The reference to the created dynamic semaphore object.
+ * @retval NULL if the dynamic semaphore object cannot be allocated or
+ * a dynamic semaphore with the same name exists.
+ *
+ * @api
+ */
+dyn_semaphore_t *chFactoryCreateSemaphore(const char *name, cnt_t n) {
+ dyn_semaphore_t *dsp;
+
+ F_LOCK();
+
+ dsp = (dyn_semaphore_t *)dyn_create_object_pool(name,
+ &ch_factory.sem_list,
+ &ch_factory.sem_pool);
+ if (dsp != NULL) {
+ /* Initializing semaphore object dataa.*/
+ chSemObjectInit(&dsp->sem, n);
+ }
+
+ F_UNLOCK();
+
+ return dsp;
+}
+
+/**
+ * @brief Retrieves a dynamic semaphore object.
+ * @post A reference to the dynamic semaphore object is returned with the
+ * reference counter increased by one.
+ *
+ * @param[in] name name of the dynamic semaphore object
+ *
+ * @return The reference to the found dynamic semaphore object.
+ * @retval NULL if a dynamic semaphore object with the specified name
+ * does not exist.
+ *
+ * @api
+ */
+dyn_semaphore_t *chFactoryFindSemaphore(const char *name) {
+ dyn_semaphore_t *dsp;
+
+ F_LOCK();
+
+ dsp = (dyn_semaphore_t *)dyn_find_object(name, &ch_factory.sem_list);
+
+ F_UNLOCK();
+
+ return dsp;
+}
+
+/**
+ * @brief Releases a dynamic semaphore object.
+ * @details The reference counter of the dynamic semaphore object is decreased
+ * by one, if reaches zero then the dynamic semaphore object memory
+ * is freed.
+ *
+ * @param[in] dsp dynamic semaphore object reference
+ *
+ * @api
+ */
+void chFactoryReleaseSemaphore(dyn_semaphore_t *dsp) {
+
+ F_LOCK();
+
+ dyn_release_object_pool(&dsp->element,
+ &ch_factory.sem_list,
+ &ch_factory.sem_pool);
+
+ F_UNLOCK();
+}
+#endif /* CH_CFG_FACTORY_SEMAPHORES = TRUE */
+
+#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXIGEN__)
+/**
+ * @brief Creates a dynamic mailbox object.
+ * @post A reference to the dynamic mailbox object is returned and the
+ * reference counter is initialized to one.
+ * @post The dynamic mailbox object is initialized and ready to use.
+ *
+ * @param[in] name name to be assigned to the new dynamic mailbox object
+ * @param[in] n mailbox buffer size as number of messages
+ *
+ * @return The reference to the created dynamic mailbox object.
+ * @retval NULL if the dynamic mailbox object cannot be allocated or
+ * a dynamic mailbox object with the same name exists.
+ *
+ * @api
+ */
+dyn_mailbox_t *chFactoryCreateMailbox(const char *name, size_t n) {
+ dyn_mailbox_t *dmp;
+
+ F_LOCK();
+
+ dmp = (dyn_mailbox_t *)dyn_create_object_heap(name,
+ &ch_factory.mbx_list,
+ sizeof (dyn_mailbox_t) +
+ (n * sizeof (msg_t)));
+ if (dmp != NULL) {
+ /* Initializing mailbox object data.*/
+ chMBObjectInit(&dmp->mbx, (msg_t *)(dmp + 1), n);
+ }
+
+ F_UNLOCK();
+
+ return dmp;
+}
+
+/**
+ * @brief Retrieves a dynamic mailbox object.
+ * @post A reference to the dynamic mailbox object is returned with the
+ * reference counter increased by one.
+ *
+ * @param[in] name name of the dynamic mailbox object
+ *
+ * @return The reference to the found dynamic mailbox object.
+ * @retval NULL if a dynamic mailbox object with the specified name
+ * does not exist.
+ *
+ * @api
+ */
+dyn_mailbox_t *chFactoryFindMailbox(const char *name) {
+ dyn_mailbox_t *dmp;
+
+ F_LOCK();
+
+ dmp = (dyn_mailbox_t *)dyn_find_object(name, &ch_factory.mbx_list);
+
+ F_UNLOCK();
+
+ return dmp;
+}
+
+/**
+ * @brief Releases a dynamic mailbox object.
+ * @details The reference counter of the dynamic mailbox object is decreased
+ * by one, if reaches zero then the dynamic mailbox object memory
+ * is freed.
+ *
+ * @param[in] dmp dynamic mailbox object reference
+ *
+ * @api
+ */
+void chFactoryReleaseMailbox(dyn_mailbox_t *dmp) {
+
+ F_LOCK();
+
+ dyn_release_object_heap(&dmp->element, &ch_factory.mbx_list);
+
+ F_UNLOCK();
+}
+#endif /* CH_CFG_FACTORY_MAILBOXES = TRUE */
+
+#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXIGEN__)
+/**
+ * @brief Creates a dynamic "objects FIFO" object.
+ * @post A reference to the dynamic "objects FIFO" object is returned and
+ * the reference counter is initialized to one.
+ * @post The dynamic "objects FIFO" object is initialized and ready to use.
+ *
+ * @param[in] name name to be assigned to the new dynamic "objects FIFO"
+ * object
+ * @param[in] objsize size of objects
+ * @param[in] objn number of objects available
+ * @param[in] objalign required objects alignment
+ * @return The reference to the created dynamic "objects FIFO"
+ * object.
+ * @retval NULL if the dynamic "objects FIFO" object cannot be
+ * allocated or a dynamic "objects FIFO" object with
+ * the same name exists.
+ *
+ * @api
+ */
+dyn_objects_fifo_t *chFactoryCreateObjectsFIFO(const char *name,
+ size_t objsize,
+ size_t objn,
+ unsigned objalign) {
+ dyn_objects_fifo_t *dofp;
+
+ F_LOCK();
+
+ dofp = (dyn_objects_fifo_t *)dyn_create_object_heap(name,
+ &ch_factory.fifo_list,
+ sizeof (dyn_objects_fifo_t) +
+ (objn * sizeof (msg_t)) +
+ (objn * objsize));
+ if (dofp != NULL) {
+ msg_t *msgbuf = (msg_t *)(dofp + 1);
+
+ /* Initializing mailbox object data.*/
+ chFifoObjectInitAligned(&dofp->fifo, objsize, objn, objalign,
+ (void *)&msgbuf[objn], msgbuf);
+ }
+
+ F_UNLOCK();
+
+ return dofp;
+}
+
+/**
+ * @brief Retrieves a dynamic "objects FIFO" object.
+ * @post A reference to the dynamic "objects FIFO" object is returned with
+ * the reference counter increased by one.
+ *
+ * @param[in] name name of the dynamic "objects FIFO" object
+ *
+ * @return The reference to the found dynamic "objects FIFO"
+ * object.
+ * @retval NULL if a dynamic "objects FIFO" object with the specified
+ * name does not exist.
+ *
+ * @api
+ */
+dyn_objects_fifo_t *chFactoryFindObjectsFIFO(const char *name) {
+ dyn_objects_fifo_t *dofp;
+
+ F_LOCK();
+
+ dofp = (dyn_objects_fifo_t *)dyn_find_object(name, &ch_factory.fifo_list);
+
+ F_UNLOCK();
+
+ return dofp;
+}
+
+/**
+ * @brief Releases a dynamic "objects FIFO" object.
+ * @details The reference counter of the dynamic "objects FIFO" object is
+ * decreased by one, if reaches zero then the dynamic "objects FIFO"
+ * object memory is freed.
+ *
+ * @param[in] dofp dynamic "objects FIFO" object reference
+ *
+ * @api
+ */
+void chFactoryReleaseObjectsFIFO(dyn_objects_fifo_t *dofp) {
+
+ F_LOCK();
+
+ dyn_release_object_heap(&dofp->element, &ch_factory.fifo_list);
+
+ F_UNLOCK();
+}
+#endif /* CH_CFG_FACTORY_OBJ_FIFOS = TRUE */
+
+#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXIGEN__)
+/**
+ * @brief Creates a dynamic pipe object.
+ * @post A reference to the dynamic pipe object is returned and
+ * the reference counter is initialized to one.
+ * @post The dynamic pipe object is initialized and ready to use.
+ *
+ * @param[in] name name to be assigned to the new dynamic pipe
+ * object
+ * @param[in] size pipe buffer size
+ * @return The reference to the created dynamic pipe
+ * object.
+ * @retval NULL if the dynamic pipe object cannot be
+ * allocated or a dynamic pipe object with
+ * the same name exists.
+ *
+ * @api
+ */
+dyn_pipe_t *chFactoryCreatePipe(const char *name, size_t size) {
+ dyn_pipe_t *dpp;
+
+ F_LOCK();
+
+ dpp = (dyn_pipe_t *)dyn_create_object_heap(name,
+ &ch_factory.pipe_list,
+ sizeof (dyn_pipe_t) + size);
+ if (dpp != NULL) {
+ /* Initializing mailbox object data.*/
+ chPipeObjectInit(&dpp->pipe, (uint8_t *)(dpp + 1), size);
+ }
+
+ F_UNLOCK();
+
+ return dpp;
+}
+
+/**
+ * @brief Retrieves a dynamic pipe object.
+ * @post A reference to the dynamic pipe object is returned with
+ * the reference counter increased by one.
+ *
+ * @param[in] name name of the pipe object
+ *
+ * @return The reference to the found dynamic pipe
+ * object.
+ * @retval NULL if a dynamic pipe object with the specified
+ * name does not exist.
+ *
+ * @api
+ */
+dyn_pipe_t *chFactoryFindPipe(const char *name) {
+ dyn_pipe_t *dpp;
+
+ F_LOCK();
+
+ dpp = (dyn_pipe_t *)dyn_find_object(name, &ch_factory.pipe_list);
+
+ F_UNLOCK();
+
+ return dpp;
+}
+
+/**
+ * @brief Releases a dynamic pipe object.
+ * @details The reference counter of the dynamic pipe object is
+ * decreased by one, if reaches zero then the dynamic pipe
+ * object memory is freed.
+ *
+ * @param[in] dpp dynamic pipe object reference
+ *
+ * @api
+ */
+void chFactoryReleasePipe(dyn_pipe_t *dpp) {
+
+ F_LOCK();
+
+ dyn_release_object_heap(&dpp->element, &ch_factory.pipe_list);
+
+ F_UNLOCK();
+}
+#endif /* CH_CFG_FACTORY_PIPES = TRUE */
+
+#endif /* CH_CFG_USE_FACTORY == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/src/chmboxes.c b/ChibiOS_20.3.2/os/oslib/src/chmboxes.c
new file mode 100644
index 0000000..a96c07d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/src/chmboxes.c
@@ -0,0 +1,522 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/src/chmboxes.c
+ * @brief Mailboxes code.
+ *
+ * @addtogroup oslib_mailboxes
+ * @details Asynchronous messages.
+ * Operation mode
+ * A mailbox is an asynchronous communication mechanism.
+ * Operations defined for mailboxes:
+ * - Post: Posts a message on the mailbox in FIFO order.
+ * - Post Ahead: Posts a message on the mailbox with urgent
+ * priority.
+ * - Fetch: A message is fetched from the mailbox and removed
+ * from the queue.
+ * - Reset: The mailbox is emptied and all the stored messages
+ * are lost.
+ * .
+ * A message is a variable of type msg_t that is guaranteed to have
+ * the same size of and be compatible with (data) pointers (anyway an
+ * explicit cast is needed).
+ * If larger messages need to be exchanged then a pointer to a
+ * structure can be posted in the mailbox but the posting side has
+ * no predefined way to know when the message has been processed. A
+ * possible approach is to allocate memory (from a memory pool for
+ * example) from the posting side and free it on the fetching side.
+ * Another approach is to set a "done" flag into the structure pointed
+ * by the message.
+ * @pre In order to use the mailboxes APIs the @p CH_CFG_USE_MAILBOXES
+ * option must be enabled in @p chconf.h.
+ * @note Compatible with RT and NIL.
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_MAILBOXES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes a @p mailbox_t object.
+ *
+ * @param[out] mbp the pointer to the @p mailbox_t structure to be
+ * initialized
+ * @param[in] buf pointer to the messages buffer as an array of @p msg_t
+ * @param[in] n number of elements in the buffer array
+ *
+ * @init
+ */
+void chMBObjectInit(mailbox_t *mbp, msg_t *buf, size_t n) {
+
+ chDbgCheck((mbp != NULL) && (buf != NULL) && (n > (size_t)0));
+
+ mbp->buffer = buf;
+ mbp->rdptr = buf;
+ mbp->wrptr = buf;
+ mbp->top = &buf[n];
+ mbp->cnt = (size_t)0;
+ mbp->reset = false;
+ chThdQueueObjectInit(&mbp->qw);
+ chThdQueueObjectInit(&mbp->qr);
+}
+
+/**
+ * @brief Resets a @p mailbox_t object.
+ * @details All the waiting threads are resumed with status @p MSG_RESET and
+ * the queued messages are lost.
+ * @post The mailbox is in reset state, all operations will fail and
+ * return @p MSG_RESET until the mailbox is enabled again using
+ * @p chMBResumeX().
+ *
+ * @param[in] mbp the pointer to an initialized @p mailbox_t object
+ *
+ * @api
+ */
+void chMBReset(mailbox_t *mbp) {
+
+ chSysLock();
+ chMBResetI(mbp);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+/**
+ * @brief Resets a @p mailbox_t object.
+ * @details All the waiting threads are resumed with status @p MSG_RESET and
+ * the queued messages are lost.
+ * @post The mailbox is in reset state, all operations will fail and
+ * return @p MSG_RESET until the mailbox is enabled again using
+ * @p chMBResumeX().
+ *
+ * @param[in] mbp the pointer to an initialized @p mailbox_t object
+ *
+ * @api
+ */
+void chMBResetI(mailbox_t *mbp) {
+
+ chDbgCheckClassI();
+ chDbgCheck(mbp != NULL);
+
+ mbp->wrptr = mbp->buffer;
+ mbp->rdptr = mbp->buffer;
+ mbp->cnt = (size_t)0;
+ mbp->reset = true;
+ chThdDequeueAllI(&mbp->qw, MSG_RESET);
+ chThdDequeueAllI(&mbp->qr, MSG_RESET);
+}
+
+/**
+ * @brief Posts a message into a mailbox.
+ * @details The invoking thread waits until a empty slot in the mailbox becomes
+ * available or the specified time runs out.
+ *
+ * @param[in] mbp the pointer to an initialized @p mailbox_t object
+ * @param[in] msg the message to be posted on the mailbox
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if a message has been correctly posted.
+ * @retval MSG_RESET if the mailbox has been reset.
+ * @retval MSG_TIMEOUT if the operation has timed out.
+ *
+ * @api
+ */
+msg_t chMBPostTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) {
+ msg_t rdymsg;
+
+ chSysLock();
+ rdymsg = chMBPostTimeoutS(mbp, msg, timeout);
+ chSysUnlock();
+
+ return rdymsg;
+}
+
+/**
+ * @brief Posts a message into a mailbox.
+ * @details The invoking thread waits until a empty slot in the mailbox becomes
+ * available or the specified time runs out.
+ *
+ * @param[in] mbp the pointer to an initialized @p mailbox_t object
+ * @param[in] msg the message to be posted on the mailbox
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if a message has been correctly posted.
+ * @retval MSG_RESET if the mailbox has been reset.
+ * @retval MSG_TIMEOUT if the operation has timed out.
+ *
+ * @sclass
+ */
+msg_t chMBPostTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) {
+ msg_t rdymsg;
+
+ chDbgCheckClassS();
+ chDbgCheck(mbp != NULL);
+
+ do {
+ /* If the mailbox is in reset state then returns immediately.*/
+ if (mbp->reset) {
+ return MSG_RESET;
+ }
+
+ /* Is there a free message slot in queue? if so then post.*/
+ if (chMBGetFreeCountI(mbp) > (size_t)0) {
+ *mbp->wrptr++ = msg;
+ if (mbp->wrptr >= mbp->top) {
+ mbp->wrptr = mbp->buffer;
+ }
+ mbp->cnt++;
+
+ /* If there is a reader waiting then makes it ready.*/
+ chThdDequeueNextI(&mbp->qr, MSG_OK);
+ chSchRescheduleS();
+
+ return MSG_OK;
+ }
+
+ /* No space in the queue, waiting for a slot to become available.*/
+ rdymsg = chThdEnqueueTimeoutS(&mbp->qw, timeout);
+ } while (rdymsg == MSG_OK);
+
+ return rdymsg;
+}
+
+/**
+ * @brief Posts a message into a mailbox.
+ * @details This variant is non-blocking, the function returns a timeout
+ * condition if the queue is full.
+ *
+ * @param[in] mbp the pointer to an initialized @p mailbox_t object
+ * @param[in] msg the message to be posted on the mailbox
+ * @return The operation status.
+ * @retval MSG_OK if a message has been correctly posted.
+ * @retval MSG_RESET if the mailbox has been reset.
+ * @retval MSG_TIMEOUT if the mailbox is full and the message cannot be
+ * posted.
+ *
+ * @iclass
+ */
+msg_t chMBPostI(mailbox_t *mbp, msg_t msg) {
+
+ chDbgCheckClassI();
+ chDbgCheck(mbp != NULL);
+
+ /* If the mailbox is in reset state then returns immediately.*/
+ if (mbp->reset) {
+ return MSG_RESET;
+ }
+
+ /* Is there a free message slot in queue? if so then post.*/
+ if (chMBGetFreeCountI(mbp) > (size_t)0) {
+ *mbp->wrptr++ = msg;
+ if (mbp->wrptr >= mbp->top) {
+ mbp->wrptr = mbp->buffer;
+ }
+ mbp->cnt++;
+
+ /* If there is a reader waiting then makes it ready.*/
+ chThdDequeueNextI(&mbp->qr, MSG_OK);
+
+ return MSG_OK;
+ }
+
+ /* No space, immediate timeout.*/
+ return MSG_TIMEOUT;
+}
+
+/**
+ * @brief Posts an high priority message into a mailbox.
+ * @details The invoking thread waits until a empty slot in the mailbox becomes
+ * available or the specified time runs out.
+ *
+ * @param[in] mbp the pointer to an initialized @p mailbox_t object
+ * @param[in] msg the message to be posted on the mailbox
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if a message has been correctly posted.
+ * @retval MSG_RESET if the mailbox has been reset.
+ * @retval MSG_TIMEOUT if the operation has timed out.
+ *
+ * @api
+ */
+msg_t chMBPostAheadTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) {
+ msg_t rdymsg;
+
+ chSysLock();
+ rdymsg = chMBPostAheadTimeoutS(mbp, msg, timeout);
+ chSysUnlock();
+
+ return rdymsg;
+}
+
+/**
+ * @brief Posts an high priority message into a mailbox.
+ * @details The invoking thread waits until a empty slot in the mailbox becomes
+ * available or the specified time runs out.
+ *
+ * @param[in] mbp the pointer to an initialized @p mailbox_t object
+ * @param[in] msg the message to be posted on the mailbox
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if a message has been correctly posted.
+ * @retval MSG_RESET if the mailbox has been reset.
+ * @retval MSG_TIMEOUT if the operation has timed out.
+ *
+ * @sclass
+ */
+msg_t chMBPostAheadTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) {
+ msg_t rdymsg;
+
+ chDbgCheckClassS();
+ chDbgCheck(mbp != NULL);
+
+ do {
+ /* If the mailbox is in reset state then returns immediately.*/
+ if (mbp->reset) {
+ return MSG_RESET;
+ }
+
+ /* Is there a free message slot in queue? if so then post.*/
+ if (chMBGetFreeCountI(mbp) > (size_t)0) {
+ if (--mbp->rdptr < mbp->buffer) {
+ mbp->rdptr = mbp->top - 1;
+ }
+ *mbp->rdptr = msg;
+ mbp->cnt++;
+
+ /* If there is a reader waiting then makes it ready.*/
+ chThdDequeueNextI(&mbp->qr, MSG_OK);
+ chSchRescheduleS();
+
+ return MSG_OK;
+ }
+
+ /* No space in the queue, waiting for a slot to become available.*/
+ rdymsg = chThdEnqueueTimeoutS(&mbp->qw, timeout);
+ } while (rdymsg == MSG_OK);
+
+ return rdymsg;
+}
+
+/**
+ * @brief Posts an high priority message into a mailbox.
+ * @details This variant is non-blocking, the function returns a timeout
+ * condition if the queue is full.
+ *
+ * @param[in] mbp the pointer to an initialized @p mailbox_t object
+ * @param[in] msg the message to be posted on the mailbox
+ * @return The operation status.
+ * @retval MSG_OK if a message has been correctly posted.
+ * @retval MSG_RESET if the mailbox has been reset.
+ * @retval MSG_TIMEOUT if the mailbox is full and the message cannot be
+ * posted.
+ *
+ * @iclass
+ */
+msg_t chMBPostAheadI(mailbox_t *mbp, msg_t msg) {
+
+ chDbgCheckClassI();
+ chDbgCheck(mbp != NULL);
+
+ /* If the mailbox is in reset state then returns immediately.*/
+ if (mbp->reset) {
+ return MSG_RESET;
+ }
+
+ /* Is there a free message slot in queue? if so then post.*/
+ if (chMBGetFreeCountI(mbp) > (size_t)0) {
+ if (--mbp->rdptr < mbp->buffer) {
+ mbp->rdptr = mbp->top - 1;
+ }
+ *mbp->rdptr = msg;
+ mbp->cnt++;
+
+ /* If there is a reader waiting then makes it ready.*/
+ chThdDequeueNextI(&mbp->qr, MSG_OK);
+
+ return MSG_OK;
+ }
+
+ /* No space, immediate timeout.*/
+ return MSG_TIMEOUT;
+}
+
+/**
+ * @brief Retrieves a message from a mailbox.
+ * @details The invoking thread waits until a message is posted in the mailbox
+ * or the specified time runs out.
+ *
+ * @param[in] mbp the pointer to an initialized @p mailbox_t object
+ * @param[out] msgp pointer to a message variable for the received message
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if a message has been correctly fetched.
+ * @retval MSG_RESET if the mailbox has been reset.
+ * @retval MSG_TIMEOUT if the operation has timed out.
+ *
+ * @api
+ */
+msg_t chMBFetchTimeout(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout) {
+ msg_t rdymsg;
+
+ chSysLock();
+ rdymsg = chMBFetchTimeoutS(mbp, msgp, timeout);
+ chSysUnlock();
+
+ return rdymsg;
+}
+
+/**
+ * @brief Retrieves a message from a mailbox.
+ * @details The invoking thread waits until a message is posted in the mailbox
+ * or the specified time runs out.
+ *
+ * @param[in] mbp the pointer to an initialized @p mailbox_t object
+ * @param[out] msgp pointer to a message variable for the received message
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if a message has been correctly fetched.
+ * @retval MSG_RESET if the mailbox has been reset.
+ * @retval MSG_TIMEOUT if the operation has timed out.
+ *
+ * @sclass
+ */
+msg_t chMBFetchTimeoutS(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout) {
+ msg_t rdymsg;
+
+ chDbgCheckClassS();
+ chDbgCheck((mbp != NULL) && (msgp != NULL));
+
+ do {
+ /* If the mailbox is in reset state then returns immediately.*/
+ if (mbp->reset) {
+ return MSG_RESET;
+ }
+
+ /* Is there a message in queue? if so then fetch.*/
+ if (chMBGetUsedCountI(mbp) > (size_t)0) {
+ *msgp = *mbp->rdptr++;
+ if (mbp->rdptr >= mbp->top) {
+ mbp->rdptr = mbp->buffer;
+ }
+ mbp->cnt--;
+
+ /* If there is a writer waiting then makes it ready.*/
+ chThdDequeueNextI(&mbp->qw, MSG_OK);
+ chSchRescheduleS();
+
+ return MSG_OK;
+ }
+
+ /* No message in the queue, waiting for a message to become available.*/
+ rdymsg = chThdEnqueueTimeoutS(&mbp->qr, timeout);
+ } while (rdymsg == MSG_OK);
+
+ return rdymsg;
+}
+
+/**
+ * @brief Retrieves a message from a mailbox.
+ * @details This variant is non-blocking, the function returns a timeout
+ * condition if the queue is empty.
+ *
+ * @param[in] mbp the pointer to an initialized @p mailbox_t object
+ * @param[out] msgp pointer to a message variable for the received message
+ * @return The operation status.
+ * @retval MSG_OK if a message has been correctly fetched.
+ * @retval MSG_RESET if the mailbox has been reset.
+ * @retval MSG_TIMEOUT if the mailbox is empty and a message cannot be
+ * fetched.
+ *
+ * @iclass
+ */
+msg_t chMBFetchI(mailbox_t *mbp, msg_t *msgp) {
+
+ chDbgCheckClassI();
+ chDbgCheck((mbp != NULL) && (msgp != NULL));
+
+ /* If the mailbox is in reset state then returns immediately.*/
+ if (mbp->reset) {
+ return MSG_RESET;
+ }
+
+ /* Is there a message in queue? if so then fetch.*/
+ if (chMBGetUsedCountI(mbp) > (size_t)0) {
+ *msgp = *mbp->rdptr++;
+ if (mbp->rdptr >= mbp->top) {
+ mbp->rdptr = mbp->buffer;
+ }
+ mbp->cnt--;
+
+ /* If there is a writer waiting then makes it ready.*/
+ chThdDequeueNextI(&mbp->qw, MSG_OK);
+
+ return MSG_OK;
+ }
+
+ /* No message, immediate timeout.*/
+ return MSG_TIMEOUT;
+}
+#endif /* CH_CFG_USE_MAILBOXES == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/src/chmemcore.c b/ChibiOS_20.3.2/os/oslib/src/chmemcore.c
new file mode 100644
index 0000000..3a61955
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/src/chmemcore.c
@@ -0,0 +1,227 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/src/chmemcore.c
+ * @brief Core memory manager code.
+ *
+ * @addtogroup oslib_memcore
+ * @details Core Memory Manager related APIs and services.
+ * Operation mode
+ * The core memory manager is a simplified allocator that only
+ * allows to allocate memory blocks without the possibility to
+ * free them.
+ * This allocator is meant as a memory blocks provider for the
+ * other allocators such as:
+ * - C-Runtime allocator (through a compiler specific adapter module).
+ * - Heap allocator (see @ref oslib_memheaps).
+ * - Memory pools allocator (see @ref oslib_mempools).
+ * .
+ * By having a centralized memory provider the various allocators
+ * can coexist and share the main memory.
+ * This allocator, alone, is also useful for very simple
+ * applications that just require a simple way to get memory
+ * blocks.
+ * @pre In order to use the core memory manager APIs the @p CH_CFG_USE_MEMCORE
+ * option must be enabled in @p chconf.h.
+ * @note Compatible with RT and NIL.
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_MEMCORE == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief Memory core descriptor.
+ */
+memcore_t ch_memcore;
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Low level memory manager initialization.
+ *
+ * @notapi
+ */
+void _core_init(void) {
+#if CH_CFG_MEMCORE_SIZE == 0
+ extern uint8_t __heap_base__[];
+ extern uint8_t __heap_end__[];
+
+ /*lint -save -e9033 [10.8] Required cast operations.*/
+ ch_memcore.basemem = __heap_base__;
+ ch_memcore.topmem = __heap_end__;
+ /*lint restore*/
+#else
+ static uint8_t static_heap[CH_CFG_MEMCORE_SIZE];
+
+ ch_memcore.basemem = &static_heap[0];
+ ch_memcore.topmem = &static_heap[CH_CFG_MEMCORE_SIZE];
+#endif
+}
+
+/**
+ * @brief Allocates a memory block starting from the lowest address upward.
+ * @details This function allocates a block of @p offset + @p size bytes. The
+ * returned pointer has @p offset bytes before its address and
+ * @p size bytes after.
+ *
+ * @param[in] size the size of the block to be allocated.
+ * @param[in] align desired memory alignment
+ * @param[in] offset aligned pointer offset
+ * @return A pointer to the allocated memory block.
+ * @retval NULL allocation failed, core memory exhausted.
+ *
+ * @iclass
+ */
+void *chCoreAllocFromBaseI(size_t size, unsigned align, size_t offset) {
+ uint8_t *p, *next;
+
+ chDbgCheckClassI();
+ chDbgCheck(MEM_IS_VALID_ALIGNMENT(align));
+
+ p = (uint8_t *)MEM_ALIGN_NEXT(ch_memcore.basemem + offset, align);
+ next = p + size;
+
+ /* Considering also the case where there is numeric overflow.*/
+ if ((next > ch_memcore.topmem) || (next < ch_memcore.basemem)) {
+ return NULL;
+ }
+
+ ch_memcore.basemem = next;
+
+ return p;
+}
+
+/**
+ * @brief Allocates a memory block starting from the top address downward.
+ * @details This function allocates a block of @p offset + @p size bytes. The
+ * returned pointer has @p offset bytes before its address and
+ * @p size bytes after.
+ *
+ * @param[in] size the size of the block to be allocated.
+ * @param[in] align desired memory alignment
+ * @param[in] offset aligned pointer offset
+ * @return A pointer to the allocated memory block.
+ * @retval NULL allocation failed, core memory exhausted.
+ *
+ * @iclass
+ */
+void *chCoreAllocFromTopI(size_t size, unsigned align, size_t offset) {
+ uint8_t *p, *prev;
+
+ chDbgCheckClassI();
+ chDbgCheck(MEM_IS_VALID_ALIGNMENT(align));
+
+ p = (uint8_t *)MEM_ALIGN_PREV(ch_memcore.topmem - size, align);
+ prev = p - offset;
+
+ /* Considering also the case where there is numeric overflow.*/
+ if ((prev < ch_memcore.basemem) || (prev > ch_memcore.topmem)) {
+ return NULL;
+ }
+
+ ch_memcore.topmem = prev;
+
+ return p;
+}
+
+/**
+ * @brief Allocates a memory block starting from the lowest address upward.
+ * @details This function allocates a block of @p offset + @p size bytes. The
+ * returned pointer has @p offset bytes before its address and
+ * @p size bytes after.
+ *
+ * @param[in] size the size of the block to be allocated.
+ * @param[in] align desired memory alignment
+ * @param[in] offset aligned pointer offset
+ * @return A pointer to the allocated memory block.
+ * @retval NULL allocation failed, core memory exhausted.
+ *
+ * @api
+ */
+void *chCoreAllocFromBase(size_t size, unsigned align, size_t offset) {
+ void *p;
+
+ chSysLock();
+ p = chCoreAllocFromBaseI(size, align, offset);
+ chSysUnlock();
+
+ return p;
+}
+
+/**
+ * @brief Allocates a memory block starting from the top address downward.
+ * @details This function allocates a block of @p offset + @p size bytes. The
+ * returned pointer has @p offset bytes before its address and
+ * @p size bytes after.
+ *
+ * @param[in] size the size of the block to be allocated.
+ * @param[in] align desired memory alignment
+ * @param[in] offset aligned pointer offset
+ * @return A pointer to the allocated memory block.
+ * @retval NULL allocation failed, core memory exhausted.
+ *
+ * @api
+ */
+void *chCoreAllocFromTop(size_t size, unsigned align, size_t offset) {
+ void *p;
+
+ chSysLock();
+ p = chCoreAllocFromTopI(size, align, offset);
+ chSysUnlock();
+
+ return p;
+}
+
+/**
+ * @brief Core memory status.
+ *
+ * @return The size, in bytes, of the free core memory.
+ *
+ * @xclass
+ */
+size_t chCoreGetStatusX(void) {
+
+ /*lint -save -e9033 [10.8] The cast is safe.*/
+ return (size_t)(ch_memcore.topmem - ch_memcore.basemem);
+ /*lint -restore*/
+}
+#endif /* CH_CFG_USE_MEMCORE == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/src/chmemheaps.c b/ChibiOS_20.3.2/os/oslib/src/chmemheaps.c
new file mode 100644
index 0000000..2e1f03d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/src/chmemheaps.c
@@ -0,0 +1,399 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/src/chmemheaps.c
+ * @brief Memory heaps code.
+ *
+ * @addtogroup oslib_memheaps
+ * @details Heap Allocator related APIs.
+ * Operation mode
+ * The heap allocator implements a first-fit strategy and its APIs
+ * are functionally equivalent to the usual @p malloc() and @p free()
+ * library functions. The main difference is that the OS heap APIs
+ * are guaranteed to be thread safe and there is the ability to
+ * return memory blocks aligned to arbitrary powers of two.
+ * @pre In order to use the heap APIs the @p CH_CFG_USE_HEAP option must
+ * be enabled in @p chconf.h.
+ * @note Compatible with RT and NIL.
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_HEAP == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*
+ * Defaults on the best synchronization mechanism available.
+ */
+#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
+#define H_LOCK(h) chMtxLock(&(h)->mtx)
+#define H_UNLOCK(h) chMtxUnlock(&(h)->mtx)
+#else
+#define H_LOCK(h) (void) chSemWait(&(h)->sem)
+#define H_UNLOCK(h) chSemSignal(&(h)->sem)
+#endif
+
+#define H_BLOCK(hp) ((hp) + 1U)
+
+#define H_LIMIT(hp) (H_BLOCK(hp) + H_PAGES(hp))
+
+#define H_NEXT(hp) ((hp)->free.next)
+
+#define H_PAGES(hp) ((hp)->free.pages)
+
+#define H_HEAP(hp) ((hp)->used.heap)
+
+#define H_SIZE(hp) ((hp)->used.size)
+
+/*
+ * Number of pages between two pointers in a MISRA-compatible way.
+ */
+#define NPAGES(p1, p2) \
+ /*lint -save -e9033 [10.8] The cast is safe.*/ \
+ ((size_t)((p1) - (p2))) \
+ /*lint -restore*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/**
+ * @brief Default heap descriptor.
+ */
+static memory_heap_t default_heap;
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes the default heap.
+ *
+ * @notapi
+ */
+void _heap_init(void) {
+
+ default_heap.provider = chCoreAllocAlignedWithOffset;
+ H_NEXT(&default_heap.header) = NULL;
+ H_PAGES(&default_heap.header) = 0;
+#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
+ chMtxObjectInit(&default_heap.mtx);
+#else
+ chSemObjectInit(&default_heap.sem, (cnt_t)1);
+#endif
+}
+
+/**
+ * @brief Initializes a memory heap from a static memory area.
+ * @note The heap buffer base and size are adjusted if the passed buffer
+ * is not aligned to @p CH_HEAP_ALIGNMENT. This mean that the
+ * effective heap size can be less than @p size.
+ *
+ * @param[out] heapp pointer to the memory heap descriptor to be initialized
+ * @param[in] buf heap buffer base
+ * @param[in] size heap size
+ *
+ * @init
+ */
+void chHeapObjectInit(memory_heap_t *heapp, void *buf, size_t size) {
+ heap_header_t *hp = (heap_header_t *)MEM_ALIGN_NEXT(buf, CH_HEAP_ALIGNMENT);
+
+ chDbgCheck((heapp != NULL) && (size > 0U));
+
+ /* Adjusting the size in case the initial block was not correctly
+ aligned.*/
+ /*lint -save -e9033 [10.8] Required cast operations.*/
+ size -= (size_t)((uint8_t *)hp - (uint8_t *)buf);
+ /*lint restore*/
+
+ /* Initializing the heap header.*/
+ heapp->provider = NULL;
+ H_NEXT(&heapp->header) = hp;
+ H_PAGES(&heapp->header) = 0;
+ H_NEXT(hp) = NULL;
+ H_PAGES(hp) = (size - sizeof (heap_header_t)) / CH_HEAP_ALIGNMENT;
+#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
+ chMtxObjectInit(&heapp->mtx);
+#else
+ chSemObjectInit(&heapp->sem, (cnt_t)1);
+#endif
+}
+
+/**
+ * @brief Allocates a block of memory from the heap by using the first-fit
+ * algorithm.
+ * @details The allocated block is guaranteed to be properly aligned to the
+ * specified alignment.
+ *
+ * @param[in] heapp pointer to a heap descriptor or @p NULL in order to
+ * access the default heap.
+ * @param[in] size the size of the block to be allocated. Note that the
+ * allocated block may be a bit bigger than the requested
+ * size for alignment and fragmentation reasons.
+ * @param[in] align desired memory alignment
+ * @return A pointer to the aligned allocated block.
+ * @retval NULL if the block cannot be allocated.
+ *
+ * @api
+ */
+void *chHeapAllocAligned(memory_heap_t *heapp, size_t size, unsigned align) {
+ heap_header_t *qp, *hp, *ahp;
+ size_t pages;
+
+ chDbgCheck((size > 0U) && MEM_IS_VALID_ALIGNMENT(align));
+
+ /* If an heap is not specified then the default system header is used.*/
+ if (heapp == NULL) {
+ heapp = &default_heap;
+ }
+
+ /* Minimum alignment is constrained by the heap header structure size.*/
+ if (align < CH_HEAP_ALIGNMENT) {
+ align = CH_HEAP_ALIGNMENT;
+ }
+
+ /* Size is converted in number of elementary allocation units.*/
+ pages = MEM_ALIGN_NEXT(size, CH_HEAP_ALIGNMENT) / CH_HEAP_ALIGNMENT;
+
+ /* Taking heap mutex/semaphore.*/
+ H_LOCK(heapp);
+
+ /* Start of the free blocks list.*/
+ qp = &heapp->header;
+ while (H_NEXT(qp) != NULL) {
+
+ /* Next free block.*/
+ hp = H_NEXT(qp);
+
+ /* Pointer aligned to the requested alignment.*/
+ ahp = (heap_header_t *)MEM_ALIGN_NEXT(H_BLOCK(hp), align) - 1U;
+
+ if ((ahp < H_LIMIT(hp)) && (pages <= NPAGES(H_LIMIT(hp), ahp + 1U))) {
+ /* The block is large enough to contain a correctly aligned area
+ of sufficient size.*/
+
+ if (ahp > hp) {
+ /* The block is not properly aligned, must split it.*/
+ size_t bpages;
+
+ bpages = NPAGES(H_LIMIT(hp), H_BLOCK(ahp));
+ H_PAGES(hp) = NPAGES(ahp, H_BLOCK(hp));
+ if (bpages > pages) {
+ /* The block is bigger than required, must split the excess.*/
+ heap_header_t *fp;
+
+ /* Creating the excess block.*/
+ fp = H_BLOCK(ahp) + pages;
+ H_PAGES(fp) = (bpages - pages) - 1U;
+
+ /* Linking the excess block.*/
+ H_NEXT(fp) = H_NEXT(hp);
+ H_NEXT(hp) = fp;
+ }
+
+ hp = ahp;
+ }
+ else {
+ /* The block is already properly aligned.*/
+
+ if (H_PAGES(hp) == pages) {
+ /* Exact size, getting the whole block.*/
+ H_NEXT(qp) = H_NEXT(hp);
+ }
+ else {
+ /* The block is bigger than required, must split the excess.*/
+ heap_header_t *fp;
+
+ fp = H_BLOCK(hp) + pages;
+ H_NEXT(fp) = H_NEXT(hp);
+ H_PAGES(fp) = NPAGES(H_LIMIT(hp), H_BLOCK(fp));
+ H_NEXT(qp) = fp;
+ }
+ }
+
+ /* Setting in the block owner heap and size.*/
+ H_SIZE(hp) = size;
+ H_HEAP(hp) = heapp;
+
+ /* Releasing heap mutex/semaphore.*/
+ H_UNLOCK(heapp);
+
+ /*lint -save -e9087 [11.3] Safe cast.*/
+ return (void *)H_BLOCK(hp);
+ /*lint -restore*/
+ }
+
+ /* Next in the free blocks list.*/
+ qp = hp;
+ }
+
+ /* Releasing heap mutex/semaphore.*/
+ H_UNLOCK(heapp);
+
+ /* More memory is required, tries to get it from the associated provider
+ else fails.*/
+ if (heapp->provider != NULL) {
+ ahp = heapp->provider(pages * CH_HEAP_ALIGNMENT,
+ align,
+ sizeof (heap_header_t));
+ if (ahp != NULL) {
+ hp = ahp - 1U;
+ H_HEAP(hp) = heapp;
+ H_SIZE(hp) = size;
+
+ /*lint -save -e9087 [11.3] Safe cast.*/
+ return (void *)ahp;
+ /*lint -restore*/
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * @brief Frees a previously allocated memory block.
+ *
+ * @param[in] p pointer to the memory block to be freed
+ *
+ * @api
+ */
+void chHeapFree(void *p) {
+ heap_header_t *qp, *hp;
+ memory_heap_t *heapp;
+
+ chDbgCheck((p != NULL) && MEM_IS_ALIGNED(p, CH_HEAP_ALIGNMENT));
+
+ /*lint -save -e9087 [11.3] Safe cast.*/
+ hp = (heap_header_t *)p - 1U;
+ /*lint -restore*/
+ heapp = H_HEAP(hp);
+ qp = &heapp->header;
+
+ /* Size is converted in number of elementary allocation units.*/
+ H_PAGES(hp) = MEM_ALIGN_NEXT(H_SIZE(hp),
+ CH_HEAP_ALIGNMENT) / CH_HEAP_ALIGNMENT;
+
+ /* Taking heap mutex/semaphore.*/
+ H_LOCK(heapp);
+
+ while (true) {
+ chDbgAssert((hp < qp) || (hp >= H_LIMIT(qp)), "within free block");
+
+ if (((qp == &heapp->header) || (hp > qp)) &&
+ ((H_NEXT(qp) == NULL) || (hp < H_NEXT(qp)))) {
+ /* Insertion after qp.*/
+ H_NEXT(hp) = H_NEXT(qp);
+ H_NEXT(qp) = hp;
+ /* Verifies if the newly inserted block should be merged.*/
+ if (H_LIMIT(hp) == H_NEXT(hp)) {
+ /* Merge with the next block.*/
+ H_PAGES(hp) += H_PAGES(H_NEXT(hp)) + 1U;
+ H_NEXT(hp) = H_NEXT(H_NEXT(hp));
+ }
+ if ((H_LIMIT(qp) == hp)) {
+ /* Merge with the previous block.*/
+ H_PAGES(qp) += H_PAGES(hp) + 1U;
+ H_NEXT(qp) = H_NEXT(hp);
+ }
+ break;
+ }
+ qp = H_NEXT(qp);
+ }
+
+ /* Releasing heap mutex/semaphore.*/
+ H_UNLOCK(heapp);
+
+ return;
+}
+
+/**
+ * @brief Reports the heap status.
+ * @note This function is meant to be used in the test suite, it should
+ * not be really useful for the application code.
+ *
+ * @param[in] heapp pointer to a heap descriptor or @p NULL in order to
+ * access the default heap.
+ * @param[in] totalp pointer to a variable that will receive the total
+ * fragmented free space or @p NULL
+ * @param[in] largestp pointer to a variable that will receive the largest
+ * free free block found space or @p NULL
+ * @return The number of fragments in the heap.
+ *
+ * @api
+ */
+size_t chHeapStatus(memory_heap_t *heapp, size_t *totalp, size_t *largestp) {
+ heap_header_t *qp;
+ size_t n, tpages, lpages;
+
+ if (heapp == NULL) {
+ heapp = &default_heap;
+ }
+
+ H_LOCK(heapp);
+ tpages = 0U;
+ lpages = 0U;
+ n = 0U;
+ qp = &heapp->header;
+ while (H_NEXT(qp) != NULL) {
+ size_t pages = H_PAGES(H_NEXT(qp));
+
+ /* Updating counters.*/
+ n++;
+ tpages += pages;
+ if (pages > lpages) {
+ lpages = pages;
+ }
+
+ qp = H_NEXT(qp);
+ }
+
+ /* Writing out fragmented free memory.*/
+ if (totalp != NULL) {
+ *totalp = tpages * CH_HEAP_ALIGNMENT;
+ }
+
+ /* Writing out unfragmented free memory.*/
+ if (largestp != NULL) {
+ *largestp = lpages * CH_HEAP_ALIGNMENT;
+ }
+ H_UNLOCK(heapp);
+
+ return n;
+}
+
+#endif /* CH_CFG_USE_HEAP == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/src/chmempools.c b/ChibiOS_20.3.2/os/oslib/src/chmempools.c
new file mode 100644
index 0000000..1144b0b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/src/chmempools.c
@@ -0,0 +1,336 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/src/chmempools.c
+ * @brief Memory Pools code.
+ *
+ * @addtogroup oslib_mempools
+ * @details Memory Pools related APIs and services.
+ * Operation mode
+ * The Memory Pools APIs allow to allocate/free fixed size objects in
+ * constant time and reliably without memory fragmentation
+ * problems.
+ * Memory Pools do not enforce any alignment constraint on the
+ * contained object however the objects must be properly aligned
+ * to contain a pointer to void.
+ * @pre In order to use the memory pools APIs the @p CH_CFG_USE_MEMPOOLS option
+ * must be enabled in @p chconf.h.
+ * @note Compatible with RT and NIL.
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_MEMPOOLS == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes an empty memory pool.
+ *
+ * @param[out] mp pointer to a @p memory_pool_t structure
+ * @param[in] size the size of the objects contained in this memory pool,
+ * the minimum accepted size is the size of a pointer to
+ * void.
+ * @param[in] align required memory alignment
+ * @param[in] provider memory provider function for the memory pool or
+ * @p NULL if the pool is not allowed to grow
+ * automatically
+ *
+ * @init
+ */
+void chPoolObjectInitAligned(memory_pool_t *mp, size_t size,
+ unsigned align, memgetfunc_t provider) {
+
+ chDbgCheck((mp != NULL) &&
+ (size >= sizeof(void *)) &&
+ (align >= PORT_NATURAL_ALIGN) &&
+ MEM_IS_VALID_ALIGNMENT(align));
+
+ mp->next = NULL;
+ mp->object_size = size;
+ mp->align = align;
+ mp->provider = provider;
+}
+
+/**
+ * @brief Loads a memory pool with an array of static objects.
+ * @pre The memory pool must already be initialized.
+ * @pre The array elements must be of the right size for the specified
+ * memory pool.
+ * @pre The array elements size must be a multiple of the alignment
+ * requirement for the pool.
+ * @post The memory pool contains the elements of the input array.
+ *
+ * @param[in] mp pointer to a @p memory_pool_t structure
+ * @param[in] p pointer to the array first element
+ * @param[in] n number of elements in the array
+ *
+ * @api
+ */
+void chPoolLoadArray(memory_pool_t *mp, void *p, size_t n) {
+
+ chDbgCheck((mp != NULL) && (n != 0U));
+
+ while (n != 0U) {
+ chPoolAdd(mp, p);
+ /*lint -save -e9087 [11.3] Safe cast.*/
+ p = (void *)(((uint8_t *)p) + mp->object_size);
+ /*lint -restore*/
+ n--;
+ }
+}
+
+/**
+ * @brief Allocates an object from a memory pool.
+ * @pre The memory pool must already be initialized.
+ *
+ * @param[in] mp pointer to a @p memory_pool_t structure
+ * @return The pointer to the allocated object.
+ * @retval NULL if pool is empty.
+ *
+ * @iclass
+ */
+void *chPoolAllocI(memory_pool_t *mp) {
+ void *objp;
+
+ chDbgCheckClassI();
+ chDbgCheck(mp != NULL);
+
+ objp = mp->next;
+ /*lint -save -e9013 [15.7] There is no else because it is not needed.*/
+ if (objp != NULL) {
+ mp->next = mp->next->next;
+ }
+ else if (mp->provider != NULL) {
+ objp = mp->provider(mp->object_size, mp->align);
+
+ chDbgAssert(MEM_IS_ALIGNED(objp, mp->align),
+ "returned object not aligned");
+ }
+ /*lint -restore*/
+
+ return objp;
+}
+
+/**
+ * @brief Allocates an object from a memory pool.
+ * @pre The memory pool must already be initialized.
+ *
+ * @param[in] mp pointer to a @p memory_pool_t structure
+ * @return The pointer to the allocated object.
+ * @retval NULL if pool is empty.
+ *
+ * @api
+ */
+void *chPoolAlloc(memory_pool_t *mp) {
+ void *objp;
+
+ chSysLock();
+ objp = chPoolAllocI(mp);
+ chSysUnlock();
+
+ return objp;
+}
+
+/**
+ * @brief Releases an object into a memory pool.
+ * @pre The memory pool must already be initialized.
+ * @pre The freed object must be of the right size for the specified
+ * memory pool.
+ * @pre The added object must be properly aligned.
+ *
+ * @param[in] mp pointer to a @p memory_pool_t structure
+ * @param[in] objp the pointer to the object to be released
+ *
+ * @iclass
+ */
+void chPoolFreeI(memory_pool_t *mp, void *objp) {
+ struct pool_header *php = objp;
+
+ chDbgCheckClassI();
+ chDbgCheck((mp != NULL) &&
+ (objp != NULL) &&
+ MEM_IS_ALIGNED(objp, mp->align));
+
+ php->next = mp->next;
+ mp->next = php;
+}
+
+/**
+ * @brief Releases an object into a memory pool.
+ * @pre The memory pool must already be initialized.
+ * @pre The freed object must be of the right size for the specified
+ * memory pool.
+ * @pre The added object must be properly aligned.
+ *
+ * @param[in] mp pointer to a @p memory_pool_t structure
+ * @param[in] objp the pointer to the object to be released
+ *
+ * @api
+ */
+void chPoolFree(memory_pool_t *mp, void *objp) {
+
+ chSysLock();
+ chPoolFreeI(mp, objp);
+ chSysUnlock();
+}
+
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Initializes an empty guarded memory pool.
+ *
+ * @param[out] gmp pointer to a @p guarded_memory_pool_t structure
+ * @param[in] size the size of the objects contained in this guarded
+ * memory pool, the minimum accepted size is the size
+ * of a pointer to void.
+ * @param[in] align required memory alignment
+ *
+ * @init
+ */
+void chGuardedPoolObjectInitAligned(guarded_memory_pool_t *gmp,
+ size_t size,
+ unsigned align) {
+
+ chPoolObjectInitAligned(&gmp->pool, size, align, NULL);
+ chSemObjectInit(&gmp->sem, (cnt_t)0);
+}
+
+/**
+ * @brief Loads a guarded memory pool with an array of static objects.
+ * @pre The guarded memory pool must already be initialized.
+ * @pre The array elements must be of the right size for the specified
+ * guarded memory pool.
+ * @post The guarded memory pool contains the elements of the input array.
+ *
+ * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
+ * @param[in] p pointer to the array first element
+ * @param[in] n number of elements in the array
+ *
+ * @api
+ */
+void chGuardedPoolLoadArray(guarded_memory_pool_t *gmp, void *p, size_t n) {
+
+ chDbgCheck((gmp != NULL) && (n != 0U));
+
+ while (n != 0U) {
+ chGuardedPoolAdd(gmp, p);
+ /*lint -save -e9087 [11.3] Safe cast.*/
+ p = (void *)(((uint8_t *)p) + gmp->pool.object_size);
+ /*lint -restore*/
+ n--;
+ }
+}
+
+/**
+ * @brief Allocates an object from a guarded memory pool.
+ * @pre The guarded memory pool must already be initialized.
+ *
+ * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The pointer to the allocated object.
+ * @retval NULL if the operation timed out.
+ *
+ * @sclass
+ */
+void *chGuardedPoolAllocTimeoutS(guarded_memory_pool_t *gmp,
+ sysinterval_t timeout) {
+ msg_t msg;
+
+ msg = chSemWaitTimeoutS(&gmp->sem, timeout);
+ if (msg != MSG_OK) {
+ return NULL;
+ }
+
+ return chPoolAllocI(&gmp->pool);
+}
+
+/**
+ * @brief Allocates an object from a guarded memory pool.
+ * @pre The guarded memory pool must already be initialized.
+ *
+ * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The pointer to the allocated object.
+ * @retval NULL if the operation timed out.
+ *
+ * @api
+ */
+void *chGuardedPoolAllocTimeout(guarded_memory_pool_t *gmp,
+ sysinterval_t timeout) {
+ void *p;
+
+ chSysLock();
+ p = chGuardedPoolAllocTimeoutS(gmp, timeout);
+ chSysUnlock();
+
+ return p;
+}
+
+/**
+ * @brief Releases an object into a guarded memory pool.
+ * @pre The guarded memory pool must already be initialized.
+ * @pre The freed object must be of the right size for the specified
+ * guarded memory pool.
+ * @pre The added object must be properly aligned.
+ *
+ * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
+ * @param[in] objp the pointer to the object to be released
+ *
+ * @api
+ */
+void chGuardedPoolFree(guarded_memory_pool_t *gmp, void *objp) {
+
+ chSysLock();
+ chGuardedPoolFreeI(gmp, objp);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+#endif
+
+#endif /* CH_CFG_USE_MEMPOOLS == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/src/chobjcaches.c b/ChibiOS_20.3.2/os/oslib/src/chobjcaches.c
new file mode 100644
index 0000000..d08421b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/src/chobjcaches.c
@@ -0,0 +1,491 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/src/chobjcaches.c
+ * @brief Objects Caches code.
+ * @details Objects caches.
+ * Operation mode
+ * An object cache allows to retrieve and release objects from a
+ * slow media, for example a disk or flash.
+ * The most recently used objects are kept in a series of RAM
+ * buffers making access faster. Objects are identified by a
+ * pair which could be mapped, for example, to a
+ * disk drive identifier and sector identifier.
+ * Read and write operations are performed using externally-supplied
+ * functions, the cache is device-agnostic.
+ * The cache uses internally an hash table, the size of the table
+ * should be dimensioned to minimize the risk of hash collisions,
+ * a factor of two is usually acceptable, it depends on the specific
+ * application requirements.
+ * Operations defined for caches:
+ * - Get Object: Retrieves an object from cache, if not
+ * present then an empty buffer is returned.
+ * - Read Object: Retrieves an object from cache, if not
+ * present a buffer is allocated and the object is read from the
+ * media.
+ * - Release Object: Releases an object to the cache handling
+ * the media update, if required.
+ * .
+ * @pre In order to use the pipes APIs the @p CH_CFG_USE_OBJ_CACHES
+ * option must be enabled in @p chconf.h.
+ * @note Compatible with RT and NIL.
+ *
+ * @addtogroup oslib_objchaches
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_OBJ_CACHES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/* Default hash function.*/
+#if !defined(OC_HASH_FUNCTION) || defined(__DOXYGEN__)
+#define OC_HASH_FUNCTION(ocp, group, key) \
+ (((unsigned)(group) + (unsigned)(key)) & ((unsigned)(ocp)->hashn - 1U))
+#endif
+
+/* Insertion into an hash slot list.*/
+#define HASH_INSERT(ocp, objp, group, key) { \
+ oc_hash_header_t *hhp; \
+ (hhp) = &(ocp)->hashp[OC_HASH_FUNCTION(ocp, group, key)]; \
+ (objp)->hash_next = (hhp)->hash_next; \
+ (objp)->hash_prev = (oc_object_t *)(hhp); \
+ (hhp)->hash_next->hash_prev = (objp); \
+ (hhp)->hash_next = (objp); \
+}
+
+/* Removal of an object from the hash.*/
+#define HASH_REMOVE(objp) { \
+ (objp)->hash_prev->hash_next = (objp)->hash_next; \
+ (objp)->hash_next->hash_prev = (objp)->hash_prev; \
+}
+
+/* Insertion on LRU list head (newer objects).*/
+#define LRU_INSERT_HEAD(ocp, objp) { \
+ (objp)->lru_next = (ocp)->lru.lru_next; \
+ (objp)->lru_prev = (oc_object_t *)&(ocp)->lru; \
+ (ocp)->lru.lru_next->lru_prev = (objp); \
+ (ocp)->lru.lru_next = (objp); \
+}
+
+/* Insertion on LRU list head (newer objects).*/
+#define LRU_INSERT_TAIL(ocp, objp) { \
+ (objp)->lru_prev = (ocp)->lru.lru_prev; \
+ (objp)->lru_next = (oc_object_t *)&(ocp)->lru; \
+ (ocp)->lru.lru_prev->lru_next = (objp); \
+ (ocp)->lru.lru_prev = (objp); \
+}
+
+/* Removal of an object from the LRU list.*/
+#define LRU_REMOVE(objp) { \
+ (objp)->lru_prev->lru_next = (objp)->lru_next; \
+ (objp)->lru_next->lru_prev = (objp)->lru_prev; \
+}
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Returns an object pointer from the cache, if present.
+ *
+ * @param[out] ocp pointer to the @p objects_cache_t structure to be
+ * @param[in] group object group identifier
+ * @param[in] key object identifier within the group
+ * initialized
+ * @return The pointer to the retrieved object.
+ * @retval NULL if the object is not in cache.
+ *
+ * @notapi
+ */
+static oc_object_t *hash_get_s(objects_cache_t *ocp,
+ uint32_t group,
+ uint32_t key) {
+ oc_hash_header_t *hhp;
+ oc_object_t *objp;
+
+ /* Hash slot where to search for an hit.*/
+ hhp = &ocp->hashp[OC_HASH_FUNCTION(ocp, group, key)];
+ objp = hhp->hash_next;
+
+ /* Scanning the siblings collision list.*/
+ while (objp != (oc_object_t *)hhp) {
+ if ((objp->obj_key == key) && (objp->obj_group == group)) {
+
+ /* Cache hit.*/
+ return objp;
+ }
+ objp = objp->hash_next;
+ }
+
+ return NULL;
+}
+
+/**
+ * @brief Gets the least recently used object buffer from the LRU list.
+ *
+ * @param[out] ocp pointer to the @p objects_cache_t structure to be
+ * @return The pointer to the retrieved object.
+ *
+ * @notapi
+ */
+static oc_object_t *lru_get_last_s(objects_cache_t *ocp) {
+ oc_object_t *objp;
+
+ while (true) {
+ /* Waiting for an object buffer to become available in the LRU.*/
+ (void) chSemWaitS(&ocp->lru_sem);
+
+ /* Now an object buffer is in the LRU for sure, taking it from the
+ LRU tail.*/
+ objp = ocp->lru.lru_prev;
+
+ chDbgAssert((objp->obj_flags & OC_FLAG_INLRU) == OC_FLAG_INLRU,
+ "not in LRU");
+ chDbgAssert(chSemGetCounterI(&objp->obj_sem) == (cnt_t)1,
+ "semaphore counter not 1");
+
+ LRU_REMOVE(objp);
+ objp->obj_flags &= ~OC_FLAG_INLRU;
+
+ /* Getting the object semaphore, we know there is no wait so
+ using the "fast" variant.*/
+ chSemFastWaitI(&objp->obj_sem);
+
+ /* If it is a buffer not needing (lazy) write then it can be used
+ right away.*/
+ if ((objp->obj_flags & OC_FLAG_LAZYWRITE) == 0U) {
+
+ /* Removing from hash table if required.*/
+ if ((objp->obj_flags & OC_FLAG_INHASH) != 0U) {
+ HASH_REMOVE(objp);
+ }
+
+ /* Removing all flags, it is "new" now.*/
+ objp->obj_flags = 0U;
+
+ return objp;
+ }
+
+
+ /* Out of critical section.*/
+ chSysUnlock();
+
+ /* Invoking the writer asynchronously, it will release the buffer once it
+ is written. It is responsibility of the write function to release
+ the buffer.*/
+ objp->obj_flags = OC_FLAG_INHASH | OC_FLAG_FORGET;
+ (void) ocp->writef(ocp, objp, true);
+
+ /* Critical section enter again.*/
+ chSysLock();
+ }
+}
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes a @p objects_cache_t object.
+ *
+ * @param[out] ocp pointer to the @p objects_cache_t structure to be
+ * initialized
+ * @param[in] hashn number of elements in the hash table array, must be
+ * a power of two and not lower than @p objn
+ * @param[in] hashp pointer to the hash table as an array of
+ * @p oc_hash_header_t
+ * @param[in] objn number of elements in the objects table array
+ * @param[in] objsz size of elements in the objects table array, the
+ * minimum value is sizeof (oc_object_t).
+ * @param[in] objvp pointer to the hash objects as an array of structures
+ * starting with an @p oc_object_t
+ * @param[in] readf pointer to an object reader function
+ * @param[in] writef pointer to an object writer function
+ *
+ * @init
+ */
+void chCacheObjectInit(objects_cache_t *ocp,
+ ucnt_t hashn,
+ oc_hash_header_t *hashp,
+ ucnt_t objn,
+ size_t objsz,
+ void *objvp,
+ oc_readf_t readf,
+ oc_writef_t writef) {
+
+ chDbgCheck((ocp != NULL) && (hashp != NULL) && (objvp != NULL) &&
+ ((hashn & (hashn - (ucnt_t)1)) == (ucnt_t)0) &&
+ (objn > (ucnt_t)0) && (hashn >= objn) &&
+ (objsz >= sizeof (oc_object_t)) &&
+ ((objsz & (PORT_NATURAL_ALIGN - 1U)) == 0U));
+
+ chSemObjectInit(&ocp->cache_sem, (cnt_t)1);
+ chSemObjectInit(&ocp->lru_sem, (cnt_t)objn);
+ ocp->hashn = hashn;
+ ocp->hashp = hashp;
+ ocp->objn = objn;
+ ocp->objvp = objvp;
+ ocp->readf = readf;
+ ocp->writef = writef;
+ ocp->lru.hash_next = NULL;
+ ocp->lru.hash_prev = NULL;
+ ocp->lru.lru_next = (oc_object_t *)&ocp->lru;
+ ocp->lru.lru_prev = (oc_object_t *)&ocp->lru;
+
+ /* Hash headers initialization.*/
+ do {
+ hashp->hash_next = (oc_object_t *)hashp;
+ hashp->hash_prev = (oc_object_t *)hashp;
+ hashp++;
+ } while (hashp < &ocp->hashp[ocp->hashn]);
+
+ /* Object headers initialization.*/
+ do {
+ oc_object_t *objp = (oc_object_t *)objvp;
+
+ chSemObjectInit(&objp->obj_sem, (cnt_t)1);
+ LRU_INSERT_HEAD(ocp, objp);
+ objp->obj_group = 0U;
+ objp->obj_key = 0U;
+ objp->obj_flags = OC_FLAG_INLRU;
+ objp->dptr = NULL;
+ objvp = (void *)((uint8_t *)objvp + objsz);
+ objn--;
+ } while (objn > (ucnt_t)0);
+}
+
+/**
+ * @brief Retrieves an object from the cache.
+ * @note If the object is not in cache then the returned object is marked
+ * as @p OC_FLAG_NOTSYNC meaning that its data contains garbage and
+ * must be initialized.
+ *
+ * @param[in] ocp pointer to the @p objects_cache_t structure
+ * @param[in] group object group identifier
+ * @param[in] key object identifier within the group
+ * @return The pointer to the retrieved object.
+ *
+ * @api
+ */
+oc_object_t *chCacheGetObject(objects_cache_t *ocp,
+ uint32_t group,
+ uint32_t key) {
+ oc_object_t *objp;
+
+ /* Critical section enter, the hash check operation is fast.*/
+ chSysLock();
+
+ /* Checking the cache for a hit.*/
+ objp = hash_get_s(ocp, group, key);
+ if (objp != NULL) {
+
+ chDbgAssert((objp->obj_flags & OC_FLAG_INHASH) == OC_FLAG_INHASH,
+ "not in hash");
+
+ /* Cache hit, checking if the buffer is owned by some
+ other thread.*/
+ if (chSemGetCounterI(&objp->obj_sem) > (cnt_t)0) {
+ /* Not owned case, it is in the LRU list.*/
+
+ chDbgAssert((objp->obj_flags & OC_FLAG_INLRU) == OC_FLAG_INLRU,
+ "not in LRU");
+
+ /* Removing the object from LRU, now it is "owned".*/
+ LRU_REMOVE(objp);
+ objp->obj_flags &= ~OC_FLAG_INLRU;
+
+ /* Getting the object semaphore, we know there is no wait so
+ using the "fast" variant.*/
+ chSemFastWaitI(&objp->obj_sem);
+ }
+ else {
+ /* Owned case, some other thread is playing with this object, we
+ need to wait.*/
+
+ chDbgAssert((objp->obj_flags & OC_FLAG_INLRU) == 0U, "in LRU");
+
+ /* Waiting on the buffer semaphore.*/
+ (void) chSemWaitS(&objp->obj_sem);
+ }
+ }
+ else {
+ /* Cache miss, getting an object buffer from the LRU list.*/
+ objp = lru_get_last_s(ocp);
+
+ /* Naming this object and publishing it in the hash table.*/
+ objp->obj_group = group;
+ objp->obj_key = key;
+ objp->obj_flags = OC_FLAG_INHASH | OC_FLAG_NOTSYNC;
+ HASH_INSERT(ocp, objp, group, key);
+ }
+
+ /* Out of critical section and returning the object.*/
+ chSysUnlock();
+
+ return objp;
+}
+
+/**
+ * @brief Releases an object into the cache.
+ * @note This function gives a meaning to the following flags:
+ * - @p OC_FLAG_INLRU must be cleared.
+ * - @p OC_FLAG_INHASH must be set.
+ * - @p OC_FLAG_SHARED must be cleared.
+ * - @p OC_FLAG_NOTSYNC invalidates the object and queues it on
+ * the LRU tail.
+ * - @p OC_FLAG_LAZYWRITE is ignored and kept, a write will occur
+ * when the object is removed from the LRU list (lazy write).
+ * .
+ *
+ * @param[in] ocp pointer to the @p objects_cache_t structure
+ * @param[in] objp pointer to the @p oc_object_t structure
+ *
+ * @iclass
+ */
+void chCacheReleaseObjectI(objects_cache_t *ocp,
+ oc_object_t *objp) {
+
+ /* Checking initial conditions of the object to be released.*/
+ chDbgAssert((objp->obj_flags & (OC_FLAG_INLRU |
+ OC_FLAG_INHASH |
+ OC_FLAG_SHARED)) == OC_FLAG_INHASH,
+ "invalid object state");
+ chDbgAssert(chSemGetCounterI(&objp->obj_sem) <= (cnt_t)0,
+ "semaphore counter greater than 0");
+
+ /* If some thread is waiting for this specific buffer then it is
+ handed directly without going through the LRU.*/
+ if (chSemGetCounterI(&objp->obj_sem) < (cnt_t)0) {
+ /* Clearing all flags except those that are still meaningful, note,
+ OC_FLAG_NOTSYNC and OC_FLAG_LAZYWRITE are passed, the other thread
+ will handle them.*/
+ objp->obj_flags &= OC_FLAG_INHASH | OC_FLAG_NOTSYNC | OC_FLAG_LAZYWRITE;
+ chSemSignalI(&objp->obj_sem);
+ return;
+ }
+
+ /* If the object specifies OC_FLAG_NOTSYNC then it must be invalidated
+ and removed from the hash table.*/
+ if ((objp->obj_flags & OC_FLAG_NOTSYNC) != 0U) {
+ HASH_REMOVE(objp);
+ LRU_INSERT_TAIL(ocp, objp);
+ objp->obj_group = 0U;
+ objp->obj_key = 0U;
+ objp->obj_flags = OC_FLAG_INLRU;
+ }
+ else {
+ /* LRU insertion point depends on the OC_FLAG_FORGET flag.*/
+ if ((objp->obj_flags & OC_FLAG_FORGET) == 0U) {
+ /* Placing it on head.*/
+ LRU_INSERT_HEAD(ocp, objp);
+ }
+ else {
+ /* Low priority data, placing it on tail.*/
+ LRU_INSERT_TAIL(ocp, objp);
+ }
+ objp->obj_flags &= OC_FLAG_INHASH | OC_FLAG_LAZYWRITE;
+ objp->obj_flags |= OC_FLAG_INLRU;
+ }
+
+ /* Increasing the LRU counter semaphore.*/
+ chSemSignalI(&ocp->lru_sem);
+
+ /* Releasing the object, we know there are no threads waiting so
+ using the "fast" signal variant.*/
+ chSemFastSignalI(&objp->obj_sem);
+}
+
+/**
+ * @brief Reads object data from the storage.
+ * @note In case of asynchronous operation an error condition is not
+ * reported by this function.
+ *
+ * @param[in] ocp pointer to the @p objects_cache_t structure
+ * @param[in] objp pointer to the @p oc_object_t structure
+ * @param[in] async requests an asynchronous operation if supported, the
+ * function is then responsible for releasing the
+ * object
+ * @return The operation status. In case of asynchronous
+ * operation @p false is always returned.
+ * @retval false if the operation succeeded.
+ * @retval true if the synchronous read operation failed.
+ *
+ * @api
+ */
+bool chCacheReadObject(objects_cache_t *ocp,
+ oc_object_t *objp,
+ bool async) {
+
+ /* Marking it as OC_FLAG_NOTSYNC because the read operation is going
+ to corrupt it in case of failure. It is responsibility of the read
+ implementation to clear it if the operation succeeds.*/
+ objp->obj_flags |= OC_FLAG_NOTSYNC;
+
+ return ocp->readf(ocp, objp, async);
+}
+
+/**
+ * @brief Writes the object data back to storage.
+ * @note In case of asynchronous operation an error condition is not
+ * reported by this function.
+ *
+ * @param[in] ocp pointer to the @p objects_cache_t structure
+ * @param[in] objp pointer to the @p oc_object_t structure
+ * @param[in] async requests an asynchronous operation if supported, the
+ * function is then responsible for releasing the
+ * object
+ * @return The operation status. In case of asynchronous
+ * operation @p false is always returned.
+ * @retval false if the operation succeeded.
+ * @retval true if the synchronous write operation failed.
+ *
+ * @api
+ */
+bool chCacheWriteObject(objects_cache_t *ocp,
+ oc_object_t *objp,
+ bool async) {
+
+ /* Resetting the OC_FLAG_LAZYWRITE flag in order to prevent multiple
+ writes.*/
+ objp->obj_flags &= ~OC_FLAG_LAZYWRITE;
+
+ return ocp->writef(ocp, objp, async);
+}
+
+#endif /* CH_CFG_USE_OBJ_CACHES == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/oslib/src/chpipes.c b/ChibiOS_20.3.2/os/oslib/src/chpipes.c
new file mode 100644
index 0000000..f3fb462
--- /dev/null
+++ b/ChibiOS_20.3.2/os/oslib/src/chpipes.c
@@ -0,0 +1,388 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file oslib/src/chpipes.c
+ * @brief Pipes code.
+ * @details Byte pipes.
+ * Operation mode
+ * A pipe is an asynchronous communication mechanism.
+ * Operations defined for mailboxes:
+ * - Write: Writes a buffer of data in the pipe in FIFO order.
+ * - Read: A buffer of data is read from the read and removed.
+ * - Reset: The pipe is emptied and all the stored data
+ * is lost.
+ * .
+ * @pre In order to use the pipes APIs the @p CH_CFG_USE_PIPES
+ * option must be enabled in @p chconf.h.
+ * @note Compatible with RT and NIL.
+ *
+ * @addtogroup oslib_pipes
+ * @{
+ */
+
+#include
+
+#include "ch.h"
+
+#if (CH_CFG_USE_PIPES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*
+ * Defaults on the best synchronization mechanism available.
+ */
+#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
+#define PC_INIT(p) chMtxObjectInit(&(p)->cmtx)
+#define PC_LOCK(p) chMtxLock(&(p)->cmtx)
+#define PC_UNLOCK(p) chMtxUnlock(&(p)->cmtx)
+#define PW_INIT(p) chMtxObjectInit(&(p)->wmtx)
+#define PW_LOCK(p) chMtxLock(&(p)->wmtx)
+#define PW_UNLOCK(p) chMtxUnlock(&(p)->wmtx)
+#define PR_INIT(p) chMtxObjectInit(&(p)->rmtx)
+#define PR_LOCK(p) chMtxLock(&(p)->rmtx)
+#define PR_UNLOCK(p) chMtxUnlock(&(p)->rmtx)
+#else
+#define PC_INIT(p) chSemObjectInit(&(p)->csem, (cnt_t)1)
+#define PC_LOCK(p) (void) chSemWait(&(p)->csem)
+#define PC_UNLOCK(p) chSemSignal(&(p)->csem)
+#define PW_INIT(p) chSemObjectInit(&(p)->wsem, (cnt_t)1)
+#define PW_LOCK(p) (void) chSemWait(&(p)->wsem)
+#define PW_UNLOCK(p) chSemSignal(&(p)->wsem)
+#define PR_INIT(p) chSemObjectInit(&(p)->rsem, (cnt_t)1)
+#define PR_LOCK(p) (void) chSemWait(&(p)->rsem)
+#define PR_UNLOCK(p) chSemSignal(&(p)->rsem)
+#endif
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Non-blocking pipe write.
+ * @details The function writes data from a buffer to a pipe. The
+ * operation completes when the specified amount of data has been
+ * transferred or when the pipe buffer has been filled.
+ *
+ * @param[in] pp the pointer to an initialized @p pipe_t object
+ * @param[in] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred, the
+ * value 0 is reserved
+ * @return The number of bytes effectively transferred.
+ *
+ * @notapi
+ */
+static size_t pipe_write(pipe_t *pp, const uint8_t *bp, size_t n) {
+ size_t s1, s2;
+
+ PC_LOCK(pp);
+
+ /* Number of bytes that can be written in a single atomic operation.*/
+ if (n > chPipeGetFreeCount(pp)) {
+ n = chPipeGetFreeCount(pp);
+ }
+ pp->cnt += n;
+
+ /* Number of bytes before buffer limit.*/
+ /*lint -save -e9033 [10.8] Checked to be safe.*/
+ s1 = (size_t)(pp->top - pp->wrptr);
+ /*lint -restore*/
+
+ if (n < s1) {
+ memcpy((void *)pp->wrptr, (const void *)bp, n);
+ pp->wrptr += n;
+ }
+ else if (n > s1) {
+ memcpy((void *)pp->wrptr, (const void *)bp, s1);
+ bp += s1;
+ s2 = n - s1;
+ memcpy((void *)pp->buffer, (const void *)bp, s2);
+ pp->wrptr = pp->buffer + s2;
+ }
+ else {
+ memcpy((void *)pp->wrptr, (const void *)bp, n);
+ pp->wrptr = pp->buffer;
+ }
+
+ PC_UNLOCK(pp);
+
+ return n;
+}
+
+/**
+ * @brief Non-blocking pipe read.
+ * @details The function reads data from a pipe into a buffer. The
+ * operation completes when the specified amount of data has been
+ * transferred or when the pipe buffer has been emptied.
+ *
+ * @param[in] pp the pointer to an initialized @p pipe_t object
+ * @param[out] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred, the
+ * value 0 is reserved
+ * @return The number of bytes effectively transferred.
+ *
+ * @notapi
+ */
+static size_t pipe_read(pipe_t *pp, uint8_t *bp, size_t n) {
+ size_t s1, s2;
+
+ PC_LOCK(pp);
+
+ /* Number of bytes that can be read in a single atomic operation.*/
+ if (n > chPipeGetUsedCount(pp)) {
+ n = chPipeGetUsedCount(pp);
+ }
+ pp->cnt -= n;
+
+ /* Number of bytes before buffer limit.*/
+ /*lint -save -e9033 [10.8] Checked to be safe.*/
+ s1 = (size_t)(pp->top - pp->rdptr);
+ /*lint -restore*/
+
+ if (n < s1) {
+ memcpy((void *)bp, (void *)pp->rdptr, n);
+ pp->rdptr += n;
+ }
+ else if (n > s1) {
+ memcpy((void *)bp, (void *)pp->rdptr, s1);
+ bp += s1;
+ s2 = n - s1;
+ memcpy((void *)bp, (void *)pp->buffer, s2);
+ pp->rdptr = pp->buffer + s2;
+ }
+ else {
+ memcpy((void *)bp, (void *)pp->rdptr, n);
+ pp->rdptr = pp->buffer;
+ }
+
+ PC_UNLOCK(pp);
+
+ return n;
+}
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes a @p mailbox_t object.
+ *
+ * @param[out] pp the pointer to the @p pipe_t structure to be
+ * initialized
+ * @param[in] buf pointer to the pipe buffer as an array of @p uint8_t
+ * @param[in] n number of elements in the buffer array
+ *
+ * @init
+ */
+void chPipeObjectInit(pipe_t *pp, uint8_t *buf, size_t n) {
+
+ chDbgCheck((pp != NULL) && (buf != NULL) && (n > (size_t)0));
+
+ pp->buffer = buf;
+ pp->rdptr = buf;
+ pp->wrptr = buf;
+ pp->top = &buf[n];
+ pp->cnt = (size_t)0;
+ pp->reset = false;
+ pp->wtr = NULL;
+ pp->rtr = NULL;
+ PC_INIT(pp);
+ PW_INIT(pp);
+ PR_INIT(pp);
+}
+
+/**
+ * @brief Resets a @p pipe_t object.
+ * @details All the waiting threads are resumed with status @p MSG_RESET and
+ * the queued data is lost.
+ * @post The pipe is in reset state, all operations will fail and
+ * return @p MSG_RESET until the mailbox is enabled again using
+ * @p chPipeResumeX().
+ *
+ * @param[in] pp the pointer to an initialized @p pipe_t object
+ *
+ * @api
+ */
+void chPipeReset(pipe_t *pp) {
+
+ chDbgCheck(pp != NULL);
+
+ PC_LOCK(pp);
+
+ pp->wrptr = pp->buffer;
+ pp->rdptr = pp->buffer;
+ pp->cnt = (size_t)0;
+ pp->reset = true;
+
+ chSysLock();
+ chThdResumeI(&pp->wtr, MSG_RESET);
+ chThdResumeI(&pp->rtr, MSG_RESET);
+ chSchRescheduleS();
+ chSysUnlock();
+
+ PC_UNLOCK(pp);
+}
+
+/**
+ * @brief Pipe write with timeout.
+ * @details The function writes data from a buffer to a pipe. The
+ * operation completes when the specified amount of data has been
+ * transferred or after the specified timeout or if the pipe has
+ * been reset.
+ *
+ * @param[in] pp the pointer to an initialized @p pipe_t object
+ * @param[in] bp pointer to the data buffer
+ * @param[in] n the number of bytes to be written, the value 0 is
+ * reserved
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The number of bytes effectively transferred. A number
+ * lower than @p n means that a timeout occurred or the
+ * pipe went in reset state.
+ *
+ * @api
+ */
+size_t chPipeWriteTimeout(pipe_t *pp, const uint8_t *bp,
+ size_t n, sysinterval_t timeout) {
+ size_t max = n;
+
+ chDbgCheck(n > 0U);
+
+ /* If the pipe is in reset state then returns immediately.*/
+ if (pp->reset) {
+ return (size_t)0;
+ }
+
+ PW_LOCK(pp);
+
+ while (n > 0U) {
+ size_t done;
+
+ done = pipe_write(pp, bp, n);
+ if (done == (size_t)0) {
+ msg_t msg;
+
+ chSysLock();
+ msg = chThdSuspendTimeoutS(&pp->wtr, timeout);
+ chSysUnlock();
+
+ /* Anything except MSG_OK causes the operation to stop.*/
+ if (msg != MSG_OK) {
+ break;
+ }
+ }
+ else {
+ n -= done;
+ bp += done;
+
+ /* Resuming the reader, if present.*/
+ chThdResume(&pp->rtr, MSG_OK);
+ }
+ }
+
+ PW_UNLOCK(pp);
+
+ return max - n;
+}
+
+/**
+ * @brief Pipe read with timeout.
+ * @details The function reads data from a pipe into a buffer. The
+ * operation completes when the specified amount of data has been
+ * transferred or after the specified timeout or if the pipe has
+ * been reset.
+ *
+ * @param[in] pp the pointer to an initialized @p pipe_t object
+ * @param[out] bp pointer to the data buffer
+ * @param[in] n the number of bytes to be read, the value 0 is
+ * reserved
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The number of bytes effectively transferred. A number
+ * lower than @p n means that a timeout occurred or the
+ * pipe went in reset state.
+ *
+ * @api
+ */
+size_t chPipeReadTimeout(pipe_t *pp, uint8_t *bp,
+ size_t n, sysinterval_t timeout) {
+ size_t max = n;
+
+ chDbgCheck(n > 0U);
+
+ /* If the pipe is in reset state then returns immediately.*/
+ if (pp->reset) {
+ return (size_t)0;
+ }
+
+ PR_LOCK(pp);
+
+ while (n > 0U) {
+ size_t done;
+
+ done = pipe_read(pp, bp, n);
+ if (done == (size_t)0) {
+ msg_t msg;
+
+ chSysLock();
+ msg = chThdSuspendTimeoutS(&pp->rtr, timeout);
+ chSysUnlock();
+
+ /* Anything except MSG_OK causes the operation to stop.*/
+ if (msg != MSG_OK) {
+ break;
+ }
+ }
+ else {
+ n -= done;
+ bp += done;
+
+ /* Resuming the writer, if present.*/
+ chThdResume(&pp->wtr, MSG_OK);
+ }
+ }
+
+ PR_UNLOCK(pp);
+
+ return max - n;
+}
+
+#endif /* CH_CFG_USE_PIPES == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/readme.txt b/ChibiOS_20.3.2/os/readme.txt
new file mode 100644
index 0000000..46ff6c7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/readme.txt
@@ -0,0 +1,29 @@
+*****************************************************************************
+*** ChibiOS products directory organization ***
+*****************************************************************************
+
+--{root} - Distribution directory.
+ +--os/ - ChibiOS products, this directory.
+ | +--rt/ - ChibiOS/RT product.
+ | | +--include/ - RT kernel headers.
+ | | +--src/ - RT kernel sources.
+ | | +--templates/ - RT kernel port template files.
+ | | +--ports/ - RT kernel port files.
+ | | +--osal/ - RT kernel OSAL module for HAL interface.
+ | +--nil/ - ChibiOS/NIL product.
+ | | +--include/ - Nil kernel headers.
+ | | +--src/ - Nil kernel sources.
+ | | +--templates/ - Nil kernel port template files.
+ | | +--ports/ - Nil kernel port files.
+ | | +--osal/ - Nil kernel OSAL module for HAL interface.
+ | +--hal/ - ChibiOS/HAL product.
+ | | +--include/ - HAL high level headers.
+ | | +--src/ - HAL high level sources.
+ | | +--templates/ - HAL port template files.
+ | | +--ports/ - HAL port files (low level drivers implementations).
+ | | +--boards/ - HAL board files.
+ | +--common/ - Files used by multiple ChibiOS products.
+ | | +--ports - Common port files for various architectures and
+ | | compilers.
+ | +--various/ - Various portable support files.
+ | +--ext/ - Vendor files used by ChibiOS products.
diff --git a/ChibiOS_20.3.2/os/rt/dox/rt.dox b/ChibiOS_20.3.2/os/rt/dox/rt.dox
new file mode 100644
index 0000000..75030ff
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/dox/rt.dox
@@ -0,0 +1,152 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @defgroup kernel RT Kernel
+ * @details The kernel is the portable part of ChibiOS/RT, this section
+ * documents the various kernel subsystems.
+ */
+
+/**
+ * @defgroup kernel_info Version Numbers and Identification
+ * @ingroup kernel
+ */
+
+/**
+ * @defgroup config_category Configuration
+ * @ingroup kernel
+ */
+
+/**
+ * @defgroup config Options
+ * @ingroup config_category
+ */
+
+/**
+ * @defgroup conf_checks Checks
+ * @ingroup config_category
+ */
+
+/**
+ * @defgroup rt_restrictions Restrictions
+ * @ingroup config_category
+ */
+
+/**
+ * @defgroup base Base Kernel Services
+ * @details Base kernel services, the base subsystems are always included in
+ * the OS builds.
+ * @ingroup kernel
+ */
+
+/**
+ * @defgroup mem Memory Alignment
+ * @ingroup base
+ */
+
+/**
+ * @defgroup system System Management
+ * @ingroup base
+ */
+
+/**
+ * @defgroup scheduler Scheduler
+ * @ingroup base
+ */
+
+/**
+ * @defgroup time_intervals Time and Intervals
+ * @ingroup base
+ */
+
+/**
+ * @defgroup time Virtual Timers
+ * @ingroup base
+ */
+
+/**
+ * @defgroup threads Threads
+ * @ingroup base
+ */
+
+/**
+ * @defgroup time_measurement Time Measurement
+ * @ingroup base
+ */
+
+/**
+ * @defgroup synchronization Synchronization
+ * @details Synchronization services.
+ * @ingroup kernel
+ */
+
+/**
+ * @defgroup semaphores Counting Semaphores
+ * @ingroup synchronization
+ */
+
+/**
+ * @defgroup mutexes Mutexes
+ * @ingroup synchronization
+ */
+
+/**
+ * @defgroup condvars Condition Variables
+ * @ingroup synchronization
+ */
+
+/**
+ * @defgroup events Event Flags
+ * @ingroup synchronization
+ */
+
+/**
+ * @defgroup messages Synchronous Messages
+ * @ingroup synchronization
+ */
+
+/**
+ * @defgroup dynamic_threads Dynamic Threads
+ * @ingroup kernel
+ */
+
+/**
+ * @defgroup registry Registry
+ * @ingroup kernel
+ */
+
+/**
+ * @defgroup debug Debug
+ * @ingroup kernel
+ */
+
+/**
+ * @defgroup checks_assertions Checks and Assertions
+ * @ingroup debug
+ */
+
+/**
+ * @defgroup trace Tracing
+ * @ingroup debug
+ */
+
+/**
+ * @defgroup statistics Statistics
+ * @ingroup debug
+ */
diff --git a/ChibiOS_20.3.2/os/rt/include/ch.h b/ChibiOS_20.3.2/os/rt/include/ch.h
new file mode 100644
index 0000000..200383b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/ch.h
@@ -0,0 +1,135 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/ch.h
+ * @brief ChibiOS/RT main include file.
+ *
+ * @addtogroup kernel_info
+ * @details This header includes all the required kernel headers so it is the
+ * only kernel header you usually want to include in your application.
+ * @details Kernel related info.
+ * @{
+ */
+
+#ifndef CH_H
+#define CH_H
+
+/**
+ * @brief ChibiOS/RT identification macro.
+ */
+#define _CHIBIOS_RT_
+
+/**
+ * @brief Stable release flag.
+ */
+#define CH_KERNEL_STABLE 1
+
+/**
+ * @name ChibiOS/RT version identification
+ * @{
+ */
+/**
+ * @brief Kernel version string.
+ */
+#define CH_KERNEL_VERSION "6.1.2"
+
+/**
+ * @brief Kernel version major number.
+ */
+#define CH_KERNEL_MAJOR 6
+
+/**
+ * @brief Kernel version minor number.
+ */
+#define CH_KERNEL_MINOR 1
+
+/**
+ * @brief Kernel version patch number.
+ */
+#define CH_KERNEL_PATCH 2
+/** @} */
+
+/**
+ * @name Constants for configuration options
+ */
+/**
+ * @brief Generic 'false' preprocessor boolean constant.
+ * @note It is meant to be used in configuration files as switch.
+ */
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+/**
+ * @brief Generic 'true' preprocessor boolean constant.
+ * @note It is meant to be used in configuration files as switch.
+ */
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+/** @} */
+
+/* Configuration headers, checks and licensing restrictions.*/
+#include "chconf.h"
+#include "chchecks.h"
+#include "chlicense.h"
+#include "chrestrictions.h"
+
+/* Early function prototype required by the following headers.*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chSysHalt(const char *reason);
+#ifdef __cplusplus
+}
+#endif
+
+/* Base kernel headers.*/
+#include "chtypes.h" /* CHTODO: Rename and rework.*/
+#include "chsystypes.h"
+#include "chdebug.h"
+#include "chtime.h"
+#include "chalign.h"
+#include "chcore.h"
+#include "chtrace.h"
+#include "chtm.h"
+#include "chstats.h"
+#include "chschd.h"
+#include "chsys.h"
+#include "chvt.h"
+#include "chthreads.h"
+
+/* Optional subsystems headers.*/
+#include "chregistry.h"
+#include "chsem.h"
+#include "chmtx.h"
+#include "chcond.h"
+#include "chevents.h"
+#include "chmsg.h"
+
+/* OSLIB.*/
+#include "chlib.h"
+
+/* Headers dependent on the OSLIB.*/
+#include "chdynamic.h"
+
+#endif /* CH_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chalign.h b/ChibiOS_20.3.2/os/rt/include/chalign.h
new file mode 100644
index 0000000..56e5f1c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chalign.h
@@ -0,0 +1,120 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/chalign.h
+ * @brief Memory alignment macros and structures.
+ *
+ * @addtogroup mem
+ * @details Memory Alignment services.
+ * @{
+ */
+
+#ifndef CHALIGN_H
+#define CHALIGN_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @name Memory alignment support macros
+ */
+/**
+ * @brief Alignment mask constant.
+ *
+ * @param[in] a alignment, must be a power of two
+ */
+#define MEM_ALIGN_MASK(a) ((size_t)(a) - 1U)
+
+/**
+ * @brief Aligns to the previous aligned memory address.
+ *
+ * @param[in] p variable to be aligned
+ * @param[in] a alignment, must be a power of two
+ */
+#define MEM_ALIGN_PREV(p, a) \
+ /*lint -save -e9033 [10.8] The cast is safe.*/ \
+ ((size_t)(p) & ~MEM_ALIGN_MASK(a)) \
+ /*lint -restore*/
+
+/**
+ * @brief Aligns to the next aligned memory address.
+ *
+ * @param[in] p variable to be aligned
+ * @param[in] a alignment, must be a power of two
+ */
+#define MEM_ALIGN_NEXT(p, a) \
+ /*lint -save -e9033 [10.8] The cast is safe.*/ \
+ MEM_ALIGN_PREV((size_t)(p) + MEM_ALIGN_MASK(a), (a)) \
+ /*lint -restore*/
+
+/**
+ * @brief Returns whatever a pointer or memory size is aligned.
+ *
+ * @param[in] p variable to be aligned
+ * @param[in] a alignment, must be a power of two
+ */
+#define MEM_IS_ALIGNED(p, a) (((size_t)(p) & MEM_ALIGN_MASK(a)) == 0U)
+
+/**
+ * @brief Returns whatever a constant is a valid alignment.
+ * @details Valid alignments are powers of two.
+ *
+ * @param[in] a alignment to be checked, must be a constant
+ */
+#define MEM_IS_VALID_ALIGNMENT(a) \
+ (((size_t)(a) != 0U) && (((size_t)(a) & ((size_t)(a) - 1U)) == 0U))
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* CHALIGN_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chchecks.h b/ChibiOS_20.3.2/os/rt/include/chchecks.h
new file mode 100644
index 0000000..c2d16c0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chchecks.h
@@ -0,0 +1,263 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/chchecks.h
+ * @brief Configuration file checks header.
+ *
+ * @addtogroup conf_checks
+ * @details This module performs a series of checks on configuration data,
+ * it is able to detect and reject obsolete or incomplete
+ * @p chconf.h files.
+ * @{
+ */
+
+#ifndef CHCHECKS_H
+#define CHCHECKS_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/* Configuration file checks.*/
+#if !defined(_CHIBIOS_RT_CONF_)
+#error "invalid configuration file"
+#endif
+
+#if !defined(_CHIBIOS_RT_CONF_VER_6_1_)
+#error "obsolete or unknown configuration file"
+#endif
+
+/* System timers checks.*/
+#if !defined(CH_CFG_ST_RESOLUTION)
+#error "CH_CFG_ST_RESOLUTION not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_ST_FREQUENCY)
+#error "CH_CFG_ST_FREQUENCY not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_INTERVALS_SIZE)
+#error "CH_CFG_INTERVALS_SIZE not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_TIME_TYPES_SIZE)
+#error "CH_CFG_TIME_TYPES_SIZE not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_ST_TIMEDELTA)
+#error "CH_CFG_ST_TIMEDELTA not defined in chconf.h"
+#endif
+
+/* Kernel parameters and options checks.*/
+#if !defined(CH_CFG_TIME_QUANTUM)
+#error "CH_CFG_TIME_QUANTUM not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_MEMCORE_SIZE)
+#error "CH_CFG_MEMCORE_SIZE not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_NO_IDLE_THREAD)
+#error "CH_CFG_NO_IDLE_THREAD not defined in chconf.h"
+#endif
+
+/* Performance options checks.*/
+#if !defined(CH_CFG_OPTIMIZE_SPEED)
+#error "CH_CFG_OPTIMIZE_SPEED not defined in chconf.h"
+#endif
+
+/* Subsystem options checks.*/
+#if !defined(CH_CFG_USE_TM)
+#error "CH_CFG_USE_TM not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_REGISTRY)
+#error "CH_CFG_USE_REGISTRY not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_WAITEXIT)
+#error "CH_CFG_USE_WAITEXIT not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_SEMAPHORES)
+#error "CH_CFG_USE_SEMAPHORES not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY)
+#error "CH_CFG_USE_SEMAPHORES_PRIORITY not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_MUTEXES)
+#error "CH_CFG_USE_MUTEXES not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE)
+#error "CH_CFG_USE_MUTEXES_RECURSIVE not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_CONDVARS)
+#error "CH_CFG_USE_CONDVARS not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT)
+#error "CH_CFG_USE_CONDVARS_TIMEOUT not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_EVENTS)
+#error "CH_CFG_USE_EVENTS not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_EVENTS_TIMEOUT)
+#error "CH_CFG_USE_EVENTS_TIMEOUT not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_MESSAGES)
+#error "CH_CFG_USE_MESSAGES not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_MESSAGES_PRIORITY)
+#error "CH_CFG_USE_MESSAGES_PRIORITY not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_DYNAMIC)
+#error "CH_CFG_USE_DYNAMIC not defined in chconf.h"
+#endif
+
+/* Debug options checks.*/
+#if !defined(CH_DBG_STATISTICS)
+#error "CH_DBG_STATISTICS not defined in chconf.h"
+#endif
+
+#if !defined(CH_DBG_SYSTEM_STATE_CHECK)
+#error "CH_DBG_SYSTEM_STATE_CHECK not defined in chconf.h"
+#endif
+
+#if !defined(CH_DBG_ENABLE_CHECKS)
+#error "CH_DBG_ENABLE_CHECKS not defined in chconf.h"
+#endif
+
+#if !defined(CH_DBG_ENABLE_ASSERTS)
+#error "CH_DBG_ENABLE_ASSERTS not defined in chconf.h"
+#endif
+
+#if !defined(CH_DBG_TRACE_MASK)
+#error "CH_DBG_TRACE_MASK not defined in chconf.h"
+#endif
+
+#if !defined(CH_DBG_TRACE_BUFFER_SIZE)
+#error "CH_DBG_TRACE_BUFFER_SIZE not defined in chconf.h"
+#endif
+
+#if !defined(CH_DBG_ENABLE_STACK_CHECK)
+#error "CH_DBG_ENABLE_STACK_CHECK not defined in chconf.h"
+#endif
+
+#if !defined(CH_DBG_FILL_THREADS)
+#error "CH_DBG_FILL_THREADS not defined in chconf.h"
+#endif
+
+#if !defined(CH_DBG_THREADS_PROFILING)
+#error "CH_DBG_THREADS_PROFILING not defined in chconf.h"
+#endif
+
+/* System hooks checks.*/
+#if !defined(CH_CFG_SYSTEM_INIT_HOOK)
+#error "CH_CFG_SYSTEM_INIT_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_SYSTEM_EXTRA_FIELDS)
+#error "CH_CFG_SYSTEM_EXTRA_FIELDS not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_THREAD_EXTRA_FIELDS)
+#error "CH_CFG_THREAD_EXTRA_FIELDS not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_THREAD_INIT_HOOK)
+#error "CH_CFG_THREAD_INIT_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_THREAD_EXIT_HOOK)
+#error "CH_CFG_THREAD_EXIT_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_CONTEXT_SWITCH_HOOK)
+#error "CH_CFG_CONTEXT_SWITCH_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_IRQ_PROLOGUE_HOOK)
+#error "CH_CFG_IRQ_PROLOGUE_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_IRQ_EPILOGUE_HOOK)
+#error "CH_CFG_IRQ_EPILOGUE_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_IDLE_ENTER_HOOK)
+#error "CH_CFG_IDLE_ENTER_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_IDLE_LEAVE_HOOK)
+#error "CH_CFG_IDLE_LEAVE_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_IDLE_LOOP_HOOK)
+#error "CH_CFG_IDLE_LOOP_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_SYSTEM_TICK_HOOK)
+#error "CH_CFG_SYSTEM_TICK_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_SYSTEM_HALT_HOOK)
+#error "CH_CFG_SYSTEM_HALT_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_TRACE_HOOK)
+#error "CH_CFG_TRACE_HOOK not defined in chconf.h"
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* CHCHECKS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chcond.h b/ChibiOS_20.3.2/os/rt/include/chcond.h
new file mode 100644
index 0000000..b6d7f96
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chcond.h
@@ -0,0 +1,116 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+/*
+ Concepts and parts of this file have been contributed by Leon Woestenberg.
+ */
+
+/**
+ * @file rt/include/chcond.h
+ * @brief Condition Variables macros and structures.
+ *
+ * @addtogroup condvars
+ * @{
+ */
+
+#ifndef CHCOND_H
+#define CHCOND_H
+
+#if (CH_CFG_USE_CONDVARS == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if CH_CFG_USE_MUTEXES == FALSE
+#error "CH_CFG_USE_CONDVARS requires CH_CFG_USE_MUTEXES"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief condition_variable_t structure.
+ */
+typedef struct condition_variable {
+ threads_queue_t queue; /**< @brief Condition variable
+ threads queue. */
+} condition_variable_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Data part of a static condition variable initializer.
+ * @details This macro should be used when statically initializing a condition
+ * variable that is part of a bigger structure.
+ *
+ * @param[in] name the name of the condition variable
+ */
+#define _CONDVAR_DATA(name) {_THREADS_QUEUE_DATA(name.queue)}
+
+/**
+ * @brief Static condition variable initializer.
+ * @details Statically initialized condition variables require no explicit
+ * initialization using @p chCondInit().
+ *
+ * @param[in] name the name of the condition variable
+ */
+#define CONDVAR_DECL(name) condition_variable_t name = _CONDVAR_DATA(name)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chCondObjectInit(condition_variable_t *cp);
+ void chCondSignal(condition_variable_t *cp);
+ void chCondSignalI(condition_variable_t *cp);
+ void chCondBroadcast(condition_variable_t *cp);
+ void chCondBroadcastI(condition_variable_t *cp);
+ msg_t chCondWait(condition_variable_t *cp);
+ msg_t chCondWaitS(condition_variable_t *cp);
+#if CH_CFG_USE_CONDVARS_TIMEOUT == TRUE
+ msg_t chCondWaitTimeout(condition_variable_t *cp, sysinterval_t timeout);
+ msg_t chCondWaitTimeoutS(condition_variable_t *cp, sysinterval_t timeout);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* CH_CFG_USE_CONDVARS == TRUE */
+
+#endif /* CHCOND_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chdebug.h b/ChibiOS_20.3.2/os/rt/include/chdebug.h
new file mode 100644
index 0000000..240d1ca
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chdebug.h
@@ -0,0 +1,169 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/chdebug.h
+ * @brief Debug support macros and structures.
+ *
+ * @addtogroup checks_assertions
+ * @{
+ */
+
+#ifndef CHDEBUG_H
+#define CHDEBUG_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Debug related settings
+ * @{
+ */
+/**
+ * @brief Fill value for thread stack area in debug mode.
+ */
+#if !defined(CH_DBG_STACK_FILL_VALUE) || defined(__DOXYGEN__)
+#define CH_DBG_STACK_FILL_VALUE 0x55
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+#if CH_DBG_SYSTEM_STATE_CHECK == TRUE
+#define _dbg_enter_lock() (ch.dbg.lock_cnt = (cnt_t)1)
+#define _dbg_leave_lock() (ch.dbg.lock_cnt = (cnt_t)0)
+#endif
+
+/* When the state checker feature is disabled then the following functions
+ are replaced by an empty macro.*/
+#if CH_DBG_SYSTEM_STATE_CHECK == FALSE
+#define _dbg_enter_lock()
+#define _dbg_leave_lock()
+#define _dbg_check_disable()
+#define _dbg_check_suspend()
+#define _dbg_check_enable()
+#define _dbg_check_lock()
+#define _dbg_check_unlock()
+#define _dbg_check_lock_from_isr()
+#define _dbg_check_unlock_from_isr()
+#define _dbg_check_enter_isr()
+#define _dbg_check_leave_isr()
+#define chDbgCheckClassI()
+#define chDbgCheckClassS()
+#endif
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Function parameters check.
+ * @details If the condition check fails then the kernel panics and halts.
+ * @note The condition is tested only if the @p CH_DBG_ENABLE_CHECKS switch
+ * is specified in @p chconf.h else the macro does nothing.
+ *
+ * @param[in] c the condition to be verified to be true
+ *
+ * @api
+ */
+#if !defined(chDbgCheck)
+#define chDbgCheck(c) do { \
+ /*lint -save -e506 -e774 [2.1, 14.3] Can be a constant by design.*/ \
+ if (CH_DBG_ENABLE_CHECKS != FALSE) { \
+ if (!(c)) { \
+ /*lint -restore*/ \
+ chSysHalt(__func__); \
+ } \
+ } \
+} while (false)
+#endif /* !defined(chDbgCheck) */
+
+/**
+ * @brief Condition assertion.
+ * @details If the condition check fails then the kernel panics with a
+ * message and halts.
+ * @note The condition is tested only if the @p CH_DBG_ENABLE_ASSERTS switch
+ * is specified in @p chconf.h else the macro does nothing.
+ * @note The remark string is not currently used except for putting a
+ * comment in the code about the assertion.
+ *
+ * @param[in] c the condition to be verified to be true
+ * @param[in] r a remark string
+ *
+ * @api
+ */
+#if !defined(chDbgAssert)
+#define chDbgAssert(c, r) do { \
+ /*lint -save -e506 -e774 [2.1, 14.3] Can be a constant by design.*/ \
+ if (CH_DBG_ENABLE_ASSERTS != FALSE) { \
+ if (!(c)) { \
+ /*lint -restore*/ \
+ chSysHalt(__func__); \
+ } \
+ } \
+} while (false)
+#endif /* !defined(chDbgAssert) */
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if CH_DBG_SYSTEM_STATE_CHECK == TRUE
+ void _dbg_check_disable(void);
+ void _dbg_check_suspend(void);
+ void _dbg_check_enable(void);
+ void _dbg_check_lock(void);
+ void _dbg_check_unlock(void);
+ void _dbg_check_lock_from_isr(void);
+ void _dbg_check_unlock_from_isr(void);
+ void _dbg_check_enter_isr(void);
+ void _dbg_check_leave_isr(void);
+ void chDbgCheckClassI(void);
+ void chDbgCheckClassS(void);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* CHDEBUG_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chdynamic.h b/ChibiOS_20.3.2/os/rt/include/chdynamic.h
new file mode 100644
index 0000000..6f44c40
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chdynamic.h
@@ -0,0 +1,99 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/chdynamic.h
+ * @brief Dynamic threads macros and structures.
+ *
+ * @addtogroup dynamic_threads
+ * @{
+ */
+
+#ifndef CHDYNAMIC_H
+#define CHDYNAMIC_H
+
+#if (CH_CFG_USE_DYNAMIC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*
+ * Module dependencies check.
+ */
+#if CH_CFG_USE_WAITEXIT == FALSE
+#error "CH_CFG_USE_DYNAMIC requires CH_CFG_USE_WAITEXIT"
+#endif
+
+#if CH_CFG_USE_REGISTRY == FALSE
+#error "CH_CFG_USE_DYNAMIC requires CH_CFG_USE_REGISTRY"
+#endif
+
+#if (CH_CFG_USE_HEAP == FALSE) && (CH_CFG_USE_MEMPOOLS == FALSE)
+#error "CH_CFG_USE_DYNAMIC requires CH_CFG_USE_HEAP and/or CH_CFG_USE_MEMPOOLS"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/*
+ * Dynamic threads APIs.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if CH_CFG_USE_HEAP == TRUE
+ thread_t *chThdCreateFromHeap(memory_heap_t *heapp, size_t size,
+ const char *name, tprio_t prio,
+ tfunc_t pf, void *arg);
+#endif
+#if CH_CFG_USE_MEMPOOLS == TRUE
+ thread_t *chThdCreateFromMemoryPool(memory_pool_t *mp, const char *name,
+ tprio_t prio, tfunc_t pf, void *arg);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* CH_CFG_USE_DYNAMIC == TRUE */
+
+#endif /* CHDYNAMIC_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chevents.h b/ChibiOS_20.3.2/os/rt/include/chevents.h
new file mode 100644
index 0000000..c81d51e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chevents.h
@@ -0,0 +1,291 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+/*
+ Concepts and parts of this file have been contributed by Scott (skute).
+ */
+
+/**
+ * @file rt/include/chevents.h
+ * @brief Events macros and structures.
+ *
+ * @addtogroup events
+ * @{
+ */
+
+#ifndef CHEVENTS_H
+#define CHEVENTS_H
+
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+typedef struct event_listener event_listener_t;
+
+/**
+ * @brief Event Listener structure.
+ */
+struct event_listener {
+ event_listener_t *next; /**< @brief Next Event Listener
+ registered on the event
+ source. */
+ thread_t *listener; /**< @brief Thread interested in the
+ event source. */
+ eventmask_t events; /**< @brief Events to be set in
+ the listening thread. */
+ eventflags_t flags; /**< @brief Flags added to the listener
+ by the event source. */
+ eventflags_t wflags; /**< @brief Flags that this listener
+ interested in. */
+};
+
+/**
+ * @brief Event Source structure.
+ */
+typedef struct event_source {
+ event_listener_t *next; /**< @brief First Event Listener
+ registered on the Event
+ Source. */
+} event_source_t;
+
+/**
+ * @brief Event Handler callback function.
+ */
+typedef void (*evhandler_t)(eventid_t id);
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief All events allowed mask.
+ */
+#define ALL_EVENTS ((eventmask_t)-1)
+
+/**
+ * @brief Returns an event mask from an event identifier.
+ */
+#define EVENT_MASK(eid) ((eventmask_t)1 << (eventmask_t)(eid))
+
+/**
+ * @brief Data part of a static event source initializer.
+ * @details This macro should be used when statically initializing an event
+ * source that is part of a bigger structure.
+ * @param name the name of the event source variable
+ */
+#define _EVENTSOURCE_DATA(name) {(event_listener_t *)(&name)}
+
+/**
+ * @brief Static event source initializer.
+ * @details Statically initialized event sources require no explicit
+ * initialization using @p chEvtInit().
+ *
+ * @param name the name of the event source variable
+ */
+#define EVENTSOURCE_DECL(name) event_source_t name = _EVENTSOURCE_DATA(name)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chEvtRegisterMaskWithFlags(event_source_t *esp,
+ event_listener_t *elp,
+ eventmask_t events,
+ eventflags_t wflags);
+ void chEvtUnregister(event_source_t *esp, event_listener_t *elp);
+ eventmask_t chEvtGetAndClearEventsI(eventmask_t events);
+ eventmask_t chEvtGetAndClearEvents(eventmask_t events);
+ eventmask_t chEvtAddEvents(eventmask_t events);
+ eventflags_t chEvtGetAndClearFlags(event_listener_t *elp);
+ eventflags_t chEvtGetAndClearFlagsI(event_listener_t *elp);
+ void chEvtSignal(thread_t *tp, eventmask_t events);
+ void chEvtSignalI(thread_t *tp, eventmask_t events);
+ void chEvtBroadcastFlags(event_source_t *esp, eventflags_t flags);
+ void chEvtBroadcastFlagsI(event_source_t *esp, eventflags_t flags);
+ void chEvtDispatch(const evhandler_t *handlers, eventmask_t events);
+#if (CH_CFG_OPTIMIZE_SPEED == TRUE) || (CH_CFG_USE_EVENTS_TIMEOUT == FALSE)
+ eventmask_t chEvtWaitOne(eventmask_t events);
+ eventmask_t chEvtWaitAny(eventmask_t events);
+ eventmask_t chEvtWaitAll(eventmask_t events);
+#endif
+#if CH_CFG_USE_EVENTS_TIMEOUT == TRUE
+ eventmask_t chEvtWaitOneTimeout(eventmask_t events, sysinterval_t timeout);
+ eventmask_t chEvtWaitAnyTimeout(eventmask_t events, sysinterval_t timeout);
+ eventmask_t chEvtWaitAllTimeout(eventmask_t events, sysinterval_t timeout);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#if (CH_CFG_OPTIMIZE_SPEED == FALSE) && (CH_CFG_USE_EVENTS_TIMEOUT == TRUE)
+#define chEvtWaitOne(mask) chEvtWaitOneTimeout(mask, TIME_INFINITE)
+#define chEvtWaitAny(mask) chEvtWaitAnyTimeout(mask, TIME_INFINITE)
+#define chEvtWaitAll(mask) chEvtWaitAllTimeout(mask, TIME_INFINITE)
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes an Event Source.
+ * @note This function can be invoked before the kernel is initialized
+ * because it just prepares a @p event_source_t structure.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ *
+ * @init
+ */
+static inline void chEvtObjectInit(event_source_t *esp) {
+
+ esp->next = (event_listener_t *)esp;
+}
+
+/**
+ * @brief Registers an Event Listener on an Event Source.
+ * @details Once a thread has registered as listener on an event source it
+ * will be notified of all events broadcasted there.
+ * @note Multiple Event Listeners can specify the same bits to be ORed to
+ * different threads.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ * @param[out] elp pointer to the @p event_listener_t structure
+ * @param[in] events the mask of events to be ORed to the thread when
+ * the event source is broadcasted
+ *
+ * @api
+ */
+static inline void chEvtRegisterMask(event_source_t *esp,
+ event_listener_t *elp,
+ eventmask_t events) {
+
+ chEvtRegisterMaskWithFlags(esp, elp, events, (eventflags_t)-1);
+}
+
+/**
+ * @brief Registers an Event Listener on an Event Source.
+ * @note Multiple Event Listeners can use the same event identifier, the
+ * listener will share the callback function.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ * @param[out] elp pointer to the @p event_listener_t structure
+ * @param[in] event numeric identifier assigned to the Event Listener.
+ * The value must range between zero and the size, in bit,
+ * of the @p eventmask_t type minus one.
+ *
+ * @api
+ */
+static inline void chEvtRegister(event_source_t *esp,
+ event_listener_t *elp,
+ eventid_t event) {
+
+ chEvtRegisterMask(esp, elp, EVENT_MASK(event));
+}
+
+/**
+ * @brief Verifies if there is at least one @p event_listener_t registered.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ * @return The event source status.
+ *
+ * @iclass
+ */
+static inline bool chEvtIsListeningI(event_source_t *esp) {
+
+ return (bool)(esp != (event_source_t *)esp->next);
+}
+
+/**
+ * @brief Signals all the Event Listeners registered on the specified Event
+ * Source.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ *
+ * @api
+ */
+static inline void chEvtBroadcast(event_source_t *esp) {
+
+ chEvtBroadcastFlags(esp, (eventflags_t)0);
+}
+
+/**
+ * @brief Signals all the Event Listeners registered on the specified Event
+ * Source.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ *
+ * @iclass
+ */
+static inline void chEvtBroadcastI(event_source_t *esp) {
+
+ chEvtBroadcastFlagsI(esp, (eventflags_t)0);
+}
+
+/**
+ * @brief Adds (OR) a set of events to the current thread, this is
+ * @b much faster than using @p chEvtBroadcast() or @p chEvtSignal().
+ *
+ * @param[in] events the events to be added
+ * @return The mask of currently pending events.
+ *
+ * @iclass
+ */
+static inline eventmask_t chEvtAddEventsI(eventmask_t events) {
+
+ return currp->epending |= events;
+}
+
+/**
+ * @brief Returns the events mask.
+ * @details The pending events mask is returned but not altered in any way.
+ *
+ * @return The pending events mask.
+ *
+ * @api
+ */
+static inline eventmask_t chEvtGetEventsX(void) {
+
+ return currp->epending;
+}
+
+#endif /* CH_CFG_USE_EVENTS == TRUE */
+
+#endif /* CHEVENTS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chmsg.h b/ChibiOS_20.3.2/os/rt/include/chmsg.h
new file mode 100644
index 0000000..6bd110a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chmsg.h
@@ -0,0 +1,212 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/chmsg.h
+ * @brief Messages macros and structures.
+ *
+ * @addtogroup messages
+ * @{
+ */
+
+#ifndef CHMSG_H
+#define CHMSG_H
+
+#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ msg_t chMsgSend(thread_t *tp, msg_t msg);
+ thread_t *chMsgWaitS(void);
+ thread_t *chMsgWaitTimeoutS(sysinterval_t timeout);
+ thread_t *chMsgPollS(void);
+ void chMsgRelease(thread_t *tp, msg_t msg);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/**
+ * @brief Suspends the thread and waits for an incoming message.
+ * @post After receiving a message the function @p chMsgGet() must be
+ * called in order to retrieve the message and then @p chMsgRelease()
+ * must be invoked in order to acknowledge the reception and send
+ * the answer.
+ * @note If the message is a pointer then you can assume that the data
+ * pointed by the message is stable until you invoke @p chMsgRelease()
+ * because the sending thread is suspended until then.
+ * @note The reference counter of the sender thread is not increased, the
+ * returned pointer is a temporary reference.
+ *
+ * @return A pointer to the thread carrying the message.
+ *
+ * @api
+ */
+static inline thread_t *chMsgWait(void) {
+ thread_t *tp;
+
+ chSysLock();
+ tp = chMsgWaitS();
+ chSysUnlock();
+
+ return tp;
+}
+
+/**
+ * @brief Suspends the thread and waits for an incoming message or a
+ * timeout to occur.
+ * @post After receiving a message the function @p chMsgGet() must be
+ * called in order to retrieve the message and then @p chMsgRelease()
+ * must be invoked in order to acknowledge the reception and send
+ * the answer.
+ * @note If the message is a pointer then you can assume that the data
+ * pointed by the message is stable until you invoke @p chMsgRelease()
+ * because the sending thread is suspended until then.
+ * @note The reference counter of the sender thread is not increased, the
+ * returned pointer is a temporary reference.
+ *
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A pointer to the thread carrying the message.
+ * @retval NULL if a timeout occurred.
+ *
+ * @api
+ */
+static inline thread_t *chMsgWaitTimeout(sysinterval_t timeout) {
+ thread_t *tp;
+
+ chSysLock();
+ tp = chMsgWaitTimeoutS(timeout);
+ chSysUnlock();
+
+ return tp;
+}
+
+/**
+ * @brief Poll to check for an incoming message.
+ * @post If a message is available the function @p chMsgGet() must be
+ * called in order to retrieve the message and then @p chMsgRelease()
+ * must be invoked in order to acknowledge the reception and send
+ * the answer.
+ * @note If the message is a pointer then you can assume that the data
+ * pointed by the message is stable until you invoke @p chMsgRelease()
+ * because the sending thread is suspended until then.
+ * @note The reference counter of the sender thread is not increased, the
+ * returned pointer is a temporary reference.
+ *
+ * @return A pointer to the thread carrying the message.
+ * @retval NULL if no incoming message waiting.
+ *
+ * @api
+ */
+static inline thread_t *chMsgPoll(void) {
+ thread_t *tp;
+
+ chSysLock();
+ tp = chMsgPollS();
+ chSysUnlock();
+
+ return tp;
+}
+
+/**
+ * @brief Evaluates to @p true if the thread has pending messages.
+ *
+ * @param[in] tp pointer to the thread
+ * @return The pending messages status.
+ *
+ * @iclass
+ */
+static inline bool chMsgIsPendingI(thread_t *tp) {
+
+ chDbgCheckClassI();
+
+ return (bool)(tp->msgqueue.next != (thread_t *)&tp->msgqueue);
+}
+
+/**
+ * @brief Returns the message carried by the specified thread.
+ * @pre This function must be invoked immediately after exiting a call
+ * to @p chMsgWait().
+ *
+ * @param[in] tp pointer to the thread
+ * @return The message carried by the sender.
+ *
+ * @api
+ */
+static inline msg_t chMsgGet(thread_t *tp) {
+
+ chDbgAssert(tp->state == CH_STATE_SNDMSG, "invalid state");
+
+ return tp->u.sentmsg;
+}
+
+/**
+ * @brief Releases the thread waiting on top of the messages queue.
+ * @pre Invoke this function only after a message has been received
+ * using @p chMsgWait().
+ *
+ * @param[in] tp pointer to the thread
+ * @param[in] msg message to be returned to the sender
+ *
+ * @sclass
+ */
+static inline void chMsgReleaseS(thread_t *tp, msg_t msg) {
+
+ chDbgCheckClassS();
+
+ chSchWakeupS(tp, msg);
+}
+
+#endif /* CH_CFG_USE_MESSAGES == TRUE */
+
+#endif /* CHMSG_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chmtx.h b/ChibiOS_20.3.2/os/rt/include/chmtx.h
new file mode 100644
index 0000000..6fa17f7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chmtx.h
@@ -0,0 +1,168 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/chmtx.h
+ * @brief Mutexes macros and structures.
+ *
+ * @addtogroup mutexes
+ * @{
+ */
+
+#ifndef CHMTX_H
+#define CHMTX_H
+
+#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a mutex structure.
+ */
+typedef struct ch_mutex mutex_t;
+
+/**
+ * @brief Mutex structure.
+ */
+struct ch_mutex {
+ threads_queue_t queue; /**< @brief Queue of the threads sleeping
+ on this mutex. */
+ thread_t *owner; /**< @brief Owner @p thread_t pointer or
+ @p NULL. */
+ mutex_t *next; /**< @brief Next @p mutex_t into an
+ owner-list or @p NULL. */
+#if (CH_CFG_USE_MUTEXES_RECURSIVE == TRUE) || defined(__DOXYGEN__)
+ cnt_t cnt; /**< @brief Mutex recursion counter. */
+#endif
+};
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Data part of a static mutex initializer.
+ * @details This macro should be used when statically initializing a mutex
+ * that is part of a bigger structure.
+ *
+ * @param[in] name the name of the mutex variable
+ */
+#if (CH_CFG_USE_MUTEXES_RECURSIVE == TRUE) || defined(__DOXYGEN__)
+#define _MUTEX_DATA(name) {_THREADS_QUEUE_DATA(name.queue), NULL, NULL, 0}
+#else
+#define _MUTEX_DATA(name) {_THREADS_QUEUE_DATA(name.queue), NULL, NULL}
+#endif
+
+/**
+ * @brief Static mutex initializer.
+ * @details Statically initialized mutexes require no explicit initialization
+ * using @p chMtxInit().
+ *
+ * @param[in] name the name of the mutex variable
+ */
+#define MUTEX_DECL(name) mutex_t name = _MUTEX_DATA(name)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chMtxObjectInit(mutex_t *mp);
+ void chMtxLock(mutex_t *mp);
+ void chMtxLockS(mutex_t *mp);
+ bool chMtxTryLock(mutex_t *mp);
+ bool chMtxTryLockS(mutex_t *mp);
+ void chMtxUnlock(mutex_t *mp);
+ void chMtxUnlockS(mutex_t *mp);
+ void chMtxUnlockAll(void);
+ void chMtxUnlockAllS(void);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Returns @p true if the mutex queue contains at least a waiting
+ * thread.
+ *
+ * @param[out] mp pointer to a @p mutex_t structure
+ * @return The mutex queue status.
+ *
+ * @sclass
+ */
+static inline bool chMtxQueueNotEmptyS(mutex_t *mp) {
+
+ chDbgCheckClassS();
+
+ return queue_notempty(&mp->queue);
+}
+
+/**
+ * @brief Returns the mutex owner thread.
+ *
+ * @param[out] mp pointer to a @p mutex_t structure
+ * @return The owner thread.
+ * @retval NULL if the mutex is not owned.
+ *
+ * @iclass
+ */
+static inline thread_t *chMtxGetOwnerI(mutex_t *mp) {
+
+ chDbgCheckClassI();
+
+ return mp->owner;
+}
+
+/**
+ * @brief Returns the next mutex in the mutexes stack of the current thread.
+ *
+ * @return A pointer to the next mutex in the stack.
+ * @retval NULL if the stack is empty.
+ *
+ * @xclass
+ */
+static inline mutex_t *chMtxGetNextMutexX(void) {
+
+ return chThdGetSelfX()->mtxlist;
+}
+
+#endif /* CH_CFG_USE_MUTEXES == TRUE */
+
+#endif /* CHMTX_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chregistry.h b/ChibiOS_20.3.2/os/rt/include/chregistry.h
new file mode 100644
index 0000000..4c36fe7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chregistry.h
@@ -0,0 +1,185 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/chregistry.h
+ * @brief Threads registry macros and structures.
+ *
+ * @addtogroup registry
+ * @{
+ */
+
+#ifndef CHREGISTRY_H
+#define CHREGISTRY_H
+
+#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief ChibiOS/RT memory signature record.
+ */
+typedef struct {
+ char identifier[4]; /**< @brief Always set to "main". */
+ uint8_t zero; /**< @brief Must be zero. */
+ uint8_t size; /**< @brief Size of this structure. */
+ uint16_t version; /**< @brief Encoded ChibiOS/RT version. */
+ uint8_t ptrsize; /**< @brief Size of a pointer. */
+ uint8_t timesize; /**< @brief Size of a @p systime_t. */
+ uint8_t threadsize; /**< @brief Size of a @p thread_t. */
+ uint8_t off_prio; /**< @brief Offset of @p prio field. */
+ uint8_t off_ctx; /**< @brief Offset of @p ctx field. */
+ uint8_t off_newer; /**< @brief Offset of @p newer field. */
+ uint8_t off_older; /**< @brief Offset of @p older field. */
+ uint8_t off_name; /**< @brief Offset of @p name field. */
+ uint8_t off_stklimit; /**< @brief Offset of @p stklimit field.*/
+ uint8_t off_state; /**< @brief Offset of @p state field. */
+ uint8_t off_flags; /**< @brief Offset of @p flags field. */
+ uint8_t off_refs; /**< @brief Offset of @p refs field. */
+ uint8_t off_preempt; /**< @brief Offset of @p preempt field. */
+ uint8_t off_time; /**< @brief Offset of @p time field. */
+} chdebug_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Removes a thread from the registry list.
+ * @note This macro is not meant for use in application code.
+ *
+ * @param[in] tp thread to remove from the registry
+ */
+#define REG_REMOVE(tp) { \
+ (tp)->older->newer = (tp)->newer; \
+ (tp)->newer->older = (tp)->older; \
+}
+
+/**
+ * @brief Adds a thread to the registry list.
+ * @note This macro is not meant for use in application code.
+ *
+ * @param[in] tp thread to add to the registry
+ */
+#define REG_INSERT(tp) { \
+ (tp)->newer = (thread_t *)&ch.rlist; \
+ (tp)->older = ch.rlist.older; \
+ (tp)->older->newer = (tp); \
+ ch.rlist.older = (tp); \
+}
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ extern ROMCONST chdebug_t ch_debug;
+ thread_t *chRegFirstThread(void);
+ thread_t *chRegNextThread(thread_t *tp);
+ thread_t *chRegFindThreadByName(const char *name);
+ thread_t *chRegFindThreadByPointer(thread_t *tp);
+ thread_t *chRegFindThreadByWorkingArea(stkalign_t *wa);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CH_CFG_USE_REGISTRY == TRUE */
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Sets the current thread name.
+ * @pre This function only stores the pointer to the name if the option
+ * @p CH_CFG_USE_REGISTRY is enabled else no action is performed.
+ *
+ * @param[in] name thread name as a zero terminated string
+ *
+ * @api
+ */
+static inline void chRegSetThreadName(const char *name) {
+
+#if CH_CFG_USE_REGISTRY == TRUE
+ ch.rlist.current->name = name;
+#else
+ (void)name;
+#endif
+}
+
+/**
+ * @brief Returns the name of the specified thread.
+ * @pre This function only returns the pointer to the name if the option
+ * @p CH_CFG_USE_REGISTRY is enabled else @p NULL is returned.
+ *
+ * @param[in] tp pointer to the thread
+ *
+ * @return Thread name as a zero terminated string.
+ * @retval NULL if the thread name has not been set.
+ *
+ */
+static inline const char *chRegGetThreadNameX(thread_t *tp) {
+
+#if CH_CFG_USE_REGISTRY == TRUE
+ return tp->name;
+#else
+ (void)tp;
+ return NULL;
+#endif
+}
+
+/**
+ * @brief Changes the name of the specified thread.
+ * @pre This function only stores the pointer to the name if the option
+ * @p CH_CFG_USE_REGISTRY is enabled else no action is performed.
+ *
+ * @param[in] tp pointer to the thread
+ * @param[in] name thread name as a zero terminated string
+ *
+ * @xclass
+ */
+static inline void chRegSetThreadNameX(thread_t *tp, const char *name) {
+
+#if CH_CFG_USE_REGISTRY == TRUE
+ tp->name = name;
+#else
+ (void)tp;
+ (void)name;
+#endif
+}
+
+#endif /* CHREGISTRY_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chrestrictions.h b/ChibiOS_20.3.2/os/rt/include/chrestrictions.h
new file mode 100644
index 0000000..7c1840f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chrestrictions.h
@@ -0,0 +1,118 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/chrestrictions.h
+ * @brief Licensing restrictions header.
+ *
+ * @addtogroup rt_restrictions
+ * @details This module is responsible for applying license-related
+ * restrictions to the configuration options.
+ * @{
+ */
+
+#ifndef CHRESTRICTIONS_H
+#define CHRESTRICTIONS_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* License checks.*/
+#if !defined(CH_CUSTOMER_LIC_RT) || !defined(CH_LICENSE_FEATURES)
+#error "malformed chlicense.h"
+#endif
+
+#if CH_CUSTOMER_LIC_RT == FALSE
+#error "ChibiOS/RT not licensed"
+#endif
+
+#if (CH_LICENSE_FEATURES != CH_FEATURES_FULL) && \
+ (CH_LICENSE_FEATURES != CH_FEATURES_INTERMEDIATE) && \
+ (CH_LICENSE_FEATURES != CH_FEATURES_BASIC)
+#error "invalid CH_LICENSE_FEATURES setting"
+#endif
+
+/* Restrictions in basic and intermediate modes.*/
+#if (CH_LICENSE_FEATURES == CH_FEATURES_INTERMEDIATE) || \
+ (CH_LICENSE_FEATURES == CH_FEATURES_BASIC)
+
+/* System tick limited to 1000hz.*/
+#if CH_CFG_ST_FREQUENCY > 1000
+#undef CH_CFG_ST_FREQUENCY
+#define CH_CFG_ST_FREQUENCY 1000
+#endif
+
+/* Restricted subsystems.*/
+#undef CH_DBG_STATISTICS
+#undef CH_DBG_TRACE_MASK
+
+#define CH_DBG_STATISTICS FALSE
+#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED
+
+#endif /* (CH_LICENSE_FEATURES == CH_FEATURES_INTERMEDIATE) ||
+ (CH_LICENSE_FEATURES == CH_FEATURES_BASIC) */
+
+/* Restrictions in basic mode.*/
+#if CH_LICENSE_FEATURES == CH_FEATURES_BASIC
+
+/* Tick-Less mode restricted.*/
+#undef CH_CFG_ST_TIMEDELTA
+#define CH_CFG_ST_TIMEDELTA 0
+
+/* Restricted subsystems.*/
+#undef CH_CFG_USE_TM
+#undef CH_CFG_USE_MUTEXES
+#undef CH_CFG_USE_CONDVARS
+#undef CH_CFG_USE_DYNAMIC
+
+#define CH_CFG_USE_TM FALSE
+#define CH_CFG_USE_MUTEXES FALSE
+#define CH_CFG_USE_CONDVARS FALSE
+#define CH_CFG_USE_DYNAMIC FALSE
+
+#endif /* CH_LICENSE_FEATURES == CH_FEATURES_BASIC */
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* CHRESTRICTIONS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chschd.h b/ChibiOS_20.3.2/os/rt/include/chschd.h
new file mode 100644
index 0000000..edff108
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chschd.h
@@ -0,0 +1,716 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/chschd.h
+ * @brief Scheduler macros and structures.
+ *
+ * @addtogroup scheduler
+ * @{
+ */
+
+#ifndef CHSCHD_H
+#define CHSCHD_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Wakeup status codes
+ * @{
+ */
+#define MSG_OK (msg_t)0 /**< @brief Normal wakeup message. */
+#define MSG_TIMEOUT (msg_t)-1 /**< @brief Wakeup caused by a timeout
+ condition. */
+#define MSG_RESET (msg_t)-2 /**< @brief Wakeup caused by a reset
+ condition. */
+/** @} */
+
+/**
+ * @name Priority constants
+ * @{
+ */
+#define NOPRIO (tprio_t)0 /**< @brief Ready list header
+ priority. */
+#define IDLEPRIO (tprio_t)1 /**< @brief Idle priority. */
+#define LOWPRIO (tprio_t)2 /**< @brief Lowest priority. */
+#define NORMALPRIO (tprio_t)128 /**< @brief Normal priority. */
+#define HIGHPRIO (tprio_t)255 /**< @brief Highest priority. */
+/** @} */
+
+/**
+ * @name Thread states
+ * @{
+ */
+#define CH_STATE_READY (tstate_t)0 /**< @brief Waiting on the
+ ready list. */
+#define CH_STATE_CURRENT (tstate_t)1 /**< @brief Currently running. */
+#define CH_STATE_WTSTART (tstate_t)2 /**< @brief Just created. */
+#define CH_STATE_SUSPENDED (tstate_t)3 /**< @brief Suspended state. */
+#define CH_STATE_QUEUED (tstate_t)4 /**< @brief On a queue. */
+#define CH_STATE_WTSEM (tstate_t)5 /**< @brief On a semaphore. */
+#define CH_STATE_WTMTX (tstate_t)6 /**< @brief On a mutex. */
+#define CH_STATE_WTCOND (tstate_t)7 /**< @brief On a cond.variable.*/
+#define CH_STATE_SLEEPING (tstate_t)8 /**< @brief Sleeping. */
+#define CH_STATE_WTEXIT (tstate_t)9 /**< @brief Waiting a thread. */
+#define CH_STATE_WTOREVT (tstate_t)10 /**< @brief One event. */
+#define CH_STATE_WTANDEVT (tstate_t)11 /**< @brief Several events. */
+#define CH_STATE_SNDMSGQ (tstate_t)12 /**< @brief Sending a message,
+ in queue. */
+#define CH_STATE_SNDMSG (tstate_t)13 /**< @brief Sent a message,
+ waiting answer. */
+#define CH_STATE_WTMSG (tstate_t)14 /**< @brief Waiting for a
+ message. */
+#define CH_STATE_FINAL (tstate_t)15 /**< @brief Thread terminated. */
+
+/**
+ * @brief Thread states as array of strings.
+ * @details Each element in an array initialized with this macro can be
+ * indexed using the numeric thread state values.
+ */
+#define CH_STATE_NAMES \
+ "READY", "CURRENT", "WTSTART", "SUSPENDED", "QUEUED", "WTSEM", "WTMTX", \
+ "WTCOND", "SLEEPING", "WTEXIT", "WTOREVT", "WTANDEVT", "SNDMSGQ", \
+ "SNDMSG", "WTMSG", "FINAL"
+/** @} */
+
+/**
+ * @name Thread flags and attributes
+ * @{
+ */
+#define CH_FLAG_MODE_MASK (tmode_t)3U /**< @brief Thread memory mode
+ mask. */
+#define CH_FLAG_MODE_STATIC (tmode_t)0U /**< @brief Static thread. */
+#define CH_FLAG_MODE_HEAP (tmode_t)1U /**< @brief Thread allocated
+ from a Memory Heap. */
+#define CH_FLAG_MODE_MPOOL (tmode_t)2U /**< @brief Thread allocated
+ from a Memory Pool. */
+#define CH_FLAG_TERMINATE (tmode_t)4U /**< @brief Termination requested
+ flag. */
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Generic threads single link list, it works like a stack.
+ */
+struct ch_threads_list {
+ thread_t *next; /**< @brief Next in the list/queue. */
+};
+
+/**
+ * @brief Generic threads bidirectional linked list header and element.
+ */
+struct ch_threads_queue {
+ thread_t *next; /**< @brief Next in the list/queue. */
+ thread_t *prev; /**< @brief Previous in the queue. */
+};
+
+/**
+ * @brief Structure representing a thread.
+ * @note Not all the listed fields are always needed, by switching off some
+ * not needed ChibiOS/RT subsystems it is possible to save RAM space
+ * by shrinking this structure.
+ */
+struct ch_thread {
+ threads_queue_t queue; /**< @brief Threads queue header. */
+ tprio_t prio; /**< @brief Thread priority. */
+ struct port_context ctx; /**< @brief Processor context. */
+#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
+ thread_t *newer; /**< @brief Newer registry element. */
+ thread_t *older; /**< @brief Older registry element. */
+#endif
+ /* End of the fields shared with the ReadyList structure. */
+#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Thread name or @p NULL.
+ */
+ const char *name;
+#endif
+#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE) || \
+ defined(__DOXYGEN__)
+ /**
+ * @brief Working area base address.
+ * @note This pointer is used for stack overflow checks and for
+ * dynamic threading.
+ */
+ stkalign_t *wabase;
+#endif
+ /**
+ * @brief Current thread state.
+ */
+ tstate_t state;
+ /**
+ * @brief Various thread flags.
+ */
+ tmode_t flags;
+#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief References to this thread.
+ */
+ trefs_t refs;
+#endif
+ /**
+ * @brief Number of ticks remaining to this thread.
+ */
+#if (CH_CFG_TIME_QUANTUM > 0) || defined(__DOXYGEN__)
+ tslices_t ticks;
+#endif
+#if (CH_DBG_THREADS_PROFILING == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Thread consumed time in ticks.
+ * @note This field can overflow.
+ */
+ volatile systime_t time;
+#endif
+ /**
+ * @brief State-specific fields.
+ * @note All the fields declared in this union are only valid in the
+ * specified state or condition and are thus volatile.
+ */
+ union {
+ /**
+ * @brief Thread wakeup code.
+ * @note This field contains the low level message sent to the thread
+ * by the waking thread or interrupt handler. The value is valid
+ * after exiting the @p chSchWakeupS() function.
+ */
+ msg_t rdymsg;
+ /**
+ * @brief Thread exit code.
+ * @note The thread termination code is stored in this field in order
+ * to be retrieved by the thread performing a @p chThdWait() on
+ * this thread.
+ */
+ msg_t exitcode;
+ /**
+ * @brief Pointer to a generic "wait" object.
+ * @note This field is used to get a generic pointer to a synchronization
+ * object and is valid when the thread is in one of the wait
+ * states.
+ */
+ void *wtobjp;
+ /**
+ * @brief Pointer to a generic thread reference object.
+ * @note This field is used to get a pointer to a synchronization
+ * object and is valid when the thread is in @p CH_STATE_SUSPENDED
+ * state.
+ */
+ thread_reference_t *wttrp;
+#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Thread sent message.
+ */
+ msg_t sentmsg;
+#endif
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Pointer to a generic semaphore object.
+ * @note This field is used to get a pointer to a synchronization
+ * object and is valid when the thread is in @p CH_STATE_WTSEM
+ * state.
+ */
+ struct ch_semaphore *wtsemp;
+#endif
+#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Pointer to a generic mutex object.
+ * @note This field is used to get a pointer to a synchronization
+ * object and is valid when the thread is in @p CH_STATE_WTMTX
+ * state.
+ */
+ struct ch_mutex *wtmtxp;
+#endif
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Enabled events mask.
+ * @note This field is only valid while the thread is in the
+ * @p CH_STATE_WTOREVT or @p CH_STATE_WTANDEVT states.
+ */
+ eventmask_t ewmask;
+#endif
+ } u;
+#if (CH_CFG_USE_WAITEXIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Termination waiting list.
+ */
+ threads_list_t waiting;
+#endif
+#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Messages queue.
+ */
+ threads_queue_t msgqueue;
+#endif
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Pending events mask.
+ */
+ eventmask_t epending;
+#endif
+#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief List of the mutexes owned by this thread.
+ * @note The list is terminated by a @p NULL in this field.
+ */
+ struct ch_mutex *mtxlist;
+ /**
+ * @brief Thread's own, non-inherited, priority.
+ */
+ tprio_t realprio;
+#endif
+#if ((CH_CFG_USE_DYNAMIC == TRUE) && (CH_CFG_USE_MEMPOOLS == TRUE)) || \
+ defined(__DOXYGEN__)
+ /**
+ * @brief Memory Pool where the thread workspace is returned.
+ */
+ void *mpool;
+#endif
+#if (CH_DBG_STATISTICS == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Thread statistics.
+ */
+ time_measurement_t stats;
+#endif
+#if defined(CH_CFG_THREAD_EXTRA_FIELDS)
+ /* Extra fields defined in chconf.h.*/
+ CH_CFG_THREAD_EXTRA_FIELDS
+#endif
+};
+
+/**
+ * @extends virtual_timers_list_t
+ *
+ * @brief Virtual Timer descriptor structure.
+ */
+struct ch_virtual_timer {
+ virtual_timer_t *next; /**< @brief Next timer in the list. */
+ virtual_timer_t *prev; /**< @brief Previous timer in the list. */
+ sysinterval_t delta; /**< @brief Time delta before timeout. */
+ vtfunc_t func; /**< @brief Timer callback function
+ pointer. */
+ void *par; /**< @brief Timer callback function
+ parameter. */
+};
+
+/**
+ * @brief Virtual timers list header.
+ * @note The timers list is implemented as a double link bidirectional list
+ * in order to make the unlink time constant, the reset of a virtual
+ * timer is often used in the code.
+ */
+struct ch_virtual_timers_list {
+ virtual_timer_t *next; /**< @brief Next timer in the delta
+ list. */
+ virtual_timer_t *prev; /**< @brief Last timer in the delta
+ list. */
+ sysinterval_t delta; /**< @brief Must be initialized to -1. */
+#if (CH_CFG_ST_TIMEDELTA == 0) || defined(__DOXYGEN__)
+ volatile systime_t systime; /**< @brief System Time counter. */
+#endif
+#if (CH_CFG_ST_TIMEDELTA > 0) || defined(__DOXYGEN__)
+ /**
+ * @brief System time of the last tick event.
+ */
+ systime_t lasttime; /**< @brief System time of the last
+ tick event. */
+#endif
+};
+
+/**
+ * @extends threads_queue_t
+ */
+struct ch_ready_list {
+ threads_queue_t queue; /**< @brief Threads queue. */
+ tprio_t prio; /**< @brief This field must be
+ initialized to zero. */
+ struct port_context ctx; /**< @brief Not used, present because
+ offsets. */
+#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
+ thread_t *newer; /**< @brief Newer registry element. */
+ thread_t *older; /**< @brief Older registry element. */
+#endif
+ /* End of the fields shared with the thread_t structure.*/
+ thread_t *current; /**< @brief The currently running
+ thread. */
+};
+
+/**
+ * @brief System debug data structure.
+ */
+struct ch_system_debug {
+ /**
+ * @brief Pointer to the panic message.
+ * @details This pointer is meant to be accessed through the debugger, it is
+ * written once and then the system is halted.
+ * @note Accesses to this pointer must never be optimized out so the
+ * field itself is declared volatile.
+ */
+ const char * volatile panic_msg;
+#if (CH_DBG_SYSTEM_STATE_CHECK == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief ISR nesting level.
+ */
+ cnt_t isr_cnt;
+ /**
+ * @brief Lock nesting level.
+ */
+ cnt_t lock_cnt;
+#endif
+#if (CH_DBG_TRACE_MASK != CH_DBG_TRACE_MASK_DISABLED) || defined(__DOXYGEN__)
+ /**
+ * @brief Public trace buffer.
+ */
+ ch_trace_buffer_t trace_buffer;
+#endif
+};
+
+/**
+ * @brief System data structure.
+ * @note This structure contain all the data areas used by the OS except
+ * stacks.
+ */
+struct ch_system {
+ /**
+ * @brief Ready list header.
+ */
+ ready_list_t rlist;
+ /**
+ * @brief Virtual timers delta list header.
+ */
+ virtual_timers_list_t vtlist;
+ /**
+ * @brief System debug.
+ */
+ system_debug_t dbg;
+ /**
+ * @brief Main thread descriptor.
+ */
+ thread_t mainthread;
+#if (CH_CFG_USE_TM == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Time measurement calibration data.
+ */
+ tm_calibration_t tm;
+#endif
+#if (CH_DBG_STATISTICS == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Global kernel statistics.
+ */
+ kernel_stats_t kernel_stats;
+#endif
+ CH_CFG_SYSTEM_EXTRA_FIELDS
+};
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Returns the priority of the first thread on the given ready list.
+ *
+ * @notapi
+ */
+#define firstprio(rlp) ((rlp)->next->prio)
+
+/**
+ * @brief Current thread pointer access macro.
+ * @note This macro is not meant to be used in the application code but
+ * only from within the kernel, use @p chThdGetSelfX() instead.
+ */
+#define currp ch.rlist.current
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern ch_system_t ch;
+#endif
+
+/*
+ * Scheduler APIs.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void _scheduler_init(void);
+ thread_t *chSchReadyI(thread_t *tp);
+ thread_t *chSchReadyAheadI(thread_t *tp);
+ void chSchGoSleepS(tstate_t newstate);
+ msg_t chSchGoSleepTimeoutS(tstate_t newstate, sysinterval_t timeout);
+ void chSchWakeupS(thread_t *ntp, msg_t msg);
+ void chSchRescheduleS(void);
+ bool chSchIsPreemptionRequired(void);
+ void chSchDoRescheduleBehind(void);
+ void chSchDoRescheduleAhead(void);
+ void chSchDoReschedule(void);
+#if CH_CFG_OPTIMIZE_SPEED == FALSE
+ void queue_prio_insert(thread_t *tp, threads_queue_t *tqp);
+ void queue_insert(thread_t *tp, threads_queue_t *tqp);
+ thread_t *queue_fifo_remove(threads_queue_t *tqp);
+ thread_t *queue_lifo_remove(threads_queue_t *tqp);
+ thread_t *queue_dequeue(thread_t *tp);
+ void list_insert(thread_t *tp, threads_list_t *tlp);
+ thread_t *list_remove(threads_list_t *tlp);
+#endif /* CH_CFG_OPTIMIZE_SPEED == FALSE */
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Threads list initialization.
+ *
+ * @param[in] tlp pointer to the threads list object
+ *
+ * @notapi
+ */
+static inline void list_init(threads_list_t *tlp) {
+
+ tlp->next = (thread_t *)tlp;
+}
+
+/**
+ * @brief Evaluates to @p true if the specified threads list is empty.
+ *
+ * @param[in] tlp pointer to the threads list object
+ * @return The status of the list.
+ *
+ * @notapi
+ */
+static inline bool list_isempty(threads_list_t *tlp) {
+
+ return (bool)(tlp->next == (thread_t *)tlp);
+}
+
+/**
+ * @brief Evaluates to @p true if the specified threads list is not empty.
+ *
+ * @param[in] tlp pointer to the threads list object
+ * @return The status of the list.
+ *
+ * @notapi
+ */
+static inline bool list_notempty(threads_list_t *tlp) {
+
+ return (bool)(tlp->next != (thread_t *)tlp);
+}
+
+/**
+ * @brief Threads queue initialization.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ *
+ * @notapi
+ */
+static inline void queue_init(threads_queue_t *tqp) {
+
+ tqp->next = (thread_t *)tqp;
+ tqp->prev = (thread_t *)tqp;
+}
+
+/**
+ * @brief Evaluates to @p true if the specified threads queue is empty.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @return The status of the queue.
+ *
+ * @notapi
+ */
+static inline bool queue_isempty(const threads_queue_t *tqp) {
+
+ return (bool)(tqp->next == (const thread_t *)tqp);
+}
+
+/**
+ * @brief Evaluates to @p true if the specified threads queue is not empty.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @return The status of the queue.
+ *
+ * @notapi
+ */
+static inline bool queue_notempty(const threads_queue_t *tqp) {
+
+ return (bool)(tqp->next != (const thread_t *)tqp);
+}
+
+/* If the performance code path has been chosen then all the following
+ functions are inlined into the various kernel modules.*/
+#if CH_CFG_OPTIMIZE_SPEED == TRUE
+static inline void list_insert(thread_t *tp, threads_list_t *tlp) {
+
+ tp->queue.next = tlp->next;
+ tlp->next = tp;
+}
+
+static inline thread_t *list_remove(threads_list_t *tlp) {
+
+ thread_t *tp = tlp->next;
+ tlp->next = tp->queue.next;
+
+ return tp;
+}
+
+static inline void queue_prio_insert(thread_t *tp, threads_queue_t *tqp) {
+
+ thread_t *cp = (thread_t *)tqp;
+ do {
+ cp = cp->queue.next;
+ } while ((cp != (thread_t *)tqp) && (cp->prio >= tp->prio));
+ tp->queue.next = cp;
+ tp->queue.prev = cp->queue.prev;
+ tp->queue.prev->queue.next = tp;
+ cp->queue.prev = tp;
+}
+
+static inline void queue_insert(thread_t *tp, threads_queue_t *tqp) {
+
+ tp->queue.next = (thread_t *)tqp;
+ tp->queue.prev = tqp->prev;
+ tp->queue.prev->queue.next = tp;
+ tqp->prev = tp;
+}
+
+static inline thread_t *queue_fifo_remove(threads_queue_t *tqp) {
+ thread_t *tp = tqp->next;
+
+ tqp->next = tp->queue.next;
+ tqp->next->queue.prev = (thread_t *)tqp;
+
+ return tp;
+}
+
+static inline thread_t *queue_lifo_remove(threads_queue_t *tqp) {
+ thread_t *tp = tqp->prev;
+
+ tqp->prev = tp->queue.prev;
+ tqp->prev->queue.next = (thread_t *)tqp;
+
+ return tp;
+}
+
+static inline thread_t *queue_dequeue(thread_t *tp) {
+
+ tp->queue.prev->queue.next = tp->queue.next;
+ tp->queue.next->queue.prev = tp->queue.prev;
+
+ return tp;
+}
+#endif /* CH_CFG_OPTIMIZE_SPEED == TRUE */
+
+/**
+ * @brief Determines if the current thread must reschedule.
+ * @details This function returns @p true if there is a ready thread with
+ * higher priority.
+ *
+ * @return The priorities situation.
+ * @retval false if rescheduling is not necessary.
+ * @retval true if there is a ready thread at higher priority.
+ *
+ * @iclass
+ */
+static inline bool chSchIsRescRequiredI(void) {
+
+ chDbgCheckClassI();
+
+ return firstprio(&ch.rlist.queue) > currp->prio;
+}
+
+/**
+ * @brief Determines if yielding is possible.
+ * @details This function returns @p true if there is a ready thread with
+ * equal or higher priority.
+ *
+ * @return The priorities situation.
+ * @retval false if yielding is not possible.
+ * @retval true if there is a ready thread at equal or higher priority.
+ *
+ * @sclass
+ */
+static inline bool chSchCanYieldS(void) {
+
+ chDbgCheckClassS();
+
+ return firstprio(&ch.rlist.queue) >= currp->prio;
+}
+
+/**
+ * @brief Yields the time slot.
+ * @details Yields the CPU control to the next thread in the ready list with
+ * equal or higher priority, if any.
+ *
+ * @sclass
+ */
+static inline void chSchDoYieldS(void) {
+
+ chDbgCheckClassS();
+
+ if (chSchCanYieldS()) {
+ chSchDoRescheduleBehind();
+ }
+}
+
+/**
+ * @brief Inline-able preemption code.
+ * @details This is the common preemption code, this function must be invoked
+ * exclusively from the port layer.
+ *
+ * @special
+ */
+static inline void chSchPreemption(void) {
+ tprio_t p1 = firstprio(&ch.rlist.queue);
+ tprio_t p2 = currp->prio;
+
+#if CH_CFG_TIME_QUANTUM > 0
+ if (currp->ticks > (tslices_t)0) {
+ if (p1 > p2) {
+ chSchDoRescheduleAhead();
+ }
+ }
+ else {
+ if (p1 >= p2) {
+ chSchDoRescheduleBehind();
+ }
+ }
+#else /* CH_CFG_TIME_QUANTUM == 0 */
+ if (p1 > p2) {
+ chSchDoRescheduleAhead();
+ }
+#endif /* CH_CFG_TIME_QUANTUM == 0 */
+}
+
+#endif /* CHSCHD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chsem.h b/ChibiOS_20.3.2/os/rt/include/chsem.h
new file mode 100644
index 0000000..62406ee
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chsem.h
@@ -0,0 +1,200 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/chsem.h
+ * @brief Semaphores macros and structures.
+ *
+ * @addtogroup semaphores
+ * @{
+ */
+
+#ifndef CHSEM_H
+#define CHSEM_H
+
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Semaphore structure.
+ */
+typedef struct ch_semaphore {
+ threads_queue_t queue; /**< @brief Queue of the threads sleeping
+ on this semaphore. */
+ cnt_t cnt; /**< @brief The semaphore counter. */
+} semaphore_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Data part of a static semaphore initializer.
+ * @details This macro should be used when statically initializing a semaphore
+ * that is part of a bigger structure.
+ *
+ * @param[in] name the name of the semaphore variable
+ * @param[in] n the counter initial value, this value must be
+ * non-negative
+ */
+#define _SEMAPHORE_DATA(name, n) {_THREADS_QUEUE_DATA(name.queue), n}
+
+/**
+ * @brief Static semaphore initializer.
+ * @details Statically initialized semaphores require no explicit
+ * initialization using @p chSemInit().
+ *
+ * @param[in] name the name of the semaphore variable
+ * @param[in] n the counter initial value, this value must be
+ * non-negative
+ */
+#define SEMAPHORE_DECL(name, n) semaphore_t name = _SEMAPHORE_DATA(name, n)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chSemObjectInit(semaphore_t *sp, cnt_t n);
+ void chSemResetWithMessage(semaphore_t *sp, cnt_t n, msg_t msg);
+ void chSemResetWithMessageI(semaphore_t *sp, cnt_t n, msg_t msg);
+ msg_t chSemWait(semaphore_t *sp);
+ msg_t chSemWaitS(semaphore_t *sp);
+ msg_t chSemWaitTimeout(semaphore_t *sp, sysinterval_t timeout);
+ msg_t chSemWaitTimeoutS(semaphore_t *sp, sysinterval_t timeout);
+ void chSemSignal(semaphore_t *sp);
+ void chSemSignalI(semaphore_t *sp);
+ void chSemAddCounterI(semaphore_t *sp, cnt_t n);
+ msg_t chSemSignalWait(semaphore_t *sps, semaphore_t *spw);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Performs a reset operation on the semaphore.
+ * @post After invoking this function all the threads waiting on the
+ * semaphore, if any, are released and the semaphore counter is set
+ * to the specified, non negative, value.
+ * @note This function implicitly sends @p MSG_RESET as message.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @param[in] n the new value of the semaphore counter. The value must
+ * be non-negative.
+ *
+ * @api
+ */
+static inline void chSemReset(semaphore_t *sp, cnt_t n) {
+
+ chSemResetWithMessage(sp, n, MSG_RESET);
+}
+
+/**
+ * @brief Performs a reset operation on the semaphore.
+ * @post After invoking this function all the threads waiting on the
+ * semaphore, if any, are released and the semaphore counter is set
+ * to the specified, non negative, value.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ * @note This function implicitly sends @p MSG_RESET as message.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @param[in] n the new value of the semaphore counter. The value must
+ * be non-negative.
+ *
+ * @iclass
+ */
+static inline void chSemResetI(semaphore_t *sp, cnt_t n) {
+
+ chSemResetWithMessageI(sp, n, MSG_RESET);
+}
+
+/**
+ * @brief Decreases the semaphore counter.
+ * @details This macro can be used when the counter is known to be positive.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ *
+ * @iclass
+ */
+static inline void chSemFastWaitI(semaphore_t *sp) {
+
+ chDbgCheckClassI();
+
+ sp->cnt--;
+}
+
+/**
+ * @brief Increases the semaphore counter.
+ * @details This macro can be used when the counter is known to be not
+ * negative.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ *
+ * @iclass
+ */
+static inline void chSemFastSignalI(semaphore_t *sp) {
+
+ chDbgCheckClassI();
+
+ sp->cnt++;
+}
+
+/**
+ * @brief Returns the semaphore counter current value.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @return The semaphore counter value.
+ *
+ * @iclass
+ */
+static inline cnt_t chSemGetCounterI(const semaphore_t *sp) {
+
+ chDbgCheckClassI();
+
+ return sp->cnt;
+}
+
+#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
+
+#endif /* CHSEM_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chstats.h b/ChibiOS_20.3.2/os/rt/include/chstats.h
new file mode 100644
index 0000000..7225ea1
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chstats.h
@@ -0,0 +1,105 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/chstats.h
+ * @brief Statistics module macros and structures.
+ *
+ * @addtogroup statistics
+ * @{
+ */
+
+#ifndef CHSTATS_H
+#define CHSTATS_H
+
+#if (CH_DBG_STATISTICS == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+#if CH_CFG_USE_TM == FALSE
+#error "CH_DBG_STATISTICS requires CH_CFG_USE_TM"
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a kernel statistics structure.
+ */
+typedef struct {
+ ucnt_t n_irq; /**< @brief Number of IRQs. */
+ ucnt_t n_ctxswc; /**< @brief Number of context switches. */
+ time_measurement_t m_crit_thd; /**< @brief Measurement of threads
+ critical zones duration. */
+ time_measurement_t m_crit_isr; /**< @brief Measurement of ISRs critical
+ zones duration. */
+} kernel_stats_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void _stats_init(void);
+ void _stats_increase_irq(void);
+ void _stats_ctxswc(thread_t *ntp, thread_t *otp);
+ void _stats_start_measure_crit_thd(void);
+ void _stats_stop_measure_crit_thd(void);
+ void _stats_start_measure_crit_isr(void);
+ void _stats_stop_measure_crit_isr(void);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#else /* CH_DBG_STATISTICS == FALSE */
+
+/* Stub functions for when the statistics module is disabled. */
+#define _stats_increase_irq()
+#define _stats_ctxswc(old, new)
+#define _stats_start_measure_crit_thd()
+#define _stats_stop_measure_crit_thd()
+#define _stats_start_measure_crit_isr()
+#define _stats_stop_measure_crit_isr()
+
+#endif /* CH_DBG_STATISTICS == FALSE */
+
+#endif /* CHSTATS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chsys.h b/ChibiOS_20.3.2/os/rt/include/chsys.h
new file mode 100644
index 0000000..afd2f36
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chsys.h
@@ -0,0 +1,469 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/chsys.h
+ * @brief System related macros and structures.
+ *
+ * @addtogroup system
+ * @{
+ */
+
+#ifndef CHSYS_H
+#define CHSYS_H
+
+/*lint -sem(chSysHalt, r_no)*/
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Masks of executable integrity checks.
+ * @{
+ */
+#define CH_INTEGRITY_RLIST 1U
+#define CH_INTEGRITY_VTLIST 2U
+#define CH_INTEGRITY_REGISTRY 4U
+#define CH_INTEGRITY_PORT 8U
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @name ISRs abstraction macros
+ */
+/**
+ * @brief Priority level validation macro.
+ * @details This macro determines if the passed value is a valid priority
+ * level for the underlying architecture.
+ *
+ * @param[in] prio the priority level
+ * @return Priority range result.
+ * @retval false if the priority is invalid or if the architecture
+ * does not support priorities.
+ * @retval true if the priority is valid.
+ */
+#if defined(PORT_IRQ_IS_VALID_PRIORITY) || defined(__DOXYGEN__)
+#define CH_IRQ_IS_VALID_PRIORITY(prio) \
+ PORT_IRQ_IS_VALID_PRIORITY(prio)
+#else
+#define CH_IRQ_IS_VALID_PRIORITY(prio) false
+#endif
+
+/**
+ * @brief Priority level validation macro.
+ * @details This macro determines if the passed value is a valid priority
+ * level that cannot preempt the kernel critical zone.
+ *
+ * @param[in] prio the priority level
+ * @return Priority range result.
+ * @retval false if the priority is invalid or if the architecture
+ * does not support priorities.
+ * @retval true if the priority is valid.
+ */
+#if defined(PORT_IRQ_IS_VALID_KERNEL_PRIORITY) || defined(__DOXYGEN__)
+#define CH_IRQ_IS_VALID_KERNEL_PRIORITY(prio) \
+ PORT_IRQ_IS_VALID_KERNEL_PRIORITY(prio)
+#else
+#define CH_IRQ_IS_VALID_KERNEL_PRIORITY(prio) false
+#endif
+
+/**
+ * @brief IRQ handler enter code.
+ * @note Usually IRQ handlers functions are also declared naked.
+ * @note On some architectures this macro can be empty.
+ *
+ * @special
+ */
+#define CH_IRQ_PROLOGUE() \
+ PORT_IRQ_PROLOGUE(); \
+ CH_CFG_IRQ_PROLOGUE_HOOK(); \
+ _stats_increase_irq(); \
+ _trace_isr_enter(__func__); \
+ _dbg_check_enter_isr()
+
+/**
+ * @brief IRQ handler exit code.
+ * @note Usually IRQ handlers function are also declared naked.
+ * @note This macro usually performs the final reschedule by using
+ * @p chSchIsPreemptionRequired() and @p chSchDoReschedule().
+ *
+ * @special
+ */
+#define CH_IRQ_EPILOGUE() \
+ _dbg_check_leave_isr(); \
+ _trace_isr_leave(__func__); \
+ CH_CFG_IRQ_EPILOGUE_HOOK(); \
+ PORT_IRQ_EPILOGUE()
+
+/**
+ * @brief Standard normal IRQ handler declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ *
+ * @special
+ */
+#define CH_IRQ_HANDLER(id) PORT_IRQ_HANDLER(id)
+/** @} */
+
+/**
+ * @name Fast ISRs abstraction macros
+ */
+/**
+ * @brief Standard fast IRQ handler declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ * @note Not all architectures support fast interrupts.
+ *
+ * @special
+ */
+#define CH_FAST_IRQ_HANDLER(id) PORT_FAST_IRQ_HANDLER(id)
+/** @} */
+
+/**
+ * @name Time conversion utilities for the realtime counter
+ * @{
+ */
+/**
+ * @brief Seconds to realtime counter.
+ * @details Converts from seconds to realtime counter cycles.
+ * @note The macro assumes that @p freq >= @p 1.
+ *
+ * @param[in] freq clock frequency, in Hz, of the realtime counter
+ * @param[in] sec number of seconds
+ * @return The number of cycles.
+ *
+ * @api
+ */
+#define S2RTC(freq, sec) ((freq) * (sec))
+
+/**
+ * @brief Milliseconds to realtime counter.
+ * @details Converts from milliseconds to realtime counter cycles.
+ * @note The result is rounded upward to the next millisecond boundary.
+ * @note The macro assumes that @p freq >= @p 1000.
+ *
+ * @param[in] freq clock frequency, in Hz, of the realtime counter
+ * @param[in] msec number of milliseconds
+ * @return The number of cycles.
+ *
+ * @api
+ */
+#define MS2RTC(freq, msec) (rtcnt_t)((((freq) + 999UL) / 1000UL) * (msec))
+
+/**
+ * @brief Microseconds to realtime counter.
+ * @details Converts from microseconds to realtime counter cycles.
+ * @note The result is rounded upward to the next microsecond boundary.
+ * @note The macro assumes that @p freq >= @p 1000000.
+ *
+ * @param[in] freq clock frequency, in Hz, of the realtime counter
+ * @param[in] usec number of microseconds
+ * @return The number of cycles.
+ *
+ * @api
+ */
+#define US2RTC(freq, usec) (rtcnt_t)((((freq) + 999999UL) / 1000000UL) * (usec))
+
+/**
+ * @brief Realtime counter cycles to seconds.
+ * @details Converts from realtime counter cycles number to seconds.
+ * @note The result is rounded up to the next second boundary.
+ * @note The macro assumes that @p freq >= @p 1.
+ *
+ * @param[in] freq clock frequency, in Hz, of the realtime counter
+ * @param[in] n number of cycles
+ * @return The number of seconds.
+ *
+ * @api
+ */
+#define RTC2S(freq, n) ((((n) - 1UL) / (freq)) + 1UL)
+
+/**
+ * @brief Realtime counter cycles to milliseconds.
+ * @details Converts from realtime counter cycles number to milliseconds.
+ * @note The result is rounded up to the next millisecond boundary.
+ * @note The macro assumes that @p freq >= @p 1000.
+ *
+ * @param[in] freq clock frequency, in Hz, of the realtime counter
+ * @param[in] n number of cycles
+ * @return The number of milliseconds.
+ *
+ * @api
+ */
+#define RTC2MS(freq, n) ((((n) - 1UL) / ((freq) / 1000UL)) + 1UL)
+
+/**
+ * @brief Realtime counter cycles to microseconds.
+ * @details Converts from realtime counter cycles number to microseconds.
+ * @note The result is rounded up to the next microsecond boundary.
+ * @note The macro assumes that @p freq >= @p 1000000.
+ *
+ * @param[in] freq clock frequency, in Hz, of the realtime counter
+ * @param[in] n number of cycles
+ * @return The number of microseconds.
+ *
+ * @api
+ */
+#define RTC2US(freq, n) ((((n) - 1UL) / ((freq) / 1000000UL)) + 1UL)
+/** @} */
+
+/**
+ * @brief Returns the current value of the system real time counter.
+ * @note This function is only available if the port layer supports the
+ * option @p PORT_SUPPORTS_RT.
+ *
+ * @return The value of the system realtime counter of
+ * type rtcnt_t.
+ *
+ * @xclass
+ */
+#if (PORT_SUPPORTS_RT == TRUE) || defined(__DOXYGEN__)
+#define chSysGetRealtimeCounterX() (rtcnt_t)port_rt_get_counter_value()
+#endif
+
+/**
+ * @brief Performs a context switch.
+ * @note Not a user function, it is meant to be invoked by the scheduler
+ * itself or from within the port layer.
+ *
+ * @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread to be switched out
+ *
+ * @special
+ */
+#define chSysSwitch(ntp, otp) { \
+ \
+ _trace_switch(ntp, otp); \
+ _stats_ctxswc(ntp, otp); \
+ CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp); \
+ port_switch(ntp, otp); \
+}
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern stkalign_t ch_idle_thread_wa[];
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chSysInit(void);
+ bool chSysIntegrityCheckI(unsigned testmask);
+ void chSysTimerHandlerI(void);
+ syssts_t chSysGetStatusAndLockX(void);
+ void chSysRestoreStatusX(syssts_t sts);
+#if PORT_SUPPORTS_RT == TRUE
+ bool chSysIsCounterWithinX(rtcnt_t cnt, rtcnt_t start, rtcnt_t end);
+ void chSysPolledDelayX(rtcnt_t cycles);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Raises the system interrupt priority mask to the maximum level.
+ * @details All the maskable interrupt sources are disabled regardless their
+ * hardware priority.
+ * @note Do not invoke this API from within a kernel lock.
+ *
+ * @special
+ */
+static inline void chSysDisable(void) {
+
+ port_disable();
+ _dbg_check_disable();
+}
+
+/**
+ * @brief Raises the system interrupt priority mask to system level.
+ * @details The interrupt sources that should not be able to preempt the kernel
+ * are disabled, interrupt sources with higher priority are still
+ * enabled.
+ * @note Do not invoke this API from within a kernel lock.
+ * @note This API is no replacement for @p chSysLock(), the @p chSysLock()
+ * could do more than just disable the interrupts.
+ *
+ * @special
+ */
+static inline void chSysSuspend(void) {
+
+ port_suspend();
+ _dbg_check_suspend();
+}
+
+/**
+ * @brief Lowers the system interrupt priority mask to user level.
+ * @details All the interrupt sources are enabled.
+ * @note Do not invoke this API from within a kernel lock.
+ * @note This API is no replacement for @p chSysUnlock(), the
+ * @p chSysUnlock() could do more than just enable the interrupts.
+ *
+ * @special
+ */
+static inline void chSysEnable(void) {
+
+ _dbg_check_enable();
+ port_enable();
+}
+
+/**
+ * @brief Enters the kernel lock state.
+ *
+ * @special
+ */
+static inline void chSysLock(void) {
+
+ port_lock();
+ _stats_start_measure_crit_thd();
+ _dbg_check_lock();
+}
+
+/**
+ * @brief Leaves the kernel lock state.
+ *
+ * @special
+ */
+static inline void chSysUnlock(void) {
+
+ _dbg_check_unlock();
+ _stats_stop_measure_crit_thd();
+
+ /* The following condition can be triggered by the use of i-class functions
+ in a critical section not followed by a chSchRescheduleS(), this means
+ that the current thread has a lower priority than the next thread in
+ the ready list.*/
+ chDbgAssert((ch.rlist.queue.next == (thread_t *)&ch.rlist.queue) ||
+ (ch.rlist.current->prio >= ch.rlist.queue.next->prio),
+ "priority order violation");
+
+ port_unlock();
+}
+
+/**
+ * @brief Enters the kernel lock state from within an interrupt handler.
+ * @note This API may do nothing on some architectures, it is required
+ * because on ports that support preemptable interrupt handlers
+ * it is required to raise the interrupt mask to the same level of
+ * the system mutual exclusion zone.
+ * It is good practice to invoke this API before invoking any I-class
+ * syscall from an interrupt handler.
+ * @note This API must be invoked exclusively from interrupt handlers.
+ *
+ * @special
+ */
+static inline void chSysLockFromISR(void) {
+
+ port_lock_from_isr();
+ _stats_start_measure_crit_isr();
+ _dbg_check_lock_from_isr();
+}
+
+/**
+ * @brief Leaves the kernel lock state from within an interrupt handler.
+ *
+ * @note This API may do nothing on some architectures, it is required
+ * because on ports that support preemptable interrupt handlers
+ * it is required to raise the interrupt mask to the same level of
+ * the system mutual exclusion zone.
+ * It is good practice to invoke this API after invoking any I-class
+ * syscall from an interrupt handler.
+ * @note This API must be invoked exclusively from interrupt handlers.
+ *
+ * @special
+ */
+static inline void chSysUnlockFromISR(void) {
+
+ _dbg_check_unlock_from_isr();
+ _stats_stop_measure_crit_isr();
+ port_unlock_from_isr();
+}
+
+/**
+ * @brief Unconditionally enters the kernel lock state.
+ * @note Can be called without previous knowledge of the current lock state.
+ * The final state is "s-locked".
+ *
+ * @special
+ */
+static inline void chSysUnconditionalLock(void) {
+
+ if (port_irq_enabled(port_get_irq_status())) {
+ chSysLock();
+ }
+}
+
+/**
+ * @brief Unconditionally leaves the kernel lock state.
+ * @note Can be called without previous knowledge of the current lock state.
+ * The final state is "normal".
+ *
+ * @special
+ */
+static inline void chSysUnconditionalUnlock(void) {
+
+ if (!port_irq_enabled(port_get_irq_status())) {
+ chSysUnlock();
+ }
+}
+
+#if (CH_CFG_NO_IDLE_THREAD == FALSE) || defined(__DOXYGEN__)
+/**
+ * @brief Returns a pointer to the idle thread.
+ * @pre In order to use this function the option @p CH_CFG_NO_IDLE_THREAD
+ * must be disabled.
+ * @note The reference counter of the idle thread is not incremented but
+ * it is not strictly required being the idle thread a static
+ * object.
+ *
+ * @return Pointer to the idle thread.
+ *
+ * @xclass
+ */
+static inline thread_t *chSysGetIdleThreadX(void) {
+
+ return ch.rlist.queue.prev;
+}
+#endif /* CH_CFG_NO_IDLE_THREAD == FALSE */
+
+#endif /* CHSYS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chsystypes.h b/ChibiOS_20.3.2/os/rt/include/chsystypes.h
new file mode 100644
index 0000000..7ca9159
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chsystypes.h
@@ -0,0 +1,130 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/chsystypes.h
+ * @brief System types header.
+ *
+ * @addtogroup scheduler
+ * @{
+ */
+
+#ifndef CHSYSTYPES_H
+#define CHSYSTYPES_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @extends threads_queue_t
+ *
+ * @brief Type of a thread structure.
+ */
+typedef struct ch_thread thread_t;
+
+/**
+ * @brief Type of a thread reference.
+ */
+typedef thread_t * thread_reference_t;
+
+/**
+ * @brief Type of a generic threads single link list, it works like a stack.
+ */
+typedef struct ch_threads_list threads_list_t;
+
+/**
+ * @extends threads_list_t
+ *
+ * @brief Type of a generic threads bidirectional linked list header and element.
+ */
+typedef struct ch_threads_queue threads_queue_t;
+
+/**
+ * @extends threads_queue_t
+ *
+ * @brief Type of a ready list header.
+ */
+typedef struct ch_ready_list ready_list_t;
+
+/**
+ * @brief Type of a Virtual Timer callback function.
+ */
+typedef void (*vtfunc_t)(void *p);
+
+/**
+ * @brief Type of a Virtual Timer structure.
+ */
+typedef struct ch_virtual_timer virtual_timer_t;
+
+/**
+ * @brief Type of virtual timers list header.
+ */
+typedef struct ch_virtual_timers_list virtual_timers_list_t;
+
+/**
+ * @brief Type of a system debug structure.
+ */
+typedef struct ch_system_debug system_debug_t;
+
+/**
+ * @brief Type of system data structure.
+ */
+typedef struct ch_system ch_system_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Utility to make the parameter a quoted string.
+ */
+#define __CH_STRINGIFY(a) #a
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* CHSYSTYPES_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chthreads.h b/ChibiOS_20.3.2/os/rt/include/chthreads.h
new file mode 100644
index 0000000..74f8952
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chthreads.h
@@ -0,0 +1,440 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/chthreads.h
+ * @brief Threads module macros and structures.
+ *
+ * @addtogroup threads
+ * @{
+ */
+
+#ifndef CHTHREADS_H
+#define CHTHREADS_H
+
+/*lint -sem(chThdExit, r_no) -sem(chThdExitS, r_no)*/
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Thread function.
+ */
+typedef void (*tfunc_t)(void *p);
+
+/**
+ * @brief Type of a thread descriptor.
+ */
+typedef struct {
+ /**
+ * @brief Thread name.
+ */
+ const char *name;
+ /**
+ * @brief Pointer to the working area base.
+ */
+ stkalign_t *wbase;
+ /**
+ * @brief End of the working area.
+ */
+ stkalign_t *wend;
+ /**
+ * @brief Thread priority.
+ */
+ tprio_t prio;
+ /**
+ * @brief Thread function pointer.
+ */
+ tfunc_t funcp;
+ /**
+ * @brief Thread argument.
+ */
+ void *arg;
+} thread_descriptor_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @name Threads queues
+ */
+/**
+ * @brief Data part of a static threads queue object initializer.
+ * @details This macro should be used when statically initializing a threads
+ * queue that is part of a bigger structure.
+ *
+ * @param[in] name the name of the threads queue variable
+ */
+#define _THREADS_QUEUE_DATA(name) {(thread_t *)&name, (thread_t *)&name}
+
+/**
+ * @brief Static threads queue object initializer.
+ * @details Statically initialized threads queues require no explicit
+ * initialization using @p queue_init().
+ *
+ * @param[in] name the name of the threads queue variable
+ */
+#define _THREADS_QUEUE_DECL(name) \
+ threads_queue_t name = _THREADS_QUEUE_DATA(name)
+/** @} */
+
+/**
+ * @name Working Areas
+ */
+/**
+ * @brief Calculates the total Working Area size.
+ *
+ * @param[in] n the stack size to be assigned to the thread
+ * @return The total used memory in bytes.
+ *
+ * @api
+ */
+#define THD_WORKING_AREA_SIZE(n) \
+ MEM_ALIGN_NEXT(sizeof(thread_t) + PORT_WA_SIZE(n), PORT_STACK_ALIGN)
+
+/**
+ * @brief Static working area allocation.
+ * @details This macro is used to allocate a static thread working area
+ * aligned as both position and size.
+ *
+ * @param[in] s the name to be assigned to the stack array
+ * @param[in] n the stack size to be assigned to the thread
+ *
+ * @api
+ */
+#define THD_WORKING_AREA(s, n) PORT_WORKING_AREA(s, n)
+
+/**
+ * @brief Base of a working area casted to the correct type.
+ *
+ * @param[in] s name of the working area
+ */
+#define THD_WORKING_AREA_BASE(s) ((stkalign_t *)(s))
+
+/**
+ * @brief End of a working area casted to the correct type.
+ *
+ * @param[in] s name of the working area
+ */
+#define THD_WORKING_AREA_END(s) (THD_WORKING_AREA_BASE(s) + \
+ (sizeof (s) / sizeof (stkalign_t)))
+/** @} */
+
+/**
+ * @name Threads abstraction macros
+ */
+/**
+ * @brief Thread declaration macro.
+ * @note Thread declarations should be performed using this macro because
+ * the port layer could define optimizations for thread functions.
+ */
+#define THD_FUNCTION(tname, arg) PORT_THD_FUNCTION(tname, arg)
+/** @} */
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Delays the invoking thread for the specified number of seconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system tick clock.
+ * @note The maximum specifiable value is implementation dependent.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] sec time in seconds, must be different from zero
+ *
+ * @api
+ */
+#define chThdSleepSeconds(sec) chThdSleep(TIME_S2I(sec))
+
+/**
+ * @brief Delays the invoking thread for the specified number of
+ * milliseconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system tick clock.
+ * @note The maximum specifiable value is implementation dependent.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] msec time in milliseconds, must be different from zero
+ *
+ * @api
+ */
+#define chThdSleepMilliseconds(msec) chThdSleep(TIME_MS2I(msec))
+
+/**
+ * @brief Delays the invoking thread for the specified number of
+ * microseconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system tick clock.
+ * @note The maximum specifiable value is implementation dependent.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] usec time in microseconds, must be different from zero
+ *
+ * @api
+ */
+#define chThdSleepMicroseconds(usec) chThdSleep(TIME_US2I(usec))
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ thread_t *_thread_init(thread_t *tp, const char *name, tprio_t prio);
+#if CH_DBG_FILL_THREADS == TRUE
+ void _thread_memfill(uint8_t *startp, uint8_t *endp, uint8_t v);
+#endif
+ thread_t *chThdCreateSuspendedI(const thread_descriptor_t *tdp);
+ thread_t *chThdCreateSuspended(const thread_descriptor_t *tdp);
+ thread_t *chThdCreateI(const thread_descriptor_t *tdp);
+ thread_t *chThdCreate(const thread_descriptor_t *tdp);
+ thread_t *chThdCreateStatic(void *wsp, size_t size,
+ tprio_t prio, tfunc_t pf, void *arg);
+ thread_t *chThdStart(thread_t *tp);
+#if CH_CFG_USE_REGISTRY == TRUE
+ thread_t *chThdAddRef(thread_t *tp);
+ void chThdRelease(thread_t *tp);
+#endif
+ void chThdExit(msg_t msg);
+ void chThdExitS(msg_t msg);
+#if CH_CFG_USE_WAITEXIT == TRUE
+ msg_t chThdWait(thread_t *tp);
+#endif
+ tprio_t chThdSetPriority(tprio_t newprio);
+ void chThdTerminate(thread_t *tp);
+ msg_t chThdSuspendS(thread_reference_t *trp);
+ msg_t chThdSuspendTimeoutS(thread_reference_t *trp, sysinterval_t timeout);
+ void chThdResumeI(thread_reference_t *trp, msg_t msg);
+ void chThdResumeS(thread_reference_t *trp, msg_t msg);
+ void chThdResume(thread_reference_t *trp, msg_t msg);
+ msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout);
+ void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg);
+ void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg);
+ void chThdSleep(sysinterval_t time);
+ void chThdSleepUntil(systime_t time);
+ systime_t chThdSleepUntilWindowed(systime_t prev, systime_t next);
+ void chThdYield(void);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+ /**
+ * @brief Returns a pointer to the current @p thread_t.
+ *
+ * @return A pointer to the current thread.
+ *
+ * @xclass
+ */
+static inline thread_t *chThdGetSelfX(void) {
+
+ return ch.rlist.current;
+}
+
+/**
+ * @brief Returns the current thread priority.
+ * @note Can be invoked in any context.
+ *
+ * @return The current thread priority.
+ *
+ * @xclass
+ */
+static inline tprio_t chThdGetPriorityX(void) {
+
+ return chThdGetSelfX()->prio;
+}
+
+/**
+ * @brief Returns the number of ticks consumed by the specified thread.
+ * @note This function is only available when the
+ * @p CH_DBG_THREADS_PROFILING configuration option is enabled.
+ *
+ * @param[in] tp pointer to the thread
+ * @return The number of consumed system ticks.
+ *
+ * @xclass
+ */
+#if (CH_DBG_THREADS_PROFILING == TRUE) || defined(__DOXYGEN__)
+static inline systime_t chThdGetTicksX(thread_t *tp) {
+
+ return tp->time;
+}
+#endif
+
+#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief Returns the working area base of the specified thread.
+ *
+ * @param[in] tp pointer to the thread
+ * @return The working area base pointer.
+ *
+ * @xclass
+ */
+static inline stkalign_t *chThdGetWorkingAreaX(thread_t *tp) {
+
+ return tp->wabase;
+}
+#endif /* CH_DBG_ENABLE_STACK_CHECK == TRUE */
+
+/**
+ * @brief Verifies if the specified thread is in the @p CH_STATE_FINAL state.
+ *
+ * @param[in] tp pointer to the thread
+ * @retval true thread terminated.
+ * @retval false thread not terminated.
+ *
+ * @xclass
+ */
+static inline bool chThdTerminatedX(thread_t *tp) {
+
+ return (bool)(tp->state == CH_STATE_FINAL);
+}
+
+/**
+ * @brief Verifies if the current thread has a termination request pending.
+ *
+ * @retval true termination request pending.
+ * @retval false termination request not pending.
+ *
+ * @xclass
+ */
+static inline bool chThdShouldTerminateX(void) {
+
+ return (bool)((chThdGetSelfX()->flags & CH_FLAG_TERMINATE) != (tmode_t)0);
+}
+
+/**
+ * @brief Resumes a thread created with @p chThdCreateI().
+ *
+ * @param[in] tp pointer to the thread
+ * @return The pointer to the @p thread_t structure allocated for
+ * the thread into the working space area.
+ *
+ * @iclass
+ */
+static inline thread_t *chThdStartI(thread_t *tp) {
+
+ chDbgAssert(tp->state == CH_STATE_WTSTART, "wrong state");
+
+ return chSchReadyI(tp);
+}
+
+/**
+ * @brief Suspends the invoking thread for the specified number of ticks.
+ *
+ * @param[in] ticks the delay in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE the thread enters an infinite sleep
+ * state.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ *
+ * @sclass
+ */
+static inline void chThdSleepS(sysinterval_t ticks) {
+
+ chDbgCheck(ticks != TIME_IMMEDIATE);
+
+ (void) chSchGoSleepTimeoutS(CH_STATE_SLEEPING, ticks);
+}
+
+/**
+ * @brief Initializes a threads queue object.
+ *
+ * @param[out] tqp pointer to the threads queue object
+ *
+ * @init
+ */
+static inline void chThdQueueObjectInit(threads_queue_t *tqp) {
+
+ queue_init(tqp);
+}
+
+/**
+ * @brief Evaluates to @p true if the specified queue is empty.
+ *
+ * @param[out] tqp pointer to the threads queue object
+ * @return The queue status.
+ * @retval false if the queue is not empty.
+ * @retval true if the queue is empty.
+ *
+ * @iclass
+ */
+static inline bool chThdQueueIsEmptyI(threads_queue_t *tqp) {
+
+ chDbgCheckClassI();
+
+ return queue_isempty(tqp);
+}
+
+/**
+ * @brief Dequeues and wakes up one thread from the threads queue object.
+ * @details Dequeues one thread from the queue without checking if the queue
+ * is empty.
+ * @pre The queue must contain at least an object.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+static inline void chThdDoDequeueNextI(threads_queue_t *tqp, msg_t msg) {
+ thread_t *tp;
+
+ chDbgAssert(queue_notempty(tqp), "empty queue");
+
+ tp = queue_fifo_remove(tqp);
+
+ chDbgAssert(tp->state == CH_STATE_QUEUED, "invalid state");
+
+ tp->u.rdymsg = msg;
+ (void) chSchReadyI(tp);
+}
+
+#endif /* CHTHREADS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chtime.h b/ChibiOS_20.3.2/os/rt/include/chtime.h
new file mode 100644
index 0000000..c6c1de8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chtime.h
@@ -0,0 +1,492 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/chtime.h
+ * @brief Time and intervals macros and structures.
+ *
+ * @addtogroup time_intervals
+ * @details This module is responsible for handling of system time and time
+ * intervals.
+ * @{
+ */
+
+#ifndef CHTIME_H
+#define CHTIME_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Special time constants
+ * @{
+ */
+/**
+ * @brief Zero interval specification for some functions with a timeout
+ * specification.
+ * @note Not all functions accept @p TIME_IMMEDIATE as timeout parameter,
+ * see the specific function documentation.
+ */
+#define TIME_IMMEDIATE ((sysinterval_t)0)
+
+/**
+ * @brief Infinite interval specification for all functions with a timeout
+ * specification.
+ * @note Not all functions accept @p TIME_INFINITE as timeout parameter,
+ * see the specific function documentation.
+ */
+#define TIME_INFINITE ((sysinterval_t)-1)
+
+/**
+ * @brief Maximum interval constant usable as timeout.
+ */
+#define TIME_MAX_INTERVAL ((sysinterval_t)-2)
+
+/**
+ * @brief Maximum system of system time before it wraps.
+ */
+#define TIME_MAX_SYSTIME ((systime_t)-1)
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if (CH_CFG_ST_RESOLUTION != 16) && (CH_CFG_ST_RESOLUTION != 32) && \
+ (CH_CFG_ST_RESOLUTION != 64)
+#error "invalid CH_CFG_ST_RESOLUTION specified, must be 16, 32 or 64"
+#endif
+
+#if CH_CFG_ST_FREQUENCY < 10
+#error "invalid CH_CFG_ST_FREQUENCY specified, must be >= 10"
+#endif
+
+#if (CH_CFG_INTERVALS_SIZE != 16) && (CH_CFG_INTERVALS_SIZE != 32) && \
+ (CH_CFG_INTERVALS_SIZE != 64)
+#error "invalid CH_CFG_INTERVALS_SIZE specified, must be 16, 32 or 64"
+#endif
+
+#if (CH_CFG_TIME_TYPES_SIZE != 16) && (CH_CFG_TIME_TYPES_SIZE != 32)
+#error "invalid CH_CFG_TIME_TYPES_SIZE specified, must be 16 or 32"
+#endif
+
+#if CH_CFG_INTERVALS_SIZE < CH_CFG_ST_RESOLUTION
+#error "CH_CFG_INTERVALS_SIZE must be >= CH_CFG_ST_RESOLUTION"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of system time.
+ * @note It is selectable in configuration between 16, 32 or 64 bits.
+ */
+#if (CH_CFG_ST_RESOLUTION == 64) || defined(__DOXYGEN__)
+typedef uint64_t systime_t;
+#elif CH_CFG_ST_RESOLUTION == 32
+typedef uint32_t systime_t;
+#elif CH_CFG_ST_RESOLUTION == 16
+typedef uint16_t systime_t;
+#endif
+
+/**
+ * @brief Type of time interval.
+ * @note It is selectable in configuration between 16, 32 or 64 bits.
+ */
+#if (CH_CFG_INTERVALS_SIZE == 64) || defined(__DOXYGEN__)
+typedef uint64_t sysinterval_t;
+#elif CH_CFG_INTERVALS_SIZE == 32
+typedef uint32_t sysinterval_t;
+#elif CH_CFG_INTERVALS_SIZE == 16
+typedef uint16_t sysinterval_t;
+#endif
+
+#if (CH_CFG_TIME_TYPES_SIZE == 32) || defined(__DOXYGEN__)
+/**
+ * @brief Type of seconds.
+ * @note It is selectable in configuration between 16 or 32 bits.
+ */
+typedef uint32_t time_secs_t;
+
+/**
+ * @brief Type of milliseconds.
+ * @note It is selectable in configuration between 16 or 32 bits.
+ */
+typedef uint32_t time_msecs_t;
+
+/**
+ * @brief Type of microseconds.
+ * @note It is selectable in configuration between 16 or 32 bits.
+ */
+typedef uint32_t time_usecs_t;
+
+/**
+ * @brief Type of time conversion variable.
+ * @note This type must have double width than other time types, it is
+ * only used internally for conversions.
+ */
+typedef uint64_t time_conv_t;
+
+#else
+typedef uint16_t time_secs_t;
+typedef uint16_t time_msecs_t;
+typedef uint16_t time_usecs_t;
+typedef uint32_t time_conv_t;
+#endif
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @name Fast time conversion utilities
+ * @{
+ */
+/**
+ * @brief Seconds to time interval.
+ * @details Converts from seconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] secs number of seconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define TIME_S2I(secs) \
+ ((sysinterval_t)((time_conv_t)(secs) * (time_conv_t)CH_CFG_ST_FREQUENCY))
+
+/**
+ * @brief Milliseconds to time interval.
+ * @details Converts from milliseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] msecs number of milliseconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define TIME_MS2I(msecs) \
+ ((sysinterval_t)((((time_conv_t)(msecs) * \
+ (time_conv_t)CH_CFG_ST_FREQUENCY) + \
+ (time_conv_t)999) / (time_conv_t)1000))
+
+/**
+ * @brief Microseconds to time interval.
+ * @details Converts from microseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] usecs number of microseconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define TIME_US2I(usecs) \
+ ((sysinterval_t)((((time_conv_t)(usecs) * \
+ (time_conv_t)CH_CFG_ST_FREQUENCY) + \
+ (time_conv_t)999999) / (time_conv_t)1000000))
+
+/**
+ * @brief Time interval to seconds.
+ * @details Converts from system ticks number to seconds.
+ * @note The result is rounded up to the next second boundary.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] interval interval in ticks
+ * @return The number of seconds.
+ *
+ * @api
+ */
+#define TIME_I2S(interval) \
+ (time_secs_t)(((time_conv_t)(interval) + \
+ (time_conv_t)CH_CFG_ST_FREQUENCY - \
+ (time_conv_t)1) / (time_conv_t)CH_CFG_ST_FREQUENCY)
+
+/**
+ * @brief Time interval to milliseconds.
+ * @details Converts from system ticks number to milliseconds.
+ * @note The result is rounded up to the next millisecond boundary.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] interval interval in ticks
+ * @return The number of milliseconds.
+ *
+ * @api
+ */
+#define TIME_I2MS(interval) \
+ (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000) + \
+ (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) / \
+ (time_conv_t)CH_CFG_ST_FREQUENCY)
+
+/**
+ * @brief Time interval to microseconds.
+ * @details Converts from system ticks number to microseconds.
+ * @note The result is rounded up to the next microsecond boundary.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] interval interval in ticks
+ * @return The number of microseconds.
+ *
+ * @api
+ */
+#define TIME_I2US(interval) \
+ (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000000) + \
+ (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) / \
+ (time_conv_t)CH_CFG_ST_FREQUENCY)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/*
+ * Virtual Timers APIs.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @name Secure time conversion utilities
+ * @{
+ */
+/**
+ * @brief Seconds to time interval.
+ * @details Converts from seconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ *
+ * @param[in] secs number of seconds
+ * @return The number of ticks.
+ *
+ * @special
+ */
+static inline sysinterval_t chTimeS2I(time_secs_t secs) {
+ time_conv_t ticks;
+
+ ticks = (time_conv_t)secs * (time_conv_t)CH_CFG_ST_FREQUENCY;
+
+ chDbgAssert(ticks <= (time_conv_t)TIME_MAX_INTERVAL,
+ "conversion overflow");
+
+ return (sysinterval_t)ticks;
+}
+
+/**
+ * @brief Milliseconds to time interval.
+ * @details Converts from milliseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ *
+ * @param[in] msec number of milliseconds
+ * @return The number of ticks.
+ *
+ * @special
+ */
+static inline sysinterval_t chTimeMS2I(time_msecs_t msec) {
+ time_conv_t ticks;
+
+ ticks = (((time_conv_t)msec * (time_conv_t)CH_CFG_ST_FREQUENCY) +
+ (time_conv_t)999) / (time_conv_t)1000;
+
+ chDbgAssert(ticks <= (time_conv_t)TIME_MAX_INTERVAL,
+ "conversion overflow");
+
+ return (sysinterval_t)ticks;
+}
+
+/**
+ * @brief Microseconds to time interval.
+ * @details Converts from microseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ *
+ * @param[in] usec number of microseconds
+ * @return The number of ticks.
+ *
+ * @special
+ */
+static inline sysinterval_t chTimeUS2I(time_usecs_t usec) {
+ time_conv_t ticks;
+
+ ticks = (((time_conv_t)usec * (time_conv_t)CH_CFG_ST_FREQUENCY) +
+ (time_conv_t)999999) / (time_conv_t)1000000;
+
+ chDbgAssert(ticks <= (time_conv_t)TIME_MAX_INTERVAL,
+ "conversion overflow");
+
+ return (sysinterval_t)ticks;
+}
+
+/**
+ * @brief Time interval to seconds.
+ * @details Converts from system interval to seconds.
+ * @note The result is rounded up to the next second boundary.
+ *
+ * @param[in] interval interval in ticks
+ * @return The number of seconds.
+ *
+ * @special
+ */
+static inline time_secs_t chTimeI2S(sysinterval_t interval) {
+ time_conv_t secs;
+
+ secs = ((time_conv_t)interval +
+ (time_conv_t)CH_CFG_ST_FREQUENCY -
+ (time_conv_t)1) / (time_conv_t)CH_CFG_ST_FREQUENCY;
+
+ chDbgAssert(secs < (time_conv_t)((time_secs_t)-1),
+ "conversion overflow");
+
+ return (time_secs_t)secs;
+}
+
+/**
+ * @brief Time interval to milliseconds.
+ * @details Converts from system interval to milliseconds.
+ * @note The result is rounded up to the next millisecond boundary.
+ *
+ * @param[in] interval interval in ticks
+ * @return The number of milliseconds.
+ *
+ * @special
+ */
+static inline time_msecs_t chTimeI2MS(sysinterval_t interval) {
+ time_conv_t msecs;
+
+ msecs = (((time_conv_t)interval * (time_conv_t)1000) +
+ (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) /
+ (time_conv_t)CH_CFG_ST_FREQUENCY;
+
+ chDbgAssert(msecs < (time_conv_t)((time_msecs_t)-1),
+ "conversion overflow");
+
+ return (time_msecs_t)msecs;
+}
+
+/**
+ * @brief Time interval to microseconds.
+ * @details Converts from system interval to microseconds.
+ * @note The result is rounded up to the next microsecond boundary.
+ *
+ * @param[in] interval interval in ticks
+ * @return The number of microseconds.
+ *
+ * @special
+ */
+static inline time_usecs_t chTimeI2US(sysinterval_t interval) {
+ time_conv_t usecs;
+
+ usecs = (((time_conv_t)interval * (time_conv_t)1000000) +
+ (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) /
+ (time_conv_t)CH_CFG_ST_FREQUENCY;
+
+ chDbgAssert(usecs <= (time_conv_t)((time_usecs_t)-1),
+ "conversion overflow");
+
+ return (time_usecs_t)usecs;
+}
+
+/**
+ * @brief Adds an interval to a system time returning a system time.
+ *
+ * @param[in] systime base system time
+ * @param[in] interval interval to be added
+ * @return The new system time.
+ *
+ * @xclass
+ */
+static inline systime_t chTimeAddX(systime_t systime,
+ sysinterval_t interval) {
+
+#if CH_CFG_ST_RESOLUTION != CH_CFG_INTERVALS_SIZE
+ chDbgCheck(interval <= (sysinterval_t)TIME_MAX_SYSTIME);
+#endif
+
+ return systime + (systime_t)interval;
+}
+
+/**
+ * @brief Subtracts two system times returning an interval.
+ *
+ * @param[in] start first system time
+ * @param[in] end second system time
+ * @return The interval representing the time difference.
+ *
+ * @xclass
+ */
+static inline sysinterval_t chTimeDiffX(systime_t start, systime_t end) {
+
+ /*lint -save -e9033 [10.8] This cast is required by the operation, it is
+ known that the destination type can be wider.*/
+ return (sysinterval_t)((systime_t)(end - start));
+ /*lint -restore*/
+}
+
+/**
+ * @brief Checks if the specified time is within the specified time range.
+ * @note When start==end then the function returns always false because the
+ * time window has zero size.
+ *
+ * @param[in] time the time to be verified
+ * @param[in] start the start of the time window (inclusive)
+ * @param[in] end the end of the time window (non inclusive)
+ * @retval true current time within the specified time window.
+ * @retval false current time not within the specified time window.
+ *
+ * @xclass
+ */
+static inline bool chTimeIsInRangeX(systime_t time,
+ systime_t start,
+ systime_t end) {
+
+ return (bool)((systime_t)((systime_t)time - (systime_t)start) <
+ (systime_t)((systime_t)end - (systime_t)start));
+}
+
+/** @} */
+
+#endif /* CHTIME_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chtm.h b/ChibiOS_20.3.2/os/rt/include/chtm.h
new file mode 100644
index 0000000..f068251
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chtm.h
@@ -0,0 +1,109 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/chtm.h
+ * @brief Time Measurement module macros and structures.
+ *
+ * @addtogroup time_measurement
+ * @{
+ */
+
+#ifndef CHTM_H
+#define CHTM_H
+
+#if (CH_CFG_USE_TM == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if PORT_SUPPORTS_RT == FALSE
+#error "CH_CFG_USE_TM requires PORT_SUPPORTS_RT"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a time measurement calibration data.
+ */
+typedef struct {
+ /**
+ * @brief Measurement calibration value.
+ */
+ rtcnt_t offset;
+} tm_calibration_t;
+
+/**
+ * @brief Type of a Time Measurement object.
+ * @note The maximum measurable time period depends on the implementation
+ * of the realtime counter and its clock frequency.
+ * @note The measurement is not 100% cycle-accurate, it can be in excess
+ * of few cycles depending on the compiler and target architecture.
+ * @note Interrupts can affect measurement if the measurement is performed
+ * with interrupts enabled.
+ */
+typedef struct {
+ rtcnt_t best; /**< @brief Best measurement. */
+ rtcnt_t worst; /**< @brief Worst measurement. */
+ rtcnt_t last; /**< @brief Last measurement. */
+ ucnt_t n; /**< @brief Number of measurements. */
+ rttime_t cumulative; /**< @brief Cumulative measurement. */
+} time_measurement_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void _tm_init(void);
+ void chTMObjectInit(time_measurement_t *tmp);
+ NOINLINE void chTMStartMeasurementX(time_measurement_t *tmp);
+ NOINLINE void chTMStopMeasurementX(time_measurement_t *tmp);
+ NOINLINE void chTMChainMeasurementToX(time_measurement_t *tmp1,
+ time_measurement_t *tmp2);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* CH_CFG_USE_TM == TRUE */
+
+#endif /* CHTM_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chtrace.h b/ChibiOS_20.3.2/os/rt/include/chtrace.h
new file mode 100644
index 0000000..c0a58ac
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chtrace.h
@@ -0,0 +1,256 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/chtrace.h
+ * @brief Tracer macros and structures.
+ *
+ * @addtogroup trace
+ * @{
+ */
+
+#ifndef CHTRACE_H
+#define CHTRACE_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Trace record types
+ * @{
+ */
+#define CH_TRACE_TYPE_UNUSED 0U
+#define CH_TRACE_TYPE_SWITCH 1U
+#define CH_TRACE_TYPE_ISR_ENTER 2U
+#define CH_TRACE_TYPE_ISR_LEAVE 3U
+#define CH_TRACE_TYPE_HALT 4U
+#define CH_TRACE_TYPE_USER 5U
+/** @} */
+
+/**
+ * @name Events to trace
+ * @{
+ */
+#define CH_DBG_TRACE_MASK_DISABLED 255U
+#define CH_DBG_TRACE_MASK_NONE 0U
+#define CH_DBG_TRACE_MASK_SWITCH 1U
+#define CH_DBG_TRACE_MASK_ISR 2U
+#define CH_DBG_TRACE_MASK_HALT 4U
+#define CH_DBG_TRACE_MASK_USER 8U
+#define CH_DBG_TRACE_MASK_SLOW (CH_DBG_TRACE_MASK_SWITCH | \
+ CH_DBG_TRACE_MASK_HALT | \
+ CH_DBG_TRACE_MASK_USER)
+#define CH_DBG_TRACE_MASK_ALL (CH_DBG_TRACE_MASK_SWITCH | \
+ CH_DBG_TRACE_MASK_ISR | \
+ CH_DBG_TRACE_MASK_HALT | \
+ CH_DBG_TRACE_MASK_USER)
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @name Debug related settings
+ * @{
+ */
+/**
+ * @brief Trace buffer entries.
+ */
+#if !defined(CH_DBG_TRACE_MASK) || defined(__DOXYGEN__)
+#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED
+#endif
+
+/**
+ * @brief Trace buffer entries.
+ * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
+ * different from @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#if !defined(CH_DBG_TRACE_BUFFER_SIZE) || defined(__DOXYGEN__)
+#define CH_DBG_TRACE_BUFFER_SIZE 128
+#endif
+/** @} */
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+#if (CH_DBG_TRACE_MASK != CH_DBG_TRACE_MASK_DISABLED) || defined(__DOXYGEN__)
+/*lint -save -e46 [6.1] An uint32_t is required.*/
+/**
+ * @brief Trace buffer record.
+ */
+typedef struct {
+ /**
+ * @brief Record type.
+ */
+ uint32_t type:3;
+ /**
+ * @brief Switched out thread state.
+ */
+ uint32_t state:5;
+ /**
+ * @brief Accurate time stamp.
+ * @note This field only available if the post supports
+ * @p PORT_SUPPORTS_RT else it is set to zero.
+ */
+ uint32_t rtstamp:24;
+ /**
+ * @brief System time stamp of the switch event.
+ */
+ systime_t time;
+ union {
+ /**
+ * @brief Structure representing a context switch.
+ */
+ struct {
+ /**
+ * @brief Switched in thread.
+ */
+ thread_t *ntp;
+ /**
+ * @brief Object where going to sleep.
+ */
+ void *wtobjp;
+ } sw;
+ /**
+ * @brief Structure representing an ISR enter.
+ */
+ struct {
+ /**
+ * @brief ISR function name taken using @p __func__.
+ */
+ const char *name;
+ } isr;
+ /**
+ * @brief Structure representing an halt.
+ */
+ struct {
+ /**
+ * @brief Halt error string.
+ */
+ const char *reason;
+ } halt;
+ /**
+ * @brief User trace structure.
+ */
+ struct {
+ /**
+ * @brief Trace user parameter 1.
+ */
+ void *up1;
+ /**
+ * @brief Trace user parameter 2.
+ */
+ void *up2;
+ } user;
+ } u;
+} ch_trace_event_t;
+/*lint -restore*/
+
+/**
+ * @brief Trace buffer header.
+ */
+typedef struct {
+ /**
+ * @brief Suspended trace sources mask.
+ */
+ uint16_t suspended;
+ /**
+ * @brief Trace buffer size (entries).
+ */
+ uint16_t size;
+ /**
+ * @brief Pointer to the buffer front.
+ */
+ ch_trace_event_t *ptr;
+ /**
+ * @brief Ring buffer.
+ */
+ ch_trace_event_t buffer[CH_DBG_TRACE_BUFFER_SIZE];
+} ch_trace_buffer_t;
+#endif /* CH_DBG_TRACE_MASK != CH_DBG_TRACE_MASK_DISABLED */
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/* When a trace feature is disabled the associated functions are replaced by
+ an empty macro. Note that the macros can be externally redefined in
+ order to interface 3rd parties tracing tools.*/
+#if CH_DBG_TRACE_MASK == CH_DBG_TRACE_MASK_DISABLED
+#if !defined(_trace_init)
+#define _trace_init()
+#endif
+#if !defined(_trace_switch)
+#define _trace_switch(ntp, otp)
+#endif
+#if !defined(_trace_isr_enter)
+#define _trace_isr_enter(isr)
+#endif
+#if !defined(_trace_isr_leave)
+#define _trace_isr_leave(isr)
+#endif
+#if !defined(_trace_halt)
+#define _trace_halt(reason)
+#endif
+#if !defined(chDbgWriteTraceI)
+#define chDbgWriteTraceI(up1, up2)
+#endif
+#if !defined(chDbgWriteTrace)
+#define chDbgWriteTrace(up1, up2)
+#endif
+#endif /* CH_DBG_TRACE_MASK == CH_DBG_TRACE_MASK_DISABLED */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if (CH_DBG_TRACE_MASK != CH_DBG_TRACE_MASK_DISABLED) || defined(__DOXYGEN__)
+ void _trace_init(void);
+ void _trace_switch(thread_t *ntp, thread_t *otp);
+ void _trace_isr_enter(const char *isr);
+ void _trace_isr_leave(const char *isr);
+ void _trace_halt(const char *reason);
+ void chDbgWriteTraceI(void *up1, void *up2);
+ void chDbgWriteTrace(void *up1, void *up2);
+ void chDbgSuspendTraceI(uint16_t mask);
+ void chDbgSuspendTrace(uint16_t mask);
+ void chDbgResumeTraceI(uint16_t mask);
+ void chDbgResumeTrace(uint16_t mask);
+#endif /* CH_DBG_TRACE_MASK != CH_DBG_TRACE_MASK_DISABLED */
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* CHTRACE_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/include/chvt.h b/ChibiOS_20.3.2/os/rt/include/chvt.h
new file mode 100644
index 0000000..ed1c512
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/include/chvt.h
@@ -0,0 +1,362 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/include/chvt.h
+ * @brief Time and Virtual Timers module macros and structures.
+ *
+ * @addtogroup time
+ * @{
+ */
+
+#ifndef CHVT_H
+#define CHVT_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if (CH_CFG_ST_TIMEDELTA < 0) || (CH_CFG_ST_TIMEDELTA == 1)
+#error "invalid CH_CFG_ST_TIMEDELTA specified, must " \
+ "be zero or greater than one"
+#endif
+
+#if (CH_CFG_ST_TIMEDELTA > 0) && (CH_CFG_TIME_QUANTUM > 0)
+#error "CH_CFG_TIME_QUANTUM not supported in tickless mode"
+#endif
+
+#if (CH_CFG_ST_TIMEDELTA > 0) && (CH_DBG_THREADS_PROFILING == TRUE)
+#error "CH_DBG_THREADS_PROFILING not supported in tickless mode"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+/*
+ * Virtual Timers APIs.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void _vt_init(void);
+ void chVTDoSetI(virtual_timer_t *vtp, sysinterval_t delay,
+ vtfunc_t vtfunc, void *par);
+ void chVTDoResetI(virtual_timer_t *vtp);
+ void chVTDoTickI(void);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes a @p virtual_timer_t object.
+ * @note Initializing a timer object is not strictly required because
+ * the function @p chVTSetI() initializes the object too. This
+ * function is only useful if you need to perform a @p chVTIsArmed()
+ * check before calling @p chVTSetI().
+ *
+ * @param[out] vtp the @p virtual_timer_t structure pointer
+ *
+ * @init
+ */
+static inline void chVTObjectInit(virtual_timer_t *vtp) {
+
+ vtp->func = NULL;
+}
+
+/**
+ * @brief Current system time.
+ * @details Returns the number of system ticks since the @p chSysInit()
+ * invocation.
+ * @note The counter can reach its maximum and then restart from zero.
+ * @note This function can be called from any context but its atomicity
+ * is not guaranteed on architectures whose word size is less than
+ * @p systime_t size.
+ *
+ * @return The system time in ticks.
+ *
+ * @xclass
+ */
+static inline systime_t chVTGetSystemTimeX(void) {
+
+#if CH_CFG_ST_TIMEDELTA == 0
+ return ch.vtlist.systime;
+#else /* CH_CFG_ST_TIMEDELTA > 0 */
+ return port_timer_get_time();
+#endif /* CH_CFG_ST_TIMEDELTA > 0 */
+}
+
+/**
+ * @brief Current system time.
+ * @details Returns the number of system ticks since the @p chSysInit()
+ * invocation.
+ * @note The counter can reach its maximum and then restart from zero.
+ *
+ * @return The system time in ticks.
+ *
+ * @api
+ */
+static inline systime_t chVTGetSystemTime(void) {
+ systime_t systime;
+
+ chSysLock();
+ systime = chVTGetSystemTimeX();
+ chSysUnlock();
+
+ return systime;
+}
+
+/**
+ * @brief Returns the elapsed time since the specified start time.
+ *
+ * @param[in] start start time
+ * @return The elapsed time.
+ *
+ * @xclass
+ */
+static inline sysinterval_t chVTTimeElapsedSinceX(systime_t start) {
+
+ return chTimeDiffX(start, chVTGetSystemTimeX());
+}
+
+/**
+ * @brief Checks if the current system time is within the specified time
+ * window.
+ * @note When start==end then the function returns always false because the
+ * time window has zero size.
+ *
+ * @param[in] start the start of the time window (inclusive)
+ * @param[in] end the end of the time window (non inclusive)
+ * @retval true current time within the specified time window.
+ * @retval false current time not within the specified time window.
+ *
+ * @xclass
+ */
+static inline bool chVTIsSystemTimeWithinX(systime_t start, systime_t end) {
+
+ return chTimeIsInRangeX(chVTGetSystemTimeX(), start, end);
+}
+
+/**
+ * @brief Checks if the current system time is within the specified time
+ * window.
+ * @note When start==end then the function returns always false because the
+ * time window has zero size.
+ *
+ * @param[in] start the start of the time window (inclusive)
+ * @param[in] end the end of the time window (non inclusive)
+ * @retval true current time within the specified time window.
+ * @retval false current time not within the specified time window.
+ *
+ * @api
+ */
+static inline bool chVTIsSystemTimeWithin(systime_t start, systime_t end) {
+
+ return chTimeIsInRangeX(chVTGetSystemTime(), start, end);
+}
+
+/**
+ * @brief Returns the time interval until the next timer event.
+ * @note The return value is not perfectly accurate and can report values
+ * in excess of @p CH_CFG_ST_TIMEDELTA ticks.
+ * @note The interval returned by this function is only meaningful if
+ * more timers are not added to the list until the returned time.
+ *
+ * @param[out] timep pointer to a variable that will contain the time
+ * interval until the next timer elapses. This pointer
+ * can be @p NULL if the information is not required.
+ * @return The time, in ticks, until next time event.
+ * @retval false if the timers list is empty.
+ * @retval true if the timers list contains at least one timer.
+ *
+ * @iclass
+ */
+static inline bool chVTGetTimersStateI(sysinterval_t *timep) {
+
+ chDbgCheckClassI();
+
+ if (&ch.vtlist == (virtual_timers_list_t *)ch.vtlist.next) {
+ return false;
+ }
+
+ if (timep != NULL) {
+#if CH_CFG_ST_TIMEDELTA == 0
+ *timep = ch.vtlist.next->delta;
+#else
+ *timep = (ch.vtlist.next->delta + (sysinterval_t)CH_CFG_ST_TIMEDELTA) -
+ chTimeDiffX(ch.vtlist.lasttime, chVTGetSystemTimeX());
+#endif
+ }
+
+ return true;
+}
+
+/**
+ * @brief Returns @p true if the specified timer is armed.
+ * @pre The timer must have been initialized using @p chVTObjectInit()
+ * or @p chVTDoSetI().
+ *
+ * @param[in] vtp the @p virtual_timer_t structure pointer
+ * @return true if the timer is armed.
+ *
+ * @iclass
+ */
+static inline bool chVTIsArmedI(const virtual_timer_t *vtp) {
+
+ chDbgCheckClassI();
+
+ return (bool)(vtp->func != NULL);
+}
+
+/**
+ * @brief Returns @p true if the specified timer is armed.
+ * @pre The timer must have been initialized using @p chVTObjectInit()
+ * or @p chVTDoSetI().
+ *
+ * @param[in] vtp the @p virtual_timer_t structure pointer
+ * @return true if the timer is armed.
+ *
+ * @api
+ */
+static inline bool chVTIsArmed(const virtual_timer_t *vtp) {
+ bool b;
+
+ chSysLock();
+ b = chVTIsArmedI(vtp);
+ chSysUnlock();
+
+ return b;
+}
+
+/**
+ * @brief Disables a Virtual Timer.
+ * @note The timer is first checked and disabled only if armed.
+ * @pre The timer must have been initialized using @p chVTObjectInit()
+ * or @p chVTDoSetI().
+ *
+ * @param[in] vtp the @p virtual_timer_t structure pointer
+ *
+ * @iclass
+ */
+static inline void chVTResetI(virtual_timer_t *vtp) {
+
+ if (chVTIsArmedI(vtp)) {
+ chVTDoResetI(vtp);
+ }
+}
+
+/**
+ * @brief Disables a Virtual Timer.
+ * @note The timer is first checked and disabled only if armed.
+ * @pre The timer must have been initialized using @p chVTObjectInit()
+ * or @p chVTDoSetI().
+ *
+ * @param[in] vtp the @p virtual_timer_t structure pointer
+ *
+ * @api
+ */
+static inline void chVTReset(virtual_timer_t *vtp) {
+
+ chSysLock();
+ chVTResetI(vtp);
+ chSysUnlock();
+}
+
+/**
+ * @brief Enables a virtual timer.
+ * @details If the virtual timer was already enabled then it is re-enabled
+ * using the new parameters.
+ * @pre The timer must have been initialized using @p chVTObjectInit()
+ * or @p chVTDoSetI().
+ *
+ * @param[in] vtp the @p virtual_timer_t structure pointer
+ * @param[in] delay the number of ticks before the operation timeouts, the
+ * special values are handled as follow:
+ * - @a TIME_INFINITE is allowed but interpreted as a
+ * normal time specification.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ * @param[in] vtfunc the timer callback function. After invoking the
+ * callback the timer is disabled and the structure can
+ * be disposed or reused.
+ * @param[in] par a parameter that will be passed to the callback
+ * function
+ *
+ * @iclass
+ */
+static inline void chVTSetI(virtual_timer_t *vtp, sysinterval_t delay,
+ vtfunc_t vtfunc, void *par) {
+
+ chVTResetI(vtp);
+ chVTDoSetI(vtp, delay, vtfunc, par);
+}
+
+/**
+ * @brief Enables a virtual timer.
+ * @details If the virtual timer was already enabled then it is re-enabled
+ * using the new parameters.
+ * @pre The timer must have been initialized using @p chVTObjectInit()
+ * or @p chVTDoSetI().
+ *
+ * @param[in] vtp the @p virtual_timer_t structure pointer
+ * @param[in] delay the number of ticks before the operation timeouts, the
+ * special values are handled as follow:
+ * - @a TIME_INFINITE is allowed but interpreted as a
+ * normal time specification.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ * @param[in] vtfunc the timer callback function. After invoking the
+ * callback the timer is disabled and the structure can
+ * be disposed or reused.
+ * @param[in] par a parameter that will be passed to the callback
+ * function
+ *
+ * @api
+ */
+static inline void chVTSet(virtual_timer_t *vtp, sysinterval_t delay,
+ vtfunc_t vtfunc, void *par) {
+
+ chSysLock();
+ chVTSetI(vtp, delay, vtfunc, par);
+ chSysUnlock();
+}
+
+#endif /* CHVT_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/rt.mk b/ChibiOS_20.3.2/os/rt/rt.mk
new file mode 100644
index 0000000..3294ce8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/rt.mk
@@ -0,0 +1,75 @@
+# List of all the ChibiOS/RT kernel files, there is no need to remove the files
+# from this list, you can disable parts of the kernel by editing chconf.h.
+ifeq ($(USE_SMART_BUILD),yes)
+
+# Configuration files directory
+ifeq ($(CHCONFDIR),)
+ ifeq ($(CONFDIR),)
+ CHCONFDIR = .
+ else
+ CHCONFDIR := $(CONFDIR)
+ endif
+endif
+
+CHCONF := $(strip $(shell cat $(CHCONFDIR)/chconf.h | egrep -e "\#define"))
+
+KERNSRC := $(CHIBIOS)/os/rt/src/chsys.c \
+ $(CHIBIOS)/os/rt/src/chdebug.c \
+ $(CHIBIOS)/os/rt/src/chtrace.c \
+ $(CHIBIOS)/os/rt/src/chvt.c \
+ $(CHIBIOS)/os/rt/src/chschd.c \
+ $(CHIBIOS)/os/rt/src/chthreads.c
+ifneq ($(findstring CH_CFG_USE_TM TRUE,$(CHCONF)),)
+KERNSRC += $(CHIBIOS)/os/rt/src/chtm.c
+endif
+ifneq ($(findstring CH_DBG_STATISTICS TRUE,$(CHCONF)),)
+KERNSRC += $(CHIBIOS)/os/rt/src/chstats.c
+endif
+ifneq ($(findstring CH_CFG_USE_REGISTRY TRUE,$(CHCONF)),)
+KERNSRC += $(CHIBIOS)/os/rt/src/chregistry.c
+endif
+ifneq ($(findstring CH_CFG_USE_SEMAPHORES TRUE,$(CHCONF)),)
+KERNSRC += $(CHIBIOS)/os/rt/src/chsem.c
+endif
+ifneq ($(findstring CH_CFG_USE_MUTEXES TRUE,$(CHCONF)),)
+KERNSRC += $(CHIBIOS)/os/rt/src/chmtx.c
+endif
+ifneq ($(findstring CH_CFG_USE_CONDVARS TRUE,$(CHCONF)),)
+KERNSRC += $(CHIBIOS)/os/rt/src/chcond.c
+endif
+ifneq ($(findstring CH_CFG_USE_EVENTS TRUE,$(CHCONF)),)
+KERNSRC += $(CHIBIOS)/os/rt/src/chevents.c
+endif
+ifneq ($(findstring CH_CFG_USE_MESSAGES TRUE,$(CHCONF)),)
+KERNSRC += $(CHIBIOS)/os/rt/src/chmsg.c
+endif
+ifneq ($(findstring CH_CFG_USE_DYNAMIC TRUE,$(CHCONF)),)
+KERNSRC += $(CHIBIOS)/os/rt/src/chdynamic.c
+endif
+else
+KERNSRC := $(CHIBIOS)/os/rt/src/chsys.c \
+ $(CHIBIOS)/os/rt/src/chdebug.c \
+ $(CHIBIOS)/os/rt/src/chtrace.c \
+ $(CHIBIOS)/os/rt/src/chvt.c \
+ $(CHIBIOS)/os/rt/src/chschd.c \
+ $(CHIBIOS)/os/rt/src/chthreads.c \
+ $(CHIBIOS)/os/rt/src/chtm.c \
+ $(CHIBIOS)/os/rt/src/chstats.c \
+ $(CHIBIOS)/os/rt/src/chregistry.c \
+ $(CHIBIOS)/os/rt/src/chsem.c \
+ $(CHIBIOS)/os/rt/src/chmtx.c \
+ $(CHIBIOS)/os/rt/src/chcond.c \
+ $(CHIBIOS)/os/rt/src/chevents.c \
+ $(CHIBIOS)/os/rt/src/chmsg.c \
+ $(CHIBIOS)/os/rt/src/chdynamic.c
+endif
+
+# Required include directories
+KERNINC := $(CHIBIOS)/os/rt/include
+
+# Shared variables
+ALLCSRC += $(KERNSRC)
+ALLINC += $(KERNINC)
+
+# OS Library
+include $(CHIBIOS)/os/oslib/oslib.mk
diff --git a/ChibiOS_20.3.2/os/rt/src/chcond.c b/ChibiOS_20.3.2/os/rt/src/chcond.c
new file mode 100644
index 0000000..bd653c3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/src/chcond.c
@@ -0,0 +1,321 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+/*
+ Concepts and parts of this file have been contributed by Leon Woestenberg.
+ */
+
+/**
+ * @file rt/src/chcond.c
+ * @brief Condition Variables code.
+ *
+ * @addtogroup condvars
+ * @details This module implements the Condition Variables mechanism. Condition
+ * variables are an extensions to the mutex subsystem and cannot
+ * work alone.
+ * Operation mode
+ * The condition variable is a synchronization object meant to be
+ * used inside a zone protected by a mutex. Mutexes and condition
+ * variables together can implement a Monitor construct.
+ * @pre In order to use the condition variable APIs the @p CH_CFG_USE_CONDVARS
+ * option must be enabled in @p chconf.h.
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_CONDVARS == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes s @p condition_variable_t structure.
+ *
+ * @param[out] cp pointer to a @p condition_variable_t structure
+ *
+ * @init
+ */
+void chCondObjectInit(condition_variable_t *cp) {
+
+ chDbgCheck(cp != NULL);
+
+ queue_init(&cp->queue);
+}
+
+/**
+ * @brief Signals one thread that is waiting on the condition variable.
+ *
+ * @param[in] cp pointer to the @p condition_variable_t structure
+ *
+ * @api
+ */
+void chCondSignal(condition_variable_t *cp) {
+
+ chDbgCheck(cp != NULL);
+
+ chSysLock();
+ if (queue_notempty(&cp->queue)) {
+ chSchWakeupS(queue_fifo_remove(&cp->queue), MSG_OK);
+ }
+ chSysUnlock();
+}
+
+/**
+ * @brief Signals one thread that is waiting on the condition variable.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] cp pointer to the @p condition_variable_t structure
+ *
+ * @iclass
+ */
+void chCondSignalI(condition_variable_t *cp) {
+
+ chDbgCheckClassI();
+ chDbgCheck(cp != NULL);
+
+ if (queue_notempty(&cp->queue)) {
+ thread_t *tp = queue_fifo_remove(&cp->queue);
+ tp->u.rdymsg = MSG_OK;
+ (void) chSchReadyI(tp);
+ }
+}
+
+/**
+ * @brief Signals all threads that are waiting on the condition variable.
+ *
+ * @param[in] cp pointer to the @p condition_variable_t structure
+ *
+ * @api
+ */
+void chCondBroadcast(condition_variable_t *cp) {
+
+ chSysLock();
+ chCondBroadcastI(cp);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+/**
+ * @brief Signals all threads that are waiting on the condition variable.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] cp pointer to the @p condition_variable_t structure
+ *
+ * @iclass
+ */
+void chCondBroadcastI(condition_variable_t *cp) {
+
+ chDbgCheckClassI();
+ chDbgCheck(cp != NULL);
+
+ /* Empties the condition variable queue and inserts all the threads into the
+ ready list in FIFO order. The wakeup message is set to @p MSG_RESET in
+ order to make a chCondBroadcast() detectable from a chCondSignal().*/
+ while (queue_notempty(&cp->queue)) {
+ chSchReadyI(queue_fifo_remove(&cp->queue))->u.rdymsg = MSG_RESET;
+ }
+}
+
+/**
+ * @brief Waits on the condition variable releasing the mutex lock.
+ * @details Releases the currently owned mutex, waits on the condition
+ * variable, and finally acquires the mutex again. All the sequence
+ * is performed atomically.
+ * @pre The invoking thread must have at least one owned mutex.
+ *
+ * @param[in] cp pointer to the @p condition_variable_t structure
+ * @return A message specifying how the invoking thread has been
+ * released from the condition variable.
+ * @retval MSG_OK if the condition variable has been signaled using
+ * @p chCondSignal().
+ * @retval MSG_RESET if the condition variable has been signaled using
+ * @p chCondBroadcast().
+ *
+ * @api
+ */
+msg_t chCondWait(condition_variable_t *cp) {
+ msg_t msg;
+
+ chSysLock();
+ msg = chCondWaitS(cp);
+ chSysUnlock();
+ return msg;
+}
+
+/**
+ * @brief Waits on the condition variable releasing the mutex lock.
+ * @details Releases the currently owned mutex, waits on the condition
+ * variable, and finally acquires the mutex again. All the sequence
+ * is performed atomically.
+ * @pre The invoking thread must have at least one owned mutex.
+ *
+ * @param[in] cp pointer to the @p condition_variable_t structure
+ * @return A message specifying how the invoking thread has been
+ * released from the condition variable.
+ * @retval MSG_OK if the condition variable has been signaled using
+ * @p chCondSignal().
+ * @retval MSG_RESET if the condition variable has been signaled using
+ * @p chCondBroadcast().
+ *
+ * @sclass
+ */
+msg_t chCondWaitS(condition_variable_t *cp) {
+ thread_t *ctp = currp;
+ mutex_t *mp = chMtxGetNextMutexX();
+ msg_t msg;
+
+ chDbgCheckClassS();
+ chDbgCheck(cp != NULL);
+ chDbgAssert(mp != NULL, "not owning a mutex");
+
+ /* Releasing "current" mutex.*/
+ chMtxUnlockS(mp);
+
+ /* Start waiting on the condition variable, on exit the mutex is taken
+ again.*/
+ ctp->u.wtobjp = cp;
+ queue_prio_insert(ctp, &cp->queue);
+ chSchGoSleepS(CH_STATE_WTCOND);
+ msg = ctp->u.rdymsg;
+ chMtxLockS(mp);
+
+ return msg;
+}
+
+#if (CH_CFG_USE_CONDVARS_TIMEOUT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Waits on the condition variable releasing the mutex lock.
+ * @details Releases the currently owned mutex, waits on the condition
+ * variable, and finally acquires the mutex again. All the sequence
+ * is performed atomically.
+ * @pre The invoking thread must have at least one owned mutex.
+ * @pre The configuration option @p CH_CFG_USE_CONDVARS_TIMEOUT must be enabled
+ * in order to use this function.
+ * @post Exiting the function because a timeout does not re-acquire the
+ * mutex, the mutex ownership is lost.
+ *
+ * @param[in] cp pointer to the @p condition_variable_t structure
+ * @param[in] timeout the number of ticks before the operation timeouts, the
+ * special values are handled as follow:
+ * - @a TIME_INFINITE no timeout.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ * @return A message specifying how the invoking thread has been
+ * released from the condition variable.
+ * @retval MSG_OK if the condition variable has been signaled using
+ * @p chCondSignal().
+ * @retval MSG_RESET if the condition variable has been signaled using
+ * @p chCondBroadcast().
+ * @retval MSG_TIMEOUT if the condition variable has not been signaled within
+ * the specified timeout.
+ *
+ * @api
+ */
+msg_t chCondWaitTimeout(condition_variable_t *cp, sysinterval_t timeout) {
+ msg_t msg;
+
+ chSysLock();
+ msg = chCondWaitTimeoutS(cp, timeout);
+ chSysUnlock();
+
+ return msg;
+}
+
+/**
+ * @brief Waits on the condition variable releasing the mutex lock.
+ * @details Releases the currently owned mutex, waits on the condition
+ * variable, and finally acquires the mutex again. All the sequence
+ * is performed atomically.
+ * @pre The invoking thread must have at least one owned mutex.
+ * @pre The configuration option @p CH_CFG_USE_CONDVARS_TIMEOUT must be enabled
+ * in order to use this function.
+ * @post Exiting the function because a timeout does not re-acquire the
+ * mutex, the mutex ownership is lost.
+ *
+ * @param[in] cp pointer to the @p condition_variable_t structure
+ * @param[in] timeout the number of ticks before the operation timeouts, the
+ * special values are handled as follow:
+ * - @a TIME_INFINITE no timeout.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ * @return A message specifying how the invoking thread has been
+ * released from the condition variable.
+ * @retval MSG_OK if the condition variable has been signaled using
+ * @p chCondSignal().
+ * @retval MSG_RESET if the condition variable has been signaled using
+ * @p chCondBroadcast().
+ * @retval MSG_TIMEOUT if the condition variable has not been signaled within
+ * the specified timeout.
+ *
+ * @sclass
+ */
+msg_t chCondWaitTimeoutS(condition_variable_t *cp, sysinterval_t timeout) {
+ mutex_t *mp = chMtxGetNextMutexX();
+ msg_t msg;
+
+ chDbgCheckClassS();
+ chDbgCheck((cp != NULL) && (timeout != TIME_IMMEDIATE));
+ chDbgAssert(mp != NULL, "not owning a mutex");
+
+ /* Releasing "current" mutex.*/
+ chMtxUnlockS(mp);
+
+ /* Start waiting on the condition variable, on exit the mutex is taken
+ again.*/
+ currp->u.wtobjp = cp;
+ queue_prio_insert(currp, &cp->queue);
+ msg = chSchGoSleepTimeoutS(CH_STATE_WTCOND, timeout);
+ if (msg != MSG_TIMEOUT) {
+ chMtxLockS(mp);
+ }
+
+ return msg;
+}
+#endif /* CH_CFG_USE_CONDVARS_TIMEOUT == TRUE */
+
+#endif /* CH_CFG_USE_CONDVARS == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/src/chdebug.c b/ChibiOS_20.3.2/os/rt/src/chdebug.c
new file mode 100644
index 0000000..d73950c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/src/chdebug.c
@@ -0,0 +1,257 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/src/chdebug.c
+ * @brief Debug support code.
+ *
+ * @addtogroup checks_assertions
+ * @details Debug APIs and services:
+ * - Runtime system state and call protocol check. The following
+ * panic messages can be generated:
+ * - SV#1, misplaced @p chSysDisable().
+ * - Called from an ISR.
+ * - Called from a critical zone.
+ * .
+ * - SV#2, misplaced @p chSysSuspend()
+ * - Called from an ISR.
+ * - Called from a critical zone.
+ * .
+ * - SV#3, misplaced @p chSysEnable().
+ * - Called from an ISR.
+ * - Called from a critical zone.
+ * .
+ * - SV#4, misplaced @p chSysLock().
+ * - Called from an ISR.
+ * - Called from a critical zone.
+ * .
+ * - SV#5, misplaced @p chSysUnlock().
+ * - Called from an ISR.
+ * - Not called from a critical zone.
+ * .
+ * - SV#6, misplaced @p chSysLockFromISR().
+ * - Not called from an ISR.
+ * - Called from a critical zone.
+ * .
+ * - SV#7, misplaced @p chSysUnlockFromISR().
+ * - Not called from an ISR.
+ * - Not called from a critical zone.
+ * .
+ * - SV#8, misplaced @p CH_IRQ_PROLOGUE().
+ * - Not called at ISR begin.
+ * - Called from a critical zone.
+ * .
+ * - SV#9, misplaced @p CH_IRQ_EPILOGUE().
+ * - @p CH_IRQ_PROLOGUE() missing.
+ * - Not called at ISR end.
+ * - Called from a critical zone.
+ * .
+ * - SV#10, misplaced I-class function.
+ * - I-class function not called from within a critical zone.
+ * .
+ * - SV#11, misplaced S-class function.
+ * - S-class function not called from within a critical zone.
+ * - Called from an ISR.
+ * .
+ * - Parameters check.
+ * - Kernel assertions.
+ * .
+ * @note Stack checks are not implemented in this module but in the port
+ * layer in an architecture-dependent way.
+ * @{
+ */
+
+#include "ch.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+#if (CH_DBG_SYSTEM_STATE_CHECK == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Guard code for @p chSysDisable().
+ *
+ * @notapi
+ */
+void _dbg_check_disable(void) {
+
+ if ((ch.dbg.isr_cnt != (cnt_t)0) || (ch.dbg.lock_cnt != (cnt_t)0)) {
+ chSysHalt("SV#1");
+ }
+}
+
+/**
+ * @brief Guard code for @p chSysSuspend().
+ *
+ * @notapi
+ */
+void _dbg_check_suspend(void) {
+
+ if ((ch.dbg.isr_cnt != (cnt_t)0) || (ch.dbg.lock_cnt != (cnt_t)0)) {
+ chSysHalt("SV#2");
+ }
+}
+
+/**
+ * @brief Guard code for @p chSysEnable().
+ *
+ * @notapi
+ */
+void _dbg_check_enable(void) {
+
+ if ((ch.dbg.isr_cnt != (cnt_t)0) || (ch.dbg.lock_cnt != (cnt_t)0)) {
+ chSysHalt("SV#3");
+ }
+}
+
+/**
+ * @brief Guard code for @p chSysLock().
+ *
+ * @notapi
+ */
+void _dbg_check_lock(void) {
+
+ if ((ch.dbg.isr_cnt != (cnt_t)0) || (ch.dbg.lock_cnt != (cnt_t)0)) {
+ chSysHalt("SV#4");
+ }
+ _dbg_enter_lock();
+}
+
+/**
+ * @brief Guard code for @p chSysUnlock().
+ *
+ * @notapi
+ */
+void _dbg_check_unlock(void) {
+
+ if ((ch.dbg.isr_cnt != (cnt_t)0) || (ch.dbg.lock_cnt <= (cnt_t)0)) {
+ chSysHalt("SV#5");
+ }
+ _dbg_leave_lock();
+}
+
+/**
+ * @brief Guard code for @p chSysLockFromIsr().
+ *
+ * @notapi
+ */
+void _dbg_check_lock_from_isr(void) {
+
+ if ((ch.dbg.isr_cnt <= (cnt_t)0) || (ch.dbg.lock_cnt != (cnt_t)0)) {
+ chSysHalt("SV#6");
+ }
+ _dbg_enter_lock();
+}
+
+/**
+ * @brief Guard code for @p chSysUnlockFromIsr().
+ *
+ * @notapi
+ */
+void _dbg_check_unlock_from_isr(void) {
+
+ if ((ch.dbg.isr_cnt <= (cnt_t)0) || (ch.dbg.lock_cnt <= (cnt_t)0)) {
+ chSysHalt("SV#7");
+ }
+ _dbg_leave_lock();
+}
+
+/**
+ * @brief Guard code for @p CH_IRQ_PROLOGUE().
+ *
+ * @notapi
+ */
+void _dbg_check_enter_isr(void) {
+
+ port_lock_from_isr();
+ if ((ch.dbg.isr_cnt < (cnt_t)0) || (ch.dbg.lock_cnt != (cnt_t)0)) {
+ chSysHalt("SV#8");
+ }
+ ch.dbg.isr_cnt++;
+ port_unlock_from_isr();
+}
+
+/**
+ * @brief Guard code for @p CH_IRQ_EPILOGUE().
+ *
+ * @notapi
+ */
+void _dbg_check_leave_isr(void) {
+
+ port_lock_from_isr();
+ if ((ch.dbg.isr_cnt <= (cnt_t)0) || (ch.dbg.lock_cnt != (cnt_t)0)) {
+ chSysHalt("SV#9");
+ }
+ ch.dbg.isr_cnt--;
+ port_unlock_from_isr();
+}
+
+/**
+ * @brief I-class functions context check.
+ * @details Verifies that the system is in an appropriate state for invoking
+ * an I-class API function. A panic is generated if the state is
+ * not compatible.
+ *
+ * @api
+ */
+void chDbgCheckClassI(void) {
+
+ if ((ch.dbg.isr_cnt < (cnt_t)0) || (ch.dbg.lock_cnt <= (cnt_t)0)) {
+ chSysHalt("SV#10");
+ }
+}
+
+/**
+ * @brief S-class functions context check.
+ * @details Verifies that the system is in an appropriate state for invoking
+ * an S-class API function. A panic is generated if the state is
+ * not compatible.
+ *
+ * @api
+ */
+void chDbgCheckClassS(void) {
+
+ if ((ch.dbg.isr_cnt != (cnt_t)0) || (ch.dbg.lock_cnt <= (cnt_t)0)) {
+ chSysHalt("SV#11");
+ }
+}
+
+#endif /* CH_DBG_SYSTEM_STATE_CHECK == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/src/chdynamic.c b/ChibiOS_20.3.2/os/rt/src/chdynamic.c
new file mode 100644
index 0000000..a11c219
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/src/chdynamic.c
@@ -0,0 +1,185 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/src/chdynamic.c
+ * @brief Dynamic threads code.
+ *
+ * @addtogroup dynamic_threads
+ * @details Dynamic threads related APIs and services.
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_DYNAMIC == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+#if (CH_CFG_USE_HEAP == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Creates a new thread allocating the memory from the heap.
+ * @pre The configuration options @p CH_CFG_USE_DYNAMIC and
+ * @p CH_CFG_USE_HEAP must be enabled in order to use this function.
+ * @note A thread can terminate by calling @p chThdExit() or by simply
+ * returning from its main function.
+ * @note The memory allocated for the thread is not released automatically,
+ * it is responsibility of the creator thread to call @p chThdWait()
+ * and then release the allocated memory.
+ *
+ * @param[in] heapp heap from which allocate the memory or @p NULL for the
+ * default heap
+ * @param[in] size size of the working area to be allocated
+ * @param[in] name thread name
+ * @param[in] prio the priority level for the new thread
+ * @param[in] pf the thread function
+ * @param[in] arg an argument passed to the thread function. It can be
+ * @p NULL.
+ * @return The pointer to the @p thread_t structure allocated for
+ * the thread into the working space area.
+ * @retval NULL if the memory cannot be allocated.
+ *
+ * @api
+ */
+thread_t *chThdCreateFromHeap(memory_heap_t *heapp, size_t size,
+ const char *name, tprio_t prio,
+ tfunc_t pf, void *arg) {
+ thread_t *tp;
+ void *wsp;
+
+ wsp = chHeapAllocAligned(heapp, size, PORT_WORKING_AREA_ALIGN);
+ if (wsp == NULL) {
+ return NULL;
+ }
+
+ thread_descriptor_t td = {
+ name,
+ wsp,
+ (stkalign_t *)((uint8_t *)wsp + size),
+ prio,
+ pf,
+ arg
+ };
+
+#if CH_DBG_FILL_THREADS == TRUE
+ _thread_memfill((uint8_t *)wsp,
+ (uint8_t *)wsp + size,
+ CH_DBG_STACK_FILL_VALUE);
+#endif
+
+ chSysLock();
+ tp = chThdCreateSuspendedI(&td);
+ tp->flags = CH_FLAG_MODE_HEAP;
+ chSchWakeupS(tp, MSG_OK);
+ chSysUnlock();
+
+ return tp;
+}
+#endif /* CH_CFG_USE_HEAP == TRUE */
+
+#if (CH_CFG_USE_MEMPOOLS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Creates a new thread allocating the memory from the specified
+ * memory pool.
+ * @pre The configuration options @p CH_CFG_USE_DYNAMIC and
+ * @p CH_CFG_USE_MEMPOOLS must be enabled in order to use this
+ * function.
+ * @pre The pool must be initialized to contain only objects with
+ * alignment @p PORT_WORKING_AREA_ALIGN.
+ * @note A thread can terminate by calling @p chThdExit() or by simply
+ * returning from its main function.
+ * @note The memory allocated for the thread is not released automatically,
+ * it is responsibility of the creator thread to call @p chThdWait()
+ * and then release the allocated memory.
+ *
+ * @param[in] mp pointer to the memory pool object
+ * @param[in] name thread name
+ * @param[in] prio the priority level for the new thread
+ * @param[in] pf the thread function
+ * @param[in] arg an argument passed to the thread function. It can be
+ * @p NULL.
+ * @return The pointer to the @p thread_t structure allocated for
+ * the thread into the working space area.
+ * @retval NULL if the memory pool is empty.
+ *
+ * @api
+ */
+thread_t *chThdCreateFromMemoryPool(memory_pool_t *mp, const char *name,
+ tprio_t prio, tfunc_t pf, void *arg) {
+ thread_t *tp;
+ void *wsp;
+
+ chDbgCheck(mp != NULL);
+
+ wsp = chPoolAlloc(mp);
+ if (wsp == NULL) {
+ return NULL;
+ }
+
+ thread_descriptor_t td = {
+ name,
+ wsp,
+ (stkalign_t *)((uint8_t *)wsp + mp->object_size),
+ prio,
+ pf,
+ arg
+ };
+
+#if CH_DBG_FILL_THREADS == TRUE
+ _thread_memfill((uint8_t *)wsp,
+ (uint8_t *)wsp + mp->object_size,
+ CH_DBG_STACK_FILL_VALUE);
+#endif
+
+ chSysLock();
+ tp = chThdCreateSuspendedI(&td);
+ tp->flags = CH_FLAG_MODE_MPOOL;
+ tp->mpool = mp;
+ chSchWakeupS(tp, MSG_OK);
+ chSysUnlock();
+
+ return tp;
+}
+#endif /* CH_CFG_USE_MEMPOOLS == TRUE */
+
+#endif /* CH_CFG_USE_DYNAMIC == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/src/chevents.c b/ChibiOS_20.3.2/os/rt/src/chevents.c
new file mode 100644
index 0000000..9b84ce2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/src/chevents.c
@@ -0,0 +1,603 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+/*
+ Concepts and parts of this file have been contributed by Scott (skute).
+ */
+
+/**
+ * @file rt/src/chevents.c
+ * @brief Events code.
+ *
+ * @addtogroup events
+ * @details Event Flags, Event Sources and Event Listeners.
+ * Operation mode
+ * Each thread has a mask of pending events inside its
+ * @p thread_t structure.
+ * Operations defined for events:
+ * - Wait, the invoking thread goes to sleep until a certain
+ * AND/OR combination of events are signaled.
+ * - Clear, a mask of events is cleared from the pending
+ * events, the cleared events mask is returned (only the
+ * events that were actually pending and then cleared).
+ * - Signal, an events mask is directly ORed to the mask of
+ * the signaled thread.
+ * - Broadcast, each thread registered on an Event Source is
+ * signaled with the events specified in its Event Listener.
+ * - Dispatch, an events mask is scanned and for each bit set
+ * to one an associated handler function is invoked. Bit masks are
+ * scanned from bit zero upward.
+ * .
+ * An Event Source is a special object that can be "broadcasted" by
+ * a thread or an interrupt service routine. Broadcasting an Event
+ * Source has the effect that all the threads registered on the
+ * Event Source will be signaled with an events mask.
+ * An unlimited number of Event Sources can exists in a system and
+ * each thread can be listening on an unlimited number of
+ * them.
+ * @pre In order to use the Events APIs the @p CH_CFG_USE_EVENTS option
+ * must be enabled in @p chconf.h.
+ * @post Enabling events requires 1-4 (depending on the architecture)
+ * extra bytes in the @p thread_t structure.
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Registers an Event Listener on an Event Source.
+ * @details Once a thread has registered as listener on an event source it
+ * will be notified of all events broadcasted there.
+ * @note Multiple Event Listeners can specify the same bits to be ORed to
+ * different threads.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ * @param[in] elp pointer to the @p event_listener_t structure
+ * @param[in] events events to be ORed to the thread when
+ * the event source is broadcasted
+ * @param[in] wflags mask of flags the listening thread is interested in
+ *
+ * @api
+ */
+void chEvtRegisterMaskWithFlags(event_source_t *esp,
+ event_listener_t *elp,
+ eventmask_t events,
+ eventflags_t wflags) {
+
+ chDbgCheck((esp != NULL) && (elp != NULL));
+
+ chSysLock();
+ elp->next = esp->next;
+ esp->next = elp;
+ elp->listener = currp;
+ elp->events = events;
+ elp->flags = (eventflags_t)0;
+ elp->wflags = wflags;
+ chSysUnlock();
+}
+
+/**
+ * @brief Unregisters an Event Listener from its Event Source.
+ * @note If the event listener is not registered on the specified event
+ * source then the function does nothing.
+ * @note For optimal performance it is better to perform the unregister
+ * operations in inverse order of the register operations (elements
+ * are found on top of the list).
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ * @param[in] elp pointer to the @p event_listener_t structure
+ *
+ * @api
+ */
+void chEvtUnregister(event_source_t *esp, event_listener_t *elp) {
+ event_listener_t *p;
+
+ chDbgCheck((esp != NULL) && (elp != NULL));
+
+ /*lint -save -e9087 -e740 [11.3, 1.3] Cast required by list handling.*/
+ p = (event_listener_t *)esp;
+ /*lint -restore*/
+ chSysLock();
+ /*lint -save -e9087 -e740 [11.3, 1.3] Cast required by list handling.*/
+ while (p->next != (event_listener_t *)esp) {
+ /*lint -restore*/
+ if (p->next == elp) {
+ p->next = elp->next;
+ break;
+ }
+ p = p->next;
+ }
+ chSysUnlock();
+}
+
+/**
+ * @brief Clears the pending events specified in the events mask.
+ *
+ * @param[in] events the events to be cleared
+ * @return The mask of pending events that were cleared.
+ *
+ * @iclass
+ */
+eventmask_t chEvtGetAndClearEventsI(eventmask_t events) {
+ eventmask_t m;
+
+ m = currp->epending & events;
+ currp->epending &= ~events;
+
+ return m;
+}
+
+/**
+ * @brief Clears the pending events specified in the events mask.
+ *
+ * @param[in] events the events to be cleared
+ * @return The mask of pending events that were cleared.
+ *
+ * @api
+ */
+eventmask_t chEvtGetAndClearEvents(eventmask_t events) {
+ eventmask_t m;
+
+ chSysLock();
+ m = chEvtGetAndClearEventsI(events);
+ chSysUnlock();
+
+ return m;
+}
+
+/**
+ * @brief Adds (OR) a set of events to the current thread, this is
+ * @b much faster than using @p chEvtBroadcast() or @p chEvtSignal().
+ *
+ * @param[in] events the events to be added
+ * @return The mask of currently pending events.
+ *
+ * @api
+ */
+eventmask_t chEvtAddEvents(eventmask_t events) {
+ eventmask_t newevt;
+
+ chSysLock();
+ newevt = chEvtAddEventsI(events);
+ chSysUnlock();
+
+ return newevt;
+}
+
+/**
+ * @brief Signals all the Event Listeners registered on the specified Event
+ * Source.
+ * @details This function variants ORs the specified event flags to all the
+ * threads registered on the @p event_source_t in addition to the
+ * event flags specified by the threads themselves in the
+ * @p event_listener_t objects.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ * @param[in] flags the flags set to be added to the listener flags mask
+ *
+ * @iclass
+ */
+void chEvtBroadcastFlagsI(event_source_t *esp, eventflags_t flags) {
+ event_listener_t *elp;
+
+ chDbgCheckClassI();
+ chDbgCheck(esp != NULL);
+
+ elp = esp->next;
+ /*lint -save -e9087 -e740 [11.3, 1.3] Cast required by list handling.*/
+ while (elp != (event_listener_t *)esp) {
+ /*lint -restore*/
+ elp->flags |= flags;
+ /* When flags == 0 the thread will always be signaled because the
+ source does not emit any flag.*/
+ if ((flags == (eventflags_t)0) ||
+ ((flags & elp->wflags) != (eventflags_t)0)) {
+ chEvtSignalI(elp->listener, elp->events);
+ }
+ elp = elp->next;
+ }
+}
+
+/**
+ * @brief Returns the flags associated to an @p event_listener_t.
+ * @details The flags are returned and the @p event_listener_t flags mask is
+ * cleared.
+ *
+ * @param[in] elp pointer to the @p event_listener_t structure
+ * @return The flags added to the listener by the associated
+ * event source.
+ *
+ * @api
+ */
+eventflags_t chEvtGetAndClearFlags(event_listener_t *elp) {
+ eventflags_t flags;
+
+ chSysLock();
+ flags = elp->flags;
+ elp->flags = (eventflags_t)0;
+ chSysUnlock();
+
+ return flags & elp->wflags;
+}
+
+/**
+ * @brief Adds a set of event flags directly to the specified @p thread_t.
+ *
+ * @param[in] tp the thread to be signaled
+ * @param[in] events the events set to be ORed
+ *
+ * @api
+ */
+void chEvtSignal(thread_t *tp, eventmask_t events) {
+
+ chDbgCheck(tp != NULL);
+
+ chSysLock();
+ chEvtSignalI(tp, events);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+/**
+ * @brief Adds a set of event flags directly to the specified @p thread_t.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] tp the thread to be signaled
+ * @param[in] events the events set to be ORed
+ *
+ * @iclass
+ */
+void chEvtSignalI(thread_t *tp, eventmask_t events) {
+
+ chDbgCheckClassI();
+ chDbgCheck(tp != NULL);
+
+ tp->epending |= events;
+ /* Test on the AND/OR conditions wait states.*/
+ if (((tp->state == CH_STATE_WTOREVT) &&
+ ((tp->epending & tp->u.ewmask) != (eventmask_t)0)) ||
+ ((tp->state == CH_STATE_WTANDEVT) &&
+ ((tp->epending & tp->u.ewmask) == tp->u.ewmask))) {
+ tp->u.rdymsg = MSG_OK;
+ (void) chSchReadyI(tp);
+ }
+}
+
+/**
+ * @brief Signals all the Event Listeners registered on the specified Event
+ * Source.
+ * @details This function variants ORs the specified event flags to all the
+ * threads registered on the @p event_source_t in addition to the
+ * event flags specified by the threads themselves in the
+ * @p event_listener_t objects.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ * @param[in] flags the flags set to be added to the listener flags mask
+ *
+ * @api
+ */
+void chEvtBroadcastFlags(event_source_t *esp, eventflags_t flags) {
+
+ chSysLock();
+ chEvtBroadcastFlagsI(esp, flags);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+/**
+ * @brief Returns the unmasked flags associated to an @p event_listener_t.
+ * @details The flags are returned and the @p event_listener_t flags mask is
+ * cleared.
+ *
+ * @param[in] elp pointer to the @p event_listener_t structure
+ * @return The flags added to the listener by the associated
+ * event source.
+ *
+ * @iclass
+ */
+eventflags_t chEvtGetAndClearFlagsI(event_listener_t *elp) {
+ eventflags_t flags;
+
+ flags = elp->flags;
+ elp->flags = (eventflags_t)0;
+
+ return flags & elp->wflags;
+}
+
+/**
+ * @brief Invokes the event handlers associated to an event flags mask.
+ *
+ * @param[in] events mask of events to be dispatched
+ * @param[in] handlers an array of @p evhandler_t. The array must have size
+ * equal to the number of bits in eventmask_t.
+ *
+ * @api
+ */
+void chEvtDispatch(const evhandler_t *handlers, eventmask_t events) {
+ eventid_t eid;
+
+ chDbgCheck(handlers != NULL);
+
+ eid = (eventid_t)0;
+ while (events != (eventmask_t)0) {
+ if ((events & EVENT_MASK(eid)) != (eventmask_t)0) {
+ chDbgAssert(handlers[eid] != NULL, "null handler");
+ events &= ~EVENT_MASK(eid);
+ handlers[eid](eid);
+ }
+ eid++;
+ }
+}
+
+#if (CH_CFG_OPTIMIZE_SPEED == TRUE) || \
+ (CH_CFG_USE_EVENTS_TIMEOUT == FALSE) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief Waits for exactly one of the specified events.
+ * @details The function waits for one event among those specified in
+ * @p events to become pending then the event is cleared and returned.
+ * @note One and only one event is served in the function, the one with the
+ * lowest event id. The function is meant to be invoked into a loop in
+ * order to serve all the pending events.
+ * This means that Event Listeners with a lower event identifier have
+ * an higher priority.
+ *
+ * @param[in] events events that the function should wait
+ * for, @p ALL_EVENTS enables all the events
+ * @return The mask of the lowest event id served and cleared.
+ *
+ * @api
+ */
+eventmask_t chEvtWaitOne(eventmask_t events) {
+ thread_t *ctp = currp;
+ eventmask_t m;
+
+ chSysLock();
+ m = ctp->epending & events;
+ if (m == (eventmask_t)0) {
+ ctp->u.ewmask = events;
+ chSchGoSleepS(CH_STATE_WTOREVT);
+ m = ctp->epending & events;
+ }
+ m ^= m & (m - (eventmask_t)1);
+ ctp->epending &= ~m;
+ chSysUnlock();
+
+ return m;
+}
+
+/**
+ * @brief Waits for any of the specified events.
+ * @details The function waits for any event among those specified in
+ * @p events to become pending then the events are cleared and
+ * returned.
+ *
+ * @param[in] events events that the function should wait
+ * for, @p ALL_EVENTS enables all the events
+ * @return The mask of the served and cleared events.
+ *
+ * @api
+ */
+eventmask_t chEvtWaitAny(eventmask_t events) {
+ thread_t *ctp = currp;
+ eventmask_t m;
+
+ chSysLock();
+ m = ctp->epending & events;
+ if (m == (eventmask_t)0) {
+ ctp->u.ewmask = events;
+ chSchGoSleepS(CH_STATE_WTOREVT);
+ m = ctp->epending & events;
+ }
+ ctp->epending &= ~m;
+ chSysUnlock();
+
+ return m;
+}
+
+/**
+ * @brief Waits for all the specified events.
+ * @details The function waits for all the events specified in @p events to
+ * become pending then the events are cleared and returned.
+ *
+ * @param[in] events events that the function should wait
+ * for, @p ALL_EVENTS requires all the events
+ * @return The mask of the served and cleared events.
+ *
+ * @api
+ */
+eventmask_t chEvtWaitAll(eventmask_t events) {
+ thread_t *ctp = currp;
+
+ chSysLock();
+ if ((ctp->epending & events) != events) {
+ ctp->u.ewmask = events;
+ chSchGoSleepS(CH_STATE_WTANDEVT);
+ }
+ ctp->epending &= ~events;
+ chSysUnlock();
+
+ return events;
+}
+#endif /* CH_CFG_OPTIMIZE_SPEED || !CH_CFG_USE_EVENTS_TIMEOUT */
+
+#if (CH_CFG_USE_EVENTS_TIMEOUT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Waits for exactly one of the specified events.
+ * @details The function waits for one event among those specified in
+ * @p events to become pending then the event is cleared and returned.
+ * @note One and only one event is served in the function, the one with the
+ * lowest event id. The function is meant to be invoked into a loop
+ * in order to serve all the pending events.
+ * This means that Event Listeners with a lower event identifier have
+ * an higher priority.
+ *
+ * @param[in] events events that the function should wait
+ * for, @p ALL_EVENTS enables all the events
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The mask of the lowest event id served and cleared.
+ * @retval 0 if the operation has timed out.
+ *
+ * @api
+ */
+eventmask_t chEvtWaitOneTimeout(eventmask_t events, sysinterval_t timeout) {
+ thread_t *ctp = currp;
+ eventmask_t m;
+
+ chSysLock();
+ m = ctp->epending & events;
+ if (m == (eventmask_t)0) {
+ if (TIME_IMMEDIATE == timeout) {
+ chSysUnlock();
+ return (eventmask_t)0;
+ }
+ ctp->u.ewmask = events;
+ if (chSchGoSleepTimeoutS(CH_STATE_WTOREVT, timeout) < MSG_OK) {
+ chSysUnlock();
+ return (eventmask_t)0;
+ }
+ m = ctp->epending & events;
+ }
+ m ^= m & (m - (eventmask_t)1);
+ ctp->epending &= ~m;
+ chSysUnlock();
+
+ return m;
+}
+
+/**
+ * @brief Waits for any of the specified events.
+ * @details The function waits for any event among those specified in
+ * @p events to become pending then the events are cleared and
+ * returned.
+ *
+ * @param[in] events events that the function should wait
+ * for, @p ALL_EVENTS enables all the events
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The mask of the served and cleared events.
+ * @retval 0 if the operation has timed out.
+ *
+ * @api
+ */
+eventmask_t chEvtWaitAnyTimeout(eventmask_t events, sysinterval_t timeout) {
+ thread_t *ctp = currp;
+ eventmask_t m;
+
+ chSysLock();
+ m = ctp->epending & events;
+ if (m == (eventmask_t)0) {
+ if (TIME_IMMEDIATE == timeout) {
+ chSysUnlock();
+ return (eventmask_t)0;
+ }
+ ctp->u.ewmask = events;
+ if (chSchGoSleepTimeoutS(CH_STATE_WTOREVT, timeout) < MSG_OK) {
+ chSysUnlock();
+ return (eventmask_t)0;
+ }
+ m = ctp->epending & events;
+ }
+ ctp->epending &= ~m;
+ chSysUnlock();
+
+ return m;
+}
+
+/**
+ * @brief Waits for all the specified events.
+ * @details The function waits for all the events specified in @p events to
+ * become pending then the events are cleared and returned.
+ *
+ * @param[in] events events that the function should wait
+ * for, @p ALL_EVENTS requires all the events
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The mask of the served and cleared events.
+ * @retval 0 if the operation has timed out.
+ *
+ * @api
+ */
+eventmask_t chEvtWaitAllTimeout(eventmask_t events, sysinterval_t timeout) {
+ thread_t *ctp = currp;
+
+ chSysLock();
+ if ((ctp->epending & events) != events) {
+ if (TIME_IMMEDIATE == timeout) {
+ chSysUnlock();
+ return (eventmask_t)0;
+ }
+ ctp->u.ewmask = events;
+ if (chSchGoSleepTimeoutS(CH_STATE_WTANDEVT, timeout) < MSG_OK) {
+ chSysUnlock();
+ return (eventmask_t)0;
+ }
+ }
+ ctp->epending &= ~events;
+ chSysUnlock();
+
+ return events;
+}
+#endif /* CH_CFG_USE_EVENTS_TIMEOUT == TRUE */
+
+#endif /* CH_CFG_USE_EVENTS == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/src/chmsg.c b/ChibiOS_20.3.2/os/rt/src/chmsg.c
new file mode 100644
index 0000000..2003dd0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/src/chmsg.c
@@ -0,0 +1,221 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/src/chmsg.c
+ * @brief Messages code.
+ *
+ * @addtogroup messages
+ * @details Synchronous inter-thread messages APIs and services.
+ * Operation Mode
+ * Synchronous messages are an easy to use and fast IPC mechanism,
+ * threads can both act as message servers and/or message clients,
+ * the mechanism allows data to be carried in both directions. Note
+ * that messages are not copied between the client and server threads
+ * but just a pointer passed so the exchange is very time
+ * efficient.
+ * Messages are scalar data types of type @p msg_t that are guaranteed
+ * to be size compatible with data pointers. Note that on some
+ * architectures function pointers can be larger that @p msg_t.
+ * Messages are usually processed in FIFO order but it is possible to
+ * process them in priority order by enabling the
+ * @p CH_CFG_USE_MESSAGES_PRIORITY option in @p chconf.h.
+ * @pre In order to use the message APIs the @p CH_CFG_USE_MESSAGES option
+ * must be enabled in @p chconf.h.
+ * @post Enabling messages requires 6-12 (depending on the architecture)
+ * extra bytes in the @p thread_t structure.
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+#if CH_CFG_USE_MESSAGES_PRIORITY == TRUE
+#define msg_insert(tp, qp) queue_prio_insert(tp, qp)
+#else
+#define msg_insert(tp, qp) queue_insert(tp, qp)
+#endif
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Sends a message to the specified thread.
+ * @details The sender is stopped until the receiver executes a
+ * @p chMsgRelease()after receiving the message.
+ *
+ * @param[in] tp the pointer to the thread
+ * @param[in] msg the message
+ * @return The answer message from @p chMsgRelease().
+ *
+ * @api
+ */
+msg_t chMsgSend(thread_t *tp, msg_t msg) {
+ thread_t *ctp = currp;
+
+ chDbgCheck(tp != NULL);
+
+ chSysLock();
+ ctp->u.sentmsg = msg;
+ msg_insert(ctp, &tp->msgqueue);
+ if (tp->state == CH_STATE_WTMSG) {
+ (void) chSchReadyI(tp);
+ }
+ chSchGoSleepS(CH_STATE_SNDMSGQ);
+ msg = ctp->u.rdymsg;
+ chSysUnlock();
+
+ return msg;
+}
+
+/**
+ * @brief Suspends the thread and waits for an incoming message.
+ * @post After receiving a message the function @p chMsgGet() must be
+ * called in order to retrieve the message and then @p chMsgRelease()
+ * must be invoked in order to acknowledge the reception and send
+ * the answer.
+ * @note If the message is a pointer then you can assume that the data
+ * pointed by the message is stable until you invoke @p chMsgRelease()
+ * because the sending thread is suspended until then.
+ * @note The reference counter of the sender thread is not increased, the
+ * returned pointer is a temporary reference.
+ *
+ * @return A pointer to the thread carrying the message.
+ *
+ * @sclass
+ */
+thread_t *chMsgWaitS(void) {
+ thread_t *tp;
+
+ chDbgCheckClassS();
+
+ if (!chMsgIsPendingI(currp)) {
+ chSchGoSleepS(CH_STATE_WTMSG);
+ }
+ tp = queue_fifo_remove(&currp->msgqueue);
+ tp->state = CH_STATE_SNDMSG;
+
+ return tp;
+}
+
+/**
+ * @brief Suspends the thread and waits for an incoming message or a
+ * timeout to occur.
+ * @post After receiving a message the function @p chMsgGet() must be
+ * called in order to retrieve the message and then @p chMsgRelease()
+ * must be invoked in order to acknowledge the reception and send
+ * the answer.
+ * @note If the message is a pointer then you can assume that the data
+ * pointed by the message is stable until you invoke @p chMsgRelease()
+ * because the sending thread is suspended until then.
+ * @note The reference counter of the sender thread is not increased, the
+ * returned pointer is a temporary reference.
+ *
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A pointer to the thread carrying the message.
+ * @retval NULL if a timeout occurred.
+ *
+ * @sclass
+ */
+thread_t *chMsgWaitTimeoutS(sysinterval_t timeout) {
+ thread_t *tp;
+
+ chDbgCheckClassS();
+
+ if (!chMsgIsPendingI(currp)) {
+ if (chSchGoSleepTimeoutS(CH_STATE_WTMSG, timeout) != MSG_OK) {
+ return NULL;
+ }
+ }
+ tp = queue_fifo_remove(&currp->msgqueue);
+ tp->state = CH_STATE_SNDMSG;
+
+ return tp;
+}
+
+/**
+ * @brief Poll to check for an incoming message.
+ * @post If a message is available the function @p chMsgGet() must be
+ * called in order to retrieve the message and then @p chMsgRelease()
+ * must be invoked in order to acknowledge the reception and send
+ * the answer.
+ * @note If the message is a pointer then you can assume that the data
+ * pointed by the message is stable until you invoke @p chMsgRelease()
+ * because the sending thread is suspended until then.
+ * @note The reference counter of the sender thread is not increased, the
+ * returned pointer is a temporary reference.
+ *
+ * @return Result of the poll.
+ * @retval NULL if no incoming message waiting.
+ *
+ * @sclass
+ */
+thread_t *chMsgPollS(void) {
+ thread_t *tp = NULL;
+
+ if (chMsgIsPendingI(currp)) {
+ tp = queue_fifo_remove(&currp->msgqueue);
+ tp->state = CH_STATE_SNDMSG;
+ }
+
+ return tp;
+}
+
+/**
+ * @brief Releases a sender thread specifying a response message.
+ * @pre Invoke this function only after a message has been received
+ * using @p chMsgWait().
+ *
+ * @param[in] tp pointer to the thread
+ * @param[in] msg message to be returned to the sender
+ *
+ * @api
+ */
+void chMsgRelease(thread_t *tp, msg_t msg) {
+
+ chSysLock();
+ chDbgAssert(tp->state == CH_STATE_SNDMSG, "invalid state");
+ chMsgReleaseS(tp, msg);
+ chSysUnlock();
+}
+
+#endif /* CH_CFG_USE_MESSAGES == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/src/chmtx.c b/ChibiOS_20.3.2/os/rt/src/chmtx.c
new file mode 100644
index 0000000..e7744f1
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/src/chmtx.c
@@ -0,0 +1,537 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/src/chmtx.c
+ * @brief Mutexes code.
+ *
+ * @addtogroup mutexes
+ * @details Mutexes related APIs and services.
+ * Operation mode
+ * A mutex is a threads synchronization object that can be in two
+ * distinct states:
+ * - Not owned (unlocked).
+ * - Owned by a thread (locked).
+ * .
+ * Operations defined for mutexes:
+ * - Lock: The mutex is checked, if the mutex is not owned by
+ * some other thread then it is associated to the locking thread
+ * else the thread is queued on the mutex in a list ordered by
+ * priority.
+ * - Unlock: The mutex is released by the owner and the highest
+ * priority thread waiting in the queue, if any, is resumed and made
+ * owner of the mutex.
+ * .
+ * Constraints
+ * In ChibiOS/RT the Unlock operations must always be performed
+ * in lock-reverse order. This restriction both improves the
+ * performance and is required for an efficient implementation
+ * of the priority inheritance mechanism.
+ * Operating under this restriction also ensures that deadlocks
+ * are no possible.
+ *
+ * Recursive mode
+ * By default mutexes are not recursive, this mean that it is not
+ * possible to take a mutex already owned by the same thread.
+ * It is possible to enable the recursive behavior by enabling the
+ * option @p CH_CFG_USE_MUTEXES_RECURSIVE.
+ *
+ * The priority inversion problem
+ * The mutexes in ChibiOS/RT implements the full priority
+ * inheritance mechanism in order handle the priority inversion
+ * problem.
+ * When a thread is queued on a mutex, any thread, directly or
+ * indirectly, holding the mutex gains the same priority of the
+ * waiting thread (if their priority was not already equal or higher).
+ * The mechanism works with any number of nested mutexes and any
+ * number of involved threads. The algorithm complexity (worst case)
+ * is N with N equal to the number of nested mutexes.
+ * @pre In order to use the mutex APIs the @p CH_CFG_USE_MUTEXES option
+ * must be enabled in @p chconf.h.
+ * @post Enabling mutexes requires 5-12 (depending on the architecture)
+ * extra bytes in the @p thread_t structure.
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes s @p mutex_t structure.
+ *
+ * @param[out] mp pointer to a @p mutex_t structure
+ *
+ * @init
+ */
+void chMtxObjectInit(mutex_t *mp) {
+
+ chDbgCheck(mp != NULL);
+
+ queue_init(&mp->queue);
+ mp->owner = NULL;
+#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
+ mp->cnt = (cnt_t)0;
+#endif
+}
+
+/**
+ * @brief Locks the specified mutex.
+ * @post The mutex is locked and inserted in the per-thread stack of owned
+ * mutexes.
+ *
+ * @param[in] mp pointer to the @p mutex_t structure
+ *
+ * @api
+ */
+void chMtxLock(mutex_t *mp) {
+
+ chSysLock();
+ chMtxLockS(mp);
+ chSysUnlock();
+}
+
+/**
+ * @brief Locks the specified mutex.
+ * @post The mutex is locked and inserted in the per-thread stack of owned
+ * mutexes.
+ *
+ * @param[in] mp pointer to the @p mutex_t structure
+ *
+ * @sclass
+ */
+void chMtxLockS(mutex_t *mp) {
+ thread_t *ctp = currp;
+
+ chDbgCheckClassS();
+ chDbgCheck(mp != NULL);
+
+ /* Is the mutex already locked? */
+ if (mp->owner != NULL) {
+#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
+
+ chDbgAssert(mp->cnt >= (cnt_t)1, "counter is not positive");
+
+ /* If the mutex is already owned by this thread, the counter is increased
+ and there is no need of more actions.*/
+ if (mp->owner == ctp) {
+ mp->cnt++;
+ }
+ else {
+#endif
+ /* Priority inheritance protocol; explores the thread-mutex dependencies
+ boosting the priority of all the affected threads to equal the
+ priority of the running thread requesting the mutex.*/
+ thread_t *tp = mp->owner;
+
+ /* Does the running thread have higher priority than the mutex
+ owning thread? */
+ while (tp->prio < ctp->prio) {
+ /* Make priority of thread tp match the running thread's priority.*/
+ tp->prio = ctp->prio;
+
+ /* The following states need priority queues reordering.*/
+ switch (tp->state) {
+ case CH_STATE_WTMTX:
+ /* Re-enqueues the mutex owner with its new priority.*/
+ queue_prio_insert(queue_dequeue(tp), &tp->u.wtmtxp->queue);
+ tp = tp->u.wtmtxp->owner;
+ /*lint -e{9042} [16.1] Continues the while.*/
+ continue;
+#if (CH_CFG_USE_CONDVARS == TRUE) || \
+ ((CH_CFG_USE_SEMAPHORES == TRUE) && \
+ (CH_CFG_USE_SEMAPHORES_PRIORITY == TRUE)) || \
+ ((CH_CFG_USE_MESSAGES == TRUE) && \
+ (CH_CFG_USE_MESSAGES_PRIORITY == TRUE))
+#if CH_CFG_USE_CONDVARS == TRUE
+ case CH_STATE_WTCOND:
+#endif
+#if (CH_CFG_USE_SEMAPHORES == TRUE) && \
+ (CH_CFG_USE_SEMAPHORES_PRIORITY == TRUE)
+ case CH_STATE_WTSEM:
+#endif
+#if (CH_CFG_USE_MESSAGES == TRUE) && (CH_CFG_USE_MESSAGES_PRIORITY == TRUE)
+ case CH_STATE_SNDMSGQ:
+#endif
+ /* Re-enqueues tp with its new priority on the queue.*/
+ queue_prio_insert(queue_dequeue(tp), &tp->u.wtmtxp->queue);
+ break;
+#endif
+ case CH_STATE_READY:
+#if CH_DBG_ENABLE_ASSERTS == TRUE
+ /* Prevents an assertion in chSchReadyI().*/
+ tp->state = CH_STATE_CURRENT;
+#endif
+ /* Re-enqueues tp with its new priority on the ready list.*/
+ (void) chSchReadyI(queue_dequeue(tp));
+ break;
+ default:
+ /* Nothing to do for other states.*/
+ break;
+ }
+ break;
+ }
+
+ /* Sleep on the mutex.*/
+ queue_prio_insert(ctp, &mp->queue);
+ ctp->u.wtmtxp = mp;
+ chSchGoSleepS(CH_STATE_WTMTX);
+
+ /* It is assumed that the thread performing the unlock operation assigns
+ the mutex to this thread.*/
+ chDbgAssert(mp->owner == ctp, "not owner");
+ chDbgAssert(ctp->mtxlist == mp, "not owned");
+#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
+ chDbgAssert(mp->cnt == (cnt_t)1, "counter is not one");
+ }
+#endif
+ }
+ else {
+#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
+ chDbgAssert(mp->cnt == (cnt_t)0, "counter is not zero");
+
+ mp->cnt++;
+#endif
+ /* It was not owned, inserted in the owned mutexes list.*/
+ mp->owner = ctp;
+ mp->next = ctp->mtxlist;
+ ctp->mtxlist = mp;
+ }
+}
+
+/**
+ * @brief Tries to lock a mutex.
+ * @details This function attempts to lock a mutex, if the mutex is already
+ * locked by another thread then the function exits without waiting.
+ * @post The mutex is locked and inserted in the per-thread stack of owned
+ * mutexes.
+ * @note This function does not have any overhead related to the
+ * priority inheritance mechanism because it does not try to
+ * enter a sleep state.
+ *
+ * @param[in] mp pointer to the @p mutex_t structure
+ * @return The operation status.
+ * @retval true if the mutex has been successfully acquired
+ * @retval false if the lock attempt failed.
+ *
+ * @api
+ */
+bool chMtxTryLock(mutex_t *mp) {
+ bool b;
+
+ chSysLock();
+ b = chMtxTryLockS(mp);
+ chSysUnlock();
+
+ return b;
+}
+
+/**
+ * @brief Tries to lock a mutex.
+ * @details This function attempts to lock a mutex, if the mutex is already
+ * taken by another thread then the function exits without waiting.
+ * @post The mutex is locked and inserted in the per-thread stack of owned
+ * mutexes.
+ * @note This function does not have any overhead related to the
+ * priority inheritance mechanism because it does not try to
+ * enter a sleep state.
+ *
+ * @param[in] mp pointer to the @p mutex_t structure
+ * @return The operation status.
+ * @retval true if the mutex has been successfully acquired
+ * @retval false if the lock attempt failed.
+ *
+ * @sclass
+ */
+bool chMtxTryLockS(mutex_t *mp) {
+
+ chDbgCheckClassS();
+ chDbgCheck(mp != NULL);
+
+ if (mp->owner != NULL) {
+#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
+
+ chDbgAssert(mp->cnt >= (cnt_t)1, "counter is not positive");
+
+ if (mp->owner == currp) {
+ mp->cnt++;
+ return true;
+ }
+#endif
+ return false;
+ }
+#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
+
+ chDbgAssert(mp->cnt == (cnt_t)0, "counter is not zero");
+
+ mp->cnt++;
+#endif
+ mp->owner = currp;
+ mp->next = currp->mtxlist;
+ currp->mtxlist = mp;
+ return true;
+}
+
+/**
+ * @brief Unlocks the specified mutex.
+ * @note Mutexes must be unlocked in reverse lock order. Violating this
+ * rules will result in a panic if assertions are enabled.
+ * @pre The invoking thread must have at least one owned mutex.
+ * @post The mutex is unlocked and removed from the per-thread stack of
+ * owned mutexes.
+ *
+ * @param[in] mp pointer to the @p mutex_t structure
+ *
+ * @api
+ */
+void chMtxUnlock(mutex_t *mp) {
+ thread_t *ctp = currp;
+ mutex_t *lmp;
+
+ chDbgCheck(mp != NULL);
+
+ chSysLock();
+
+ chDbgAssert(ctp->mtxlist != NULL, "owned mutexes list empty");
+ chDbgAssert(ctp->mtxlist->owner == ctp, "ownership failure");
+#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
+ chDbgAssert(mp->cnt >= (cnt_t)1, "counter is not positive");
+
+ if (--mp->cnt == (cnt_t)0) {
+#endif
+
+ chDbgAssert(ctp->mtxlist == mp, "not next in list");
+
+ /* Removes the top mutex from the thread's owned mutexes list and marks
+ it as not owned. Note, it is assumed to be the same mutex passed as
+ parameter of this function.*/
+ ctp->mtxlist = mp->next;
+
+ /* If a thread is waiting on the mutex then the fun part begins.*/
+ if (chMtxQueueNotEmptyS(mp)) {
+ thread_t *tp;
+
+ /* Recalculates the optimal thread priority by scanning the owned
+ mutexes list.*/
+ tprio_t newprio = ctp->realprio;
+ lmp = ctp->mtxlist;
+ while (lmp != NULL) {
+ /* If the highest priority thread waiting in the mutexes list has a
+ greater priority than the current thread base priority then the
+ final priority will have at least that priority.*/
+ if (chMtxQueueNotEmptyS(lmp) &&
+ (lmp->queue.next->prio > newprio)) {
+ newprio = lmp->queue.next->prio;
+ }
+ lmp = lmp->next;
+ }
+
+ /* Assigns to the current thread the highest priority among all the
+ waiting threads.*/
+ ctp->prio = newprio;
+
+ /* Awakens the highest priority thread waiting for the unlocked mutex and
+ assigns the mutex to it.*/
+#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
+ mp->cnt = (cnt_t)1;
+#endif
+ tp = queue_fifo_remove(&mp->queue);
+ mp->owner = tp;
+ mp->next = tp->mtxlist;
+ tp->mtxlist = mp;
+
+ /* Note, not using chSchWakeupS() because that function expects the
+ current thread to have the higher or equal priority than the ones
+ in the ready list. This is not necessarily true here because we
+ just changed priority.*/
+ (void) chSchReadyI(tp);
+ chSchRescheduleS();
+ }
+ else {
+ mp->owner = NULL;
+ }
+#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
+ }
+#endif
+
+ chSysUnlock();
+}
+
+/**
+ * @brief Unlocks the specified mutex.
+ * @note Mutexes must be unlocked in reverse lock order. Violating this
+ * rules will result in a panic if assertions are enabled.
+ * @pre The invoking thread must have at least one owned mutex.
+ * @post The mutex is unlocked and removed from the per-thread stack of
+ * owned mutexes.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel.
+ *
+ * @param[in] mp pointer to the @p mutex_t structure
+ *
+ * @sclass
+ */
+void chMtxUnlockS(mutex_t *mp) {
+ thread_t *ctp = currp;
+ mutex_t *lmp;
+
+ chDbgCheckClassS();
+ chDbgCheck(mp != NULL);
+
+ chDbgAssert(ctp->mtxlist != NULL, "owned mutexes list empty");
+ chDbgAssert(ctp->mtxlist->owner == ctp, "ownership failure");
+#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
+ chDbgAssert(mp->cnt >= (cnt_t)1, "counter is not positive");
+
+ if (--mp->cnt == (cnt_t)0) {
+#endif
+
+ chDbgAssert(ctp->mtxlist == mp, "not next in list");
+
+ /* Removes the top mutex from the thread's owned mutexes list and marks
+ it as not owned. Note, it is assumed to be the same mutex passed as
+ parameter of this function.*/
+ ctp->mtxlist = mp->next;
+
+ /* If a thread is waiting on the mutex then the fun part begins.*/
+ if (chMtxQueueNotEmptyS(mp)) {
+ thread_t *tp;
+
+ /* Recalculates the optimal thread priority by scanning the owned
+ mutexes list.*/
+ tprio_t newprio = ctp->realprio;
+ lmp = ctp->mtxlist;
+ while (lmp != NULL) {
+ /* If the highest priority thread waiting in the mutexes list has a
+ greater priority than the current thread base priority then the
+ final priority will have at least that priority.*/
+ if (chMtxQueueNotEmptyS(lmp) &&
+ (lmp->queue.next->prio > newprio)) {
+ newprio = lmp->queue.next->prio;
+ }
+ lmp = lmp->next;
+ }
+
+ /* Assigns to the current thread the highest priority among all the
+ waiting threads.*/
+ ctp->prio = newprio;
+
+ /* Awakens the highest priority thread waiting for the unlocked mutex and
+ assigns the mutex to it.*/
+#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
+ mp->cnt = (cnt_t)1;
+#endif
+ tp = queue_fifo_remove(&mp->queue);
+ mp->owner = tp;
+ mp->next = tp->mtxlist;
+ tp->mtxlist = mp;
+ (void) chSchReadyI(tp);
+ }
+ else {
+ mp->owner = NULL;
+ }
+#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
+ }
+#endif
+}
+
+/**
+ * @brief Unlocks all mutexes owned by the invoking thread.
+ * @post The stack of owned mutexes is emptied and all the found
+ * mutexes are unlocked.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel.
+ * @note This function is MUCH MORE efficient than releasing the
+ * mutexes one by one and not just because the call overhead,
+ * this function does not have any overhead related to the priority
+ * inheritance mechanism.
+ *
+ * @sclass
+ */
+void chMtxUnlockAllS(void) {
+ thread_t *ctp = currp;
+
+ if (ctp->mtxlist != NULL) {
+ do {
+ mutex_t *mp = ctp->mtxlist;
+ ctp->mtxlist = mp->next;
+ if (chMtxQueueNotEmptyS(mp)) {
+ thread_t *tp;
+#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
+ mp->cnt = (cnt_t)1;
+#endif
+ tp = queue_fifo_remove(&mp->queue);
+ mp->owner = tp;
+ mp->next = tp->mtxlist;
+ tp->mtxlist = mp;
+ (void) chSchReadyI(tp);
+ }
+ else {
+#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
+ mp->cnt = (cnt_t)0;
+#endif
+ mp->owner = NULL;
+ }
+ } while (ctp->mtxlist != NULL);
+ ctp->prio = ctp->realprio;
+ chSchRescheduleS();
+ }
+}
+
+/**
+ * @brief Unlocks all mutexes owned by the invoking thread.
+ * @post The stack of owned mutexes is emptied and all the found
+ * mutexes are unlocked.
+ * @note This function is MUCH MORE efficient than releasing the
+ * mutexes one by one and not just because the call overhead,
+ * this function does not have any overhead related to the priority
+ * inheritance mechanism.
+ *
+ * @api
+ */
+void chMtxUnlockAll(void) {
+
+ chSysLock();
+ chMtxUnlockAllS();
+ chSysUnlock();
+}
+
+#endif /* CH_CFG_USE_MUTEXES == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/src/chregistry.c b/ChibiOS_20.3.2/os/rt/src/chregistry.c
new file mode 100644
index 0000000..69be197
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/src/chregistry.c
@@ -0,0 +1,268 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/src/chregistry.c
+ * @brief Threads registry code.
+ *
+ * @addtogroup registry
+ * @details Threads Registry related APIs and services.
+ * Operation mode
+ * The Threads Registry is a double linked list that holds all the
+ * active threads in the system.
+ * Operations defined for the registry:
+ * - First, returns the first, in creation order, active thread
+ * in the system.
+ * - Next, returns the next, in creation order, active thread
+ * in the system.
+ * .
+ * The registry is meant to be mainly a debug feature, for example,
+ * using the registry a debugger can enumerate the active threads
+ * in any given moment or the shell can print the active threads
+ * and their state.
+ * Another possible use is for centralized threads memory management,
+ * terminating threads can pulse an event source and an event handler
+ * can perform a scansion of the registry in order to recover the
+ * memory.
+ * @pre In order to use the threads registry the @p CH_CFG_USE_REGISTRY
+ * option must be enabled in @p chconf.h.
+ * @{
+ */
+
+#include
+
+#include "ch.h"
+
+#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+#define _offsetof(st, m) \
+ /*lint -save -e9005 -e9033 -e413 [11.8, 10.8 1.3] Normal pointers
+ arithmetic, it is safe.*/ \
+ ((size_t)((char *)&((st *)0)->m - (char *)0)) \
+ /*lint -restore*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/*
+ * OS signature in ROM plus debug-related information.
+ */
+ROMCONST chdebug_t ch_debug = {
+ {'m', 'a', 'i', 'n'},
+ (uint8_t)0,
+ (uint8_t)sizeof (chdebug_t),
+ (uint16_t)(((unsigned)CH_KERNEL_MAJOR << 11U) |
+ ((unsigned)CH_KERNEL_MINOR << 6U) |
+ ((unsigned)CH_KERNEL_PATCH << 0U)),
+ (uint8_t)sizeof (void *),
+ (uint8_t)sizeof (systime_t),
+ (uint8_t)sizeof (thread_t),
+ (uint8_t)_offsetof(thread_t, prio),
+ (uint8_t)_offsetof(thread_t, ctx),
+ (uint8_t)_offsetof(thread_t, newer),
+ (uint8_t)_offsetof(thread_t, older),
+ (uint8_t)_offsetof(thread_t, name),
+#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE)
+ (uint8_t)_offsetof(thread_t, wabase),
+#else
+ (uint8_t)0,
+#endif
+ (uint8_t)_offsetof(thread_t, state),
+ (uint8_t)_offsetof(thread_t, flags),
+#if CH_CFG_USE_DYNAMIC == TRUE
+ (uint8_t)_offsetof(thread_t, refs),
+#else
+ (uint8_t)0,
+#endif
+#if CH_CFG_TIME_QUANTUM > 0
+ (uint8_t)_offsetof(thread_t, ticks),
+#else
+ (uint8_t)0,
+#endif
+#if CH_DBG_THREADS_PROFILING == TRUE
+ (uint8_t)_offsetof(thread_t, time)
+#else
+ (uint8_t)0
+#endif
+};
+
+/**
+ * @brief Returns the first thread in the system.
+ * @details Returns the most ancient thread in the system, usually this is
+ * the main thread unless it terminated. A reference is added to the
+ * returned thread in order to make sure its status is not lost.
+ * @note This function cannot return @p NULL because there is always at
+ * least one thread in the system.
+ *
+ * @return A reference to the most ancient thread.
+ *
+ * @api
+ */
+thread_t *chRegFirstThread(void) {
+ thread_t *tp;
+
+ chSysLock();
+ tp = ch.rlist.newer;
+#if CH_CFG_USE_DYNAMIC == TRUE
+ tp->refs++;
+#endif
+ chSysUnlock();
+
+ return tp;
+}
+
+/**
+ * @brief Returns the thread next to the specified one.
+ * @details The reference counter of the specified thread is decremented and
+ * the reference counter of the returned thread is incremented.
+ *
+ * @param[in] tp pointer to the thread
+ * @return A reference to the next thread.
+ * @retval NULL if there is no next thread.
+ *
+ * @api
+ */
+thread_t *chRegNextThread(thread_t *tp) {
+ thread_t *ntp;
+
+ chSysLock();
+ ntp = tp->newer;
+ /*lint -save -e9087 -e740 [11.3, 1.3] Cast required by list handling.*/
+ if (ntp == (thread_t *)&ch.rlist) {
+ /*lint -restore*/
+ ntp = NULL;
+ }
+#if CH_CFG_USE_DYNAMIC == TRUE
+ else {
+ chDbgAssert(ntp->refs < (trefs_t)255, "too many references");
+ ntp->refs++;
+ }
+#endif
+ chSysUnlock();
+#if CH_CFG_USE_DYNAMIC == TRUE
+ chThdRelease(tp);
+#endif
+
+ return ntp;
+}
+
+/**
+ * @brief Retrieves a thread pointer by name.
+ * @note The reference counter of the found thread is increased by one so
+ * it cannot be disposed incidentally after the pointer has been
+ * returned.
+ *
+ * @param[in] name the thread name
+ * @return A pointer to the found thread.
+ * @retval NULL if a matching thread has not been found.
+ *
+ * @api
+ */
+thread_t *chRegFindThreadByName(const char *name) {
+ thread_t *ctp;
+
+ /* Scanning registry.*/
+ ctp = chRegFirstThread();
+ do {
+ if (strcmp(chRegGetThreadNameX(ctp), name) == 0) {
+ return ctp;
+ }
+ ctp = chRegNextThread(ctp);
+ } while (ctp != NULL);
+
+ return NULL;
+}
+
+/**
+ * @brief Confirms that a pointer is a valid thread pointer.
+ * @note The reference counter of the found thread is increased by one so
+ * it cannot be disposed incidentally after the pointer has been
+ * returned.
+ *
+ * @param[in] tp pointer to the thread
+ * @return A pointer to the found thread.
+ * @retval NULL if a matching thread has not been found.
+ *
+ * @api
+ */
+thread_t *chRegFindThreadByPointer(thread_t *tp) {
+ thread_t *ctp;
+
+ /* Scanning registry.*/
+ ctp = chRegFirstThread();
+ do {
+ if (ctp == tp) {
+ return ctp;
+ }
+ ctp = chRegNextThread(ctp);
+ } while (ctp != NULL);
+
+ return NULL;
+}
+
+#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE) || \
+ defined(__DOXYGEN__)
+/**
+ * @brief Confirms that a working area is being used by some active thread.
+ * @note The reference counter of the found thread is increased by one so
+ * it cannot be disposed incidentally after the pointer has been
+ * returned.
+ *
+ * @param[in] wa pointer to a static working area
+ * @return A pointer to the found thread.
+ * @retval NULL if a matching thread has not been found.
+ *
+ * @api
+ */
+thread_t *chRegFindThreadByWorkingArea(stkalign_t *wa) {
+ thread_t *ctp;
+
+ /* Scanning registry.*/
+ ctp = chRegFirstThread();
+ do {
+ if (chThdGetWorkingAreaX(ctp) == wa) {
+ return ctp;
+ }
+ ctp = chRegNextThread(ctp);
+ } while (ctp != NULL);
+
+ return NULL;
+}
+#endif
+
+#endif /* CH_CFG_USE_REGISTRY == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/src/chschd.c b/ChibiOS_20.3.2/os/rt/src/chschd.c
new file mode 100644
index 0000000..540b1c2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/src/chschd.c
@@ -0,0 +1,610 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/src/chschd.c
+ * @brief Scheduler code.
+ *
+ * @addtogroup scheduler
+ * @details This module provides the default portable scheduler code.
+ * @{
+ */
+
+#include "ch.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief System data structures.
+ */
+ch_system_t ch;
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Scheduler initialization.
+ *
+ * @notapi
+ */
+void _scheduler_init(void) {
+
+ queue_init(&ch.rlist.queue);
+ ch.rlist.prio = NOPRIO;
+#if CH_CFG_USE_REGISTRY == TRUE
+ ch.rlist.newer = (thread_t *)&ch.rlist;
+ ch.rlist.older = (thread_t *)&ch.rlist;
+#endif
+}
+
+#if (CH_CFG_OPTIMIZE_SPEED == FALSE) || defined(__DOXYGEN__)
+/**
+ * @brief Inserts a thread into a priority ordered queue.
+ * @note The insertion is done by scanning the list from the highest
+ * priority toward the lowest.
+ *
+ * @param[in] tp the pointer to the thread to be inserted in the list
+ * @param[in] tqp the pointer to the threads list header
+ *
+ * @notapi
+ */
+void queue_prio_insert(thread_t *tp, threads_queue_t *tqp) {
+
+ thread_t *cp = (thread_t *)tqp;
+ do {
+ cp = cp->queue.next;
+ } while ((cp != (thread_t *)tqp) && (cp->prio >= tp->prio));
+ tp->queue.next = cp;
+ tp->queue.prev = cp->queue.prev;
+ tp->queue.prev->queue.next = tp;
+ cp->queue.prev = tp;
+}
+
+/**
+ * @brief Inserts a thread into a queue.
+ *
+ * @param[in] tp the pointer to the thread to be inserted in the list
+ * @param[in] tqp the pointer to the threads list header
+ *
+ * @notapi
+ */
+void queue_insert(thread_t *tp, threads_queue_t *tqp) {
+
+ tp->queue.next = (thread_t *)tqp;
+ tp->queue.prev = tqp->prev;
+ tp->queue.prev->queue.next = tp;
+ tqp->prev = tp;
+}
+
+/**
+ * @brief Removes the first-out thread from a queue and returns it.
+ * @note If the queue is priority ordered then this function returns the
+ * thread with the highest priority.
+ *
+ * @param[in] tqp the pointer to the threads list header
+ * @return The removed thread pointer.
+ *
+ * @notapi
+ */
+thread_t *queue_fifo_remove(threads_queue_t *tqp) {
+ thread_t *tp = tqp->next;
+
+ tqp->next = tp->queue.next;
+ tqp->next->queue.prev = (thread_t *)tqp;
+
+ return tp;
+}
+
+/**
+ * @brief Removes the last-out thread from a queue and returns it.
+ * @note If the queue is priority ordered then this function returns the
+ * thread with the lowest priority.
+ *
+ * @param[in] tqp the pointer to the threads list header
+ * @return The removed thread pointer.
+ *
+ * @notapi
+ */
+thread_t *queue_lifo_remove(threads_queue_t *tqp) {
+ thread_t *tp = tqp->prev;
+
+ tqp->prev = tp->queue.prev;
+ tqp->prev->queue.next = (thread_t *)tqp;
+
+ return tp;
+}
+
+/**
+ * @brief Removes a thread from a queue and returns it.
+ * @details The thread is removed from the queue regardless of its relative
+ * position and regardless the used insertion method.
+ *
+ * @param[in] tp the pointer to the thread to be removed from the queue
+ * @return The removed thread pointer.
+ *
+ * @notapi
+ */
+thread_t *queue_dequeue(thread_t *tp) {
+
+ tp->queue.prev->queue.next = tp->queue.next;
+ tp->queue.next->queue.prev = tp->queue.prev;
+
+ return tp;
+}
+
+/**
+ * @brief Pushes a thread_t on top of a stack list.
+ *
+ * @param[in] tp the pointer to the thread to be inserted in the list
+ * @param[in] tlp the pointer to the threads list header
+ *
+ * @notapi
+ */
+void list_insert(thread_t *tp, threads_list_t *tlp) {
+
+ tp->queue.next = tlp->next;
+ tlp->next = tp;
+}
+
+/**
+ * @brief Pops a thread from the top of a stack list and returns it.
+ * @pre The list must be non-empty before calling this function.
+ *
+ * @param[in] tlp the pointer to the threads list header
+ * @return The removed thread pointer.
+ *
+ * @notapi
+ */
+thread_t *list_remove(threads_list_t *tlp) {
+
+ thread_t *tp = tlp->next;
+ tlp->next = tp->queue.next;
+
+ return tp;
+}
+#endif /* CH_CFG_OPTIMIZE_SPEED */
+
+/**
+ * @brief Inserts a thread in the Ready List placing it behind its peers.
+ * @details The thread is positioned behind all threads with higher or equal
+ * priority.
+ * @pre The thread must not be already inserted in any list through its
+ * @p next and @p prev or list corruption would occur.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] tp the thread to be made ready
+ * @return The thread pointer.
+ *
+ * @iclass
+ */
+thread_t *chSchReadyI(thread_t *tp) {
+ thread_t *cp;
+
+ chDbgCheckClassI();
+ chDbgCheck(tp != NULL);
+ chDbgAssert((tp->state != CH_STATE_READY) &&
+ (tp->state != CH_STATE_FINAL),
+ "invalid state");
+
+ tp->state = CH_STATE_READY;
+ cp = (thread_t *)&ch.rlist.queue;
+ do {
+ cp = cp->queue.next;
+ } while (cp->prio >= tp->prio);
+ /* Insertion on prev.*/
+ tp->queue.next = cp;
+ tp->queue.prev = cp->queue.prev;
+ tp->queue.prev->queue.next = tp;
+ cp->queue.prev = tp;
+
+ return tp;
+}
+
+/**
+ * @brief Inserts a thread in the Ready List placing it ahead its peers.
+ * @details The thread is positioned ahead all threads with higher or equal
+ * priority.
+ * @pre The thread must not be already inserted in any list through its
+ * @p next and @p prev or list corruption would occur.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] tp the thread to be made ready
+ * @return The thread pointer.
+ *
+ * @iclass
+ */
+thread_t *chSchReadyAheadI(thread_t *tp) {
+ thread_t *cp;
+
+ chDbgCheckClassI();
+ chDbgCheck(tp != NULL);
+ chDbgAssert((tp->state != CH_STATE_READY) &&
+ (tp->state != CH_STATE_FINAL),
+ "invalid state");
+
+ tp->state = CH_STATE_READY;
+ cp = (thread_t *)&ch.rlist.queue;
+ do {
+ cp = cp->queue.next;
+ } while (cp->prio > tp->prio);
+ /* Insertion on prev.*/
+ tp->queue.next = cp;
+ tp->queue.prev = cp->queue.prev;
+ tp->queue.prev->queue.next = tp;
+ cp->queue.prev = tp;
+
+ return tp;
+}
+
+/**
+ * @brief Puts the current thread to sleep into the specified state.
+ * @details The thread goes into a sleeping state. The possible
+ * @ref thread_states are defined into @p threads.h.
+ *
+ * @param[in] newstate the new thread state
+ *
+ * @sclass
+ */
+void chSchGoSleepS(tstate_t newstate) {
+ thread_t *otp = currp;
+
+ chDbgCheckClassS();
+
+ /* New state.*/
+ otp->state = newstate;
+
+#if CH_CFG_TIME_QUANTUM > 0
+ /* The thread is renouncing its remaining time slices so it will have a new
+ time quantum when it will wakeup.*/
+ otp->ticks = (tslices_t)CH_CFG_TIME_QUANTUM;
+#endif
+
+ /* Next thread in ready list becomes current.*/
+ currp = queue_fifo_remove(&ch.rlist.queue);
+ currp->state = CH_STATE_CURRENT;
+
+ /* Handling idle-enter hook.*/
+ if (currp->prio == IDLEPRIO) {
+ CH_CFG_IDLE_ENTER_HOOK();
+ }
+
+ /* Swap operation as tail call.*/
+ chSysSwitch(currp, otp);
+}
+
+/*
+ * Timeout wakeup callback.
+ */
+static void wakeup(void *p) {
+ thread_t *tp = (thread_t *)p;
+
+ chSysLockFromISR();
+ switch (tp->state) {
+ case CH_STATE_READY:
+ /* Handling the special case where the thread has been made ready by
+ another thread with higher priority.*/
+ chSysUnlockFromISR();
+ return;
+ case CH_STATE_SUSPENDED:
+ *tp->u.wttrp = NULL;
+ break;
+#if CH_CFG_USE_SEMAPHORES == TRUE
+ case CH_STATE_WTSEM:
+ chSemFastSignalI(tp->u.wtsemp);
+#endif
+ /* Falls through.*/
+ case CH_STATE_QUEUED:
+ /* Falls through.*/
+#if (CH_CFG_USE_CONDVARS == TRUE) && (CH_CFG_USE_CONDVARS_TIMEOUT == TRUE)
+ case CH_STATE_WTCOND:
+#endif
+ /* States requiring dequeuing.*/
+ (void) queue_dequeue(tp);
+ break;
+ default:
+ /* Any other state, nothing to do.*/
+ break;
+ }
+ tp->u.rdymsg = MSG_TIMEOUT;
+ (void) chSchReadyI(tp);
+ chSysUnlockFromISR();
+}
+
+/**
+ * @brief Puts the current thread to sleep into the specified state with
+ * timeout specification.
+ * @details The thread goes into a sleeping state, if it is not awakened
+ * explicitly within the specified timeout then it is forcibly
+ * awakened with a @p MSG_TIMEOUT low level message. The possible
+ * @ref thread_states are defined into @p threads.h.
+ *
+ * @param[in] newstate the new thread state
+ * @param[in] timeout the number of ticks before the operation timeouts, the
+ * special values are handled as follow:
+ * - @a TIME_INFINITE the thread enters an infinite sleep
+ * state, this is equivalent to invoking
+ * @p chSchGoSleepS() but, of course, less efficient.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ * @return The wakeup message.
+ * @retval MSG_TIMEOUT if a timeout occurs.
+ *
+ * @sclass
+ */
+msg_t chSchGoSleepTimeoutS(tstate_t newstate, sysinterval_t timeout) {
+
+ chDbgCheckClassS();
+
+ if (TIME_INFINITE != timeout) {
+ virtual_timer_t vt;
+
+ chVTDoSetI(&vt, timeout, wakeup, currp);
+ chSchGoSleepS(newstate);
+ if (chVTIsArmedI(&vt)) {
+ chVTDoResetI(&vt);
+ }
+ }
+ else {
+ chSchGoSleepS(newstate);
+ }
+
+ return currp->u.rdymsg;
+}
+
+/**
+ * @brief Wakes up a thread.
+ * @details The thread is inserted into the ready list or immediately made
+ * running depending on its relative priority compared to the current
+ * thread.
+ * @pre The thread must not be already inserted in any list through its
+ * @p next and @p prev or list corruption would occur.
+ * @note It is equivalent to a @p chSchReadyI() followed by a
+ * @p chSchRescheduleS() but much more efficient.
+ * @note The function assumes that the current thread has the highest
+ * priority.
+ *
+ * @param[in] ntp the thread to be made ready
+ * @param[in] msg the wakeup message
+ *
+ * @sclass
+ */
+void chSchWakeupS(thread_t *ntp, msg_t msg) {
+ thread_t *otp = currp;
+
+ chDbgCheckClassS();
+
+ chDbgAssert((ch.rlist.queue.next == (thread_t *)&ch.rlist.queue) ||
+ (ch.rlist.current->prio >= ch.rlist.queue.next->prio),
+ "priority order violation");
+
+ /* Storing the message to be retrieved by the target thread when it will
+ restart execution.*/
+ ntp->u.rdymsg = msg;
+
+ /* If the waken thread has a not-greater priority than the current
+ one then it is just inserted in the ready list else it made
+ running immediately and the invoking thread goes in the ready
+ list instead.*/
+ if (ntp->prio <= otp->prio) {
+ (void) chSchReadyI(ntp);
+ }
+ else {
+ otp = chSchReadyAheadI(otp);
+
+ /* Handling idle-leave hook.*/
+ if (otp->prio == IDLEPRIO) {
+ CH_CFG_IDLE_LEAVE_HOOK();
+ }
+
+ /* The extracted thread is marked as current.*/
+ currp = ntp;
+ ntp->state = CH_STATE_CURRENT;
+
+ /* Swap operation as tail call.*/
+ chSysSwitch(ntp, otp);
+ }
+}
+
+/**
+ * @brief Performs a reschedule if a higher priority thread is runnable.
+ * @details If a thread with a higher priority than the current thread is in
+ * the ready list then make the higher priority thread running.
+ *
+ * @sclass
+ */
+void chSchRescheduleS(void) {
+
+ chDbgCheckClassS();
+
+ if (chSchIsRescRequiredI()) {
+ chSchDoRescheduleAhead();
+ }
+}
+
+#if !defined(CH_SCH_IS_PREEMPTION_REQUIRED_HOOKED)
+/**
+ * @brief Evaluates if preemption is required.
+ * @details The decision is taken by comparing the relative priorities and
+ * depending on the state of the round robin timeout counter.
+ * @note Not a user function, it is meant to be invoked by the scheduler
+ * itself or from within the port layer.
+ *
+ * @retval true if there is a thread that must go in running state
+ * immediately.
+ * @retval false if preemption is not required.
+ *
+ * @special
+ */
+bool chSchIsPreemptionRequired(void) {
+ tprio_t p1 = firstprio(&ch.rlist.queue);
+ tprio_t p2 = currp->prio;
+
+#if CH_CFG_TIME_QUANTUM > 0
+ /* If the running thread has not reached its time quantum, reschedule only
+ if the first thread on the ready queue has a higher priority.
+ Otherwise, if the running thread has used up its time quantum, reschedule
+ if the first thread on the ready queue has equal or higher priority.*/
+ return (currp->ticks > (tslices_t)0) ? (p1 > p2) : (p1 >= p2);
+#else
+ /* If the round robin preemption feature is not enabled then performs a
+ simpler comparison.*/
+ return p1 > p2;
+#endif
+}
+#endif /* !defined(CH_SCH_IS_PREEMPTION_REQUIRED_HOOKED) */
+
+/**
+ * @brief Switches to the first thread on the runnable queue.
+ * @details The current thread is positioned in the ready list behind all
+ * threads having the same priority. The thread regains its time
+ * quantum.
+ * @note Not a user function, it is meant to be invoked by the scheduler
+ * itself.
+ *
+ * @special
+ */
+void chSchDoRescheduleBehind(void) {
+ thread_t *otp = currp;
+
+ /* Picks the first thread from the ready queue and makes it current.*/
+ currp = queue_fifo_remove(&ch.rlist.queue);
+ currp->state = CH_STATE_CURRENT;
+
+ /* Handling idle-leave hook.*/
+ if (otp->prio == IDLEPRIO) {
+ CH_CFG_IDLE_LEAVE_HOOK();
+ }
+
+#if CH_CFG_TIME_QUANTUM > 0
+ /* It went behind peers so it gets a new time quantum.*/
+ otp->ticks = (tslices_t)CH_CFG_TIME_QUANTUM;
+#endif
+
+ /* Placing in ready list behind peers.*/
+ otp = chSchReadyI(otp);
+
+ /* Swap operation as tail call.*/
+ chSysSwitch(currp, otp);
+}
+
+/**
+ * @brief Switches to the first thread on the runnable queue.
+ * @details The current thread is positioned in the ready list ahead of all
+ * threads having the same priority.
+ * @note Not a user function, it is meant to be invoked by the scheduler
+ * itself.
+ *
+ * @special
+ */
+void chSchDoRescheduleAhead(void) {
+ thread_t *otp = currp;
+
+ /* Picks the first thread from the ready queue and makes it current.*/
+ currp = queue_fifo_remove(&ch.rlist.queue);
+ currp->state = CH_STATE_CURRENT;
+
+ /* Handling idle-leave hook.*/
+ if (otp->prio == IDLEPRIO) {
+ CH_CFG_IDLE_LEAVE_HOOK();
+ }
+
+ /* Placing in ready list ahead of peers.*/
+ otp = chSchReadyAheadI(otp);
+
+ /* Swap operation as tail call.*/
+ chSysSwitch(currp, otp);
+}
+
+#if !defined(CH_SCH_DO_RESCHEDULE_HOOKED)
+/**
+ * @brief Switches to the first thread on the runnable queue.
+ * @details The current thread is positioned in the ready list behind or
+ * ahead of all threads having the same priority depending on
+ * if it used its whole time slice.
+ * @note Not a user function, it is meant to be invoked by the scheduler
+ * itself or from within the port layer.
+ *
+ * @special
+ */
+void chSchDoReschedule(void) {
+ thread_t *otp = currp;
+
+ /* Picks the first thread from the ready queue and makes it current.*/
+ currp = queue_fifo_remove(&ch.rlist.queue);
+ currp->state = CH_STATE_CURRENT;
+
+ /* Handling idle-leave hook.*/
+ if (otp->prio == IDLEPRIO) {
+ CH_CFG_IDLE_LEAVE_HOOK();
+ }
+
+#if CH_CFG_TIME_QUANTUM > 0
+ /* If CH_CFG_TIME_QUANTUM is enabled then there are two different scenarios
+ to handle on preemption: time quantum elapsed or not.*/
+ if (otp->ticks == (tslices_t)0) {
+
+ /* The thread consumed its time quantum so it is enqueued behind threads
+ with same priority level, however, it acquires a new time quantum.*/
+ otp = chSchReadyI(otp);
+
+ /* The thread being swapped out receives a new time quantum.*/
+ otp->ticks = (tslices_t)CH_CFG_TIME_QUANTUM;
+ }
+ else {
+ /* The thread didn't consume all its time quantum so it is put ahead of
+ threads with equal priority and does not acquire a new time quantum.*/
+ otp = chSchReadyAheadI(otp);
+ }
+#else /* !(CH_CFG_TIME_QUANTUM > 0) */
+ /* If the round-robin mechanism is disabled then the thread goes always
+ ahead of its peers.*/
+ otp = chSchReadyAheadI(otp);
+#endif /* !(CH_CFG_TIME_QUANTUM > 0) */
+
+ /* Swap operation as tail call.*/
+ chSysSwitch(currp, otp);
+}
+#endif /* !defined(CH_SCH_DO_RESCHEDULE_HOOKED) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/src/chsem.c b/ChibiOS_20.3.2/os/rt/src/chsem.c
new file mode 100644
index 0000000..7671aec
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/src/chsem.c
@@ -0,0 +1,405 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/src/chsem.c
+ * @brief Semaphores code.
+ *
+ * @addtogroup semaphores
+ * @details Semaphores related APIs and services.
+ * Operation mode
+ * Semaphores are a flexible synchronization primitive, ChibiOS/RT
+ * implements semaphores in their "counting semaphores" variant as
+ * defined by Edsger Dijkstra plus several enhancements like:
+ * - Wait operation with timeout.
+ * - Reset operation.
+ * - Atomic wait+signal operation.
+ * - Return message from the wait operation (OK, RESET, TIMEOUT).
+ * .
+ * The binary semaphores variant can be easily implemented using
+ * counting semaphores.
+ * Operations defined for semaphores:
+ * - Signal: The semaphore counter is increased and if the
+ * result is non-positive then a waiting thread is removed from
+ * the semaphore queue and made ready for execution.
+ * - Wait: The semaphore counter is decreased and if the result
+ * becomes negative the thread is queued in the semaphore and
+ * suspended.
+ * - Reset: The semaphore counter is reset to a non-negative
+ * value and all the threads in the queue are released.
+ * .
+ * Semaphores can be used as guards for mutual exclusion zones
+ * (note that mutexes are recommended for this kind of use) but
+ * also have other uses, queues guards and counters for example.
+ * Semaphores usually use a FIFO queuing strategy but it is possible
+ * to make them order threads by priority by enabling
+ * @p CH_CFG_USE_SEMAPHORES_PRIORITY in @p chconf.h.
+ * @pre In order to use the semaphore APIs the @p CH_CFG_USE_SEMAPHORES
+ * option must be enabled in @p chconf.h.
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+#if CH_CFG_USE_SEMAPHORES_PRIORITY == TRUE
+#define sem_insert(tp, qp) queue_prio_insert(tp, qp)
+#else
+#define sem_insert(tp, qp) queue_insert(tp, qp)
+#endif
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes a semaphore with the specified counter value.
+ *
+ * @param[out] sp pointer to a @p semaphore_t structure
+ * @param[in] n initial value of the semaphore counter. Must be
+ * non-negative.
+ *
+ * @init
+ */
+void chSemObjectInit(semaphore_t *sp, cnt_t n) {
+
+ chDbgCheck((sp != NULL) && (n >= (cnt_t)0));
+
+ queue_init(&sp->queue);
+ sp->cnt = n;
+}
+
+/**
+ * @brief Performs a reset operation on the semaphore.
+ * @post After invoking this function all the threads waiting on the
+ * semaphore, if any, are released and the semaphore counter is set
+ * to the specified, non negative, value.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @param[in] n the new value of the semaphore counter. The value must
+ * be non-negative.
+ * @param[in] msg message to be sent
+ *
+ * @api
+ */
+void chSemResetWithMessage(semaphore_t *sp, cnt_t n, msg_t msg) {
+
+ chSysLock();
+ chSemResetWithMessageI(sp, n, msg);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+/**
+ * @brief Performs a reset operation on the semaphore.
+ * @post After invoking this function all the threads waiting on the
+ * semaphore, if any, are released and the semaphore counter is set
+ * to the specified, non negative, value.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @param[in] n the new value of the semaphore counter. The value must
+ * be non-negative.
+ * @param[in] msg message to be sent
+ *
+ * @iclass
+ */
+void chSemResetWithMessageI(semaphore_t *sp, cnt_t n, msg_t msg) {
+
+ chDbgCheckClassI();
+ chDbgCheck((sp != NULL) && (n >= (cnt_t)0));
+ chDbgAssert(((sp->cnt >= (cnt_t)0) && queue_isempty(&sp->queue)) ||
+ ((sp->cnt < (cnt_t)0) && queue_notempty(&sp->queue)),
+ "inconsistent semaphore");
+
+ sp->cnt = n;
+ while (queue_notempty(&sp->queue)) {
+ chSchReadyI(queue_lifo_remove(&sp->queue))->u.rdymsg = msg;
+ }
+}
+
+/**
+ * @brief Performs a wait operation on a semaphore.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @return A message specifying how the invoking thread has been
+ * released from the semaphore.
+ * @retval MSG_OK if the thread has not stopped on the semaphore or the
+ * semaphore has been signaled.
+ * @retval MSG_RESET if the semaphore has been reset using @p chSemReset().
+ *
+ * @api
+ */
+msg_t chSemWait(semaphore_t *sp) {
+ msg_t msg;
+
+ chSysLock();
+ msg = chSemWaitS(sp);
+ chSysUnlock();
+
+ return msg;
+}
+
+/**
+ * @brief Performs a wait operation on a semaphore.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @return A message specifying how the invoking thread has been
+ * released from the semaphore.
+ * @retval MSG_OK if the thread has not stopped on the semaphore or the
+ * semaphore has been signaled.
+ * @retval MSG_RESET if the semaphore has been reset using @p chSemReset().
+ *
+ * @sclass
+ */
+msg_t chSemWaitS(semaphore_t *sp) {
+
+ chDbgCheckClassS();
+ chDbgCheck(sp != NULL);
+ chDbgAssert(((sp->cnt >= (cnt_t)0) && queue_isempty(&sp->queue)) ||
+ ((sp->cnt < (cnt_t)0) && queue_notempty(&sp->queue)),
+ "inconsistent semaphore");
+
+ if (--sp->cnt < (cnt_t)0) {
+ currp->u.wtsemp = sp;
+ sem_insert(currp, &sp->queue);
+ chSchGoSleepS(CH_STATE_WTSEM);
+
+ return currp->u.rdymsg;
+ }
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Performs a wait operation on a semaphore with timeout specification.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A message specifying how the invoking thread has been
+ * released from the semaphore.
+ * @retval MSG_OK if the thread has not stopped on the semaphore or the
+ * semaphore has been signaled.
+ * @retval MSG_RESET if the semaphore has been reset using @p chSemReset().
+ * @retval MSG_TIMEOUT if the semaphore has not been signaled or reset within
+ * the specified timeout.
+ *
+ * @api
+ */
+msg_t chSemWaitTimeout(semaphore_t *sp, sysinterval_t timeout) {
+ msg_t msg;
+
+ chSysLock();
+ msg = chSemWaitTimeoutS(sp, timeout);
+ chSysUnlock();
+
+ return msg;
+}
+
+/**
+ * @brief Performs a wait operation on a semaphore with timeout specification.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A message specifying how the invoking thread has been
+ * released from the semaphore.
+ * @retval MSG_OK if the thread has not stopped on the semaphore or the
+ * semaphore has been signaled.
+ * @retval MSG_RESET if the semaphore has been reset using @p chSemReset().
+ * @retval MSG_TIMEOUT if the semaphore has not been signaled or reset within
+ * the specified timeout.
+ *
+ * @sclass
+ */
+msg_t chSemWaitTimeoutS(semaphore_t *sp, sysinterval_t timeout) {
+
+ chDbgCheckClassS();
+ chDbgCheck(sp != NULL);
+ chDbgAssert(((sp->cnt >= (cnt_t)0) && queue_isempty(&sp->queue)) ||
+ ((sp->cnt < (cnt_t)0) && queue_notempty(&sp->queue)),
+ "inconsistent semaphore");
+
+ if (--sp->cnt < (cnt_t)0) {
+ if (TIME_IMMEDIATE == timeout) {
+ sp->cnt++;
+
+ return MSG_TIMEOUT;
+ }
+ currp->u.wtsemp = sp;
+ sem_insert(currp, &sp->queue);
+
+ return chSchGoSleepTimeoutS(CH_STATE_WTSEM, timeout);
+ }
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Performs a signal operation on a semaphore.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ *
+ * @api
+ */
+void chSemSignal(semaphore_t *sp) {
+
+ chDbgCheck(sp != NULL);
+
+ chSysLock();
+ chDbgAssert(((sp->cnt >= (cnt_t)0) && queue_isempty(&sp->queue)) ||
+ ((sp->cnt < (cnt_t)0) && queue_notempty(&sp->queue)),
+ "inconsistent semaphore");
+ if (++sp->cnt <= (cnt_t)0) {
+ chSchWakeupS(queue_fifo_remove(&sp->queue), MSG_OK);
+ }
+ chSysUnlock();
+}
+
+/**
+ * @brief Performs a signal operation on a semaphore.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ *
+ * @iclass
+ */
+void chSemSignalI(semaphore_t *sp) {
+
+ chDbgCheckClassI();
+ chDbgCheck(sp != NULL);
+ chDbgAssert(((sp->cnt >= (cnt_t)0) && queue_isempty(&sp->queue)) ||
+ ((sp->cnt < (cnt_t)0) && queue_notempty(&sp->queue)),
+ "inconsistent semaphore");
+
+ if (++sp->cnt <= (cnt_t)0) {
+ /* Note, it is done this way in order to allow a tail call on
+ chSchReadyI().*/
+ thread_t *tp = queue_fifo_remove(&sp->queue);
+ tp->u.rdymsg = MSG_OK;
+ (void) chSchReadyI(tp);
+ }
+}
+
+/**
+ * @brief Adds the specified value to the semaphore counter.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @param[in] n value to be added to the semaphore counter. The value
+ * must be positive.
+ *
+ * @iclass
+ */
+void chSemAddCounterI(semaphore_t *sp, cnt_t n) {
+
+ chDbgCheckClassI();
+ chDbgCheck((sp != NULL) && (n > (cnt_t)0));
+ chDbgAssert(((sp->cnt >= (cnt_t)0) && queue_isempty(&sp->queue)) ||
+ ((sp->cnt < (cnt_t)0) && queue_notempty(&sp->queue)),
+ "inconsistent semaphore");
+
+ while (n > (cnt_t)0) {
+ if (++sp->cnt <= (cnt_t)0) {
+ chSchReadyI(queue_fifo_remove(&sp->queue))->u.rdymsg = MSG_OK;
+ }
+ n--;
+ }
+}
+
+/**
+ * @brief Performs atomic signal and wait operations on two semaphores.
+ *
+ * @param[in] sps pointer to a @p semaphore_t structure to be signaled
+ * @param[in] spw pointer to a @p semaphore_t structure to wait on
+ * @return A message specifying how the invoking thread has been
+ * released from the semaphore.
+ * @retval MSG_OK if the thread has not stopped on the semaphore or the
+ * semaphore has been signaled.
+ * @retval MSG_RESET if the semaphore has been reset using @p chSemReset().
+ *
+ * @api
+ */
+msg_t chSemSignalWait(semaphore_t *sps, semaphore_t *spw) {
+ msg_t msg;
+
+ chDbgCheck((sps != NULL) && (spw != NULL));
+
+ chSysLock();
+ chDbgAssert(((sps->cnt >= (cnt_t)0) && queue_isempty(&sps->queue)) ||
+ ((sps->cnt < (cnt_t)0) && queue_notempty(&sps->queue)),
+ "inconsistent semaphore");
+ chDbgAssert(((spw->cnt >= (cnt_t)0) && queue_isempty(&spw->queue)) ||
+ ((spw->cnt < (cnt_t)0) && queue_notempty(&spw->queue)),
+ "inconsistent semaphore");
+ if (++sps->cnt <= (cnt_t)0) {
+ chSchReadyI(queue_fifo_remove(&sps->queue))->u.rdymsg = MSG_OK;
+ }
+ if (--spw->cnt < (cnt_t)0) {
+ thread_t *ctp = currp;
+ sem_insert(ctp, &spw->queue);
+ ctp->u.wtsemp = spw;
+ chSchGoSleepS(CH_STATE_WTSEM);
+ msg = ctp->u.rdymsg;
+ }
+ else {
+ chSchRescheduleS();
+ msg = MSG_OK;
+ }
+ chSysUnlock();
+
+ return msg;
+}
+
+#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/src/chstats.c b/ChibiOS_20.3.2/os/rt/src/chstats.c
new file mode 100644
index 0000000..5d3c0fc
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/src/chstats.c
@@ -0,0 +1,126 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/src/chstats.c
+ * @brief Statistics module code.
+ *
+ * @addtogroup statistics
+ * @details Statistics services.
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_DBG_STATISTICS == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes the statistics module.
+ *
+ * @init
+ */
+void _stats_init(void) {
+
+ ch.kernel_stats.n_irq = (ucnt_t)0;
+ ch.kernel_stats.n_ctxswc = (ucnt_t)0;
+ chTMObjectInit(&ch.kernel_stats.m_crit_thd);
+ chTMObjectInit(&ch.kernel_stats.m_crit_isr);
+}
+
+/**
+ * @brief Increases the IRQ counter.
+ */
+void _stats_increase_irq(void) {
+
+ port_lock_from_isr();
+ ch.kernel_stats.n_irq++;
+ port_unlock_from_isr();
+}
+
+/**
+ * @brief Updates context switch related statistics.
+ *
+ * @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread to be switched out
+ */
+void _stats_ctxswc(thread_t *ntp, thread_t *otp) {
+
+ ch.kernel_stats.n_ctxswc++;
+ chTMChainMeasurementToX(&otp->stats, &ntp->stats);
+}
+
+/**
+ * @brief Starts the measurement of a thread critical zone.
+ */
+void _stats_start_measure_crit_thd(void) {
+
+ chTMStartMeasurementX(&ch.kernel_stats.m_crit_thd);
+}
+
+/**
+ * @brief Stops the measurement of a thread critical zone.
+ */
+void _stats_stop_measure_crit_thd(void) {
+
+ chTMStopMeasurementX(&ch.kernel_stats.m_crit_thd);
+}
+
+/**
+ * @brief Starts the measurement of an ISR critical zone.
+ */
+void _stats_start_measure_crit_isr(void) {
+
+ chTMStartMeasurementX(&ch.kernel_stats.m_crit_isr);
+}
+
+/**
+ * @brief Stops the measurement of an ISR critical zone.
+ */
+void _stats_stop_measure_crit_isr(void) {
+
+ chTMStopMeasurementX(&ch.kernel_stats.m_crit_isr);
+}
+
+#endif /* CH_DBG_STATISTICS == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/src/chsys.c b/ChibiOS_20.3.2/os/rt/src/chsys.c
new file mode 100644
index 0000000..cfe9321
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/src/chsys.c
@@ -0,0 +1,445 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/src/chsys.c
+ * @brief System related code.
+ *
+ * @addtogroup system
+ * @details System related APIs and services:
+ * - Initialization.
+ * - Locks.
+ * - Interrupt Handling.
+ * - Power Management.
+ * - Abnormal Termination.
+ * - Realtime counter.
+ * .
+ * @{
+ */
+
+#include "ch.h"
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+#if (CH_CFG_NO_IDLE_THREAD == FALSE) || defined(__DOXYGEN__)
+/**
+ * @brief Idle thread working area.
+ */
+THD_WORKING_AREA(ch_idle_thread_wa, PORT_IDLE_THREAD_STACK_SIZE);
+#endif
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+#if (CH_CFG_NO_IDLE_THREAD == FALSE) || defined(__DOXYGEN__)
+/**
+ * @brief This function implements the idle thread infinite loop.
+ * @details The function puts the processor in the lowest power mode capable
+ * to serve interrupts.
+ * The priority is internally set to the minimum system value so
+ * that this thread is executed only if there are no other ready
+ * threads in the system.
+ *
+ * @param[in] p the thread parameter, unused in this scenario
+ */
+static void _idle_thread(void *p) {
+
+ (void)p;
+
+ while (true) {
+ /*lint -save -e522 [2.2] Apparently no side effects because it contains
+ an asm instruction.*/
+ port_wait_for_interrupt();
+ /*lint -restore*/
+ CH_CFG_IDLE_LOOP_HOOK();
+ }
+}
+#endif /* CH_CFG_NO_IDLE_THREAD == FALSE */
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief ChibiOS/RT initialization.
+ * @details After executing this function the current instructions stream
+ * becomes the main thread.
+ * @pre Interrupts must disabled before invoking this function.
+ * @post The main thread is created with priority @p NORMALPRIO and
+ * interrupts are enabled.
+ *
+ * @special
+ */
+void chSysInit(void) {
+
+ _scheduler_init();
+ _vt_init();
+ _trace_init();
+ _oslib_init();
+
+#if CH_DBG_SYSTEM_STATE_CHECK == TRUE
+ ch.dbg.isr_cnt = (cnt_t)0;
+ ch.dbg.lock_cnt = (cnt_t)0;
+#endif
+#if CH_CFG_USE_TM == TRUE
+ _tm_init();
+#endif
+#if CH_DBG_STATISTICS == TRUE
+ _stats_init();
+#endif
+
+#if CH_CFG_NO_IDLE_THREAD == FALSE
+ /* Now this instructions flow becomes the main thread.*/
+#if CH_CFG_USE_REGISTRY == TRUE
+ currp = _thread_init(&ch.mainthread, (const char *)&ch_debug, NORMALPRIO);
+#else
+ currp = _thread_init(&ch.mainthread, "main", NORMALPRIO);
+#endif
+#else
+ /* Now this instructions flow becomes the idle thread.*/
+ currp = _thread_init(&ch.mainthread, "idle", IDLEPRIO);
+#endif
+
+#if CH_DBG_ENABLE_STACK_CHECK == TRUE
+ {
+ /* Setting up the base address of the static main thread stack, the
+ symbol must be provided externally.*/
+ extern stkalign_t __main_thread_stack_base__;
+ currp->wabase = &__main_thread_stack_base__;
+ }
+#elif CH_CFG_USE_DYNAMIC == TRUE
+ currp->wabase = NULL;
+#endif
+
+ /* Setting up the caller as current thread.*/
+ currp->state = CH_STATE_CURRENT;
+
+ /* Port layer initialization last because it depend on some of the
+ initializations performed before.*/
+ port_init();
+
+#if CH_DBG_STATISTICS == TRUE
+ /* Starting measurement for this thread.*/
+ chTMStartMeasurementX(&currp->stats);
+#endif
+
+ /* Initialization hook.*/
+ CH_CFG_SYSTEM_INIT_HOOK();
+
+ /* It is alive now.*/
+ chSysEnable();
+
+#if CH_CFG_NO_IDLE_THREAD == FALSE
+ {
+ static const thread_descriptor_t idle_descriptor = {
+ "idle",
+ THD_WORKING_AREA_BASE(ch_idle_thread_wa),
+ THD_WORKING_AREA_END(ch_idle_thread_wa),
+ IDLEPRIO,
+ _idle_thread,
+ NULL
+ };
+
+ /* This thread has the lowest priority in the system, its role is just to
+ serve interrupts in its context while keeping the lowest energy saving
+ mode compatible with the system status.*/
+ (void) chThdCreate(&idle_descriptor);
+ }
+#endif
+}
+
+/**
+ * @brief Halts the system.
+ * @details This function is invoked by the operating system when an
+ * unrecoverable error is detected, for example because a programming
+ * error in the application code that triggers an assertion while
+ * in debug mode.
+ * @note Can be invoked from any system state.
+ *
+ * @param[in] reason pointer to an error string
+ *
+ * @special
+ */
+void chSysHalt(const char *reason) {
+
+ port_disable();
+
+ /* Logging the event.*/
+ _trace_halt(reason);
+
+ /* Pointing to the passed message.*/
+ ch.dbg.panic_msg = reason;
+
+ /* Halt hook code, usually empty.*/
+ CH_CFG_SYSTEM_HALT_HOOK(reason);
+
+ /* Harmless infinite loop.*/
+ while (true) {
+ }
+}
+
+/**
+ * @brief System integrity check.
+ * @details Performs an integrity check of the important ChibiOS/RT data
+ * structures.
+ * @note The appropriate action in case of failure is to halt the system
+ * before releasing the critical zone.
+ * @note If the system is corrupted then one possible outcome of this
+ * function is an exception caused by @p NULL or corrupted pointers
+ * in list elements. Exception vectors must be monitored as well.
+ * @note This function is not used internally, it is up to the
+ * application to define if and where to perform system
+ * checking.
+ * @note Performing all tests at once can be a slow operation and can
+ * degrade the system response time. It is suggested to execute
+ * one test at time and release the critical zone in between tests.
+ *
+ * @param[in] testmask Each bit in this mask is associated to a test to be
+ * performed.
+ * @return The test result.
+ * @retval false The test succeeded.
+ * @retval true Test failed.
+ *
+ * @iclass
+ */
+bool chSysIntegrityCheckI(unsigned testmask) {
+ cnt_t n;
+
+ chDbgCheckClassI();
+
+ /* Ready List integrity check.*/
+ if ((testmask & CH_INTEGRITY_RLIST) != 0U) {
+ thread_t *tp;
+
+ /* Scanning the ready list forward.*/
+ n = (cnt_t)0;
+ tp = ch.rlist.queue.next;
+ while (tp != (thread_t *)&ch.rlist.queue) {
+ n++;
+ tp = tp->queue.next;
+ }
+
+ /* Scanning the ready list backward.*/
+ tp = ch.rlist.queue.prev;
+ while (tp != (thread_t *)&ch.rlist.queue) {
+ n--;
+ tp = tp->queue.prev;
+ }
+
+ /* The number of elements must match.*/
+ if (n != (cnt_t)0) {
+ return true;
+ }
+ }
+
+ /* Timers list integrity check.*/
+ if ((testmask & CH_INTEGRITY_VTLIST) != 0U) {
+ virtual_timer_t * vtp;
+
+ /* Scanning the timers list forward.*/
+ n = (cnt_t)0;
+ vtp = ch.vtlist.next;
+ while (vtp != (virtual_timer_t *)&ch.vtlist) {
+ n++;
+ vtp = vtp->next;
+ }
+
+ /* Scanning the timers list backward.*/
+ vtp = ch.vtlist.prev;
+ while (vtp != (virtual_timer_t *)&ch.vtlist) {
+ n--;
+ vtp = vtp->prev;
+ }
+
+ /* The number of elements must match.*/
+ if (n != (cnt_t)0) {
+ return true;
+ }
+ }
+
+#if CH_CFG_USE_REGISTRY == TRUE
+ if ((testmask & CH_INTEGRITY_REGISTRY) != 0U) {
+ thread_t *tp;
+
+ /* Scanning the ready list forward.*/
+ n = (cnt_t)0;
+ tp = ch.rlist.newer;
+ while (tp != (thread_t *)&ch.rlist) {
+ n++;
+ tp = tp->newer;
+ }
+
+ /* Scanning the ready list backward.*/
+ tp = ch.rlist.older;
+ while (tp != (thread_t *)&ch.rlist) {
+ n--;
+ tp = tp->older;
+ }
+
+ /* The number of elements must match.*/
+ if (n != (cnt_t)0) {
+ return true;
+ }
+ }
+#endif /* CH_CFG_USE_REGISTRY == TRUE */
+
+#if defined(PORT_INTEGRITY_CHECK)
+ if ((testmask & CH_INTEGRITY_PORT) != 0U) {
+ PORT_INTEGRITY_CHECK();
+ }
+#endif
+
+ return false;
+}
+
+/**
+ * @brief Handles time ticks for round robin preemption and timer increments.
+ * @details Decrements the remaining time quantum of the running thread
+ * and preempts it when the quantum is used up. Increments system
+ * time and manages the timers.
+ * @note The frequency of the timer determines the system tick granularity
+ * and, together with the @p CH_CFG_TIME_QUANTUM macro, the round robin
+ * interval.
+ *
+ * @iclass
+ */
+void chSysTimerHandlerI(void) {
+
+ chDbgCheckClassI();
+
+#if CH_CFG_TIME_QUANTUM > 0
+ /* Running thread has not used up quantum yet? */
+ if (currp->ticks > (tslices_t)0) {
+ /* Decrement remaining quantum.*/
+ currp->ticks--;
+ }
+#endif
+#if CH_DBG_THREADS_PROFILING == TRUE
+ currp->time++;
+#endif
+ chVTDoTickI();
+ CH_CFG_SYSTEM_TICK_HOOK();
+}
+
+/**
+ * @brief Returns the execution status and enters a critical zone.
+ * @details This functions enters into a critical zone and can be called
+ * from any context. Because its flexibility it is less efficient
+ * than @p chSysLock() which is preferable when the calling context
+ * is known.
+ * @post The system is in a critical zone.
+ *
+ * @return The previous system status, the encoding of this
+ * status word is architecture-dependent and opaque.
+ *
+ * @xclass
+ */
+syssts_t chSysGetStatusAndLockX(void) {
+
+ syssts_t sts = port_get_irq_status();
+ if (port_irq_enabled(sts)) {
+ if (port_is_isr_context()) {
+ chSysLockFromISR();
+ }
+ else {
+ chSysLock();
+ }
+ }
+ return sts;
+}
+
+/**
+ * @brief Restores the specified execution status and leaves a critical zone.
+ * @note A call to @p chSchRescheduleS() is automatically performed
+ * if exiting the critical zone and if not in ISR context.
+ *
+ * @param[in] sts the system status to be restored.
+ *
+ * @xclass
+ */
+void chSysRestoreStatusX(syssts_t sts) {
+
+ if (port_irq_enabled(sts)) {
+ if (port_is_isr_context()) {
+ chSysUnlockFromISR();
+ }
+ else {
+ chSchRescheduleS();
+ chSysUnlock();
+ }
+ }
+}
+
+#if (PORT_SUPPORTS_RT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Realtime window test.
+ * @details This function verifies if the current realtime counter value
+ * lies within the specified range or not. The test takes care
+ * of the realtime counter wrapping to zero on overflow.
+ * @note When start==end then the function returns always false because a
+ * null time range is specified.
+ * @note This function is only available if the port layer supports the
+ * option @p PORT_SUPPORTS_RT.
+ *
+ * @param[in] cnt the counter value to be tested
+ * @param[in] start the start of the time window (inclusive)
+ * @param[in] end the end of the time window (non inclusive)
+ * @retval true current time within the specified time window.
+ * @retval false current time not within the specified time window.
+ *
+ * @xclass
+ */
+bool chSysIsCounterWithinX(rtcnt_t cnt, rtcnt_t start, rtcnt_t end) {
+
+ return (bool)(((rtcnt_t)cnt - (rtcnt_t)start) <
+ ((rtcnt_t)end - (rtcnt_t)start));
+}
+
+/**
+ * @brief Polled delay.
+ * @note The real delay is always few cycles in excess of the specified
+ * value.
+ * @note This function is only available if the port layer supports the
+ * option @p PORT_SUPPORTS_RT.
+ *
+ * @param[in] cycles number of cycles
+ *
+ * @xclass
+ */
+void chSysPolledDelayX(rtcnt_t cycles) {
+ rtcnt_t start = chSysGetRealtimeCounterX();
+ rtcnt_t end = start + cycles;
+
+ while (chSysIsCounterWithinX(chSysGetRealtimeCounterX(), start, end)) {
+ }
+}
+#endif /* PORT_SUPPORTS_RT == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/src/chthreads.c b/ChibiOS_20.3.2/os/rt/src/chthreads.c
new file mode 100644
index 0000000..caa846b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/src/chthreads.c
@@ -0,0 +1,906 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/src/chthreads.c
+ * @brief Threads code.
+ *
+ * @addtogroup threads
+ * @details Threads related APIs and services.
+ * Operation mode
+ * A thread is an abstraction of an independent instructions flow.
+ * In ChibiOS/RT a thread is represented by a "C" function owning
+ * a processor context, state informations and a dedicated stack
+ * area. In this scenario static variables are shared among all
+ * threads while automatic variables are local to the thread.
+ * Operations defined for threads:
+ * - Create, a thread is started on the specified thread
+ * function. This operation is available in multiple variants,
+ * both static and dynamic.
+ * - Exit, a thread terminates by returning from its top
+ * level function or invoking a specific API, the thread can
+ * return a value that can be retrieved by other threads.
+ * - Wait, a thread waits for the termination of another
+ * thread and retrieves its return value.
+ * - Resume, a thread created in suspended state is started.
+ * - Sleep, the execution of a thread is suspended for the
+ * specified amount of time or the specified future absolute time
+ * is reached.
+ * - SetPriority, a thread changes its own priority level.
+ * - Yield, a thread voluntarily renounces to its time slot.
+ * .
+ * @{
+ */
+
+#include "ch.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes a thread structure.
+ * @note This is an internal functions, do not use it in application code.
+ *
+ * @param[in] tp pointer to the thread
+ * @param[in] name thread name
+ * @param[in] prio the priority level for the new thread
+ * @return The same thread pointer passed as parameter.
+ *
+ * @notapi
+ */
+thread_t *_thread_init(thread_t *tp, const char *name, tprio_t prio) {
+
+ tp->prio = prio;
+ tp->state = CH_STATE_WTSTART;
+ tp->flags = CH_FLAG_MODE_STATIC;
+#if CH_CFG_TIME_QUANTUM > 0
+ tp->ticks = (tslices_t)CH_CFG_TIME_QUANTUM;
+#endif
+#if CH_CFG_USE_MUTEXES == TRUE
+ tp->realprio = prio;
+ tp->mtxlist = NULL;
+#endif
+#if CH_CFG_USE_EVENTS == TRUE
+ tp->epending = (eventmask_t)0;
+#endif
+#if CH_DBG_THREADS_PROFILING == TRUE
+ tp->time = (systime_t)0;
+#endif
+#if CH_CFG_USE_REGISTRY == TRUE
+ tp->refs = (trefs_t)1;
+ tp->name = name;
+ REG_INSERT(tp);
+#else
+ (void)name;
+#endif
+#if CH_CFG_USE_WAITEXIT == TRUE
+ list_init(&tp->waiting);
+#endif
+#if CH_CFG_USE_MESSAGES == TRUE
+ queue_init(&tp->msgqueue);
+#endif
+#if CH_DBG_STATISTICS == TRUE
+ chTMObjectInit(&tp->stats);
+#endif
+ CH_CFG_THREAD_INIT_HOOK(tp);
+ return tp;
+}
+
+#if (CH_DBG_FILL_THREADS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Memory fill utility.
+ *
+ * @param[in] startp first address to fill
+ * @param[in] endp last address to fill +1
+ * @param[in] v filler value
+ *
+ * @notapi
+ */
+void _thread_memfill(uint8_t *startp, uint8_t *endp, uint8_t v) {
+
+ while (startp < endp) {
+ *startp++ = v;
+ }
+}
+#endif /* CH_DBG_FILL_THREADS */
+
+/**
+ * @brief Creates a new thread into a static memory area.
+ * @details The new thread is initialized but not inserted in the ready list,
+ * the initial state is @p CH_STATE_WTSTART.
+ * @post The created thread has a reference counter set to one, it is
+ * caller responsibility to call @p chThdRelease() or @p chthdWait()
+ * in order to release the reference. The thread persists in the
+ * registry until its reference counter reaches zero.
+ * @post The initialized thread can be subsequently started by invoking
+ * @p chThdStart(), @p chThdStartI() or @p chSchWakeupS()
+ * depending on the execution context.
+ * @note A thread can terminate by calling @p chThdExit() or by simply
+ * returning from its main function.
+ * @note Threads created using this function do not obey to the
+ * @p CH_DBG_FILL_THREADS debug option because it would keep
+ * the kernel locked for too much time.
+ *
+ * @param[out] tdp pointer to the thread descriptor
+ * @return The pointer to the @p thread_t structure allocated for
+ * the thread into the working space area.
+ *
+ * @iclass
+ */
+thread_t *chThdCreateSuspendedI(const thread_descriptor_t *tdp) {
+ thread_t *tp;
+
+ chDbgCheckClassI();
+ chDbgCheck(tdp != NULL);
+ chDbgCheck(MEM_IS_ALIGNED(tdp->wbase, PORT_WORKING_AREA_ALIGN) &&
+ MEM_IS_ALIGNED(tdp->wend, PORT_STACK_ALIGN) &&
+ (tdp->wend > tdp->wbase) &&
+ (((size_t)tdp->wend - (size_t)tdp->wbase) >= THD_WORKING_AREA_SIZE(0)));
+ chDbgCheck((tdp->prio <= HIGHPRIO) && (tdp->funcp != NULL));
+
+ /* The thread structure is laid out in the upper part of the thread
+ workspace. The thread position structure is aligned to the required
+ stack alignment because it represents the stack top.*/
+ tp = (thread_t *)((uint8_t *)tdp->wend -
+ MEM_ALIGN_NEXT(sizeof (thread_t), PORT_STACK_ALIGN));
+
+#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE)
+ /* Stack boundary.*/
+ tp->wabase = tdp->wbase;
+#endif
+
+ /* Setting up the port-dependent part of the working area.*/
+ PORT_SETUP_CONTEXT(tp, tdp->wbase, tp, tdp->funcp, tdp->arg);
+
+ /* The driver object is initialized but not started.*/
+ return _thread_init(tp, tdp->name, tdp->prio);
+}
+
+/**
+ * @brief Creates a new thread into a static memory area.
+ * @details The new thread is initialized but not inserted in the ready list,
+ * the initial state is @p CH_STATE_WTSTART.
+ * @post The created thread has a reference counter set to one, it is
+ * caller responsibility to call @p chThdRelease() or @p chthdWait()
+ * in order to release the reference. The thread persists in the
+ * registry until its reference counter reaches zero.
+ * @post The initialized thread can be subsequently started by invoking
+ * @p chThdStart(), @p chThdStartI() or @p chSchWakeupS()
+ * depending on the execution context.
+ * @note A thread can terminate by calling @p chThdExit() or by simply
+ * returning from its main function.
+ *
+ * @param[out] tdp pointer to the thread descriptor
+ * @return The pointer to the @p thread_t structure allocated for
+ * the thread into the working space area.
+ *
+ * @api
+ */
+thread_t *chThdCreateSuspended(const thread_descriptor_t *tdp) {
+ thread_t *tp;
+
+#if CH_CFG_USE_REGISTRY == TRUE
+ chDbgAssert(chRegFindThreadByWorkingArea(tdp->wbase) == NULL,
+ "working area in use");
+#endif
+
+#if CH_DBG_FILL_THREADS == TRUE
+ _thread_memfill((uint8_t *)tdp->wbase,
+ (uint8_t *)tdp->wend,
+ CH_DBG_STACK_FILL_VALUE);
+#endif
+
+ chSysLock();
+ tp = chThdCreateSuspendedI(tdp);
+ chSysUnlock();
+
+ return tp;
+}
+
+/**
+ * @brief Creates a new thread into a static memory area.
+ * @details The new thread is initialized and make ready to execute.
+ * @post The created thread has a reference counter set to one, it is
+ * caller responsibility to call @p chThdRelease() or @p chthdWait()
+ * in order to release the reference. The thread persists in the
+ * registry until its reference counter reaches zero.
+ * @post The initialized thread can be subsequently started by invoking
+ * @p chThdStart(), @p chThdStartI() or @p chSchWakeupS()
+ * depending on the execution context.
+ * @note A thread can terminate by calling @p chThdExit() or by simply
+ * returning from its main function.
+ * @note Threads created using this function do not obey to the
+ * @p CH_DBG_FILL_THREADS debug option because it would keep
+ * the kernel locked for too much time.
+ *
+ * @param[out] tdp pointer to the thread descriptor
+ * @return The pointer to the @p thread_t structure allocated for
+ * the thread into the working space area.
+ *
+ * @iclass
+ */
+thread_t *chThdCreateI(const thread_descriptor_t *tdp) {
+
+ return chSchReadyI(chThdCreateSuspendedI(tdp));
+}
+
+/**
+ * @brief Creates a new thread into a static memory area.
+ * @details The new thread is initialized and make ready to execute.
+ * @post The created thread has a reference counter set to one, it is
+ * caller responsibility to call @p chThdRelease() or @p chthdWait()
+ * in order to release the reference. The thread persists in the
+ * registry until its reference counter reaches zero.
+ * @note A thread can terminate by calling @p chThdExit() or by simply
+ * returning from its main function.
+ *
+ * @param[out] tdp pointer to the thread descriptor
+ * @return The pointer to the @p thread_t structure allocated for
+ * the thread into the working space area.
+ *
+ * @iclass
+ */
+thread_t *chThdCreate(const thread_descriptor_t *tdp) {
+ thread_t *tp;
+
+#if (CH_CFG_USE_REGISTRY == TRUE) && \
+ ((CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE))
+ chDbgAssert(chRegFindThreadByWorkingArea(tdp->wbase) == NULL,
+ "working area in use");
+#endif
+
+#if CH_DBG_FILL_THREADS == TRUE
+ _thread_memfill((uint8_t *)tdp->wbase,
+ (uint8_t *)tdp->wend,
+ CH_DBG_STACK_FILL_VALUE);
+#endif
+
+ chSysLock();
+ tp = chThdCreateSuspendedI(tdp);
+ chSchWakeupS(tp, MSG_OK);
+ chSysUnlock();
+
+ return tp;
+}
+
+/**
+ * @brief Creates a new thread into a static memory area.
+ * @post The created thread has a reference counter set to one, it is
+ * caller responsibility to call @p chThdRelease() or @p chThdWait()
+ * in order to release the reference. The thread persists in the
+ * registry until its reference counter reaches zero.
+ * @note A thread can terminate by calling @p chThdExit() or by simply
+ * returning from its main function.
+ *
+ * @param[out] wsp pointer to a working area dedicated to the thread stack
+ * @param[in] size size of the working area
+ * @param[in] prio the priority level for the new thread
+ * @param[in] pf the thread function
+ * @param[in] arg an argument passed to the thread function. It can be
+ * @p NULL.
+ * @return The pointer to the @p thread_t structure allocated for
+ * the thread into the working space area.
+ *
+ * @api
+ */
+thread_t *chThdCreateStatic(void *wsp, size_t size,
+ tprio_t prio, tfunc_t pf, void *arg) {
+ thread_t *tp;
+
+ chDbgCheck((wsp != NULL) &&
+ MEM_IS_ALIGNED(wsp, PORT_WORKING_AREA_ALIGN) &&
+ (size >= THD_WORKING_AREA_SIZE(0)) &&
+ MEM_IS_ALIGNED(size, PORT_STACK_ALIGN) &&
+ (prio <= HIGHPRIO) && (pf != NULL));
+
+#if (CH_CFG_USE_REGISTRY == TRUE) && \
+ ((CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE))
+ chDbgAssert(chRegFindThreadByWorkingArea(wsp) == NULL,
+ "working area in use");
+#endif
+
+#if CH_DBG_FILL_THREADS == TRUE
+ _thread_memfill((uint8_t *)wsp,
+ (uint8_t *)wsp + size,
+ CH_DBG_STACK_FILL_VALUE);
+#endif
+
+ chSysLock();
+
+ /* The thread structure is laid out in the upper part of the thread
+ workspace. The thread position structure is aligned to the required
+ stack alignment because it represents the stack top.*/
+ tp = (thread_t *)((uint8_t *)wsp + size -
+ MEM_ALIGN_NEXT(sizeof (thread_t), PORT_STACK_ALIGN));
+
+#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE)
+ /* Stack boundary.*/
+ tp->wabase = (stkalign_t *)wsp;
+#endif
+
+ /* Setting up the port-dependent part of the working area.*/
+ PORT_SETUP_CONTEXT(tp, wsp, tp, pf, arg);
+
+ tp = _thread_init(tp, "noname", prio);
+
+ /* Starting the thread immediately.*/
+ chSchWakeupS(tp, MSG_OK);
+ chSysUnlock();
+
+ return tp;
+}
+
+/**
+ * @brief Resumes a thread created with @p chThdCreateI().
+ *
+ * @param[in] tp pointer to the thread
+ * @return The pointer to the @p thread_t structure allocated for
+ * the thread into the working space area.
+ *
+ * @api
+ */
+thread_t *chThdStart(thread_t *tp) {
+
+ chSysLock();
+ chDbgAssert(tp->state == CH_STATE_WTSTART, "wrong state");
+ chSchWakeupS(tp, MSG_OK);
+ chSysUnlock();
+
+ return tp;
+}
+
+#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Adds a reference to a thread object.
+ * @pre The configuration option @p CH_CFG_USE_REGISTRY must be enabled in
+ * order to use this function.
+ *
+ * @param[in] tp pointer to the thread
+ * @return The same thread pointer passed as parameter
+ * representing the new reference.
+ *
+ * @api
+ */
+thread_t *chThdAddRef(thread_t *tp) {
+
+ chSysLock();
+ chDbgAssert(tp->refs < (trefs_t)255, "too many references");
+ tp->refs++;
+ chSysUnlock();
+
+ return tp;
+}
+
+/**
+ * @brief Releases a reference to a thread object.
+ * @details If the references counter reaches zero and the thread
+ * is in the @p CH_STATE_FINAL state then the thread's memory is
+ * returned to the proper allocator and the thread is removed
+ * from the registry.
+ * Threads whose counter reaches zero and are still active become
+ * "detached" and will be removed from registry on termination.
+ * @pre The configuration option @p CH_CFG_USE_REGISTRY must be enabled in
+ * order to use this function.
+ * @note Static threads are not affected.
+ *
+ * @param[in] tp pointer to the thread
+ *
+ * @api
+ */
+void chThdRelease(thread_t *tp) {
+
+ chSysLock();
+ chDbgAssert(tp->refs > (trefs_t)0, "not referenced");
+ tp->refs--;
+
+ /* If the references counter reaches zero and the thread is in its
+ terminated state then the memory can be returned to the proper
+ allocator.*/
+ if ((tp->refs == (trefs_t)0) && (tp->state == CH_STATE_FINAL)) {
+ REG_REMOVE(tp);
+ chSysUnlock();
+
+#if CH_CFG_USE_DYNAMIC == TRUE
+ switch (tp->flags & CH_FLAG_MODE_MASK) {
+#if CH_CFG_USE_HEAP == TRUE
+ case CH_FLAG_MODE_HEAP:
+ chHeapFree(chThdGetWorkingAreaX(tp));
+ break;
+#endif
+#if CH_CFG_USE_MEMPOOLS == TRUE
+ case CH_FLAG_MODE_MPOOL:
+ chPoolFree(tp->mpool, chThdGetWorkingAreaX(tp));
+ break;
+#endif
+ default:
+ /* Nothing else to do for static threads.*/
+ break;
+ }
+#endif /* CH_CFG_USE_DYNAMIC == TRUE */
+ return;
+ }
+ chSysUnlock();
+}
+#endif /* CH_CFG_USE_REGISTRY == TRUE */
+
+/**
+ * @brief Terminates the current thread.
+ * @details The thread goes in the @p CH_STATE_FINAL state holding the
+ * specified exit status code, other threads can retrieve the
+ * exit status code by invoking the function @p chThdWait().
+ * @post Eventual code after this function will never be executed,
+ * this function never returns. The compiler has no way to
+ * know this so do not assume that the compiler would remove
+ * the dead code.
+ *
+ * @param[in] msg thread exit code
+ *
+ * @api
+ */
+void chThdExit(msg_t msg) {
+
+ chSysLock();
+ chThdExitS(msg);
+ /* The thread never returns here.*/
+}
+
+/**
+ * @brief Terminates the current thread.
+ * @details The thread goes in the @p CH_STATE_FINAL state holding the
+ * specified exit status code, other threads can retrieve the
+ * exit status code by invoking the function @p chThdWait().
+ * @post Exiting a non-static thread that does not have references
+ * (detached) causes the thread to remain in the registry.
+ * It can only be removed by performing a registry scan operation.
+ * @post Eventual code after this function will never be executed,
+ * this function never returns. The compiler has no way to
+ * know this so do not assume that the compiler would remove
+ * the dead code.
+ *
+ * @param[in] msg thread exit code
+ *
+ * @sclass
+ */
+void chThdExitS(msg_t msg) {
+ thread_t *tp = currp;
+
+ /* Storing exit message.*/
+ tp->u.exitcode = msg;
+
+ /* Exit handler hook.*/
+ CH_CFG_THREAD_EXIT_HOOK(tp);
+
+#if CH_CFG_USE_WAITEXIT == TRUE
+ /* Waking up any waiting thread.*/
+ while (list_notempty(&tp->waiting)) {
+ (void) chSchReadyI(list_remove(&tp->waiting));
+ }
+#endif
+
+#if CH_CFG_USE_REGISTRY == TRUE
+ /* Static threads with no references are immediately removed from the
+ registry because there is no memory to recover.*/
+#if CH_CFG_USE_DYNAMIC == TRUE
+ if ((tp->refs == (trefs_t)0) &&
+ ((tp->flags & CH_FLAG_MODE_MASK) == CH_FLAG_MODE_STATIC)) {
+ REG_REMOVE(tp);
+ }
+#else
+ if (tp->refs == (trefs_t)0) {
+ REG_REMOVE(tp);
+ }
+#endif
+#endif
+
+ /* Going into final state.*/
+ chSchGoSleepS(CH_STATE_FINAL);
+
+ /* The thread never returns here.*/
+ chDbgAssert(false, "zombies apocalypse");
+}
+
+#if (CH_CFG_USE_WAITEXIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Blocks the execution of the invoking thread until the specified
+ * thread terminates then the exit code is returned.
+ * @details This function waits for the specified thread to terminate then
+ * decrements its reference counter, if the counter reaches zero then
+ * the thread working area is returned to the proper allocator and
+ * the thread is removed from registry.
+ * @pre The configuration option @p CH_CFG_USE_WAITEXIT must be enabled in
+ * order to use this function.
+ * @post Enabling @p chThdWait() requires 2-4 (depending on the
+ * architecture) extra bytes in the @p thread_t structure.
+ * @note If @p CH_CFG_USE_DYNAMIC is not specified this function just waits
+ * for the thread termination, no memory allocators are involved.
+ *
+ * @param[in] tp pointer to the thread
+ * @return The exit code from the terminated thread.
+ *
+ * @api
+ */
+msg_t chThdWait(thread_t *tp) {
+ msg_t msg;
+
+ chDbgCheck(tp != NULL);
+
+ chSysLock();
+ chDbgAssert(tp != currp, "waiting self");
+#if CH_CFG_USE_REGISTRY == TRUE
+ chDbgAssert(tp->refs > (trefs_t)0, "no references");
+#endif
+
+ if (tp->state != CH_STATE_FINAL) {
+ list_insert(currp, &tp->waiting);
+ chSchGoSleepS(CH_STATE_WTEXIT);
+ }
+ msg = tp->u.exitcode;
+ chSysUnlock();
+
+#if CH_CFG_USE_REGISTRY == TRUE
+ /* Releasing a reference to the thread.*/
+ chThdRelease(tp);
+#endif
+
+ return msg;
+}
+#endif /* CH_CFG_USE_WAITEXIT */
+
+/**
+ * @brief Changes the running thread priority level then reschedules if
+ * necessary.
+ * @note The function returns the real thread priority regardless of the
+ * current priority that could be higher than the real priority
+ * because the priority inheritance mechanism.
+ *
+ * @param[in] newprio the new priority level of the running thread
+ * @return The old priority level.
+ *
+ * @api
+ */
+tprio_t chThdSetPriority(tprio_t newprio) {
+ tprio_t oldprio;
+
+ chDbgCheck(newprio <= HIGHPRIO);
+
+ chSysLock();
+#if CH_CFG_USE_MUTEXES == TRUE
+ oldprio = currp->realprio;
+ if ((currp->prio == currp->realprio) || (newprio > currp->prio)) {
+ currp->prio = newprio;
+ }
+ currp->realprio = newprio;
+#else
+ oldprio = currp->prio;
+ currp->prio = newprio;
+#endif
+ chSchRescheduleS();
+ chSysUnlock();
+
+ return oldprio;
+}
+
+/**
+ * @brief Requests a thread termination.
+ * @pre The target thread must be written to invoke periodically
+ * @p chThdShouldTerminate() and terminate cleanly if it returns
+ * @p true.
+ * @post The specified thread will terminate after detecting the termination
+ * condition.
+ *
+ * @param[in] tp pointer to the thread
+ *
+ * @api
+ */
+void chThdTerminate(thread_t *tp) {
+
+ chSysLock();
+ tp->flags |= CH_FLAG_TERMINATE;
+ chSysUnlock();
+}
+
+/**
+ * @brief Suspends the invoking thread for the specified time.
+ *
+ * @param[in] time the delay in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE the thread enters an infinite sleep
+ * state.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ *
+ * @api
+ */
+void chThdSleep(sysinterval_t time) {
+
+ chSysLock();
+ chThdSleepS(time);
+ chSysUnlock();
+}
+
+/**
+ * @brief Suspends the invoking thread until the system time arrives to the
+ * specified value.
+ * @note The function has no concept of "past", all specifiable times
+ * are in the future, this means that if you call this function
+ * exceeding your calculated intervals then the function will
+ * return in a far future time, not immediately.
+ * @see chThdSleepUntilWindowed()
+ *
+ * @param[in] time absolute system time
+ *
+ * @api
+ */
+void chThdSleepUntil(systime_t time) {
+ sysinterval_t interval;
+
+ chSysLock();
+ interval = chTimeDiffX(chVTGetSystemTimeX(), time);
+ if (interval > (sysinterval_t)0) {
+ chThdSleepS(interval);
+ }
+ chSysUnlock();
+}
+
+/**
+ * @brief Suspends the invoking thread until the system time arrives to the
+ * specified value.
+ * @note The system time is assumed to be between @p prev and @p next
+ * else the call is assumed to have been called outside the
+ * allowed time interval, in this case no sleep is performed.
+ * @see chThdSleepUntil()
+ *
+ * @param[in] prev absolute system time of the previous deadline
+ * @param[in] next absolute system time of the next deadline
+ * @return the @p next parameter
+ *
+ * @api
+ */
+systime_t chThdSleepUntilWindowed(systime_t prev, systime_t next) {
+ systime_t time;
+
+ chSysLock();
+ time = chVTGetSystemTimeX();
+ if (chTimeIsInRangeX(time, prev, next)) {
+ chThdSleepS(chTimeDiffX(time, next));
+ }
+ chSysUnlock();
+
+ return next;
+}
+
+/**
+ * @brief Yields the time slot.
+ * @details Yields the CPU control to the next thread in the ready list with
+ * equal priority, if any.
+ *
+ * @api
+ */
+void chThdYield(void) {
+
+ chSysLock();
+ chSchDoYieldS();
+ chSysUnlock();
+}
+
+/**
+ * @brief Sends the current thread sleeping and sets a reference variable.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @return The wake up message.
+ *
+ * @sclass
+ */
+msg_t chThdSuspendS(thread_reference_t *trp) {
+ thread_t *tp = chThdGetSelfX();
+
+ chDbgAssert(*trp == NULL, "not NULL");
+
+ *trp = tp;
+ tp->u.wttrp = trp;
+ chSchGoSleepS(CH_STATE_SUSPENDED);
+
+ return chThdGetSelfX()->u.rdymsg;
+}
+
+/**
+ * @brief Sends the current thread sleeping and sets a reference variable.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] timeout the timeout in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE the thread enters an infinite sleep
+ * state.
+ * - @a TIME_IMMEDIATE the thread is not enqueued and
+ * the function returns @p MSG_TIMEOUT as if a timeout
+ * occurred.
+ * .
+ * @return The wake up message.
+ * @retval MSG_TIMEOUT if the operation timed out.
+ *
+ * @sclass
+ */
+msg_t chThdSuspendTimeoutS(thread_reference_t *trp, sysinterval_t timeout) {
+ thread_t *tp = chThdGetSelfX();
+
+ chDbgAssert(*trp == NULL, "not NULL");
+
+ if (TIME_IMMEDIATE == timeout) {
+ return MSG_TIMEOUT;
+ }
+
+ *trp = tp;
+ tp->u.wttrp = trp;
+
+ return chSchGoSleepTimeoutS(CH_STATE_SUSPENDED, timeout);
+}
+
+/**
+ * @brief Wakes up a thread waiting on a thread reference object.
+ * @note This function must not reschedule because it can be called from
+ * ISR context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void chThdResumeI(thread_reference_t *trp, msg_t msg) {
+
+ if (*trp != NULL) {
+ thread_t *tp = *trp;
+
+ chDbgAssert(tp->state == CH_STATE_SUSPENDED, "not CH_STATE_SUSPENDED");
+
+ *trp = NULL;
+ tp->u.rdymsg = msg;
+ (void) chSchReadyI(tp);
+ }
+}
+
+/**
+ * @brief Wakes up a thread waiting on a thread reference object.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void chThdResumeS(thread_reference_t *trp, msg_t msg) {
+
+ if (*trp != NULL) {
+ thread_t *tp = *trp;
+
+ chDbgAssert(tp->state == CH_STATE_SUSPENDED, "not CH_STATE_SUSPENDED");
+
+ *trp = NULL;
+ chSchWakeupS(tp, msg);
+ }
+}
+
+/**
+ * @brief Wakes up a thread waiting on a thread reference object.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] msg the message code
+ *
+ * @api
+ */
+void chThdResume(thread_reference_t *trp, msg_t msg) {
+
+ chSysLock();
+ chThdResumeS(trp, msg);
+ chSysUnlock();
+}
+
+/**
+ * @brief Enqueues the caller thread on a threads queue object.
+ * @details The caller thread is enqueued and put to sleep until it is
+ * dequeued or the specified timeouts expires.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] timeout the timeout in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE the thread enters an infinite sleep
+ * state.
+ * - @a TIME_IMMEDIATE the thread is not enqueued and
+ * the function returns @p MSG_TIMEOUT as if a timeout
+ * occurred.
+ * .
+ * @return The message from @p osalQueueWakeupOneI() or
+ * @p osalQueueWakeupAllI() functions.
+ * @retval MSG_TIMEOUT if the thread has not been dequeued within the
+ * specified timeout or if the function has been
+ * invoked with @p TIME_IMMEDIATE as timeout
+ * specification.
+ *
+ * @sclass
+ */
+msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout) {
+
+ if (TIME_IMMEDIATE == timeout) {
+ return MSG_TIMEOUT;
+ }
+
+ queue_insert(currp, tqp);
+
+ return chSchGoSleepTimeoutS(CH_STATE_QUEUED, timeout);
+}
+
+/**
+ * @brief Dequeues and wakes up one thread from the threads queue object,
+ * if any.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg) {
+
+ if (queue_notempty(tqp)) {
+ chThdDoDequeueNextI(tqp, msg);
+ }
+}
+
+/**
+ * @brief Dequeues and wakes up all threads from the threads queue object.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg) {
+
+ while (queue_notempty(tqp)) {
+ chThdDoDequeueNextI(tqp, msg);
+ }
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/src/chtm.c b/ChibiOS_20.3.2/os/rt/src/chtm.c
new file mode 100644
index 0000000..5b3758c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/src/chtm.c
@@ -0,0 +1,168 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/src/chtm.c
+ * @brief Time Measurement module code.
+ *
+ * @addtogroup time_measurement
+ * @details Time Measurement APIs and services.
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_TM == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of iterations in the calibration loop.
+ * @note This is required in order to assess the best result in
+ * architectures with instruction cache.
+ */
+#define TM_CALIBRATION_LOOP 4U
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+static inline void tm_stop(time_measurement_t *tmp,
+ rtcnt_t now,
+ rtcnt_t offset) {
+
+ tmp->n++;
+ tmp->last = (now - tmp->last) - offset;
+ tmp->cumulative += (rttime_t)tmp->last;
+ if (tmp->last > tmp->worst) {
+ tmp->worst = tmp->last;
+ }
+ if (tmp->last < tmp->best) {
+ tmp->best = tmp->last;
+ }
+}
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes the time measurement unit.
+ *
+ * @init
+ */
+void _tm_init(void) {
+ time_measurement_t tm;
+ unsigned i;
+
+ /* Time Measurement subsystem calibration, it does a null measurement
+ and calculates the call overhead which is subtracted to real
+ measurements.*/
+ ch.tm.offset = (rtcnt_t)0;
+ chTMObjectInit(&tm);
+ i = TM_CALIBRATION_LOOP;
+ do {
+ chTMStartMeasurementX(&tm);
+ chTMStopMeasurementX(&tm);
+ i--;
+ } while (i > 0U);
+ ch.tm.offset = tm.best;
+}
+
+/**
+ * @brief Initializes a @p TimeMeasurement object.
+ *
+ * @param[out] tmp pointer to a @p TimeMeasurement structure
+ *
+ * @init
+ */
+void chTMObjectInit(time_measurement_t *tmp) {
+
+ tmp->best = (rtcnt_t)-1;
+ tmp->worst = (rtcnt_t)0;
+ tmp->last = (rtcnt_t)0;
+ tmp->n = (ucnt_t)0;
+ tmp->cumulative = (rttime_t)0;
+}
+
+/**
+ * @brief Starts a measurement.
+ * @pre The @p time_measurement_t structure must be initialized.
+ *
+ * @param[in,out] tmp pointer to a @p TimeMeasurement structure
+ *
+ * @xclass
+ */
+NOINLINE void chTMStartMeasurementX(time_measurement_t *tmp) {
+
+ tmp->last = chSysGetRealtimeCounterX();
+}
+
+/**
+ * @brief Stops a measurement.
+ * @pre The @p time_measurement_t structure must be initialized.
+ *
+ * @param[in,out] tmp pointer to a @p time_measurement_t structure
+ *
+ * @xclass
+ */
+NOINLINE void chTMStopMeasurementX(time_measurement_t *tmp) {
+
+ tm_stop(tmp, chSysGetRealtimeCounterX(), ch.tm.offset);
+}
+
+/**
+ * @brief Stops a measurement and chains to the next one using the same time
+ * stamp.
+ *
+ * @param[in,out] tmp1 pointer to the @p time_measurement_t structure to be
+ * stopped
+ * @param[in,out] tmp2 pointer to the @p time_measurement_t structure to be
+ * started
+ *
+ *
+ * @xclass
+ */
+NOINLINE void chTMChainMeasurementToX(time_measurement_t *tmp1,
+ time_measurement_t *tmp2) {
+
+ /* Starts new measurement.*/
+ tmp2->last = chSysGetRealtimeCounterX();
+
+ /* Stops previous measurement using the same time stamp.*/
+ tm_stop(tmp1, tmp2->last, (rtcnt_t)0);
+}
+
+#endif /* CH_CFG_USE_TM == TRUE */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/src/chtrace.c b/ChibiOS_20.3.2/os/rt/src/chtrace.c
new file mode 100644
index 0000000..ecc2367
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/src/chtrace.c
@@ -0,0 +1,265 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/src/chtrace.c
+ * @brief Tracer code.
+ *
+ * @addtogroup trace
+ * @details System events tracing service.
+ * @{
+ */
+
+#include "ch.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+#if (CH_DBG_TRACE_MASK != CH_DBG_TRACE_MASK_DISABLED) || defined(__DOXYGEN__)
+/**
+ * @brief Writes a time stamp and increases the trace buffer pointer.
+ *
+ * @notapi
+ */
+NOINLINE static void trace_next(void) {
+
+ ch.dbg.trace_buffer.ptr->time = chVTGetSystemTimeX();
+#if PORT_SUPPORTS_RT == TRUE
+ ch.dbg.trace_buffer.ptr->rtstamp = chSysGetRealtimeCounterX();
+#else
+ ch.dbg.trace_buffer.ptr->rtstamp = (rtcnt_t)0;
+#endif
+
+ /* Trace hook, useful in order to interface debug tools.*/
+ CH_CFG_TRACE_HOOK(ch.dbg.trace_buffer.ptr);
+
+ if (++ch.dbg.trace_buffer.ptr >=
+ &ch.dbg.trace_buffer.buffer[CH_DBG_TRACE_BUFFER_SIZE]) {
+ ch.dbg.trace_buffer.ptr = &ch.dbg.trace_buffer.buffer[0];
+ }
+}
+#endif
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+#if (CH_DBG_TRACE_MASK != CH_DBG_TRACE_MASK_DISABLED) || defined(__DOXYGEN__)
+/**
+ * @brief Trace circular buffer subsystem initialization.
+ * @note Internal use only.
+ */
+void _trace_init(void) {
+ unsigned i;
+
+ ch.dbg.trace_buffer.suspended = (uint16_t)~CH_DBG_TRACE_MASK;
+ ch.dbg.trace_buffer.size = CH_DBG_TRACE_BUFFER_SIZE;
+ ch.dbg.trace_buffer.ptr = &ch.dbg.trace_buffer.buffer[0];
+ for (i = 0U; i < (unsigned)CH_DBG_TRACE_BUFFER_SIZE; i++) {
+ ch.dbg.trace_buffer.buffer[i].type = CH_TRACE_TYPE_UNUSED;
+ }
+}
+
+/**
+ * @brief Inserts in the circular debug trace buffer a context switch record.
+ *
+ * @param[in] ntp the thread being switched in
+ * @param[in] otp the thread being switched out
+ *
+ * @notapi
+ */
+void _trace_switch(thread_t *ntp, thread_t *otp) {
+
+ (void)ntp;
+
+ if ((ch.dbg.trace_buffer.suspended & CH_DBG_TRACE_MASK_SWITCH) == 0U) {
+ ch.dbg.trace_buffer.ptr->type = CH_TRACE_TYPE_SWITCH;
+ ch.dbg.trace_buffer.ptr->state = (uint8_t)otp->state;
+ ch.dbg.trace_buffer.ptr->u.sw.ntp = currp;
+ ch.dbg.trace_buffer.ptr->u.sw.wtobjp = otp->u.wtobjp;
+ trace_next();
+ }
+}
+
+/**
+ * @brief Inserts in the circular debug trace buffer an ISR-enter record.
+ *
+ * @param[in] isr name of the isr
+ *
+ * @notapi
+ */
+void _trace_isr_enter(const char *isr) {
+
+ if ((ch.dbg.trace_buffer.suspended & CH_DBG_TRACE_MASK_ISR) == 0U) {
+ port_lock_from_isr();
+ ch.dbg.trace_buffer.ptr->type = CH_TRACE_TYPE_ISR_ENTER;
+ ch.dbg.trace_buffer.ptr->state = 0U;
+ ch.dbg.trace_buffer.ptr->u.isr.name = isr;
+ trace_next();
+ port_unlock_from_isr();
+ }
+}
+
+/**
+ * @brief Inserts in the circular debug trace buffer an ISR-leave record.
+ *
+ * @param[in] isr name of the isr
+ *
+ * @notapi
+ */
+void _trace_isr_leave(const char *isr) {
+
+ if ((ch.dbg.trace_buffer.suspended & CH_DBG_TRACE_MASK_ISR) == 0U) {
+ port_lock_from_isr();
+ ch.dbg.trace_buffer.ptr->type = CH_TRACE_TYPE_ISR_LEAVE;
+ ch.dbg.trace_buffer.ptr->state = 0U;
+ ch.dbg.trace_buffer.ptr->u.isr.name = isr;
+ trace_next();
+ port_unlock_from_isr();
+ }
+}
+
+/**
+ * @brief Inserts in the circular debug trace buffer an halt record.
+ *
+ * @param[in] reason the halt error string
+ *
+ * @notapi
+ */
+void _trace_halt(const char *reason) {
+
+ if ((ch.dbg.trace_buffer.suspended & CH_DBG_TRACE_MASK_HALT) == 0U) {
+ ch.dbg.trace_buffer.ptr->type = CH_TRACE_TYPE_HALT;
+ ch.dbg.trace_buffer.ptr->state = 0;
+ ch.dbg.trace_buffer.ptr->u.halt.reason = reason;
+ trace_next();
+ }
+}
+
+/**
+ * @brief Adds an user trace record to the trace buffer.
+ *
+ * @param[in] up1 user parameter 1
+ * @param[in] up2 user parameter 2
+ *
+ * @iclass
+ */
+void chDbgWriteTraceI(void *up1, void *up2) {
+
+ chDbgCheckClassI();
+
+ if ((ch.dbg.trace_buffer.suspended & CH_DBG_TRACE_MASK_USER) == 0U) {
+ ch.dbg.trace_buffer.ptr->type = CH_TRACE_TYPE_USER;
+ ch.dbg.trace_buffer.ptr->state = 0;
+ ch.dbg.trace_buffer.ptr->u.user.up1 = up1;
+ ch.dbg.trace_buffer.ptr->u.user.up2 = up2;
+ trace_next();
+ }
+}
+
+/**
+ * @brief Adds an user trace record to the trace buffer.
+ *
+ * @param[in] up1 user parameter 1
+ * @param[in] up2 user parameter 2
+ *
+ * @api
+ */
+void chDbgWriteTrace(void *up1, void *up2) {
+
+ chSysLock();
+ chDbgWriteTraceI(up1, up2);
+ chSysUnlock();
+}
+
+/**
+ * @brief Suspends one or more trace events.
+ *
+ * @param[in] mask mask of the trace events to be suspended
+ *
+ * @iclass
+ */
+void chDbgSuspendTraceI(uint16_t mask) {
+
+ chDbgCheckClassI();
+
+ ch.dbg.trace_buffer.suspended |= mask;
+}
+
+/**
+ * @brief Suspends one or more trace events.
+ *
+ * @param[in] mask mask of the trace events to be suspended
+ *
+ * @api
+ */
+void chDbgSuspendTrace(uint16_t mask) {
+
+ chSysLock();
+ chDbgSuspendTraceI(mask);
+ chSysUnlock();
+}
+
+/**
+ * @brief Resumes one or more trace events.
+ *
+ * @param[in] mask mask of the trace events to be resumed
+ *
+ * @iclass
+ */
+void chDbgResumeTraceI(uint16_t mask) {
+
+ chDbgCheckClassI();
+
+ ch.dbg.trace_buffer.suspended &= ~mask;
+}
+
+/**
+ * @brief Resumes one or more trace events.
+ *
+ * @param[in] mask mask of the trace events to be resumed
+ *
+ * @api
+ */
+void chDbgResumeTrace(uint16_t mask) {
+
+ chSysLock();
+ chDbgResumeTraceI(mask);
+ chSysUnlock();
+}
+#endif /* CH_DBG_TRACE_MASK != CH_DBG_TRACE_MASK_DISABLED */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/src/chvt.c b/ChibiOS_20.3.2/os/rt/src/chvt.c
new file mode 100644
index 0000000..c138796
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/src/chvt.c
@@ -0,0 +1,477 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file rt/src/chvt.c
+ * @brief Time and Virtual Timers module code.
+ *
+ * @addtogroup time
+ * @details Time and Virtual Timers related APIs and services.
+ * @{
+ */
+
+#include "ch.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/**
+ * @brief List empty check.
+ *
+ * @param[in] vtlp pointer to the list header
+ *
+ * @notapi
+ */
+#define is_vtlist_empty(vtlp) ((vtlp) == (virtual_timers_list_t *)(vtlp)->next)
+
+/**
+ * @brief Last timer in the list check.
+ *
+ * @param[in] vtlp pointer to the list header
+ * @param[in] vtp pointer to the timer header
+ *
+ * @notapi
+ */
+#define is_last_timer(vtlp, vtp) ((vtp)->next == (virtual_timer_t *)(vtlp))
+
+/**
+ * @brief Fist timer in the list check.
+ *
+ * @param[in] vtlp pointer to the list header
+ * @param[in] vtp pointer to the timer header
+ *
+ * @notapi
+ */
+#define is_first_timer(vtlp, vtp) ((vtlp)->next == (vtp))
+
+/**
+ * @brief Timer check.
+ *
+ * @param[in] vtlp pointer to the list header
+ * @param[in] vtp pointer to the timer header
+ *
+ * @notapi
+ */
+#define is_timer(vtlp, vtp) ((vtp) != (virtual_timer_t *)(vtlp))
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+#if (CH_CFG_ST_TIMEDELTA > 0) || defined(__DOXYGEN__)
+/**
+ * @brief Delta list compression.
+ *
+ * @param[in] vtlp pointer to the delta list to be compressed
+ * @param[in] deltanow interval to be compacted starting from "lasttime"
+ *
+ * @notapi
+ */
+static void vt_list_compress(virtual_timers_list_t *vtlp,
+ sysinterval_t deltanow) {
+ virtual_timer_t *vtp = vtlp->next;
+
+ /* The loop is bounded because the delta list header has the delta field
+ set to (sysinterval_t)-1 which is larger than all deltas.*/
+ while (vtp->delta < deltanow) {
+ deltanow -= vtp->delta;
+ vtp->delta = (sysinterval_t)0;
+ vtp = vtp->next;
+ }
+
+ vtlp->lasttime = vtlp->lasttime + deltanow;
+
+ /* Adjusting next timer in the list, if any.*/
+ if (is_timer(vtlp, vtp)) {
+ vtp->delta -= deltanow;
+ }
+}
+#endif
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Virtual Timers initialization.
+ * @note Internal use only.
+ *
+ * @notapi
+ */
+void _vt_init(void) {
+
+ ch.vtlist.next = (virtual_timer_t *)&ch.vtlist;
+ ch.vtlist.prev = (virtual_timer_t *)&ch.vtlist;
+ ch.vtlist.delta = (sysinterval_t)-1;
+#if CH_CFG_ST_TIMEDELTA == 0
+ ch.vtlist.systime = (systime_t)0;
+#else /* CH_CFG_ST_TIMEDELTA > 0 */
+ ch.vtlist.lasttime = (systime_t)0;
+#endif /* CH_CFG_ST_TIMEDELTA > 0 */
+}
+
+/**
+ * @brief Enables a virtual timer.
+ * @details The timer is enabled and programmed to trigger after the delay
+ * specified as parameter.
+ * @pre The timer must not be already armed before calling this function.
+ * @note The callback function is invoked from interrupt context.
+ *
+ * @param[out] vtp the @p virtual_timer_t structure pointer
+ * @param[in] delay the number of ticks before the operation timeouts, the
+ * special values are handled as follow:
+ * - @a TIME_INFINITE is allowed but interpreted as a
+ * normal time specification.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ * @param[in] vtfunc the timer callback function. After invoking the
+ * callback the timer is disabled and the structure can
+ * be disposed or reused.
+ * @param[in] par a parameter that will be passed to the callback
+ * function
+ *
+ * @iclass
+ */
+void chVTDoSetI(virtual_timer_t *vtp, sysinterval_t delay,
+ vtfunc_t vtfunc, void *par) {
+ virtual_timers_list_t *vtlp = &ch.vtlist;
+ virtual_timer_t *p;
+ sysinterval_t delta;
+
+ chDbgCheckClassI();
+ chDbgCheck((vtp != NULL) && (vtfunc != NULL) && (delay != TIME_IMMEDIATE));
+
+ vtp->par = par;
+ vtp->func = vtfunc;
+
+#if CH_CFG_ST_TIMEDELTA > 0
+ {
+ systime_t now = chVTGetSystemTimeX();
+ sysinterval_t deltanow;
+
+ /* If the requested delay is lower than the minimum safe delta then it
+ is raised to the minimum safe value.*/
+ if (delay < (sysinterval_t)CH_CFG_ST_TIMEDELTA) {
+ delay = (sysinterval_t)CH_CFG_ST_TIMEDELTA;
+ }
+
+ /* Special case where the timers list is empty.*/
+ if (is_vtlist_empty(vtlp)) {
+
+ /* The delta list is empty, the current time becomes the new
+ delta list base time, the timer is inserted.*/
+ vtlp->lasttime = now;
+ vtlp->next = vtp;
+ vtlp->prev = vtp;
+ vtp->next = (virtual_timer_t *)vtlp;
+ vtp->prev = (virtual_timer_t *)vtlp;
+ vtp->delta = delay;
+
+#if CH_CFG_INTERVALS_SIZE > CH_CFG_ST_RESOLUTION
+ /* The delta could be too large for the physical timer to handle.*/
+ if (delay > (sysinterval_t)TIME_MAX_SYSTIME) {
+ delay = (sysinterval_t)TIME_MAX_SYSTIME;
+ }
+#endif
+
+ /* Being the first element in the list the alarm timer is started.*/
+ port_timer_start_alarm(chTimeAddX(vtlp->lasttime, delay));
+
+ return;
+ }
+
+ /* Delay as delta from 'lasttime'. Note, it can overflow and the value
+ becomes lower than 'deltanow'.*/
+ deltanow = chTimeDiffX(vtlp->lasttime, now);
+ delta = deltanow + delay;
+
+ /* Scenario where a very large delay exceeded the numeric range, it
+ requires a special handling, the compression procedure.*/
+ if (delta < deltanow) {
+ vt_list_compress(vtlp, deltanow);
+ delta -= deltanow;
+ }
+ else if (delta < vtlp->next->delta) {
+ sysinterval_t deadline_delta;
+
+ /* A small delay that will become the first element in the delta list
+ and next deadline.*/
+ deadline_delta = delta;
+#if CH_CFG_INTERVALS_SIZE > CH_CFG_ST_RESOLUTION
+ /* The delta could be too large for the physical timer to handle.*/
+ if (deadline_delta > (sysinterval_t)TIME_MAX_SYSTIME) {
+ deadline_delta = (sysinterval_t)TIME_MAX_SYSTIME;
+ }
+#endif
+ port_timer_set_alarm(chTimeAddX(vtlp->lasttime, deadline_delta));
+ }
+ }
+#else /* CH_CFG_ST_TIMEDELTA == 0 */
+ /* Delta is initially equal to the specified delay.*/
+ delta = delay;
+#endif /* CH_CFG_ST_TIMEDELTA == 0 */
+
+ /* The delta list is scanned in order to find the correct position for
+ this timer. */
+ p = vtlp->next;
+ while (p->delta < delta) {
+ /* Debug assert if the timer is already in the list.*/
+ chDbgAssert(p != vtp, "timer already armed");
+
+ delta -= p->delta;
+ p = p->next;
+ }
+
+ /* The timer is inserted in the delta list.*/
+ vtp->next = p;
+ vtp->prev = vtp->next->prev;
+ vtp->prev->next = vtp;
+ p->prev = vtp;
+ vtp->delta = delta;
+
+ /* Calculate new delta for the following entry.*/
+ p->delta -= delta;
+
+ /* Special case when the timer is in last position in the list, the
+ value in the header must be restored.*/
+ vtlp->delta = (sysinterval_t)-1;
+}
+
+/**
+ * @brief Disables a Virtual Timer.
+ * @pre The timer must be in armed state before calling this function.
+ *
+ * @param[in] vtp the @p virtual_timer_t structure pointer
+ *
+ * @iclass
+ */
+void chVTDoResetI(virtual_timer_t *vtp) {
+ virtual_timers_list_t *vtlp = &ch.vtlist;
+
+ chDbgCheckClassI();
+ chDbgCheck(vtp != NULL);
+ chDbgAssert(vtp->func != NULL, "timer not set or already triggered");
+
+#if CH_CFG_ST_TIMEDELTA == 0
+
+ /* The delta of the timer is added to the next timer.*/
+ vtp->next->delta += vtp->delta;
+
+ /* Removing the element from the delta list.*/
+ vtp->prev->next = vtp->next;
+ vtp->next->prev = vtp->prev;
+ vtp->func = NULL;
+
+ /* The above code changes the value in the header when the removed element
+ is the last of the list, restoring it.*/
+ vtlp->delta = (sysinterval_t)-1;
+#else /* CH_CFG_ST_TIMEDELTA > 0 */
+ sysinterval_t nowdelta, delta;
+
+ /* If the timer is not the first of the list then it is simply unlinked
+ else the operation is more complex.*/
+ if (!is_first_timer(vtlp, vtp)) {
+ /* Removing the element from the delta list.*/
+ vtp->prev->next = vtp->next;
+ vtp->next->prev = vtp->prev;
+ vtp->func = NULL;
+
+ /* Adding delta to the next element, if it is not the last one.*/
+ if (is_timer(vtlp, vtp->next))
+ vtp->next->delta += vtp->delta;
+
+ return;
+ }
+
+ /* Removing the first timer from the list.*/
+ vtlp->next = vtp->next;
+ vtlp->next->prev = (virtual_timer_t *)vtlp;
+ vtp->func = NULL;
+
+ /* If the list become empty then the alarm timer is stopped and done.*/
+ if (is_vtlist_empty(vtlp)) {
+ port_timer_stop_alarm();
+
+ return;
+ }
+
+ /* The delta of the removed timer is added to the new first timer.*/
+ vtlp->next->delta += vtp->delta;
+
+ /* If the new first timer has a delta of zero then the alarm is not
+ modified, the already programmed alarm will serve it.*/
+/* if (vtlp->next->delta == 0) {
+ return;
+ }*/
+
+ /* Distance in ticks between the last alarm event and current time.*/
+ nowdelta = chTimeDiffX(vtlp->lasttime, chVTGetSystemTimeX());
+
+ /* If the current time surpassed the time of the next element in list
+ then the event interrupt is already pending, just return.*/
+ if (nowdelta >= vtlp->next->delta) {
+ return;
+ }
+
+ /* Distance from the next scheduled event and now.*/
+ delta = vtlp->next->delta - nowdelta;
+
+ /* Making sure to not schedule an event closer than CH_CFG_ST_TIMEDELTA
+ ticks from now.*/
+ if (delta < (sysinterval_t)CH_CFG_ST_TIMEDELTA) {
+ delta = nowdelta + (sysinterval_t)CH_CFG_ST_TIMEDELTA;
+ }
+ else {
+ delta = nowdelta + delta;
+#if CH_CFG_INTERVALS_SIZE > CH_CFG_ST_RESOLUTION
+ /* The delta could be too large for the physical timer to handle.*/
+ if (delta > (sysinterval_t)TIME_MAX_SYSTIME) {
+ delta = (sysinterval_t)TIME_MAX_SYSTIME;
+ }
+#endif
+ }
+ port_timer_set_alarm(chTimeAddX(vtlp->lasttime, delta));
+#endif /* CH_CFG_ST_TIMEDELTA > 0 */
+}
+
+/**
+ * @brief Virtual timers ticker.
+ * @note The system lock is released before entering the callback and
+ * re-acquired immediately after. It is callback's responsibility
+ * to acquire the lock if needed. This is done in order to reduce
+ * interrupts jitter when many timers are in use.
+ *
+ * @iclass
+ */
+void chVTDoTickI(void) {
+ virtual_timers_list_t *vtlp = &ch.vtlist;
+
+ chDbgCheckClassI();
+
+#if CH_CFG_ST_TIMEDELTA == 0
+ vtlp->systime++;
+ if (!is_vtlist_empty(vtlp)) {
+ /* The list is not empty, processing elements on top.*/
+ --vtlp->next->delta;
+ while (vtlp->next->delta == (sysinterval_t)0) {
+ virtual_timer_t *vtp;
+ vtfunc_t fn;
+
+ vtp = vtlp->next;
+ fn = vtp->func;
+ vtp->func = NULL;
+ vtp->next->prev = (virtual_timer_t *)vtlp;
+ vtlp->next = vtp->next;
+ chSysUnlockFromISR();
+ fn(vtp->par);
+ chSysLockFromISR();
+ }
+ }
+#else /* CH_CFG_ST_TIMEDELTA > 0 */
+ virtual_timer_t *vtp;
+ systime_t now;
+ sysinterval_t delta, nowdelta;
+
+ /* Looping through timers.*/
+ vtp = vtlp->next;
+ while (true) {
+
+ /* Getting the system time as reference.*/
+ now = chVTGetSystemTimeX();
+ nowdelta = chTimeDiffX(vtlp->lasttime, now);
+
+ /* The list scan is limited by the timers header having
+ "vtlp->vt_delta == (sysinterval_t)-1" which is
+ greater than all deltas.*/
+ if (nowdelta < vtp->delta) {
+ break;
+ }
+
+ /* Consuming all timers between "vtp->lasttime" and now.*/
+ do {
+ vtfunc_t fn;
+
+ /* The "last time" becomes this timer's expiration time.*/
+ vtlp->lasttime += vtp->delta;
+ nowdelta -= vtp->delta;
+
+ vtp->next->prev = (virtual_timer_t *)vtlp;
+ vtlp->next = vtp->next;
+ fn = vtp->func;
+ vtp->func = NULL;
+
+ /* If the list becomes empty then the timer is stopped.*/
+ if (is_vtlist_empty(vtlp)) {
+ port_timer_stop_alarm();
+ }
+
+ /* The callback is invoked outside the kernel critical zone.*/
+ chSysUnlockFromISR();
+ fn(vtp->par);
+ chSysLockFromISR();
+
+ /* Next element in the list.*/
+ vtp = vtlp->next;
+ }
+ while (vtp->delta <= nowdelta);
+ }
+
+ /* If the list is empty, nothing else to do.*/
+ if (is_vtlist_empty(vtlp)) {
+ return;
+ }
+
+ /* The "unprocessed nowdelta" time slice is added to "last time"
+ and subtracted to next timer's delta.*/
+ vtlp->lasttime += nowdelta;
+ vtlp->next->delta -= nowdelta;
+
+ /* Recalculating the next alarm time.*/
+ delta = vtp->delta - chTimeDiffX(vtlp->lasttime, now);
+ if (delta < (sysinterval_t)CH_CFG_ST_TIMEDELTA) {
+ delta = (sysinterval_t)CH_CFG_ST_TIMEDELTA;
+ }
+#if CH_CFG_INTERVALS_SIZE > CH_CFG_ST_RESOLUTION
+ /* The delta could be too large for the physical timer to handle.*/
+ else if (delta > (sysinterval_t)TIME_MAX_SYSTIME) {
+ delta = (sysinterval_t)TIME_MAX_SYSTIME;
+ }
+#endif
+ port_timer_set_alarm(chTimeAddX(now, delta));
+
+ chDbgAssert(chTimeDiffX(vtlp->lasttime, chVTGetSystemTimeX()) <=
+ chTimeDiffX(vtlp->lasttime, chTimeAddX(now, delta)),
+ "exceeding delta");
+#endif /* CH_CFG_ST_TIMEDELTA > 0 */
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/templates/chconf.h b/ChibiOS_20.3.2/os/rt/templates/chconf.h
new file mode 100644
index 0000000..dd19aae
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/templates/chconf.h
@@ -0,0 +1,756 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file rt/templates/chconf.h
+ * @brief Configuration file template.
+ * @details A copy of this file must be placed in each project directory, it
+ * contains the application specific kernel settings.
+ *
+ * @addtogroup config
+ * @details Kernel related settings and hooks.
+ * @{
+ */
+
+#ifndef CHCONF_H
+#define CHCONF_H
+
+#define _CHIBIOS_RT_CONF_
+#define _CHIBIOS_RT_CONF_VER_6_1_
+
+/*===========================================================================*/
+/**
+ * @name System timers settings
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System time counter resolution.
+ * @note Allowed values are 16 or 32 bits.
+ */
+#if !defined(CH_CFG_ST_RESOLUTION)
+#define CH_CFG_ST_RESOLUTION 32
+#endif
+
+/**
+ * @brief System tick frequency.
+ * @details Frequency of the system timer that drives the system ticks. This
+ * setting also defines the system tick time unit.
+ */
+#if !defined(CH_CFG_ST_FREQUENCY)
+#define CH_CFG_ST_FREQUENCY 10000
+#endif
+
+/**
+ * @brief Time intervals data size.
+ * @note Allowed values are 16, 32 or 64 bits.
+ */
+#if !defined(CH_CFG_INTERVALS_SIZE)
+#define CH_CFG_INTERVALS_SIZE 32
+#endif
+
+/**
+ * @brief Time types data size.
+ * @note Allowed values are 16 or 32 bits.
+ */
+#if !defined(CH_CFG_TIME_TYPES_SIZE)
+#define CH_CFG_TIME_TYPES_SIZE 32
+#endif
+
+/**
+ * @brief Time delta constant for the tick-less mode.
+ * @note If this value is zero then the system uses the classic
+ * periodic tick. This value represents the minimum number
+ * of ticks that is safe to specify in a timeout directive.
+ * The value one is not valid, timeouts are rounded up to
+ * this value.
+ */
+#if !defined(CH_CFG_ST_TIMEDELTA)
+#define CH_CFG_ST_TIMEDELTA 2
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel parameters and options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Round robin interval.
+ * @details This constant is the number of system ticks allowed for the
+ * threads before preemption occurs. Setting this value to zero
+ * disables the preemption for threads with equal priority and the
+ * round robin becomes cooperative. Note that higher priority
+ * threads can still preempt, the kernel is always preemptive.
+ * @note Disabling the round robin preemption makes the kernel more compact
+ * and generally faster.
+ * @note The round robin preemption is not supported in tickless mode and
+ * must be set to zero in that case.
+ */
+#if !defined(CH_CFG_TIME_QUANTUM)
+#define CH_CFG_TIME_QUANTUM 0
+#endif
+
+/**
+ * @brief Idle thread automatic spawn suppression.
+ * @details When this option is activated the function @p chSysInit()
+ * does not spawn the idle thread. The application @p main()
+ * function becomes the idle thread and must implement an
+ * infinite loop.
+ */
+#if !defined(CH_CFG_NO_IDLE_THREAD)
+#define CH_CFG_NO_IDLE_THREAD FALSE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Performance options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief OS optimization.
+ * @details If enabled then time efficient rather than space efficient code
+ * is used when two possible implementations exist.
+ *
+ * @note This is not related to the compiler optimization options.
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_OPTIMIZE_SPEED)
+#define CH_CFG_OPTIMIZE_SPEED TRUE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Subsystem options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Time Measurement APIs.
+ * @details If enabled then the time measurement APIs are included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_TM)
+#define CH_CFG_USE_TM TRUE
+#endif
+
+/**
+ * @brief Threads registry APIs.
+ * @details If enabled then the registry APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_REGISTRY)
+#define CH_CFG_USE_REGISTRY TRUE
+#endif
+
+/**
+ * @brief Threads synchronization APIs.
+ * @details If enabled then the @p chThdWait() function is included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_WAITEXIT)
+#define CH_CFG_USE_WAITEXIT TRUE
+#endif
+
+/**
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_SEMAPHORES)
+#define CH_CFG_USE_SEMAPHORES TRUE
+#endif
+
+/**
+ * @brief Semaphores queuing mode.
+ * @details If enabled then the threads are enqueued on semaphores by
+ * priority rather than in FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY)
+#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
+#endif
+
+/**
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_MUTEXES)
+#define CH_CFG_USE_MUTEXES TRUE
+#endif
+
+/**
+ * @brief Enables recursive behavior on mutexes.
+ * @note Recursive mutexes are heavier and have an increased
+ * memory footprint.
+ *
+ * @note The default is @p FALSE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE)
+#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
+#endif
+
+/**
+ * @brief Conditional Variables APIs.
+ * @details If enabled then the conditional variables APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#if !defined(CH_CFG_USE_CONDVARS)
+#define CH_CFG_USE_CONDVARS TRUE
+#endif
+
+/**
+ * @brief Conditional Variables APIs with timeout.
+ * @details If enabled then the conditional variables APIs with timeout
+ * specification are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_CONDVARS.
+ */
+#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT)
+#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE
+#endif
+
+/**
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_EVENTS)
+#define CH_CFG_USE_EVENTS TRUE
+#endif
+
+/**
+ * @brief Events Flags APIs with timeout.
+ * @details If enabled then the events APIs with timeout specification
+ * are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_EVENTS.
+ */
+#if !defined(CH_CFG_USE_EVENTS_TIMEOUT)
+#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
+#endif
+
+/**
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_MESSAGES)
+#define CH_CFG_USE_MESSAGES TRUE
+#endif
+
+/**
+ * @brief Synchronous Messages queuing mode.
+ * @details If enabled then messages are served by priority rather than in
+ * FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_MESSAGES.
+ */
+#if !defined(CH_CFG_USE_MESSAGES_PRIORITY)
+#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
+#endif
+
+/**
+ * @brief Dynamic Threads APIs.
+ * @details If enabled then the dynamic threads creation APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_WAITEXIT.
+ * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
+ */
+#if !defined(CH_CFG_USE_DYNAMIC)
+#define CH_CFG_USE_DYNAMIC TRUE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name OSLIB options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#if !defined(CH_CFG_USE_MAILBOXES)
+#define CH_CFG_USE_MAILBOXES TRUE
+#endif
+
+/**
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_MEMCORE)
+#define CH_CFG_USE_MEMCORE TRUE
+#endif
+
+/**
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
+ * provide the @p __heap_base__ and @p __heap_end__ symbols.
+ * @note Requires @p CH_CFG_USE_MEMCORE.
+ */
+#if !defined(CH_CFG_MEMCORE_SIZE)
+#define CH_CFG_MEMCORE_SIZE 0
+#endif
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
+ * @p CH_CFG_USE_SEMAPHORES.
+ * @note Mutexes are recommended.
+ */
+#if !defined(CH_CFG_USE_HEAP)
+#define CH_CFG_USE_HEAP TRUE
+#endif
+
+/**
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_MEMPOOLS)
+#define CH_CFG_USE_MEMPOOLS TRUE
+#endif
+
+/**
+ * @brief Objects FIFOs APIs.
+ * @details If enabled then the objects FIFOs APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_OBJ_FIFOS)
+#define CH_CFG_USE_OBJ_FIFOS TRUE
+#endif
+
+/**
+ * @brief Pipes APIs.
+ * @details If enabled then the pipes APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_PIPES)
+#define CH_CFG_USE_PIPES TRUE
+#endif
+
+/**
+ * @brief Objects Caches APIs.
+ * @details If enabled then the objects caches APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_OBJ_CACHES)
+#define CH_CFG_USE_OBJ_CACHES TRUE
+#endif
+
+/**
+ * @brief Delegate threads APIs.
+ * @details If enabled then the delegate threads APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_DELEGATES)
+#define CH_CFG_USE_DELEGATES TRUE
+#endif
+
+/**
+ * @brief Jobs Queues APIs.
+ * @details If enabled then the jobs queues APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#if !defined(CH_CFG_USE_JOBS)
+#define CH_CFG_USE_JOBS TRUE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Objects factory options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Objects Factory APIs.
+ * @details If enabled then the objects factory APIs are included in the
+ * kernel.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_CFG_USE_FACTORY)
+#define CH_CFG_USE_FACTORY TRUE
+#endif
+
+/**
+ * @brief Maximum length for object names.
+ * @details If the specified length is zero then the name is stored by
+ * pointer but this could have unintended side effects.
+ */
+#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH)
+#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8
+#endif
+
+/**
+ * @brief Enables the registry of generic objects.
+ */
+#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY)
+#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE
+#endif
+
+/**
+ * @brief Enables factory for generic buffers.
+ */
+#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS)
+#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE
+#endif
+
+/**
+ * @brief Enables factory for semaphores.
+ */
+#if !defined(CH_CFG_FACTORY_SEMAPHORES)
+#define CH_CFG_FACTORY_SEMAPHORES TRUE
+#endif
+
+/**
+ * @brief Enables factory for mailboxes.
+ */
+#if !defined(CH_CFG_FACTORY_MAILBOXES)
+#define CH_CFG_FACTORY_MAILBOXES TRUE
+#endif
+
+/**
+ * @brief Enables factory for objects FIFOs.
+ */
+#if !defined(CH_CFG_FACTORY_OBJ_FIFOS)
+#define CH_CFG_FACTORY_OBJ_FIFOS TRUE
+#endif
+
+/**
+ * @brief Enables factory for Pipes.
+ */
+#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__)
+#define CH_CFG_FACTORY_PIPES TRUE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Debug options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Debug option, kernel statistics.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_STATISTICS)
+#define CH_DBG_STATISTICS FALSE
+#endif
+
+/**
+ * @brief Debug option, system state check.
+ * @details If enabled the correct call protocol for system APIs is checked
+ * at runtime.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_SYSTEM_STATE_CHECK)
+#define CH_DBG_SYSTEM_STATE_CHECK TRUE
+#endif
+
+/**
+ * @brief Debug option, parameters checks.
+ * @details If enabled then the checks on the API functions input
+ * parameters are activated.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_ENABLE_CHECKS)
+#define CH_DBG_ENABLE_CHECKS TRUE
+#endif
+
+/**
+ * @brief Debug option, consistency checks.
+ * @details If enabled then all the assertions in the kernel code are
+ * activated. This includes consistency checks inside the kernel,
+ * runtime anomalies and port-defined checks.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_ENABLE_ASSERTS)
+#define CH_DBG_ENABLE_ASSERTS TRUE
+#endif
+
+/**
+ * @brief Debug option, trace buffer.
+ * @details If enabled then the trace buffer is activated.
+ *
+ * @note The default is @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#if !defined(CH_DBG_TRACE_MASK)
+#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_ALL
+#endif
+
+/**
+ * @brief Trace buffer entries.
+ * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
+ * different from @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#if !defined(CH_DBG_TRACE_BUFFER_SIZE)
+#define CH_DBG_TRACE_BUFFER_SIZE 128
+#endif
+
+/**
+ * @brief Debug option, stack checks.
+ * @details If enabled then a runtime stack check is performed.
+ *
+ * @note The default is @p FALSE.
+ * @note The stack check is performed in a architecture/port dependent way.
+ * It may not be implemented or some ports.
+ * @note The default failure mode is to halt the system with the global
+ * @p panic_msg variable set to @p NULL.
+ */
+#if !defined(CH_DBG_ENABLE_STACK_CHECK)
+#define CH_DBG_ENABLE_STACK_CHECK TRUE
+#endif
+
+/**
+ * @brief Debug option, stacks initialization.
+ * @details If enabled then the threads working area is filled with a byte
+ * value when a thread is created. This can be useful for the
+ * runtime measurement of the used stack.
+ *
+ * @note The default is @p FALSE.
+ */
+#if !defined(CH_DBG_FILL_THREADS)
+#define CH_DBG_FILL_THREADS TRUE
+#endif
+
+/**
+ * @brief Debug option, threads profiling.
+ * @details If enabled then a field is added to the @p thread_t structure that
+ * counts the system ticks occurred while executing the thread.
+ *
+ * @note The default is @p FALSE.
+ * @note This debug option is not currently compatible with the
+ * tickless mode.
+ */
+#if !defined(CH_DBG_THREADS_PROFILING)
+#define CH_DBG_THREADS_PROFILING FALSE
+#endif
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel hooks
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System structure extension.
+ * @details User fields added to the end of the @p ch_system_t structure.
+ */
+#define CH_CFG_SYSTEM_EXTRA_FIELDS \
+ /* Add threads custom fields here.*/
+
+/**
+ * @brief System initialization hook.
+ * @details User initialization code added to the @p chSysInit() function
+ * just before interrupts are enabled globally.
+ */
+#define CH_CFG_SYSTEM_INIT_HOOK() { \
+ /* Add threads initialization code here.*/ \
+}
+
+/**
+ * @brief Threads descriptor structure extension.
+ * @details User fields added to the end of the @p thread_t structure.
+ */
+#define CH_CFG_THREAD_EXTRA_FIELDS \
+ /* Add threads custom fields here.*/
+
+/**
+ * @brief Threads initialization hook.
+ * @details User initialization code added to the @p _thread_init() function.
+ *
+ * @note It is invoked from within @p _thread_init() and implicitly from all
+ * the threads creation APIs.
+ */
+#define CH_CFG_THREAD_INIT_HOOK(tp) { \
+ /* Add threads initialization code here.*/ \
+}
+
+/**
+ * @brief Threads finalization hook.
+ * @details User finalization code added to the @p chThdExit() API.
+ */
+#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
+ /* Add threads finalization code here.*/ \
+}
+
+/**
+ * @brief Context switch hook.
+ * @details This hook is invoked just before switching between threads.
+ */
+#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
+ /* Context switch code here.*/ \
+}
+
+/**
+ * @brief ISR enter hook.
+ */
+#define CH_CFG_IRQ_PROLOGUE_HOOK() { \
+ /* IRQ prologue code here.*/ \
+}
+
+/**
+ * @brief ISR exit hook.
+ */
+#define CH_CFG_IRQ_EPILOGUE_HOOK() { \
+ /* IRQ epilogue code here.*/ \
+}
+
+/**
+ * @brief Idle thread enter hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to activate a power saving mode.
+ */
+#define CH_CFG_IDLE_ENTER_HOOK() { \
+ /* Idle-enter code here.*/ \
+}
+
+/**
+ * @brief Idle thread leave hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to deactivate a power saving mode.
+ */
+#define CH_CFG_IDLE_LEAVE_HOOK() { \
+ /* Idle-leave code here.*/ \
+}
+
+/**
+ * @brief Idle Loop hook.
+ * @details This hook is continuously invoked by the idle thread loop.
+ */
+#define CH_CFG_IDLE_LOOP_HOOK() { \
+ /* Idle loop code here.*/ \
+}
+
+/**
+ * @brief System tick event hook.
+ * @details This hook is invoked in the system tick handler immediately
+ * after processing the virtual timers queue.
+ */
+#define CH_CFG_SYSTEM_TICK_HOOK() { \
+ /* System tick event code here.*/ \
+}
+
+/**
+ * @brief System halt hook.
+ * @details This hook is invoked in case to a system halting error before
+ * the system is halted.
+ */
+#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
+ /* System halt code here.*/ \
+}
+
+/**
+ * @brief Trace hook.
+ * @details This hook is invoked each time a new record is written in the
+ * trace buffer.
+ */
+#define CH_CFG_TRACE_HOOK(tep) { \
+ /* Trace code here.*/ \
+}
+
+/** @} */
+
+/*===========================================================================*/
+/* Port-specific settings (override port settings defaulted in chcore.h). */
+/*===========================================================================*/
+
+#endif /* CHCONF_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/templates/meta/module.c b/ChibiOS_20.3.2/os/rt/templates/meta/module.c
new file mode 100644
index 0000000..e88687d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/templates/meta/module.c
@@ -0,0 +1,80 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file chXxx.c
+ * @brief XXX module code.
+ *
+ * @addtogroup XXX
+ * @{
+ */
+
+#include "ch.h"
+
+#if CH_CFG_USE_XXX || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief XXX Module initialization.
+ * @note This function is implicitly invoked on system initialization,
+ * there is no need to explicitly initialize the module.
+ *
+ * @notapi
+ */
+void _xxx_init(void) {
+
+}
+
+/**
+ * @brief Initializes a @p xxx_t object.
+ *
+ * @param[out] xxxp pointer to the @p xxx_t object
+ *
+ * @init
+ */
+void chXxxObjectInit(xxx_t *xxxp) {
+
+}
+
+#endif /* CH_CFG_USE_XXX */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/rt/templates/meta/module.h b/ChibiOS_20.3.2/os/rt/templates/meta/module.h
new file mode 100644
index 0000000..0e120c4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/rt/templates/meta/module.h
@@ -0,0 +1,76 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file chXxx.h
+ * @brief XXX Module macros and structures.
+ *
+ * @addtogroup XXX
+ * @{
+ */
+
+#ifndef CHXXX_H
+#define CHXXX_H
+
+#include "ch.h"
+
+#if CH_CFG_USE_XXX || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chXxxInit(void);
+ void chXxxObjectInit(xxx_t *xxxp);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* CH_CFG_USE_XXX */
+
+#endif /* CHXXX_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/sb/common/sberr.h b/ChibiOS_20.3.2/os/sb/common/sberr.h
new file mode 100644
index 0000000..b827f7d
--- /dev/null
+++ b/ChibiOS_20.3.2/os/sb/common/sberr.h
@@ -0,0 +1,97 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file sb/common/sberr.h
+ * @brief ARMv7-M sandbox common macros and structures.
+ *
+ * @addtogroup ARM_SANDBOX_ERRORS
+ * @{
+ */
+
+#ifndef SBERR_H
+#define SBERR_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @name Sandbox API error codes
+ * @{
+ */
+#define SB_ERR_NOERROR 0U
+#define SB_ERR_ENOENT ((uint32_t)(-2))
+#define SB_ERR_EFAULT ((uint32_t)(-14))
+#define SB_ERR_EBUSY ((uint32_t)(-16))
+#define SB_ERR_EINVAL ((uint32_t)(-22))
+#define SB_ERR_ESPIPE ((uint32_t)(-29))
+#define SB_ERR_EBADFD ((uint32_t)(-81))
+#define SB_ERR_ENOSYS ((uint32_t)(-88))
+
+#define SB_ERR_ERRORMASK 0xFFFFFF00U
+#define SB_ERR_ISERROR(x) (((uint32_t)(x) & SB_ERR_ERRORMASK) == SB_ERR_ERRORMASK)
+/** @} */
+
+/**
+ * @name Posix-like function codes
+ * @{
+ */
+#define SB_POSIX_OPEN 1
+#define SB_POSIX_CLOSE 2
+#define SB_POSIX_READ 3
+#define SB_POSIX_WRITE 4
+#define SB_POSIX_LSEEK 5
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* SBERR_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/sb/host/compilers/GCC/sbexc.S b/ChibiOS_20.3.2/os/sb/host/compilers/GCC/sbexc.S
new file mode 100644
index 0000000..3cccaf3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/sb/host/compilers/GCC/sbexc.S
@@ -0,0 +1,170 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file sb/sbexc.S
+ * @brief Exception handlers for sandbox.
+ *
+ * @defgroup ARMV7M_SANDBOX_EXCEPTIONS SandBox Exception Vectors
+ * @{
+ */
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+#define FPU 0xE000EF30
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Code section. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+
+ .syntax unified
+ .cpu cortex-m3
+ .thumb
+
+ .text
+
+ .align 2
+ .thumb_func
+ .global port_syscall
+port_syscall:
+ ldr r3, =sb_syscalls
+ ldr.w r3, [r3, r1, lsl #2]
+ blx r3
+ svc 0
+.zombies1: b .zombies1
+
+ .align 2
+ .thumb_func
+ .global HardFault_Handler
+HardFault_Handler:
+ tst.w lr, #8
+ beq.n .normal_hf
+ mrs r3, CONTROL
+ tst.w r3, #1
+ bne.w .exit_thd
+.normal_hf: ldr r3, =HardFault_Handler_SB
+ bx r3
+
+ .align 2
+ .thumb_func
+ .global MemManage_Handler
+MemManage_Handler:
+ tst.w lr, #8
+ beq.n .normal_mm
+ mrs r3, CONTROL
+ tst.w r3, #1
+ bne.w .exit_thd
+.normal_mm: ldr r3, =MemManage_Handler_SB
+ bx r3
+
+ .align 2
+ .thumb_func
+ .global BusFault_Handler
+BusFault_Handler:
+ tst.w lr, #8
+ beq.n .normal_bf
+ mrs r3, CONTROL
+ tst.w r3, #1
+ bne.w .exit_thd
+.normal_bf: ldr r3, =BusFault_Handler_SB
+ bx r3
+
+ .align 2
+ .thumb_func
+ .global UsageFault_Handler
+UsageFault_Handler:
+ tst.w lr, #8
+ beq.n .normal_uf
+ mrs r3, CONTROL
+ tst.w r3, #1
+ bne.w .exit_thd
+.normal_uf: ldr r3, =UsageFault_Handler_SB
+ bx r3
+
+/*
+ * Common thread-exit handler on exception.
+ * Makes the current exception return on chThdExit() with the PSR
+ * value as exit message.
+ */
+.exit_thd:
+ mov.w r4, lr
+
+ /* This thread is going to die so going back on
+ S-PSP and working safely from there.*/
+ bl port_get_s_psp
+#if CORTEX_USE_FPU
+ sub.w r0, r0, #104
+#else
+ sub.w r0, r0, #32
+ msr PSP, r0
+#endif
+
+ /* Forcing return on exit syscall code with PSR
+ value as exit message.*/
+ mrs r2, PSR
+ str r2, [r0, #0]
+ ldr r2, =.do_exit
+ str r2, [r0, #24]
+ ldr r2, =0x01000000
+ str r2, [r0, #28]
+#if CORTEX_USE_FPU
+ ldr r2, =FPU
+ ldr r2, [r2, #12] /* FPDSCR*/
+ str r2, [r0, #96] /* port_extctx.fpscr */
+#endif
+
+ /* Back to privileged mode.*/
+ mrs r3, CONTROL
+ bic.w r3, #1
+ msr CONTROL, r3
+
+ /* Making sure there are no chained exceptions or interrupts
+ in the way, we need to exit this one atomically.*/
+ bl port_syslock_noinline
+ bx r4
+
+ /* Exception exit point.*/
+.do_exit:
+ bl chThdExitS
+.zombies2: b .zombies2
+
+ .align 2
+ .thumb_func
+ .weak HardFault_Handler_SB
+ .weak MemManage_Handler_SB
+ .weak BusFault_Handler_SB
+ .weak UsageFault_Handler_SB
+HardFault_Handler_SB:
+MemManage_Handler_SB:
+BusFault_Handler_SB:
+UsageFault_Handler_SB:
+ ldr r3, =_unhandled_exception
+ bx r3
+
+#endif /* !defined(__DOXYGEN__) */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/sb/host/compilers/GCC/sbhost.mk b/ChibiOS_20.3.2/os/sb/host/compilers/GCC/sbhost.mk
new file mode 100644
index 0000000..dbae38e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/sb/host/compilers/GCC/sbhost.mk
@@ -0,0 +1,14 @@
+# List of the ChibiOS ARMv7-M sandbox host files.
+SBHOSTSRC = $(CHIBIOS)/os/sb/host/sbhost.c \
+ $(CHIBIOS)/os/sb/host/sbapi.c \
+ $(CHIBIOS)/os/sb/host/sbposix.c
+
+SBHOSTASM = $(CHIBIOS)/os/sb/host/compilers/GCC/sbexc.S
+
+SBHOSTINC = $(CHIBIOS)/os/sb/common \
+ $(CHIBIOS)/os/sb/host
+
+# Shared variables
+ALLXASMSRC += $(SBHOSTASM)
+ALLCSRC += $(SBHOSTSRC)
+ALLINC += $(SBHOSTINC)
diff --git a/ChibiOS_20.3.2/os/sb/host/sb.h b/ChibiOS_20.3.2/os/sb/host/sb.h
new file mode 100644
index 0000000..5b58fbd
--- /dev/null
+++ b/ChibiOS_20.3.2/os/sb/host/sb.h
@@ -0,0 +1,151 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file sb/host/sb.h
+ * @brief ARM sandbox macros and structures.
+ *
+ * @addtogroup ARM_SANDBOX
+ * @{
+ */
+
+#ifndef SB_H
+#define SB_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @brief ChibiOS/SB identification macro.
+ */
+#define _CHIBIOS_SB_
+
+/**
+ * @brief Stable release flag.
+ */
+#define CH_SB_STABLE 1
+
+/**
+ * @name ChibiOS/SE version identification
+ * @{
+ */
+/**
+ * @brief Safety Extensions version string.
+ */
+#define CH_SB_VERSION "1.0.0"
+
+/**
+ * @brief Safety Extensions version major number.
+ */
+#define CH_SB_MAJOR 1
+
+/**
+ * @brief Safety Extensions version minor number.
+ */
+#define CH_SB_MINOR 0
+
+/**
+ * @brief Safety Extensions version patch number.
+ */
+#define CH_SB_PATCH 0
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of memory regions for each sandbox.
+ */
+#if !defined(SB_NUM_REGIONS) || defined(__DOXYGEN__)
+#define SB_NUM_REGIONS 2
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* License checks.*/
+#if !defined(CH_CUSTOMER_LIC_SB) || !defined(CH_LICENSE_FEATURES)
+#error "malformed chlicense.h"
+#endif
+
+#if CH_CUSTOMER_LIC_SB == FALSE
+#error "ChibiOS/SB not licensed"
+#endif
+
+#if (CH_LICENSE_FEATURES != CH_FEATURES_FULL) && \
+ (CH_LICENSE_FEATURES != CH_FEATURES_INTERMEDIATE) && \
+ (CH_LICENSE_FEATURES != CH_FEATURES_BASIC)
+#error "invalid CH_LICENSE_FEATURES setting"
+#endif
+
+#if CH_LICENSE_FEATURES != CH_FEATURES_FULL
+#error "ChibiOS/SB insufficient features level"
+#endif
+
+#if CH_CFG_ST_RESOLUTION != 32
+#error "SandBox requires CH_CFG_ST_RESOLUTION == 32"
+#endif
+
+#if CH_CFG_INTERVALS_SIZE != 32
+#error "SandBox requires CH_CFG_INTERVALS_SIZE == 32"
+#endif
+
+#if PORT_USE_SYSCALL == FALSE
+#error "SandBox requires PORT_USE_SYSCALL == TRUE"
+#endif
+
+#if (SB_NUM_REGIONS < 1) || (SB_NUM_REGIONS > 4)
+#error "invalid SB_NUM_REGIONS value"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#include "sberr.h"
+#include "sbhost.h"
+#include "sbapi.h"
+#include "sbposix.h"
+
+#endif /* SBHOST_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/sb/host/sbapi.c b/ChibiOS_20.3.2/os/sb/host/sbapi.c
new file mode 100644
index 0000000..b52d16b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/sb/host/sbapi.c
@@ -0,0 +1,1067 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file sb/host/sbhost.c
+ * @brief ARM sandbox host API code.
+ *
+ * @addtogroup ARM_SANDBOX_HOSTAPI
+ * @{
+ */
+
+#include "ch.h"
+#include "sb.h"
+
+#if defined(SB_INCLUDE_USERAPI)
+#include "sbuserapi.h"
+#endif
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/**
+ * @name Standard API handlers
+ * @{
+ */
+#define SB_SVC0_HANDLER sb_api_stdio
+#define SB_SVC1_HANDLER sb_api_exit
+#define SB_SVC2_HANDLER sb_api_get_systime
+#define SB_SVC3_HANDLER sb_api_get_frequency
+#define SB_SVC4_HANDLER sb_api_sleep
+#define SB_SVC5_HANDLER sb_api_sleep_until_windowed
+#define SB_SVC6_HANDLER sb_api_wait_message
+#define SB_SVC7_HANDLER sb_api_reply_message
+#define SB_SVC8_HANDLER sb_api_wait_one_timeout
+#define SB_SVC9_HANDLER sb_api_wait_any_timeout
+#define SB_SVC10_HANDLER sb_api_wait_all_timeout
+#define SB_SVC11_HANDLER sb_api_broadcast_flags
+/** @} */
+
+#define __SVC(x) asm volatile ("svc " #x)
+
+/*
+ * All handlers defaulted to a common function.
+ */
+#if !defined(SB_SVC0_HANDLER)
+#define SB_SVC0_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC1_HANDLER)
+#define SB_SVC1_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC2_HANDLER)
+#define SB_SVC2_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC3_HANDLER)
+#define SB_SVC3_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC4_HANDLER)
+#define SB_SVC4_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC5_HANDLER)
+#define SB_SVC5_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC6_HANDLER)
+#define SB_SVC6_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC7_HANDLER)
+#define SB_SVC7_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC8_HANDLER)
+#define SB_SVC8_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC9_HANDLER)
+#define SB_SVC9_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC10_HANDLER)
+#define SB_SVC10_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC11_HANDLER)
+#define SB_SVC11_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC12_HANDLER)
+#define SB_SVC12_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC13_HANDLER)
+#define SB_SVC13_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC14_HANDLER)
+#define SB_SVC14_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC15_HANDLER)
+#define SB_SVC15_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC16_HANDLER)
+#define SB_SVC16_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC17_HANDLER)
+#define SB_SVC17_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC18_HANDLER)
+#define SB_SVC18_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC19_HANDLER)
+#define SB_SVC19_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC20_HANDLER)
+#define SB_SVC20_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC21_HANDLER)
+#define SB_SVC21_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC22_HANDLER)
+#define SB_SVC22_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC23_HANDLER)
+#define SB_SVC23_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC24_HANDLER)
+#define SB_SVC24_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC25_HANDLER)
+#define SB_SVC25_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC26_HANDLER)
+#define SB_SVC26_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC27_HANDLER)
+#define SB_SVC27_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC28_HANDLER)
+#define SB_SVC28_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC29_HANDLER)
+#define SB_SVC29_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC30_HANDLER)
+#define SB_SVC30_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC31_HANDLER)
+#define SB_SVC31_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC32_HANDLER)
+#define SB_SVC32_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC33_HANDLER)
+#define SB_SVC33_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC34_HANDLER)
+#define SB_SVC34_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC35_HANDLER)
+#define SB_SVC35_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC36_HANDLER)
+#define SB_SVC36_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC37_HANDLER)
+#define SB_SVC37_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC38_HANDLER)
+#define SB_SVC38_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC39_HANDLER)
+#define SB_SVC39_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC40_HANDLER)
+#define SB_SVC40_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC41_HANDLER)
+#define SB_SVC41_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC42_HANDLER)
+#define SB_SVC42_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC43_HANDLER)
+#define SB_SVC43_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC44_HANDLER)
+#define SB_SVC44_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC45_HANDLER)
+#define SB_SVC45_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC46_HANDLER)
+#define SB_SVC46_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC47_HANDLER)
+#define SB_SVC47_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC48_HANDLER)
+#define SB_SVC48_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC49_HANDLER)
+#define SB_SVC49_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC50_HANDLER)
+#define SB_SVC50_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC51_HANDLER)
+#define SB_SVC51_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC52_HANDLER)
+#define SB_SVC52_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC53_HANDLER)
+#define SB_SVC53_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC54_HANDLER)
+#define SB_SVC54_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC55_HANDLER)
+#define SB_SVC55_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC56_HANDLER)
+#define SB_SVC56_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC57_HANDLER)
+#define SB_SVC57_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC58_HANDLER)
+#define SB_SVC58_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC59_HANDLER)
+#define SB_SVC59_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC60_HANDLER)
+#define SB_SVC60_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC61_HANDLER)
+#define SB_SVC61_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC62_HANDLER)
+#define SB_SVC62_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC63_HANDLER)
+#define SB_SVC63_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC64_HANDLER)
+#define SB_SVC64_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC65_HANDLER)
+#define SB_SVC65_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC66_HANDLER)
+#define SB_SVC66_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC67_HANDLER)
+#define SB_SVC67_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC68_HANDLER)
+#define SB_SVC68_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC69_HANDLER)
+#define SB_SVC69_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC70_HANDLER)
+#define SB_SVC70_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC71_HANDLER)
+#define SB_SVC71_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC72_HANDLER)
+#define SB_SVC72_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC73_HANDLER)
+#define SB_SVC73_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC74_HANDLER)
+#define SB_SVC74_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC75_HANDLER)
+#define SB_SVC75_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC76_HANDLER)
+#define SB_SVC76_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC77_HANDLER)
+#define SB_SVC77_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC78_HANDLER)
+#define SB_SVC78_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC79_HANDLER)
+#define SB_SVC79_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC80_HANDLER)
+#define SB_SVC80_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC81_HANDLER)
+#define SB_SVC81_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC82_HANDLER)
+#define SB_SVC82_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC83_HANDLER)
+#define SB_SVC83_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC84_HANDLER)
+#define SB_SVC84_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC85_HANDLER)
+#define SB_SVC85_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC86_HANDLER)
+#define SB_SVC86_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC87_HANDLER)
+#define SB_SVC87_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC88_HANDLER)
+#define SB_SVC88_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC89_HANDLER)
+#define SB_SVC89_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC90_HANDLER)
+#define SB_SVC90_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC91_HANDLER)
+#define SB_SVC91_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC92_HANDLER)
+#define SB_SVC92_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC93_HANDLER)
+#define SB_SVC93_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC94_HANDLER)
+#define SB_SVC94_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC95_HANDLER)
+#define SB_SVC95_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC96_HANDLER)
+#define SB_SVC96_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC97_HANDLER)
+#define SB_SVC97_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC98_HANDLER)
+#define SB_SVC98_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC99_HANDLER)
+#define SB_SVC99_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC100_HANDLER)
+#define SB_SVC100_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC101_HANDLER)
+#define SB_SVC101_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC102_HANDLER)
+#define SB_SVC102_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC103_HANDLER)
+#define SB_SVC103_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC104_HANDLER)
+#define SB_SVC104_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC105_HANDLER)
+#define SB_SVC105_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC106_HANDLER)
+#define SB_SVC106_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC107_HANDLER)
+#define SB_SVC107_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC108_HANDLER)
+#define SB_SVC108_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC109_HANDLER)
+#define SB_SVC109_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC110_HANDLER)
+#define SB_SVC110_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC111_HANDLER)
+#define SB_SVC111_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC112_HANDLER)
+#define SB_SVC112_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC113_HANDLER)
+#define SB_SVC113_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC114_HANDLER)
+#define SB_SVC114_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC115_HANDLER)
+#define SB_SVC115_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC116_HANDLER)
+#define SB_SVC116_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC117_HANDLER)
+#define SB_SVC117_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC118_HANDLER)
+#define SB_SVC118_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC119_HANDLER)
+#define SB_SVC119_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC120_HANDLER)
+#define SB_SVC120_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC121_HANDLER)
+#define SB_SVC121_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC122_HANDLER)
+#define SB_SVC122_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC123_HANDLER)
+#define SB_SVC123_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC124_HANDLER)
+#define SB_SVC124_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC125_HANDLER)
+#define SB_SVC125_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC126_HANDLER)
+#define SB_SVC126_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC127_HANDLER)
+#define SB_SVC127_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC128_HANDLER)
+#define SB_SVC128_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC129_HANDLER)
+#define SB_SVC129_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC130_HANDLER)
+#define SB_SVC130_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC131_HANDLER)
+#define SB_SVC131_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC132_HANDLER)
+#define SB_SVC132_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC133_HANDLER)
+#define SB_SVC133_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC134_HANDLER)
+#define SB_SVC134_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC135_HANDLER)
+#define SB_SVC135_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC136_HANDLER)
+#define SB_SVC136_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC137_HANDLER)
+#define SB_SVC137_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC138_HANDLER)
+#define SB_SVC138_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC139_HANDLER)
+#define SB_SVC139_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC140_HANDLER)
+#define SB_SVC140_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC141_HANDLER)
+#define SB_SVC141_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC142_HANDLER)
+#define SB_SVC142_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC143_HANDLER)
+#define SB_SVC143_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC144_HANDLER)
+#define SB_SVC144_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC145_HANDLER)
+#define SB_SVC145_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC146_HANDLER)
+#define SB_SVC146_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC147_HANDLER)
+#define SB_SVC147_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC148_HANDLER)
+#define SB_SVC148_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC149_HANDLER)
+#define SB_SVC149_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC150_HANDLER)
+#define SB_SVC150_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC151_HANDLER)
+#define SB_SVC151_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC152_HANDLER)
+#define SB_SVC152_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC153_HANDLER)
+#define SB_SVC153_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC154_HANDLER)
+#define SB_SVC154_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC155_HANDLER)
+#define SB_SVC155_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC156_HANDLER)
+#define SB_SVC156_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC157_HANDLER)
+#define SB_SVC157_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC158_HANDLER)
+#define SB_SVC158_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC159_HANDLER)
+#define SB_SVC159_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC160_HANDLER)
+#define SB_SVC160_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC161_HANDLER)
+#define SB_SVC161_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC162_HANDLER)
+#define SB_SVC162_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC163_HANDLER)
+#define SB_SVC163_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC164_HANDLER)
+#define SB_SVC164_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC165_HANDLER)
+#define SB_SVC165_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC166_HANDLER)
+#define SB_SVC166_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC167_HANDLER)
+#define SB_SVC167_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC168_HANDLER)
+#define SB_SVC168_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC169_HANDLER)
+#define SB_SVC169_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC170_HANDLER)
+#define SB_SVC170_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC171_HANDLER)
+#define SB_SVC171_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC172_HANDLER)
+#define SB_SVC172_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC173_HANDLER)
+#define SB_SVC173_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC174_HANDLER)
+#define SB_SVC174_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC175_HANDLER)
+#define SB_SVC175_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC176_HANDLER)
+#define SB_SVC176_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC177_HANDLER)
+#define SB_SVC177_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC178_HANDLER)
+#define SB_SVC178_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC179_HANDLER)
+#define SB_SVC179_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC180_HANDLER)
+#define SB_SVC180_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC181_HANDLER)
+#define SB_SVC181_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC182_HANDLER)
+#define SB_SVC182_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC183_HANDLER)
+#define SB_SVC183_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC184_HANDLER)
+#define SB_SVC184_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC185_HANDLER)
+#define SB_SVC185_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC186_HANDLER)
+#define SB_SVC186_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC187_HANDLER)
+#define SB_SVC187_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC188_HANDLER)
+#define SB_SVC188_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC189_HANDLER)
+#define SB_SVC189_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC190_HANDLER)
+#define SB_SVC190_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC191_HANDLER)
+#define SB_SVC191_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC192_HANDLER)
+#define SB_SVC192_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC193_HANDLER)
+#define SB_SVC193_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC194_HANDLER)
+#define SB_SVC194_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC195_HANDLER)
+#define SB_SVC195_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC196_HANDLER)
+#define SB_SVC196_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC197_HANDLER)
+#define SB_SVC197_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC198_HANDLER)
+#define SB_SVC198_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC199_HANDLER)
+#define SB_SVC199_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC200_HANDLER)
+#define SB_SVC200_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC201_HANDLER)
+#define SB_SVC201_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC202_HANDLER)
+#define SB_SVC202_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC203_HANDLER)
+#define SB_SVC203_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC204_HANDLER)
+#define SB_SVC204_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC205_HANDLER)
+#define SB_SVC205_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC206_HANDLER)
+#define SB_SVC206_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC207_HANDLER)
+#define SB_SVC207_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC208_HANDLER)
+#define SB_SVC208_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC209_HANDLER)
+#define SB_SVC209_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC210_HANDLER)
+#define SB_SVC210_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC211_HANDLER)
+#define SB_SVC211_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC212_HANDLER)
+#define SB_SVC212_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC213_HANDLER)
+#define SB_SVC213_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC214_HANDLER)
+#define SB_SVC214_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC215_HANDLER)
+#define SB_SVC215_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC216_HANDLER)
+#define SB_SVC216_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC217_HANDLER)
+#define SB_SVC217_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC218_HANDLER)
+#define SB_SVC218_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC219_HANDLER)
+#define SB_SVC219_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC220_HANDLER)
+#define SB_SVC220_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC221_HANDLER)
+#define SB_SVC221_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC222_HANDLER)
+#define SB_SVC222_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC223_HANDLER)
+#define SB_SVC223_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC224_HANDLER)
+#define SB_SVC224_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC225_HANDLER)
+#define SB_SVC225_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC226_HANDLER)
+#define SB_SVC226_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC227_HANDLER)
+#define SB_SVC227_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC228_HANDLER)
+#define SB_SVC228_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC229_HANDLER)
+#define SB_SVC229_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC230_HANDLER)
+#define SB_SVC230_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC231_HANDLER)
+#define SB_SVC231_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC232_HANDLER)
+#define SB_SVC232_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC233_HANDLER)
+#define SB_SVC233_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC234_HANDLER)
+#define SB_SVC234_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC235_HANDLER)
+#define SB_SVC235_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC236_HANDLER)
+#define SB_SVC236_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC237_HANDLER)
+#define SB_SVC237_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC238_HANDLER)
+#define SB_SVC238_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC239_HANDLER)
+#define SB_SVC239_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC240_HANDLER)
+#define SB_SVC240_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC241_HANDLER)
+#define SB_SVC241_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC242_HANDLER)
+#define SB_SVC242_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC243_HANDLER)
+#define SB_SVC243_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC244_HANDLER)
+#define SB_SVC244_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC245_HANDLER)
+#define SB_SVC245_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC246_HANDLER)
+#define SB_SVC246_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC247_HANDLER)
+#define SB_SVC247_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC248_HANDLER)
+#define SB_SVC248_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC249_HANDLER)
+#define SB_SVC249_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC250_HANDLER)
+#define SB_SVC250_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC251_HANDLER)
+#define SB_SVC251_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC252_HANDLER)
+#define SB_SVC252_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC253_HANDLER)
+#define SB_SVC253_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC254_HANDLER)
+#define SB_SVC254_HANDLER sb_undef_handler
+#endif
+#if !defined(SB_SVC255_HANDLER)
+#define SB_SVC255_HANDLER sb_undef_handler
+#endif
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+static void sb_undef_handler(struct port_extctx *ectxp);
+
+const port_syscall_t sb_syscalls[256] = {
+ SB_SVC0_HANDLER, SB_SVC1_HANDLER, SB_SVC2_HANDLER, SB_SVC3_HANDLER,
+ SB_SVC4_HANDLER, SB_SVC5_HANDLER, SB_SVC6_HANDLER, SB_SVC7_HANDLER,
+ SB_SVC8_HANDLER, SB_SVC9_HANDLER, SB_SVC10_HANDLER, SB_SVC11_HANDLER,
+ SB_SVC12_HANDLER, SB_SVC13_HANDLER, SB_SVC14_HANDLER, SB_SVC15_HANDLER,
+ SB_SVC16_HANDLER, SB_SVC17_HANDLER, SB_SVC18_HANDLER, SB_SVC19_HANDLER,
+ SB_SVC20_HANDLER, SB_SVC21_HANDLER, SB_SVC22_HANDLER, SB_SVC23_HANDLER,
+ SB_SVC24_HANDLER, SB_SVC25_HANDLER, SB_SVC26_HANDLER, SB_SVC27_HANDLER,
+ SB_SVC28_HANDLER, SB_SVC29_HANDLER, SB_SVC30_HANDLER, SB_SVC31_HANDLER,
+ SB_SVC32_HANDLER, SB_SVC33_HANDLER, SB_SVC34_HANDLER, SB_SVC35_HANDLER,
+ SB_SVC36_HANDLER, SB_SVC37_HANDLER, SB_SVC38_HANDLER, SB_SVC39_HANDLER,
+ SB_SVC40_HANDLER, SB_SVC41_HANDLER, SB_SVC42_HANDLER, SB_SVC43_HANDLER,
+ SB_SVC44_HANDLER, SB_SVC45_HANDLER, SB_SVC46_HANDLER, SB_SVC47_HANDLER,
+ SB_SVC48_HANDLER, SB_SVC49_HANDLER, SB_SVC50_HANDLER, SB_SVC51_HANDLER,
+ SB_SVC52_HANDLER, SB_SVC53_HANDLER, SB_SVC54_HANDLER, SB_SVC55_HANDLER,
+ SB_SVC56_HANDLER, SB_SVC57_HANDLER, SB_SVC58_HANDLER, SB_SVC59_HANDLER,
+ SB_SVC60_HANDLER, SB_SVC61_HANDLER, SB_SVC62_HANDLER, SB_SVC63_HANDLER,
+ SB_SVC64_HANDLER, SB_SVC65_HANDLER, SB_SVC66_HANDLER, SB_SVC67_HANDLER,
+ SB_SVC68_HANDLER, SB_SVC69_HANDLER, SB_SVC70_HANDLER, SB_SVC71_HANDLER,
+ SB_SVC72_HANDLER, SB_SVC73_HANDLER, SB_SVC74_HANDLER, SB_SVC75_HANDLER,
+ SB_SVC76_HANDLER, SB_SVC77_HANDLER, SB_SVC78_HANDLER, SB_SVC79_HANDLER,
+ SB_SVC80_HANDLER, SB_SVC81_HANDLER, SB_SVC82_HANDLER, SB_SVC83_HANDLER,
+ SB_SVC84_HANDLER, SB_SVC85_HANDLER, SB_SVC86_HANDLER, SB_SVC87_HANDLER,
+ SB_SVC88_HANDLER, SB_SVC89_HANDLER, SB_SVC90_HANDLER, SB_SVC91_HANDLER,
+ SB_SVC92_HANDLER, SB_SVC93_HANDLER, SB_SVC94_HANDLER, SB_SVC95_HANDLER,
+ SB_SVC96_HANDLER, SB_SVC97_HANDLER, SB_SVC98_HANDLER, SB_SVC99_HANDLER,
+ SB_SVC100_HANDLER, SB_SVC101_HANDLER, SB_SVC102_HANDLER, SB_SVC103_HANDLER,
+ SB_SVC104_HANDLER, SB_SVC105_HANDLER, SB_SVC106_HANDLER, SB_SVC107_HANDLER,
+ SB_SVC108_HANDLER, SB_SVC109_HANDLER, SB_SVC110_HANDLER, SB_SVC111_HANDLER,
+ SB_SVC112_HANDLER, SB_SVC113_HANDLER, SB_SVC114_HANDLER, SB_SVC115_HANDLER,
+ SB_SVC116_HANDLER, SB_SVC117_HANDLER, SB_SVC118_HANDLER, SB_SVC119_HANDLER,
+ SB_SVC120_HANDLER, SB_SVC121_HANDLER, SB_SVC122_HANDLER, SB_SVC123_HANDLER,
+ SB_SVC124_HANDLER, SB_SVC125_HANDLER, SB_SVC126_HANDLER, SB_SVC127_HANDLER,
+ SB_SVC128_HANDLER, SB_SVC129_HANDLER, SB_SVC130_HANDLER, SB_SVC131_HANDLER,
+ SB_SVC132_HANDLER, SB_SVC133_HANDLER, SB_SVC134_HANDLER, SB_SVC135_HANDLER,
+ SB_SVC136_HANDLER, SB_SVC137_HANDLER, SB_SVC138_HANDLER, SB_SVC139_HANDLER,
+ SB_SVC140_HANDLER, SB_SVC141_HANDLER, SB_SVC142_HANDLER, SB_SVC143_HANDLER,
+ SB_SVC144_HANDLER, SB_SVC145_HANDLER, SB_SVC146_HANDLER, SB_SVC147_HANDLER,
+ SB_SVC148_HANDLER, SB_SVC149_HANDLER, SB_SVC150_HANDLER, SB_SVC151_HANDLER,
+ SB_SVC152_HANDLER, SB_SVC153_HANDLER, SB_SVC154_HANDLER, SB_SVC155_HANDLER,
+ SB_SVC156_HANDLER, SB_SVC157_HANDLER, SB_SVC158_HANDLER, SB_SVC159_HANDLER,
+ SB_SVC160_HANDLER, SB_SVC161_HANDLER, SB_SVC162_HANDLER, SB_SVC163_HANDLER,
+ SB_SVC164_HANDLER, SB_SVC165_HANDLER, SB_SVC166_HANDLER, SB_SVC167_HANDLER,
+ SB_SVC168_HANDLER, SB_SVC169_HANDLER, SB_SVC170_HANDLER, SB_SVC171_HANDLER,
+ SB_SVC172_HANDLER, SB_SVC173_HANDLER, SB_SVC174_HANDLER, SB_SVC175_HANDLER,
+ SB_SVC176_HANDLER, SB_SVC177_HANDLER, SB_SVC178_HANDLER, SB_SVC179_HANDLER,
+ SB_SVC180_HANDLER, SB_SVC181_HANDLER, SB_SVC182_HANDLER, SB_SVC183_HANDLER,
+ SB_SVC184_HANDLER, SB_SVC185_HANDLER, SB_SVC186_HANDLER, SB_SVC187_HANDLER,
+ SB_SVC188_HANDLER, SB_SVC189_HANDLER, SB_SVC190_HANDLER, SB_SVC191_HANDLER,
+ SB_SVC192_HANDLER, SB_SVC193_HANDLER, SB_SVC194_HANDLER, SB_SVC195_HANDLER,
+ SB_SVC196_HANDLER, SB_SVC197_HANDLER, SB_SVC198_HANDLER, SB_SVC199_HANDLER,
+ SB_SVC200_HANDLER, SB_SVC201_HANDLER, SB_SVC202_HANDLER, SB_SVC203_HANDLER,
+ SB_SVC204_HANDLER, SB_SVC205_HANDLER, SB_SVC206_HANDLER, SB_SVC207_HANDLER,
+ SB_SVC208_HANDLER, SB_SVC209_HANDLER, SB_SVC210_HANDLER, SB_SVC211_HANDLER,
+ SB_SVC212_HANDLER, SB_SVC213_HANDLER, SB_SVC214_HANDLER, SB_SVC215_HANDLER,
+ SB_SVC216_HANDLER, SB_SVC217_HANDLER, SB_SVC218_HANDLER, SB_SVC219_HANDLER,
+ SB_SVC220_HANDLER, SB_SVC221_HANDLER, SB_SVC222_HANDLER, SB_SVC223_HANDLER,
+ SB_SVC224_HANDLER, SB_SVC225_HANDLER, SB_SVC226_HANDLER, SB_SVC227_HANDLER,
+ SB_SVC228_HANDLER, SB_SVC229_HANDLER, SB_SVC230_HANDLER, SB_SVC231_HANDLER,
+ SB_SVC232_HANDLER, SB_SVC233_HANDLER, SB_SVC234_HANDLER, SB_SVC235_HANDLER,
+ SB_SVC236_HANDLER, SB_SVC237_HANDLER, SB_SVC238_HANDLER, SB_SVC239_HANDLER,
+ SB_SVC240_HANDLER, SB_SVC241_HANDLER, SB_SVC242_HANDLER, SB_SVC243_HANDLER,
+ SB_SVC244_HANDLER, SB_SVC245_HANDLER, SB_SVC246_HANDLER, SB_SVC247_HANDLER,
+ SB_SVC248_HANDLER, SB_SVC249_HANDLER, SB_SVC250_HANDLER, SB_SVC251_HANDLER,
+ SB_SVC252_HANDLER, SB_SVC253_HANDLER, SB_SVC254_HANDLER, SB_SVC255_HANDLER
+};
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+static void sb_undef_handler(struct port_extctx *ectxp) {
+
+ ectxp->r0 = SB_ERR_ENOSYS;
+}
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+void sb_api_stdio(struct port_extctx *ectxp) {
+
+ switch (ectxp->r0) {
+ case SB_POSIX_OPEN:
+ ectxp->r0 = sb_posix_open((const char *)ectxp->r1,
+ ectxp->r2);
+ break;
+ case SB_POSIX_CLOSE:
+ ectxp->r0 = sb_posix_close(ectxp->r1);
+ break;
+ case SB_POSIX_READ:
+ ectxp->r0 = sb_posix_read(ectxp->r1,
+ (void *)ectxp->r2,
+ (size_t)ectxp->r3);
+ break;
+ case SB_POSIX_WRITE:
+ ectxp->r0 = sb_posix_write(ectxp->r1,
+ (const void *)ectxp->r2,
+ (size_t)ectxp->r3);
+ break;
+ case SB_POSIX_LSEEK:
+ ectxp->r0 = sb_posix_lseek(ectxp->r1,
+ ectxp->r2,
+ ectxp->r3);
+ break;
+ default:
+ ectxp->r0 = SB_ERR_ENOSYS;
+ break;
+ }
+}
+
+void sb_api_exit(struct port_extctx *ectxp) {
+
+ chThdExit((msg_t )ectxp->r0);
+
+ /* Cannot get here.*/
+ ectxp->r0 = SB_ERR_ENOSYS;
+}
+
+void sb_api_get_systime(struct port_extctx *ectxp) {
+
+ ectxp->r0 = (uint32_t)chVTGetSystemTimeX();
+}
+
+void sb_api_get_frequency(struct port_extctx *ectxp) {
+
+ ectxp->r0 = (uint32_t)CH_CFG_ST_FREQUENCY;
+}
+
+void sb_api_sleep(struct port_extctx *ectxp) {
+ sysinterval_t interval = (sysinterval_t )ectxp->r0;
+
+ if (interval != TIME_IMMEDIATE) {
+ chThdSleep(interval);
+ }
+
+ ectxp->r0 = SB_ERR_NOERROR;
+}
+
+void sb_api_sleep_until_windowed(struct port_extctx *ectxp) {
+
+ chThdSleepUntilWindowed((systime_t )ectxp->r0, (systime_t )ectxp->r1);
+
+ ectxp->r0 = SB_ERR_NOERROR;
+}
+
+void sb_api_wait_message(struct port_extctx *ectxp) {
+#if CH_CFG_USE_MESSAGES == TRUE
+ sb_class_t *sbcp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
+
+ if (sbcp->msg_tp == NULL) {
+ sbcp->msg_tp = chMsgWait();
+ ectxp->r0 = (uint32_t)chMsgGet(sbcp->msg_tp);
+ }
+ else {
+ chMsgRelease(sbcp->msg_tp, MSG_RESET);
+ sbcp->msg_tp = NULL;
+ ectxp->r0 = SB_ERR_EBUSY;
+ }
+#else
+ ectxp->r0 = SB_ERR_NOT_IMPLEMENTED;
+#endif
+}
+
+void sb_api_reply_message(struct port_extctx *ectxp) {
+#if CH_CFG_USE_MESSAGES == TRUE
+ sb_class_t *sbcp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
+
+ if (sbcp->msg_tp != NULL) {
+ chMsgRelease(sbcp->msg_tp, (msg_t )ectxp->r0);
+ sbcp->msg_tp = NULL;
+ ectxp->r0 = SB_ERR_NOERROR;
+ }
+ else {
+ ectxp->r0 = SB_ERR_EBUSY;
+ }
+#else
+ ectxp->r0 = SB_ERR_NOT_IMPLEMENTED;
+#endif
+}
+
+void sb_api_wait_one_timeout(struct port_extctx *ectxp) {
+#if CH_CFG_USE_EVENTS == TRUE
+
+ ectxp->r0 = (uint32_t)chEvtWaitOneTimeout((eventmask_t )ectxp->r0,
+ (sysinterval_t )ectxp->r1);
+#else
+ ectxp->r0 = SB_ERR_NOT_IMPLEMENTED;
+#endif
+}
+
+void sb_api_wait_any_timeout(struct port_extctx *ectxp) {
+#if CH_CFG_USE_EVENTS == TRUE
+
+ ectxp->r0 = (uint32_t)chEvtWaitAnyTimeout((eventmask_t )ectxp->r0,
+ (sysinterval_t )ectxp->r1);
+#else
+ ectxp->r0 = SB_ERR_NOT_IMPLEMENTED;
+#endif
+}
+
+void sb_api_wait_all_timeout(struct port_extctx *ectxp) {
+#if CH_CFG_USE_EVENTS == TRUE
+
+ ectxp->r0 = (uint32_t)chEvtWaitAllTimeout((eventmask_t )ectxp->r0,
+ (sysinterval_t )ectxp->r1);
+#else
+ ectxp->r0 = SB_ERR_NOT_IMPLEMENTED;
+#endif
+}
+
+void sb_api_broadcast_flags(struct port_extctx *ectxp) {
+#if CH_CFG_USE_EVENTS == TRUE
+ sb_class_t *sbcp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
+
+ chEvtBroadcastFlags(&sbcp->es, (eventflags_t )ectxp->r0);
+ ectxp->r0 = SB_ERR_NOERROR;
+#else
+ ectxp->r0 = SB_ERR_NOT_IMPLEMENTED;
+#endif
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/sb/host/sbapi.h b/ChibiOS_20.3.2/os/sb/host/sbapi.h
new file mode 100644
index 0000000..e2a08d7
--- /dev/null
+++ b/ChibiOS_20.3.2/os/sb/host/sbapi.h
@@ -0,0 +1,127 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file sb/host/sbapi.h
+ * @brief ARM sandbox host API macros and structures.
+ *
+ * @addtogroup ARM_SANDBOX_HOSTAPI
+ * @{
+ */
+
+#ifndef SBAPI_H
+#define SBAPI_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a syscall handler.
+ */
+typedef void (*port_syscall_t)(struct port_extctx *ectx);
+
+/**
+ * @brief Sandbox Stream interface methods.
+ * @note Is intentionally compatible with HAL streams but we have to
+ * duplicate is because we don't want dependencies with HAL in
+ * this subsystem.
+ */
+struct SandboxStreamVMT {
+ /**
+ * @brief Object instance offset.
+ */
+ size_t instance_offset;
+ /**
+ * @brief Stream write buffer method.
+ */
+ size_t (*write)(void *instance, const uint8_t *bp, size_t n);
+ /**
+ * @brief Stream read buffer method.
+ */
+ size_t (*read)(void *instance, uint8_t *bp, size_t n);
+ /**
+ * @brief Channel put method, blocking.
+ */
+ msg_t (*put)(void *instance, uint8_t b);
+ /**
+ * @brief Channel get method, blocking.
+ */
+ msg_t (*get)(void *instance);
+};
+
+/**
+ * @brief Sandbox Stream class.
+ * @note Is intentionally compatible with HAL streams but we have to
+ * duplicate is because we don't want dependencies with HAL in
+ * this subsystem.
+ */
+typedef struct {
+ /**
+ * @brief Virtual Methods Table.
+ */
+ const struct SandboxStreamVMT *vmt;
+} SandboxStream;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void sb_api_stdio(struct port_extctx *ectxp);
+ void sb_api_exit(struct port_extctx *ctxp);
+ void sb_api_get_systime(struct port_extctx *ctxp);
+ void sb_api_get_frequency(struct port_extctx *ctxp);
+ void sb_api_sleep(struct port_extctx *ctxp);
+ void sb_api_sleep_until_windowed(struct port_extctx *ctxp);
+ void sb_api_wait_message(struct port_extctx *ctxp);
+ void sb_api_reply_message(struct port_extctx *ctxp);
+ void sb_api_wait_one_timeout(struct port_extctx *ctxp);
+ void sb_api_wait_any_timeout(struct port_extctx *ctxp);
+ void sb_api_wait_all_timeout(struct port_extctx *ctxp);
+ void sb_api_broadcast_flags(struct port_extctx *ctxp);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* SBAPI_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/sb/host/sbhost.c b/ChibiOS_20.3.2/os/sb/host/sbhost.c
new file mode 100644
index 0000000..177a144
--- /dev/null
+++ b/ChibiOS_20.3.2/os/sb/host/sbhost.c
@@ -0,0 +1,146 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file sb/host/sbhost.c
+ * @brief ARM sandbox host code.
+ *
+ * @addtogroup ARM_SANDBOX
+ * @{
+ */
+
+#include "ch.h"
+#include "sb.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+bool sb_is_valid_read_range(sb_class_t *sbcp, const void *start, size_t size) {
+ const sb_memory_region_t *rp = &sbcp->config->regions[0];
+
+ do {
+ if (((uint32_t)start >= rp->base) && ((uint32_t)start < rp->end) &&
+ (size <= ((size_t)rp->base - (size_t)start))) {
+ return true;
+ }
+ rp++;
+ } while (rp < &sbcp->config->regions[SB_NUM_REGIONS]);
+
+ return false;
+}
+
+bool sb_is_valid_write_range(sb_class_t *sbcp, void *start, size_t size) {
+ const sb_memory_region_t *rp = &sbcp->config->regions[0];
+
+ do {
+ if (((uint32_t)start >= rp->base) && ((uint32_t)start < rp->end) &&
+ (size <= ((size_t)rp->base - (size_t)start))) {
+ return rp->writeable;
+ }
+ rp++;
+ } while (rp < &sbcp->config->regions[SB_NUM_REGIONS]);
+
+ return false;
+}
+
+/**
+ * @brief Sandbox object initialization.
+ *
+ * @param[out] sbcp pointer to the sandbox object
+ *
+ * @init
+ */
+void sbObjectInit(sb_class_t *sbcp) {
+
+ sbcp->config = NULL;
+ sbcp->tp = NULL;
+#if CH_CFG_USE_MESSAGES == TRUE
+ sbcp->msg_tp = NULL;
+#endif
+#if CH_CFG_USE_EVENTS == TRUE
+ chEvtObjectInit(&sbcp->es);
+#endif
+}
+
+/**
+ * @brief Starts a sandboxed thread.
+ *
+ * @param[in] sbcp pointer to the sandbox object
+ * @return The function returns only if the operation failed.
+ *
+ * @api
+ */
+void sbStart(sb_class_t *sbcp, const sb_config_t *config) {
+ uint32_t pc, psp;
+ const sb_header_t *sbhp;
+
+ /* Header location.*/
+ sbhp = (const sb_header_t *)config->regions[config->code_region].base;
+
+ /* Checking header magic numbers.*/
+ if ((sbhp->hdr_magic1 != SB_MAGIC1) || (sbhp->hdr_magic2 != SB_MAGIC2)) {
+ return;
+ }
+
+ /* Checking header size and alignment.*/
+ if (sbhp->hdr_size != sizeof (sb_header_t)) {
+ return;
+ }
+
+ /* PC initial address, by convention it is immediately after the header.*/
+ pc = (config->regions[config->code_region].base + sizeof (sb_header_t)) | 1U;
+
+ /* PSP initial address.*/
+ psp = config->regions[config->data_region].end;
+
+ /* Additional context information.*/
+ sbcp->config = config;
+ sbcp->tp = chThdGetSelfX();
+ sbcp->tp->ctx.syscall.p = (const void *)sbcp;
+ sbcp->tp->ctx.syscall.psp = __get_PSP();
+
+ /* Jumping to the unprivileged code.*/
+ port_unprivileged_jump(pc, psp);
+
+ /* Must never happen condition.*/
+ chSysHalt("returned");
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/sb/host/sbhost.h b/ChibiOS_20.3.2/os/sb/host/sbhost.h
new file mode 100644
index 0000000..5207af1
--- /dev/null
+++ b/ChibiOS_20.3.2/os/sb/host/sbhost.h
@@ -0,0 +1,265 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file sb/host/sbhost.h
+ * @brief ARM sandbox host macros and structures.
+ *
+ * @addtogroup ARM_SANDBOX
+ * @{
+ */
+
+#ifndef SBHOST_H
+#define SBHOST_H
+
+#include "sberr.h"
+#include "sbapi.h"
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Magic numbers
+ * @{
+ */
+#define SB_MAGIC1 0xFE9154C0U
+#define SB_MAGIC2 0x0C4519EFU
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+typedef struct {
+ /**
+ * @brief Memory range base.
+ * @note Zero if not used.
+ */
+ uint32_t base;
+ /**
+ * @brief Memory range end (non inclusive).
+ * @note Zero if not used.
+ */
+ uint32_t end;
+ /**
+ * @brief Writable memory range.
+ */
+ bool writeable;
+} sb_memory_region_t;
+
+/**
+ * @brief Type of a sandbox configuration structure.
+ */
+typedef struct {
+ /**
+ * @brief Memory region for code.
+ * @note It is used to locate the startup header.
+ */
+ uint32_t code_region;
+ /**
+ * @brief Memory region for data and stack.
+ * @note It is used for initial PSP placement.
+ */
+ uint32_t data_region;
+ /**
+ * @brief SandBox regions.
+ * @note The following memory regions are used only for pointers
+ * validation, not for MPU setup.
+ */
+ sb_memory_region_t regions[SB_NUM_REGIONS];
+ /**
+ * @brief Sandbox STDIN stream.
+ * @note Set this to @p NULL if standard I/O is not needed.
+ * @note By design you can use HAL streams here, you need to use
+ * a cast however.
+ */
+ SandboxStream *stdin_stream;
+ /**
+ * @brief Sandbox STDOUT stream.
+ * @note Set this to @p NULL if standard I/O is not needed.
+ * @note By design you can use HAL streams here, you need to use
+ * a cast however.
+ */
+ SandboxStream *stdout_stream;
+ /**
+ * @brief Sandbox STDERR stream.
+ * @note Set this to @p NULL if standard I/O is not needed.
+ * @note By design you can use HAL streams here, you need to use
+ * a cast however.
+ */
+ SandboxStream *stderr_stream;
+} sb_config_t;
+
+/**
+ * @brief Type of a sandbox object.
+ */
+typedef struct {
+ /**
+ * @brief Pointer to the sandbox configuration data.
+ */
+ const sb_config_t *config;
+ /**
+ * @brief Thread running in the sandbox.
+ */
+ thread_t *tp;
+#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Thread sending a message to the sandbox.
+ */
+ thread_t *msg_tp;
+#endif
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+ event_source_t es;
+#endif
+} sb_class_t;
+
+/**
+ * @brief Type of a sandbox binary image header.
+ */
+typedef struct {
+ /**
+ * @brief Magic number 1.
+ */
+ uint32_t hdr_magic1;
+ /**
+ * @brief Magic number 2.
+ */
+ uint32_t hdr_magic2;
+ /**
+ * @brief Header size, inclusive of magic numbers.
+ */
+ uint32_t hdr_size;
+ /**
+ * @brief Used-defined parameters, defaulted to zero.
+ */
+ uint32_t user;
+} sb_header_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void port_syscall(struct port_extctx *ctxp, uint32_t n);
+ bool sb_is_valid_read_range(sb_class_t *sbcp, const void *start, size_t size);
+ bool sb_is_valid_write_range(sb_class_t *sbcp, void *start, size_t size);
+ void sbObjectInit(sb_class_t *sbcp);
+ void sbStart(sb_class_t *sbcp, const sb_config_t *config);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#if (CH_CFG_USE_WAITEXIT == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Blocks the execution of the invoking thread until the sandbox
+ * thread terminates then the exit code is returned.
+ * @pre The configuration option @p CH_CFG_USE_WAITEXIT must be enabled in
+ * order to use this function.
+ *
+ * @param[in] sbcp pointer to the sandbox object
+ * @return The exit code from the terminated thread.
+ *
+ * @api
+ */
+static inline msg_t sbWait(sb_class_t *sbcp) {
+
+ return chThdWait(sbcp->tp);
+}
+#endif /* CH_CFG_USE_WAITEXIT == TRUE */
+
+#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Sends a message to a sandboxed thread.
+ *
+ * @param[in] sbcp pointer to the sandbox object
+ * @param[in] msg message to be sent
+ * @return The returned message.
+ * @retval MSG_RESET Sandboxed thread API usage error, exchange aborted.
+ *
+ * @api
+ */
+static inline msg_t sbSendMessage(sb_class_t *sbcp, msg_t msg) {
+
+ return chMsgSend(sbcp->tp, msg);
+}
+#endif /* CH_CFG_USE_MESSAGES == TRUE */
+
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Adds a set of event flags directly to the specified sandbox.
+ *
+ * @param[in] sbcp pointer to the sandbox object
+ * @param[in] events the events set to be ORed
+ *
+ * @iclass
+ */
+static inline void sbEvtSignalI(sb_class_t *sbcp, eventmask_t events) {
+
+ chEvtSignalI(sbcp->tp, events);
+}
+
+/**
+ * @brief Adds a set of event flags directly to the specified sandbox.
+ *
+ * @param[in] sbcp pointer to the sandbox object
+ * @param[in] events the events set to be ORed
+ *
+ * @api
+ */
+static inline void sbEvtSignal(sb_class_t *sbcp, eventmask_t events) {
+
+ chEvtSignal(sbcp->tp, events);
+}
+
+/**
+ * @brief Returns the sandbox event source object.
+ *
+ * @param[in] sbcp pointer to the sandbox object
+ * @return The pointer to the event source object.
+ *
+ * @xclass
+ */
+static inline event_source_t *sbGetEventSourceX(sb_class_t *sbcp) {
+
+ return &sbcp->es;
+}
+#endif /* CH_CFG_USE_EVENTS == TRUE */
+
+#endif /* SBHOST_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/sb/host/sbposix.c b/ChibiOS_20.3.2/os/sb/host/sbposix.c
new file mode 100644
index 0000000..b2f6839
--- /dev/null
+++ b/ChibiOS_20.3.2/os/sb/host/sbposix.c
@@ -0,0 +1,136 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file sb/host/sbposix.c
+ * @brief ARM sandbox host Posix API code.
+ *
+ * @addtogroup ARM_SANDBOX_HOSTAPI
+ * @{
+ */
+
+#include "ch.h"
+#include "sb.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+uint32_t sb_posix_open(const char *pathname, uint32_t flags) {
+
+ (void)pathname;
+ (void)flags;
+
+ return SB_ERR_ENOENT;
+}
+
+uint32_t sb_posix_close(uint32_t fd) {
+
+ if ((fd == 0U) || (fd == 1U) || (fd == 2U)) {
+
+ return SB_ERR_NOERROR;
+ }
+
+ return SB_ERR_EBADFD;
+}
+
+uint32_t sb_posix_read(uint32_t fd, uint8_t *buf, size_t count) {
+ sb_class_t *sbcp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
+
+ if (!sb_is_valid_write_range(sbcp, (void *)buf, count)) {
+ return SB_ERR_EFAULT;
+ }
+
+ if (fd == 0U) {
+ SandboxStream *ssp = sbcp->config->stdin_stream;
+
+ if ((count == 0U) || (ssp == NULL)) {
+ return 0U;
+ }
+
+ return (uint32_t)ssp->vmt->read((void *)ssp, buf, count);
+ }
+
+ return SB_ERR_EBADFD;
+}
+
+uint32_t sb_posix_write(uint32_t fd, const uint8_t *buf, size_t count) {
+ sb_class_t *sbcp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p;
+
+ if (!sb_is_valid_read_range(sbcp, (const void *)buf, count)) {
+ return SB_ERR_EFAULT;
+ }
+
+ if (fd == 1U) {
+ SandboxStream *ssp = sbcp->config->stdout_stream;
+
+ if ((count == 0U) || (ssp == NULL)) {
+ return 0U;
+ }
+
+ return (uint32_t)ssp->vmt->write((void *)ssp, buf, count);
+ }
+
+ if (fd == 2U) {
+ SandboxStream *ssp = sbcp->config->stderr_stream;
+
+ if ((count == 0U) || (ssp == NULL)) {
+ return 0U;
+ }
+
+ return (uint32_t)ssp->vmt->write((void *)ssp, buf, count);
+ }
+
+ return SB_ERR_EBADFD;
+}
+
+uint32_t sb_posix_lseek(uint32_t fd, uint32_t offset, uint32_t whence) {
+
+ (void)offset;
+ (void)whence;
+
+ if ((fd == 0U) || (fd == 1U) || (fd == 2U)) {
+
+ return SB_ERR_ESPIPE;
+ }
+
+ return SB_ERR_EBADFD;
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/sb/host/sbposix.h b/ChibiOS_20.3.2/os/sb/host/sbposix.h
new file mode 100644
index 0000000..9969363
--- /dev/null
+++ b/ChibiOS_20.3.2/os/sb/host/sbposix.h
@@ -0,0 +1,73 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file sb/host/sbposix.h
+ * @brief ARM sandbox host Posix API macros and structures.
+ *
+ * @addtogroup ARM_SANDBOX_POSIX
+ * @{
+ */
+
+#ifndef SBPOSIX_H
+#define SBPOSIX_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ uint32_t sb_posix_open(const char *pathname, uint32_t flags);
+ uint32_t sb_posix_close(uint32_t fd);
+ uint32_t sb_posix_read(uint32_t fd, uint8_t *buf, size_t count);
+ uint32_t sb_posix_write(uint32_t fd, const uint8_t *buf, size_t count);
+ uint32_t sb_posix_lseek(uint32_t fd, uint32_t offset, uint32_t whence);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* SBPOSIX_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/sb/user/sbuser.c b/ChibiOS_20.3.2/os/sb/user/sbuser.c
new file mode 100644
index 0000000..92838d5
--- /dev/null
+++ b/ChibiOS_20.3.2/os/sb/user/sbuser.c
@@ -0,0 +1,74 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file sb/user/sbuser.c
+ * @brief ARMv7-M sandbox user API code.
+ *
+ * @addtogroup ARMV7M_SANDBOX_API
+ * @{
+ */
+
+#include
+#include
+#include
+
+#include "sbuser.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief Sandbox API internal state.
+ */
+sbapi_state_t sb;
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief API layer initialization.
+ * @note To be called before any other call to the "sb" functions.
+ *
+ * @init
+ */
+void sbApiInit(void) {
+
+ sb.frequency = (time_conv_t)sbGetFrequency();
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/sb/user/sbuser.h b/ChibiOS_20.3.2/os/sb/user/sbuser.h
new file mode 100644
index 0000000..ed0be6f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/sb/user/sbuser.h
@@ -0,0 +1,669 @@
+/*
+ ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * @file sb/user/sbapi.h
+ * @brief ARMv7-M sandbox user API macros and structures.
+ *
+ * @addtogroup ARMV7M_SANDBOX_USERAPI
+ * @{
+ */
+
+#ifndef SBUSER_H
+#define SBUSER_H
+
+#include "sberr.h"
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of system time counter.
+ */
+typedef uint32_t systime_t;
+
+/**
+ * @brief Type of system time interval.
+ */
+typedef uint32_t sysinterval_t;
+
+/**
+ * @brief Type of a wide time conversion variable.
+ */
+typedef uint64_t time_conv_t;
+
+/**
+ * @brief Type of time in microseconds.
+ */
+typedef uint32_t time_usecs_t;
+
+/**
+ * @brief Type of time in milliseconds.
+ */
+typedef uint32_t time_msecs_t;
+
+/**
+ * @brief Type of time in seconds.
+ */
+typedef uint32_t time_secs_t;
+
+/**
+ * @brief Type of a message.
+ */
+typedef uint32_t msg_t;
+
+/**
+ * @brief Type of an event mask.
+ */
+typedef uint32_t eventmask_t;
+
+/**
+ * @brief Type of event flags.
+ */
+typedef uint32_t eventflags_t;
+
+/**
+ * @brief Type of a sandbox API internal state variables.
+ */
+typedef struct {
+ /**
+ * @brief System tick frequency.
+ */
+ time_conv_t frequency;
+} sbapi_state_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @name Messages-related macros
+ * @{
+ */
+#define MSG_OK (msg_t)0
+#define MSG_TIMEOUT (msg_t)-1
+#define MSG_RESET (msg_t)-2
+/** @} */
+
+/**
+ * @name Events-related macros
+ * @{
+ */
+#define ALL_EVENTS ((eventmask_t)-1)
+#define EVENT_MASK(eid) ((eventmask_t)1 << (eventmask_t)(eid))
+/** @} */
+
+/**
+ * @name Time and intervals related macros
+ * @{
+ */
+#define TIME_IMMEDIATE ((sysinterval_t)0)
+#define TIME_INFINITE ((sysinterval_t)-1)
+#define TIME_MAX_INTERVAL ((sysinterval_t)-2)
+#define TIME_MAX_SYSTIME ((systime_t)-1)
+/** @} */
+
+/**
+ * @name SVC instruction wrappers.
+ * @{
+ */
+#define __syscall0(x) \
+ asm volatile ("svc " #x : : : "memory")
+
+#define __syscall0r(x) \
+ register uint32_t r0 asm ("r0"); \
+ asm volatile ("svc " #x : "=r" (r0) : : "memory")
+
+#define __syscall1r(x, p1) \
+ register uint32_t r0 asm ("r0") = (uint32_t)(p1); \
+ asm volatile ("svc " #x : "=r" (r0) : "r" (r0) : "memory")
+
+#define __syscall2r(x, p1, p2) \
+ register uint32_t r0 asm ("r0") = (uint32_t)(p1); \
+ register uint32_t r1 asm ("r1") = (uint32_t)(p2); \
+ asm volatile ("svc " #x : "=r" (r0) : "r" (r0), "r" (r1) : "memory")
+
+#define __syscall3r(x, p1, p2, p3) \
+ register uint32_t r0 asm ("r0") = (uint32_t)(p1); \
+ register uint32_t r1 asm ("r1") = (uint32_t)(p2); \
+ register uint32_t r2 asm ("r2") = (uint32_t)(p3); \
+ asm volatile ("svc " #x : "=r" (r0) : "r" (r0), "r" (r1), \
+ "r" (r2) : "memory")
+
+#define __syscall4r(x, p1, p2, p3, p4) \
+ register uint32_t r0 asm ("r0") = (uint32_t)(p1); \
+ register uint32_t r1 asm ("r1") = (uint32_t)(p2); \
+ register uint32_t r2 asm ("r2") = (uint32_t)(p3); \
+ register uint32_t r3 asm ("r3") = (uint32_t)(p4); \
+ asm volatile ("svc " #x : "=r" (r0) : "r" (r0), "r" (r1), \
+ "r" (r2), "r" (r3) : "memory")
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+extern sbapi_state_t sb;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void sbApiInit(void);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Posix-style file open.
+ *
+ * @param[in] pathname file to be opened
+ * @param[in] flags open mode
+ * @return The file descriptor or an error.
+ */
+static inline uint32_t sbFileOpen(const char *pathname,
+ uint32_t flags) {
+
+ __syscall3r(0, SB_POSIX_OPEN, pathname, flags);
+ return r0;
+}
+
+/**
+ * @brief Posix-style file close.
+ *
+ * @param[in] fd file descriptor
+ * @return Operation result.
+ */
+static inline uint32_t sbFileClose(uint32_t fd) {
+
+ __syscall2r(0, SB_POSIX_CLOSE, fd);
+ return r0;
+}
+
+/**
+ * @brief Posix-style file read.
+ *
+ * @param[in] fd file descriptor
+ * @param[out] buf buffer pointer
+ * @param[in] count number of bytes
+ * @return The number of bytes really transferred or an error.
+ */
+static inline size_t sbFileRead(uint32_t fd,
+ uint8_t *buf,
+ size_t count) {
+
+ __syscall4r(0, SB_POSIX_READ, fd, buf, count);
+ return (size_t)r0;
+}
+
+/**
+ * @brief Posix-style file write.
+ *
+ * @param[in] fd file descriptor
+ * @param[in] buf buffer pointer
+ * @param[in] count number of bytes
+ * @return The number of bytes really transferred or an error.
+ */
+static inline size_t sbFileWrite(uint32_t fd,
+ const uint8_t *buf,
+ size_t count) {
+
+ __syscall4r(0, SB_POSIX_WRITE, fd, buf, count);
+ return (size_t)r0;
+}
+
+/**
+ * @brief Posix-style file seek.
+ *
+ * @param[in] fd file descriptor
+ * @param[in] offset file offset
+ * @param[in] whence operation mode
+ * @return Operation result.
+ */
+static inline uint32_t sbFileSeek(uint32_t fd,
+ uint32_t offset,
+ uint32_t whence) {
+
+ __syscall4r(0, SB_POSIX_LSEEK, fd, offset, whence);
+ return (size_t)r0;
+}
+
+/**
+ * @brief Terminates the sandbox.
+ *
+ * @param[in] msg The exit message.
+ *
+ * @api
+ */
+static inline void sbExit(msg_t msg) {
+
+ __syscall1r(1, msg);
+}
+
+/**
+ * @brief Returns the system time.
+ *
+ * @return The current system time.
+ */
+static inline systime_t sbGetSystemTime(void) {
+
+ __syscall0r(2);
+ return (systime_t)r0;
+}
+
+/**
+ * @brief Returns the system time frequency.
+ *
+ * @return The system time frequency.
+ */
+static inline uint32_t sbGetFrequency(void) {
+
+ __syscall0r(3);
+ return (uint32_t)r0;
+}
+
+/**
+ * @brief Suspends the invoking thread for the specified interval.
+ *
+ * @param[in] interval the delay in system ticks
+ *
+ * @api
+ */
+static inline void sbSleep(sysinterval_t interval) {
+
+ __syscall1r(4, interval);
+}
+
+/**
+ * @brief Suspends the invoking thread until the system time arrives to the
+ * specified value.
+ * @note The system time is assumed to be between @p start and @p next
+ * else the call is assumed to have been called outside the
+ * allowed time interval, in this case no sleep is performed.
+ *
+ * @param[in] prev absolute system time of the previous deadline
+ * @param[in] next absolute system time of the next deadline
+ * @return the @p next parameter
+ *
+ * @api
+ */
+static inline void sbSleepUntil(systime_t prev, systime_t next) {
+
+ __syscall2r(5, prev, next);
+}
+
+/**
+ * @brief Waits for a message.
+ *
+ * @return The received message.
+ */
+static inline msg_t sbMsgWait(void) {
+
+ __syscall0r(6);
+ return (uint32_t)r0;
+}
+
+/**
+ * @brief Replies to a message.
+ *
+ * @param[in] msg the reply message
+ *
+ * @api
+ */
+static inline uint32_t sbMsgReply(msg_t msg) {
+
+ __syscall1r(7, msg);
+ return (uint32_t)r0;
+}
+
+/**
+ * @brief Waits for exactly one of the specified events.
+ * @details The function waits for one event among those specified in
+ * @p events to become pending then the event is cleared and returned.
+ * @note One and only one event is served in the function, the one with the
+ * lowest event id. The function is meant to be invoked into a loop
+ * in order to serve all the pending events.
+ * This means that Event Listeners with a lower event identifier have
+ * an higher priority.
+ *
+ * @param[in] events events that the function should wait
+ * for, @p ALL_EVENTS enables all the events
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The mask of the lowest event id served and cleared.
+ * @retval 0 if the operation has timed out.
+ *
+ * @api
+ */
+static inline eventmask_t sbEventWaitOneTimeout(eventmask_t events,
+ sysinterval_t timeout) {
+
+ __syscall2r(8, events, timeout);
+ return (uint32_t)r0;
+}
+
+/**
+ * @brief Waits for any of the specified events.
+ * @details The function waits for any event among those specified in
+ * @p events to become pending then the events are cleared and
+ * returned.
+ *
+ * @param[in] events events that the function should wait
+ * for, @p ALL_EVENTS enables all the events
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The mask of the served and cleared events.
+ * @retval 0 if the operation has timed out.
+ *
+ * @api
+ */
+static inline eventmask_t sbEventWaitAnyTimeout(eventmask_t events,
+ sysinterval_t timeout) {
+
+ __syscall2r(9, events, timeout);
+ return (uint32_t)r0;
+}
+
+/**
+ * @brief Waits for all the specified events.
+ * @details The function waits for all the events specified in @p events to
+ * become pending then the events are cleared and returned.
+ *
+ * @param[in] events events that the function should wait
+ * for, @p ALL_EVENTS requires all the events
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The mask of the served and cleared events.
+ * @retval 0 if the operation has timed out.
+ *
+ * @api
+ */
+static inline eventmask_t sbEventWaitAllTimeout(eventmask_t events,
+ sysinterval_t timeout) {
+
+ __syscall2r(10, events, timeout);
+ return (uint32_t)r0;
+}
+
+/**
+ * @brief Signals all the Event Listeners registered on the specified Event
+ * Source.
+ *
+ * @param[in] flags the flags set to be added to the listener flags mask
+ *
+ * @api
+ */
+static inline uint32_t sbEventBroadcastFlags(eventflags_t flags) {
+
+ __syscall1r(11, flags);
+ return (uint32_t)r0;
+}
+
+/**
+ * @brief Seconds to time interval.
+ * @details Converts from seconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ *
+ * @param[in] secs number of seconds
+ * @return The number of ticks.
+ *
+ * @special
+ */
+static inline sysinterval_t sbTimeS2I(time_secs_t secs) {
+ time_conv_t ticks;
+
+ ticks = (time_conv_t)secs * sb.frequency;
+
+/* sbDbgAssert(ticks <= (time_conv_t)TIME_MAX_INTERVAL,
+ "conversion overflow");*/
+
+ return (sysinterval_t)ticks;
+}
+
+/**
+ * @brief Milliseconds to time interval.
+ * @details Converts from milliseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ *
+ * @param[in] msec number of milliseconds
+ * @return The number of ticks.
+ *
+ * @special
+ */
+static inline sysinterval_t sbTimeMS2I(time_msecs_t msec) {
+ time_conv_t ticks;
+
+ ticks = (((time_conv_t)msec * sb.frequency) +
+ (time_conv_t)999) / (time_conv_t)1000;
+
+/* chDbgAssert(ticks <= (time_conv_t)TIME_MAX_INTERVAL,
+ "conversion overflow");*/
+
+ return (sysinterval_t)ticks;
+}
+
+/**
+ * @brief Microseconds to time interval.
+ * @details Converts from microseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ *
+ * @param[in] usec number of microseconds
+ * @return The number of ticks.
+ *
+ * @special
+ */
+static inline sysinterval_t sbTimeUS2I(time_usecs_t usec) {
+ time_conv_t ticks;
+
+ ticks = (((time_conv_t)usec * sb.frequency) +
+ (time_conv_t)999999) / (time_conv_t)1000000;
+
+/* chDbgAssert(ticks <= (time_conv_t)TIME_MAX_INTERVAL,
+ "conversion overflow");*/
+
+ return (sysinterval_t)ticks;
+}
+
+/**
+ * @brief Time interval to seconds.
+ * @details Converts from system interval to seconds.
+ * @note The result is rounded up to the next second boundary.
+ *
+ * @param[in] interval interval in ticks
+ * @return The number of seconds.
+ *
+ * @special
+ */
+static inline time_secs_t sbTimeI2S(sysinterval_t interval) {
+ time_conv_t secs;
+
+ secs = ((time_conv_t)interval +
+ sb.frequency -
+ (time_conv_t)1) / sb.frequency;
+
+/* sbDbgAssert(secs < (time_conv_t)((time_secs_t)-1),
+ "conversion overflow");*/
+
+ return (time_secs_t)secs;
+}
+
+/**
+ * @brief Time interval to milliseconds.
+ * @details Converts from system interval to milliseconds.
+ * @note The result is rounded up to the next millisecond boundary.
+ *
+ * @param[in] interval interval in ticks
+ * @return The number of milliseconds.
+ *
+ * @special
+ */
+static inline time_msecs_t sbTimeI2MS(sysinterval_t interval) {
+ time_conv_t msecs;
+
+ msecs = (((time_conv_t)interval * (time_conv_t)1000) +
+ sb.frequency - (time_conv_t)1) /
+ sb.frequency;
+
+/* sbDbgAssert(msecs < (time_conv_t)((time_msecs_t)-1),
+ "conversion overflow");*/
+
+ return (time_msecs_t)msecs;
+}
+
+/**
+ * @brief Time interval to microseconds.
+ * @details Converts from system interval to microseconds.
+ * @note The result is rounded up to the next microsecond boundary.
+ *
+ * @param[in] interval interval in ticks
+ * @return The number of microseconds.
+ *
+ * @special
+ */
+static inline time_usecs_t sbTimeI2US(sysinterval_t interval) {
+ time_conv_t usecs;
+
+ usecs = (((time_conv_t)interval * (time_conv_t)1000000) +
+ sb.frequency - (time_conv_t)1) / sb.frequency;
+
+/* sbDbgAssert(usecs <= (time_conv_t)((time_usecs_t)-1),
+ "conversion overflow");*/
+
+ return (time_usecs_t)usecs;
+}
+
+/**
+ * @brief Adds an interval to a system time returning a system time.
+ *
+ * @param[in] systime base system time
+ * @param[in] interval interval to be added
+ * @return The new system time.
+ *
+ * @xclass
+ */
+static inline systime_t sbTimeAddX(systime_t systime, sysinterval_t interval) {
+
+ return systime + (systime_t)interval;
+}
+
+/**
+ * @brief Subtracts two system times returning an interval.
+ *
+ * @param[in] start first system time
+ * @param[in] end second system time
+ * @return The interval representing the time difference.
+ *
+ * @xclass
+ */
+static inline sysinterval_t sbTimeDiffX(systime_t start, systime_t end) {
+
+ return (sysinterval_t)((systime_t)(end - start));
+}
+
+/**
+ * @brief Checks if the specified time is within the specified time range.
+ * @note When start==end then the function returns always true because the
+ * whole time range is specified.
+ *
+ * @param[in] time the time to be verified
+ * @param[in] start the start of the time window (inclusive)
+ * @param[in] end the end of the time window (non inclusive)
+ * @retval true current time within the specified time window.
+ * @retval false current time not within the specified time window.
+ *
+ * @xclass
+ */
+static inline bool sbTimeIsInRangeX(systime_t time, systime_t start, systime_t end) {
+
+ return (bool)((systime_t)((systime_t)time - (systime_t)start) <
+ (systime_t)((systime_t)end - (systime_t)start));
+}
+
+/**
+ * @brief Delays the invoking thread for the specified number of seconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system tick clock.
+ *
+ * @param[in] secs time in seconds
+ *
+ * @api
+ */
+static inline void sbSleepSeconds(time_secs_t secs) {
+
+ sbSleep(sbTimeS2I(secs));
+}
+
+/**
+ * @brief Delays the invoking thread for the specified number of
+ * milliseconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system tick clock.
+ *
+ * @param[in] msecs time in milliseconds
+ *
+ * @api
+ */
+static inline void sbSleepMilliseconds(time_msecs_t msecs) {
+
+ sbSleep(sbTimeMS2I(msecs));
+}
+
+/**
+ * @brief Delays the invoking thread for the specified number of
+ * microseconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system tick clock.
+ *
+ * @param[in] usecs time in microseconds
+ *
+ * @api
+ */
+static inline void sbSleepMicroseconds(time_usecs_t usecs) {
+
+ sbSleep(sbTimeUS2I(usecs));
+}
+
+#endif /* SBUSER_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/sb/user/sbuser.mk b/ChibiOS_20.3.2/os/sb/user/sbuser.mk
new file mode 100644
index 0000000..fcf16f3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/sb/user/sbuser.mk
@@ -0,0 +1,12 @@
+# List of the ChibiOS ARMv7-M sandbox user files.
+SBUSERSRC = $(CHIBIOS)/os/sb/user/sbuser.c
+
+SBUSERASM =
+
+SBUSERINC = $(CHIBIOS)/os/sb/common \
+ $(CHIBIOS)/os/sb/user
+
+# Shared variables
+ALLXASMSRC += $(SBUSERASM)
+ALLCSRC += $(SBUSERSRC)
+ALLINC += $(SBUSERINC)
diff --git a/ChibiOS_20.3.2/os/sb/various/syscalls.c b/ChibiOS_20.3.2/os/sb/various/syscalls.c
new file mode 100644
index 0000000..4d3ae0f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/sb/various/syscalls.c
@@ -0,0 +1,142 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "sbuser.h"
+
+#define MAKERR(e) (-(int)(e))
+
+__attribute__((used))
+int _close_r(struct _reent *r, int file) {
+ uint32_t err;
+
+ err = sbFileClose((uint32_t)file);
+ if (SB_ERR_ISERROR(err)) {
+ __errno_r(r) = MAKERR(err);
+ return -1;
+ }
+
+ return 0;
+}
+
+__attribute__((used))
+int _write_r(struct _reent *r, int file, char * ptr, int len) {
+ uint32_t err;
+
+ err = sbFileWrite((uint32_t)file, (const uint8_t *)ptr, (size_t)len);
+ if (SB_ERR_ISERROR(err)) {
+ __errno_r(r) = MAKERR(err);
+ return -1;
+ }
+
+ return (int)err;
+}
+
+__attribute__((used))
+int _read_r(struct _reent *r, int file, char * ptr, int len) {
+ uint32_t err;
+
+ err = sbFileRead((uint32_t)file, (uint8_t *)ptr, (size_t)len);
+ if (SB_ERR_ISERROR(err)) {
+ __errno_r(r) = MAKERR(err);
+ return -1;
+ }
+
+ return (int)err;
+}
+
+__attribute__((used))
+int _lseek_r(struct _reent *r, int file, int ptr, int dir) {
+ uint32_t err;
+
+ err = sbFileSeek((uint32_t)file, (uint32_t)ptr, (uint32_t)dir);
+ if (SB_ERR_ISERROR(err)) {
+ __errno_r(r) = MAKERR(err);
+ return -1;
+ }
+
+ return (int)err;
+}
+
+__attribute__((used))
+int _fstat_r(struct _reent *r, int file, struct stat * st) {
+ (void)r;
+ (void)file;
+
+ memset(st, 0, sizeof(*st));
+ st->st_mode = S_IFCHR;
+ return 0;
+}
+
+__attribute__((used))
+int _isatty_r(struct _reent *r, int fd) {
+ (void)r;
+ (void)fd;
+
+ return 1;
+}
+
+__attribute__((used))
+caddr_t _sbrk_r(struct _reent *r, int incr) {
+ extern uint8_t __heap_end__, __heap_base__;
+ static uint8_t *p = &__heap_base__;
+ uint8_t *prevp;
+
+ prevp = p;
+ if ((p + incr > &__heap_end__) ||
+ (p + incr < &__heap_base__)) {
+ __errno_r(r) = ENOMEM;
+ return (caddr_t)-1;
+ }
+
+ p += incr;
+ return (caddr_t)prevp;
+}
+
+__attribute__((used))
+int _getpid_r(struct _reent *r) {
+
+ (void)r;
+
+ return 1;
+}
+
+__attribute__((used))
+int _kill_r(struct _reent *r, int pid, int sig) {
+
+ (void)pid;
+ (void)sig;
+
+ __errno_r(r) = EINVAL;
+ return -1;
+}
+
+__attribute__((used))
+void _exit(int code) {
+
+ sbExit((msg_t)code);
+ while (true);
+}
+
+/*** EOF ***/
diff --git a/ChibiOS_20.3.2/os/various/cpp_wrappers/ch.cpp b/ChibiOS_20.3.2/os/various/cpp_wrappers/ch.cpp
new file mode 100644
index 0000000..0f7ae05
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/cpp_wrappers/ch.cpp
@@ -0,0 +1,45 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/**
+ * @file ch.cpp
+ * @brief C++ wrapper code.
+ *
+ * @addtogroup cpp_library
+ * @{
+ */
+
+#include "ch.hpp"
+
+namespace chibios_rt {
+
+#if (CH_CFG_NO_IDLE_THREAD == FALSE) || defined(__DOXYGEN__)
+ ThreadReference System::getIdleThreadX(void) {
+
+ return ThreadReference(chSysGetIdleThreadX());
+ }
+#endif /* CH_CFG_NO_IDLE_THREAD == FALSE */
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::BaseStaticThread *
+ *------------------------------------------------------------------------*/
+
+ void _thd_start(void *arg) {
+
+ ((BaseThread *)arg)->main();
+ }
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/various/cpp_wrappers/ch.hpp b/ChibiOS_20.3.2/os/various/cpp_wrappers/ch.hpp
new file mode 100644
index 0000000..49d33a4
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/cpp_wrappers/ch.hpp
@@ -0,0 +1,3133 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file ch.hpp
+ * @brief C++ wrapper classes and definitions.
+ *
+ * @addtogroup cpp_library
+ * @{
+ */
+
+#include
+
+#ifndef _CH_HPP_
+#define _CH_HPP_
+
+/**
+ * @brief ChibiOS-RT kernel-related classes and interfaces.
+ */
+namespace chibios_rt {
+
+ /* Forward declaration of some classes.*/
+ class ThreadReference;
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::System *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating the base system functionalities.
+ */
+ class System {
+ public:
+ /**
+ * @brief ChibiOS/RT initialization.
+ * @details After executing this function the current instructions stream
+ * becomes the main thread.
+ * @pre Interrupts must be still disabled when @p chSysInit() is invoked
+ * and are internally enabled.
+ * @post The main thread is created with priority @p NORMALPRIO.
+ * @note This function has special, architecture-dependent, requirements,
+ * see the notes into the various port reference manuals.
+ *
+ * @special
+ */
+ static void init(void) {
+
+ chSysInit();
+ }
+
+ /**
+ * @brief Halts the system.
+ * @details This function is invoked by the operating system when an
+ * unrecoverable error is detected, for example because a programming
+ * error in the application code that triggers an assertion while
+ * in debug mode.
+ * @note Can be invoked from any system state.
+ *
+ * @param[in] reason pointer to an error string
+ *
+ * @special
+ */
+ static void halt(const char *reason) {
+
+ chSysHalt(reason);
+ }
+
+ /**
+ * @brief System integrity check.
+ * @details Performs an integrity check of the important ChibiOS/RT data
+ * structures.
+ * @note The appropriate action in case of failure is to halt the system
+ * before releasing the critical zone.
+ * @note If the system is corrupted then one possible outcome of this
+ * function is an exception caused by @p nullptr or corrupted
+ * pointers in list elements. Exception vectors must be monitored
+ * as well.
+ * @note This function is not used internally, it is up to the
+ * application to define if and where to perform system
+ * checking.
+ * @note Performing all tests at once can be a slow operation and can
+ * degrade the system response time. It is suggested to execute
+ * one test at time and release the critical zone in between tests.
+ *
+ * @param[in] testmask Each bit in this mask is associated to a test to be
+ * performed.
+ * @return The test result.
+ * @retval false The test succeeded.
+ * @retval true Test failed.
+ *
+ * @iclass
+ */
+ static bool integrityCheckI(unsigned int testmask) {
+
+ return chSysIntegrityCheckI(testmask);
+ }
+
+ /**
+ * @brief Raises the system interrupt priority mask to the maximum level.
+ * @details All the maskable interrupt sources are disabled regardless their
+ * hardware priority.
+ * @note Do not invoke this API from within a kernel lock.
+ *
+ * @special
+ */
+ static void disable(void) {
+
+ chSysDisable();
+ }
+
+ /**
+ * @brief Raises the system interrupt priority mask to system level.
+ * @details The interrupt sources that should not be able to preempt the kernel
+ * are disabled, interrupt sources with higher priority are still
+ * enabled.
+ * @note Do not invoke this API from within a kernel lock.
+ * @note This API is no replacement for @p chSysLock(), the @p chSysLock()
+ * could do more than just disable the interrupts.
+ *
+ * @special
+ */
+ static void suspend(void) {
+
+ chSysSuspend();
+ }
+
+ /**
+ * @brief Lowers the system interrupt priority mask to user level.
+ * @details All the interrupt sources are enabled.
+ * @note Do not invoke this API from within a kernel lock.
+ * @note This API is no replacement for @p chSysUnlock(), the
+ * @p chSysUnlock() could do more than just enable the interrupts.
+ *
+ * @special
+ */
+ static void enable(void) {
+
+ chSysEnable();
+ }
+
+ /**
+ * @brief Enters the kernel lock mode.
+ *
+ * @special
+ */
+ static void lock(void) {
+
+ chSysLock();
+ }
+
+ /**
+ * @brief Leaves the kernel lock mode.
+ *
+ * @special
+ */
+ static void unlock(void) {
+
+ chSysUnlock();
+ }
+
+ /**
+ * @brief Enters the kernel lock mode from within an interrupt handler.
+ * @note This API may do nothing on some architectures, it is required
+ * because on ports that support preemptable interrupt handlers
+ * it is required to raise the interrupt mask to the same level of
+ * the system mutual exclusion zone.
+ * It is good practice to invoke this API before invoking any I-class
+ * syscall from an interrupt handler.
+ * @note This API must be invoked exclusively from interrupt handlers.
+ *
+ * @special
+ */
+ static void lockFromIsr(void) {
+
+ chSysLockFromISR();
+ }
+
+ /**
+ * @brief Leaves the kernel lock mode from within an interrupt handler.
+ *
+ * @note This API may do nothing on some architectures, it is required
+ * because on ports that support preemptable interrupt handlers
+ * it is required to raise the interrupt mask to the same level of
+ * the system mutual exclusion zone.
+ * It is good practice to invoke this API after invoking any I-class
+ * syscall from an interrupt handler.
+ * @note This API must be invoked exclusively from interrupt handlers.
+ *
+ * @special
+ */
+ static void unlockFromIsr(void) {
+
+ chSysUnlockFromISR();
+ }
+
+ /**
+ * @brief Unconditionally enters the kernel lock state.
+ * @note Can be called without previous knowledge of the current lock state.
+ * The final state is "s-locked".
+ *
+ * @special
+ */
+ static void unconditionalLock(void) {
+
+ chSysUnconditionalLock();
+ }
+
+ /**
+ * @brief Unconditionally leaves the kernel lock state.
+ * @note Can be called without previous knowledge of the current lock state.
+ * The final state is "normal".
+ *
+ * @special
+ */
+ static void unconditionalUnlock(void) {
+
+ chSysUnconditionalUnlock();
+ }
+
+ /**
+ * @brief Returns the execution status and enters a critical zone.
+ * @details This functions enters into a critical zone and can be called
+ * from any context. Because its flexibility it is less efficient
+ * than @p chSysLock() which is preferable when the calling context
+ * is known.
+ * @post The system is in a critical zone.
+ *
+ * @return The previous system status, the encoding of this
+ * status word is architecture-dependent and opaque.
+ *
+ * @xclass
+ */
+ static syssts_t getStatusAndLockX(void) {
+
+ return chSysGetStatusAndLockX();
+ }
+
+ /**
+ * @brief Restores the specified execution status and leaves a critical zone.
+ * @note A call to @p chSchRescheduleS() is automatically performed
+ * if exiting the critical zone and if not in ISR context.
+ *
+ * @param[in] sts the system status to be restored.
+ *
+ * @xclass
+ */
+ static void restoreStatusX(syssts_t sts) {
+
+ chSysRestoreStatusX(sts);
+ }
+
+#if (PORT_SUPPORTS_RT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Returns the current value of the system real time counter.
+ * @note This function is only available if the port layer supports the
+ * option @p PORT_SUPPORTS_RT.
+ *
+ * @return The value of the system realtime counter of
+ * type rtcnt_t.
+ *
+ * @xclass
+ */
+ static rtcnt_t getRealtimeCounterX(void) {
+
+ return chSysGetRealtimeCounterX();
+ }
+
+ /**
+ * @brief Realtime window test.
+ * @details This function verifies if the current realtime counter value
+ * lies within the specified range or not. The test takes care
+ * of the realtime counter wrapping to zero on overflow.
+ * @note When start==end then the function returns always true because the
+ * whole time range is specified.
+ * @note This function is only available if the port layer supports the
+ * option @p PORT_SUPPORTS_RT.
+ *
+ * @param[in] cnt the counter value to be tested
+ * @param[in] start the start of the time window (inclusive)
+ * @param[in] end the end of the time window (non inclusive)
+ * @retval true current time within the specified time window.
+ * @retval false current time not within the specified time window.
+ *
+ * @xclass
+ */
+ static bool isCounterWithinX(rtcnt_t cnt,
+ rtcnt_t start,
+ rtcnt_t end) {
+
+ return chSysIsCounterWithinX(cnt, start, end);
+ }
+
+ /**
+ * @brief Polled delay.
+ * @note The real delay is always few cycles in excess of the specified
+ * value.
+ * @note This function is only available if the port layer supports the
+ * option @p PORT_SUPPORTS_RT.
+ *
+ * @param[in] cycles number of cycles
+ *
+ * @xclass
+ */
+ static void polledDelayX(rtcnt_t cycles) {
+
+ chSysPolledDelayX(cycles);
+ }
+#endif /* PORT_SUPPORTS_RT == TRUE */
+
+ /**
+ * @brief Returns the system time as system ticks.
+ * @note The system tick time interval is implementation dependent.
+ *
+ * @return The system time.
+ *
+ * @api
+ */
+ static systime_t getTime(void) {
+
+ return chVTGetSystemTime();
+ }
+
+ /**
+ * @brief Returns the system time as system ticks.
+ * @note The system tick time interval is implementation dependent.
+ *
+ * @return The system time.
+ *
+ * @xclass
+ */
+ static systime_t getTimeX(void) {
+
+ return chVTGetSystemTimeX();
+ }
+
+ /**
+ * @brief Checks if the current system time is within the specified time
+ * window.
+ * @note When start==end then the function returns always true because the
+ * whole time range is specified.
+ *
+ * @param[in] start the start of the time window (inclusive)
+ * @param[in] end the end of the time window (non inclusive)
+ * @retval true current time within the specified time window.
+ * @retval false current time not within the specified time window.
+ *
+ * @api
+ */
+ static bool isSystemTimeWithin(systime_t start, systime_t end) {
+
+ return chVTIsSystemTimeWithin(start, end);
+ }
+
+#if (CH_CFG_NO_IDLE_THREAD == FALSE) || defined(__DOXYGEN__)
+ /**
+ * @brief Returns a reference to the idle thread.
+ * @pre In order to use this function the option @p CH_CFG_NO_IDLE_THREAD
+ * must be disabled.
+ * @note The reference counter of the idle thread is not incremented but
+ * it is not strictly required being the idle thread a static
+ * object.
+ *
+ * @return Reference to the idle thread.
+ *
+ * @xclass
+ */
+ static ThreadReference getIdleThreadX(void);
+#endif /* CH_CFG_NO_IDLE_THREAD == FALSE */
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::CriticalSectionLocker *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief RAII helper for reentrant critical sections.
+ */
+ class CriticalSectionLocker {
+ volatile const syssts_t syssts = chSysGetStatusAndLockX();
+
+ public:
+ ~CriticalSectionLocker() {
+
+ chSysRestoreStatusX(syssts);
+ }
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::Scheduler *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating the low level scheduler functionalities.
+ */
+ class Scheduler {
+ public:
+ /**
+ * @brief Performs a reschedule if a higher priority thread is runnable.
+ * @details If a thread with a higher priority than the current thread is in
+ * the ready list then make the higher priority thread running.
+ *
+ * @sclass
+ */
+ static void rescheduleS(void) {
+
+ void chSchRescheduleS();
+ }
+ };
+
+#if (CH_CFG_USE_MEMCORE == TRUE) || defined(__DOXYGEN__)
+ /*------------------------------------------------------------------------*
+ * chibios_rt::Core *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating the base system functionalities.
+ */
+ class Core {
+ public:
+ /**
+ * @brief Allocates a memory block.
+ * @details The size of the returned block is aligned to the alignment
+ * type so it is not possible to allocate less
+ * than MEM_ALIGN_SIZE
.
+ *
+ * @param[in] size the size of the block to be allocated
+ * @return A pointer to the allocated memory block.
+ * @retval nullptr allocation failed, core memory exhausted.
+ *
+ * @api
+ */
+ static void *alloc(size_t size) {
+
+ return chCoreAlloc(size);
+ }
+
+ /**
+ * @brief Allocates a memory block.
+ * @details The size of the returned block is aligned to the alignment
+ * type so it is not possible to allocate less than
+ * MEM_ALIGN_SIZE
.
+ *
+ * @param[in] size the size of the block to be allocated.
+ * @return A pointer to the allocated memory block.
+ * @retval nullptr allocation failed, core memory exhausted.
+ *
+ * @iclass
+ */
+ static void *allocI(size_t size) {
+
+ return chCoreAllocI(size);
+ }
+
+ /**
+ * @brief Core memory status.
+ *
+ * @return The size, in bytes, of the free core memory.
+ *
+ * @xclass
+ */
+ static size_t getStatusX(void) {
+
+ return chCoreGetStatusX();
+ }
+ };
+#endif /* CH_CFG_USE_MEMCORE == TRUE */
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::Timer *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Timer class.
+ */
+ class Timer {
+ /**
+ * @brief Embedded @p virtual_timer_t structure.
+ */
+ virtual_timer_t vt;
+
+ public:
+ /**
+ * @brief Construct a virtual timer.
+ */
+ Timer() : vt() {
+
+ chVTObjectInit(&vt);
+ }
+
+ /* Prohibit copy construction and assignment.*/
+ Timer(const Timer &) = delete;
+ Timer &operator=(const Timer &) = delete;
+
+ /**
+ * @brief Enables a virtual timer.
+ * @note The associated function is invoked from interrupt context.
+ *
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the special values are handled as follow:
+ * - @a TIME_INFINITE is allowed but interpreted as a
+ * normal time specification.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ * @param[in] vtfunc the timer callback function. After invoking the
+ * callback the timer is disabled and the structure
+ * can be disposed or reused.
+ * @param[in] par a parameter that will be passed to the callback
+ * function
+ *
+ * @api
+ */
+ void set(sysinterval_t timeout, vtfunc_t vtfunc, void *par) {
+
+ chVTSet(&vt, timeout, vtfunc, par);
+ }
+
+ /**
+ * @brief Enables a virtual timer.
+ * @note The associated function is invoked from interrupt context.
+ *
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the special values are handled as follow:
+ * - @a TIME_INFINITE is allowed but interpreted as a
+ * normal time specification.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ * @param[in] vtfunc the timer callback function. After invoking the
+ * callback the timer is disabled and the structure
+ * can be disposed or reused.
+ * @param[in] par a parameter that will be passed to the callback
+ * function
+ *
+ * @iclass
+ */
+ void setI(sysinterval_t timeout, vtfunc_t vtfunc, void *par) {
+
+ chVTSetI(&vt, timeout, vtfunc, par);
+ }
+
+ /**
+ * @brief Resets the timer, if armed.
+ *
+ * @api
+ */
+ void reset() {
+
+ chVTReset(&vt);
+ }
+
+ /**
+ * @brief Resets the timer, if armed.
+ *
+ * @iclass
+ */
+ void resetI() {
+
+ chVTResetI(&vt);
+ }
+
+ /**
+ * @brief Returns the timer status.
+ *
+ * @return The timer status.
+ * @retval true If the timer is armed.
+ * @retval false If the timer already fired its callback.
+ *
+ * @iclass
+ */
+ bool isArmedI(void) const {
+
+ return chVTIsArmedI(&vt);
+ }
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::ThreadReference *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Thread reference class.
+ * @details This class encapsulates a reference to a system thread. All
+ * operations involving another thread are performed through
+ * an object of this type.
+ */
+ class ThreadReference final {
+ /**
+ * @brief Pointer to the system thread.
+ */
+ thread_t *thread_ref;
+
+ public:
+ /**
+ * @brief Thread reference constructor.
+ * @note Do not call this version directly, this constructor is empty
+ * and is here only to do nothing when an object of this kind
+ * is declared then assigned.
+ * @note Automatic instances of this object are not initialized
+ * because this constructor, this is intentional.
+ *
+ * @param[in] tp the target thread
+ *
+ * @init
+ */
+ ThreadReference(void) {
+
+ }
+
+ /**
+ * @brief Thread reference constructor.
+ *
+ * @param[in] tp the target thread
+ *
+ * @init
+ */
+ ThreadReference(thread_t *tp) : thread_ref(tp) {
+
+ }
+
+ /**
+ * @brief Returns the reference state.
+ *
+ * @return The reference state.
+ * @retval false if the reference is still valid.
+ * @retval true if the reference is set to @p nullptr.
+ */
+ bool isNull(void) const {
+
+ return (bool)(thread_ref == nullptr);
+ }
+
+ /**
+ * @brief Returns the low level pointer to the referenced thread.
+ */
+ thread_t *getInner(void) {
+
+ return thread_ref;
+ }
+
+ /**
+ * @brief Requests a thread termination.
+ * @pre The target thread must be written to invoke periodically
+ * @p chThdShouldTerminate() and terminate cleanly if it returns
+ * @p TRUE.
+ * @post The specified thread will terminate after detecting the
+ * termination condition.
+ *
+ * @api
+ */
+ void requestTerminate(void) const {
+
+ chThdTerminate(thread_ref);
+ }
+
+#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Adds a reference to a thread object.
+ * @pre The configuration option @p CH_CFG_USE_REGISTRY must be enabled
+ * in order to use this function.
+ *
+ * @return A new thread reference.
+ *
+ * @api
+ */
+ ThreadReference addRef(void) const {
+
+ return ThreadReference(chThdAddRef(thread_ref));
+ }
+
+ /**
+ * @brief Releases a reference to a thread object.
+ * @details If the references counter reaches zero and the thread
+ * is in the @p CH_STATE_FINAL state then the thread's memory is
+ * returned to the proper allocator and the thread is removed
+ * from the registry.
+ * Threads whose counter reaches zero and are still active become
+ * "detached" and will be removed from registry on termination.
+ * @pre The configuration option @p CH_CFG_USE_REGISTRY must be enabled in
+ * order to use this function.
+ * @post The reference is set to @p nullptr.
+ * @note Static threads are not affected.
+ *
+ * @api
+ */
+ void release(void) {
+ thread_t *tp = thread_ref;
+ thread_ref = nullptr;
+
+ chThdRelease(tp);
+ }
+#endif /* CH_CFG_USE_REGISTRY == TRUE */
+
+#if (CH_CFG_USE_WAITEXIT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Blocks the execution of the invoking thread until the specified
+ * thread terminates then the exit code is returned.
+ * @details This function waits for the specified thread to terminate then
+ * decrements its reference counter, if the counter reaches zero
+ * then the thread working area is returned to the proper
+ * allocator.
+ * The memory used by the exited thread is handled in different
+ * ways depending on the API that spawned the thread:
+ * - If the thread was spawned by @p chThdCreateStatic() or by
+ * @p chThdCreateI() then nothing happens and the thread working
+ * area is not released or modified in any way. This is the
+ * default, totally static, behavior.
+ * - If the thread was spawned by @p chThdCreateFromHeap() then
+ * the working area is returned to the system heap.
+ * - If the thread was spawned by @p chThdCreateFromMemoryPool()
+ * then the working area is returned to the owning memory pool.
+ * .
+ * @pre The configuration option @p CH_USE_WAITEXIT must be enabled in
+ * order to use this function.
+ * @post Enabling @p chThdWait() requires 2-4 (depending on the
+ * architecture) extra bytes in the @p Thread structure.
+ * @post The reference is set to @p nullptr.
+ * @note If @p CH_USE_DYNAMIC is not specified this function just waits
+ * for the thread termination, no memory allocators are involved.
+ *
+ * @return The exit code from the terminated thread.
+ *
+ * @api
+ */
+ msg_t wait(void) {
+ thread_t *tp = thread_ref;
+ thread_ref = nullptr;
+
+ msg_t msg = chThdWait(tp);
+ return msg;
+ }
+#endif /* CH_CFG_USE_WAITEXIT == TRUE */
+
+#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Sends a message to the thread and returns the answer.
+ *
+ * @param[in] msg the sent message
+ * @return The returned message.
+ *
+ * @api
+ */
+ msg_t sendMessage(msg_t msg) const {
+
+ return chMsgSend(thread_ref, msg);
+ }
+
+ /**
+ * @brief Returns true if there is at least one message in queue.
+ *
+ * @retval true A message is waiting in queue.
+ * @retval false A message is not waiting in queue.
+ *
+ * @api
+ */
+ bool isPendingMessage(void) const {
+
+ return chMsgIsPendingI(thread_ref);
+ }
+
+ /**
+ * @brief Returns an enqueued message or @p nullptr.
+ *
+ * @return The incoming message.
+ *
+ * @api
+ */
+ msg_t getMessage(void) const {
+
+ return chMsgGet(thread_ref);
+ }
+
+ /**
+ * @brief Releases the next message in queue with a reply.
+ * @post The reference is set to @p nullptr.
+ *
+ * @param[in] msg the answer message
+ *
+ * @api
+ */
+ void releaseMessage(msg_t msg) {
+ thread_t *tp = thread_ref;
+ thread_ref = nullptr;
+
+ chMsgRelease(tp, msg);
+ }
+#endif /* CH_CFG_USE_MESSAGES == TRUE */
+
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Adds a set of event flags directly to specified @p Thread.
+ *
+ * @param[in] mask the event flags set to be ORed
+ *
+ * @api
+ */
+ void signalEvents(eventmask_t mask) const {
+
+ chEvtSignal(thread_ref, mask);
+ }
+
+ /**
+ * @brief Adds a set of event flags directly to specified @p Thread.
+ *
+ * @param[in] mask the event flags set to be ORed
+ *
+ * @iclass
+ */
+ void signalEventsI(eventmask_t mask) const {
+
+ chEvtSignalI(thread_ref, mask);
+ }
+#endif /* CH_CFG_USE_EVENTS == TRUE */
+
+#if (CH_DBG_THREADS_PROFILING == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Returns the number of ticks consumed by the specified thread.
+ * @note This function is only available when the
+ * @p CH_DBG_THREADS_PROFILING configuration option is enabled.
+ *
+ * @param[in] tp pointer to the thread
+ * @return The number of consumed system ticks.
+ *
+ * @xclass
+ */
+ systime_t getTicksX(void) const {
+
+ return chThdGetTicksX(thread_ref);
+ }
+#endif /* CH_DBG_THREADS_PROFILING == TRUE */
+ };
+
+#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
+ /*------------------------------------------------------------------------*
+ * chibios_rt::Registry *
+ *------------------------------------------------------------------------*/
+ class Registry {
+ public:
+ /**
+ * @brief Returns the first thread in the system.
+ * @details Returns the most ancient thread in the system, usually this is
+ * the main thread unless it terminated. A reference is added to the
+ * returned thread in order to make sure its status is not lost.
+ * @note This function cannot return @p nullptr because there is always at
+ * least one thread in the system.
+ *
+ * @return A reference to the most ancient thread.
+ *
+ * @api
+ */
+ static ThreadReference firstThread(void) {
+
+ return ThreadReference(chRegFirstThread());
+ }
+
+ /**
+ * @brief Returns the thread next to the specified one.
+ * @details The reference counter of the specified thread is decremented and
+ * the reference counter of the returned thread is incremented.
+ *
+ * @param[in] tref reference to the thread
+ * @return A reference to the next thread. The reference is
+ * set to @p nullptr if there is no next thread.
+ *
+ * @api
+ */
+ static ThreadReference nextThread(ThreadReference tref) {
+
+ return ThreadReference(chRegNextThread(tref.getInner()));
+ }
+
+ /**
+ * @brief Retrieves a thread reference by name.
+ * @note The reference counter of the found thread is increased by one so
+ * it cannot be disposed incidentally after the pointer has been
+ * returned.
+ *
+ * @param[in] name the thread name
+ * @return A pointer to the found thread.
+ * @return A reference to the found thread. The reference is
+ * set to @p nullptr if no next thread is found.
+ *
+ * @api
+ */
+ static ThreadReference findThreadByName(const char *name) {
+
+ return ThreadReference(chRegFindThreadByName(name));
+ }
+ };
+#endif /* CH_CFG_USE_REGISTRY == TRUE */
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::BaseThread *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Abstract base class for a ChibiOS/RT thread.
+ * @details The thread body is the virtual function @p Main().
+ */
+ class BaseThread {
+ public:
+ /**
+ * @brief BaseThread constructor.
+ *
+ * @init
+ */
+ BaseThread(void) {
+
+ }
+
+ /**
+ * @brief Thread body function.
+ *
+ * @return The exit message.
+ *
+ * @api
+ */
+ virtual void main(void) = 0;
+
+ /**
+ * @brief Creates and starts a system thread.
+ *
+ * @param[in] prio thread priority
+ * @return A reference to the created thread with
+ * reference counter set to one.
+ *
+ * @api
+ */
+ virtual ThreadReference start(tprio_t prio) = 0;
+
+ /**
+ * @brief Returns a reference to the current thread.
+ *
+ * @return A reference to the current thread.
+ *
+ * @xclass
+ */
+ static ThreadReference getSelfX(void) {
+
+ return ThreadReference(chThdGetSelfX());
+ }
+
+ /**
+ * @brief Sets the current thread name.
+ * @pre This function only stores the pointer to the name if the option
+ * @p CH_USE_REGISTRY is enabled else no action is performed.
+ *
+ * @param[in] tname thread name as a zero terminated string
+ *
+ * @api
+ */
+ static void setName(const char *tname) {
+
+ chRegSetThreadName(tname);
+ }
+
+ /**
+ * @brief Changes the running thread priority level then reschedules if
+ * necessary.
+ * @note The function returns the real thread priority regardless of the
+ * current priority that could be higher than the real priority
+ * because the priority inheritance mechanism.
+ *
+ * @param[in] newprio the new priority level of the running thread
+ * @return The old priority level.
+ *
+ * @api
+ */
+ static tprio_t setPriority(tprio_t newprio) {
+
+ return chThdSetPriority(newprio);
+ }
+
+ /**
+ * @brief Returns the current thread priority.
+ * @note Can be invoked in any context.
+ *
+ * @return The current thread priority.
+ *
+ * @xclass
+ */
+ static tprio_t getPriorityX(void) {
+
+ return chThdGetPriorityX();
+ }
+
+ /**
+ * @brief Terminates the current thread.
+ * @details The thread goes in the @p THD_STATE_FINAL state holding the
+ * specified exit status code, other threads can retrieve the
+ * exit status code by invoking the function @p chThdWait().
+ * @post Eventual code after this function will never be executed,
+ * this function never returns. The compiler has no way to
+ * know this so do not assume that the compiler would remove
+ * the dead code.
+ *
+ * @param[in] msg thread exit code
+ *
+ * @api
+ */
+ static void exit(msg_t msg) {
+
+ chThdExit(msg);
+ }
+
+ /**
+ * @brief Terminates the current thread.
+ * @details The thread goes in the @p THD_STATE_FINAL state holding the
+ * specified exit status code, other threads can retrieve the
+ * exit status code by invoking the function @p chThdWait().
+ * @post Eventual code after this function will never be executed,
+ * this function never returns. The compiler has no way to
+ * know this so do not assume that the compiler would remove
+ * the dead code.
+ *
+ * @param[in] msg thread exit code
+ *
+ * @sclass
+ */
+ static void exitS(msg_t msg) {
+
+ chThdExitS(msg);
+ }
+
+ /**
+ * @brief Verifies if the current thread has a termination request
+ * pending.
+ * @note Can be invoked in any context.
+ *
+ * @retval TRUE termination request pending.
+ * @retval FALSE termination request not pending.
+ *
+ * @special
+ */
+ static bool shouldTerminate(void) {
+
+ return chThdShouldTerminateX();
+ }
+
+ /**
+ * @brief Suspends the invoking thread for the specified time.
+ *
+ * @param[in] interval the delay in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE the thread enters an infinite
+ * sleep state.
+ * - @a TIME_IMMEDIATE this value is not allowed.
+ * .
+ *
+ * @api
+ */
+ static void sleep(sysinterval_t interval) {
+
+ chThdSleep(interval);
+ }
+
+ /**
+ * @brief Suspends the invoking thread until the system time arrives to
+ * the specified value.
+ *
+ * @param[in] time absolute system time
+ *
+ * @api
+ */
+ static void sleepUntil(systime_t time) {
+
+ chThdSleepUntil(time);
+ }
+
+ /**
+ * @brief Suspends the invoking thread until the system time arrives to the
+ * specified value.
+ * @note The system time is assumed to be between @p prev and @p time
+ * else the call is assumed to have been called outside the
+ * allowed time interval, in this case no sleep is performed.
+ * @see chThdSleepUntil()
+ *
+ * @param[in] prev absolute system time of the previous deadline
+ * @param[in] next absolute system time of the next deadline
+ * @return the @p next parameter
+ *
+ * @api
+ */
+ static systime_t sleepUntilWindowed(systime_t prev, systime_t next) {
+
+ return chThdSleepUntilWindowed(prev, next);
+ }
+
+ /**
+ * @brief Yields the time slot.
+ * @details Yields the CPU control to the next thread in the ready list
+ * with equal priority, if any.
+ *
+ * @api
+ */
+ static void yield(void) {
+
+ chThdYield();
+ }
+
+#if CH_CFG_USE_MESSAGES || defined(__DOXYGEN__)
+ /**
+ * @brief Waits for a message.
+ * @post On the returned reference it is mandatory to call
+ * @p releaseMessage() or the sender thread would be waiting
+ * undefinitely.
+ *
+ * @return The sender thread reference.
+ *
+ * @api
+ */
+ static ThreadReference waitMessage(void) {
+
+ return ThreadReference(chMsgWait());
+ }
+#endif /* CH_CFG_USE_MESSAGES == TRUE */
+
+#if CH_CFG_USE_EVENTS || defined(__DOXYGEN__)
+ /**
+ * @brief Clears the pending events specified in the mask.
+ *
+ * @param[in] mask the events to be cleared
+ * @return The pending events that were cleared.
+ *
+ * @api
+ */
+ static eventmask_t getAndClearEvents(eventmask_t mask) {
+
+ return chEvtGetAndClearEvents(mask);
+ }
+
+ /**
+ * @brief Adds (OR) a set of event flags on the current thread, this is
+ * @b much faster than using @p chEvtBroadcast() or
+ * @p chEvtSignal().
+ *
+ * @param[in] mask the event flags to be added
+ * @return The current pending events mask.
+ *
+ * @api
+ */
+ static eventmask_t addEvents(eventmask_t mask) {
+
+ return chEvtAddEvents(mask);
+ }
+
+ /**
+ * @brief Waits for a single event.
+ * @details A pending event among those specified in @p ewmask is selected,
+ * cleared and its mask returned.
+ * @note One and only one event is served in the function, the one with
+ * the lowest event id. The function is meant to be invoked into
+ * a loop in order to serve all the pending events.
+ * This means that Event Listeners with a lower event identifier
+ * have an higher priority.
+ *
+ * @param[in] ewmask mask of the events that the function should
+ * wait for, @p ALL_EVENTS enables all the events
+ * @return The mask of the lowest id served and cleared
+ * event.
+ *
+ * @api
+ */
+ static eventmask_t waitOneEvent(eventmask_t ewmask) {
+
+ return chEvtWaitOne(ewmask);
+ }
+
+ /**
+ * @brief Waits for any of the specified events.
+ * @details The function waits for any event among those specified in
+ * @p ewmask to become pending then the events are cleared and
+ * returned.
+ *
+ * @param[in] ewmask mask of the events that the function should
+ * wait for, @p ALL_EVENTS enables all the events
+ * @return The mask of the served and cleared events.
+ *
+ * @api
+ */
+ static eventmask_t waitAnyEvent(eventmask_t ewmask) {
+
+ return chEvtWaitAny(ewmask);
+ }
+
+ /**
+ * @brief Waits for all the specified event flags then clears them.
+ * @details The function waits for all the events specified in @p ewmask
+ * to become pending then the events are cleared and returned.
+ *
+ * @param[in] ewmask mask of the event ids that the function should
+ * wait for
+ * @return The mask of the served and cleared events.
+ *
+ * @api
+ */
+ static eventmask_t waitAllEvents(eventmask_t ewmask) {
+
+ return chEvtWaitAll(ewmask);
+ }
+
+#if CH_CFG_USE_EVENTS_TIMEOUT || defined(__DOXYGEN__)
+ /**
+ * @brief Waits for a single event.
+ * @details A pending event among those specified in @p ewmask is selected,
+ * cleared and its mask returned.
+ * @note One and only one event is served in the function, the one with
+ * the lowest event id. The function is meant to be invoked into
+ * a loop in order to serve all the pending events.
+ * This means that Event Listeners with a lower event identifier
+ * have an higher priority.
+ *
+ * @param[in] ewmask mask of the events that the function should
+ * wait for, @p ALL_EVENTS enables all the events
+ *
+ * @param[in] timeout the number of ticks before the operation
+ * timouts
+ * @return The mask of the lowest id served and cleared
+ * event.
+ * @retval 0 if the specified timeout expired.
+ *
+ * @api
+ */
+ static eventmask_t waitOneEventTimeout(eventmask_t ewmask,
+ sysinterval_t timeout) {
+
+ return chEvtWaitOneTimeout(ewmask, timeout);
+ }
+
+ /**
+ * @brief Waits for any of the specified events.
+ * @details The function waits for any event among those specified in
+ * @p ewmask to become pending then the events are cleared and
+ * returned.
+ *
+ * @param[in] ewmask mask of the events that the function should
+ * wait for, @p ALL_EVENTS enables all the events
+ * @param[in] timeout the number of ticks before the operation
+ * timouts
+ * @return The mask of the served and cleared events.
+ * @retval 0 if the specified timeout expired.
+ *
+ * @api
+ */
+ static eventmask_t waitAnyEventTimeout(eventmask_t ewmask,
+ sysinterval_t timeout) {
+
+ return chEvtWaitAnyTimeout(ewmask, timeout);
+ }
+
+ /**
+ * @brief Waits for all the specified event flags then clears them.
+ * @details The function waits for all the events specified in @p ewmask
+ * to become pending then the events are cleared and returned.
+ *
+ * @param[in] ewmask mask of the event ids that the function should
+ * wait for
+ * @param[in] timeout the number of ticks before the operation
+ * timouts
+ * @return The mask of the served and cleared events.
+ * @retval 0 if the specified timeout expired.
+ *
+ * @api
+ */
+ static eventmask_t waitAllEventsTimeout(eventmask_t ewmask,
+ sysinterval_t timeout) {
+
+ return chEvtWaitAllTimeout(ewmask, timeout);
+ }
+#endif /* CH_CFG_USE_EVENTS_TIMEOUT == TRUE */
+
+ /**
+ * @brief Invokes the event handlers associated to an event flags mask.
+ *
+ * @param[in] mask mask of the event flags to be dispatched
+ * @param[in] handlers an array of @p evhandler_t. The array must have
+ * size equal to the number of bits in eventmask_t.
+ *
+ * @api
+ */
+ static void dispatchEvents(const evhandler_t handlers[],
+ eventmask_t mask) {
+
+ chEvtDispatch(handlers, mask);
+ }
+#endif /* CH_CFG_USE_EVENTS == TRUE */
+
+#if CH_CFG_USE_MUTEXES || defined(__DOXYGEN__)
+ /**
+ * @brief Unlocks all the mutexes owned by the invoking thread.
+ * @post The stack of owned mutexes is emptied and all the found
+ * mutexes are unlocked.
+ * @note This function is MUCH MORE efficient than releasing the
+ * mutexes one by one and not just because the call overhead,
+ * this function does not have any overhead related to the
+ * priority inheritance mechanism.
+ *
+ * @api
+ */
+ static void unlockAllMutexes(void) {
+
+ chMtxUnlockAll();
+ }
+#endif /* CH_CFG_USE_MUTEXES == TRUE */
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::BaseStaticThread *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Static threads template base class.
+ * @details This class introduces static working area instantiation.
+ *
+ * @param N the working area size for the thread class
+ */
+ template
+ class BaseStaticThread : public BaseThread {
+ protected:
+ THD_WORKING_AREA(wa, N);
+
+ public:
+ /**
+ * @brief Starts a static thread.
+ *
+ * @param[in] prio thread priority
+ * @return A reference to the created thread with
+ * reference counter set to one.
+ *
+ * @api
+ */
+ ThreadReference start(tprio_t prio) override {
+ void _thd_start(void *arg);
+
+ return ThreadReference(chThdCreateStatic(wa, sizeof(wa), prio,
+ _thd_start, this));
+ }
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::BaseDynamicThread *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Dynamic threads base class.
+ */
+ class BaseDynamicThread : public BaseThread {
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::ThreadStayPoint *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Thread suspension point class.
+ * @details This class encapsulates a reference to a suspended thread.
+ */
+ class ThreadStayPoint {
+ /**
+ * @brief Pointer to the suspended thread.
+ */
+ thread_reference_t thread_ref = nullptr;
+
+ public:
+ /**
+ * @brief Thread stay point constructor.
+ *
+ * @init
+ */
+ ThreadStayPoint() {
+
+ }
+
+ /* Prohibit copy construction and assignment.*/
+ ThreadStayPoint(const ThreadStayPoint &) = delete;
+ ThreadStayPoint &operator=(const ThreadStayPoint &) = delete;
+
+ /**
+ * @brief Suspends the current thread on the stay point.
+ * @details The suspended thread becomes the referenced thread. It is
+ * possible to use this method only if the thread reference
+ * was set to @p nullptr.
+ *
+ * @return The incoming message.
+ *
+ * @sclass
+ */
+ msg_t suspendS(void) {
+
+ return chThdSuspendS(&thread_ref);
+ }
+
+ /**
+ * @brief Suspends the current thread on the stay point with timeout.
+ * @details The suspended thread becomes the referenced thread. It is
+ * possible to use this method only if the thread reference
+ * was set to @p nullptr.
+ *
+ *
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A message specifying how the invoking thread has
+ * been released from the semaphore.
+ * @retval MSG_OK if the binary semaphore has been successfully
+ * taken.
+ * @retval MSG_RESET if the binary semaphore has been reset using
+ * @p bsemReset().
+ * @retval MSG_TIMEOUT if the binary semaphore has not been signaled
+ * or reset within the specified timeout.
+ *
+ * @sclass
+ */
+ msg_t suspendS(sysinterval_t timeout) {
+
+ return chThdSuspendTimeoutS(&thread_ref, timeout);
+ }
+
+ /**
+ * @brief Resumes the currently referenced thread, if any.
+ *
+ * @param[in] msg the wakeup message
+ *
+ * @iclass
+ */
+ void resumeI(msg_t msg) {
+
+ chThdResumeI(&thread_ref, msg);
+ }
+
+ /**
+ * @brief Resumes the currently referenced thread, if any.
+ *
+ * @param[in] msg the wakeup message
+ *
+ * @sclass
+ */
+ void resumeS(msg_t msg) {
+
+ chThdResumeS(&thread_ref, msg);
+ }
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::SynchronizationObject *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Base class for all synchronization objects.
+ * @note No other uses.
+ */
+ class SynchronizationObject {
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::ThreadsQueue *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Threads queue class.
+ * @details This class encapsulates a queue of threads.
+ */
+ class ThreadsQueue : public SynchronizationObject {
+ /**
+ * @brief Pointer to the system thread.
+ */
+ threads_queue_t threads_queue;
+
+ public:
+ /**
+ * @brief Threads queue constructor.
+ *
+ * @init
+ */
+ ThreadsQueue() {
+
+ chThdQueueObjectInit(&threads_queue);
+ }
+
+ /* Prohibit copy construction and assignment.*/
+ ThreadsQueue(const ThreadsQueue &) = delete;
+ ThreadsQueue &operator=(const ThreadsQueue &) = delete;
+
+ /**
+ * @brief Enqueues the caller thread on a threads queue object.
+ * @details The caller thread is enqueued and put to sleep until it is
+ * dequeued or the specified timeouts expires.
+ *
+ * @param[in] timeout the timeout in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE the thread enters an infinite sleep
+ * state.
+ * - @a TIME_IMMEDIATE the thread is not enqueued and
+ * the function returns @p MSG_TIMEOUT as if a timeout
+ * occurred.
+ * .
+ * @return The message from @p osalQueueWakeupOneI() or
+ * @p osalQueueWakeupAllI() functions.
+ * @retval MSG_TIMEOUT if the thread has not been dequeued within the
+ * specified timeout or if the function has been
+ * invoked with @p TIME_IMMEDIATE as timeout
+ * specification.
+ *
+ * @sclass
+ */
+ msg_t enqueueSelfS(sysinterval_t timeout) {
+
+ return chThdEnqueueTimeoutS(&threads_queue, timeout);
+ }
+
+ /**
+ * @brief Dequeues and wakes up one thread from the threads queue object,
+ * if any.
+ *
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+ void dequeueNextI(msg_t msg) {
+
+ chThdDequeueNextI(&threads_queue, msg);
+ }
+
+ /**
+ * @brief Dequeues and wakes up all threads from the threads queue object.
+ *
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+ void chdequeueAllI(msg_t msg) {
+
+ chThdDequeueAllI(&threads_queue, msg);
+ }
+};
+
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+ /*------------------------------------------------------------------------*
+ * chibios_rt::CounterSemaphore *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating a semaphore.
+ */
+ class CounterSemaphore : public SynchronizationObject {
+ /**
+ * @brief Embedded @p semaphore_t structure.
+ */
+ semaphore_t sem;
+
+ public:
+ /**
+ * @brief CounterSemaphore constructor.
+ * @details The embedded @p Semaphore structure is initialized.
+ *
+ * @param[in] n the semaphore counter value, must be greater
+ * or equal to zero
+ *
+ * @init
+ */
+ CounterSemaphore(cnt_t n) {
+
+ chSemObjectInit(&sem, n);
+ }
+
+ /**
+ * @brief Performs a reset operation on the semaphore.
+ * @post After invoking this function all the threads waiting on the
+ * semaphore, if any, are released and the semaphore counter is
+ * set to the specified, non negative, value.
+ * @note The released threads can recognize they were waked up by a
+ * reset rather than a signal because the @p chSemWait() will
+ * return @p MSG_RESET instead of @p MSG_OK.
+ *
+ * @param[in] n the new value of the semaphore counter. The value
+ * must be non-negative.
+ *
+ * @api
+ */
+ void reset(cnt_t n) {
+
+ chSemReset(&sem, n);
+ }
+
+ /**
+ * @brief Performs a reset operation on the semaphore.
+ * @post After invoking this function all the threads waiting on the
+ * semaphore, if any, are released and the semaphore counter is
+ * set to the specified, non negative, value.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note
+ * that interrupt handlers always reschedule on exit so an
+ * explicit reschedule must not be performed in ISRs.
+ * @note The released threads can recognize they were waked up by a
+ * reset rather than a signal because the @p chSemWait() will
+ * return @p MSG_RESET instead of @p MSG_OK.
+ *
+ * @param[in] n the new value of the semaphore counter. The value
+ * must be non-negative.
+ *
+ * @iclass
+ */
+ void resetI(cnt_t n) {
+
+ chSemResetI(&sem, n);
+ }
+
+ /**
+ * @brief Performs a wait operation on a semaphore.
+ *
+ * @return A message specifying how the invoking thread has
+ * been released from the semaphore.
+ * @retval MSG_OK if the thread has not stopped on the semaphore or
+ * the semaphore has been signaled.
+ * @retval MSG_RESET if the semaphore has been reset using
+ * @p chSemReset().
+ *
+ * @api
+ */
+ msg_t wait(void) {
+
+ return chSemWait(&sem);
+ }
+
+ /**
+ * @brief Performs a wait operation on a semaphore.
+ *
+ * @return A message specifying how the invoking thread has
+ * been released from the semaphore.
+ * @retval MSG_OK if the thread has not stopped on the semaphore or
+ * the semaphore has been signaled.
+ * @retval MSG_RESET if the semaphore has been reset using
+ * @p chSemReset().
+ *
+ * @sclass
+ */
+ msg_t waitS(void) {
+
+ return chSemWaitS(&sem);
+ }
+
+ /**
+ * @brief Performs a wait operation on a semaphore with timeout
+ * specification.
+ *
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A message specifying how the invoking thread has
+ * been released from the semaphore.
+ * @retval MSG_OK if the thread has not stopped on the semaphore or
+ * the semaphore has been signaled.
+ * @retval MSG_RESET if the semaphore has been reset using
+ * @p chSemReset().
+ * @retval MSG_TIMEOUT if the semaphore has not been signaled or reset
+ * within the specified timeout.
+ *
+ * @api
+ */
+ msg_t wait(sysinterval_t timeout) {
+
+ return chSemWaitTimeout(&sem, timeout);
+ }
+
+ /**
+ * @brief Performs a wait operation on a semaphore with timeout
+ * specification.
+ *
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A message specifying how the invoking thread has
+ * been released from the semaphore.
+ * @retval MSG_OK if the thread has not stopped on the semaphore or
+ * the semaphore has been signaled.
+ * @retval MSG_RESET if the semaphore has been reset using
+ * @p chSemReset().
+ * @retval MSG_TIMEOUT if the semaphore has not been signaled or reset
+ * within the specified timeout.
+ *
+ * @sclass
+ */
+ msg_t waitS(sysinterval_t timeout) {
+
+ return chSemWaitTimeoutS(&sem, timeout);
+ }
+
+ /**
+ * @brief Performs a signal operation on a semaphore.
+ *
+ * @api
+ */
+ void signal(void) {
+
+ chSemSignal(&sem);
+ }
+
+ /**
+ * @brief Performs a signal operation on a semaphore.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note
+ * that interrupt handlers always reschedule on exit so an
+ * explicit reschedule must not be performed in ISRs.
+ *
+ * @iclass
+ */
+ void signalI(void) {
+
+ chSemSignalI(&sem);
+ }
+
+ /**
+ * @brief Adds the specified value to the semaphore counter.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note
+ * that interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] n value to be added to the semaphore counter. The
+ * value must be positive.
+ *
+ * @iclass
+ */
+ void addCounterI(cnt_t n) {
+
+ chSemAddCounterI(&sem, n);
+ }
+
+ /**
+ * @brief Returns the semaphore counter value.
+ *
+ * @return The semaphore counter value.
+ *
+ * @iclass
+ */
+ cnt_t getCounterI(void) const {
+
+ return chSemGetCounterI(&sem);
+ }
+
+ /**
+ * @brief Atomic signal and wait operations.
+ *
+ * @param[in] ssem @p Semaphore object to be signaled
+ * @param[in] wsem @p Semaphore object to wait on
+ * @return A message specifying how the invoking thread
+ * has been released from the semaphore.
+ * @retval MSG_OK if the thread has not stopped on the semaphore
+ * or the semaphore has been signaled.
+ * @retval MSG_RESET if the semaphore has been reset using
+ * @p chSemReset().
+ *
+ * @api
+ */
+ static msg_t signalWait(CounterSemaphore *ssem,
+ CounterSemaphore *wsem) {
+
+ return chSemSignalWait(&ssem->sem, &wsem->sem);
+ }
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::BinarySemaphore *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating a binary semaphore.
+ */
+ class BinarySemaphore : public SynchronizationObject {
+ /**
+ * @brief Embedded @p binary_semaphore_t structure.
+ */
+ binary_semaphore_t bsem;
+
+ public:
+ /**
+ * @brief BinarySemaphore constructor.
+ * @details The embedded @p ::BinarySemaphore structure is initialized.
+ *
+ * @param[in] taken initial state of the binary semaphore:
+ * - @a false, the initial state is not taken.
+ * - @a true, the initial state is taken.
+ * .
+ *
+ * @init
+ */
+ BinarySemaphore(bool taken) {
+
+ chBSemObjectInit(&bsem, taken);
+ }
+
+ /**
+ * @brief Wait operation on the binary semaphore.
+ *
+ * @return A message specifying how the invoking thread has
+ * been released from the semaphore.
+ * @retval MSG_OK if the binary semaphore has been successfully
+ * taken.
+ * @retval MSG_RESET if the binary semaphore has been reset using
+ * @p bsemReset().
+ *
+ * @api
+ */
+ msg_t wait(void) {
+
+ return chBSemWait(&bsem);
+ }
+
+ /**
+ * @brief Wait operation on the binary semaphore.
+ *
+ * @return A message specifying how the invoking thread has
+ * been released from the semaphore.
+ * @retval MSG_OK if the binary semaphore has been successfully
+ * taken.
+ * @retval MSG_RESET if the binary semaphore has been reset using
+ * @p bsemReset().
+ *
+ * @sclass
+ */
+ msg_t waitS(void) {
+
+ return chBSemWaitS(&bsem);
+ }
+
+ /**
+ * @brief Wait operation on the binary semaphore.
+ *
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A message specifying how the invoking thread has
+ * been released from the semaphore.
+ * @retval MSG_OK if the binary semaphore has been successfully
+ * taken.
+ * @retval MSG_RESET if the binary semaphore has been reset using
+ * @p bsemReset().
+ * @retval MSG_TIMEOUT if the binary semaphore has not been signaled
+ * or reset within the specified timeout.
+ *
+ * @api
+ */
+ msg_t wait(sysinterval_t timeout) {
+
+ return chBSemWaitTimeout(&bsem, timeout);
+ }
+
+ /**
+ * @brief Wait operation on the binary semaphore.
+ *
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A message specifying how the invoking thread has
+ * been released from the semaphore.
+ * @retval MSG_OK if the binary semaphore has been successfully
+ * taken.
+ * @retval MSG_RESET if the binary semaphore has been reset using
+ * @p bsemReset().
+ * @retval MSG_TIMEOUT if the binary semaphore has not been signaled
+ * or reset within the specified timeout.
+ *
+ * @sclass
+ */
+ msg_t waitS(sysinterval_t timeout) {
+
+ return chBSemWaitTimeoutS(&bsem, timeout);
+ }
+
+ /**
+ * @brief Reset operation on the binary semaphore.
+ * @note The released threads can recognize they were waked up by a
+ * reset rather than a signal because the @p bsemWait() will
+ * return @p MSG_RESET instead of @p MSG_OK.
+ *
+ * @param[in] taken new state of the binary semaphore
+ * - @a FALSE, the new state is not taken.
+ * - @a TRUE, the new state is taken.
+ * .
+ *
+ * @api
+ */
+ void reset(bool taken) {
+
+ chBSemReset(&bsem, taken);
+ }
+
+ /**
+ * @brief Reset operation on the binary semaphore.
+ * @note The released threads can recognize they were waked up by a
+ * reset rather than a signal because the @p bsemWait() will
+ * return @p MSG_RESET instead of @p MSG_OK.
+ * @note This function does not reschedule.
+ *
+ * @param[in] taken new state of the binary semaphore
+ * - @a FALSE, the new state is not taken.
+ * - @a TRUE, the new state is taken.
+ * .
+ *
+ * @iclass
+ */
+ void resetI(bool taken) {
+
+ chBSemResetI(&bsem, taken);
+ }
+
+ /**
+ * @brief Performs a signal operation on a binary semaphore.
+ *
+ * @api
+ */
+ void signal(void) {
+
+ chBSemSignal(&bsem);
+ }
+
+ /**
+ * @brief Performs a signal operation on a binary semaphore.
+ * @note This function does not reschedule.
+ *
+ * @iclass
+ */
+ void signalI(void) {
+
+ chBSemSignalI(&bsem);
+ }
+
+ /**
+ * @brief Returns the binary semaphore current state.
+ *
+ * @return The binary semaphore current state.
+ * @retval false if the binary semaphore is not taken.
+ * @retval true if the binary semaphore is taken.
+ *
+ * @iclass
+ */
+ bool getStateI(void) const {
+
+ return (bool)chBSemGetStateI(&bsem);
+ }
+};
+#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
+
+#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__)
+ /*------------------------------------------------------------------------*
+ * chibios_rt::Mutex *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating a mutex.
+ */
+ class Mutex : public SynchronizationObject {
+ /**
+ * @brief Embedded @p mutex_t structure.
+ */
+ mutex_t mutex;
+
+ public:
+ /**
+ * @brief Mutex object constructor.
+ * @details The embedded @p mutex_t structure is initialized.
+ *
+ * @init
+ */
+ Mutex(void) {
+
+ chMtxObjectInit(&mutex);
+ }
+
+ /**
+ * @brief Tries to lock a mutex.
+ * @details This function attempts to lock a mutex, if the mutex is already
+ * locked by another thread then the function exits without
+ * waiting.
+ * @post The mutex is locked and inserted in the per-thread stack of
+ * owned mutexes.
+ * @note This function does not have any overhead related to the
+ * priority inheritance mechanism because it does not try to
+ * enter a sleep state.
+ *
+ * @return The operation status.
+ * @retval TRUE if the mutex has been successfully acquired
+ * @retval FALSE if the lock attempt failed.
+ *
+ * @api
+ */
+ bool tryLock(void) {
+
+ return chMtxTryLock(&mutex);
+ }
+
+ /**
+ * @brief Tries to lock a mutex.
+ * @details This function attempts to lock a mutex, if the mutex is already
+ * taken by another thread then the function exits without
+ * waiting.
+ * @post The mutex is locked and inserted in the per-thread stack of
+ * owned mutexes.
+ * @note This function does not have any overhead related to the
+ * priority inheritance mechanism because it does not try to
+ * enter a sleep state.
+ *
+ * @return The operation status.
+ * @retval TRUE if the mutex has been successfully acquired
+ * @retval FALSE if the lock attempt failed.
+ *
+ * @sclass
+ */
+ bool tryLockS(void) {
+
+ return chMtxTryLockS(&mutex);
+ }
+
+ /**
+ * @brief Locks the specified mutex.
+ * @post The mutex is locked and inserted in the per-thread stack of
+ * owned mutexes.
+ *
+ * @api
+ */
+ void lock(void) {
+
+ chMtxLock(&mutex);
+ }
+
+ /**
+ * @brief Locks the specified mutex.
+ * @post The mutex is locked and inserted in the per-thread stack of
+ * owned mutexes.
+ *
+ * @sclass
+ */
+ void lockS(void) {
+
+ chMtxLockS(&mutex);
+ }
+
+ /**
+ * @brief Unlocks the next owned mutex in reverse lock order.
+ * @pre The invoking thread must have at least one owned mutex.
+ * @post The mutex is unlocked and removed from the per-thread stack of
+ * owned mutexes.
+ *
+ * @api
+ */
+ void unlock(void) {
+
+ chMtxUnlock(&mutex);
+ }
+
+ /**
+ * @brief Unlocks the next owned mutex in reverse lock order.
+ * @pre The invoking thread must have at least one owned mutex.
+ * @post The mutex is unlocked and removed from the per-thread stack of
+ * owned mutexes.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel.
+ *
+ * @sclass
+ */
+ void unlockS(void) {
+
+ chMtxUnlockS(&mutex);
+ }
+
+ /**
+ * @brief Unlocks the next owned mutex in reverse lock order.
+ * @pre The invoking thread must have at least one owned mutex.
+ * @post The mutex is unlocked and removed from the per-thread stack of
+ * owned mutexes.
+ *
+ * @return A pointer to the unlocked mutex.
+ *
+ * @api
+ */
+ void unlockMutex(void) {
+
+ chMtxUnlock(&mutex);
+ }
+
+ /**
+ * @brief Unlocks the next owned mutex in reverse lock order.
+ * @pre The invoking thread must have at least one owned mutex.
+ * @post The mutex is unlocked and removed from the per-thread stack of
+ * owned mutexes.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel.
+ *
+ * @return A pointer to the unlocked mutex.
+ *
+ * @sclass
+ */
+ void unlockMutexS(void) {
+
+ chMtxUnlockS(&mutex);
+ }
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::MutexLocker *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief RAII helper for mutexes.
+ */
+ class MutexLocker
+ {
+ Mutex& mutex;
+
+ public:
+ MutexLocker(Mutex& m) : mutex(m) {
+
+ mutex.lock();
+ }
+
+ ~MutexLocker() {
+
+ mutex.unlock();
+ }
+ };
+
+#if (CH_CFG_USE_CONDVARS == TRUE) || defined(__DOXYGEN__)
+ /*------------------------------------------------------------------------*
+ * chibios_rt::Monitor *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Template class to be used for implementing a monitor.
+ */
+ template
+ class Monitor: protected Mutex {
+ condition_variable_t condvars[N];
+
+ protected:
+ /**
+ * @brief Waits on the condition variable releasing the mutex lock.
+ *
+ * @param[in] var the condition variable index
+ * @return A message specifying how the invoking thread has
+ * been released from the condition variable.
+ * @retval MSG_OK if the condition variable has been signaled using
+ * @p signal().
+ * @retval MSG_RESET if the condition variable has been signaled using
+ * @p broadcast().
+ *
+ * @api
+ */
+ msg_t wait(unsigned var) {
+
+ chDbgCheck(var < N);
+
+ return chCondWait(&condvars[var]);
+ }
+
+ /**
+ * @brief Waits on the condition variable releasing the mutex lock.
+ *
+ * @param[in] var the condition variable index
+ * @return A message specifying how the invoking thread has
+ * been released from the condition variable.
+ * @retval MSG_OK if the condition variable has been signaled using
+ * @p signal().
+ * @retval MSG_RESET if the condition variable has been signaled using
+ * @p broadcast().
+ *
+ * @sclass
+ */
+ msg_t waitS(unsigned var) {
+
+ chDbgCheck(var < N);
+
+ return chCondWaitS(&condvars[var]);
+ }
+
+#if (CH_CFG_USE_CONDVARS_TIMEOUT == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Waits on the CondVar while releasing the controlling mutex.
+ *
+ * @param[in] var the condition variable index
+ * @param[in] timeout the number of ticks before the operation fails
+ * @return The wakep mode.
+ * @retval MSG_OK if the condition variable was signaled using
+ * @p signal().
+ * @retval MSG_RESET if the condition variable was signaled using
+ * @p broadcast().
+ * @retval MSG_TIMEOUT if the condition variable was not signaled
+ * within the specified timeout.
+ *
+ * @api
+ */
+ msg_t wait(unsigned var, sysinterval_t timeout) {
+
+ chDbgCheck(var < N);
+
+ return chCondWaitTimeout(&condvars[var], timeout);
+ }
+
+ /**
+ * @brief Waits on the CondVar while releasing the controlling mutex.
+ *
+ * @param[in] var the condition variable index
+ * @param[in] timeout the number of ticks before the operation fails
+ * @return The wakep mode.
+ * @retval MSG_OK if the condition variable was signaled using
+ * @p signal().
+ * @retval MSG_RESET if the condition variable was signaled using
+ * @p broadcast().
+ * @retval MSG_TIMEOUT if the condition variable was not signaled
+ * within the specified timeout.
+ *
+ * @sclass
+ */
+ msg_t waitS(unsigned var, sysinterval_t timeout) {
+
+ chDbgCheck(var < N);
+
+ return chCondWaitTimeoutS(&condvars[var], timeout);
+ }
+#endif /* CH_CFG_USE_CONDVARS_TIMEOUT == TRUE */
+
+ public:
+ /**
+ * @brief Monitor object constructor.
+ *
+ * @init
+ */
+ Monitor(void) : Mutex() {
+
+ for (unsigned i = 0; i < N; i++) {
+ chCondObjectInit(&condvars[i]);
+ }
+ }
+
+ /**
+ * @brief Signals one thread that is waiting on the condition variable.
+ *
+ * @param[in] var the condition variable index
+ *
+ * @api
+ */
+ void signal(unsigned var) {
+
+ chDbgCheck(var < N);
+
+ chCondSignal(&condvars[var]);
+ }
+
+ /**
+ * @brief Signals one thread that is waiting on the condition variable.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note
+ * that interrupt handlers always reschedule on exit so an
+ * explicit reschedule must not be performed in ISRs.
+ *
+ * @param[in] var the condition variable index
+ *
+ * @iclass
+ */
+ void signalI(unsigned var) {
+
+ chDbgCheck(var < N);
+
+ chCondSignalI(&condvars[var]);
+ }
+
+ /**
+ * @brief Signals all threads that are waiting on the condition variable.
+ *
+ * @param[in] var the condition variable index
+ *
+ * @api
+ */
+ void broadcast(unsigned var) {
+
+ chDbgCheck(var < N);
+
+ chCondBroadcast(&condvars[var]);
+ }
+
+ /**
+ * @brief Signals all threads that are waiting on the condition variable.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note
+ * that interrupt handlers always reschedule on exit so an
+ * explicit reschedule must not be performed in ISRs.
+ *
+ * @param[in] var the condition variable index
+ *
+ * @iclass
+ */
+ void broadcastI(unsigned var) {
+
+ chDbgCheck(var < N);
+
+ chCondBroadcastI(&condvars[var]);
+ }
+ };
+
+#endif /* CH_CFG_USE_CONDVARS == TRUE */
+#endif /* CH_CFG_USE_MUTEXES == TRUE */
+
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+ /*------------------------------------------------------------------------*
+ * chibios_rt::EvtListener *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating an event listener.
+ */
+ class EventListener {
+ public:
+ /**
+ * @brief Embedded @p event_listener_t structure.
+ */
+ event_listener_t ev_listener;
+
+ /**
+ * @brief Returns the pending flags from the listener and clears them.
+ *
+ * @return The flags added to the listener by the
+ * associated event source.
+ *
+ * @api
+ */
+ eventflags_t getAndClearFlags(void) {
+
+ return chEvtGetAndClearFlags(&ev_listener);
+ }
+
+ /**
+ * @brief Returns the flags associated to an @p event_listener_t.
+ * @details The flags are returned and the @p event_listener_t flags mask is
+ * cleared.
+ *
+ * @return The flags added to the listener by the associated
+ * event source.
+ *
+ * @iclass
+ */
+ eventflags_t getAndClearFlagsI(void) {
+
+ return chEvtGetAndClearFlagsI(&ev_listener);
+ }
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::EvtSource *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating an event source.
+ */
+ class EventSource {
+ /**
+ * @brief Embedded @p event_source_t structure.
+ */
+ event_source_t ev_source;
+
+ public:
+ /**
+ * @brief EvtSource object constructor.
+ * @details The embedded @p event_source_t structure is initialized.
+ *
+ * @init
+ */
+ EventSource(void) {
+
+ chEvtObjectInit(&ev_source);
+ }
+
+ /**
+ * @brief Registers a listener on the event source.
+ *
+ * @param[in] elp pointer to the @p EvtListener object
+ * @param[in] eid numeric identifier assigned to the Event
+ * Listener
+ *
+ * @api
+ */
+ void registerOne(EventListener *elp,
+ eventid_t eid) {
+
+ chEvtRegister(&ev_source, &elp->ev_listener, eid);
+ }
+
+ /**
+ * @brief Registers an Event Listener on an Event Source.
+ * @note Multiple Event Listeners can specify the same bits to be added.
+ *
+ * @param[in] elp pointer to the @p EvtListener object
+ * @param[in] emask the mask of event flags to be pended to the
+ * thread when the event source is broadcasted
+ *
+ * @api
+ */
+ void registerMask(EventListener *elp,
+ eventmask_t emask) {
+
+ chEvtRegisterMask(&ev_source, &elp->ev_listener, emask);
+ }
+
+ /**
+ * @brief Unregisters a listener.
+ * @details The specified listeners is no more signaled by the event
+ * source.
+ *
+ * @param[in] elp the listener to be unregistered
+ *
+ * @api
+ */
+ void unregister(EventListener *elp) {
+
+ chEvtUnregister(&ev_source, &elp->ev_listener);
+ }
+
+ /**
+ * @brief Broadcasts on an event source.
+ * @details All the listeners registered on the event source are signaled
+ * and the flags are added to the listener's flags mask.
+ *
+ * @param[in] flags the flags set to be added to the listener
+ * flags mask
+ *
+ * @api
+ */
+ void broadcastFlags(eventflags_t flags) {
+
+ chEvtBroadcastFlags(&ev_source, flags);
+ }
+
+ /**
+ * @brief Broadcasts on an event source.
+ * @details All the listeners registered on the event source are signaled
+ * and the flags are added to the listener's flags mask.
+ *
+ * @param[in] flags the flags set to be added to the listener
+ * flags mask
+ *
+ * @iclass
+ */
+ void broadcastFlagsI(eventflags_t flags) {
+
+ chEvtBroadcastFlagsI(&ev_source, flags);
+ }
+ };
+#endif /* CH_CFG_USE_EVENTS == TRUE */
+
+#if (CH_CFG_USE_MAILBOXES == TRUE) || defined(__DOXYGEN__)
+ /*------------------------------------------------------------------------*
+ * chibios_rt::Mailbox *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Base mailbox class.
+ *
+ * @param T type of objects that mailbox able to handle
+ */
+ template
+ class MailboxBase {
+
+ /**
+ * @brief Embedded @p mailbox_t structure.
+ */
+ mailbox_t mb;
+
+ public:
+ /**
+ * @brief Mailbox constructor.
+ * @details The embedded @p mailbox_t structure is initialized.
+ *
+ * @param[in] buf pointer to the messages buffer as an array of
+ * @p msg_t
+ * @param[in] n number of elements in the buffer array
+ *
+ * @init
+ */
+ MailboxBase(msg_t *buf, cnt_t n) {
+
+ chMBObjectInit(&mb, buf, n);
+ }
+
+ /**
+ * @brief Resets a Mailbox object.
+ * @details All the waiting threads are resumed with status @p MSG_RESET
+ * and the queued messages are lost.
+ *
+ * @api
+ */
+ void reset(void) {
+
+ chMBReset(&mb);
+ }
+
+ /**
+ * @brief Terminates the reset state.
+ *
+ * @xclass
+ */
+ void resumeX(void) {
+
+ chMBResumeX(&mb);
+ }
+
+ /**
+ * @brief Posts a message into a mailbox.
+ * @details The invoking thread waits until a empty slot in the mailbox
+ * becomes available or the specified time runs out.
+ *
+ * @param[in] msg the message to be posted on the mailbox
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if a message has been correctly posted.
+ * @retval MSG_RESET if the mailbox has been reset while waiting.
+ * @retval MSG_TIMEOUT if the operation has timed out.
+ *
+ * @api
+ */
+ msg_t post(T msg, sysinterval_t timeout) {
+
+ return chMBPostTimeout(&mb, reinterpret_cast(msg), timeout);
+ }
+
+ /**
+ * @brief Posts a message into a mailbox.
+ * @details The invoking thread waits until a empty slot in the mailbox
+ * becomes available or the specified time runs out.
+ *
+ * @param[in] msg the message to be posted on the mailbox
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if a message has been correctly posted.
+ * @retval MSG_RESET if the mailbox has been reset while waiting.
+ * @retval MSG_TIMEOUT if the operation has timed out.
+ *
+ * @sclass
+ */
+ msg_t postS(T msg, sysinterval_t timeout) {
+
+ return chMBPostTimeoutS(&mb, reinterpret_cast(msg), timeout);
+ }
+
+ /**
+ * @brief Posts a message into a mailbox.
+ * @details This variant is non-blocking, the function returns a timeout
+ * condition if the queue is full.
+ *
+ * @param[in] msg the message to be posted on the mailbox
+ * @return The operation status.
+ * @retval MSG_OK if a message has been correctly posted.
+ * @retval MSG_TIMEOUT if the mailbox is full and the message cannot be
+ * posted.
+ *
+ * @iclass
+ */
+ msg_t postI(T msg) {
+
+ return chMBPostI(&mb, reinterpret_cast(msg));
+ }
+
+ /**
+ * @brief Posts an high priority message into a mailbox.
+ * @details The invoking thread waits until a empty slot in the mailbox
+ * becomes available or the specified time runs out.
+ *
+ * @param[in] msg the message to be posted on the mailbox
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if a message has been correctly posted.
+ * @retval MSG_RESET if the mailbox has been reset while waiting.
+ * @retval MSG_TIMEOUT if the operation has timed out.
+ *
+ * @api
+ */
+ msg_t postAhead(T msg, sysinterval_t timeout) {
+
+ return chMBPostAheadTimeout(&mb, reinterpret_cast(msg), timeout);
+ }
+
+ /**
+ * @brief Posts an high priority message into a mailbox.
+ * @details The invoking thread waits until a empty slot in the mailbox
+ * becomes available or the specified time runs out.
+ *
+ * @param[in] msg the message to be posted on the mailbox
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if a message has been correctly posted.
+ * @retval MSG_RESET if the mailbox has been reset while waiting.
+ * @retval MSG_TIMEOUT if the operation has timed out.
+ *
+ * @sclass
+ */
+ msg_t postAheadS(T msg, sysinterval_t timeout) {
+
+ return chMBPostAheadTimeoutS(&mb, reinterpret_cast(msg), timeout);
+ }
+
+ /**
+ * @brief Posts an high priority message into a mailbox.
+ * @details This variant is non-blocking, the function returns a timeout
+ * condition if the queue is full.
+ *
+ * @param[in] msg the message to be posted on the mailbox
+ * @return The operation status.
+ * @retval MSG_OK if a message has been correctly posted.
+ * @retval MSG_TIMEOUT if the mailbox is full and the message cannot be
+ * posted.
+ *
+ * @iclass
+ */
+ msg_t postAheadI(T msg) {
+
+ return chMBPostAheadI(&mb, reinterpret_cast(msg));
+ }
+
+ /**
+ * @brief Retrieves a message from a mailbox.
+ * @details The invoking thread waits until a message is posted in the
+ * mailbox or the specified time runs out.
+ *
+ * @param[out] msgp pointer to a message variable for the received
+ * @param[in] timeout message the number of ticks before the operation
+ * timeouts, the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if a message has been correctly fetched.
+ * @retval MSG_RESET if the mailbox has been reset while waiting.
+ * @retval MSG_TIMEOUT if the operation has timed out.
+ *
+ * @api
+ */
+ msg_t fetch(T *msgp, sysinterval_t timeout) {
+
+ return chMBFetchTimeout(&mb, reinterpret_cast(msgp), timeout);
+ }
+
+ /**
+ * @brief Retrieves a message from a mailbox.
+ * @details The invoking thread waits until a message is posted in the
+ * mailbox or the specified time runs out.
+ *
+ * @param[out] msgp pointer to a message variable for the received
+ * @param[in] timeout message the number of ticks before the operation
+ * timeouts, the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The operation status.
+ * @retval MSG_OK if a message has been correctly fetched.
+ * @retval MSG_RESET if the mailbox has been reset while waiting.
+ * @retval MSG_TIMEOUT if the operation has timed out.
+ *
+ * @sclass
+ */
+ msg_t fetchS(T *msgp, sysinterval_t timeout) {
+
+ return chMBFetchTimeoutS(&mb, reinterpret_cast(msgp), timeout);
+ }
+
+ /**
+ * @brief Retrieves a message from a mailbox.
+ * @details This variant is non-blocking, the function returns a timeout
+ * condition if the queue is empty.
+ *
+ * @param[out] msgp pointer to a message variable for the received
+ * message
+ * @return The operation status.
+ * @retval MSG_OK if a message has been correctly fetched.
+ * @retval MSG_TIMEOUT if the mailbox is empty and a message cannot be
+ * fetched.
+ *
+ * @iclass
+ */
+ msg_t fetchI(T *msgp) {
+
+ return chMBFetchI(&mb, reinterpret_cast(msgp));
+ }
+
+ /**
+ * @brief Returns the next message in the queue without removing it.
+ * @pre A message must be waiting in the queue for this function to work
+ * or it would return garbage. The correct way to use this macro is
+ * to use @p getUsedCountI() and then use this macro, all within
+ * a lock state.
+ *
+ * @return The next message in queue.
+ *
+ * @iclass
+ */
+ T peekI(const mailbox_t *mbp) const {
+
+ return chMBPeekI(&mb);
+ }
+
+ /**
+ * @brief Returns the number of free message slots into a mailbox.
+ * @note Can be invoked in any system state but if invoked out of a
+ * locked state then the returned value may change after reading.
+ * @note The returned value can be less than zero when there are waiting
+ * threads on the internal semaphore.
+ *
+ * @return The number of empty message slots.
+ *
+ * @iclass
+ */
+ cnt_t getFreeCountI(void) const {
+
+ return chMBGetFreeCountI(&mb);
+ }
+
+ /**
+ * @brief Returns the number of used message slots into a mailbox.
+ * @note Can be invoked in any system state but if invoked out of a
+ * locked state then the returned value may change after reading.
+ * @note The returned value can be less than zero when there are waiting
+ * threads on the internal semaphore.
+ *
+ * @return The number of queued messages.
+ *
+ * @iclass
+ */
+ cnt_t getUsedCountI(void) const {
+
+ return chMBGetUsedCountI(&mb);
+ }
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::Mailbox *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Template class encapsulating a mailbox and its messages buffer.
+ *
+ * @param N length of the mailbox buffer
+ */
+ template
+ class Mailbox : public MailboxBase {
+
+ static_assert(sizeof(T) <= sizeof(msg_t),
+ "Mailbox type does not fit in msg_t");
+
+ private:
+ msg_t mb_buf[N];
+
+ public:
+ /**
+ * @brief Mailbox constructor.
+ *
+ * @init
+ */
+ Mailbox(void) :
+ MailboxBase(mb_buf, (cnt_t)(sizeof mb_buf / sizeof (msg_t))) {
+ }
+ };
+#endif /* CH_CFG_USE_MAILBOXES == TRUE */
+
+#if (CH_CFG_USE_MEMPOOLS == TRUE) || defined(__DOXYGEN__)
+ /*------------------------------------------------------------------------*
+ * chibios_rt::MemoryPool *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating a memory pool.
+ */
+ class MemoryPool {
+ /**
+ * @brief Embedded @p memory_pool_t structure.
+ */
+ memory_pool_t pool;
+
+ public:
+ /**
+ * @brief MemoryPool constructor.
+ *
+ * @param[in] size the size of the objects contained in this memory
+ * pool, the minimum accepted size is the size of
+ * a pointer to void.
+ * @param[in] provider memory provider function for the memory pool or
+ * @p nullptr if the pool is not allowed to grow
+ * automatically
+ *
+ * @init
+ */
+ MemoryPool(size_t size, memgetfunc_t provider=0) : pool() {
+
+ chPoolObjectInit(&pool, size, provider);
+ }
+
+ /**
+ * @brief MemoryPool constructor.
+ *
+ * @param[in] size the size of the objects contained in this memory
+ * pool, the minimum accepted size is the size of
+ * a pointer to void.
+ * @param[in] provider memory provider function for the memory pool or
+ * @p nullptr if the pool is not allowed to grow
+ * automatically
+ * @param[in] p pointer to the array first element
+ * @param[in] n number of elements in the array
+ *
+ * @init
+ */
+ MemoryPool(size_t size, void* p, size_t n,
+ memgetfunc_t provider=0) : pool() {
+
+ chPoolObjectInit(&pool, size, provider);
+ chPoolLoadArray(&pool, p, n);
+ }
+
+ /* Prohibit copy construction and assignment, but allow move.*/
+ MemoryPool(const MemoryPool &) = delete;
+ MemoryPool &operator=(const MemoryPool &) = delete;
+ MemoryPool(MemoryPool &&) = default;
+ MemoryPool &operator=(MemoryPool &&) = default;
+
+ /**
+ * @brief Loads a memory pool with an array of static objects.
+ * @pre The memory pool must be already been initialized.
+ * @pre The array elements must be of the right size for the specified
+ * memory pool.
+ * @post The memory pool contains the elements of the input array.
+ *
+ * @param[in] p pointer to the array first element
+ * @param[in] n number of elements in the array
+ *
+ * @api
+ */
+ void loadArray(void *p, size_t n) {
+
+ chPoolLoadArray(&pool, p, n);
+ }
+
+ /**
+ * @brief Allocates an object from a memory pool.
+ * @pre The memory pool must be already been initialized.
+ *
+ * @return The pointer to the allocated object.
+ * @retval nullptr if pool is empty.
+ *
+ * @iclass
+ */
+ void *allocI(void) {
+
+ return chPoolAllocI(&pool);
+ }
+
+ /**
+ * @brief Allocates an object from a memory pool.
+ * @pre The memory pool must be already been initialized.
+ *
+ * @return The pointer to the allocated object.
+ * @retval nullptr if pool is empty.
+ *
+ * @api
+ */
+ void *alloc(void) {
+
+ return chPoolAlloc(&pool);
+ }
+
+ /**
+ * @brief Releases an object into a memory pool.
+ * @pre The memory pool must be already been initialized.
+ * @pre The freed object must be of the right size for the specified
+ * memory pool.
+ * @pre The object must be properly aligned to contain a pointer to
+ * void.
+ *
+ * @param[in] objp the pointer to the object to be released
+ *
+ * @iclass
+ */
+ void free(void *objp) {
+
+ chPoolFree(&pool, objp);
+ }
+
+ /**
+ * @brief Adds an object to a memory pool.
+ * @pre The memory pool must be already been initialized.
+ * @pre The added object must be of the right size for the specified
+ * memory pool.
+ * @pre The added object must be memory aligned to the size of
+ * @p stkalign_t type.
+ * @note This function is just an alias for @p chPoolFree() and has been
+ * added for clarity.
+ *
+ * @param[in] objp the pointer to the object to be added
+ *
+ * @iclass
+ */
+ void freeI(void *objp) {
+
+ chPoolFreeI(&pool, objp);
+ }
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::ObjectsPool *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Template class encapsulating a memory pool and its elements.
+ */
+ template
+ class ObjectsPool : public MemoryPool {
+ /* The buffer is declared as an array of pointers to void for two
+ reasons:
+ 1) The objects must be properly aligned to hold a pointer as
+ first field.
+ 2) Objects are dirtied when loaded in the pool.*/
+ void *pool_buf[(N * sizeof (T)) / sizeof (void *)];
+
+ public:
+ /**
+ * @brief ObjectsPool constructor.
+ *
+ * @init
+ */
+ ObjectsPool(void) : MemoryPool(sizeof (T), nullptr) {
+
+ loadArray(pool_buf, N);
+ }
+ };
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::ThreadsPool *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Template class encapsulating a pool of threads.
+ */
+ template
+ class ThreadsPool : public BaseDynamicThread {
+ THD_WORKING_AREA(working_areas, S)[N];
+ MemoryPool threads_pool;
+
+ public:
+ /**
+ * @brief ThreadsPool constructor.
+ *
+ * @init
+ */
+ ThreadsPool(void) : threads_pool(THD_WORKING_AREA_SIZE(S)) {
+
+ threads_pool.loadArray(working_areas, N);
+ }
+
+ /**
+ * @brief Starts a dynamic thread from the pool.
+ *
+ * @param[in] prio thread priority
+ * @return A reference to the created thread with
+ * reference counter set to one.
+ *
+ * @api
+ */
+ ThreadReference start(tprio_t prio) override {
+ void _thd_start(void *arg);
+
+ return ThreadReference(chThdCreateFromMemoryPool(&threads_pool.pool,
+ C,
+ prio,
+ _thd_start,
+ this));
+ }
+ };
+#endif /* CH_CFG_USE_MEMPOOLS == TRUE */
+
+#if (CH_CFG_USE_HEAP == TRUE) || defined(__DOXYGEN__)
+ /*------------------------------------------------------------------------*
+ * chibios_rt::Heap *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Class encapsulating a heap.
+ */
+ class Heap {
+ /**
+ * @brief Embedded @p memory_heap_t structure.
+ */
+ memory_heap_t heap;
+
+ public:
+ /**
+ * @brief Heap constructor.
+ * @pre Both the heap buffer base and the heap size must be aligned to
+ * the @p stkalign_t type size.
+ *
+ * @param[in] buffer heap buffer base
+ * @param[in] size the size of the memory area located at \e buffer
+ * @init
+ */
+ Heap(void *buffer, const size_t size) : heap() {
+
+ chHeapObjectInit(&heap, buffer, size);
+ }
+
+ /* Prohibit copy construction and assignment, but allow move.*/
+ Heap(const Heap &) = delete;
+ Heap &operator=(const Heap &) = delete;
+ Heap(Heap &&) = default;
+ Heap &operator=(Heap &&) = default;
+
+ /**
+ * @brief Allocates an object from a heap.
+ * @pre The heap must be already been initialized.
+ *
+ * @return The pointer to the allocated object.
+ * @retval nullptr if pool is empty.
+ *
+ * @api
+ */
+ void *alloc(const size_t size) {
+
+ return chHeapAlloc(&heap, size);
+ }
+
+ /**
+ * @brief Releases an object into the heap.
+ *
+ * @param[in] objp the pointer to the object to be released
+ *
+ * @api
+ */
+ void free(void *objp) {
+
+ chHeapFree(objp);
+ }
+
+ /**
+ * @brief Reports the heap status.
+ *
+ * @param[out] frag the size of total fragmented free space
+ * @param[in] largestp pointer to a variable that will receive the largest
+ * free free block found space or @p nullptr
+ * @return the number of fragments in the heap
+ *
+ * @api
+ */
+ size_t status(size_t &frag, size_t *largestp=0) {
+
+ return chHeapStatus(&heap, &frag, largestp);
+ }
+ };
+#endif /* CH_CFG_USE_MEMPOOLS == TRUE */
+
+ /*------------------------------------------------------------------------*
+ * chibios_rt::BaseSequentialStreamInterface *
+ *------------------------------------------------------------------------*/
+ /**
+ * @brief Interface of a BaseSequentialStream.
+ * @note You can cast a BaseSequentialStream to this interface and use
+ * it, the memory layout is the same.
+ */
+ class BaseSequentialStreamInterface {
+ public:
+ /**
+ * @brief Sequential Stream write.
+ * @details The function writes data from a buffer to a stream.
+ *
+ * @param[in] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred
+ * @return The number of bytes transferred. The return value
+ * can be less than the specified number of bytes if
+ * an end-of-file condition has been met.
+ *
+ * @api
+ */
+ virtual size_t write(const uint8_t *bp, const size_t n) = 0;
+
+ /**
+ * @brief Sequential Stream read.
+ * @details The function reads data from a stream into a buffer.
+ *
+ * @param[out] bp pointer to the data buffer
+ * @param[in] n the maximum amount of data to be transferred
+ * @return The number of bytes transferred. The return value
+ * can be less than the specified number of bytes if
+ * an end-of-file condition has been met.
+ *
+ * @api
+ */
+ virtual size_t read(uint8_t *bp, const size_t n) = 0;
+
+ /**
+ * @brief Sequential Stream blocking byte write.
+ * @details This function writes a byte value to a channel. If the channel
+ * is not ready to accept data then the calling thread is
+ * suspended.
+ *
+ * @param[in] b the byte value to be written to the channel
+ *
+ * @return The operation status.
+ * @retval Q_OK if the operation succeeded.
+ * @retval Q_RESET if an end-of-file condition has been met.
+ *
+ * @api
+ */
+ virtual msg_t put(const uint8_t b) = 0;
+
+ /**
+ * @brief Sequential Stream blocking byte read.
+ * @details This function reads a byte value from a channel. If the data
+ * is not available then the calling thread is suspended.
+ *
+ * @return A byte value from the queue.
+ * @retval Q_RESET if an end-of-file condition has been met.
+ *
+ * @api
+ */
+ virtual msg_t get(void) = 0;
+ };
+}
+
+#endif /* _CH_HPP_ */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/various/cpp_wrappers/chcpp.mk b/ChibiOS_20.3.2/os/various/cpp_wrappers/chcpp.mk
new file mode 100644
index 0000000..b1a5466
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/cpp_wrappers/chcpp.mk
@@ -0,0 +1,9 @@
+# C++ wrapper files.
+CHCPPSRC = $(CHIBIOS)/os/various/cpp_wrappers/ch.cpp \
+ $(CHIBIOS)/os/various/cpp_wrappers/syscalls_cpp.cpp
+
+CHCPPINC = $(CHIBIOS)/os/various/cpp_wrappers
+
+# Shared variables
+ALLCPPSRC += $(CHCPPSRC)
+ALLINC += $(CHCPPINC)
diff --git a/ChibiOS_20.3.2/os/various/cpp_wrappers/syscalls_cpp.cpp b/ChibiOS_20.3.2/os/various/cpp_wrappers/syscalls_cpp.cpp
new file mode 100644
index 0000000..d7d6d92
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/cpp_wrappers/syscalls_cpp.cpp
@@ -0,0 +1,41 @@
+#include
+#include
+
+#include "osal.h"
+
+#include "syscalls_cpp.hpp"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void _exit(int status){
+ (void) status;
+ osalSysHalt("Unrealized");
+ while(TRUE){}
+}
+
+pid_t _getpid(void){
+ return 1;
+}
+
+#undef errno
+extern int errno;
+int _kill(int pid, int sig) {
+ (void)pid;
+ (void)sig;
+ errno = EINVAL;
+ return -1;
+}
+
+void _open_r(void){
+ return;
+}
+
+void __cxa_pure_virtual() {
+ osalSysHalt("Pure virtual function call.");
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/ChibiOS_20.3.2/os/various/cpp_wrappers/syscalls_cpp.hpp b/ChibiOS_20.3.2/os/various/cpp_wrappers/syscalls_cpp.hpp
new file mode 100644
index 0000000..681ce2c
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/cpp_wrappers/syscalls_cpp.hpp
@@ -0,0 +1,13 @@
+#ifndef SYSCALLS_CPP_HPP_
+#define SYSCALLS_CPP_HPP_
+
+/* The ABI requires a 32-bit type.*/
+typedef int __guard;
+
+int __cxa_guard_acquire(__guard *);
+void __cxa_guard_release (__guard *);
+void __cxa_guard_abort (__guard *);
+
+void *__dso_handle = NULL;
+
+#endif /* SYSCALLS_CPP_HPP_ */
diff --git a/ChibiOS_20.3.2/os/various/evtimer.c b/ChibiOS_20.3.2/os/various/evtimer.c
new file mode 100644
index 0000000..e9dcb93
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/evtimer.c
@@ -0,0 +1,85 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file evtimer.c
+ * @brief Events Generator Timer code.
+ *
+ * @addtogroup event_timer
+ * @{
+ */
+
+#include "ch.h"
+#include "evtimer.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+static void tmrcb(void *p) {
+ event_timer_t *etp = p;
+
+ chSysLockFromISR();
+ chEvtBroadcastI(&etp->et_es);
+ chVTDoSetI(&etp->et_vt, etp->et_interval, tmrcb, etp);
+ chSysUnlockFromISR();
+}
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Initializes an @p event_timer_t structure.
+ *
+ * @param[out] etp the @p event_timer_t structure to be initialized
+ * @param[in] time the interval in system ticks
+ */
+void evtObjectInit(event_timer_t *etp, systime_t time) {
+
+ chEvtObjectInit(&etp->et_es);
+ chVTObjectInit(&etp->et_vt);
+ etp->et_interval = time;
+}
+
+/**
+ * @brief Starts the timer
+ * @details If the timer was already running then the function has no effect.
+ *
+ * @param[in] etp pointer to an initialized @p event_timer_t structure.
+ */
+void evtStart(event_timer_t *etp) {
+
+ chVTSet(&etp->et_vt, etp->et_interval, tmrcb, etp);
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/various/evtimer.h b/ChibiOS_20.3.2/os/various/evtimer.h
new file mode 100644
index 0000000..f0591a8
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/evtimer.h
@@ -0,0 +1,94 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file evtimer.h
+ * @brief Events Generator Timer structures and macros.
+ *
+ * @addtogroup event_timer
+ * @{
+ */
+
+#ifndef EVTIMER_H
+#define EVTIMER_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*
+ * Module dependencies check.
+ */
+#if !CH_CFG_USE_EVENTS
+#error "Event Timers require CH_CFG_USE_EVENTS"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Type of a event timer structure.
+ */
+typedef struct {
+ virtual_timer_t et_vt;
+ event_source_t et_es;
+ systime_t et_interval;
+} event_timer_t;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void evtObjectInit(event_timer_t *etp, systime_t time);
+ void evtStart(event_timer_t *etp);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Stops the timer.
+ * @details If the timer was already stopped then the function has no effect.
+ *
+ * @param[in] etp pointer to an initialized @p event_timer_t structure.
+ */
+static inline void evtStop(event_timer_t *etp) {
+
+ chVTReset(&etp->et_vt);
+}
+
+#endif /* EVTIMER_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/various/fatfs_bindings/fatfs.mk b/ChibiOS_20.3.2/os/various/fatfs_bindings/fatfs.mk
new file mode 100644
index 0000000..9da59e0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/fatfs_bindings/fatfs.mk
@@ -0,0 +1,11 @@
+# FATFS files.
+FATFSSRC = $(CHIBIOS)/os/various/fatfs_bindings/fatfs_diskio.c \
+ $(CHIBIOS)/os/various/fatfs_bindings/fatfs_syscall.c \
+ $(CHIBIOS)/ext/fatfs/source/ff.c \
+ $(CHIBIOS)/ext/fatfs/source/ffunicode.c
+
+FATFSINC = $(CHIBIOS)/ext/fatfs/source
+
+# Shared variables
+ALLCSRC += $(FATFSSRC)
+ALLINC += $(FATFSINC)
diff --git a/ChibiOS_20.3.2/os/various/fatfs_bindings/fatfs_diskio.c b/ChibiOS_20.3.2/os/various/fatfs_bindings/fatfs_diskio.c
new file mode 100644
index 0000000..ef04746
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/fatfs_bindings/fatfs_diskio.c
@@ -0,0 +1,267 @@
+/*-----------------------------------------------------------------------*/
+/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */
+/*-----------------------------------------------------------------------*/
+/* This is a stub disk I/O module that acts as front end of the existing */
+/* disk I/O modules and attach it to FatFs module with common interface. */
+/*-----------------------------------------------------------------------*/
+
+#include "hal.h"
+#include "ffconf.h"
+#include "ff.h"
+#include "diskio.h"
+
+#if HAL_USE_MMC_SPI && HAL_USE_SDC
+#error "cannot specify both MMC_SPI and SDC drivers"
+#endif
+
+#if !defined(FATFS_HAL_DEVICE)
+#if HAL_USE_MMC_SPI
+#define FATFS_HAL_DEVICE MMCD1
+#else
+#define FATFS_HAL_DEVICE SDCD1
+#endif
+#endif
+
+#if HAL_USE_MMC_SPI
+extern MMCDriver FATFS_HAL_DEVICE;
+#elif HAL_USE_SDC
+extern SDCDriver FATFS_HAL_DEVICE;
+#else
+#error "MMC_SPI or SDC driver must be specified"
+#endif
+
+#if HAL_USE_RTC
+extern RTCDriver RTCD1;
+#endif
+
+/*-----------------------------------------------------------------------*/
+/* Correspondence between physical drive number and physical drive. */
+
+#define MMC 0
+#define SDC 0
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Inidialize a Drive */
+
+DSTATUS disk_initialize (
+ BYTE pdrv /* Physical drive number (0..) */
+)
+{
+ DSTATUS stat;
+
+ switch (pdrv) {
+#if HAL_USE_MMC_SPI
+ case MMC:
+ stat = 0;
+ /* It is initialized externally, just reads the status.*/
+ if (blkGetDriverState(&FATFS_HAL_DEVICE) != BLK_READY)
+ stat |= STA_NOINIT;
+ if (mmcIsWriteProtected(&FATFS_HAL_DEVICE))
+ stat |= STA_PROTECT;
+ return stat;
+#else
+ case SDC:
+ stat = 0;
+ /* It is initialized externally, just reads the status.*/
+ if (blkGetDriverState(&FATFS_HAL_DEVICE) != BLK_READY)
+ stat |= STA_NOINIT;
+ if (sdcIsWriteProtected(&FATFS_HAL_DEVICE))
+ stat |= STA_PROTECT;
+ return stat;
+#endif
+ }
+ return STA_NOINIT;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Return Disk Status */
+
+DSTATUS disk_status (
+ BYTE pdrv /* Physical drive number (0..) */
+)
+{
+ DSTATUS stat;
+
+ switch (pdrv) {
+#if HAL_USE_MMC_SPI
+ case MMC:
+ stat = 0;
+ /* It is initialized externally, just reads the status.*/
+ if (blkGetDriverState(&FATFS_HAL_DEVICE) != BLK_READY)
+ stat |= STA_NOINIT;
+ if (mmcIsWriteProtected(&FATFS_HAL_DEVICE))
+ stat |= STA_PROTECT;
+ return stat;
+#else
+ case SDC:
+ stat = 0;
+ /* It is initialized externally, just reads the status.*/
+ if (blkGetDriverState(&FATFS_HAL_DEVICE) != BLK_READY)
+ stat |= STA_NOINIT;
+ if (sdcIsWriteProtected(&FATFS_HAL_DEVICE))
+ stat |= STA_PROTECT;
+ return stat;
+#endif
+ }
+ return STA_NOINIT;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read Sector(s) */
+
+DRESULT disk_read (
+ BYTE pdrv, /* Physical drive number (0..) */
+ BYTE *buff, /* Data buffer to store read data */
+ DWORD sector, /* Sector address (LBA) */
+ UINT count /* Number of sectors to read (1..255) */
+)
+{
+ switch (pdrv) {
+#if HAL_USE_MMC_SPI
+ case MMC:
+ if (blkGetDriverState(&FATFS_HAL_DEVICE) != BLK_READY)
+ return RES_NOTRDY;
+ if (mmcStartSequentialRead(&FATFS_HAL_DEVICE, sector))
+ return RES_ERROR;
+ while (count > 0) {
+ if (mmcSequentialRead(&FATFS_HAL_DEVICE, buff))
+ return RES_ERROR;
+ buff += MMCSD_BLOCK_SIZE;
+ count--;
+ }
+ if (mmcStopSequentialRead(&FATFS_HAL_DEVICE))
+ return RES_ERROR;
+ return RES_OK;
+#else
+ case SDC:
+ if (blkGetDriverState(&FATFS_HAL_DEVICE) != BLK_READY)
+ return RES_NOTRDY;
+ if (sdcRead(&FATFS_HAL_DEVICE, sector, buff, count))
+ return RES_ERROR;
+ return RES_OK;
+#endif
+ }
+ return RES_PARERR;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Write Sector(s) */
+
+#if !FF_FS_READONLY
+DRESULT disk_write (
+ BYTE pdrv, /* Physical drive number (0..) */
+ const BYTE *buff, /* Data to be written */
+ DWORD sector, /* Sector address (LBA) */
+ UINT count /* Number of sectors to write (1..255) */
+)
+{
+ switch (pdrv) {
+#if HAL_USE_MMC_SPI
+ case MMC:
+ if (blkGetDriverState(&FATFS_HAL_DEVICE) != BLK_READY)
+ return RES_NOTRDY;
+ if (mmcIsWriteProtected(&FATFS_HAL_DEVICE))
+ return RES_WRPRT;
+ if (mmcStartSequentialWrite(&FATFS_HAL_DEVICE, sector))
+ return RES_ERROR;
+ while (count > 0) {
+ if (mmcSequentialWrite(&FATFS_HAL_DEVICE, buff))
+ return RES_ERROR;
+ buff += MMCSD_BLOCK_SIZE;
+ count--;
+ }
+ if (mmcStopSequentialWrite(&FATFS_HAL_DEVICE))
+ return RES_ERROR;
+ return RES_OK;
+#else
+ case SDC:
+ if (blkGetDriverState(&FATFS_HAL_DEVICE) != BLK_READY)
+ return RES_NOTRDY;
+ if (sdcWrite(&FATFS_HAL_DEVICE, sector, buff, count))
+ return RES_ERROR;
+ return RES_OK;
+#endif
+ }
+ return RES_PARERR;
+}
+#endif /* _FS_READONLY */
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Miscellaneous Functions */
+
+DRESULT disk_ioctl (
+ BYTE pdrv, /* Physical drive number (0..) */
+ BYTE cmd, /* Control code */
+ void *buff /* Buffer to send/receive control data */
+)
+{
+ (void)buff;
+
+ switch (pdrv) {
+#if HAL_USE_MMC_SPI
+ case MMC:
+ switch (cmd) {
+ case CTRL_SYNC:
+ return RES_OK;
+#if FF_MAX_SS > FF_MIN_SS
+ case GET_SECTOR_SIZE:
+ *((WORD *)buff) = MMCSD_BLOCK_SIZE;
+ return RES_OK;
+#endif
+#if FF_USE_TRIM
+ case CTRL_TRIM:
+ mmcErase(&FATFS_HAL_DEVICE, *((DWORD *)buff), *((DWORD *)buff + 1));
+ return RES_OK;
+#endif
+ default:
+ return RES_PARERR;
+ }
+#else
+ case SDC:
+ switch (cmd) {
+ case CTRL_SYNC:
+ return RES_OK;
+ case GET_SECTOR_COUNT:
+ *((DWORD *)buff) = mmcsdGetCardCapacity(&FATFS_HAL_DEVICE);
+ return RES_OK;
+#if FF_MAX_SS > FF_MIN_SS
+ case GET_SECTOR_SIZE:
+ *((WORD *)buff) = MMCSD_BLOCK_SIZE;
+ return RES_OK;
+#endif
+ case GET_BLOCK_SIZE:
+ *((DWORD *)buff) = 256; /* 512b blocks in one erase block */
+ return RES_OK;
+#if FF_USE_TRIM
+ case CTRL_TRIM:
+ sdcErase(&FATFS_HAL_DEVICE, *((DWORD *)buff), *((DWORD *)buff + 1));
+ return RES_OK;
+#endif
+ default:
+ return RES_PARERR;
+ }
+#endif
+ }
+ return RES_PARERR;
+}
+
+DWORD get_fattime(void) {
+#if HAL_USE_RTC
+ RTCDateTime timespec;
+
+ rtcGetTime(&RTCD1, ×pec);
+ return rtcConvertDateTimeToFAT(×pec);
+#else
+ return ((uint32_t)0 | (1 << 16)) | (1 << 21); /* wrong but valid time */
+#endif
+}
diff --git a/ChibiOS_20.3.2/os/various/fatfs_bindings/fatfs_syscall.c b/ChibiOS_20.3.2/os/various/fatfs_bindings/fatfs_syscall.c
new file mode 100644
index 0000000..dbe569e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/fatfs_bindings/fatfs_syscall.c
@@ -0,0 +1,84 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*------------------------------------------------------------------------*/
+/* Sample code of OS dependent controls for FatFs */
+/* (C)ChaN, 2014 */
+/*------------------------------------------------------------------------*/
+
+#include "hal.h"
+#include "ff.h"
+
+#if FF_FS_REENTRANT
+/*------------------------------------------------------------------------*/
+/* Static array of Synchronization Objects */
+/*------------------------------------------------------------------------*/
+static semaphore_t ff_sem[FF_VOLUMES];
+
+/*------------------------------------------------------------------------*/
+/* Create a Synchronization Object */
+/*------------------------------------------------------------------------*/
+int ff_cre_syncobj(BYTE vol, FF_SYNC_t *sobj) {
+
+ *sobj = &ff_sem[vol];
+ chSemObjectInit(*sobj, 1);
+ return TRUE;
+}
+
+/*------------------------------------------------------------------------*/
+/* Delete a Synchronization Object */
+/*------------------------------------------------------------------------*/
+int ff_del_syncobj(FF_SYNC_t sobj) {
+
+ chSemReset(sobj, 0);
+ return TRUE;
+}
+
+/*------------------------------------------------------------------------*/
+/* Request Grant to Access the Volume */
+/*------------------------------------------------------------------------*/
+int ff_req_grant(FF_SYNC_t sobj) {
+
+ msg_t msg = chSemWaitTimeout(sobj, (systime_t)FF_FS_TIMEOUT);
+ return msg == MSG_OK;
+}
+
+/*------------------------------------------------------------------------*/
+/* Release Grant to Access the Volume */
+/*------------------------------------------------------------------------*/
+void ff_rel_grant(FF_SYNC_t sobj) {
+
+ chSemSignal(sobj);
+}
+#endif /* FF_FS_REENTRANT */
+
+#if FF_USE_LFN == 3 /* LFN with a working buffer on the heap */
+/*------------------------------------------------------------------------*/
+/* Allocate a memory block */
+/*------------------------------------------------------------------------*/
+void *ff_memalloc(UINT size) {
+
+ return chHeapAlloc(NULL, size);
+}
+
+/*------------------------------------------------------------------------*/
+/* Free a memory block */
+/*------------------------------------------------------------------------*/
+void ff_memfree(void *mblock) {
+
+ chHeapFree(mblock);
+}
+#endif /* FF_USE_LFN == 3 */
diff --git a/ChibiOS_20.3.2/os/various/fatfs_bindings/readme.txt b/ChibiOS_20.3.2/os/various/fatfs_bindings/readme.txt
new file mode 100644
index 0000000..b6000ae
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/fatfs_bindings/readme.txt
@@ -0,0 +1,12 @@
+This directory contains the ChibiOS/RT "official" bindings with the FatFS
+library by ChaN: http://elm-chan.org
+
+In order to use FatFS within ChibiOS/RT project:
+1. unzip FatFS under ./ext/fatfs [See Note 2]
+2. include $(CHIBIOS)/os/various/fatfs_bindings/fatfs.mk in your makefile.
+3. Add $(FATFSSRC) to $(CSRC)
+4. Add $(FATFSINC) to $(INCDIR)
+
+Note:
+1. These files modified for use with version 0.13 of fatfs.
+2. In the original distribution, the source directory is called 'source' rather than 'src'
diff --git a/ChibiOS_20.3.2/os/various/lwip_bindings/arch/cc.h b/ChibiOS_20.3.2/os/various/lwip_bindings/arch/cc.h
new file mode 100644
index 0000000..5258a84
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/lwip_bindings/arch/cc.h
@@ -0,0 +1,89 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ * **** This file incorporates work covered by the following copyright and ****
+ * **** permission notice: ****
+ *
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels
+ *
+ */
+
+#ifndef __CC_H__
+#define __CC_H__
+
+#include
+
+/* Use errno provided by system. */
+#define LWIP_ERRNO_INCLUDE
+
+/**
+ * @brief Use system provided struct timeval by default.
+ */
+#ifndef LWIP_TIMEVAL_PRIVATE
+#define LWIP_TIMEVAL_PRIVATE 0
+#include
+#endif
+
+/**
+ * @brief Use a no-op diagnostic output macro by default.
+ */
+#if !defined(LWIP_PLATFORM_DIAG)
+#define LWIP_PLATFORM_DIAG(x)
+#endif
+
+/**
+ * @brief Halt the system on lwIP assert failure by default.
+ */
+#if !defined(LWIP_PLATFORM_ASSERT)
+#define LWIP_PLATFORM_ASSERT(x) osalSysHalt(x)
+#endif
+
+/**
+ * @brief The NETIF API is required by lwipthread.
+ */
+#ifdef LWIP_NETIF_API
+#undef LWIP_NETIF_API
+#endif
+#define LWIP_NETIF_API 1
+
+#endif /* __CC_H__ */
diff --git a/ChibiOS_20.3.2/os/various/lwip_bindings/arch/sys_arch.c b/ChibiOS_20.3.2/os/various/lwip_bindings/arch/sys_arch.c
new file mode 100644
index 0000000..7a7d5ea
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/lwip_bindings/arch/sys_arch.c
@@ -0,0 +1,239 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ * **** This file incorporates work covered by the following copyright and ****
+ * **** permission notice: ****
+ *
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels
+ *
+ */
+
+/*
+ * See http://lwip.wikia.com/wiki/Porting_for_an_OS for instructions.
+ */
+
+#include "hal.h"
+
+#include "lwip/opt.h"
+#include "lwip/mem.h"
+#include "lwip/sys.h"
+#include "lwip/stats.h"
+
+#include "arch/cc.h"
+#include "arch/sys_arch.h"
+
+void sys_init(void) {
+
+}
+
+err_t sys_sem_new(sys_sem_t *sem, u8_t count) {
+
+ *sem = chHeapAlloc(NULL, sizeof(semaphore_t));
+ if (*sem == 0) {
+ SYS_STATS_INC(sem.err);
+ return ERR_MEM;
+ }
+ else {
+ chSemObjectInit(*sem, (cnt_t)count);
+ SYS_STATS_INC_USED(sem);
+ return ERR_OK;
+ }
+}
+
+void sys_sem_free(sys_sem_t *sem) {
+
+ chHeapFree(*sem);
+ *sem = SYS_SEM_NULL;
+ SYS_STATS_DEC(sem.used);
+}
+
+void sys_sem_signal(sys_sem_t *sem) {
+
+ chSemSignal(*sem);
+}
+
+/* CHIBIOS FIX: specific variant of this call to be called from within
+ a lock.*/
+void sys_sem_signal_S(sys_sem_t *sem) {
+
+ chSemSignalI(*sem);
+ chSchRescheduleS();
+}
+
+u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) {
+ systime_t start;
+ sysinterval_t tmo, remaining;
+
+ chSysLock();
+ tmo = timeout > 0 ? TIME_MS2I((time_msecs_t)timeout) : TIME_INFINITE;
+ start = chVTGetSystemTimeX();
+ if (chSemWaitTimeoutS(*sem, tmo) != MSG_OK) {
+ chSysUnlock();
+ return SYS_ARCH_TIMEOUT;
+ }
+ remaining = chTimeDiffX(start, chVTGetSystemTimeX());
+ chSysUnlock();
+ return (u32_t)TIME_I2MS(remaining);
+}
+
+int sys_sem_valid(sys_sem_t *sem) {
+ return *sem != SYS_SEM_NULL;
+}
+
+// typically called within lwIP after freeing a semaphore
+// to make sure the pointer is not left pointing to invalid data
+void sys_sem_set_invalid(sys_sem_t *sem) {
+ *sem = SYS_SEM_NULL;
+}
+
+err_t sys_mbox_new(sys_mbox_t *mbox, int size) {
+
+ *mbox = chHeapAlloc(NULL, sizeof(mailbox_t) + sizeof(msg_t) * size);
+ if (*mbox == 0) {
+ SYS_STATS_INC(mbox.err);
+ return ERR_MEM;
+ }
+ else {
+ chMBObjectInit(*mbox, (void *)(((uint8_t *)*mbox) + sizeof(mailbox_t)), size);
+ SYS_STATS_INC(mbox.used);
+ return ERR_OK;
+ }
+}
+
+void sys_mbox_free(sys_mbox_t *mbox) {
+ cnt_t tmpcnt;
+
+ chSysLock();
+ tmpcnt = chMBGetUsedCountI(*mbox);
+ chSysUnlock();
+
+ if (tmpcnt != 0) {
+ // If there are messages still present in the mailbox when the mailbox
+ // is deallocated, it is an indication of a programming error in lwIP
+ // and the developer should be notified.
+ SYS_STATS_INC(mbox.err);
+ chMBReset(*mbox);
+ }
+ chHeapFree(*mbox);
+ *mbox = SYS_MBOX_NULL;
+ SYS_STATS_DEC(mbox.used);
+}
+
+void sys_mbox_post(sys_mbox_t *mbox, void *msg) {
+
+ chMBPostTimeout(*mbox, (msg_t)msg, TIME_INFINITE);
+}
+
+err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) {
+
+ if (chMBPostTimeout(*mbox, (msg_t)msg, TIME_IMMEDIATE) == MSG_TIMEOUT) {
+ SYS_STATS_INC(mbox.err);
+ return ERR_MEM;
+ }
+ return ERR_OK;
+}
+
+u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) {
+ systime_t start;
+ sysinterval_t tmo, remaining;
+
+ chSysLock();
+ tmo = timeout > 0 ? TIME_MS2I((time_msecs_t)timeout) : TIME_INFINITE;
+ start = chVTGetSystemTimeX();
+ if (chMBFetchTimeoutS(*mbox, (msg_t *)msg, tmo) != MSG_OK) {
+ chSysUnlock();
+ return SYS_ARCH_TIMEOUT;
+ }
+ remaining = chTimeDiffX(start, chVTGetSystemTimeX());
+ chSysUnlock();
+ return (u32_t)TIME_I2MS(remaining);
+}
+
+u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) {
+
+ if (chMBFetchTimeout(*mbox, (msg_t *)msg, TIME_IMMEDIATE) == MSG_TIMEOUT)
+ return SYS_MBOX_EMPTY;
+ return 0;
+}
+
+int sys_mbox_valid(sys_mbox_t *mbox) {
+ return *mbox != SYS_MBOX_NULL;
+}
+
+// typically called within lwIP after freeing an mbox
+// to make sure the pointer is not left pointing to invalid data
+void sys_mbox_set_invalid(sys_mbox_t *mbox) {
+ *mbox = SYS_MBOX_NULL;
+}
+
+sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread,
+ void *arg, int stacksize, int prio) {
+ thread_t *tp;
+
+ tp = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(stacksize),
+ name, prio, (tfunc_t)thread, arg);
+ return (sys_thread_t)tp;
+}
+
+sys_prot_t sys_arch_protect(void) {
+
+ return chSysGetStatusAndLockX();
+}
+
+void sys_arch_unprotect(sys_prot_t pval) {
+
+ chSysRestoreStatusX((syssts_t)pval);
+}
+
+u32_t sys_now(void) {
+
+#if OSAL_ST_FREQUENCY == 1000
+ return (u32_t)chVTGetSystemTimeX();
+#elif (OSAL_ST_FREQUENCY / 1000) >= 1 && (OSAL_ST_FREQUENCY % 1000) == 0
+ return ((u32_t)chVTGetSystemTimeX() - 1) / (OSAL_ST_FREQUENCY / 1000) + 1;
+#elif (1000 / OSAL_ST_FREQUENCY) >= 1 && (1000 % OSAL_ST_FREQUENCY) == 0
+ return ((u32_t)chVTGetSystemTimeX() - 1) * (1000 / OSAL_ST_FREQUENCY) + 1;
+#else
+ return (u32_t)(((u64_t)(chVTGetSystemTimeX() - 1) * 1000) / OSAL_ST_FREQUENCY) + 1;
+#endif
+}
diff --git a/ChibiOS_20.3.2/os/various/lwip_bindings/arch/sys_arch.h b/ChibiOS_20.3.2/os/various/lwip_bindings/arch/sys_arch.h
new file mode 100644
index 0000000..bbb3531
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/lwip_bindings/arch/sys_arch.h
@@ -0,0 +1,68 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ * **** This file incorporates work covered by the following copyright and ****
+ * **** permission notice: ****
+ *
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels
+ *
+ */
+
+#include
+
+#ifndef __SYS_ARCH_H__
+#define __SYS_ARCH_H__
+
+typedef semaphore_t * sys_sem_t;
+typedef mailbox_t * sys_mbox_t;
+typedef thread_t * sys_thread_t;
+typedef syssts_t sys_prot_t;
+
+#define SYS_MBOX_NULL (mailbox_t *)0
+#define SYS_THREAD_NULL (thread_t *)0
+#define SYS_SEM_NULL (semaphore_t *)0
+
+/* let sys.h use binary semaphores for mutexes */
+#define LWIP_COMPAT_MUTEX 1
+
+#endif /* __SYS_ARCH_H__ */
diff --git a/ChibiOS_20.3.2/os/various/lwip_bindings/lwip.mk b/ChibiOS_20.3.2/os/various/lwip_bindings/lwip.mk
new file mode 100644
index 0000000..961e710
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/lwip_bindings/lwip.mk
@@ -0,0 +1,23 @@
+# List of the required lwIP files.
+LWIPDIR = $(CHIBIOS)/ext/lwip/src
+
+# The various blocks of files are outlined in Filelists.mk.
+include $(LWIPDIR)/Filelists.mk
+
+LWBINDSRC = \
+ $(CHIBIOS)/os/various/lwip_bindings/lwipthread.c \
+ $(CHIBIOS)/os/various/lwip_bindings/arch/sys_arch.c
+
+
+# Add blocks of files from Filelists.mk as required for enabled options
+LWSRC_REQUIRED = $(COREFILES) $(CORE4FILES) $(APIFILES) $(LWBINDSRC) $(NETIFFILES)
+LWSRC_EXTRAS ?= $(HTTPFILES)
+
+LWINC = \
+ $(CHIBIOS)/os/various/lwip_bindings \
+ $(LWIPDIR)/include
+
+# Shared variables
+ALLCSRC += $(LWSRC_REQUIRED) $(LWSRC_EXTRAS)
+ALLINC += $(LWINC) \
+ $(CHIBIOS)/os/various
diff --git a/ChibiOS_20.3.2/os/various/lwip_bindings/lwipthread.c b/ChibiOS_20.3.2/os/various/lwip_bindings/lwipthread.c
new file mode 100644
index 0000000..ee4303f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/lwip_bindings/lwipthread.c
@@ -0,0 +1,530 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ * **** This file incorporates work covered by the following copyright and ****
+ * **** permission notice: ****
+ *
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels
+ *
+ */
+
+/**
+ * @file lwipthread.c
+ * @brief LWIP wrapper thread code.
+ * @addtogroup LWIP_THREAD
+ * @{
+ */
+
+#include "hal.h"
+#include "evtimer.h"
+
+#include "lwipthread.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if LWIP_DHCP
+#include
+#endif
+
+#if LWIP_AUTOIP
+#include
+#endif
+
+#define PERIODIC_TIMER_ID 1
+#define FRAME_RECEIVED_ID 2
+
+/*
+ * Suspension point for initialization procedure.
+ */
+thread_reference_t lwip_trp = NULL;
+
+/*
+ * Stack area for the LWIP-MAC thread.
+ */
+static THD_WORKING_AREA(wa_lwip_thread, LWIP_THREAD_STACK_SIZE);
+
+/*
+ * Initialization.
+ */
+static void low_level_init(struct netif *netif) {
+ /* set MAC hardware address length */
+ netif->hwaddr_len = ETHARP_HWADDR_LEN;
+
+ /* maximum transfer unit */
+ netif->mtu = LWIP_NETIF_MTU;
+
+ /* device capabilities */
+ /* don't set NETIF_FLAG_ETHARP if this device is not an Ethernet one */
+ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
+
+ /* Do whatever else is needed to initialize interface. */
+}
+
+/*
+ * This function does the actual transmission of the packet. The packet is
+ * contained in the pbuf that is passed to the function. This pbuf
+ * might be chained.
+ *
+ * @param netif the lwip network interface structure for this ethernetif
+ * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
+ * @return ERR_OK if the packet could be sent
+ * an err_t value if the packet couldn't be sent
+ *
+ * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
+ * strange results. You might consider waiting for space in the DMA queue
+ * to become available since the stack doesn't retry to send a packet
+ * dropped because of memory failure (except for the TCP timers).
+ */
+static err_t low_level_output(struct netif *netif, struct pbuf *p) {
+ struct pbuf *q;
+ MACTransmitDescriptor td;
+
+ (void)netif;
+ if (macWaitTransmitDescriptor(ÐD1, &td, TIME_MS2I(LWIP_SEND_TIMEOUT)) != MSG_OK)
+ return ERR_TIMEOUT;
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
+#endif
+
+ /* Iterates through the pbuf chain. */
+ for(q = p; q != NULL; q = q->next)
+ macWriteTransmitDescriptor(&td, (uint8_t *)q->payload, (size_t)q->len);
+ macReleaseTransmitDescriptor(&td);
+
+ MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
+ if (((u8_t*)p->payload)[0] & 1) {
+ /* broadcast or multicast packet*/
+ MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
+ }
+ else {
+ /* unicast packet */
+ MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
+ }
+ /* increase ifoutdiscards or ifouterrors on error */
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
+#endif
+
+ LINK_STATS_INC(link.xmit);
+
+ return ERR_OK;
+}
+
+/*
+ * Receives a frame.
+ * Allocates a pbuf and transfers the bytes of the incoming
+ * packet from the interface into the pbuf.
+ *
+ * @param netif the lwip network interface structure for this ethernetif
+ * @return a pbuf filled with the received packet (including MAC header)
+ * NULL on memory error
+ */
+static bool low_level_input(struct netif *netif, struct pbuf **pbuf) {
+ MACReceiveDescriptor rd;
+ struct pbuf *q;
+ u16_t len;
+
+ (void)netif;
+
+ osalDbgAssert(pbuf != NULL, "invalid null pointer");
+
+ if (macWaitReceiveDescriptor(ÐD1, &rd, TIME_IMMEDIATE) != MSG_OK)
+ return false;
+
+ len = (u16_t)rd.size;
+
+#if ETH_PAD_SIZE
+ len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
+#endif
+
+ /* We allocate a pbuf chain of pbufs from the pool. */
+ *pbuf = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+
+ if (*pbuf != NULL) {
+#if ETH_PAD_SIZE
+ pbuf_header(*pbuf, -ETH_PAD_SIZE); /* drop the padding word */
+#endif
+
+ /* Iterates through the pbuf chain. */
+ for(q = *pbuf; q != NULL; q = q->next)
+ macReadReceiveDescriptor(&rd, (uint8_t *)q->payload, (size_t)q->len);
+ macReleaseReceiveDescriptor(&rd);
+
+ MIB2_STATS_NETIF_ADD(netif, ifinoctets, (*pbuf)->tot_len);
+
+ if (*(uint8_t *)((*pbuf)->payload) & 1) {
+ /* broadcast or multicast packet*/
+ MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
+ }
+ else {
+ /* unicast packet*/
+ MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
+ }
+
+#if ETH_PAD_SIZE
+ pbuf_header(*pbuf, ETH_PAD_SIZE); /* reclaim the padding word */
+#endif
+
+ LINK_STATS_INC(link.recv);
+ }
+ else {
+ macReleaseReceiveDescriptor(&rd); // Drop packet
+ LINK_STATS_INC(link.memerr);
+ LINK_STATS_INC(link.drop);
+ MIB2_STATS_NETIF_INC(netif, ifindiscards);
+ }
+
+ return true;
+}
+
+/*
+ * Called at the beginning of the program to set up the
+ * network interface. It calls the function low_level_init() to do the
+ * actual setup of the hardware.
+ *
+ * This function should be passed as a parameter to netifapi_netif_add().
+ *
+ * @param netif the lwip network interface structure for this ethernetif
+ * @return ERR_OK if the loopif is initialised
+ * ERR_MEM if private data couldn't be allocated
+ * any other err_t on error
+ */
+static err_t ethernetif_init(struct netif *netif) {
+ osalDbgAssert((netif != NULL), "netif != NULL");
+
+ /*
+ * Initialize the snmp variables and counters inside the struct netif.
+ * The last argument should be replaced with your link speed, in units
+ * of bits per second.
+ */
+ MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LWIP_LINK_SPEED);
+
+ netif->state = NULL;
+ netif->name[0] = LWIP_IFNAME0;
+ netif->name[1] = LWIP_IFNAME1;
+ /* We directly use etharp_output() here to save a function call.
+ * You can instead declare your own function an call etharp_output()
+ * from it if you have to do some checks before sending (e.g. if link
+ * is available...) */
+ netif->output = etharp_output;
+ netif->linkoutput = low_level_output;
+
+ /* initialize the hardware */
+ low_level_init(netif);
+
+ return ERR_OK;
+}
+
+static net_addr_mode_t addressMode;
+static ip4_addr_t ip, gateway, netmask;
+static struct netif thisif;
+
+void lwipDefaultLinkUpCB(void *p)
+{
+ struct netif *ifc = (struct netif*) p;
+ (void) ifc;
+#if LWIP_AUTOIP
+ if (addressMode == NET_ADDRESS_AUTO)
+ autoip_start(ifc);
+#endif
+#if LWIP_DHCP
+ if (addressMode == NET_ADDRESS_DHCP)
+ dhcp_start(ifc);
+#endif
+}
+
+void lwipDefaultLinkDownCB(void *p)
+{
+ struct netif *ifc = (struct netif*) p;
+ (void) ifc;
+#if LWIP_AUTOIP
+ if (addressMode == NET_ADDRESS_AUTO)
+ autoip_stop(ifc);
+#endif
+#if LWIP_DHCP
+ if (addressMode == NET_ADDRESS_DHCP)
+ dhcp_stop(ifc);
+#endif
+}
+
+/**
+ * @brief LWIP handling thread.
+ *
+ * @param[in] p pointer to a @p lwipthread_opts structure or @p NULL
+ * @return The function does not return.
+ */
+static THD_FUNCTION(lwip_thread, p) {
+ event_timer_t evt;
+ event_listener_t el0, el1;
+ static const MACConfig mac_config = {thisif.hwaddr};
+ err_t result;
+ tcpip_callback_fn link_up_cb = NULL;
+ tcpip_callback_fn link_down_cb = NULL;
+
+ chRegSetThreadName(LWIP_THREAD_NAME);
+
+ /* Initializes the thing.*/
+ tcpip_init(NULL, NULL);
+
+ /* TCP/IP parameters, runtime or compile time.*/
+ if (p) {
+ lwipthread_opts_t *opts = p;
+ unsigned i;
+
+ for (i = 0; i < 6; i++)
+ thisif.hwaddr[i] = opts->macaddress[i];
+ ip.addr = opts->address;
+ gateway.addr = opts->gateway;
+ netmask.addr = opts->netmask;
+ addressMode = opts->addrMode;
+#if LWIP_NETIF_HOSTNAME
+ thisif.hostname = opts->ourHostName;
+#endif
+ link_up_cb = opts->link_up_cb;
+ link_down_cb = opts->link_down_cb;
+ }
+ else {
+ thisif.hwaddr[0] = LWIP_ETHADDR_0;
+ thisif.hwaddr[1] = LWIP_ETHADDR_1;
+ thisif.hwaddr[2] = LWIP_ETHADDR_2;
+ thisif.hwaddr[3] = LWIP_ETHADDR_3;
+ thisif.hwaddr[4] = LWIP_ETHADDR_4;
+ thisif.hwaddr[5] = LWIP_ETHADDR_5;
+ LWIP_IPADDR(&ip);
+ LWIP_GATEWAY(&gateway);
+ LWIP_NETMASK(&netmask);
+#if LWIP_DHCP
+ addressMode = NET_ADDRESS_DHCP;
+#elif LWIP_AUTOIP
+ addressMode = NET_ADDRESS_AUTO;
+#else
+ addressMode = NET_ADDRESS_STATIC;
+#endif
+#if LWIP_NETIF_HOSTNAME
+ thisif.hostname = NULL;
+#endif
+ }
+
+ if (!link_up_cb)
+ link_up_cb = lwipDefaultLinkUpCB;
+ if (!link_down_cb)
+ link_down_cb = lwipDefaultLinkDownCB;
+
+#if LWIP_NETIF_HOSTNAME
+ if (thisif.hostname == NULL)
+ thisif.hostname = LWIP_NETIF_HOSTNAME_STRING;
+#endif
+
+ macStart(ÐD1, &mac_config);
+
+ MIB2_INIT_NETIF(&thisif, snmp_ifType_ethernet_csmacd, 0);
+
+ /* Add interface. */
+ result = netifapi_netif_add(&thisif, &ip, &netmask, &gateway, NULL, ethernetif_init, tcpip_input);
+ if (result != ERR_OK)
+ {
+ chThdSleepMilliseconds(1000); // Give some time to print any other diagnostics.
+ osalSysHalt("netif_add error"); // Not sure what else we can do if an error occurs here.
+ };
+
+ netifapi_netif_set_default(&thisif);
+ netifapi_netif_set_up(&thisif);
+
+ /* Setup event sources.*/
+ evtObjectInit(&evt, LWIP_LINK_POLL_INTERVAL);
+ evtStart(&evt);
+ chEvtRegisterMask(&evt.et_es, &el0, PERIODIC_TIMER_ID);
+ chEvtRegisterMask(macGetReceiveEventSource(ÐD1), &el1, FRAME_RECEIVED_ID);
+ chEvtAddEvents(PERIODIC_TIMER_ID | FRAME_RECEIVED_ID);
+
+ /* Resumes the caller and goes to the final priority.*/
+ chThdResume(&lwip_trp, MSG_OK);
+ chThdSetPriority(LWIP_THREAD_PRIORITY);
+
+ while (true) {
+ eventmask_t mask = chEvtWaitAny(ALL_EVENTS);
+ if (mask & PERIODIC_TIMER_ID) {
+ bool current_link_status = macPollLinkStatus(ÐD1);
+ if (current_link_status != netif_is_link_up(&thisif)) {
+ if (current_link_status) {
+ tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_up,
+ &thisif, 0);
+ tcpip_callback_with_block(link_up_cb, &thisif, 0);
+ }
+ else {
+ tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_down,
+ &thisif, 0);
+ tcpip_callback_with_block(link_down_cb, &thisif, 0);
+ }
+ }
+ }
+
+ if (mask & FRAME_RECEIVED_ID) {
+ struct pbuf *p;
+ while (low_level_input(&thisif, &p)) {
+ if (p != NULL) {
+ struct eth_hdr *ethhdr = p->payload;
+ switch (htons(ethhdr->type)) {
+ /* IP or ARP packet? */
+ case ETHTYPE_IP:
+ case ETHTYPE_ARP:
+ /* full packet send to tcpip_thread to process */
+ if (thisif.input(p, &thisif) == ERR_OK)
+ break;
+ LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
+ /* Falls through */
+ default:
+ pbuf_free(p);
+ }
+ }
+ }
+ }
+ }
+}
+
+/**
+ * @brief Initializes the lwIP subsystem.
+ * @note The function exits after the initialization is finished.
+ *
+ * @param[in] opts pointer to the configuration structure, if @p NULL
+ * then the static configuration is used.
+ */
+void lwipInit(const lwipthread_opts_t *opts) {
+
+ /* Creating the lwIP thread (it changes priority internally).*/
+ chThdCreateStatic(wa_lwip_thread, sizeof (wa_lwip_thread),
+ chThdGetPriorityX() - 1, lwip_thread, (void *)opts);
+
+ /* Waiting for the lwIP thread complete initialization. Note,
+ this thread reaches the thread reference object first because
+ the relative priorities.*/
+ chSysLock();
+ chThdSuspendS(&lwip_trp);
+ chSysUnlock();
+}
+
+typedef struct lwip_reconf_params {
+ const lwipreconf_opts_t *opts;
+ semaphore_t completion;
+} lwip_reconf_params_t;
+
+static void do_reconfigure(void *p)
+{
+ lwip_reconf_params_t *reconf = (lwip_reconf_params_t*) p;
+
+ switch (addressMode) {
+#if LWIP_DHCP
+ case NET_ADDRESS_DHCP: {
+ if (netif_is_up(&thisif))
+ dhcp_stop(&thisif);
+ break;
+ }
+#endif
+ case NET_ADDRESS_STATIC: {
+ ip4_addr_t zero = { 0 };
+ netif_set_ipaddr(&thisif, &zero);
+ netif_set_netmask(&thisif, &zero);
+ netif_set_gw(&thisif, &zero);
+ break;
+ }
+#if LWIP_AUTOIP
+ case NET_ADDRESS_AUTO: {
+ if (netif_is_up(&thisif))
+ autoip_stop(&thisif);
+ break;
+ }
+#endif
+ }
+
+ ip.addr = reconf->opts->address;
+ gateway.addr = reconf->opts->gateway;
+ netmask.addr = reconf->opts->netmask;
+ addressMode = reconf->opts->addrMode;
+
+ switch (addressMode) {
+#if LWIP_DHCP
+ case NET_ADDRESS_DHCP: {
+ if (netif_is_up(&thisif))
+ dhcp_start(&thisif);
+ break;
+ }
+#endif
+ case NET_ADDRESS_STATIC: {
+ netif_set_ipaddr(&thisif, &ip);
+ netif_set_netmask(&thisif, &netmask);
+ netif_set_gw(&thisif, &gateway);
+ break;
+ }
+#if LWIP_AUTOIP
+ case NET_ADDRESS_AUTO: {
+ if (netif_is_up(&thisif))
+ autoip_start(&thisif);
+ break;
+ }
+#endif
+ }
+
+ chSemSignal(&reconf->completion);
+}
+
+void lwipReconfigure(const lwipreconf_opts_t *opts)
+{
+ lwip_reconf_params_t params;
+ params.opts = opts;
+ chSemObjectInit(¶ms.completion, 0);
+ tcpip_callback_with_block(do_reconfigure, ¶ms, 0);
+ chSemWait(¶ms.completion);
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/various/lwip_bindings/lwipthread.h b/ChibiOS_20.3.2/os/various/lwip_bindings/lwipthread.h
new file mode 100644
index 0000000..b40d05f
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/lwip_bindings/lwipthread.h
@@ -0,0 +1,275 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file lwipthread.h
+ * @brief LWIP wrapper thread macros and structures.
+ * @addtogroup LWIP_THREAD
+ * @{
+ */
+
+#ifndef LWIPTHREAD_H
+#define LWIPTHREAD_H
+
+#include
+
+/**
+ * @brief lwIP default network interface maximum transmission unit (MTU).
+ */
+#if !defined(LWIP_NETIF_MTU) || defined(__DOXYGEN__)
+#define LWIP_NETIF_MTU 1500
+#endif
+
+/**
+ * @brief Default network interface hostname.
+ */
+#if !defined(LWIP_NETIF_HOSTNAME_STRING) || defined(__DOXYGEN__)
+#define LWIP_NETIF_HOSTNAME_STRING "lwip"
+#endif
+
+/**
+ * @brief Default network interface hostname.
+ */
+#if !defined(LWIP_THREAD_NAME) || defined(__DOXYGEN__)
+#define LWIP_THREAD_NAME "lwipthread"
+#endif
+
+/**
+ * @brief lwIP thread priority.
+ */
+#ifndef LWIP_THREAD_PRIORITY
+#define LWIP_THREAD_PRIORITY LOWPRIO
+#endif
+
+/**
+ * @brief lwIP thread stack size.
+ */
+#if !defined(LWIP_THREAD_STACK_SIZE) || defined(__DOXYGEN__)
+#define LWIP_THREAD_STACK_SIZE 672
+#endif
+
+/**
+ * @brief Link poll interval.
+ */
+#if !defined(LWIP_LINK_POLL_INTERVAL) || defined(__DOXYGEN__)
+#define LWIP_LINK_POLL_INTERVAL TIME_S2I(5)
+#endif
+
+/**
+ * @brief IP Address.
+ */
+#if !defined(LWIP_IPADDR) || defined(__DOXYGEN__)
+#define LWIP_IPADDR(p) IP4_ADDR(p, 192, 168, 1, 10)
+#endif
+
+/**
+ * @brief IP Gateway.
+ */
+#if !defined(LWIP_GATEWAY) || defined(__DOXYGEN__)
+#define LWIP_GATEWAY(p) IP4_ADDR(p, 192, 168, 1, 1)
+#endif
+
+/**
+ * @brief IP netmask.
+ */
+#if !defined(LWIP_NETMASK) || defined(__DOXYGEN__)
+#define LWIP_NETMASK(p) IP4_ADDR(p, 255, 255, 255, 0)
+#endif
+
+/**
+ * @brief Transmission timeout.
+ */
+#if !defined(LWIP_SEND_TIMEOUT) || defined(__DOXYGEN__)
+#define LWIP_SEND_TIMEOUT 50
+#endif
+
+/**
+ * @brief Link speed.
+ */
+#if !defined(LWIP_LINK_SPEED) || defined(__DOXYGEN__)
+#define LWIP_LINK_SPEED 100000000
+#endif
+
+/**
+ * @brief MAC Address byte 0.
+ */
+#if !defined(LWIP_ETHADDR_0) || defined(__DOXYGEN__)
+#define LWIP_ETHADDR_0 0xC2
+#endif
+
+/**
+ * @brief MAC Address byte 1.
+ */
+#if !defined(LWIP_ETHADDR_1) || defined(__DOXYGEN__)
+#define LWIP_ETHADDR_1 0xAF
+#endif
+
+/**
+ * @brief MAC Address byte 2.
+ */
+#if !defined(LWIP_ETHADDR_2) || defined(__DOXYGEN__)
+#define LWIP_ETHADDR_2 0x51
+#endif
+
+/**
+ * @brief MAC Address byte 3.
+ */
+#if !defined(LWIP_ETHADDR_3) || defined(__DOXYGEN__)
+#define LWIP_ETHADDR_3 0x03
+#endif
+
+/**
+ * @brief MAC Address byte 4.
+ */
+#if !defined(LWIP_ETHADDR_4) || defined(__DOXYGEN__)
+#define LWIP_ETHADDR_4 0xCF
+#endif
+
+/**
+ * @brief MAC Address byte 5.
+ */
+#if !defined(LWIP_ETHADDR_5) || defined(__DOXYGEN__)
+#define LWIP_ETHADDR_5 0x46
+#endif
+
+/**
+ * @brief Interface name byte 0.
+ */
+#if !defined(LWIP_IFNAME0) || defined(__DOXYGEN__)
+#define LWIP_IFNAME0 'm'
+#endif
+
+/**
+ * @brief Interface name byte 1.
+ */
+#if !defined(LWIP_IFNAME1) || defined(__DOXYGEN__)
+#define LWIP_IFNAME1 's'
+#endif
+
+/**
+ * @brief Utility macro to define an IPv4 address.
+ *
+ * @note Within the networking subsystem, IPv4 network addresses are
+ * stored with LS byte of network address in MS byte of unsigned int.
+ */
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define IP4_ADDR_VALUE(a,b,c,d) \
+ (((u32_t)((d) & 0xff) << 24) | \
+ ((u32_t)((c) & 0xff) << 16) | \
+ ((u32_t)((b) & 0xff) << 8) | \
+ (u32_t)((a) & 0xff))
+#else
+#define IP4_ADDR_VALUE(a,b,c,d) \
+ (((u32_t)((a) & 0xff) << 24) | \
+ ((u32_t)((b) & 0xff) << 16) | \
+ ((u32_t)((c) & 0xff) << 8) | \
+ (u32_t)((d) & 0xff))
+#endif
+
+/**
+ * @brief Startup network assigning modes.
+ */
+typedef enum {
+#if LWIP_DHCP || defined(__DOXYGEN__)
+ /**
+ * @brief Assign a DHCP given address.
+ */
+ NET_ADDRESS_DHCP = 1,
+#endif
+ /**
+ * @brief Assign a statically IPv4 address.
+ */
+ NET_ADDRESS_STATIC = 2,
+#if LWIP_AUTOIP || defined(__DOXYGEN__)
+ /**
+ * @brief Assign an IPv4 link-Local address.
+ */
+ NET_ADDRESS_AUTO = 3
+#endif
+} net_addr_mode_t;
+
+/**
+ * @brief Runtime TCP/IP settings.
+ */
+typedef struct lwipthread_opts {
+ /**
+ * @brief Pointer to MAC address as an array of 6 unsigned bytes.
+ */
+ uint8_t *macaddress;
+ /**
+ * @brief Network address as 32-bit unsigned integer.
+ */
+ uint32_t address;
+ /**
+ * @brief Network subnet mask as 32-bit unsigned integer.
+ */
+ uint32_t netmask;
+ /**
+ * @brief Network gateway as 32-bit unsigned integer.
+ */
+ uint32_t gateway;
+ /**
+ * @brief Startup network addressing mode - static, DHCP, auto.
+ */
+ net_addr_mode_t addrMode;
+ /**
+ * @brief Host name. If NULL, a default string is used.
+ * @note Not checked for validity. In particular, spaces not allowed.
+ */
+#if LWIP_NETIF_HOSTNAME || defined(__DOXYGEN__)
+ const char *ourHostName;
+#endif
+ /**
+ * @brief Link up callback.
+ *
+ * @note Called from the tcpip thread when the link goes up.
+ * Can be NULL to default to lwipDefaultLinkUpCB.
+ */
+ void (*link_up_cb)(void*);
+ /**
+ * @brief Link down callback.
+ *
+ * @note Called from the tcpip thread when the link goes down.
+ * Can be NULL to default to lwipDefaultLinkDownCB.
+ */
+ void (*link_down_cb)(void*);
+} lwipthread_opts_t;
+
+/**
+ * @brief Parameters for lwipReconfigure.
+ * @note Same meaning as in lwipthread_opts_t.
+ */
+typedef struct lwipreconf_opts {
+ uint32_t address;
+ uint32_t netmask;
+ uint32_t gateway;
+ net_addr_mode_t addrMode;
+} lwipreconf_opts_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void lwipDefaultLinkUpCB(void *p);
+ void lwipDefaultLinkDownCB(void *p);
+ void lwipInit(const lwipthread_opts_t *opts);
+ void lwipReconfigure(const lwipreconf_opts_t *opts);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LWIPTHREAD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/various/lwip_bindings/readme.txt b/ChibiOS_20.3.2/os/various/lwip_bindings/readme.txt
new file mode 100644
index 0000000..07544e2
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/lwip_bindings/readme.txt
@@ -0,0 +1,6 @@
+This directory contains the ChibiOS "official" bindings with the lwIP
+TCP/IP stack: http://savannah.nongnu.org/projects/lwip
+
+In order to use lwIP within ChibiOS/RT project, unzip lwIP under
+./ext/lwip then include $(CHIBIOS)/os/various/lwip_bindings/lwip.mk
+in your makefile.
diff --git a/ChibiOS_20.3.2/os/various/lwip_bindings/static_lwipopts.h b/ChibiOS_20.3.2/os/various/lwip_bindings/static_lwipopts.h
new file mode 100644
index 0000000..7baa387
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/lwip_bindings/static_lwipopts.h
@@ -0,0 +1,42 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file static_lwipopts.h
+ *
+ * @addtogroup static_lwipopts
+ * @{
+ */
+
+#ifndef STATIC_LWIPOPTS_H
+#define STATIC_LWIPOPTS_H
+
+#define NO_SYS 0
+
+#define LWIP_TIMERS 1
+#define LWIP_TIMERS_CUSTOM 0
+
+#define LWIP_TCPIP_CORE_LOCKING 1
+#define LWIP_TCPIP_CORE_LOCKING_INPUT 0
+#define LWIP_COMPAT_MUTEX_ALLOWED
+
+#define SYS_LIGHTWEIGHT_PROT 1
+
+#define MEM_ALIGNMENT 4
+
+#endif /* STATIC_LWIPOPTS_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/various/shell/shell.c b/ChibiOS_20.3.2/os/various/shell/shell.c
new file mode 100644
index 0000000..19db9aa
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/shell/shell.c
@@ -0,0 +1,604 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file shell.c
+ * @brief Simple CLI shell code.
+ *
+ * @addtogroup SHELL
+ * @{
+ */
+
+#include
+
+#include "ch.h"
+#include "hal.h"
+#include "shell.h"
+#include "shell_cmd.h"
+#include "chprintf.h"
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+#if !defined(_CHIBIOS_NIL_) || defined(__DOXYGEN__)
+/**
+ * @brief Shell termination event source.
+ */
+event_source_t shell_terminated;
+#endif
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+static char *parse_arguments(char *str, char **saveptr) {
+ char *p;
+
+ if (str != NULL)
+ *saveptr = str;
+
+ p = *saveptr;
+ if (!p) {
+ return NULL;
+ }
+
+ /* Skipping white space.*/
+ p += strspn(p, " \t");
+
+ if (*p == '"') {
+ /* If an argument starts with a double quote then its delimiter is another
+ quote.*/
+ p++;
+ *saveptr = strpbrk(p, "\"");
+ }
+ else {
+ /* The delimiter is white space.*/
+ *saveptr = strpbrk(p, " \t");
+ }
+
+ /* Replacing the delimiter with a zero.*/
+ if (*saveptr != NULL) {
+ *(*saveptr)++ = '\0';
+ }
+
+ return *p != '\0' ? p : NULL;
+}
+
+static void list_commands(BaseSequentialStream *chp, const ShellCommand *scp) {
+
+ while (scp->sc_name != NULL) {
+ chprintf(chp, "%s ", scp->sc_name);
+ scp++;
+ }
+}
+
+static bool cmdexec(const ShellCommand *scp, BaseSequentialStream *chp,
+ char *name, int argc, char *argv[]) {
+
+ while (scp->sc_name != NULL) {
+ if (strcmp(scp->sc_name, name) == 0) {
+ scp->sc_function(chp, argc, argv);
+ return false;
+ }
+ scp++;
+ }
+ return true;
+}
+
+#if (SHELL_USE_HISTORY == TRUE) || defined(__DOXYGEN__)
+static void del_histbuff_entry(ShellHistory *shp) {
+ int pos = shp->sh_beg + *(shp->sh_buffer + shp->sh_beg) + 1;
+
+ if (pos >= shp->sh_size)
+ pos -= shp->sh_size;
+
+ shp->sh_beg = pos;
+}
+
+static bool is_histbuff_space(ShellHistory *shp, int length) {
+
+ if (shp->sh_end >= shp->sh_beg) {
+ if (length < (shp->sh_size - (shp->sh_end - shp->sh_beg + 1)))
+ return true;
+ }
+ else {
+ if (length < (shp->sh_beg - shp->sh_end - 1))
+ return true;
+ }
+
+ return false;
+}
+
+static void save_history(ShellHistory *shp, char *line, int length) {
+
+ if (shp == NULL)
+ return;
+
+ if (length > shp->sh_size - 2)
+ return;
+
+ while ((*(line + length -1) == ' ') && (length > 0))
+ length--;
+
+ if (length <= 0)
+ return;
+
+ while (!is_histbuff_space(shp, length))
+ del_histbuff_entry(shp);
+
+ if (length < shp->sh_size - shp->sh_end - 1)
+ memcpy(shp->sh_buffer + shp->sh_end + 1, line, length);
+ else {
+ /*
+ * Since there isn't enough room left at the end of the buffer,
+ * split the line to save up to the end of the buffer and then
+ * wrap back to the beginning of the buffer.
+ */
+ int part_len = shp->sh_size - shp->sh_end - 1;
+ memcpy(shp->sh_buffer + shp->sh_end + 1, line, part_len);
+ memcpy(shp->sh_buffer, line + part_len, length - part_len);
+ }
+
+ /* Save the length of the current line and move the buffer end pointer */
+ *(shp->sh_buffer + shp->sh_end) = (char)length;
+ shp->sh_end += length + 1;
+ if (shp->sh_end >= shp->sh_size)
+ shp->sh_end -= shp->sh_size;
+ *(shp->sh_buffer + shp->sh_end) = 0;
+ shp->sh_cur = 0;
+}
+
+static int get_history(ShellHistory *shp, char *line, int dir) {
+ int count=0;
+
+ if (shp == NULL)
+ return -1;
+
+ /* Count the number of lines saved in the buffer */
+ int idx = shp->sh_beg;
+ while (idx != shp->sh_end) {
+ idx += *(shp->sh_buffer + idx) + 1;
+ if (idx >= shp->sh_size)
+ idx -= shp->sh_size;
+ count++;
+ }
+
+ if (dir == SHELL_HIST_DIR_FW) {
+ if (shp->sh_cur > 0)
+ shp->sh_cur -= 2;
+ else
+ return 0;
+ }
+
+ if (count >= shp->sh_cur) {
+ idx = shp->sh_beg;
+ int i = 0;
+ while (idx != shp->sh_end && shp->sh_cur != (count - i - 1)) {
+ idx += *(shp->sh_buffer + idx) + 1;
+ if (idx >= shp->sh_size)
+ idx -= shp->sh_size;
+ i++;
+ }
+
+ int length = *(shp->sh_buffer + idx);
+
+ if (length > 0) {
+ shp->sh_cur++;
+
+ memset(line, 0, SHELL_MAX_LINE_LENGTH);
+ if ((idx + length) < shp->sh_size) {
+ memcpy(line, (shp->sh_buffer + idx + 1), length);
+ }
+ else {
+ /*
+ * Since the saved line was split at the end of the buffer,
+ * get the line in two parts.
+ */
+ int part_len = shp->sh_size - idx - 1;
+ memcpy(line, shp->sh_buffer + idx + 1, part_len);
+ memcpy(line + part_len, shp->sh_buffer, length - part_len);
+ }
+ return length;
+ }
+ else if (dir == SHELL_HIST_DIR_FW) {
+ shp->sh_cur++;
+ return 0;
+ }
+ }
+ return -1;
+}
+#endif
+
+#if (SHELL_USE_COMPLETION == TRUE) || defined(__DOXYGEN__)
+static void get_completions(ShellConfig *scfg, char *line) {
+ const ShellCommand *lcp = shell_local_commands;
+ const ShellCommand *scp = scfg->sc_commands;
+ char **scmp = scfg->sc_completion;
+ char help_cmp[] = "help";
+
+ if (strstr(help_cmp, line) == help_cmp) {
+ *scmp++ = help_cmp;
+ }
+ while (lcp->sc_name != NULL) {
+ if (strstr(lcp->sc_name, line) == lcp->sc_name) {
+ *scmp++ = (char *)lcp->sc_name;
+ }
+ lcp++;
+ }
+ if (scp != NULL) {
+ while (scp->sc_name != NULL) {
+ if (strstr(scp->sc_name, line) == scp->sc_name) {
+ *scmp++ = (char *)scp->sc_name;
+ }
+ scp++;
+ }
+ }
+
+ *scmp = NULL;
+}
+
+static int process_completions(ShellConfig *scfg, char *line, int length, unsigned size) {
+ char **scmp = scfg->sc_completion;
+ char **cmp = scmp + 1;
+ char *c = line + length;
+ int clen = 0;
+
+ if (*scmp != NULL) {
+ if (*cmp == NULL) {
+ clen = strlen(*scmp);
+ int i = length;
+ while ((c < line + clen) && (c < line + size - 1))
+ *c++ = *(*scmp + i++);
+ if (c < line + size -1) {
+ *c = ' ';
+ clen++;
+ }
+ }
+ else {
+ while (*(*scmp + clen) != 0) {
+ while ((*(*scmp + clen) == *(*cmp + clen)) &&
+ (*(*cmp + clen) != 0) && (*cmp != NULL)) {
+ cmp++;
+ }
+ if (*cmp == NULL) {
+ if ((c < line + size - 1) && (clen >= length))
+ *c++ = *(*scmp + clen);
+ cmp = scmp + 1;
+ clen++;
+ }
+ else {
+ break;
+ }
+ }
+ }
+
+ *(line + clen) = 0;
+ }
+
+ return clen;
+}
+
+static void write_completions(ShellConfig *scfg, char *line, int pos) {
+ BaseSequentialStream *chp = scfg->sc_channel;
+ char **scmp = scfg->sc_completion;
+
+ if (*(scmp + 1) != NULL) {
+ chprintf(chp, SHELL_NEWLINE_STR);
+ while (*scmp != NULL)
+ chprintf(chp, " %s", *scmp++);
+ chprintf(chp, SHELL_NEWLINE_STR);
+
+ chprintf(chp, SHELL_PROMPT_STR);
+ chprintf(chp, "%s", line);
+ }
+ else {
+ chprintf(chp, "%s", line + pos);
+ }
+}
+#endif
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Shell thread function.
+ *
+ * @param[in] p pointer to a @p BaseSequentialStream object
+ */
+THD_FUNCTION(shellThread, p) {
+ int n;
+ ShellConfig *scfg = p;
+ BaseSequentialStream *chp = scfg->sc_channel;
+ const ShellCommand *scp = scfg->sc_commands;
+ char *lp, *cmd, *tokp, line[SHELL_MAX_LINE_LENGTH];
+ char *args[SHELL_MAX_ARGUMENTS + 1];
+
+#if !defined(_CHIBIOS_NIL_)
+ chRegSetThreadName(SHELL_THREAD_NAME);
+#endif
+
+#if SHELL_USE_HISTORY == TRUE
+ *(scfg->sc_histbuf) = 0;
+ ShellHistory hist = {
+ scfg->sc_histbuf,
+ scfg->sc_histsize,
+ 0,
+ 0,
+ 0
+ };
+ ShellHistory *shp = &hist;
+#else
+ ShellHistory *shp = NULL;
+#endif
+
+ chprintf(chp, SHELL_NEWLINE_STR);
+ chprintf(chp, "ChibiOS/RT Shell" SHELL_NEWLINE_STR);
+#if !defined(_CHIBIOS_NIL_)
+ while (!chThdShouldTerminateX()) {
+#else
+ while (true) {
+#endif
+ chprintf(chp, SHELL_PROMPT_STR);
+ if (shellGetLine(scfg, line, sizeof(line), shp)) {
+#if (SHELL_CMD_EXIT_ENABLED == TRUE) && !defined(_CHIBIOS_NIL_)
+ chprintf(chp, SHELL_NEWLINE_STR);
+ chprintf(chp, "logout");
+ break;
+#else
+ /* Putting a delay in order to avoid an endless loop trying to read
+ an unavailable stream.*/
+ osalThreadSleepMilliseconds(100);
+#endif
+ }
+ lp = parse_arguments(line, &tokp);
+ cmd = lp;
+ n = 0;
+ while ((lp = parse_arguments(NULL, &tokp)) != NULL) {
+ if (n >= SHELL_MAX_ARGUMENTS) {
+ chprintf(chp, "too many arguments" SHELL_NEWLINE_STR);
+ cmd = NULL;
+ break;
+ }
+ args[n++] = lp;
+ }
+ args[n] = NULL;
+ if (cmd != NULL) {
+ if (strcmp(cmd, "help") == 0) {
+ if (n > 0) {
+ shellUsage(chp, "help");
+ continue;
+ }
+ chprintf(chp, "Commands: help ");
+ list_commands(chp, shell_local_commands);
+ if (scp != NULL)
+ list_commands(chp, scp);
+ chprintf(chp, SHELL_NEWLINE_STR);
+ }
+ else if (cmdexec(shell_local_commands, chp, cmd, n, args) &&
+ ((scp == NULL) || cmdexec(scp, chp, cmd, n, args))) {
+ chprintf(chp, "%s", cmd);
+ chprintf(chp, " ?" SHELL_NEWLINE_STR);
+ }
+ }
+ }
+#if !defined(_CHIBIOS_NIL_)
+ shellExit(MSG_OK);
+#endif
+}
+
+/**
+ * @brief Shell manager initialization.
+ *
+ * @api
+ */
+void shellInit(void) {
+
+#if !defined(_CHIBIOS_NIL_)
+ chEvtObjectInit(&shell_terminated);
+#endif
+}
+
+#if !defined(_CHIBIOS_NIL_) || defined(__DOXYGEN__)
+/**
+ * @brief Terminates the shell.
+ * @note Must be invoked from the command handlers.
+ * @note Does not return.
+ *
+ * @param[in] msg shell exit code
+ *
+ * @api
+ */
+void shellExit(msg_t msg) {
+
+ /* Atomically broadcasting the event source and terminating the thread,
+ there is not a chSysUnlock() because the thread terminates upon return.*/
+ chSysLock();
+ chEvtBroadcastI(&shell_terminated);
+ chThdExitS(msg);
+}
+#endif
+
+/**
+ * @brief Reads a whole line from the input channel.
+ * @note Input chars are echoed on the same stream object with the
+ * following exceptions:
+ * - DEL and BS are echoed as BS-SPACE-BS.
+ * - CR is echoed as CR-LF.
+ * - 0x4 is echoed as "^D".
+ * - Other values below 0x20 are not echoed.
+ * .
+ *
+ * @param[in] scfg pointer to a @p ShellConfig object
+ * @param[in] line pointer to the line buffer
+ * @param[in] size buffer maximum length
+ * @param[in] shp pointer to a @p ShellHistory object or NULL
+ * @return The operation status.
+ * @retval true the channel was reset or CTRL-D pressed.
+ * @retval false operation successful.
+ *
+ * @api
+ */
+bool shellGetLine(ShellConfig *scfg, char *line, unsigned size, ShellHistory *shp) {
+ char *p = line;
+ BaseSequentialStream *chp = scfg->sc_channel;
+#if SHELL_USE_ESC_SEQ == TRUE
+ bool escape = false;
+ bool bracket = false;
+#endif
+
+#if SHELL_USE_HISTORY != TRUE
+ (void) shp;
+#endif
+
+ while (true) {
+ char c;
+
+ if (streamRead(chp, (uint8_t *)&c, 1) == 0)
+ return true;
+#if SHELL_USE_ESC_SEQ == TRUE
+ if (c == 27) {
+ escape = true;
+ continue;
+ }
+ if (escape) {
+ escape = false;
+ if (c == '[') {
+ escape = true;
+ bracket = true;
+ continue;
+ }
+ if (bracket) {
+ bracket = false;
+#if SHELL_USE_HISTORY == TRUE
+ if (c == 'A') {
+ int len = get_history(shp, line, SHELL_HIST_DIR_BK);
+
+ if (len > 0) {
+ _shell_reset_cur(chp);
+ _shell_clr_line(chp);
+ chprintf(chp, "%s", line);
+ p = line + len;
+ }
+ continue;
+ }
+ if (c == 'B') {
+ int len = get_history(shp, line, SHELL_HIST_DIR_FW);
+
+ if (len == 0)
+ *line = 0;
+
+ if (len >= 0) {
+ _shell_reset_cur(chp);
+ _shell_clr_line(chp);
+ chprintf(chp, "%s", line);
+ p = line + len;
+ }
+ continue;
+ }
+#endif
+ }
+ continue;
+ }
+#endif
+#if (SHELL_CMD_EXIT_ENABLED == TRUE) && !defined(_CHIBIOS_NIL_)
+ if (c == 4) {
+ chprintf(chp, "^D");
+ return true;
+ }
+#endif
+ if ((c == 8) || (c == 127)) {
+ if (p != line) {
+ streamPut(chp, 0x08);
+ streamPut(chp, 0x20);
+ streamPut(chp, 0x08);
+ p--;
+ }
+ continue;
+ }
+ if (c == '\r') {
+ chprintf(chp, SHELL_NEWLINE_STR);
+#if SHELL_USE_HISTORY == TRUE
+ save_history(shp, line, p - line);
+#endif
+ *p = 0;
+ return false;
+ }
+#if SHELL_USE_COMPLETION == TRUE
+ if (c == '\t') {
+ if (p < line + size - 1) {
+ *p = 0;
+
+ get_completions(scfg, line);
+ int len = process_completions(scfg, line, p - line, size);
+ if (len > 0) {
+ write_completions(scfg, line, p - line);
+ p = line + len;
+ }
+ }
+ continue;
+ }
+#endif
+#if SHELL_USE_HISTORY == TRUE
+ if (c == 14) {
+ int len = get_history(shp, line, SHELL_HIST_DIR_FW);
+
+ if (len == 0)
+ *line = 0;
+
+ if (len >= 0) {
+ _shell_reset_cur(chp);
+ _shell_clr_line(chp);
+ chprintf(chp, "%s", line);
+ p = line + len;
+ }
+ continue;
+ }
+ if (c == 16) {
+ int len = get_history(shp, line, SHELL_HIST_DIR_BK);
+
+ if (len > 0) {
+ _shell_reset_cur(chp);
+ _shell_clr_line(chp);
+ chprintf(chp, "%s", line);
+ p = line + len;
+ }
+ continue;
+ }
+#endif
+ if (c < 0x20)
+ continue;
+ if (p < line + size - 1) {
+ streamPut(chp, c);
+ *p++ = (char)c;
+ }
+ }
+}
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/various/shell/shell.h b/ChibiOS_20.3.2/os/various/shell/shell.h
new file mode 100644
index 0000000..d11adc0
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/shell/shell.h
@@ -0,0 +1,235 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file shell.h
+ * @brief Simple CLI shell header.
+ *
+ * @addtogroup SHELL
+ * @{
+ */
+
+#ifndef SHELL_H
+#define SHELL_H
+
+#if defined(SHELL_CONFIG_FILE)
+#include "shellconf.h"
+#endif
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @brief Shell History Constants
+ */
+#define SHELL_HIST_DIR_BK 0
+#define SHELL_HIST_DIR_FW 1
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Shell maximum input line length.
+ */
+#if !defined(SHELL_MAX_LINE_LENGTH) || defined(__DOXYGEN__)
+#define SHELL_MAX_LINE_LENGTH 64
+#endif
+
+/**
+ * @brief Shell maximum arguments per command.
+ */
+#if !defined(SHELL_MAX_ARGUMENTS) || defined(__DOXYGEN__)
+#define SHELL_MAX_ARGUMENTS 4
+#endif
+
+/**
+ * @brief Shell maximum command history.
+ */
+#if !defined(SHELL_MAX_HIST_BUFF) || defined(__DOXYGEN__)
+#define SHELL_MAX_HIST_BUFF 8 * SHELL_MAX_LINE_LENGTH
+#endif
+
+/**
+ * @brief Enable shell command history
+ */
+#if !defined(SHELL_USE_HISTORY) || defined(__DOXYGEN__)
+#define SHELL_USE_HISTORY FALSE
+#endif
+
+/**
+ * @brief Enable shell command completion
+ */
+#if !defined(SHELL_USE_COMPLETION) || defined(__DOXYGEN__)
+#define SHELL_USE_COMPLETION FALSE
+#endif
+
+/**
+ * @brief Shell Maximum Completions (Set to max commands with common prefix)
+ */
+#if !defined(SHELL_MAX_COMPLETIONS) || defined(__DOXYGEN__)
+#define SHELL_MAX_COMPLETIONS 8
+#endif
+
+/**
+ * @brief Enable shell escape sequence processing
+ */
+#if !defined(SHELL_USE_ESC_SEQ) || defined(__DOXYGEN__)
+#define SHELL_USE_ESC_SEQ FALSE
+#endif
+
+/**
+ * @brief Prompt string
+ */
+#if !defined(SHELL_PROMPT_STR) || defined(__DOXYGEN__)
+#define SHELL_PROMPT_STR "ch> "
+#endif
+
+/**
+ * @brief Newline string
+ */
+#if !defined(SHELL_NEWLINE_STR) || defined(__DOXYGEN__)
+#define SHELL_NEWLINE_STR "\r\n"
+#endif
+
+/**
+ * @brief Default shell thread name.
+ */
+#if !defined(SHELL_THREAD_NAME) || defined(__DOXYGEN__)
+#define SHELL_THREAD_NAME "shell"
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/**
+ * @brief Command handler function type.
+ */
+typedef void (*shellcmd_t)(BaseSequentialStream *chp, int argc, char *argv[]);
+
+/**
+ * @brief Custom command entry type.
+ */
+typedef struct {
+ const char *sc_name; /**< @brief Command name. */
+ shellcmd_t sc_function; /**< @brief Command function. */
+} ShellCommand;
+
+/**
+ * @brief Shell history type.
+ */
+typedef struct {
+ char *sh_buffer; /**< @brief Buffer to store command
+ history. */
+ const int sh_size; /**< @brief Shell history buffer
+ size. */
+ int sh_beg; /**< @brief Beginning command index
+ in buffer. */
+ int sh_end; /**< @brief Ending command index
+ in buffer. */
+ int sh_cur; /**< @brief Currently selected
+ command in buffer. */
+} ShellHistory;
+
+/**
+ * @brief Shell descriptor type.
+ */
+typedef struct {
+ BaseSequentialStream *sc_channel; /**< @brief I/O channel associated
+ to the shell. */
+ const ShellCommand *sc_commands; /**< @brief Shell extra commands
+ table. */
+#if (SHELL_USE_HISTORY == TRUE) || defined(__DOXYGEN__)
+ char *sc_histbuf; /**< @brief Shell command history
+ buffer. */
+ const int sc_histsize; /**< @brief Shell history buffer
+ size. */
+#endif
+#if (SHELL_USE_COMPLETION == TRUE) || defined(__DOXYGEN__)
+ char **sc_completion; /**< @brief Shell command completion
+ buffer. */
+#endif
+} ShellConfig;
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief Send escape codes to move cursor to the beginning of the line
+ *
+ * @param[in] stream pointer to a @p BaseSequentialStream object
+ *
+ * @notapi
+ */
+#define _shell_reset_cur(stream) chprintf(stream, "\033[%dD\033[%dC", \
+ SHELL_MAX_LINE_LENGTH + \
+ strlen(SHELL_PROMPT_STR) + 2, \
+ strlen(SHELL_PROMPT_STR))
+
+/**
+ * @brief Send escape codes to clear the rest of the line
+ *
+ * @param[in] stream pointer to a @p BaseSequentialStream object
+ *
+ * @notapi
+ */
+#define _shell_clr_line(stream) chprintf(stream, "\033[K")
+
+/**
+ * @brief Prints out usage message
+ *
+ * @param[in] stream pointer to a @p BaseSequentialStream object
+ * @param[in] message pointer to message string
+ *
+ * @api
+ */
+#define shellUsage(stream, message) \
+ chprintf(stream, "Usage: %s" SHELL_NEWLINE_STR, message)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern event_source_t shell_terminated;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void shellInit(void);
+ THD_FUNCTION(shellThread, p);
+ void shellExit(msg_t msg);
+ bool shellGetLine(ShellConfig *scfg, char *line,
+ unsigned size, ShellHistory *shp);
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* SHELL_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/various/shell/shell.mk b/ChibiOS_20.3.2/os/various/shell/shell.mk
new file mode 100644
index 0000000..dfe901a
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/shell/shell.mk
@@ -0,0 +1,9 @@
+# RT Shell files.
+SHELLSRC = $(CHIBIOS)/os/various/shell/shell.c \
+ $(CHIBIOS)/os/various/shell/shell_cmd.c
+
+SHELLINC = $(CHIBIOS)/os/various/shell
+
+# Shared variables
+ALLCSRC += $(SHELLSRC)
+ALLINC += $(SHELLINC)
diff --git a/ChibiOS_20.3.2/os/various/shell/shell_cmd.c b/ChibiOS_20.3.2/os/various/shell/shell_cmd.c
new file mode 100644
index 0000000..525f269
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/shell/shell_cmd.c
@@ -0,0 +1,247 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file shell_cmd.c
+ * @brief Simple CLI shell common commands code.
+ *
+ * @addtogroup SHELL
+ * @{
+ */
+
+#include
+
+#include "ch.h"
+#include "hal.h"
+#include "shell.h"
+#include "shell_cmd.h"
+#include "chprintf.h"
+
+#if (SHELL_CMD_TEST_ENABLED == TRUE) || defined(__DOXYGEN__)
+#include "rt_test_root.h"
+#include "oslib_test_root.h"
+#endif
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+#if ((SHELL_CMD_EXIT_ENABLED == TRUE) && !defined(_CHIBIOS_NIL_)) || \
+ defined(__DOXYGEN__)
+static void cmd_exit(BaseSequentialStream *chp, int argc, char *argv[]) {
+
+ (void)argv;
+ if (argc > 0) {
+ shellUsage(chp, "exit");
+ return;
+ }
+
+ shellExit(MSG_OK);
+}
+#endif
+
+#if (SHELL_CMD_INFO_ENABLED == TRUE) || defined(__DOXYGEN__)
+static void cmd_info(BaseSequentialStream *chp, int argc, char *argv[]) {
+
+ (void)argv;
+ if (argc > 0) {
+ shellUsage(chp, "info");
+ return;
+ }
+
+ chprintf(chp, "Kernel: %s" SHELL_NEWLINE_STR, CH_KERNEL_VERSION);
+#ifdef PORT_COMPILER_NAME
+ chprintf(chp, "Compiler: %s" SHELL_NEWLINE_STR, PORT_COMPILER_NAME);
+#endif
+ chprintf(chp, "Architecture: %s" SHELL_NEWLINE_STR, PORT_ARCHITECTURE_NAME);
+#ifdef PORT_CORE_VARIANT_NAME
+ chprintf(chp, "Core Variant: %s" SHELL_NEWLINE_STR, PORT_CORE_VARIANT_NAME);
+#endif
+#ifdef PORT_INFO
+ chprintf(chp, "Port Info: %s" SHELL_NEWLINE_STR, PORT_INFO);
+#endif
+#ifdef PLATFORM_NAME
+ chprintf(chp, "Platform: %s" SHELL_NEWLINE_STR, PLATFORM_NAME);
+#endif
+#ifdef BOARD_NAME
+ chprintf(chp, "Board: %s" SHELL_NEWLINE_STR, BOARD_NAME);
+#endif
+#ifdef __DATE__
+#ifdef __TIME__
+ chprintf(chp, "Build time: %s%s%s" SHELL_NEWLINE_STR, __DATE__, " - ", __TIME__);
+#endif
+#endif
+}
+#endif
+
+#if (SHELL_CMD_ECHO_ENABLED == TRUE) || defined(__DOXYGEN__)
+static void cmd_echo(BaseSequentialStream *chp, int argc, char *argv[]) {
+
+ (void)argv;
+ if (argc != 1) {
+ shellUsage(chp, "echo \"message\"");
+ return;
+ }
+ chprintf(chp, "%s" SHELL_NEWLINE_STR, argv[0]);
+}
+#endif
+
+#if (SHELL_CMD_SYSTIME_ENABLED == TRUE) || defined(__DOXYGEN__)
+static void cmd_systime(BaseSequentialStream *chp, int argc, char *argv[]) {
+
+ (void)argv;
+ if (argc > 0) {
+ shellUsage(chp, "systime");
+ return;
+ }
+ chprintf(chp, "%lu" SHELL_NEWLINE_STR, (unsigned long)chVTGetSystemTime());
+}
+#endif
+
+#if (SHELL_CMD_MEM_ENABLED == TRUE) || defined(__DOXYGEN__)
+static void cmd_mem(BaseSequentialStream *chp, int argc, char *argv[]) {
+ size_t n, total, largest;
+
+ (void)argv;
+ if (argc > 0) {
+ shellUsage(chp, "mem");
+ return;
+ }
+ n = chHeapStatus(NULL, &total, &largest);
+ chprintf(chp, "core free memory : %u bytes" SHELL_NEWLINE_STR, chCoreGetStatusX());
+ chprintf(chp, "heap fragments : %u" SHELL_NEWLINE_STR, n);
+ chprintf(chp, "heap free total : %u bytes" SHELL_NEWLINE_STR, total);
+ chprintf(chp, "heap free largest: %u bytes" SHELL_NEWLINE_STR, largest);
+}
+#endif
+
+#if (SHELL_CMD_THREADS_ENABLED == TRUE) || defined(__DOXYGEN__)
+static void cmd_threads(BaseSequentialStream *chp, int argc, char *argv[]) {
+ static const char *states[] = {CH_STATE_NAMES};
+ thread_t *tp;
+
+ (void)argv;
+ if (argc > 0) {
+ shellUsage(chp, "threads");
+ return;
+ }
+ chprintf(chp, "stklimit stack addr refs prio state name\r\n" SHELL_NEWLINE_STR);
+ tp = chRegFirstThread();
+ do {
+#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE)
+ uint32_t stklimit = (uint32_t)tp->wabase;
+#else
+ uint32_t stklimit = 0U;
+#endif
+ chprintf(chp, "%08lx %08lx %08lx %4lu %4lu %9s %12s" SHELL_NEWLINE_STR,
+ stklimit, (uint32_t)tp->ctx.sp, (uint32_t)tp,
+ (uint32_t)tp->refs - 1, (uint32_t)tp->prio, states[tp->state],
+ tp->name == NULL ? "" : tp->name);
+ tp = chRegNextThread(tp);
+ } while (tp != NULL);
+}
+#endif
+
+#if (SHELL_CMD_TEST_ENABLED == TRUE) || defined(__DOXYGEN__)
+static THD_FUNCTION(test_rt, arg) {
+ BaseSequentialStream *chp = (BaseSequentialStream *)arg;
+ test_execute(chp, &rt_test_suite);
+}
+
+static THD_FUNCTION(test_oslib, arg) {
+ BaseSequentialStream *chp = (BaseSequentialStream *)arg;
+ test_execute(chp, &oslib_test_suite);
+}
+
+static void cmd_test(BaseSequentialStream *chp, int argc, char *argv[]) {
+ thread_t *tp;
+ tfunc_t tfp;
+
+ (void)argv;
+ if (argc != 1) {
+ shellUsage(chp, "test rt|oslib");
+ return;
+ }
+ if (!strcmp(argv[0], "rt")) {
+ tfp = test_rt;
+ }
+ else if (!strcmp(argv[0], "oslib")) {
+ tfp = test_oslib;
+ }
+ else {
+ shellUsage(chp, "test rt|oslib");
+ return;
+ }
+ tp = chThdCreateFromHeap(NULL, SHELL_CMD_TEST_WA_SIZE,
+ "test", chThdGetPriorityX(),
+ tfp, chp);
+ if (tp == NULL) {
+ chprintf(chp, "out of memory" SHELL_NEWLINE_STR);
+ return;
+ }
+ chThdWait(tp);
+}
+#endif
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Array of the default commands.
+ */
+const ShellCommand shell_local_commands[] = {
+#if (SHELL_CMD_EXIT_ENABLED == TRUE) && !defined(_CHIBIOS_NIL_)
+ {"exit", cmd_exit},
+#endif
+#if SHELL_CMD_INFO_ENABLED == TRUE
+ {"info", cmd_info},
+#endif
+#if SHELL_CMD_ECHO_ENABLED == TRUE
+ {"echo", cmd_echo},
+#endif
+#if SHELL_CMD_SYSTIME_ENABLED == TRUE
+ {"systime", cmd_systime},
+#endif
+#if SHELL_CMD_MEM_ENABLED == TRUE
+ {"mem", cmd_mem},
+#endif
+#if SHELL_CMD_THREADS_ENABLED == TRUE
+ {"threads", cmd_threads},
+#endif
+#if SHELL_CMD_TEST_ENABLED == TRUE
+ {"test", cmd_test},
+#endif
+ {NULL, NULL}
+};
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/various/shell/shell_cmd.h b/ChibiOS_20.3.2/os/various/shell/shell_cmd.h
new file mode 100644
index 0000000..f913822
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/shell/shell_cmd.h
@@ -0,0 +1,114 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file shell_cmd.h
+ * @brief Simple CLI shell common commands header.
+ *
+ * @addtogroup SHELL
+ * @{
+ */
+
+#ifndef SHELLCMD_H
+#define SHELLCMD_H
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+#if !defined(SHELL_CMD_EXIT_ENABLED) || defined(__DOXYGEN__)
+#define SHELL_CMD_EXIT_ENABLED TRUE
+#endif
+
+#if !defined(SHELL_CMD_INFO_ENABLED) || defined(__DOXYGEN__)
+#define SHELL_CMD_INFO_ENABLED TRUE
+#endif
+
+#if !defined(SHELL_CMD_ECHO_ENABLED) || defined(__DOXYGEN__)
+#define SHELL_CMD_ECHO_ENABLED TRUE
+#endif
+
+#if !defined(SHELL_CMD_SYSTIME_ENABLED) || defined(__DOXYGEN__)
+#define SHELL_CMD_SYSTIME_ENABLED TRUE
+#endif
+
+#if !defined(SHELL_CMD_MEM_ENABLED) || defined(__DOXYGEN__)
+#define SHELL_CMD_MEM_ENABLED TRUE
+#endif
+
+#if !defined(SHELL_CMD_THREADS_ENABLED) || defined(__DOXYGEN__)
+#define SHELL_CMD_THREADS_ENABLED TRUE
+#endif
+
+#if !defined(SHELL_CMD_TEST_ENABLED) || defined(__DOXYGEN__)
+#define SHELL_CMD_TEST_ENABLED TRUE
+#endif
+
+#if !defined(SHELL_CMD_TEST_WA_SIZE) || defined(__DOXYGEN__)
+#define SHELL_CMD_TEST_WA_SIZE THD_WORKING_AREA_SIZE(256)
+#endif
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+#if (SHELL_CMD_MEM_ENABLED == TRUE) && (CH_CFG_USE_MEMCORE == FALSE)
+#error "SHELL_CMD_MEM_ENABLED requires CH_CFG_USE_MEMCORE"
+#endif
+
+#if (SHELL_CMD_MEM_ENABLED == TRUE) && (CH_CFG_USE_HEAP == FALSE)
+#error "SHELL_CMD_MEM_ENABLED requires CH_CFG_USE_HEAP"
+#endif
+
+#if (SHELL_CMD_THREADS_ENABLED == TRUE) && (CH_CFG_USE_REGISTRY == FALSE)
+#error "SHELL_CMD_THREADS_ENABLED requires CH_CFG_USE_REGISTRY"
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+extern const ShellCommand shell_local_commands[];
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Module inline functions. */
+/*===========================================================================*/
+
+#endif /* SHELLCMD_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/various/syscalls.c b/ChibiOS_20.3.2/os/various/syscalls.c
new file mode 100644
index 0000000..8da8f75
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/syscalls.c
@@ -0,0 +1,172 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+/*
+ * **** This file incorporates work covered by the following copyright and ****
+ * **** permission notice: ****
+ *
+ * Copyright (c) 2009 by Michael Fischer. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ ****************************************************************************
+ * History:
+ *
+ * 28.03.09 mifi First Version, based on the original syscall.c from
+ * newlib version 1.17.0
+ * 17.08.09 gdisirio Modified the file for use under ChibiOS/RT
+ * 15.11.09 gdisirio Added read and write handling
+ ****************************************************************************/
+
+#include
+#include
+#include
+#include
+#include
+
+#include "ch.h"
+#if defined(STDOUT_SD) || defined(STDIN_SD)
+#include "hal.h"
+#endif
+
+/***************************************************************************/
+
+__attribute__((used))
+int _read_r(struct _reent *r, int file, char * ptr, int len) {
+ (void)r;
+#if defined(STDIN_SD)
+ if (!len || (file != 0)) {
+ __errno_r(r) = EINVAL;
+ return -1;
+ }
+ len = sdRead(&STDIN_SD, (uint8_t *)ptr, (size_t)len);
+ return len;
+#else
+ (void)file;
+ (void)ptr;
+ (void)len;
+ __errno_r(r) = EINVAL;
+ return -1;
+#endif
+}
+
+/***************************************************************************/
+
+__attribute__((used))
+int _lseek_r(struct _reent *r, int file, int ptr, int dir) {
+ (void)r;
+ (void)file;
+ (void)ptr;
+ (void)dir;
+
+ return 0;
+}
+
+/***************************************************************************/
+
+__attribute__((used))
+int _write_r(struct _reent *r, int file, char * ptr, int len) {
+ (void)r;
+ (void)file;
+ (void)ptr;
+#if defined(STDOUT_SD)
+ if (file != 1) {
+ __errno_r(r) = EINVAL;
+ return -1;
+ }
+ sdWrite(&STDOUT_SD, (uint8_t *)ptr, (size_t)len);
+#endif
+ return len;
+}
+
+/***************************************************************************/
+
+__attribute__((used))
+int _close_r(struct _reent *r, int file) {
+ (void)r;
+ (void)file;
+
+ return 0;
+}
+
+/***************************************************************************/
+
+__attribute__((used))
+caddr_t _sbrk_r(struct _reent *r, int incr) {
+#if CH_CFG_USE_MEMCORE
+ void *p;
+
+ chDbgCheck(incr >= 0);
+
+ p = chCoreAllocFromBase((size_t)incr, 1U, 0U);
+ if (p == NULL) {
+ __errno_r(r) = ENOMEM;
+ return (caddr_t)-1;
+ }
+ return (caddr_t)p;
+#else
+ (void)incr;
+ __errno_r(r) = ENOMEM;
+ return (caddr_t)-1;
+#endif
+}
+
+/***************************************************************************/
+
+__attribute__((used))
+int _fstat_r(struct _reent *r, int file, struct stat * st) {
+ (void)r;
+ (void)file;
+
+ memset(st, 0, sizeof(*st));
+ st->st_mode = S_IFCHR;
+ return 0;
+}
+
+/***************************************************************************/
+
+__attribute__((used))
+int _isatty_r(struct _reent *r, int fd) {
+ (void)r;
+ (void)fd;
+
+ return 1;
+}
+
+/*** EOF ***/
diff --git a/ChibiOS_20.3.2/os/various/various.dox b/ChibiOS_20.3.2/os/various/various.dox
new file mode 100644
index 0000000..0c8540e
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/various.dox
@@ -0,0 +1,91 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @defgroup various Various
+ *
+ * @brief Utilities Library.
+ * @details This is a collection of useful library code that is not part of
+ * the base kernel services.
+ * Notes
+ * The library code does not follow the same naming convention of the
+ * system APIs in order to make very clear that it is not "core" code.
+ * The main difference is that library code is not formally tested in the
+ * test suite but through usage in the various demo applications.
+ */
+
+/**
+ * @defgroup cpp_library C++ Wrapper
+ *
+ * @brief C++ wrapper module.
+ * @details This module allows to use the ChibiOS/RT functionalities
+ * from C++ as classes and objects rather the traditional "C" APIs.
+ *
+ * @ingroup various
+ */
+
+/**
+ * @defgroup memory_streams Memory Streams
+ *
+ * @brief Memory Streams.
+ * @details This module allows to use a memory area (RAM or ROM) using a
+ * @ref data_streams interface.
+ *
+ * @ingroup various
+ */
+
+/**
+ * @defgroup event_timer Periodic Events Timer
+ *
+ * @brief Periodic Event Timer.
+ * @details This timer generates an event at regular intervals. The
+ * listening threads can use the event to perform time related
+ * activities. Multiple threads can listen to the same timer.
+ *
+ * @ingroup various
+ */
+
+/**
+ * @defgroup SHELL Command Shell
+ *
+ * @brief Small extendible command line shell.
+ * @details This module implements a generic extendible command line interface.
+ * The CLI just requires an I/O channel (@p BaseChannel), more
+ * commands can be added to the shell using the configuration
+ * structure.
+ *
+ * @ingroup various
+ */
+
+/**
+ * @defgroup chprintf System formatted print
+ *
+ * @brief System formatted print service.
+ * @details This module implements printf()-like function able to send data
+ * to any module implementing a @p BaseSequentialStream interface.
+ *
+ * @ingroup various
+ */
+
+/**
+ * @defgroup LWIP_THREAD LWIP bindings
+ *
+ * @brief lwIP port and wrapper thread.
+ * @details This module implements the lwIP system abstraction and wrapper
+ * thread.
+ *
+ * @ingroup various
+ */
diff --git a/ChibiOS_20.3.2/os/various/wolfssl_bindings/hwrng.c b/ChibiOS_20.3.2/os/various/wolfssl_bindings/hwrng.c
new file mode 100644
index 0000000..ca11e48
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/wolfssl_bindings/hwrng.c
@@ -0,0 +1,80 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ * **** This file incorporates work covered by the following copyright and ****
+ * **** permission notice: ****
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ *
+ */
+#include
+#include
+#include "wolfssl_chibios.h"
+#include "user_settings.h"
+
+unsigned int chibios_rand_generate(void)
+{
+ static unsigned int last_value=0;
+ static unsigned int new_value=0;
+ unsigned int error_bits = 0;
+ error_bits = RNG_SR_SEIS | RNG_SR_CEIS;
+ while (new_value==last_value) {
+ /* Check for error flags and if data is ready. */
+ if ( ((RNG->SR & error_bits) == 0) && ( (RNG->SR & RNG_SR_DRDY) == 1 ) )
+ new_value=RNG->DR;
+ }
+ last_value=new_value;
+ return new_value;
+}
+
+int custom_rand_generate_block(unsigned char* output, unsigned int sz)
+{
+ uint32_t i = 0;
+
+ while (i < sz)
+ {
+ /* If not aligned or there is odd/remainder */
+ if( (i + sizeof(CUSTOM_RAND_TYPE)) > sz ||
+ ((uint32_t)&output[i] % sizeof(CUSTOM_RAND_TYPE)) != 0
+ ) {
+ /* Single byte at a time */
+ output[i++] = (unsigned char)chibios_rand_generate();
+ }
+ else {
+ /* Use native 8, 16, 32 or 64 copy instruction */
+ *((CUSTOM_RAND_TYPE*)&output[i]) = chibios_rand_generate();
+ i += sizeof(CUSTOM_RAND_TYPE);
+ }
+ }
+ return 0;
+}
+
diff --git a/ChibiOS_20.3.2/os/various/wolfssl_bindings/user_settings.h b/ChibiOS_20.3.2/os/various/wolfssl_bindings/user_settings.h
new file mode 100644
index 0000000..03be06b
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/wolfssl_bindings/user_settings.h
@@ -0,0 +1,86 @@
+#include
+
+/* Configuration */
+
+#define WOLFSSL_GENERAL_ALIGNMENT 4
+#define HAVE_TM_TYPE
+#define WORD64_AVAILABLE
+
+
+/* ChibiOS + Lwip */
+#define HAVE_LWIP_NATIVE
+#define WOLFSSL_CHIBIOS
+
+#define USER_TICKS
+#define WOLFSSL_USER_CURRTIME
+#define XMALLOC_OVERRIDE
+//#define USE_WOLF_TIME_T
+#define XTIME(tl) (LowResTimer())
+
+
+/* ARM */
+
+#define RSA_LOW_MEM
+#define NO_OLD_RNGNAME
+#define SMALL_SESSION_CACHE
+#define WOLFSSL_SMALL_STACK
+
+#define TFM_ARM
+#define SINGLE_THREADED
+#define NO_SIG_WRAPPER
+
+/* Cipher features */
+//#define USE_FAST_MATH
+//#define ALT_ECC_SIZE
+
+#define HAVE_FFDHE_2048
+#define HAVE_CHACHA
+#define HAVE_POLY1305
+#define HAVE_ECC
+#define HAVE_CURVE25519
+#define CURVED25519_SMALL
+#define HAVE_ONE_TIME_AUTH
+#define WOLFSSL_DH_CONST
+
+/* HW RNG support */
+
+unsigned int chibios_rand_generate(void);
+int custom_rand_generate_block(unsigned char* output, unsigned int sz);
+
+#define CUSTOM_RAND_GENERATE chibios_rand_generate
+#define CUSTOM_RAND_TYPE uint32_t
+
+#define HAVE_ED25519
+#define HAVE_POLY1305
+#define HAVE_SHA512
+#define WOLFSSL_SHA512
+
+
+/* Size/speed config */
+#define USE_SLOW_SHA2
+#define USE_SLOW_SHA512
+
+/* Robustness */
+#define TFM_TIMING_RESISTANT
+#define ECC_TIMING_RESISTANT
+#define WC_RSA_BLINDING
+
+/* Remove Features */
+#define NO_WRITEV
+#define NO_DEV_RANDOM
+#define NO_FILESYSTEM
+#define NO_MAIN_DRIVER
+#define NO_MD4
+#define NO_RABBIT
+#define NO_HC128
+#define NO_DSA
+#define NO_PWDBASED
+#define NO_PSK
+#define NO_DES3
+#define NO_RC4
+
+
+/* Realloc (to use without USE_FAST_MATH) */
+
+void *chHeapRealloc (void *addr, uint32_t size);
+#define XREALLOC(p,n,h,t) chHeapRealloc( (p) , (n) )
diff --git a/ChibiOS_20.3.2/os/various/wolfssl_bindings/wolfssl.mk b/ChibiOS_20.3.2/os/various/wolfssl_bindings/wolfssl.mk
new file mode 100644
index 0000000..00ef082
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/wolfssl_bindings/wolfssl.mk
@@ -0,0 +1,98 @@
+# List of the required lwIP files.
+WOLFSSL = $(CHIBIOS)/ext/wolfssl
+
+WOLFBINDSRC = \
+ $(CHIBIOS)/os/various/wolfssl_bindings/wolfssl_chibios.c \
+ $(CHIBIOS)/os/various/wolfssl_bindings/hwrng.c
+
+WOLFCRYPTSRC = \
+ $(WOLFSSL)/wolfcrypt/src/sha.c \
+ $(WOLFSSL)/wolfcrypt/src/ge_low_mem.c \
+ $(WOLFSSL)/wolfcrypt/src/compress.c \
+ $(WOLFSSL)/wolfcrypt/src/chacha20_poly1305.c \
+ $(WOLFSSL)/wolfcrypt/src/des3.c \
+ $(WOLFSSL)/wolfcrypt/src/fe_low_mem.c \
+ $(WOLFSSL)/wolfcrypt/src/hmac.c \
+ $(WOLFSSL)/wolfcrypt/src/asm.c \
+ $(WOLFSSL)/wolfcrypt/src/camellia.c \
+ $(WOLFSSL)/wolfcrypt/src/ecc.c \
+ $(WOLFSSL)/wolfcrypt/src/ecc_fp.c \
+ $(WOLFSSL)/wolfcrypt/src/ripemd.c \
+ $(WOLFSSL)/wolfcrypt/src/rsa.c \
+ $(WOLFSSL)/wolfcrypt/src/wc_port.c \
+ $(WOLFSSL)/wolfcrypt/src/arc4.c \
+ $(WOLFSSL)/wolfcrypt/src/srp.c \
+ $(WOLFSSL)/wolfcrypt/src/random.c \
+ $(WOLFSSL)/wolfcrypt/src/idea.c \
+ $(WOLFSSL)/wolfcrypt/src/blake2b.c \
+ $(WOLFSSL)/wolfcrypt/src/error.c \
+ $(WOLFSSL)/wolfcrypt/src/dh.c \
+ $(WOLFSSL)/wolfcrypt/src/asn.c \
+ $(WOLFSSL)/wolfcrypt/src/cmac.c \
+ $(WOLFSSL)/wolfcrypt/src/signature.c \
+ $(WOLFSSL)/wolfcrypt/src/pwdbased.c \
+ $(WOLFSSL)/wolfcrypt/src/chacha.c \
+ $(WOLFSSL)/wolfcrypt/src/md5.c \
+ $(WOLFSSL)/wolfcrypt/src/aes.c \
+ $(WOLFSSL)/wolfcrypt/src/wolfmath.c \
+ $(WOLFSSL)/wolfcrypt/src/memory.c \
+ $(WOLFSSL)/wolfcrypt/src/logging.c \
+ $(WOLFSSL)/wolfcrypt/src/tfm.c \
+ $(WOLFSSL)/wolfcrypt/src/coding.c \
+ $(WOLFSSL)/wolfcrypt/src/rabbit.c \
+ $(WOLFSSL)/wolfcrypt/src/pkcs12.c \
+ $(WOLFSSL)/wolfcrypt/src/md2.c \
+ $(WOLFSSL)/wolfcrypt/src/ge_operations.c \
+ $(WOLFSSL)/wolfcrypt/src/sha512.c \
+ $(WOLFSSL)/wolfcrypt/src/sha3.c \
+ $(WOLFSSL)/wolfcrypt/src/port/nrf51.c \
+ $(WOLFSSL)/wolfcrypt/src/port/pic32/pic32mz-crypt.c \
+ $(WOLFSSL)/wolfcrypt/src/port/atmel/atmel.c \
+ $(WOLFSSL)/wolfcrypt/src/port/nxp/ksdk_port.c \
+ $(WOLFSSL)/wolfcrypt/src/port/ti/ti-des3.c \
+ $(WOLFSSL)/wolfcrypt/src/port/ti/ti-ccm.c \
+ $(WOLFSSL)/wolfcrypt/src/port/ti/ti-hash.c \
+ $(WOLFSSL)/wolfcrypt/src/port/ti/ti-aes.c \
+ $(WOLFSSL)/wolfcrypt/src/port/arm/armv8-aes.c \
+ $(WOLFSSL)/wolfcrypt/src/port/arm/armv8-sha256.c \
+ $(WOLFSSL)/wolfcrypt/src/port/xilinx/xil-aesgcm.c \
+ $(WOLFSSL)/wolfcrypt/src/port/xilinx/xil-sha3.c \
+ $(WOLFSSL)/wolfcrypt/src/hash.c \
+ $(WOLFSSL)/wolfcrypt/src/curve25519.c \
+ $(WOLFSSL)/wolfcrypt/src/integer.c \
+ $(WOLFSSL)/wolfcrypt/src/wolfevent.c \
+ $(WOLFSSL)/wolfcrypt/src/dsa.c \
+ $(WOLFSSL)/wolfcrypt/src/pkcs7.c \
+ $(WOLFSSL)/wolfcrypt/src/wc_encrypt.c \
+ $(WOLFSSL)/wolfcrypt/src/cpuid.c \
+ $(WOLFSSL)/wolfcrypt/src/sha256.c \
+ $(WOLFSSL)/wolfcrypt/src/md4.c \
+ $(WOLFSSL)/wolfcrypt/src/fe_operations.c \
+ $(WOLFSSL)/wolfcrypt/src/ed25519.c \
+ $(WOLFSSL)/wolfcrypt/src/poly1305.c \
+ $(WOLFSSL)/wolfcrypt/src/hc128.c \
+
+WOLFSSLSRC = \
+ $(WOLFSSL)/src/internal.c \
+ $(WOLFSSL)/src/tls.c \
+ $(WOLFSSL)/src/keys.c \
+ $(WOLFSSL)/src/crl.c \
+ $(WOLFSSL)/src/ssl.c \
+ $(WOLFSSL)/src/wolfio.c \
+ $(WOLFSSL)/src/sniffer.c \
+ $(WOLFSSL)/src/ocsp.c \
+ $(WOLFSSL)/src/tls13.c
+
+
+WOLFSRC = $(WOLFBINDSRC) $(WOLFCRYPTSRC) $(WOLFSSLSRC)
+
+WOLFINC = \
+ $(CHIBIOS)/os/various/wolfssl_bindings \
+ $(WOLFSSL)/wolfcrypt/include \
+ $(WOLFSSL)/wolfssl/include \
+ $(WOLFSSL)
+
+# Shared variables
+ALLCSRC += $(WOLFSRC)
+ALLINC += $(WOLFINC)
+
diff --git a/ChibiOS_20.3.2/os/various/wolfssl_bindings/wolfssl_chibios.c b/ChibiOS_20.3.2/os/various/wolfssl_bindings/wolfssl_chibios.c
new file mode 100644
index 0000000..4b6cff3
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/wolfssl_bindings/wolfssl_chibios.c
@@ -0,0 +1,252 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ * **** This file incorporates work covered by the following copyright and ****
+ * **** permission notice: ****
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ *
+ */
+
+#include "ch.h"
+#include "wolfssl_chibios.h"
+#include "lwip/opt.h"
+#include "lwip/arch.h"
+#include "lwip/api.h"
+#include "lwip/mem.h"
+#include "lwip/sockets.h"
+#include "lwip/tcp.h"
+#include
+static int wolfssl_is_initialized = 0;
+
+sslconn *sslconn_accept(sslconn *sk)
+{
+ sslconn *new;
+ struct netconn *newconn = NULL;
+ err_t err;
+ err = netconn_accept(sk->conn, &newconn);
+ if (err != ERR_OK) {
+ return NULL;
+ }
+ new = chHeapAlloc(NULL, sizeof(sslconn));
+ if (!new)
+ return NULL;
+ new->conn = newconn;
+ new->ctx = sk->ctx;
+ new->ssl = wolfSSL_new(new->ctx);
+ wolfSSL_SetIOReadCtx(new->ssl, new);
+ wolfSSL_SetIOWriteCtx(new->ssl, new);
+
+ if (wolfSSL_accept(new->ssl) == SSL_SUCCESS) {
+ wolfSSL_set_using_nonblock(new->ssl, 1);
+ newconn->pcb.tcp->mss = 1480;
+ return new;
+ } else {
+ wolfSSL_free(new->ssl);
+ chHeapFree(new);
+ return NULL;
+ }
+}
+
+sslconn *sslconn_new(enum netconn_type t, WOLFSSL_METHOD* method)
+{
+ sslconn *sk;
+ if (!wolfssl_is_initialized) {
+ wolfSSL_Init();
+ wolfssl_is_initialized++;
+ }
+
+ sk = chHeapAlloc(NULL, sizeof(sslconn));
+ if (!sk)
+ return NULL;
+ memset(sk, 0, sizeof(sslconn));
+ sk->ctx = wolfSSL_CTX_new(method);
+ if (!sk->ctx)
+ goto error;
+ sk->conn = netconn_new(t);
+ if (!sk->conn)
+ goto error;
+ wolfSSL_SetIORecv(sk->ctx, wolfssl_recv_cb);
+ wolfSSL_SetIOSend(sk->ctx, wolfssl_send_cb);
+ return sk;
+
+error:
+ if (sk->ctx)
+ wolfSSL_CTX_free(sk->ctx);
+ chHeapFree(sk);
+ return NULL;
+}
+
+void sslconn_close(sslconn *sk)
+{
+ netconn_delete(sk->conn);
+ wolfSSL_free(sk->ssl);
+ chHeapFree(sk);
+}
+
+
+/* IO Callbacks */
+int wolfssl_send_cb(WOLFSSL* ssl, char *buf, int sz, void *ctx)
+{
+ sslconn *sk = (sslconn *)ctx;
+ int err;
+ (void)ssl;
+ err = netconn_write(sk->conn, buf, sz, NETCONN_COPY);
+ if (err == ERR_OK)
+ return sz;
+ else
+ return -2;
+}
+
+
+#define MAX_SSL_BUF 1460
+static uint8_t ssl_recv_buffer[MAX_SSL_BUF];
+static int ssl_rb_len = 0;
+static int ssl_rb_off = 0;
+
+int wolfssl_recv_cb(WOLFSSL *ssl, char *buf, int sz, void *ctx)
+{
+ sslconn *sk = (sslconn *)ctx;
+ struct netbuf *inbuf = NULL;
+ uint8_t *net_buf;
+ uint16_t buflen;
+ (void)ssl;
+ err_t err;
+
+ if (ssl_rb_len > 0) {
+ if (sz > ssl_rb_len - ssl_rb_off)
+ sz = ssl_rb_len - ssl_rb_off;
+ memcpy(buf, ssl_recv_buffer + ssl_rb_off, sz);
+ ssl_rb_off += sz;
+ if (ssl_rb_off >= ssl_rb_len) {
+ ssl_rb_len = 0;
+ ssl_rb_off = 0;
+ }
+ return sz;
+ }
+
+
+ err = netconn_recv(sk->conn, &inbuf);
+ if (err == ERR_OK) {
+ netbuf_data(inbuf, (void **)&net_buf, &buflen);
+ ssl_rb_len = buflen;
+ if (ssl_rb_len > MAX_SSL_BUF)
+ ssl_rb_len = MAX_SSL_BUF;
+ memcpy(ssl_recv_buffer, net_buf, ssl_rb_len);
+ ssl_rb_off = 0;
+ if (sz > ssl_rb_len)
+ sz = ssl_rb_len;
+ memcpy(buf, ssl_recv_buffer, sz);
+ ssl_rb_off += sz;
+ if (ssl_rb_off >= ssl_rb_len) {
+ ssl_rb_len = 0;
+ ssl_rb_off = 0;
+ }
+ netbuf_delete(inbuf);
+ return sz;
+ }
+ else
+ return 0;
+ //return WOLFSSL_CBIO_ERR_WANT_READ;
+}
+
+#ifndef ST2S
+# define ST2S(n) (((n) + CH_CFG_ST_FREQUENCY - 1UL) / CH_CFG_ST_FREQUENCY)
+#endif
+
+#ifndef ST2MS
+#define ST2MS(n) (((n) * 1000UL + CH_CFG_ST_FREQUENCY - 1UL) / CH_CFG_ST_FREQUENCY)
+#endif
+
+
+word32 LowResTimer(void)
+{
+ systime_t t = chVTGetSystemTimeX();
+ return ST2S(t);
+}
+
+uint32_t TimeNowInMilliseconds(void)
+{
+ systime_t t = chVTGetSystemTimeX();
+ return ST2MS(t);
+}
+
+void *chHeapRealloc (void *addr, uint32_t size)
+{
+ union heap_header *hp;
+ uint32_t prev_size, new_size;
+
+ void *ptr;
+
+ if(addr == NULL) {
+ return chHeapAlloc(NULL, size);
+ }
+
+ /* previous allocated segment is preceded by an heap_header */
+ hp = addr - sizeof(union heap_header);
+ prev_size = hp->used.size; /* size is always multiple of 8 */
+
+ /* check new size memory alignment */
+ if(size % 8 == 0) {
+ new_size = size;
+ }
+ else {
+ new_size = ((int) (size / 8)) * 8 + 8;
+ }
+
+ if(prev_size >= new_size) {
+ return addr;
+ }
+
+ ptr = chHeapAlloc(NULL, size);
+ if(ptr == NULL) {
+ return NULL;
+ }
+
+ memcpy(ptr, addr, prev_size);
+
+ chHeapFree(addr);
+
+ return ptr;
+}
+
+void *chibios_alloc(void *heap, int size)
+{
+ return chHeapAlloc(heap, size);
+}
+
+void chibios_free(void *ptr)
+{
+ if (ptr)
+ chHeapFree(ptr);
+}
+
diff --git a/ChibiOS_20.3.2/os/various/wolfssl_bindings/wolfssl_chibios.h b/ChibiOS_20.3.2/os/various/wolfssl_bindings/wolfssl_chibios.h
new file mode 100644
index 0000000..42b1809
--- /dev/null
+++ b/ChibiOS_20.3.2/os/various/wolfssl_bindings/wolfssl_chibios.h
@@ -0,0 +1,70 @@
+/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/*
+ * **** This file incorporates work covered by the following copyright and ****
+ * **** permission notice: ****
+ *
+ * Copyright (C) 2006-2017 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ *
+ */
+#ifndef WOLFSSL_SK_H
+#define WOLFSSL_SK_H
+#include "user_settings.h"
+#include "wolfssl/wolfcrypt/settings.h"
+#include "wolfssl/wolfcrypt/types.h"
+#include "wolfssl/ssl.h"
+#include "lwip/opt.h"
+#include "lwip/arch.h"
+#include "lwip/api.h"
+#define XMALLOC(s,h,t) chibios_alloc(h,s)
+#define XFREE(p,h,t) chibios_free(p)
+
+struct sslconn {
+ WOLFSSL_CTX *ctx;
+ WOLFSSL *ssl;
+ struct netconn *conn;
+};
+
+typedef struct sslconn sslconn;
+
+sslconn *sslconn_accept(struct sslconn *sk);
+sslconn *sslconn_new(enum netconn_type t, WOLFSSL_METHOD *method);
+void sslconn_close(sslconn *sk);
+
+int wolfssl_send_cb(WOLFSSL* ssl, char *buf, int sz, void *ctx);
+int wolfssl_recv_cb(WOLFSSL *ssl, char *buf, int sz, void *ctx);
+
+void *chibios_alloc(void *heap, int size);
+void chibios_free(void *ptr);
+word32 LowResTimer(void);
+
+#endif
diff --git a/ChibiOS_20.3.2/readme.txt b/ChibiOS_20.3.2/readme.txt
new file mode 100644
index 0000000..2da79ae
--- /dev/null
+++ b/ChibiOS_20.3.2/readme.txt
@@ -0,0 +1,139 @@
+*****************************************************************************
+*** Files Organization ***
+*****************************************************************************
+
+--{root} - ChibiOS directory.
+ +--readme.txt - This file.
+ +--documentation.html - Shortcut to the web documentation page.
+ +--license.txt - GPL license text.
+ +--demos/ - Demo projects, one directory per platform.
+ +--docs/ - Documentation.
+ | +--common/ - Documentation common build resources.
+ | +--hal/ - Builders for HAL.
+ | +--nil/ - Builders for NIL.
+ | +--rt/ - Builders for RT.
+ +--ext/ - External libraries, not part of ChibiOS.
+ +--os/ - ChibiOS components.
+ | +--common/ - Shared OS modules.
+ | | +--abstractions/ - API emulator wrappers.
+ | | | +--cmsis_os/ - CMSIS OS emulation layer for RT.
+ | | | +--nasa_osal/ - NASA Operating System Abstraction Layer.
+ | | +--ext/ - Vendor files used by the OS.
+ | | +--ports/ - RTOS ports usable by both RT and NIL.
+ | | +--startup/ - Startup support.
+ | +--ex/ - EX component.
+ | | +--dox/ - EX documentation resources.
+ | | +--include/ - EX header files.
+ | | +--devices / - EX complex drivers.
+ | +--hal/ - HAL component.
+ | | +--boards/ - HAL board support files.
+ | | +--dox/ - HAL documentation resources.
+ | | +--include/ - HAL high level headers.
+ | | +--lib/ - HAL libraries.
+ | | | +--complex/ - HAL collection of complex drivers.
+ | | | | +--mfs/ - HAL managed flash storage driver.
+ | | | | +--serial_nor/ - HAL managed flash storage driver.
+ | | | +--fallback/ - HAL fall back software drivers.
+ | | | +--peripherals/ - HAL peripherals interfaces.
+ | | | +--streams/ - HAL streams.
+ | | +--osal/ - HAL OSAL implementations.
+ | | | +--lib/ - HAL OSAL common modules.
+ | | +--src/ - HAL high level source.
+ | | +--ports/ - HAL ports.
+ | | +--templates/ - HAL driver template files.
+ | | +--osal/ - HAL OSAL templates.
+ | +--oslib/ - RTOS modules usable by both RT and NIL.
+ | | +--include/ - OSLIB high level headers.
+ | | +--src/ - OSLIB high level source.
+ | | +--templates/ - OSLIB configuration template files.
+ | +--nil/ - NIL RTOS component.
+ | | +--dox/ - NIL documentation resources.
+ | | +--include/ - NIL high level headers.
+ | | +--src/ - NIL high level source.
+ | | +--templates/ - NIL configuration template files.
+ | +--rt/ - RT RTOS component.
+ | | +--dox/ - RT documentation resources.
+ | | +--include/ - RT high level headers.
+ | | +--src/ - RT high level source.
+ | | +--templates/ - RT configuration template files.
+ | +--various/ - Various portable support files.
+ +--test/ - Kernel test suite source code.
+ | +--lib/ - Portable test engine.
+ | +--hal/ - HAL test suites.
+ | | +--testbuild/ - HAL build test and MISRA check.
+ | +--nil/ - NIL test suites.
+ | | +--testbuild/ - NIL build test and MISRA check.
+ | +--rt/ - RT test suites.
+ | | +--testbuild/ - RT build test and MISRA check.
+ | | +--coverage/ - RT code coverage project.
+ +--testex/ - EX integration test demos.
+ +--testhal/ - HAL integration test demos.
+
+*****************************************************************************
+*** Releases and Change Log ***
+*****************************************************************************
+
+*** 20.3.2 ***
+- NEW: Support for 3 analog watchdogs in ADCv3 (STM32F3, L4, L4+, G4).
+- NEW: Support for 3 analog watchdogs in ADCv5 (STM32G0).
+- NEW: Updated FatFS to version 0.14.
+- NEW: Added a new setting to STM32 USBv1 allowing for some clock deviation
+ from 48MHz. Renamed setting USB_HOST_WAKEUP_DURATION to
+ STM32_USB_HOST_WAKEUP_DURATION for consistency.
+- FIX: Fixed STM32 QSPI errata workaround (bug #1116).
+- FIX: Fixed wrong condition in STM32 BDMAv1 driver (bug #1115).
+- FIX: Fixed HSI48 not getting enabled on STM32H7 (bug #1114).
+- FIX: Fixed LPUART1 support for STM32H7xx (bug #1113).
+- FIX: Fixed wrong sector count in EFL driver for L4+ dual bank configuration
+ (bug #1112).
+- FIX: Fixed wrong preprocessor checks in STM32 TIMv1 ICU driver (bug #1111).
+- FIX: Fixed wrong revisions handling in STM32H743 HAL (bug #1110).
+- FIX: Fixed missing STM32_I2C_BDMA_REQUIRED definition in I2Cv3 driver
+ (bug #1109).
+- FIX: Fixed wrong definitions in SPC563M board files (bug #1108).
+- FIX: Fixed cortex-M vectors table alignment problem (bug #1107).
+- FIX: Fixed extra condition in MAC driver macWaitTransmitDescriptor() function
+ (bug #1106).
+- FIX: Fixed schedule anomaly when CH_CFG_TIME_QUANTUM is greater than zero
+ (bug #1105).
+- FIX: Fixed Virtual Timers corner case (bug #1104).
+- FIX: Fixed GCC6 problem breaks Cortex-M0 port (bug #985).
+- FIX: Fixed a wrong management of the SPI TX buffer in the ADUCM port
+ (bug #1103).
+- FIX: Fixed STM32F4 EFL sector bug (bug #1102).
+- FIX: Fixed differences in STM32 EXTI (bug #1101).
+- FIX: Fixed STM32 DACv1 driver regressed because DMA changes (bug #1100).
+- FIX: Fixed STM32L0 missing LPUART IRQ initialization (bug #1099).
+- FIX: Fixed invalid EXTI definitions for STM32L0xx (bug #1098).
+- FIX: Fixed compilation error in file nvic.c (bug #1097).
+- FIX: Fixed STM32_DMAx_CH8_HANDLER not defined for DMAv1 (bug #1096).
+- FIX: Fixed STM32 EXTI2 and EXTI4 not triggering a callback (bug #1095).
+- FIX: Fixed STM32G4 demos compile fails if smart mode is disabled (bug #1094).
+- FIX: Fixed failure in chSemReset() function when counter is equal to MAXINT
+ (bug #1093).
+- FIX: Fixed error in EXTIv1 ISRs (bug #1077).
+
+*** 20.3.1 ***
+- NEW: STM32 ICU driver now allows to setup the ARR register in the
+ configuration structure, the default value should be 0xFFFFFFFFU.
+- NEW: Updated debug tools to be independent from the toolchain position:
+ they now rely on the environment variable CHIBISTUDIO.
+- NEW: Added dynamic reconfiguration API to lwIP bindings.
+- FIX: Fixed swapped definition in ST_STM32F746G_DISCOVERY board files
+ (bug #1092).
+- FIX: Fixed missing symbols in GCC scatter files (bug #1091).
+- FIX: Fixed wrong SAI1 clock selection for STM32G4xx (bug #1090).
+- FIX: Fixed STM32H7xx ADC problem in dual mode (bug #1089).
+- FIX: Fixed invalid CHSEL DMA setting in STM32 UART drivers (bug #1088).
+- FIX: Fixed sector count incorrect in STM32G07/8 EFL driver (bug #1085).
+- FIX: Fixed sector size incorrect in STM32F413 EFL driver (bug #1084).
+- FIX: Fixed wrong arguments for the cacheBufferInvalidate in the STM32 SPI
+ demo (bug #1086).
+- FIX: Fixed race condition in HAL MAC driver (bug #1083).
+- FIX: Fixed STM32H7 compile fails for I2C4 (bug #1082).
+- FIX: Fixed early interrupts enable in ARMv7-M port (bug #1081).
+- FIX: Fixed I2CD4 interrupt vectors are swapped versus I2CD1-I2CD3 (bug #1080).
+- FIX: Fixed incorrect clock check when using PLLSAI1R in ADCv3 (bug #1079).
+- FIX: Fixed missing checks in TIM6 and TIM7 STM32 mini drivers (bug #1078).
+- FIX: Fixed problem in chMtxUnlockAllS() (bug #1076).
+
diff --git a/ChibiOS_20.3.2/release_note_next.txt b/ChibiOS_20.3.2/release_note_next.txt
new file mode 100644
index 0000000..7eea5b2
--- /dev/null
+++ b/ChibiOS_20.3.2/release_note_next.txt
@@ -0,0 +1,120 @@
+******************************************************************************
+*** ChibiOS next Release Notes. ***
+******************************************************************************
+
+ChibiOS next is composed of several independent but inter-operable
+sub-projects: RT, NIL, SB, HAL, EX. Plus several external libraries
+integrated in our structure: WolfSSL, FatFS and lwIP.
+
+*** ChibiOS next highlights ****
+
+- New NIL 4.0.
+- New ARM SandBox subsystem.
+- New modules in OSLIB.
+- Support for STM32G0xx and STM32G4xx.
+- Support for all STM32 timers in all drivers.
+- Improved support for all STM32s.
+- Improved MFS module.
+
+*** ChibiOS next general improvements ***
+
+- Lots of style fixes thanks to the new code checker tool.
+- Improved syscalls.c support.
+- Updated FatFS to version 0.13c.
+- Updated lwIP to version 2.1.2.
+- Updated WolfSSL to latest version.
+- Added support for .cc files extensions in makefiles.
+
+*** What's new in RT/NIL ports ***
+
+- Added support for a syscall entry point, it is used by the new ChibiOS/SB
+ subsystem.
+
+*** What's new in OS Library 1.2.0 ***
+
+- Improved OSLIB initialization.
+- Modified core allocator to be able to get blocks starting from bottom
+ or top of the available memory range.
+- Re-introduced missing chGuardedPoolGetCounterI() function to guarded
+ pools allocator.
+- Added a cache class to OSLIB (experimental).
+- Added support for delegate threads.
+- Added support for asynchronous jobs queues.
+
+*** What's new in SB 1.0.0 ***
+
+- New sandbox subsystem. It allows to have untrusted/unreliable code to
+ be run into one or more isolated enclaves (experimental).
+ - Currently only GCC is supported.
+
+*** What's new in RT 6.1.0 ***
+
+- Added a "library generator" project for RT, it allows to
+ generate a library with a pre-configured RT. It also includes
+ an "header generator" able to generate an unified "ch.h" with
+ all options resolved.
+- New functions: chSemResetWithMessageI() and chSemResetWithMessage().
+- Improvements to messages, new functions chMsgWaitS(), chMsgWaitTimeoutS(),
+ chMsgWaitTimeout(), chMsgPollS(), chMsgPoll().
+
+*** What's new in NIL 4.0.0 ***
+
+- New NIL 4.
+ - Increased API compatibility with RT.
+ - Full threading (create, wait, exit).
+ - Events support like in RT (optional).
+ - Messages support like in RT (optional).
+ - Full OSLIB support.
+- New functions: chSemResetWithMessageI() and chSemResetWithMessage().
+- Improvements to messages, new functions chMsgWaitS(),
+ chMsgWaitTimeoutS(), chMsgWaitTimeout().
+
+*** What's new in HAL 7.1.0 ***
+
+- Added a new interface for range-finder devices.
+- Added transactional updates to MFS. Doubled data headers magic numbers
+ for improved safety and to keep the final write aligned to 64 bits.
+- Modified AES GCM function signatures.
+- Added and embedded flash driver model in HAL. Added an implementation
+ for STM32F1xx, STM32L4xx, STM32L4xx+.
+- Modified the ST driver to support, optionally, multiple additional
+ callback-capable channels.
+- Added error handling to WSPI driver, now LLDs can report error
+ conditions to upper layers.
+- Added canTryAbortX() function to CAN driver, implemented
+ for STM32 CANv1.
+
+*** What's new in EX 1.1.0 ***
+
+
+*** What's new in AVR HAL support ***
+
+
+*** What's new in STM32 HAL support ***
+
+- Added support for STM32G0xx.
+- Added support for STM32G4xx.
+- Added support for ADuCM36x.
+- Improved DMAv1 and DMAv2 drivers.
+- TRNG support added to STM32F7xx, STM32G0xx, STM32G4xx, STM32H7xx and
+ STM32L0xx.
+- Idle callback support for STM32 USARTv1 UART driver.
+- Improved support for shared handlers. Now there are centralized
+ inclusion modules (.inc) containing shared handlers. The new modules
+ can be included by the various STM32 platforms. So far the new system
+ has been implemented for STM32G0, STM32G4, STM32L0, STM32L4, STM32L4+,
+ STM32F7, STM3277.
+- Added support for timers 9..17, 20..22 to STM32 PWM driver.
+- Added support for timers 9..17, 20..22 to STM32 ICU driver.
+- Added support for timers 10 and 13 to STM32 GPT driver.
+- Added support for timers 9..14 to STM32 ST driver.
+- PAL, SERIAL and SPI support added to ADuCM36x.
+
+*** What's new in tools ***
+
+- Code style checker tool added.
+- Introduced mcuconf.h updater tool for STM32F407, STM32L052/L053/L062/L063,
+ STM32L072/L073, STM32G4x1/G4x3/G4x4.
+- Added script to generate board files from command line, just
+ run ./os/hal/boards/genboard.sh with the board directory name
+ as parameter.
diff --git a/ChibiOS_20.3.2/tools/mk/autobuild.mk b/ChibiOS_20.3.2/tools/mk/autobuild.mk
new file mode 100644
index 0000000..1e2410d
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/mk/autobuild.mk
@@ -0,0 +1,18 @@
+# Source files located under $(AUTOBUILD_ROOT) are automatically added.
+ifeq ($(AUTOBUILD_ROOT),)
+ AUTOBUILD_ROOT := ./source/
+endif
+
+rwildcard = $(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))
+AUTOCSRC := $(call rwildcard,$(AUTOBUILD_ROOT),*.c)
+AUTOCPPSRC := $(call rwildcard,$(AUTOBUILD_ROOT),*.cpp)
+AUTOASMSRC := $(call rwildcard,$(AUTOBUILD_ROOT),*.s)
+AUTOXASMSRC := $(call rwildcard,$(AUTOBUILD_ROOT),*.S)
+AUTOINC := $(sort $(dir $(call rwildcard,$(AUTOBUILD_ROOT),*)))
+
+# Shared variables.
+ALLCSRC += $(AUTOCSRC)
+ALLCPPSRC += $(AUTOCPPSRC)
+ALLASMSRC += $(AUTOASMSRC)
+ALLXASMSRC += $(AUTOXASMSRC)
+ALLINC += $(AUTOINC)
diff --git a/ChibiOS_20.3.2/tools/style/style_ex.sh b/ChibiOS_20.3.2/tools/style/style_ex.sh
new file mode 100644
index 0000000..ace92ee
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/style/style_ex.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+find ../../os/ex -name "*.[ch]" -exec perl stylecheck.pl "{}" \;
+
diff --git a/ChibiOS_20.3.2/tools/style/style_hal.sh b/ChibiOS_20.3.2/tools/style/style_hal.sh
new file mode 100644
index 0000000..eef4b28
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/style/style_hal.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+find ../../os/hal/include -name "*.[ch]" -exec perl stylecheck.pl "{}" \;
+find ../../os/hal/src -name "*.[ch]" -exec perl stylecheck.pl "{}" \;
+find ../../os/hal/templates -name "*.[ch]" -exec perl stylecheck.pl "{}" \;
+find ../../os/hal/osal -name "*.[ch]" -exec perl stylecheck.pl "{}" \;
+find ../../os/hal/ports/STM32 -name "*.[ch]" -exec perl stylecheck.pl "{}" \;
+
diff --git a/ChibiOS_20.3.2/tools/style/style_nil.sh b/ChibiOS_20.3.2/tools/style/style_nil.sh
new file mode 100644
index 0000000..12375bf
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/style/style_nil.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+find ../../os/nil -name "*.[ch]" -exec perl stylecheck.pl "{}" \;
+find ../../os/oslib -name "*.[ch]" -exec perl stylecheck.pl "{}" \;
+find ../../os/license -name "*.[ch]" -exec perl stylecheck.pl "{}" \;
+
diff --git a/ChibiOS_20.3.2/tools/style/style_rt.sh b/ChibiOS_20.3.2/tools/style/style_rt.sh
new file mode 100644
index 0000000..d829d03
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/style/style_rt.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+find ../../os/rt -name "*.[ch]" -exec perl stylecheck.pl "{}" \;
+find ../../os/oslib -name "*.[ch]" -exec perl stylecheck.pl "{}" \;
+find ../../os/license -name "*.[ch]" -exec perl stylecheck.pl "{}" \;
+
diff --git a/ChibiOS_20.3.2/tools/style/stylecheck.pl b/ChibiOS_20.3.2/tools/style/stylecheck.pl
new file mode 100644
index 0000000..9a44cbd
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/style/stylecheck.pl
@@ -0,0 +1,291 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use File::Basename;
+
+# Desired indentation.
+my $indentation = 2;
+
+if ($#ARGV != 0) {
+ print "\nUsage: stylecheck.pl source\n";
+ exit;
+}
+
+my $source = $ARGV[0];
+
+open(my $in, "<", $source) or die "Can't open source: $!";
+
+my $lineno = 0;
+my @c_source = <$in>;
+my $filename = $source;
+$filename =~ y/\\/\//;
+$filename = basename($filename);
+
+my $cr = "\r";
+my $lf = "\n";
+my $tab = "\t";
+
+sub style {
+ my $desc = shift;
+
+ print("style: $desc at line $lineno in \"$source\"\n");
+}
+
+sub error {
+ my $desc = shift;
+
+ print("error: $desc at line $lineno in \"$source\"\n");
+}
+
+my $emptycnt = 0;
+my $c_comment_complete = 0;
+my $c_comment = "";
+my $state = "start";
+foreach my $line (@c_source) {
+
+ $lineno += 1;
+
+ #****************************************************************************
+ # Processing comments after decoding.
+ if ($c_comment_complete != 0) {
+# print($c_comment . "\n");
+
+ #******************************************************************************
+ # Special case of lint comment.
+ if ("$c_comment" =~ /^\s*\/\*lint/) {
+ }
+ else {
+ #******************************************************************************
+ # Check on glued doxygen back-comment start.
+ if ("$c_comment" =~ /^\s*\/\*\*<[^\s]/) {
+ style "detected glued doxygen back-comment start";
+ }
+
+ #******************************************************************************
+ # Check on glued doxygen comment start.
+ if ("$c_comment" =~ /^\s*\/\*\*[^\s<]/) {
+ style "detected glued doxygen comment start";
+ }
+
+ #******************************************************************************
+ # Check on glued comment start.
+ if ("$c_comment" =~ /^\s*\/\*[^\s\*=]/) {
+ style "detected glued comment start";
+ }
+
+ #******************************************************************************
+ # Check on lower case letter at comment beginning.
+ if ("$c_comment" =~ /^\s*\/\*\s*[a-z]/) {
+ style "detected lower case comment start";
+ }
+
+ #******************************************************************************
+ # Check on loose comment stop.
+# if ("$line" =~ /\s\*\//) {
+# style "detected loose comment stop";
+# }
+ }
+
+ $c_comment_complete = 0;
+ }
+
+ #****************************************************************************
+ # Check on EOL.
+ if (not ($line =~ /$cr$lf$/)) {
+ error "detected malformed EOL";
+ }
+ $line =~ s/$cr//;
+ $line =~ s/$lf//;
+
+ #****************************************************************************
+ # Check on trailing spaces.
+ if ($line =~ /\s$/) {
+ style "detected trailing spaces";
+ }
+
+ #****************************************************************************
+ # Check on TABs.
+ if ($line =~ /$tab/) {
+ style "detected TAB";
+ $line =~ s/$tab/ /;
+ }
+
+ #****************************************************************************
+ # Check on empty lines.
+ my $tmp = $line;
+ $tmp =~ s/\s//;
+ if (length($tmp) == 0) {
+ $emptycnt = $emptycnt + 1;
+ if ($emptycnt == 2) {
+ style "detected multiple empty lines"
+ }
+ next;
+ }
+ else {
+ $emptycnt = 0;
+ }
+
+ #****************************************************************************
+ # Stripping strings content for ease of parsing, all strings become _string_.
+ $line =~ s/\\\"//;
+ if ($line =~ s/(\"[^"]*\")/_string_/) {
+# print "string: $1 replaced by _string_\n";
+ }
+
+ #******************************************************************************
+ # State machine handling.
+ if ($state eq "start") {
+
+ #******************************************************************************
+ # Standard separator.
+
+ #******************************************************************************
+ # Comment start matching.
+ if ("$line" =~ /\/\*/) {
+
+ #******************************************************************************
+ # Single or multi line comments.
+ if ("$line" =~ /\*\//) {
+ # Special case of single line comments.
+ $line =~ /(\/\*.*\*\/)/;
+ $c_comment = $1;
+ $c_comment_complete = 1;
+ }
+ else {
+ # Start of multi-line comment.
+ $line =~ /(\/\*.*)/;
+ $c_comment = $1;
+ $state = "incomment";
+ }
+ }
+ else {
+
+ #****************************************************************************
+ # Check on C++ comments.
+ if ($line =~ /\/\//) {
+ style "detected // comment";
+ }
+
+ #****************************************************************************
+ # Check on commas.
+ if ($line =~ /,\S/) {
+ style "detected comma not followed by space";
+ }
+
+ #****************************************************************************
+ # Check on loose semicolons.
+ if ($line =~ /\S\s;/) {
+ style "detected loose semicolon";
+ }
+
+ #****************************************************************************
+ # Check on glued keywords.
+ if ($line =~ /\sif\(/) {
+ style "detected glued \"if\"";
+ }
+ if ($line =~ /\sfor\(/) {
+ style "detected glued \"for\"";
+ }
+ if ($line =~ /\swhile\(/) {
+ style "detected glued \"while\"";
+ }
+ if ($line =~ /\)while/) {
+ style "detected glued \"while\"";
+ }
+ if ($line =~ /\sswitch\(/) {
+ style "detected glued \"switch\"";
+ }
+ if ($line =~ /\sdo\{/) {
+ style "detected glued \"do\"";
+ }
+
+ #****************************************************************************
+ # Check on loose parenthesis.
+ if ($line =~ /\(\s+/) {
+ style "detected loose \"(\"";
+ }
+ if ($line =~ /\S\s+\)/) {
+ style "detected loose \")\"";
+ }
+
+ #****************************************************************************
+ # Check on glued braces.
+ if ($line =~ /\)\{/) {
+ style "detected glued left brace";
+ }
+ if ($line =~ /\w\{/) {
+ style "detected glued left brace";
+ }
+ if ($line =~ /\}\w/) {
+ style "detected glued right brace";
+ }
+
+ #****************************************************************************
+ # Check on (some) operators.
+ # Before: <<= << >>= >> <= >= == != += -= *= /= %= &= |= ^=
+ if ($line =~ /(\(\S<<=?|\S>>=?|[^\s<]<=|[^\s>]>=|\S[=!+\-*\/%&|^]=)/) {
+ style "detected glued operator (1)";
+ }
+ # After: =
+ elsif ($line =~ /=[^\s=]/) {
+ style "detected glued assignment/comparison operator (2)";
+ }
+ # Before: =
+ elsif ($line =~ /[^\s\=\!\+\-\*\/\%\&\|\^\<\>]=/) {
+ style "detected glued assignment/comparison operator (3)";
+ }
+ # After: << >>
+ elsif ($line =~ /(<<|>>)[^\s=]/) {
+ style "detected glued assignment/comparison operator (4)";
+ }
+ # Before: && || ^^
+ elsif ($line =~ /\S(&&|\|\||\^\^)/) {
+ style "detected glued logical operator (1)";
+ }
+ # After: && || ^^
+ elsif ($line =~ /(&&|\|\||\^\^)\S/) {
+ style "detected glued logical operator (2)";
+ }
+
+ #****************************************************************************
+ # Check function-call-like returns (not perfect so disabled).
+ if ($line =~ /return\s*\(/) {
+ if ($line =~ /return\s*\([\w\d\s\*]*\)\s*[^;]/) {
+ }
+ else {
+# style "detected function-call-like return";
+ }
+ }
+ }
+ }
+
+ #******************************************************************************
+ # Scanning for comment end.
+ elsif ($state eq "incomment") {
+ # Left trimming.
+ $line =~ s/^\s+//;
+ if ("$line" =~ /^\s*\*\/\s*$/) {
+ # Just end of comment line.
+ $c_comment .= "*/";
+ $c_comment_complete = 1;
+# print("$c_comment");
+ $state = "start";
+ }
+ elsif ("$line" =~ /\*\/\s*$/) {
+ # Text followed by end of comment.
+ $line =~ /(.*\*\/)/;
+ $c_comment .= " " . $1;
+ $c_comment_complete = 1;
+# print("$c_comment");
+ $state = "start";
+ }
+ else {
+ # Add the whole line, remove first * and following spaces if any.
+ $line =~ s/^\*?\s*//;
+ $c_comment .= " " . $line;
+# print("$c_comment");
+ }
+ }
+}
+
+close $in or die "$in: $!";
diff --git a/ChibiOS_20.3.2/tools/style/test.c b/ChibiOS_20.3.2/tools/style/test.c
new file mode 100644
index 0000000..2135056
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/style/test.c
@@ -0,0 +1,21 @@
+static struct pippo **pluto (void) {
+
+}
+
+static struct pp qq (void) {
+
+}
+
+static cc ss (void) {
+
+}
+
+static aa bb (int a,
+ char *p) {
+
+}
+
+dd *ee (void) {
+
+ bb(0, "pip\"po", "pluto");
+}
diff --git a/ChibiOS_20.3.2/tools/style/test_negatives.txt b/ChibiOS_20.3.2/tools/style/test_negatives.txt
new file mode 100644
index 0000000..fee96e5
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/style/test_negatives.txt
@@ -0,0 +1,54 @@
+a = b
+a == b
+a != b
+a += b
+a -= b
+a *= b
+a /= b
+a %= b
+a &= b
+a |= b
+a ^= b
+a <= b
+a >= b
+a >> b
+a << b
+a <<= b
+a >>= b
+a && b
+a || b
+a ^^ b
+
+foo(); /* Function call.*/
+
+foo(); /* Multiple lines
+ right comment.*/
+
+/** @} */
+
+/*lint .*/
+
+/* Good comment.*/
+
+/** @Good comment.*/
+
+/**< @Good comment.*/
+
+/*
+ This is a good comment.
+*/
+
+/*
+ * Good comment.
+ */
+
+/* Multiple lines
+ comment 1.*/
+
+/*
+ * Multiple lines
+ * comment 2.
+ */
+
+/*===========================================================================*/
+
diff --git a/ChibiOS_20.3.2/tools/style/test_positives.txt b/ChibiOS_20.3.2/tools/style/test_positives.txt
new file mode 100644
index 0000000..ae7e2c7
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/style/test_positives.txt
@@ -0,0 +1,65 @@
+a=b
+a= b
+a =b
+a==b
+a== b
+a ==b
+a!=b
+a!= b
+a !=b
+a+=b
+a+= b
+a +=b
+a-=b
+a-= b
+a -=b
+a*=b
+a*= b
+a *=b
+a/=b
+a/= b
+a /=b
+a%=b
+a%= b
+a %=b
+a&=b
+a&= b
+a &=b
+a|=b
+a|= b
+a |=b
+a^=b
+a^= b
+a ^=b
+a<=b
+a<= b
+a <=b
+a>=b
+a>= b
+a >=b
+a>>b
+a>> b
+a >>b
+a<>=b
+a>>= b
+a >>=b
+a&&b
+a&& b
+a &&b
+a||b
+a|| b
+a ||b
+a^^b
+a^^ b
+a ^^b
+/** Comment.*/
+/**Comment.*/
+/*Comment*/
+/* comment*/
+/* Comment. */
diff --git a/ChibiOS_20.3.2/tools/updater/conf.fmpp b/ChibiOS_20.3.2/tools/updater/conf.fmpp
new file mode 100644
index 0000000..38ec6d2
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/updater/conf.fmpp
@@ -0,0 +1,10 @@
+outputRoot: .
+dataRoot: .
+
+freemarkerLinks: {
+ lib: ../ftl/libs
+}
+
+data : {
+ doc:properties (./values.txt)
+}
diff --git a/ChibiOS_20.3.2/tools/updater/update_chconf_nil.sh b/ChibiOS_20.3.2/tools/updater/update_chconf_nil.sh
new file mode 100644
index 0000000..ec29728
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/updater/update_chconf_nil.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+if [ $# -eq 2 ]
+ then
+ if [ $1 = "rootpath" ]
+ then
+ find $2 -name "chconf.h" -exec bash update_chconf_nil.sh "{}" \;
+ else
+ echo "Usage: update_chconf_nil.sh [rootpath ]"
+ fi
+elif [ $# -eq 1 ]
+then
+ declare conffile=$(<$1)
+ if egrep -q "_CHIBIOS_NIL_CONF_" <<< "$conffile"
+ then
+ echo Processing: $1
+ egrep -e "\#define\s+[a-zA-Z0-9_]*\s+[a-zA-Z0-9_]" <<< "$conffile" | sed 's/\#define //g; s/ */=/g' > ./values.txt
+ if ! fmpp -q -C conf.fmpp -S ../ftl/processors/conf/chconf_nil
+ then
+ echo
+ echo "aborted"
+ exit 1
+ fi
+ cp ./chconf.h $1
+ rm ./chconf.h ./values.txt
+ fi
+else
+ echo "Usage: update_chconf_nil.sh [rootpath ]"
+ echo " update_chconf_nil.sh ]"
+fi
diff --git a/ChibiOS_20.3.2/tools/updater/update_chconf_rt.sh b/ChibiOS_20.3.2/tools/updater/update_chconf_rt.sh
new file mode 100644
index 0000000..d29f530
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/updater/update_chconf_rt.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+if [ $# -eq 2 ]
+ then
+ if [ $1 = "rootpath" ]
+ then
+ find $2 -name "chconf.h" -exec bash update_chconf_rt.sh "{}" \;
+ else
+ echo "Usage: update_chconf_rt.sh [rootpath ]"
+ fi
+elif [ $# -eq 1 ]
+then
+ declare conffile=$(<$1)
+ if egrep -q "_CHIBIOS_RT_CONF_" <<< "$conffile"
+ then
+ echo Processing: $1
+ egrep -e "\#define\s+[a-zA-Z0-9_]*\s+[a-zA-Z0-9_]" <<< "$conffile" | sed 's/\#define //g; s/ */=/g' > ./values.txt
+ if ! fmpp -q -C conf.fmpp -S ../ftl/processors/conf/chconf_rt
+ then
+ echo
+ echo "aborted"
+ exit 1
+ fi
+ cp ./chconf.h $1
+ rm ./chconf.h ./values.txt
+ fi
+else
+ echo "Usage: update_chconf_rt.sh [rootpath ]"
+ echo " update_chconf_rt.sh ]"
+fi
diff --git a/ChibiOS_20.3.2/tools/updater/update_halconf.sh b/ChibiOS_20.3.2/tools/updater/update_halconf.sh
new file mode 100644
index 0000000..130ca5b
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/updater/update_halconf.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+if [ $# -eq 2 ]
+ then
+ if [ $1 = "rootpath" ]
+ then
+ find $2 -name "halconf.h" -exec bash update_halconf.sh "{}" \;
+ else
+ echo "Usage: update_halconf.sh [rootpath ]"
+ fi
+elif [ $# -eq 1 ]
+then
+ declare conffile=$(<$1)
+# if egrep -q "" <<< "$conffile"
+# then
+ echo Processing: $1
+ egrep -e "\#define\s+[a-zA-Z0-9_]*\s+[a-zA-Z0-9_]" <<< "$conffile" | sed 's/\#define //g; s/ */=/g' > ./values.txt
+ if ! fmpp -q -C conf.fmpp -S ../ftl/processors/conf/halconf
+ then
+ echo
+ echo "aborted"
+ exit 1
+ fi
+ cp ./halconf.h $1
+ rm ./halconf.h ./values.txt
+# fi
+else
+ echo "Usage: update_halconf.sh [rootpath ]"
+ echo " update_halconf.sh ]"
+fi
diff --git a/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32f303xx.sh b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32f303xx.sh
new file mode 100644
index 0000000..3e5f24f
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32f303xx.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+if [ $# -eq 2 ]
+ then
+ if [ $1 = "rootpath" ]
+ then
+ find $2 -name "mcuconf.h" -exec bash update_mcuconf_stm32f303xx.sh "{}" \;
+ else
+ echo "Usage: update_mcuconf_stm32f303xx.sh [rootpath ]"
+ fi
+elif [ $# -eq 1 ]
+then
+ declare conffile=$(<$1)
+ if egrep -q "STM32F303_MCUCONF" <<< "$conffile"
+ then
+ echo Processing: $1
+ egrep -e "\#define\s+[a-zA-Z0-9_()]*\s+[^\s]" <<< "$conffile" | sed -r 's/\#define\s+([a-zA-Z0-9_]*)(\([^)]*\))?\s+/\1=/g' > ./values.txt
+ if ! fmpp -q -C conf.fmpp -S ../ftl/processors/conf/mcuconf_stm32f303xx
+ then
+ echo
+ echo "aborted"
+ exit 1
+ fi
+ cp ./mcuconf.h $1
+ rm ./mcuconf.h ./values.txt
+ fi
+else
+ echo "Usage: update_mcuconf_stm32f303xx.sh [rootpath ]"
+ echo " update_mcuconf_stm32f303xx.sh ]"
+fi
diff --git a/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32f407xx.sh b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32f407xx.sh
new file mode 100644
index 0000000..96997ee
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32f407xx.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+if [ $# -eq 2 ]
+ then
+ if [ $1 = "rootpath" ]
+ then
+ find $2 -name "mcuconf.h" -exec bash update_mcuconf_stm32f407xx.sh "{}" \;
+ else
+ echo "Usage: update_mcuconf_stm32f407xx.sh [rootpath ]"
+ fi
+elif [ $# -eq 1 ]
+then
+ declare conffile=$(<$1)
+ if egrep -q "STM32F407_MCUCONF" <<< "$conffile"
+ then
+ echo Processing: $1
+ egrep -e "\#define\s+[a-zA-Z0-9_()]*\s+[^\s]" <<< "$conffile" | sed -r 's/\#define\s+([a-zA-Z0-9_]*)(\([^)]*\))?\s+/\1=/g' > ./values.txt
+ if ! fmpp -q -C conf.fmpp -S ../ftl/processors/conf/mcuconf_stm32f407xx
+ then
+ echo
+ echo "aborted"
+ exit 1
+ fi
+ cp ./mcuconf.h $1
+ rm ./mcuconf.h ./values.txt
+ fi
+else
+ echo "Usage: update_mcuconf_stm32f407xx.sh [rootpath ]"
+ echo " update_mcuconf_stm32f407xx.sh ]"
+fi
diff --git a/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32f413xx.sh b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32f413xx.sh
new file mode 100644
index 0000000..2e000a7
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32f413xx.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+if [ $# -eq 2 ]
+ then
+ if [ $1 = "rootpath" ]
+ then
+ find $2 -name "mcuconf.h" -exec bash update_mcuconf_stm32f413xx.sh "{}" \;
+ else
+ echo "Usage: update_mcuconf_stm32f413xx.sh [rootpath ]"
+ fi
+elif [ $# -eq 1 ]
+then
+ declare conffile=$(<$1)
+ if egrep -q "STM32F413_MCUCONF" <<< "$conffile"
+ then
+ echo Processing: $1
+ egrep -e "\#define\s+[a-zA-Z0-9_()]*\s+[^\s]" <<< "$conffile" | sed -r 's/\#define\s+([a-zA-Z0-9_]*)(\([^)]*\))?\s+/\1=/g' > ./values.txt
+ if ! fmpp -q -C conf.fmpp -S ../ftl/processors/conf/mcuconf_stm32f413xx
+ then
+ echo
+ echo "aborted"
+ exit 1
+ fi
+ cp ./mcuconf.h $1
+ rm ./mcuconf.h ./values.txt
+ fi
+else
+ echo "Usage: update_mcuconf_stm32f413xx.sh [rootpath ]"
+ echo " update_mcuconf_stm32f413xx.sh ]"
+fi
diff --git a/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32f72xxx.sh b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32f72xxx.sh
new file mode 100644
index 0000000..97639e6
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32f72xxx.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+if [ $# -eq 2 ]
+ then
+ if [ $1 = "rootpath" ]
+ then
+ find $2 -name "mcuconf.h" -exec bash update_mcuconf_stm32f72xxx.sh "{}" \;
+ else
+ echo "Usage: update_mcuconf_stm32f72xxx.sh [rootpath ]"
+ fi
+elif [ $# -eq 1 ]
+then
+ declare conffile=$(<$1)
+ if egrep -q "STM32F722_MCUCONF" <<< "$conffile" || egrep -q "STM32F723_MCUCONF" <<< "$conffile" || egrep -q "STM32F732_MCUCONF" <<< "$conffile" || egrep -q "STM32F733_MCUCONF" <<< "$conffile"
+ then
+ echo Processing: $1
+ egrep -e "\#define\s+[a-zA-Z0-9_()]*\s+[^\s]" <<< "$conffile" | sed -r 's/\#define\s+([a-zA-Z0-9_]*)(\([^)]*\))?\s+/\1=/g' > ./values.txt
+ if ! fmpp -q -C conf.fmpp -S ../ftl/processors/conf/mcuconf_stm32f72xxx
+ then
+ echo
+ echo "aborted"
+ exit 1
+ fi
+ cp ./mcuconf.h $1
+ rm ./mcuconf.h ./values.txt
+ fi
+else
+ echo "Usage: update_mcuconf_stm32f72xxx.sh [rootpath ]"
+ echo " update_mcuconf_stm32f72xxx.sh ]"
+fi
diff --git a/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32f746xx.sh b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32f746xx.sh
new file mode 100644
index 0000000..997510c
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32f746xx.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+if [ $# -eq 2 ]
+ then
+ if [ $1 = "rootpath" ]
+ then
+ find $2 -name "mcuconf.h" -exec bash update_mcuconf_stm32f746xx.sh "{}" \;
+ else
+ echo "Usage: update_mcuconf_stm32f746xx.sh [rootpath ]"
+ fi
+elif [ $# -eq 1 ]
+then
+ declare conffile=$(<$1)
+ if egrep -q "STM32F746_MCUCONF" <<< "$conffile" || egrep -q "STM32F756_MCUCONF" <<< "$conffile"
+ then
+ echo Processing: $1
+ egrep -e "\#define\s+[a-zA-Z0-9_()]*\s+[^\s]" <<< "$conffile" | sed -r 's/\#define\s+([a-zA-Z0-9_]*)(\([^)]*\))?\s+/\1=/g' > ./values.txt
+ if ! fmpp -q -C conf.fmpp -S ../ftl/processors/conf/mcuconf_stm32f746xx
+ then
+ echo
+ echo "aborted"
+ exit 1
+ fi
+ cp ./mcuconf.h $1
+ rm ./mcuconf.h ./values.txt
+ fi
+else
+ echo "Usage: update_mcuconf_stm32f746xx.sh [rootpath ]"
+ echo " update_mcuconf_stm32f746xx.sh ]"
+fi
diff --git a/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32f76xxx.sh b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32f76xxx.sh
new file mode 100644
index 0000000..b442dcc
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32f76xxx.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+if [ $# -eq 2 ]
+ then
+ if [ $1 = "rootpath" ]
+ then
+ find $2 -name "mcuconf.h" -exec bash update_mcuconf_stm32f76xxx.sh "{}" \;
+ else
+ echo "Usage: update_mcuconf_stm32f76xxx.sh [rootpath ]"
+ fi
+elif [ $# -eq 1 ]
+then
+ declare conffile=$(<$1)
+ if egrep -q "STM32F765_MCUCONF" <<< "$conffile" || egrep -q "STM32F767_MCUCONF" <<< "$conffile" || egrep -q "STM32F777_MCUCONF" <<< "$conffile" || egrep -q "STM32F769_MCUCONF" <<< "$conffile" || egrep -q "STM32F779_MCUCONF" <<< "$conffile"
+ then
+ echo Processing: $1
+ egrep -e "\#define\s+[a-zA-Z0-9_()]*\s+[^\s]" <<< "$conffile" | sed -r 's/\#define\s+([a-zA-Z0-9_]*)(\([^)]*\))?\s+/\1=/g' > ./values.txt
+ if ! fmpp -q -C conf.fmpp -S ../ftl/processors/conf/mcuconf_stm32f76xxx
+ then
+ echo
+ echo "aborted"
+ exit 1
+ fi
+ cp ./mcuconf.h $1
+ rm ./mcuconf.h ./values.txt
+ fi
+else
+ echo "Usage: update_mcuconf_stm32f76xxx.sh [rootpath ]"
+ echo " update_mcuconf_stm32f76xxx.sh ]"
+fi
diff --git a/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32g071xx.sh b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32g071xx.sh
new file mode 100644
index 0000000..c9fff12
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32g071xx.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+if [ $# -eq 2 ]
+ then
+ if [ $1 = "rootpath" ]
+ then
+ find $2 -name "mcuconf.h" -exec bash update_mcuconf_stm32g071xx.sh "{}" \;
+ else
+ echo "Usage: update_mcuconf_stm32g071xx.sh [rootpath ]"
+ fi
+elif [ $# -eq 1 ]
+then
+ declare conffile=$(<$1)
+ if egrep -q "STM32G071_MCUCONF" <<< "$conffile"
+ then
+ echo Processing: $1
+ egrep -e "\#define\s+[a-zA-Z0-9_()]*\s+[^\s]" <<< "$conffile" | sed -r 's/\#define\s+([a-zA-Z0-9_]*)(\([^)]*\))?\s+/\1=/g' > ./values.txt
+ if ! fmpp -q -C conf.fmpp -S ../ftl/processors/conf/mcuconf_stm32g071xx
+ then
+ echo
+ echo "aborted"
+ exit 1
+ fi
+ cp ./mcuconf.h $1
+ rm ./mcuconf.h ./values.txt
+ fi
+else
+ echo "Usage: update_mcuconf_stm32g071xx.sh [rootpath ]"
+ echo " update_mcuconf_stm32g071xx.sh ]"
+fi
diff --git a/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32g4x1xx.sh b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32g4x1xx.sh
new file mode 100644
index 0000000..ab71dad
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32g4x1xx.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+if [ $# -eq 2 ]
+ then
+ if [ $1 = "rootpath" ]
+ then
+ find $2 -name "mcuconf.h" -exec bash update_mcuconf_stm32g4x1xx.sh "{}" \;
+ else
+ echo "Usage: update_mcuconf_stm32g4x1xx.sh [rootpath ]"
+ fi
+elif [ $# -eq 1 ]
+then
+ declare conffile=$(<$1)
+ if egrep -q "STM32G431_MCUCONF" <<< "$conffile"
+ then
+ echo Processing: $1
+ egrep -e "\#define\s+[a-zA-Z0-9_()]*\s+[^\s]" <<< "$conffile" | sed -r 's/\#define\s+([a-zA-Z0-9_]*)(\([^)]*\))?\s+/\1=/g' > ./values.txt
+ if ! fmpp -q -C conf.fmpp -S ../ftl/processors/conf/mcuconf_stm32g4x1xx
+ then
+ echo
+ echo "aborted"
+ exit 1
+ fi
+ cp ./mcuconf.h $1
+ rm ./mcuconf.h ./values.txt
+ fi
+else
+ echo "Usage: update_mcuconf_stm32g4x1xx.sh [rootpath ]"
+ echo " update_mcuconf_stm32g4x1xx.sh ]"
+fi
diff --git a/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32g4x4xx.sh b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32g4x4xx.sh
new file mode 100644
index 0000000..76424aa
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32g4x4xx.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+if [ $# -eq 2 ]
+ then
+ if [ $1 = "rootpath" ]
+ then
+ find $2 -name "mcuconf.h" -exec bash update_mcuconf_stm32g4x4xx.sh "{}" \;
+ else
+ echo "Usage: update_mcuconf_stm32g4x4xx.sh [rootpath ]"
+ fi
+elif [ $# -eq 1 ]
+then
+ declare conffile=$(<$1)
+ if egrep -q "STM32G474_MCUCONF" <<< "$conffile"
+ then
+ echo Processing: $1
+ egrep -e "\#define\s+[a-zA-Z0-9_()]*\s+[^\s]" <<< "$conffile" | sed -r 's/\#define\s+([a-zA-Z0-9_]*)(\([^)]*\))?\s+/\1=/g' > ./values.txt
+ if ! fmpp -q -C conf.fmpp -S ../ftl/processors/conf/mcuconf_stm32g4x4xx
+ then
+ echo
+ echo "aborted"
+ exit 1
+ fi
+ cp ./mcuconf.h $1
+ rm ./mcuconf.h ./values.txt
+ fi
+else
+ echo "Usage: update_mcuconf_stm32g4x4xx.sh [rootpath ]"
+ echo " update_mcuconf_stm32g4x4xx.sh ]"
+fi
diff --git a/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32h743xx.sh b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32h743xx.sh
new file mode 100644
index 0000000..14a6126
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32h743xx.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+if [ $# -eq 2 ]
+ then
+ if [ $1 = "rootpath" ]
+ then
+ find $2 -name "mcuconf.h" -exec bash update_mcuconf_stm32h743xx.sh "{}" \;
+ else
+ echo "Usage: update_mcuconf_stm32h743xx.sh [rootpath ]"
+ fi
+elif [ $# -eq 1 ]
+then
+ declare conffile=$(<$1)
+ if egrep -q "STM32H743_MCUCONF" <<< "$conffile"
+ then
+ echo Processing: $1
+ egrep -e "\#define\s+[a-zA-Z0-9_()]*\s+[^\s]" <<< "$conffile" | sed -r 's/\#define\s+([a-zA-Z0-9_]*)(\([^)]*\))?\s+/\1=/g' > ./values.txt
+ if ! fmpp -q -C conf.fmpp -S ../ftl/processors/conf/mcuconf_stm32h743xx
+ then
+ echo
+ echo "aborted"
+ exit 1
+ fi
+ cp ./mcuconf.h $1
+ rm ./mcuconf.h ./values.txt
+ fi
+else
+ echo "Usage: update_mcuconf_stm32h743xx.sh [rootpath ]"
+ echo " update_mcuconf_stm32h743xx.sh ]"
+fi
diff --git a/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32l05xxx.sh b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32l05xxx.sh
new file mode 100644
index 0000000..7e5b7bd
--- /dev/null
+++ b/ChibiOS_20.3.2/tools/updater/update_mcuconf_stm32l05xxx.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+if [ $# -eq 2 ]
+ then
+ if [ $1 = "rootpath" ]
+ then
+ find $2 -name "mcuconf.h" -exec bash update_mcuconf_stm32l05xxx.sh "{}" \;
+ else
+ echo "Usage: update_mcuconf_stm32l05xxx.sh [rootpath